From c46f84a00e02e1736a2398920673a2598ff6b4c0 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 18:27:08 -0700 Subject: [PATCH 001/220] create Column interface --- .../java/com/dfsek/terra/api/util/Column.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 common/api/src/main/java/com/dfsek/terra/api/util/Column.java diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java new file mode 100644 index 000000000..99d929ba4 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.api.util; + +import java.util.function.Consumer; + + +public interface Column { + int getMinY(); + + int getMaxY(); + + T get(int y); + + default void forEach(Consumer consumer) { + for(int y = getMinY(); y < getMaxY(); y++) { + consumer.accept(get(y)); + } + } +} From 84cb428b6c5ac696df7c64fd6c9ef4dcf03fea0c Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 18:33:31 -0700 Subject: [PATCH 002/220] add BiomeProvider#getColumn --- .../java/com/dfsek/terra/api/util/Column.java | 10 +++++ .../world/biome/generation/BiomeColumn.java | 39 +++++++++++++++++++ .../world/biome/generation/BiomeProvider.java | 9 +++++ 3 files changed, 58 insertions(+) create mode 100644 common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeColumn.java diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index 99d929ba4..dadceebe6 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -1,5 +1,9 @@ package com.dfsek.terra.api.util; +import com.google.common.collect.ImmutableList; + +import java.util.ArrayList; +import java.util.List; import java.util.function.Consumer; @@ -15,4 +19,10 @@ public interface Column { consumer.accept(get(y)); } } + + default List asList() { + List list = new ArrayList<>(); + forEach(list::add); + return list; + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeColumn.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeColumn.java new file mode 100644 index 000000000..22b19767b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeColumn.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.api.world.biome.generation; + +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.world.biome.Biome; + + +class BiomeColumn implements Column { + private final BiomeProvider biomeProvider; + private final int min; + private final int max; + + private final int x; + private final int z; + private final long seed; + + protected BiomeColumn(BiomeProvider biomeProvider, int min, int max, int x, int z, long seed) { + this.biomeProvider = biomeProvider; + this.min = min; + this.max = max; + this.x = x; + this.z = z; + this.seed = seed; + } + + @Override + public int getMinY() { + return min; + } + + @Override + public int getMaxY() { + return max; + } + + @Override + public Biome get(int y) { + return biomeProvider.getBiome(x, y, z, seed); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 282541720..cdba21f31 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -7,6 +7,7 @@ package com.dfsek.terra.api.world.biome.generation; +import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.util.vector.Vector3Int; import com.dfsek.terra.api.world.biome.Biome; @@ -62,6 +63,14 @@ public interface BiomeProvider { return getBiome(vector3.getX(), vector3.getY(), vector3.getZ(), seed); } + default Column getColumn(int x, int z, int min, int max, long seed) { + return new BiomeColumn(this, min, max, x, z, seed); + } + + default Column getColumn(int x, int z, WorldProperties properties) { + return getColumn(x, z, properties.getMinHeight(), properties.getMaxHeight(), properties.getSeed()); + } + /** * Get all biomes this {@link BiomeProvider} is capable of generating in the world. *

From 2307138fa8239733b918827d6a73cf18f3291896 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 18:35:49 -0700 Subject: [PATCH 003/220] add IntObjConsumer and forEach implementation in Column --- .../src/main/java/com/dfsek/terra/api/util/Column.java | 10 +++++++++- .../dfsek/terra/api/util/function/IntObjConsumer.java | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 common/api/src/main/java/com/dfsek/terra/api/util/function/IntObjConsumer.java diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index dadceebe6..87c1d1416 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -1,5 +1,7 @@ package com.dfsek.terra.api.util; +import com.dfsek.terra.api.util.function.IntObjConsumer; + import com.google.common.collect.ImmutableList; import java.util.ArrayList; @@ -20,9 +22,15 @@ public interface Column { } } + default void forEach(IntObjConsumer consumer) { + for(int y = getMinY(); y < getMaxY(); y++) { + consumer.accept(y, get(y)); + } + } + default List asList() { List list = new ArrayList<>(); - forEach(list::add); + forEach((Consumer) list::add); return list; } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/function/IntObjConsumer.java b/common/api/src/main/java/com/dfsek/terra/api/util/function/IntObjConsumer.java new file mode 100644 index 000000000..4e9c9e54b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/function/IntObjConsumer.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.util.function; + +@FunctionalInterface +public interface IntObjConsumer { + void accept(int i, T obj); +} From 8a1d329fd930589b72d123e8a7c2a99fad56c855 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 18:39:19 -0700 Subject: [PATCH 004/220] use biome y-level for palette in NoiseChunkGenerator3D --- .../generation/NoiseChunkGenerator3D.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 300cdbfcc..199540bab 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 @@ -73,15 +73,17 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { int cx = xOrig + x; int cz = zOrig + z; - Biome biome = biomeProvider.getBiome(cx, 0, cz, seed); - PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); - - int sea = paletteInfo.seaLevel(); - Palette seaPalette = paletteInfo.ocean(); BlockState data; for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { + Biome biome = biomeProvider.getBiome(cx, y, cz, seed); + + PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); + + int sea = paletteInfo.seaLevel(); + Palette seaPalette = paletteInfo.ocean(); + if(sampler.sample(x, y, z) > 0) { if(carver.sample(x, y, z) <= 0) { data = PaletteUtil.getPalette(x, y, z, sampler, paletteInfo, paletteLevel).get(paletteLevel, cx, y, cz, From 111470c9f44706b944b7e103fea2ebbd37a9cac8 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 18:39:45 -0700 Subject: [PATCH 005/220] bump noise-chunk-generator-3d addon version --- common/addons/chunk-generator-noise-3d/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/addons/chunk-generator-noise-3d/build.gradle.kts b/common/addons/chunk-generator-noise-3d/build.gradle.kts index 36e6012d7..685cc848c 100644 --- a/common/addons/chunk-generator-noise-3d/build.gradle.kts +++ b/common/addons/chunk-generator-noise-3d/build.gradle.kts @@ -1,4 +1,4 @@ -version = version("1.0.0") +version = version("1.1.0") dependencies { compileOnlyApi(project(":common:addons:manifest-addon-loader")) From 3d4e2e4263463c9b08640b224445b94dc6fce891 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 18:53:57 -0700 Subject: [PATCH 006/220] use y-level in ChunkInterpolator --- .../math/interpolation/ChunkInterpolator.java | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 9f8cb782f..26fbb16b4 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -7,15 +7,15 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.util.mutable.MutableInteger; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + import net.jafama.FastMath; import java.util.HashMap; import java.util.Map; -import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; -import com.dfsek.terra.api.util.mutable.MutableInteger; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; - /** * Class to abstract away the Interpolators needed to generate a chunk.
@@ -55,25 +55,24 @@ public class ChunkInterpolator { for(int x = 0; x < 5; x++) { for(int z = 0; z < 5; z++) { - BiomeNoiseProperties generationSettings = provider.getBiome(xOrigin + (x << 2), 0, zOrigin + (z << 2), seed) - .getContext() - .get(BiomeNoiseProperties.class); - Map genMap = new HashMap<>(); - - int step = generationSettings.blendStep(); - int blend = generationSettings.blendDistance(); - - for(int xi = -blend; xi <= blend; xi++) { - for(int zi = -blend; zi <= blend; zi++) { - genMap.computeIfAbsent( - provider.getBiome(xOrigin + (x << 2) + (xi * step), 0, zOrigin + (z << 2) + (zi * step), seed) - .getContext() - .get(BiomeNoiseProperties.class), - g -> new MutableInteger(0)).increment(); // Increment by 1 - } - } - for(int y = 0; y < size + 1; y++) { + BiomeNoiseProperties generationSettings = provider.getBiome(xOrigin + (x << 2), (y << 2) + min, zOrigin + (z << 2), seed) + .getContext() + .get(BiomeNoiseProperties.class); + Map genMap = new HashMap<>(); + + int step = generationSettings.blendStep(); + int blend = generationSettings.blendDistance(); + + for(int xi = -blend; xi <= blend; xi++) { + for(int zi = -blend; zi <= blend; zi++) { + genMap.computeIfAbsent( + provider.getBiome(xOrigin + (x << 2) + (xi * step), 0, zOrigin + (z << 2) + (zi * step), seed) + .getContext() + .get(BiomeNoiseProperties.class), + g -> new MutableInteger(0)).increment(); // Increment by 1 + } + } noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + this.min, (z << 2) + zOrigin); } } From f036bddf9ebe63241c27c086e0227a883bd78816 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 19:03:52 -0700 Subject: [PATCH 007/220] add Column#forRanges --- .../java/com/dfsek/terra/api/util/Column.java | 17 +++++++++++++++++ .../api/util/function/IntIntObjConsumer.java | 6 ++++++ 2 files changed, 23 insertions(+) create mode 100644 common/api/src/main/java/com/dfsek/terra/api/util/function/IntIntObjConsumer.java diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index 87c1d1416..4d99c331d 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -1,5 +1,6 @@ package com.dfsek.terra.api.util; +import com.dfsek.terra.api.util.function.IntIntObjConsumer; import com.dfsek.terra.api.util.function.IntObjConsumer; import com.google.common.collect.ImmutableList; @@ -28,6 +29,22 @@ public interface Column { } } + default void forRanges(IntIntObjConsumer consumer) { + int y = getMinY(); + int runningMin = y; + T runningObj = get(runningMin); + do { + y++; + T current = get(y); + + if(!current.equals(runningObj)) { + consumer.accept(runningMin, y, runningObj); + runningMin = y; + runningObj = current; + } + } while(y < getMaxY()); + } + default List asList() { List list = new ArrayList<>(); forEach((Consumer) list::add); diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/function/IntIntObjConsumer.java b/common/api/src/main/java/com/dfsek/terra/api/util/function/IntIntObjConsumer.java new file mode 100644 index 000000000..69af95224 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/function/IntIntObjConsumer.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.util.function; + +@FunctionalInterface +public interface IntIntObjConsumer { + void accept(int i, int j, T obj); +} From 53df9a47fc6f8bfcd788d51b3bde2047d6ac19d9 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 19:13:57 -0700 Subject: [PATCH 008/220] add Column#clamp --- .../world/chunk/generation/util/Column.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index 6defa986b..4a9309fe9 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -17,16 +17,30 @@ import com.dfsek.terra.api.world.WritableWorld; /** * A single vertical column of a world. + * + * Due to the {@link #clamp(int, int)} method, the height of the column may not always be the same as the world! Be careful! */ public class Column { private final int x; private final int z; + private final int min; + private final int max; private final T world; public Column(int x, int z, T world) { this.x = x; this.z = z; this.world = world; + this.max = world.getMaxHeight(); + this.min = world.getMinHeight(); + } + + public Column(int x, int z, T world, int min, int max) { + this.x = x; + this.z = z; + this.world = world; + this.max = min; + this.min = max; } public int getX() { @@ -38,6 +52,9 @@ public class Column { } public BlockState getBlock(int y) { + if(y >= max || y < min) { + throw new IllegalArgumentException("Y out of range [" + min + ", " + max + ")"); + } return world.getBlockState(x, y, z); } @@ -46,11 +63,11 @@ public class Column { } public int getMinY() { - return world.getMinHeight(); + return min; } public int getMaxY() { - return world.getMaxHeight(); + return max; } public void forEach(IntConsumer function) { @@ -59,6 +76,10 @@ public class Column { } } + public Column clamp(int min, int max) { + return new Column<>(x, z, world, min, max); + } + public BinaryColumn newBinaryColumn(IntToBooleanFunction function) { return new BinaryColumn(getMinY(), getMaxY(), function); } From 245acde336263971c1b2f387954ecc653dfd1a2a Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 19:17:00 -0700 Subject: [PATCH 009/220] use 3d biomes in FeatureGenerationStage --- .../feature/FeatureGenerationStage.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) 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 c60ecc6aa..00b60fa6b 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,9 +7,6 @@ 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.registry.key.StringIdentifiable; @@ -20,6 +17,9 @@ import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.api.world.chunk.generation.util.Column; +import java.util.Collections; +import java.util.Random; + public class FeatureGenerationStage implements GenerationStage, StringIdentifiable { private final Platform platform; @@ -49,26 +49,26 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab long coordinateSeed = (seed * 31 + tx) * 31 + tz; world.getBiomeProvider() - .getBiome(tx, 0, tz, seed) - .getContext() - .get(BiomeFeatures.class) - .getFeatures() - .getOrDefault(this, Collections.emptyList()) - .forEach(feature -> { - platform.getProfiler().push(feature.getID()); - if(feature.getDistributor().matches(tx, tz, seed)) { - feature.getLocator() - .getSuitableCoordinates(column) - .forEach(y -> - feature.getStructure(world, tx, y, tz) - .generate(Vector3Int.of(tx, y, tz), - world, - new Random(coordinateSeed * 31 + y), - Rotation.NONE) - ); - } - platform.getProfiler().pop(feature.getID()); - }); + .getColumn(tx, tz, world) + .forRanges((min, max, biome) -> + biome.getContext() + .get(BiomeFeatures.class) + .getFeatures() + .getOrDefault(this, Collections.emptyList()) + .forEach(feature -> { + platform.getProfiler().push(feature.getID()); + if(feature.getDistributor().matches(tx, tz, seed)) { + feature.getLocator() + .getSuitableCoordinates(column.clamp(min, max)) + .forEach(y -> feature.getStructure(world, tx, y, tz) + .generate(Vector3Int.of(tx, y, tz), + world, + new Random(coordinateSeed * 31 + y), + Rotation.NONE) + ); + } + platform.getProfiler().pop(feature.getID()); + })); } } platform.getProfiler().pop(profile); From 3c94b5960dff527dc6e60bae5b1df5c7bc435d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Wed, 8 Jun 2022 22:18:21 -0500 Subject: [PATCH 010/220] More environment settings for fabric --- .gitignore | 3 +- .../com/dfsek/terra/fabric/PlatformImpl.java | 21 ++++- .../config/BiomeAdditionsSoundTemplate.java | 27 ++++++ .../fabric/config/BiomeMoodSoundTemplate.java | 35 +++++++ .../config/BiomeParticleConfigTemplate.java | 33 +++++++ .../fabric/config/MusicSoundTemplate.java | 36 +++++++ .../fabric/config/SoundEventTemplate.java | 29 ++++++ .../fabric/config/VanillaBiomeProperties.java | 87 +++++++++++++++-- .../dfsek/terra/fabric/util/BiomeUtil.java | 93 ++++++++++++------- 9 files changed, 319 insertions(+), 45 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeAdditionsSoundTemplate.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeMoodSoundTemplate.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeParticleConfigTemplate.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/MusicSoundTemplate.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/SoundEventTemplate.java diff --git a/.gitignore b/.gitignore index c93edc41f..7e27208c8 100644 --- a/.gitignore +++ b/.gitignore @@ -245,4 +245,5 @@ nbdist/ /run/ -**/testDir/ \ No newline at end of file +**/testDir/ +platforms/fabric/run/config/Terra/config.yml diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java index fef99d2cd..329001a4d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java @@ -23,14 +23,26 @@ import ca.solostudios.strata.version.Version; import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.exception.LoadException; + +import com.dfsek.terra.fabric.config.BiomeAdditionsSoundTemplate; +import com.dfsek.terra.fabric.config.BiomeMoodSoundTemplate; +import com.dfsek.terra.fabric.config.BiomeParticleConfigTemplate; +import com.dfsek.terra.fabric.config.MusicSoundTemplate; +import com.dfsek.terra.fabric.config.SoundEventTemplate; import com.dfsek.terra.fabric.util.BiomeUtil; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.MinecraftVersion; import net.minecraft.server.MinecraftServer; +import net.minecraft.sound.BiomeAdditionsSound; +import net.minecraft.sound.BiomeMoodSound; +import net.minecraft.sound.MusicSound; +import net.minecraft.sound.SoundEvent; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.world.biome.Biome.Precipitation; +import net.minecraft.world.biome.Biome.TemperatureModifier; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; +import net.minecraft.world.biome.BiomeParticleConfig; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -164,7 +176,14 @@ public class PlatformImpl extends AbstractPlatform { .registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase( Locale.ROOT))) .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase( - Locale.ROOT))); + Locale.ROOT))) + .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase( + Locale.ROOT))) + .registerLoader(BiomeParticleConfig.class, BiomeParticleConfigTemplate::new) + .registerLoader(SoundEvent.class, SoundEventTemplate::new) + .registerLoader(BiomeMoodSound.class, BiomeMoodSoundTemplate::new) + .registerLoader(BiomeAdditionsSound.class, BiomeAdditionsSoundTemplate::new) + .registerLoader(MusicSound.class, MusicSoundTemplate::new); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeAdditionsSoundTemplate.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeAdditionsSoundTemplate.java new file mode 100644 index 000000000..5867a2f2a --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeAdditionsSoundTemplate.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.fabric.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.sound.BiomeAdditionsSound; +import net.minecraft.sound.SoundEvent; + + +public class BiomeAdditionsSoundTemplate implements ObjectTemplate { + @Value("sound") + @Default + private SoundEvent sound = null; + + @Value("sound") + @Default + private Double soundChance = null; + + @Override + public BiomeAdditionsSound get() { + if (sound == null || soundChance == null) { + return null; + } else { + return new BiomeAdditionsSound(sound, soundChance); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeMoodSoundTemplate.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeMoodSoundTemplate.java new file mode 100644 index 000000000..5bdec6876 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeMoodSoundTemplate.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.fabric.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.sound.BiomeMoodSound; +import net.minecraft.sound.SoundEvent; + + +public class BiomeMoodSoundTemplate implements ObjectTemplate { + @Value("sound") + @Default + private SoundEvent sound = null; + + @Value("cultivation-ticks") + @Default + private Integer soundCultivationTicks = null; + + @Value("spawn-range") + @Default + private Integer soundSpawnRange = null; + + @Value("extra-distance") + @Default + private Double soundExtraDistance = null; + + @Override + public BiomeMoodSound get() { + if (sound == null || soundCultivationTicks == null || soundSpawnRange == null || soundExtraDistance == null) { + return null; + } else { + return new BiomeMoodSound(sound, soundCultivationTicks, soundSpawnRange, soundExtraDistance); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeParticleConfigTemplate.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeParticleConfigTemplate.java new file mode 100644 index 000000000..a15310a85 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/BiomeParticleConfigTemplate.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.fabric.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.argument.ParticleEffectArgumentType; +import net.minecraft.world.biome.BiomeParticleConfig; + + +public class BiomeParticleConfigTemplate implements ObjectTemplate { + @Value("particle") + @Default + private String particle = null; + + @Value("probability") + @Default + private Integer particleProbability = null; + + @Override + public BiomeParticleConfig get() { + if (particle == null || particleProbability == null) { + return null; + } + + try { + return new BiomeParticleConfig(ParticleEffectArgumentType.readParameters(new StringReader(particle)), particleProbability); + } catch(CommandSyntaxException e) { + throw new RuntimeException(e); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/MusicSoundTemplate.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/MusicSoundTemplate.java new file mode 100644 index 000000000..a7bcea6d2 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/MusicSoundTemplate.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.fabric.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.sound.BiomeMoodSound; +import net.minecraft.sound.MusicSound; +import net.minecraft.sound.SoundEvent; + + +public class MusicSoundTemplate implements ObjectTemplate { + @Value("sound") + @Default + private SoundEvent sound = null; + + @Value("min-delay") + @Default + private Integer minDelay = null; + + @Value("max-delay") + @Default + private Integer maxDelay = null; + + @Value("-current-music") + @Default + private Boolean replaceCurrentMusic = null; + + @Override + public MusicSound get() { + if (sound == null || minDelay == null || maxDelay == null || replaceCurrentMusic == null) { + return null; + } else { + return new MusicSound(sound, minDelay, maxDelay, replaceCurrentMusic); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/SoundEventTemplate.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/SoundEventTemplate.java new file mode 100644 index 000000000..e12ed1b2b --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/SoundEventTemplate.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.fabric.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.sound.SoundEvent; +import net.minecraft.util.Identifier; + + +public class SoundEventTemplate implements ObjectTemplate { + @Value("id") + @Default + private Identifier id = null; + + @Value("distanceToTravel") + @Default + private Float distanceToTravel = null; + + @Override + public SoundEvent get() { + if (id == null) { + return null; + } else if (distanceToTravel == null) { + return new SoundEvent(id); + } else { + return new SoundEvent(id, distanceToTravel); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java index 889c9148f..57f89fb9e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java @@ -3,11 +3,18 @@ package com.dfsek.terra.fabric.config; import com.dfsek.tectonic.api.config.template.ConfigTemplate; import com.dfsek.tectonic.api.config.template.annotations.Default; import com.dfsek.tectonic.api.config.template.annotations.Value; +import net.minecraft.sound.BiomeAdditionsSound; +import net.minecraft.sound.BiomeMoodSound; +import net.minecraft.sound.MusicSound; +import net.minecraft.sound.SoundEvent; import net.minecraft.world.biome.Biome.Precipitation; +import net.minecraft.world.biome.Biome.TemperatureModifier; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; import com.dfsek.terra.api.properties.Properties; +import net.minecraft.world.biome.BiomeParticleConfig; + public class VanillaBiomeProperties implements ConfigTemplate, Properties { @Value("colors.grass") @@ -38,21 +45,49 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { @Default private GrassColorModifier modifier = null; + @Value("particles") + @Default + private BiomeParticleConfig particleConfig = null; + @Value("climate.precipitation") @Default private Precipitation precipitation = null; - public Integer getFogColor() { - return fogColor; - } + @Value("climate.temperature") + @Default + private Float temperature = null; - public Integer getFoliageColor() { - return foliageColor; - } + @Value("climate.temperature-modifier") + @Default + private TemperatureModifier temperatureModifier = null; + + @Value("climate.downfall") + @Default + private Float downfall = null; + + @Value("sound.loop-sound.sound") + @Default + private SoundEvent loopSound = null; + + @Value("sound.mood-sound") + @Default + private BiomeMoodSound moodSound = null; + + @Value("sound.additions-sound") + @Default + private BiomeAdditionsSound additionsSound = null; + + @Value("sound.music") + @Default + private MusicSound music = null; public Integer getGrassColor() { return grassColor; } + + public Integer getFogColor() { + return fogColor; + } public Integer getWaterColor() { return waterColor; @@ -62,15 +97,51 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { return waterFogColor; } + public Integer getFoliageColor() { + return foliageColor; + } + public Integer getSkyColor() { return skyColor; } + public GrassColorModifier getGrassColorModifier() { + return modifier; + } + + public BiomeParticleConfig getParticleConfig() { + return particleConfig; + } + public Precipitation getPrecipitation() { return precipitation; } - public GrassColorModifier getModifier() { - return modifier; + public Float getTemperature() { + return temperature; + } + + public TemperatureModifier getTemperatureModifier() { + return temperatureModifier; + } + + public Float getDownfall() { + return downfall; + } + + public SoundEvent getLoopSound() { + return loopSound; + } + + public BiomeMoodSound getMoodSound() { + return moodSound; + } + + public BiomeAdditionsSound getAdditionsSound() { + return additionsSound; + } + + public MusicSound getMusic() { + return music; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java index d1d2ec9a9..367426e7e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -113,46 +113,69 @@ public final class BiomeUtil { BiomeEffects.Builder effects = new BiomeEffects.Builder(); net.minecraft.world.biome.Biome.Builder builder = new Builder(); - - if(biome.getContext().has(VanillaBiomeProperties.class)) { - VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - - effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) - .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) - .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) - .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())) - .grassColorModifier( - Objects.requireNonNullElse(vanillaBiomeProperties.getModifier(), vanilla.getEffects().getGrassColorModifier())); - - - if(vanillaBiomeProperties.getGrassColor() == null) { - vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); - } else { - effects.grassColor(vanillaBiomeProperties.getGrassColor()); - } - - if(vanillaBiomeProperties.getFoliageColor() == null) { - vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); - } else { - effects.foliageColor(vanillaBiomeProperties.getFoliageColor()); - } - - builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation())); - - } else { - effects.waterColor(vanilla.getWaterColor()) - .waterFogColor(vanilla.getWaterFogColor()) - .fogColor(vanilla.getFogColor()) - .skyColor(vanilla.getSkyColor()); + + VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); + + effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) + .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) + .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) + .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())) + .grassColorModifier( + Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(), vanilla.getEffects().getGrassColorModifier())); + + if (vanillaBiomeProperties.getFoliageColor() == null) { vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); + } else { + effects.foliageColor(vanillaBiomeProperties.getFoliageColor()); + } + + if (vanillaBiomeProperties.getGrassColor() == null) { vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); - - builder.precipitation(vanilla.getPrecipitation()); + } else { + effects.grassColor(vanillaBiomeProperties.getGrassColor()); + } + + if (vanillaBiomeProperties.getParticleConfig() == null) { + vanilla.getEffects().getParticleConfig().ifPresent(effects::particleConfig); + } else { + effects.particleConfig(vanillaBiomeProperties.getParticleConfig()); + } + + if (vanillaBiomeProperties.getLoopSound() == null) { + vanilla.getEffects().getLoopSound().ifPresent(effects::loopSound); + } else { + effects.loopSound(vanillaBiomeProperties.getLoopSound()); + } + + if (vanillaBiomeProperties.getMoodSound() == null) { + vanilla.getEffects().getMoodSound().ifPresent(effects::moodSound); + } else { + effects.moodSound(vanillaBiomeProperties.getMoodSound()); + } + + if (vanillaBiomeProperties.getAdditionsSound() == null) { + vanilla.getEffects().getAdditionsSound().ifPresent(effects::additionsSound); + } else { + effects.additionsSound(vanillaBiomeProperties.getAdditionsSound()); + } + + if (vanillaBiomeProperties.getMusic() == null) { + vanilla.getEffects().getMusic().ifPresent(effects::music); + } else { + effects.music(vanillaBiomeProperties.getMusic()); + } + + builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation())); + + builder.temperature(Objects.requireNonNullElse(vanillaBiomeProperties.getTemperature(), vanilla.getTemperature())); + + builder.downfall(Objects.requireNonNullElse(vanillaBiomeProperties.getDownfall(), vanilla.getDownfall())); + + if (vanillaBiomeProperties.getTemperatureModifier() != null) { + builder.temperatureModifier(vanillaBiomeProperties.getTemperatureModifier()); } return builder - .temperature(vanilla.getTemperature()) - .downfall(vanilla.getDownfall()) .effects(effects.build()) .spawnSettings(vanilla.getSpawnSettings()) .generationSettings(generationSettings.build()) From dcc6f025a6e6a3208be88c61ab376f8cb1e7f50a Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 8 Jun 2022 23:06:01 -0700 Subject: [PATCH 011/220] fix oobe in ChunkInterpolator --- .../generation/math/interpolation/ChunkInterpolator.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 26fbb16b4..091f4d9b6 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -55,7 +55,7 @@ public class ChunkInterpolator { for(int x = 0; x < 5; x++) { for(int z = 0; z < 5; z++) { - for(int y = 0; y < size + 1; y++) { + for(int y = 0; y < size; y++) { BiomeNoiseProperties generationSettings = provider.getBiome(xOrigin + (x << 2), (y << 2) + min, zOrigin + (z << 2), seed) .getContext() .get(BiomeNoiseProperties.class); @@ -73,7 +73,11 @@ public class ChunkInterpolator { g -> new MutableInteger(0)).increment(); // Increment by 1 } } - noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + this.min, (z << 2) + zOrigin); + double noise = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + this.min, (z << 2) + zOrigin); + noiseStorage[x][z][y] = noise; + if(y == size - 1) { + noiseStorage[x][z][size] = noise; + } } } } From 1e3cb91ed205fb2cdd1064a52fe52d732f8a36fa Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 07:52:02 -0700 Subject: [PATCH 012/220] fix max/min assignment --- .../dfsek/terra/api/world/chunk/generation/util/Column.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index 4a9309fe9..edbdeed4f 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -39,8 +39,8 @@ public class Column { this.x = x; this.z = z; this.world = world; - this.max = min; - this.min = max; + this.max = max; + this.min = min; } public int getX() { From 0797c113a62e0b6bc3df7800e9615135ea0b704e Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 08:12:36 -0700 Subject: [PATCH 013/220] cache columns in BiomeProvider --- .../terra/api/world/biome/generation/BiomeProvider.java | 6 +----- .../api/world/biome/generation/CachingBiomeProvider.java | 9 +++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index cdba21f31..271ccff37 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -63,12 +63,8 @@ public interface BiomeProvider { return getBiome(vector3.getX(), vector3.getY(), vector3.getZ(), seed); } - default Column getColumn(int x, int z, int min, int max, long seed) { - return new BiomeColumn(this, min, max, x, z, seed); - } - default Column getColumn(int x, int z, WorldProperties properties) { - return getColumn(x, z, properties.getMinHeight(), properties.getMaxHeight(), properties.getSeed()); + return new BiomeColumn(this, x, z, properties.getMinHeight(), properties.getMaxHeight(), properties.getSeed()); } /** diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index ee2b41dbc..49846b11a 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -1,8 +1,11 @@ package com.dfsek.terra.api.world.biome.generation; import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.util.MathUtil; +import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.info.WorldProperties; import java.util.HashMap; import java.util.Map; @@ -18,6 +21,7 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { private final int minY; private final int maxY; private final Map cache = new HashMap<>(); + private final Map> columns = new HashMap<>(); protected CachingBiomeProvider(BiomeProvider delegate, int minY, int maxY) { this.delegate = delegate; @@ -41,6 +45,11 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { return biomes[yi]; } + @Override + public Column getColumn(int x, int z, WorldProperties properties) { + return columns.computeIfAbsent(MathUtil.squash(x, z), k -> BiomeProvider.super.getColumn(x, z, properties)); + } + @Override public Iterable getBiomes() { return delegate.getBiomes(); From 089710247bbe13b5238a2eb5fe7dc9bed52a3469 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 08:29:00 -0700 Subject: [PATCH 014/220] fix range sample --- common/api/src/main/java/com/dfsek/terra/api/util/Column.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index 4d99c331d..f3ea62260 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -43,6 +43,7 @@ public interface Column { runningObj = current; } } while(y < getMaxY()); + consumer.accept(runningMin, y, runningObj); } default List asList() { From 876e4b86ae2959a07c147f15351c43f66ba3c77c Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 08:29:08 -0700 Subject: [PATCH 015/220] add y to exception message --- .../com/dfsek/terra/api/world/chunk/generation/util/Column.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index edbdeed4f..391278b30 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -53,7 +53,7 @@ public class Column { public BlockState getBlock(int y) { if(y >= max || y < min) { - throw new IllegalArgumentException("Y out of range [" + min + ", " + max + ")"); + throw new IllegalArgumentException("Y " + y + " out of range [" + min + ", " + max + ")"); } return world.getBlockState(x, y, z); } From 544b3767d2125a8eb977be0eeb402d78c4976821 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 13:04:05 -0700 Subject: [PATCH 016/220] remove column check --- .../dfsek/terra/api/world/chunk/generation/util/Column.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index 391278b30..436245b5c 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -52,9 +52,6 @@ public class Column { } public BlockState getBlock(int y) { - if(y >= max || y < min) { - throw new IllegalArgumentException("Y " + y + " out of range [" + min + ", " + max + ")"); - } return world.getBlockState(x, y, z); } From e5e926cf100c4603cb9a1e34f616ad3488c9519e Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 13:17:36 -0700 Subject: [PATCH 017/220] fix column iterator --- .../api/src/main/java/com/dfsek/terra/api/util/Column.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index f3ea62260..7226687d0 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -33,7 +33,7 @@ public interface Column { int y = getMinY(); int runningMin = y; T runningObj = get(runningMin); - do { + while(y < getMaxY()) { y++; T current = get(y); @@ -42,8 +42,8 @@ public interface Column { runningMin = y; runningObj = current; } - } while(y < getMaxY()); - consumer.accept(runningMin, y, runningObj); + } + consumer.accept(runningMin, ++y, runningObj); } default List asList() { From 20c7f2f1fb98a409a66ef282db77c0374be1d965 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 13:18:12 -0700 Subject: [PATCH 018/220] fix SurfaceLocator --- .../terra/addons/feature/locator/locators/SurfaceLocator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java index c56f583d2..20dd31d3d 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java @@ -25,6 +25,8 @@ public class SurfaceLocator implements Locator { public BinaryColumn getSuitableCoordinates(Column column) { BinaryColumnBuilder builder = column.newBinaryColumn(); for(int y : search) { + if(y < column.getMinY()) continue; + if(y >= column.getMaxY()) break; if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) { builder.set(y); } From 6434b6b2132c9db9972e70d538621458ae0b4dbb Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 13:39:25 -0700 Subject: [PATCH 019/220] delegate constructor --- .../dfsek/terra/api/world/chunk/generation/util/Column.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index 436245b5c..43ce7a67e 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -28,11 +28,7 @@ public class Column { private final T world; public Column(int x, int z, T world) { - this.x = x; - this.z = z; - this.world = world; - this.max = world.getMaxHeight(); - this.min = world.getMinHeight(); + this(x, z, world, world.getMinHeight(), world.getMaxHeight()); } public Column(int x, int z, T world, int min, int max) { From 81023e1d67d6ea236e658f599d0774995ae01355 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 14:44:21 -0700 Subject: [PATCH 020/220] bounds check --- .../com/dfsek/terra/api/world/chunk/generation/util/Column.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index 43ce7a67e..a3ee0c92f 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -70,6 +70,7 @@ public class Column { } public Column clamp(int min, int max) { + if(min >= max) throw new IllegalArgumentException("Min greater than or equal to max: " + min + ", " + max); return new Column<>(x, z, world, min, max); } From d95e998e5db27f4d296e5c12983da4c8233466ff Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 15:21:54 -0700 Subject: [PATCH 021/220] add test for Column --- .../java/com/dfsek/terra/api/util/Column.java | 20 ++++-- common/api/src/test/java/util/ColumnTest.java | 72 +++++++++++++++++++ 2 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 common/api/src/test/java/util/ColumnTest.java diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index 7226687d0..a4eb50189 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -4,6 +4,8 @@ import com.dfsek.terra.api.util.function.IntIntObjConsumer; import com.dfsek.terra.api.util.function.IntObjConsumer; import com.google.common.collect.ImmutableList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; @@ -28,13 +30,18 @@ public interface Column { consumer.accept(y, get(y)); } } - default void forRanges(IntIntObjConsumer consumer) { - int y = getMinY(); - int runningMin = y; - T runningObj = get(runningMin); - while(y < getMaxY()) { - y++; + int min = getMinY(); + + int y = min + 1; + + T runningObj = get(min); + + + int runningMin = min; + int max = (getMaxY() - 1); + + while(y < max) { T current = get(y); if(!current.equals(runningObj)) { @@ -42,6 +49,7 @@ public interface Column { runningMin = y; runningObj = current; } + y++; } consumer.accept(runningMin, ++y, runningObj); } diff --git a/common/api/src/test/java/util/ColumnTest.java b/common/api/src/test/java/util/ColumnTest.java new file mode 100644 index 000000000..89156d198 --- /dev/null +++ b/common/api/src/test/java/util/ColumnTest.java @@ -0,0 +1,72 @@ +package util; + +import com.dfsek.terra.api.util.Column; + +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.api.util.mutable.MutableInteger; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +import static org.junit.jupiter.api.Assertions.*; + + +public class ColumnTest { + private final Column returnY = new ColumnImpl<>(-10, 10, Function.identity()); + private final Column returnPositive = new ColumnImpl<>(-10, 10, i -> i >= 0); + + @Test + public void testForEach() { + returnY.forEach(Assertions::assertEquals); + MutableInteger test = new MutableInteger(returnY.getMinY()); + returnY.forEach(i -> { + assertEquals(i, test.get()); + test.increment(); + }); + assertEquals(returnY.getMaxY(), test.get()); + } + + @Test + public void testForRanges() { + List, Boolean>> list = new ArrayList<>(); + + returnPositive.forRanges((min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); + + assertEquals(List.of( + Pair.of(Pair.of(-10, 0), false), + Pair.of(Pair.of(0, 10), true) + ), + list); + } + + static class ColumnImpl implements Column { + private final int min; + private final int max; + private final Function p; + + ColumnImpl(int min, int max, Function p) { + this.min = min; + this.max = max; + this.p = p; + } + + @Override + public int getMinY() { + return min; + } + + @Override + public int getMaxY() { + return max; + } + + @Override + public T get(int y) { + return p.apply(y); + } + } +} From 7ce8dfbc65576be47f3d9958873f73771edc4514 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 15:24:43 -0700 Subject: [PATCH 022/220] add ColumnTest#testForRangesIndividual --- common/api/src/test/java/util/ColumnTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/common/api/src/test/java/util/ColumnTest.java b/common/api/src/test/java/util/ColumnTest.java index 89156d198..d172f97f2 100644 --- a/common/api/src/test/java/util/ColumnTest.java +++ b/common/api/src/test/java/util/ColumnTest.java @@ -11,6 +11,8 @@ import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import static org.junit.jupiter.api.Assertions.*; @@ -43,6 +45,15 @@ public class ColumnTest { list); } + @Test + public void testForRangesIndividual() { + List, Integer>> list = new ArrayList<>(); + + returnY.forRanges((min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); + + assertEquals(IntStream.range(-10, 11).mapToObj(i -> Pair.of(Pair.of(i, i + 1), i)).collect(Collectors.toList()), + list); + } static class ColumnImpl implements Column { private final int min; private final int max; From cc9f9cc8d8c273dfeb218c875f0857ff47db9a0a Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 15:28:33 -0700 Subject: [PATCH 023/220] fix Column --- .../main/java/com/dfsek/terra/api/util/Column.java | 12 ++++++------ common/api/src/test/java/util/ColumnTest.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index a4eb50189..08e696156 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -33,15 +33,16 @@ public interface Column { default void forRanges(IntIntObjConsumer consumer) { int min = getMinY(); - int y = min + 1; + int y = min; + + T runningObj = get(y); - T runningObj = get(min); - - int runningMin = min; - int max = (getMaxY() - 1); + + int max = getMaxY() - 1; while(y < max) { + y++; T current = get(y); if(!current.equals(runningObj)) { @@ -49,7 +50,6 @@ public interface Column { runningMin = y; runningObj = current; } - y++; } consumer.accept(runningMin, ++y, runningObj); } diff --git a/common/api/src/test/java/util/ColumnTest.java b/common/api/src/test/java/util/ColumnTest.java index d172f97f2..6fe019802 100644 --- a/common/api/src/test/java/util/ColumnTest.java +++ b/common/api/src/test/java/util/ColumnTest.java @@ -51,7 +51,7 @@ public class ColumnTest { returnY.forRanges((min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); - assertEquals(IntStream.range(-10, 11).mapToObj(i -> Pair.of(Pair.of(i, i + 1), i)).collect(Collectors.toList()), + assertEquals(IntStream.range(-10, 10).mapToObj(i -> Pair.of(Pair.of(i, i + 1), i)).collect(Collectors.toList()), list); } static class ColumnImpl implements Column { From 09e7d58eafe9bfe7b6c6c0c04a1087b8e94feb44 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 15:33:35 -0700 Subject: [PATCH 024/220] add ColumnTest#testForRangesContiguous --- common/api/src/test/java/util/ColumnTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/common/api/src/test/java/util/ColumnTest.java b/common/api/src/test/java/util/ColumnTest.java index 6fe019802..b621a1465 100644 --- a/common/api/src/test/java/util/ColumnTest.java +++ b/common/api/src/test/java/util/ColumnTest.java @@ -21,6 +21,8 @@ public class ColumnTest { private final Column returnY = new ColumnImpl<>(-10, 10, Function.identity()); private final Column returnPositive = new ColumnImpl<>(-10, 10, i -> i >= 0); + private final Column returnTrue = new ColumnImpl<>(-10, 10, i -> true); + @Test public void testForEach() { returnY.forEach(Assertions::assertEquals); @@ -54,6 +56,17 @@ public class ColumnTest { assertEquals(IntStream.range(-10, 10).mapToObj(i -> Pair.of(Pair.of(i, i + 1), i)).collect(Collectors.toList()), list); } + + @Test + public void testForRangesContiguous() { + List, Boolean>> list = new ArrayList<>(); + + returnTrue.forRanges((min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); + + assertEquals(List.of(Pair.of(Pair.of(-10, 10), true)), + list); + } + static class ColumnImpl implements Column { private final int min; private final int max; From dc80fc1ffbfbf1ad1b9a992fde407ea692e1b1bc Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 16:09:46 -0700 Subject: [PATCH 025/220] fix BiomeProvider#getColumn --- .../dfsek/terra/api/world/biome/generation/BiomeProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 271ccff37..9d1554e1c 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -64,7 +64,7 @@ public interface BiomeProvider { } default Column getColumn(int x, int z, WorldProperties properties) { - return new BiomeColumn(this, x, z, properties.getMinHeight(), properties.getMaxHeight(), properties.getSeed()); + return new BiomeColumn(this, properties.getMinHeight(), properties.getMaxHeight(), x, z, properties.getSeed()); } /** From 158adb55af8d99f02f898c078c9edd5653119427 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 16:09:54 -0700 Subject: [PATCH 026/220] bound check SurfaceLocator --- .../addons/feature/locator/locators/SurfaceLocator.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java index 20dd31d3d..e0194167b 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java @@ -13,6 +13,8 @@ import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.world.chunk.generation.util.Column; import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder; +import net.jafama.FastMath; + public class SurfaceLocator implements Locator { private final Range search; @@ -24,9 +26,10 @@ public class SurfaceLocator implements Locator { @Override public BinaryColumn getSuitableCoordinates(Column column) { BinaryColumnBuilder builder = column.newBinaryColumn(); - for(int y : search) { - if(y < column.getMinY()) continue; - if(y >= column.getMaxY()) break; + int max = FastMath.min(search.getMax(), column.getMaxY()); + int min = FastMath.max(search.getMin(), column.getMinY()); + if(min >= max) return builder.build(); + for(int y = min; y < max; y++) { if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) { builder.set(y); } From 6d2a6346862ca0d5060820045d78731ff71b1f3b Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 9 Jun 2022 23:23:44 -0700 Subject: [PATCH 027/220] registerChecked config packs --- .../java/com/dfsek/terra/registry/master/ConfigRegistry.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java b/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java index 98ab127e1..b4ba6dc40 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java @@ -45,7 +45,7 @@ public class ConfigRegistry extends OpenRegistryImpl { public void load(File folder, Platform platform) throws ConfigException { ConfigPack pack = new ConfigPackImpl(folder, platform); - register(pack.getRegistryKey(), pack); + registerChecked(pack.getRegistryKey(), pack); } public boolean loadAll(Platform platform) { @@ -75,6 +75,6 @@ public class ConfigRegistry extends OpenRegistryImpl { public void load(ZipFile file, Platform platform) throws ConfigException { ConfigPackImpl pack = new ConfigPackImpl(file, platform); - register(pack.getRegistryKey(), pack); + registerChecked(pack.getRegistryKey(), pack); } } From 0e815500d0647f50fa2add372c85795dd89b8d8b Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 13:36:43 -0700 Subject: [PATCH 028/220] update Loom --- buildSrc/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index f466b89ba..72aaef641 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -24,7 +24,7 @@ object Versions { const val yarn = "$minecraft+build.1" const val permissionsAPI = "0.1-SNAPSHOT" const val mixin = "0.11.2+mixin.0.8.5" - const val loom = "0.11-SNAPSHOT" + const val loom = "0.12-SNAPSHOT" } object Bukkit { From 47d2ec6bb0fe57a3edc6c08562f1bbd9ecee0419 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 13:39:04 -0700 Subject: [PATCH 029/220] update Loom run addon configuration --- platforms/fabric/build.gradle.kts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index e84d53391..295e97a0e 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -40,8 +40,9 @@ loom { } -addonDir(project.rootProject.file("./run/config/Terra/addons"), tasks.named("runClient").get()) -addonDir(project.rootProject.file("./run/config/Terra/addons"), tasks.named("runServer").get()) + +addonDir(project.file("./run/config/Terra/addons"), tasks.named("runClient").get()) +addonDir(project.file("./run/config/Terra/addons"), tasks.named("runServer").get()) tasks.withType().configureEach { options.release.set(17) From 4a3f21f8f7ad0a9c57e5b0d221f244f79cb4c7af Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 13:51:35 -0700 Subject: [PATCH 030/220] add loom-quiltflower plugin --- platforms/fabric/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 295e97a0e..01c7a24db 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -5,6 +5,7 @@ import net.fabricmc.loom.task.RemapJarTask plugins { id("fabric-loom").version(Versions.Fabric.loom) id("com.modrinth.minotaur").version("1.1.0") + id("io.github.juuxel.loom-quiltflower") version "1.7.1" } dependencies { From dad0a0bd29e612a355ce7d7635b84eaee8a80509 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 14:15:25 -0700 Subject: [PATCH 031/220] create extrusion biome provider project --- common/addons/biome-provider-extrusion/build.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 common/addons/biome-provider-extrusion/build.gradle.kts diff --git a/common/addons/biome-provider-extrusion/build.gradle.kts b/common/addons/biome-provider-extrusion/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/biome-provider-extrusion/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} From 50f895c8f4c405dd78ef0403220c2b4063685eaf Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 14:48:59 -0700 Subject: [PATCH 032/220] begin implementing BiomeExtrusionAddon --- .../biome/extrusion/BiomeExtrusionAddon.java | 39 +++++++++++++++++++ .../extrusion/BiomeExtrusionProvider.java | 30 ++++++++++++++ .../addons/biome/extrusion/api/Extrusion.java | 10 +++++ .../extrusions/SamplerExtrusion.java | 20 ++++++++++ .../extrusion/extrusions/SetExtrusion.java | 7 ++++ .../src/main/resources/terra.addon.yml | 12 ++++++ 6 files changed, 118 insertions(+) create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/Extrusion.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java create mode 100644 common/addons/biome-provider-extrusion/src/main/resources/terra.addon.yml diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java new file mode 100644 index 000000000..4a33d8e57 --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.addons.biome.extrusion; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + +import java.util.function.Supplier; + + +public class BiomeExtrusionAddon implements AddonInitializer { + public static final TypeKey>> EXTRUSION_REGISTRY_KEY = new TypeKey<>() { + }; + + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + + }) + .failThrough(); + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java new file mode 100644 index 000000000..2f9a897df --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.addons.biome.extrusion; + +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + + +public class BiomeExtrusionProvider implements BiomeProvider { + private final BiomeProvider delegate; + private final Set biomes; + + public BiomeExtrusionProvider(BiomeProvider delegate) { + this.delegate = delegate; + this.biomes = delegate.stream().collect(Collectors.toSet()); + } + + @Override + public Biome getBiome(int x, int y, int z, long seed) { + return delegate.getBiome(x, y, z, seed); + } + + @Override + public Iterable getBiomes() { + return biomes; + } +} 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 new file mode 100644 index 000000000..cb9783d66 --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/Extrusion.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.addons.biome.extrusion.api; + +import com.dfsek.terra.api.world.biome.Biome; + + +public interface Extrusion { + Biome extrude(Biome original, int x, int y, int z, long seed); + + Iterable getBiomes(); +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java new file mode 100644 index 000000000..0975265de --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.addons.biome.extrusion.extrusions; + +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.world.biome.Biome; + +import java.security.cert.Extension; + + +/** + * Extrusion which operates using a noise sampler + */ +public abstract class SamplerExtrusion implements Extrusion { + protected NoiseSampler sampler; + + @Override + public Biome extrude(Biome original, int x, int y, int z, long seed) { + return null; + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java new file mode 100644 index 000000000..fae6a7b98 --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.addons.biome.extrusion.extrusions; + +/** + * Sets biomes at locations based on a sampler. + */ +public class SetExtrusion { +} diff --git a/common/addons/biome-provider-extrusion/src/main/resources/terra.addon.yml b/common/addons/biome-provider-extrusion/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..ea0dd68c1 --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: biome-provider-extrusion +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.biome.extrusion.BiomeExtrusionAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file From 8f5d2c80f4c13cea40ca99d62c206eb99c42b2e2 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 15:02:46 -0700 Subject: [PATCH 033/220] cache biome provider in chunkregion --- .../world/ChunkRegionMixin.java | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java index ab00eedd3..fdc832a60 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -17,6 +17,21 @@ package com.dfsek.terra.fabric.mixin.implementations.world; +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.fabric.util.FabricUtil; + import net.minecraft.block.FluidBlock; import net.minecraft.fluid.Fluid; import net.minecraft.util.math.BlockPos; @@ -26,32 +41,13 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.tick.MultiTickScheduler; import net.minecraft.world.tick.OrderedTick; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; 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; -import com.dfsek.terra.api.entity.Entity; -import com.dfsek.terra.api.entity.EntityType; -import com.dfsek.terra.api.util.vector.Vector3; -import com.dfsek.terra.api.world.ServerWorld; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.generation.TerraBiomeSource; -import com.dfsek.terra.fabric.util.FabricUtil; - @Mixin(ChunkRegion.class) @Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$")) @@ -73,6 +69,13 @@ public abstract class ChunkRegionMixin { @Final private MultiTickScheduler fluidTickScheduler; + @SuppressWarnings("deprecation") + private final Lazy caching = Lazy.lazy(() -> ((TerraBiomeSource) ((ChunkRegion) (Object) this) + .toServerWorld() + .getChunkManager() + .getChunkGenerator() + .getBiomeSource()).getProvider().caching((ProtoWorld) this)); + @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, @@ -126,12 +129,8 @@ public abstract class ChunkRegionMixin { return ((FabricChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle(); } - @SuppressWarnings("deprecation") public BiomeProvider terraWorld$getBiomeProvider() { - return ((TerraBiomeSource) ((ChunkRegion) (Object) this).toServerWorld() - .getChunkManager() - .getChunkGenerator() - .getBiomeSource()).getProvider(); + return caching.value(); } public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { From 33a39cb237a756432a5cf1dacfa7c990d4dffb1b Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 15:23:06 -0700 Subject: [PATCH 034/220] optimize biome pipeline cache for 3 dimensions --- .../biome-provider-pipeline/build.gradle.kts | 2 +- .../biome/pipeline/BiomePipelineColumn.java | 71 +++++++++++++++++++ .../biome/pipeline/BiomePipelineProvider.java | 8 +++ .../java/com/dfsek/terra/api/util/Column.java | 3 + .../world/biome/generation/BiomeColumn.java | 10 +++ .../generation/CachingBiomeProvider.java | 3 +- common/api/src/test/java/util/ColumnTest.java | 12 +++- 7 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java diff --git a/common/addons/biome-provider-pipeline/build.gradle.kts b/common/addons/biome-provider-pipeline/build.gradle.kts index 9342c3cad..ec1104ce3 100644 --- a/common/addons/biome-provider-pipeline/build.gradle.kts +++ b/common/addons/biome-provider-pipeline/build.gradle.kts @@ -1,4 +1,4 @@ -version = version("1.0.0") +version = version("1.0.1") dependencies { compileOnlyApi(project(":common:addons:manifest-addon-loader")) diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java new file mode 100644 index 000000000..2f9d5f15e --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java @@ -0,0 +1,71 @@ +package com.dfsek.terra.addons.biome.pipeline; + +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.util.function.IntIntObjConsumer; +import com.dfsek.terra.api.util.function.IntObjConsumer; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + +import java.util.function.Consumer; + + +class BiomePipelineColumn implements Column { + private final int min; + private final int max; + + private final int x; + private final int z; + private final Biome biome; + + protected BiomePipelineColumn(BiomeProvider biomeProvider, int min, int max, int x, int z, long seed) { + this.min = min; + this.max = max; + this.x = x; + this.z = z; + this.biome = biomeProvider.getBiome(x, 0, z, seed); + } + + @Override + public int getMinY() { + return min; + } + + @Override + public int getMaxY() { + return max; + } + + @Override + public int getX() { + return x; + } + + @Override + public int getZ() { + return z; + } + + @Override + public Biome get(int y) { + return biome; + } + + @Override + public void forRanges(IntIntObjConsumer consumer) { + consumer.accept(min, max, biome); + } + + @Override + public void forEach(Consumer consumer) { + for(int y = min; y < max; y++) { + consumer.accept(biome); + } + } + + @Override + public void forEach(IntObjConsumer consumer) { + for(int y = min; y < max; y++) { + consumer.accept(y, biome); + } + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java index bef494a0f..0fece9698 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -7,6 +7,9 @@ package com.dfsek.terra.addons.biome.pipeline; +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.world.info.WorldProperties; + import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import net.jafama.FastMath; @@ -92,6 +95,11 @@ public class BiomePipelineProvider implements BiomeProvider { return biomes; } + @Override + public Column getColumn(int x, int z, WorldProperties properties) { + return new BiomePipelineColumn(this, properties.getMinHeight(), properties.getMaxHeight(), x, z, properties.getSeed()); + } + private record SeededVector(int x, int z, long seed) { } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index 08e696156..cbabcaaa1 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -17,6 +17,9 @@ public interface Column { int getMaxY(); + int getX(); + int getZ(); + T get(int y); default void forEach(Consumer consumer) { diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeColumn.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeColumn.java index 22b19767b..addec2110 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeColumn.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeColumn.java @@ -32,6 +32,16 @@ class BiomeColumn implements Column { return max; } + @Override + public int getX() { + return x; + } + + @Override + public int getZ() { + return z; + } + @Override public Biome get(int y) { return biomeProvider.getBiome(x, y, z, seed); diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index 49846b11a..7e29a180c 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -21,7 +21,6 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { private final int minY; private final int maxY; private final Map cache = new HashMap<>(); - private final Map> columns = new HashMap<>(); protected CachingBiomeProvider(BiomeProvider delegate, int minY, int maxY) { this.delegate = delegate; @@ -47,7 +46,7 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { @Override public Column getColumn(int x, int z, WorldProperties properties) { - return columns.computeIfAbsent(MathUtil.squash(x, z), k -> BiomeProvider.super.getColumn(x, z, properties)); + return delegate.getColumn(x, z, properties); } @Override diff --git a/common/api/src/test/java/util/ColumnTest.java b/common/api/src/test/java/util/ColumnTest.java index b621a1465..df6f2d53c 100644 --- a/common/api/src/test/java/util/ColumnTest.java +++ b/common/api/src/test/java/util/ColumnTest.java @@ -87,7 +87,17 @@ public class ColumnTest { public int getMaxY() { return max; } - + + @Override + public int getX() { + return 0; + } + + @Override + public int getZ() { + return 0; + } + @Override public T get(int y) { return p.apply(y); From b148401f0f63e03d3fc953e0eb25d8fb66c6b82c Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 15:28:48 -0700 Subject: [PATCH 035/220] null entity --- .../fabric/mixin/implementations/world/ChunkRegionMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java index fdc832a60..b849f700a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -134,7 +134,7 @@ public abstract class ChunkRegionMixin { } public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(world); + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(null); entity.setPos(x, y, z); ((ChunkRegion) (Object) this).spawnEntity(entity); return (Entity) entity; From deb6de3d6c4996e453db927b92af797bd6662186 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 17:09:39 -0700 Subject: [PATCH 036/220] implement ReplaceableBiome --- .../biome/extrusion/BiomeExtrusionAddon.java | 13 +++++++ .../biome/extrusion/api/PresentBiome.java | 23 +++++++++++ .../biome/extrusion/api/ReplaceableBiome.java | 31 +++++++++++++++ .../addons/biome/extrusion/api/SelfBiome.java | 21 ++++++++++ .../config/ReplaceableBiomeLoader.java | 32 +++++++++++++++ .../extrusions/SamplerExtrusion.java | 20 ---------- .../extrusion/extrusions/SetExtrusion.java | 39 ++++++++++++++++++- .../java/com/dfsek/terra/api/util/Range.java | 21 ++++++++++ 8 files changed, 179 insertions(+), 21 deletions(-) create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/PresentBiome.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/ReplaceableBiomeLoader.java delete mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java index 4a33d8e57..b5b774dc3 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java @@ -3,14 +3,19 @@ package com.dfsek.terra.addons.biome.extrusion; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.addons.biome.extrusion.config.ReplaceableBiomeLoader; import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; 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.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import java.util.function.Supplier; @@ -35,5 +40,13 @@ public class BiomeExtrusionAddon implements AddonInitializer { }) .failThrough(); + + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPostLoadEvent.class) + .then(event -> { + Registry biomeRegistry = event.getPack().getRegistry(Biome.class); + event.getPack().applyLoader(ReplaceableBiome.class, new ReplaceableBiomeLoader(biomeRegistry)); + }); } } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/PresentBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/PresentBiome.java new file mode 100644 index 000000000..385b01e0b --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/PresentBiome.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.biome.extrusion.api; + + +import com.dfsek.terra.api.world.biome.Biome; + + +final class PresentBiome implements ReplaceableBiome { + private final Biome biome; + + PresentBiome(Biome biome) { + this.biome = biome; + } + + @Override + public Biome get(Biome existing) { + return biome; + } + + @Override + public boolean isSelf() { + return false; + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java new file mode 100644 index 000000000..31e742afa --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.addons.biome.extrusion.api; + + +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.Optional; + + +/** + * Basically just a specialised implementation of {@link Optional} for biomes where a biome may be a "self" reference. + */ +public sealed interface ReplaceableBiome permits PresentBiome, SelfBiome { + Biome get(Biome existing); + + default Biome get() { + if(isSelf()) { + throw new IllegalStateException("Cannot get() self biome!"); + } + return get(null); + } + + boolean isSelf(); + + static ReplaceableBiome of(Biome biome) { + return new PresentBiome(biome); + } + + static ReplaceableBiome self() { + return SelfBiome.INSTANCE; + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java new file mode 100644 index 000000000..4e37192af --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.addons.biome.extrusion.api; + + +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.Objects; + + +final class SelfBiome implements ReplaceableBiome { + public static final SelfBiome INSTANCE = new SelfBiome(); + + @Override + public Biome get(Biome existing) { + return Objects.requireNonNull(existing); + } + + @Override + public boolean isSelf() { + return true; + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/ReplaceableBiomeLoader.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/ReplaceableBiomeLoader.java new file mode 100644 index 000000000..9ef2573ab --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/ReplaceableBiomeLoader.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.addons.biome.extrusion.config; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; + +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.world.biome.Biome; + + +public class ReplaceableBiomeLoader implements TypeLoader { + private final Registry biomeRegistry; + + public ReplaceableBiomeLoader(Registry biomeRegistry) { + this.biomeRegistry = biomeRegistry; + } + + @Override + public ReplaceableBiome load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + if(c.equals("SELF")) return ReplaceableBiome.self(); + return biomeRegistry + .getByID((String) c) + .map(ReplaceableBiome::of) + .orElseThrow(() -> new LoadException("No such biome: " + c, depthTracker)); + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java deleted file mode 100644 index 0975265de..000000000 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.addons.biome.extrusion.extrusions; - -import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; -import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.world.biome.Biome; - -import java.security.cert.Extension; - - -/** - * Extrusion which operates using a noise sampler - */ -public abstract class SamplerExtrusion implements Extrusion { - protected NoiseSampler sampler; - - @Override - public Biome extrude(Biome original, int x, int y, int z, long seed) { - return null; - } -} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java index fae6a7b98..fdea728a1 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java @@ -1,7 +1,44 @@ package com.dfsek.terra.addons.biome.extrusion.extrusions; +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.function.Predicate; +import java.util.stream.Collectors; + + /** * Sets biomes at locations based on a sampler. */ -public class SetExtrusion { +public class SetExtrusion implements Extrusion { + private final NoiseSampler sampler; + + private final Range range; + + private final ProbabilityCollection biomes; + + public SetExtrusion(NoiseSampler sampler, Range range, ProbabilityCollection biomes) { + this.sampler = sampler; + this.range = range; + this.biomes = biomes; + } + + @Override + public Biome extrude(Biome original, int x, int y, int z, long seed) { + return range.ifInRange(y, () -> biomes.get(sampler, x, y, z, seed).get(original), original); + } + + @Override + public Iterable getBiomes() { + return biomes + .getContents() + .stream() + .filter(Predicate.not(ReplaceableBiome::isSelf)) + .map(ReplaceableBiome::get) + .collect(Collectors.toSet()); + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Range.java b/common/api/src/main/java/com/dfsek/terra/api/util/Range.java index 9aa57fde3..c417b8183 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Range.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Range.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Iterator; import java.util.Random; +import java.util.function.Supplier; public interface Range extends Iterable { @@ -41,4 +42,24 @@ public interface Range extends Iterable { Range setMin(int min); int getRange(); + + default T ifInRange(int y, T inRange, T notInRange) { + if(isInRange(y)) return inRange; + return notInRange; + } + + default T ifInRange(int y, Supplier inRange, Supplier notInRange) { + if(isInRange(y)) return inRange.get(); + return notInRange.get(); + } + + default T ifInRange(int y, Supplier inRange, T notInRange) { + if(isInRange(y)) return inRange.get(); + return notInRange; + } + + default T ifInRange(int y, T inRange, Supplier notInRange) { + if(isInRange(y)) return inRange; + return notInRange.get(); + } } From aa5947a9bd409b8cb80941a1c89507288659b280 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 17:15:28 -0700 Subject: [PATCH 037/220] create BiomeExtrusionTemplate --- .../biome/extrusion/BiomeExtrusionAddon.java | 11 +++++-- .../extrusion/BiomeExtrusionProvider.java | 10 +++++-- .../config/BiomeExtrusionTemplate.java | 29 +++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java index b5b774dc3..b7e1dbe9b 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java @@ -4,6 +4,7 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.addons.biome.extrusion.config.BiomeExtrusionTemplate; import com.dfsek.terra.addons.biome.extrusion.config.ReplaceableBiomeLoader; import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.api.Platform; @@ -25,6 +26,9 @@ public class BiomeExtrusionAddon implements AddonInitializer { public static final TypeKey>> EXTRUSION_REGISTRY_KEY = new TypeKey<>() { }; + public static final TypeKey>> PROVIDER_REGISTRY_KEY = new TypeKey<>() { + }; + @Inject private Platform platform; @@ -37,10 +41,13 @@ public class BiomeExtrusionAddon implements AddonInitializer { .getHandler(FunctionalEventHandler.class) .register(addon, ConfigPackPreLoadEvent.class) .then(event -> { - + CheckedRegistry>> providerRegistry = + event.getPack() + .getOrCreateRegistry(PROVIDER_REGISTRY_KEY); + providerRegistry.register(addon.key("PIPELINE"), BiomeExtrusionTemplate::new); }) .failThrough(); - + platform.getEventManager() .getHandler(FunctionalEventHandler.class) .register(addon, ConfigPackPostLoadEvent.class) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index 2f9a897df..af5b4965d 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -1,21 +1,25 @@ package com.dfsek.terra.addons.biome.extrusion; +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.StreamSupport; public class BiomeExtrusionProvider implements BiomeProvider { private final BiomeProvider delegate; private final Set biomes; + private final List extrusions; + private final int resolution; - public BiomeExtrusionProvider(BiomeProvider delegate) { + public BiomeExtrusionProvider(BiomeProvider delegate, List extrusions, int resolution) { this.delegate = delegate; this.biomes = delegate.stream().collect(Collectors.toSet()); + this.extrusions = extrusions; + this.resolution = resolution; } @Override diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java new file mode 100644 index 000000000..b2fd24ed6 --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.addons.biome.extrusion.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.biome.extrusion.BiomeExtrusionProvider; +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + +import java.util.List; + + +public class BiomeExtrusionTemplate implements ObjectTemplate { + @Value("provider") + private BiomeProvider provider; + + @Value("resolution") + @Default + private int resolution = 4; + + @Value("extrusions") + private List extrusions; + + @Override + public BiomeProvider get() { + return new BiomeExtrusionProvider(provider, extrusions, resolution); + } +} From 132a200e43f01175b167b2b7e06d1f7797677000 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 17:33:41 -0700 Subject: [PATCH 038/220] create and register SetExtrusionTemplate --- .../biome/extrusion/BiomeExtrusionAddon.java | 7 +++++++ .../extrusions/SamplerExtrusionTemplate.java | 17 +++++++++++++++++ .../extrusions/SetExtrusionTemplate.java | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SamplerExtrusionTemplate.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SetExtrusionTemplate.java diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java index b7e1dbe9b..56c6f90a3 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java @@ -6,6 +6,8 @@ import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; import com.dfsek.terra.addons.biome.extrusion.config.BiomeExtrusionTemplate; import com.dfsek.terra.addons.biome.extrusion.config.ReplaceableBiomeLoader; +import com.dfsek.terra.addons.biome.extrusion.config.extrusions.SetExtrusionTemplate; +import com.dfsek.terra.addons.biome.extrusion.extrusions.SetExtrusion; import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; @@ -46,6 +48,11 @@ public class BiomeExtrusionAddon implements AddonInitializer { .getOrCreateRegistry(PROVIDER_REGISTRY_KEY); providerRegistry.register(addon.key("PIPELINE"), BiomeExtrusionTemplate::new); }) + .then(event -> { + CheckedRegistry>> sourceRegistry = event.getPack().getOrCreateRegistry( + EXTRUSION_REGISTRY_KEY); + sourceRegistry.register(addon.key("SET"), SetExtrusionTemplate::new); + }) .failThrough(); platform.getEventManager() diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SamplerExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SamplerExtrusionTemplate.java new file mode 100644 index 000000000..d0315be4e --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SamplerExtrusionTemplate.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.biome.extrusion.config.extrusions; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.Range; + + +public abstract class SamplerExtrusionTemplate implements ObjectTemplate { + @Value("sampler") + protected NoiseSampler sampler; + + @Value("range") + protected Range range; +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SetExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SetExtrusionTemplate.java new file mode 100644 index 000000000..90a4b05ad --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SetExtrusionTemplate.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.addons.biome.extrusion.config.extrusions; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.addons.biome.extrusion.extrusions.SetExtrusion; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class SetExtrusionTemplate extends SamplerExtrusionTemplate { + @Value("biomes") + private ProbabilityCollection biomes; + + @Override + public Extrusion get() { + return new SetExtrusion(sampler, range, biomes); + } +} From 37d98df8c30c191b63d78db2b27405e55762e59b Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 17:36:16 -0700 Subject: [PATCH 039/220] use extrusions to calculate biomes --- .../addons/biome/extrusion/BiomeExtrusionProvider.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index af5b4965d..4c5e0d241 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -24,7 +24,13 @@ public class BiomeExtrusionProvider implements BiomeProvider { @Override public Biome getBiome(int x, int y, int z, long seed) { - return delegate.getBiome(x, y, z, seed); + Biome delegated = delegate.getBiome(x, y, z, seed); + + for(Extrusion extrusion : extrusions) { + delegated = extrusion.extrude(delegated, x, y, z, seed); + } + + return delegated; } @Override From d71b1ca9843f8e7471739236334182e586a132a4 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 18:18:31 -0700 Subject: [PATCH 040/220] implement ExtrusionColumn --- .../extrusion/BiomeExtrusionProvider.java | 11 +++ .../biome/extrusion/ExtrusionColumn.java | 74 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index 4c5e0d241..93eef30dc 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -1,8 +1,10 @@ package com.dfsek.terra.addons.biome.extrusion; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.info.WorldProperties; import java.util.List; import java.util.Set; @@ -37,4 +39,13 @@ public class BiomeExtrusionProvider implements BiomeProvider { public Iterable getBiomes() { return biomes; } + + public int getResolution() { + return resolution; + } + + @Override + public Column getColumn(int x, int z, WorldProperties properties) { + return new ExtrusionColumn(properties, this, x, z); + } } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java new file mode 100644 index 000000000..09031083d --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java @@ -0,0 +1,74 @@ +package com.dfsek.terra.addons.biome.extrusion; + +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.util.function.IntIntObjConsumer; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.info.WorldProperties; + + +public class ExtrusionColumn implements Column { + private final int min; + private final int max; + private final BiomeExtrusionProvider provider; + private final int x, z; + private final long seed; + + public ExtrusionColumn(WorldProperties worldProperties, BiomeExtrusionProvider provider, int x, int z) { + this.min = worldProperties.getMinHeight(); + this.max = worldProperties.getMaxHeight(); + this.provider = provider; + this.x = x; + this.z = z; + this.seed = worldProperties.getSeed(); + } + + @Override + public int getMinY() { + return min; + } + + @Override + public int getMaxY() { + return max; + } + + @Override + public int getX() { + return x; + } + + @Override + public int getZ() { + return z; + } + + @Override + public Biome get(int y) { + return provider.getBiome(x, y, z, seed); + } + + @Override + public void forRanges(IntIntObjConsumer consumer) { + int min = getMinY(); + + int y = min; + + Biome runningObj = get(y); + + int runningMin = min; + + int max = getMaxY() - 1; + + while(y < max) { + y += provider.getResolution(); + Biome current = get(y); + + if(!current.equals(runningObj)) { + consumer.accept(runningMin, y, runningObj); + runningMin = y; + runningObj = current; + } + } + consumer.accept(runningMin, ++y, runningObj); + } +} From 12d51e3f278f10c8994087e958787a39745a4f5b Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 18:31:10 -0700 Subject: [PATCH 041/220] fix extrusion registration --- .../dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java index 56c6f90a3..e2465b362 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java @@ -46,7 +46,7 @@ public class BiomeExtrusionAddon implements AddonInitializer { CheckedRegistry>> providerRegistry = event.getPack() .getOrCreateRegistry(PROVIDER_REGISTRY_KEY); - providerRegistry.register(addon.key("PIPELINE"), BiomeExtrusionTemplate::new); + providerRegistry.register(addon.key("EXTRUSION"), BiomeExtrusionTemplate::new); }) .then(event -> { CheckedRegistry>> sourceRegistry = event.getPack().getOrCreateRegistry( From ee6ecb96131d52bea46aef12654df4dbaf57d6dd Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 18:33:58 -0700 Subject: [PATCH 042/220] fix getHeight in air section --- .../terra/fabric/generation/FabricChunkGeneratorWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 26bd28dc6..08b324ca9 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -189,7 +189,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C int y = height.getTopY(); WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); - while(y >= getMinimumY() && !heightmap.getBlockPredicate().test( + while(y > getMinimumY() && !heightmap.getBlockPredicate().test( (BlockState) delegate.getBlock(properties, x, y - 1, z, biomeProvider))) { y--; } From 3b2f2ab679a36dbf2f703f0eaf5addf9b5cf6e6b Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 18:47:22 -0700 Subject: [PATCH 043/220] add optional getBaseBiome method --- .../terra/api/world/biome/generation/BiomeProvider.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 9d1554e1c..2163345fb 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -16,6 +16,7 @@ import com.dfsek.terra.api.world.info.WorldProperties; import org.jetbrains.annotations.Contract; +import java.util.Optional; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -63,6 +64,11 @@ public interface BiomeProvider { return getBiome(vector3.getX(), vector3.getY(), vector3.getZ(), seed); } + default Optional getBaseBiome(int x, int z, long seed) { + return Optional.empty(); + } + + default Column getColumn(int x, int z, WorldProperties properties) { return new BiomeColumn(this, properties.getMinHeight(), properties.getMaxHeight(), x, z, properties.getSeed()); } From 8126f3c2be36f0f3e9b2a4889bb1fe8fdf45ab30 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 18:50:34 -0700 Subject: [PATCH 044/220] implement getBaseBiome --- .../extrusion/BiomeExtrusionProvider.java | 6 ++++++ .../biome/image/ImageBiomeProvider.java | 10 ++++++++++ .../biome/pipeline/BiomePipelineProvider.java | 20 ++++++++++++++----- .../biome/single/SingleBiomeProvider.java | 6 ++++++ .../generation/CachingBiomeProvider.java | 6 ++++++ 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index 93eef30dc..124bec7c3 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -7,6 +7,7 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.info.WorldProperties; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -35,6 +36,11 @@ public class BiomeExtrusionProvider implements BiomeProvider { return delegated; } + @Override + public Optional getBaseBiome(int x, int z, long seed) { + return delegate.getBaseBiome(x, z, seed); + } + @Override public Iterable getBiomes() { return biomes; diff --git a/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java index 3c3fa90f5..aa2f647bb 100644 --- a/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java +++ b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java @@ -13,6 +13,7 @@ import java.awt.Color; import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.Set; import com.dfsek.terra.api.world.biome.Biome; @@ -38,6 +39,10 @@ public class ImageBiomeProvider implements BiomeProvider { @Override public Biome getBiome(int x, int y, int z, long seed) { + return getBiome(x, z); + } + + public Biome getBiome(int x, int z) { x /= resolution; z /= resolution; Color color = align.getColor(image, x, z); @@ -51,6 +56,11 @@ public class ImageBiomeProvider implements BiomeProvider { })); } + @Override + public Optional getBaseBiome(int x, int z, long seed) { + return Optional.of(getBiome(x, z)); + } + @Override public Iterable getBiomes() { return colorBiomeMap.values(); diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java index 0fece9698..4a351a8e4 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -16,6 +16,7 @@ import net.jafama.FastMath; import java.util.Comparator; import java.util.HashSet; +import java.util.Optional; import java.util.Set; import java.util.stream.StreamSupport; @@ -76,18 +77,27 @@ public class BiomePipelineProvider implements BiomeProvider { @Override public Biome getBiome(int x, int y, int z, long seed) { + return getBiome(x, z, seed); + } + + public Biome getBiome(int x, int z, long seed) { x += mutator.noise(seed + 1, x, z) * noiseAmp; z += mutator.noise(seed + 2, x, z) * noiseAmp; - - + + x = FastMath.floorToInt(FastMath.floorDiv(x, resolution)); - + z = FastMath.floorToInt(FastMath.floorDiv(z, resolution)); - + int fdX = FastMath.floorDiv(x, pipeline.getSize()); int fdZ = FastMath.floorDiv(z, pipeline.getSize()); return holderCache.get(new SeededVector(fdX, fdZ, seed)).getBiome(x - fdX * pipeline.getSize(), - z - fdZ * pipeline.getSize()).getBiome(); + z - fdZ * pipeline.getSize()).getBiome(); + } + + @Override + public Optional getBaseBiome(int x, int z, long seed) { + return Optional.of(getBiome(x, z, seed)); } @Override diff --git a/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProvider.java b/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProvider.java index 0ca97bfbc..11524b9de 100644 --- a/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProvider.java +++ b/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProvider.java @@ -8,6 +8,7 @@ package com.dfsek.terra.addons.biome.single; import java.util.Collections; +import java.util.Optional; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; @@ -25,6 +26,11 @@ public class SingleBiomeProvider implements BiomeProvider { return biome; } + @Override + public Optional getBaseBiome(int x, int z, long seed) { + return Optional.of(biome); + } + @Override public Iterable getBiomes() { return Collections.singleton(biome); diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index 7e29a180c..7eb59fe31 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -9,6 +9,7 @@ import com.dfsek.terra.api.world.info.WorldProperties; import java.util.HashMap; import java.util.Map; +import java.util.Optional; /** @@ -44,6 +45,11 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { return biomes[yi]; } + @Override + public Optional getBaseBiome(int x, int z, long seed) { + return delegate.getBaseBiome(x, z, seed); + } + @Override public Column getColumn(int x, int z, WorldProperties properties) { return delegate.getColumn(x, z, properties); From 2da54b9843d5f843b57636cc9b1cc481b56b3cb3 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 18:52:21 -0700 Subject: [PATCH 045/220] use base biome in ElevationInterpolator --- .../math/interpolation/ElevationInterpolator.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java index 0342ca751..352ea7d1c 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java @@ -23,8 +23,14 @@ public class ElevationInterpolator { // Precompute generators. for(int x = -1 - smooth; x <= 16 + smooth; x++) { for(int z = -1 - smooth; z <= 16 + smooth; z++) { - gens[x + 1 + smooth][z + 1 + smooth] = provider.getBiome(xOrigin + x, 0, zOrigin + z, seed).getContext().get( - BiomeNoiseProperties.class); + int bx = xOrigin + x; + int bz = zOrigin + z; + gens[x + 1 + smooth][z + 1 + smooth] = + provider + .getBaseBiome(bx, bz, seed) + .orElseGet(() -> provider.getBiome(bx, 0, bz, seed)) // kind of a hack + .getContext() + .get(BiomeNoiseProperties.class); } } From 2c5567296d52ed9d20d40eaf183899dc4ea96628 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 18:56:00 -0700 Subject: [PATCH 046/220] add extruded biomes to provider list --- .../terra/addons/biome/extrusion/BiomeExtrusionProvider.java | 1 + .../com/dfsek/terra/addons/biome/extrusion/api/Extrusion.java | 4 +++- .../terra/addons/biome/extrusion/extrusions/SetExtrusion.java | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index 124bec7c3..ea1d316b4 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -21,6 +21,7 @@ public class BiomeExtrusionProvider implements BiomeProvider { public BiomeExtrusionProvider(BiomeProvider delegate, List extrusions, int resolution) { this.delegate = delegate; this.biomes = delegate.stream().collect(Collectors.toSet()); + extrusions.forEach(e -> biomes.addAll(e.getBiomes())); this.extrusions = extrusions; this.resolution = resolution; } 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 cb9783d66..3f3474428 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 @@ -2,9 +2,11 @@ package com.dfsek.terra.addons.biome.extrusion.api; 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); - Iterable getBiomes(); + Collection getBiomes(); } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java index fdea728a1..a272d42be 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java @@ -7,6 +7,7 @@ import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.util.collection.ProbabilityCollection; import com.dfsek.terra.api.world.biome.Biome; +import java.util.Collection; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -33,7 +34,7 @@ public class SetExtrusion implements Extrusion { } @Override - public Iterable getBiomes() { + public Collection getBiomes() { return biomes .getContents() .stream() From e5f0e64cf3513d9d312fa386c303df5a7b75783c Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 00:33:29 -0700 Subject: [PATCH 047/220] fix ChunkInterpolator 3d biome fetching --- .../generation/math/interpolation/ChunkInterpolator.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 091f4d9b6..8b1e2f748 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -56,7 +56,10 @@ public class ChunkInterpolator { for(int x = 0; x < 5; x++) { for(int z = 0; z < 5; z++) { for(int y = 0; y < size; y++) { - BiomeNoiseProperties generationSettings = provider.getBiome(xOrigin + (x << 2), (y << 2) + min, zOrigin + (z << 2), seed) + int scaledX = x << 2; + int scaledY = (y << 2) + min; + int scaledZ = z << 2; + BiomeNoiseProperties generationSettings = provider.getBiome(xOrigin + scaledX, scaledY, zOrigin + scaledZ, seed) .getContext() .get(BiomeNoiseProperties.class); Map genMap = new HashMap<>(); @@ -67,13 +70,13 @@ public class ChunkInterpolator { for(int xi = -blend; xi <= blend; xi++) { for(int zi = -blend; zi <= blend; zi++) { genMap.computeIfAbsent( - provider.getBiome(xOrigin + (x << 2) + (xi * step), 0, zOrigin + (z << 2) + (zi * step), seed) + provider.getBiome(xOrigin + scaledX + (xi * step), scaledY, zOrigin + scaledZ + (zi * step), seed) .getContext() .get(BiomeNoiseProperties.class), g -> new MutableInteger(0)).increment(); // Increment by 1 } } - double noise = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + this.min, (z << 2) + zOrigin); + double noise = computeNoise(genMap, scaledX + xOrigin, scaledY, scaledZ + zOrigin); noiseStorage[x][z][y] = noise; if(y == size - 1) { noiseStorage[x][z][size] = noise; From c9221ca64c135b4779e8bed4feaab5a6cf5e5fa2 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 01:47:32 -0700 Subject: [PATCH 048/220] implement feature stage resolution --- .../feature/FeatureGenerationStage.java | 63 +++++++++++-------- .../feature/config/FeatureStageTemplate.java | 22 ++++++- 2 files changed, 56 insertions(+), 29 deletions(-) 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 00b60fa6b..4fbc3f2c9 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 @@ -28,10 +28,13 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab private final String profile; - public FeatureGenerationStage(Platform platform, String id) { + private final int resolution; + + public FeatureGenerationStage(Platform platform, String id, int resolution) { this.platform = platform; this.id = id; this.profile = "feature_stage:" + id; + this.resolution = resolution; } @Override @@ -41,34 +44,40 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab int cx = world.centerChunkX() << 4; int cz = world.centerChunkZ() << 4; long seed = world.getSeed(); - for(int x = 0; x < 16; x++) { - for(int z = 0; z < 16; z++) { - int tx = cx + x; - int tz = cz + z; - Column column = world.column(tx, tz); - long coordinateSeed = (seed * 31 + tx) * 31 + tz; - + for(int chunkX = 0; chunkX < 16; chunkX += resolution) { + for(int chunkZ = 0; chunkZ < 16; chunkZ += resolution) { + int tx = cx + chunkX; + int tz = cz + chunkZ; world.getBiomeProvider() .getColumn(tx, tz, world) - .forRanges((min, max, biome) -> - biome.getContext() - .get(BiomeFeatures.class) - .getFeatures() - .getOrDefault(this, Collections.emptyList()) - .forEach(feature -> { - platform.getProfiler().push(feature.getID()); - if(feature.getDistributor().matches(tx, tz, seed)) { - feature.getLocator() - .getSuitableCoordinates(column.clamp(min, max)) - .forEach(y -> feature.getStructure(world, tx, y, tz) - .generate(Vector3Int.of(tx, y, tz), - world, - new Random(coordinateSeed * 31 + y), - Rotation.NONE) - ); - } - platform.getProfiler().pop(feature.getID()); - })); + .forRanges((min, max, biome) -> { + for(int subChunkX = 0; subChunkX < resolution; subChunkX++) { + for(int subChunkZ = 0; subChunkZ < resolution; subChunkZ++) { + int x = subChunkX + tx; + int z = subChunkZ + tz; + long coordinateSeed = (seed * 31 + x) * 31 + z; + Column column = world.column(x, z); + biome.getContext() + .get(BiomeFeatures.class) + .getFeatures() + .getOrDefault(this, Collections.emptyList()) + .forEach(feature -> { + platform.getProfiler().push(feature.getID()); + if(feature.getDistributor().matches(x, z, seed)) { + feature.getLocator() + .getSuitableCoordinates(column.clamp(min, max)) + .forEach(y -> feature.getStructure(world, x, y, z) + .generate(Vector3Int.of(x, y, z), + world, + new Random(coordinateSeed * 31 + y), + Rotation.NONE) + ); + } + platform.getProfiler().pop(feature.getID()); + }); + } + } + }); } } platform.getProfiler().pop(profile); 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 1663ceed8..b1604cc1a 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 @@ -1,23 +1,41 @@ package com.dfsek.terra.addons.generation.feature.config; +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; import com.dfsek.terra.addons.generation.feature.FeatureGenerationStage; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; -public class FeatureStageTemplate implements ObjectTemplate { +public class FeatureStageTemplate implements ObjectTemplate, ValidatedConfigTemplate { private final Platform platform; @Value("id") private String id; + @Value("resolution") + @Default + private int resolution = 4; + public FeatureStageTemplate(Platform platform) { this.platform = platform; } @Override public FeatureGenerationStage get() { - return new FeatureGenerationStage(platform, id); + return new FeatureGenerationStage(platform, id, resolution); + } + + @Override + public boolean validate() throws ValidationException { + if(!(resolution == 1 + || resolution == 2 + || resolution == 4 + || resolution == 8 + || resolution == 16)) throw new ValidationException( + "Resolution must be power of 2 less than or equal to 16 (1, 2, 4, 8, 16), got: " + resolution); + return true; } } From ad5435f69d5ad022403ddcf3edd52784ba14454c Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 02:27:45 -0700 Subject: [PATCH 049/220] use column in ChunkInterpolator --- .../biome/extrusion/BiomeExtrusionProvider.java | 13 ++++++++++++- .../addons/biome/extrusion/ExtrusionColumn.java | 6 ++++-- .../math/interpolation/ChunkInterpolator.java | 15 ++++++++++----- .../api/world/biome/generation/BiomeProvider.java | 6 +++++- .../biome/generation/CachingBiomeProvider.java | 5 +++-- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index ea1d316b4..b14207d0f 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -42,6 +42,13 @@ public class BiomeExtrusionProvider implements BiomeProvider { return delegate.getBaseBiome(x, z, seed); } + public Biome getBiome(int x, int y, int z, long seed, Biome biome) { + for(Extrusion extrusion : extrusions) { + biome = extrusion.extrude(biome, x, y, z, seed); + } + return biome; + } + @Override public Iterable getBiomes() { return biomes; @@ -51,8 +58,12 @@ public class BiomeExtrusionProvider implements BiomeProvider { return resolution; } + public BiomeProvider getDelegate() { + return delegate; + } + @Override public Column getColumn(int x, int z, WorldProperties properties) { - return new ExtrusionColumn(properties, this, x, z); + return new ExtrusionColumn(properties, this, x, z, properties.getSeed()); } } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java index 09031083d..e3d187d35 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java @@ -12,14 +12,16 @@ public class ExtrusionColumn implements Column { private final BiomeExtrusionProvider provider; private final int x, z; private final long seed; + private final Column delegate; - public ExtrusionColumn(WorldProperties worldProperties, BiomeExtrusionProvider provider, int x, int z) { + public ExtrusionColumn(WorldProperties worldProperties, BiomeExtrusionProvider provider, int x, int z, long seed) { this.min = worldProperties.getMinHeight(); this.max = worldProperties.getMaxHeight(); this.provider = provider; this.x = x; this.z = z; this.seed = worldProperties.getSeed(); + this.delegate = provider.getDelegate().getColumn(x, z, seed, min, max); } @Override @@ -44,7 +46,7 @@ public class ExtrusionColumn implements Column { @Override public Biome get(int y) { - return provider.getBiome(x, y, z, seed); + return provider.getBiome(x, y, z, seed, delegate.get(y)); } @Override diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 8b1e2f748..652b64790 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -8,7 +8,9 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.util.mutable.MutableInteger; +import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import net.jafama.FastMath; @@ -54,12 +56,15 @@ public class ChunkInterpolator { double[][][] noiseStorage = new double[5][5][size + 1]; for(int x = 0; x < 5; x++) { + int scaledX = x << 2; + int absoluteX = xOrigin + scaledX; for(int z = 0; z < 5; z++) { + int scaledZ = z << 2; + int absoluteZ = zOrigin + scaledZ; + Column column = provider.getColumn(absoluteX, absoluteZ, seed, min, max); for(int y = 0; y < size; y++) { - int scaledX = x << 2; int scaledY = (y << 2) + min; - int scaledZ = z << 2; - BiomeNoiseProperties generationSettings = provider.getBiome(xOrigin + scaledX, scaledY, zOrigin + scaledZ, seed) + BiomeNoiseProperties generationSettings = column.get(scaledY) .getContext() .get(BiomeNoiseProperties.class); Map genMap = new HashMap<>(); @@ -70,13 +75,13 @@ public class ChunkInterpolator { for(int xi = -blend; xi <= blend; xi++) { for(int zi = -blend; zi <= blend; zi++) { genMap.computeIfAbsent( - provider.getBiome(xOrigin + scaledX + (xi * step), scaledY, zOrigin + scaledZ + (zi * step), seed) + provider.getBiome(absoluteX + (xi * step), scaledY, absoluteZ + (zi * step), seed) .getContext() .get(BiomeNoiseProperties.class), g -> new MutableInteger(0)).increment(); // Increment by 1 } } - double noise = computeNoise(genMap, scaledX + xOrigin, scaledY, scaledZ + zOrigin); + double noise = computeNoise(genMap, absoluteX, scaledY, absoluteZ); noiseStorage[x][z][y] = noise; if(y == size - 1) { noiseStorage[x][z][size] = noise; diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 2163345fb..37483b564 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -70,7 +70,11 @@ public interface BiomeProvider { default Column getColumn(int x, int z, WorldProperties properties) { - return new BiomeColumn(this, properties.getMinHeight(), properties.getMaxHeight(), x, z, properties.getSeed()); + return getColumn(x, z, properties.getSeed(), properties.getMinHeight(), properties.getMaxHeight()); + } + + default Column getColumn(int x, int z, long seed, int min, int max) { + return new BiomeColumn(this, min, max, x, z, seed); } /** diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index 7eb59fe31..08877f968 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -22,6 +22,7 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { private final int minY; private final int maxY; private final Map cache = new HashMap<>(); + private final Map> columnCache = new HashMap<>(); protected CachingBiomeProvider(BiomeProvider delegate, int minY, int maxY) { this.delegate = delegate; @@ -51,8 +52,8 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { } @Override - public Column getColumn(int x, int z, WorldProperties properties) { - return delegate.getColumn(x, z, properties); + public Column getColumn(int x, int z, long seed, int min, int max) { + return columnCache.computeIfAbsent(MathUtil.squash(x, z), k -> delegate.getColumn(x, z, seed, min, max)); } @Override From 0cb29e471ef65e0029eab6a4d204e117e39b949a Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 02:33:51 -0700 Subject: [PATCH 050/220] use column sampler in NoiseChunkGenerator3D --- .../chunkgenerator/generation/NoiseChunkGenerator3D.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 199540bab..de4354198 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 @@ -8,6 +8,8 @@ package com.dfsek.terra.addons.chunkgenerator.generation; +import com.dfsek.terra.api.util.Column; + import net.jafama.FastMath; import org.jetbrains.annotations.NotNull; @@ -73,11 +75,10 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { int cx = xOrig + x; int cz = zOrig + z; - - + Column biomeColumn = biomeProvider.getColumn(cx, cz, world); BlockState data; for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { - Biome biome = biomeProvider.getBiome(cx, y, cz, seed); + Biome biome = biomeColumn.get(y); PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); From e2ba6716263db7a7548f2446c1ca4c7292df353d Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 02:46:59 -0700 Subject: [PATCH 051/220] add replace extrusion --- .../biome/extrusion/BiomeExtrusionAddon.java | 6 ++- .../extrusions/ReplaceExtrusionTemplate.java | 24 +++++++++ .../extrusions/SamplerExtrusionTemplate.java | 5 +- .../extrusions/SetExtrusionTemplate.java | 5 +- .../extrusions/ReplaceExtrusion.java | 49 +++++++++++++++++++ 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/ReplaceExtrusionTemplate.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java index e2465b362..5d8b1275b 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java @@ -6,6 +6,7 @@ import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; import com.dfsek.terra.addons.biome.extrusion.config.BiomeExtrusionTemplate; import com.dfsek.terra.addons.biome.extrusion.config.ReplaceableBiomeLoader; +import com.dfsek.terra.addons.biome.extrusion.config.extrusions.ReplaceExtrusionTemplate; import com.dfsek.terra.addons.biome.extrusion.config.extrusions.SetExtrusionTemplate; import com.dfsek.terra.addons.biome.extrusion.extrusions.SetExtrusion; import com.dfsek.terra.addons.manifest.api.AddonInitializer; @@ -49,9 +50,10 @@ public class BiomeExtrusionAddon implements AddonInitializer { providerRegistry.register(addon.key("EXTRUSION"), BiomeExtrusionTemplate::new); }) .then(event -> { - CheckedRegistry>> sourceRegistry = event.getPack().getOrCreateRegistry( + CheckedRegistry>> extrusionRegistry = event.getPack().getOrCreateRegistry( EXTRUSION_REGISTRY_KEY); - sourceRegistry.register(addon.key("SET"), SetExtrusionTemplate::new); + extrusionRegistry.register(addon.key("SET"), SetExtrusionTemplate::new); + extrusionRegistry.register(addon.key("REPLACE"), ReplaceExtrusionTemplate::new); }) .failThrough(); diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/ReplaceExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/ReplaceExtrusionTemplate.java new file mode 100644 index 000000000..de5127b81 --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/ReplaceExtrusionTemplate.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.addons.biome.extrusion.config.extrusions; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.addons.biome.extrusion.extrusions.ReplaceExtrusion; +import com.dfsek.terra.addons.biome.extrusion.extrusions.SetExtrusion; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class ReplaceExtrusionTemplate extends SamplerExtrusionTemplate { + @Value("to") + private @Meta ProbabilityCollection<@Meta ReplaceableBiome> biomes; + + @Value("from") + private @Meta String fromTag; + + @Override + public Extrusion get() { + return new ReplaceExtrusion(sampler, range, biomes, fromTag); + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SamplerExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SamplerExtrusionTemplate.java index d0315be4e..d21ef0f64 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SamplerExtrusionTemplate.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SamplerExtrusionTemplate.java @@ -4,14 +4,15 @@ import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.util.Range; public abstract class SamplerExtrusionTemplate implements ObjectTemplate { @Value("sampler") - protected NoiseSampler sampler; + protected @Meta NoiseSampler sampler; @Value("range") - protected Range range; + protected @Meta Range range; } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SetExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SetExtrusionTemplate.java index 90a4b05ad..1cfbaeb48 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SetExtrusionTemplate.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/SetExtrusionTemplate.java @@ -5,12 +5,13 @@ import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; import com.dfsek.terra.addons.biome.extrusion.extrusions.SetExtrusion; +import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.util.collection.ProbabilityCollection; public class SetExtrusionTemplate extends SamplerExtrusionTemplate { - @Value("biomes") - private ProbabilityCollection biomes; + @Value("to") + private @Meta ProbabilityCollection<@Meta ReplaceableBiome> biomes; @Override public Extrusion get() { diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java new file mode 100644 index 000000000..91efd92aa --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java @@ -0,0 +1,49 @@ +package com.dfsek.terra.addons.biome.extrusion.extrusions; + +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Collectors; + + +/** + * Sets biomes at locations based on a sampler. + */ +public class ReplaceExtrusion implements Extrusion { + private final NoiseSampler sampler; + + private final Range range; + + private final ProbabilityCollection biomes; + + private final String tag; + + public ReplaceExtrusion(NoiseSampler sampler, Range range, ProbabilityCollection biomes, String tag) { + this.sampler = sampler; + this.range = range; + this.biomes = biomes; + this.tag = tag; + } + + @Override + public Biome extrude(Biome original, int x, int y, int z, long seed) { + if(!original.getTags().contains(tag)) return original; + return range.ifInRange(y, () -> biomes.get(sampler, x, y, z, seed).get(original), original); + } + + @Override + public Collection getBiomes() { + return biomes + .getContents() + .stream() + .filter(Predicate.not(ReplaceableBiome::isSelf)) + .map(ReplaceableBiome::get) + .collect(Collectors.toSet()); + } +} From 47d2b66046e8a182a74f38ec4722615c4c86103e Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 12:58:49 -0700 Subject: [PATCH 052/220] fix getHeight again --- .../FabricChunkGeneratorWrapper.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 08b324ca9..af5186802 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -17,6 +17,19 @@ package com.dfsek.terra.fabric.generation; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; +import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; +import com.dfsek.terra.api.world.info.WorldProperties; +import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.fabric.data.Codecs; +import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; +import com.dfsek.terra.fabric.util.FabricAdapter; + import com.mojang.serialization.Codec; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -53,19 +66,6 @@ import java.util.Optional; 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; -import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; -import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; -import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; -import com.dfsek.terra.api.world.info.WorldProperties; -import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.fabric.data.Codecs; -import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; -import com.dfsek.terra.fabric.util.FabricAdapter; - public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class); @@ -96,7 +96,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C protected Codec getCodec() { return Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER; } - + @Override public void buildSurface(ChunkRegion region, StructureAccessor structures, NoiseConfig noiseConfig, Chunk chunk) { // no op @@ -104,7 +104,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public void populateEntities(ChunkRegion region) { - if (!this.settings.value().mobGenerationDisabled()) { + if(!this.settings.value().mobGenerationDisabled()) { ChunkPos chunkPos = region.getCenterPos(); RegistryEntry registryEntry = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1)); ChunkRandom chunkRandom = new ChunkRandom(new CheckedRandom(RandomSeed.getSeed())); @@ -119,7 +119,6 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C } - @Override public CompletableFuture populateNoise(Executor executor, Blender blender, NoiseConfig noiseConfig, StructureAccessor structureAccessor, Chunk chunk) { @@ -127,7 +126,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); BiomeProvider biomeProvider = pack.getBiomeProvider().caching(world); delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z); - + PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class); if(compatibilityOptions.isBeard()) { beard(structureAccessor, chunk, world, biomeProvider, compatibilityOptions); @@ -137,7 +136,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C } private void beard(StructureAccessor structureAccessor, Chunk chunk, WorldProperties world, BiomeProvider biomeProvider, - PreLoadCompatibilityOptions compatibilityOptions) { + PreLoadCompatibilityOptions compatibilityOptions) { StructureWeightSampler structureWeightSampler = StructureWeightSampler.method_42695(structureAccessor, chunk.getPos()); double threshold = compatibilityOptions.getBeardThreshold(); double airThreshold = compatibilityOptions.getAirThreshold(); @@ -186,14 +185,15 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public int getHeight(int x, int z, Type heightmap, HeightLimitView height, NoiseConfig noiseConfig) { - int y = height.getTopY(); WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); - while(y > getMinimumY() && !heightmap.getBlockPredicate().test( - (BlockState) delegate.getBlock(properties, x, y - 1, z, biomeProvider))) { - y--; + int min = height.getBottomY(); + for(int y = height.getTopY() - 1; y >= min; y--) { + if(heightmap + .getBlockPredicate() + .test((BlockState) delegate.getBlock(properties, x, y, z, biomeProvider))) return y + 1; } - return y; + return min; } @Override From aac16414d984adb87e4074012cf080daff08ec3c Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 20:50:48 -0700 Subject: [PATCH 053/220] attach caching biome provider to protochunk --- .../generation/BiomeProviderHolder.java | 10 ++++++ .../FabricChunkGeneratorWrapper.java | 18 ++++++++++- .../chunk/data/ProtoChunkMixin.java | 32 ++++++++++++++++--- 3 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java new file mode 100644 index 000000000..d3aa529e8 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.fabric.generation; + +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public interface BiomeProviderHolder { + void setBiomeProvider(BiomeProvider biomeProvider); + + BiomeProvider getBiomeProvider(); +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index af5186802..ba5de63ee 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -88,6 +88,17 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C this.biomeSource = biomeSource; } + @Override + public CompletableFuture populateBiomes(Registry biomeRegistry, Executor executor, NoiseConfig noiseConfig, + Blender blender, StructureAccessor structureAccessor, Chunk chunk) { + if(chunk instanceof net.minecraft.world.chunk.ProtoChunk) { + ((BiomeProviderHolder) chunk) + .setBiomeProvider(pack.getBiomeProvider() + .caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld())); + } + return super.populateBiomes(biomeRegistry, executor, noiseConfig, blender, structureAccessor, chunk); + } + public Registry getNoiseRegistry() { return noiseRegistry; } @@ -124,7 +135,12 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C StructureAccessor structureAccessor, Chunk chunk) { return CompletableFuture.supplyAsync(() -> { ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); - BiomeProvider biomeProvider = pack.getBiomeProvider().caching(world); + BiomeProvider biomeProvider; + if(chunk instanceof net.minecraft.world.chunk.ProtoChunk) { + biomeProvider = ((BiomeProviderHolder) chunk).getBiomeProvider(); + } else { + biomeProvider = pack.getBiomeProvider().caching(world); + } delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z); PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java index 627a1766f..a77681b2d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java @@ -17,23 +17,34 @@ package com.dfsek.terra.fabric.mixin.implementations.chunk.data; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; +import com.dfsek.terra.fabric.generation.BiomeProviderHolder; + import net.minecraft.util.math.BlockPos; +import net.minecraft.world.HeightLimitView; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; - @Mixin(net.minecraft.world.chunk.ProtoChunk.class) -@Implements(@Interface(iface = ProtoChunk.class, prefix = "terra$")) +@Implements(value = { + @Interface(iface = ProtoChunk.class, prefix = "terra$"), + @Interface(iface = BiomeProviderHolder.class, prefix = "provider$") +}) public abstract class ProtoChunkMixin { @Shadow public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos); + @Shadow + public abstract HeightLimitView getHeightLimitView(); + + private BiomeProvider biomeProvider; + public void terra$setBlock(int x, int y, int z, @NotNull BlockState blockState) { ((net.minecraft.world.chunk.Chunk) (Object) this).setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) blockState, false); @@ -44,6 +55,17 @@ public abstract class ProtoChunkMixin { } public int terra$getMaxHeight() { - return 255; // TODO: 1.17 - Implement dynamic height. + return getHeightLimitView().getTopY(); + } + + public void provider$setBiomeProvider(BiomeProvider provider) { + if(this.biomeProvider != null) { + throw new IllegalStateException("Already set biome provider for chunk " + this); + } + this.biomeProvider = provider; + } + + public BiomeProvider provider$getBiomeProvider() { + return biomeProvider; } } From dbadef567242770c19f105d9b019f5b072c3dda4 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 20:58:41 -0700 Subject: [PATCH 054/220] add null check for biome provider --- .../terra/fabric/generation/FabricChunkGeneratorWrapper.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index ba5de63ee..5a1beb340 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -138,6 +138,9 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C BiomeProvider biomeProvider; if(chunk instanceof net.minecraft.world.chunk.ProtoChunk) { biomeProvider = ((BiomeProviderHolder) chunk).getBiomeProvider(); + if(biomeProvider == null) { + biomeProvider = pack.getBiomeProvider().caching(world); + } } else { biomeProvider = pack.getBiomeProvider().caching(world); } From db61729e11faefa08ceded51ab4e9998f5ea68ce Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 21:11:20 -0700 Subject: [PATCH 055/220] pass caching provider through all stages --- .../FabricChunkGeneratorWrapper.java | 4 +- .../fabric/mixin/cache/ChunkRegionMixin.java | 48 +++++++++ .../fabric/mixin/cache/ProtoChunkMixin.java | 27 +++++ .../chunk/data/ProtoChunkMixin.java | 18 +--- .../world/ChunkRegionMixin.java | 5 + .../src/main/resources/terra.mixins.json | 100 +++++++++--------- 6 files changed, 134 insertions(+), 68 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 5a1beb340..391e31b4e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -136,8 +136,8 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C return CompletableFuture.supplyAsync(() -> { ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); BiomeProvider biomeProvider; - if(chunk instanceof net.minecraft.world.chunk.ProtoChunk) { - biomeProvider = ((BiomeProviderHolder) chunk).getBiomeProvider(); + if(chunk instanceof BiomeProviderHolder providerHolder) { + biomeProvider = providerHolder.getBiomeProvider(); if(biomeProvider == null) { biomeProvider = pack.getBiomeProvider().caching(world); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java new file mode 100644 index 000000000..b24dfbf6b --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.fabric.mixin.cache; + +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.Chunk; +import com.dfsek.terra.fabric.generation.BiomeProviderHolder; + +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.chunk.ProtoChunk; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +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; + +import java.util.List; + + +@Mixin(ChunkRegion.class) +@Implements(@Interface(iface = BiomeProviderHolder.class, prefix = "provider$")) +public class ChunkRegionMixin { + @Shadow + @Final + private net.minecraft.world.chunk.Chunk centerPos; + private BiomeProvider biomeProvider; + + @Inject(method = "", at = @At("RETURN")) + public void addProvider(ServerWorld world, List chunks, ChunkStatus status, int placementRadius, CallbackInfo ci) { + if(centerPos instanceof BiomeProviderHolder providerHolder) { + biomeProvider = providerHolder.getBiomeProvider(); + } + } + + public void provider$setBiomeProvider(BiomeProvider provider) { + if(this.biomeProvider != null) { + throw new IllegalStateException("Already set biome provider for chunk " + this); + } + this.biomeProvider = provider; + } + + public BiomeProvider provider$getBiomeProvider() { + return biomeProvider; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java new file mode 100644 index 000000000..6818d353f --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.fabric.mixin.cache; + +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.fabric.generation.BiomeProviderHolder; + +import net.minecraft.world.chunk.ProtoChunk; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + + +@Mixin(ProtoChunk.class) +@Implements(@Interface(iface = BiomeProviderHolder.class, prefix = "provider$")) +public class ProtoChunkMixin { + private BiomeProvider biomeProvider; + + public void provider$setBiomeProvider(BiomeProvider provider) { + if(this.biomeProvider != null) { + throw new IllegalStateException("Already set biome provider for chunk " + this); + } + this.biomeProvider = provider; + } + + public BiomeProvider provider$getBiomeProvider() { + return biomeProvider; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java index a77681b2d..a65a4f4d8 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java @@ -32,10 +32,7 @@ import org.spongepowered.asm.mixin.Shadow; @Mixin(net.minecraft.world.chunk.ProtoChunk.class) -@Implements(value = { - @Interface(iface = ProtoChunk.class, prefix = "terra$"), - @Interface(iface = BiomeProviderHolder.class, prefix = "provider$") -}) +@Implements(@Interface(iface = ProtoChunk.class, prefix = "terra$")) public abstract class ProtoChunkMixin { @Shadow public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos); @@ -43,8 +40,6 @@ public abstract class ProtoChunkMixin { @Shadow public abstract HeightLimitView getHeightLimitView(); - private BiomeProvider biomeProvider; - public void terra$setBlock(int x, int y, int z, @NotNull BlockState blockState) { ((net.minecraft.world.chunk.Chunk) (Object) this).setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) blockState, false); @@ -57,15 +52,4 @@ public abstract class ProtoChunkMixin { public int terra$getMaxHeight() { return getHeightLimitView().getTopY(); } - - public void provider$setBiomeProvider(BiomeProvider provider) { - if(this.biomeProvider != null) { - throw new IllegalStateException("Already set biome provider for chunk " + this); - } - this.biomeProvider = provider; - } - - public BiomeProvider provider$getBiomeProvider() { - return biomeProvider; - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java index b849f700a..7b1562d59 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -28,6 +28,7 @@ import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.fabric.generation.BiomeProviderHolder; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.generation.TerraBiomeSource; import com.dfsek.terra.fabric.util.FabricUtil; @@ -130,6 +131,10 @@ public abstract class ChunkRegionMixin { } public BiomeProvider terraWorld$getBiomeProvider() { + BiomeProvider provider = ((BiomeProviderHolder) this).getBiomeProvider(); + if(provider != null) { + return provider; + } return caching.value(); } diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 778f06889..9fb0d4ea2 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -1,51 +1,53 @@ { - "required": true, - "minVersion": "0.8", - "package": "com.dfsek.terra.fabric.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - "ReloadCommandMixin", - "access.MobSpawnerLogicAccessor", - "access.StateAccessor", - "access.StructureAccessorAccessor", - "compat.GenerationSettingsFloraFeaturesMixin", - "implementations.BiomeMixin", - "implementations.HandleImplementationMixin", - "implementations.block.BlockMixin", - "implementations.block.entity.BlockEntityMixin", - "implementations.block.entity.LootableContainerBlockEntityMixin", - "implementations.block.entity.MobSpawnerBlockEntityMixin", - "implementations.block.entity.SignBlockEntityMixin", - "implementations.block.state.BlockStateMixin", - "implementations.block.state.PropertyMixin", - "implementations.chunk.ChunkRegionMixin", - "implementations.chunk.WorldChunkMixin", - "implementations.chunk.data.ProtoChunkMixin", - "implementations.entity.EntityMixin", - "implementations.entity.EntityTypeMixin", - "implementations.entity.PlayerEntityMixin", - "implementations.entity.ServerCommandSourceMixin", - "implementations.inventory.LockableContainerBlockEntityMixin", - "implementations.inventory.item.ItemMixin", - "implementations.inventory.item.ItemStackMixin", - "implementations.inventory.meta.EnchantmentMixin", - "implementations.inventory.meta.ItemStackDamageableMixin", - "implementations.inventory.meta.ItemStackMetaMixin", - "implementations.world.ChunkRegionMixin", - "implementations.world.ServerWorldMixin", - "lifecycle.DataPackContentsMixin", - "lifecycle.MinecraftServerMixin", - "lifecycle.NoiseConfigMixin", - "lifecycle.RegistryMixin" - ], - "client": [ - "lifecycle.client.MinecraftClientMixin" - ], - "server": [ - "lifecycle.server.ServerMainMixin" - ], - "injectors": { - "defaultRequire": 1 - }, - "refmap": "terra-refmap.json" + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.fabric.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "ReloadCommandMixin", + "access.MobSpawnerLogicAccessor", + "access.StateAccessor", + "access.StructureAccessorAccessor", + "cache.ChunkRegionMixin", + "cache.ProtoChunkMixin", + "compat.GenerationSettingsFloraFeaturesMixin", + "implementations.BiomeMixin", + "implementations.HandleImplementationMixin", + "implementations.block.BlockMixin", + "implementations.block.entity.BlockEntityMixin", + "implementations.block.entity.LootableContainerBlockEntityMixin", + "implementations.block.entity.MobSpawnerBlockEntityMixin", + "implementations.block.entity.SignBlockEntityMixin", + "implementations.block.state.BlockStateMixin", + "implementations.block.state.PropertyMixin", + "implementations.chunk.ChunkRegionMixin", + "implementations.chunk.WorldChunkMixin", + "implementations.chunk.data.ProtoChunkMixin", + "implementations.entity.EntityMixin", + "implementations.entity.EntityTypeMixin", + "implementations.entity.PlayerEntityMixin", + "implementations.entity.ServerCommandSourceMixin", + "implementations.inventory.LockableContainerBlockEntityMixin", + "implementations.inventory.item.ItemMixin", + "implementations.inventory.item.ItemStackMixin", + "implementations.inventory.meta.EnchantmentMixin", + "implementations.inventory.meta.ItemStackDamageableMixin", + "implementations.inventory.meta.ItemStackMetaMixin", + "implementations.world.ChunkRegionMixin", + "implementations.world.ServerWorldMixin", + "lifecycle.DataPackContentsMixin", + "lifecycle.MinecraftServerMixin", + "lifecycle.NoiseConfigMixin", + "lifecycle.RegistryMixin" + ], + "client": [ + "lifecycle.client.MinecraftClientMixin" + ], + "server": [ + "lifecycle.server.ServerMainMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "terra-refmap.json" } \ No newline at end of file From 1aa0c715b90736df38775179641cb7641514514d Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 21:16:46 -0700 Subject: [PATCH 056/220] properly implement caching getColumn --- .../addons/biome/extrusion/BiomeExtrusionProvider.java | 4 ++-- .../terra/addons/biome/extrusion/ExtrusionColumn.java | 8 ++++---- .../addons/biome/pipeline/BiomePipelineProvider.java | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index b14207d0f..5c5007612 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -63,7 +63,7 @@ public class BiomeExtrusionProvider implements BiomeProvider { } @Override - public Column getColumn(int x, int z, WorldProperties properties) { - return new ExtrusionColumn(properties, this, x, z, properties.getSeed()); + public Column getColumn(int x, int z, long seed, int min, int max) { + return new ExtrusionColumn(min, max, this, x, z, seed); } } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java index e3d187d35..52b5a6300 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java @@ -14,13 +14,13 @@ public class ExtrusionColumn implements Column { private final long seed; private final Column delegate; - public ExtrusionColumn(WorldProperties worldProperties, BiomeExtrusionProvider provider, int x, int z, long seed) { - this.min = worldProperties.getMinHeight(); - this.max = worldProperties.getMaxHeight(); + public ExtrusionColumn(int min, int max, BiomeExtrusionProvider provider, int x, int z, long seed) { + this.min = min; + this.max = max; this.provider = provider; this.x = x; this.z = z; - this.seed = worldProperties.getSeed(); + this.seed = seed; this.delegate = provider.getDelegate().getColumn(x, z, seed, min, max); } diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java index 4a351a8e4..afcf2d774 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -106,8 +106,8 @@ public class BiomePipelineProvider implements BiomeProvider { } @Override - public Column getColumn(int x, int z, WorldProperties properties) { - return new BiomePipelineColumn(this, properties.getMinHeight(), properties.getMaxHeight(), x, z, properties.getSeed()); + public Column getColumn(int x, int z, long seed, int min, int max) { + return new BiomePipelineColumn(this, min, max, x, z, seed); } private record SeededVector(int x, int z, long seed) { From d58eb699f1fb96867f14cf8454c535cde633b0fd Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 21:39:15 -0700 Subject: [PATCH 057/220] create ChunkLocalCachingBiomeProvider --- .../world/biome/generation/BiomeProvider.java | 4 +- .../generation/CachingBiomeProvider.java | 6 +- .../ChunkLocalCachingBiomeProvider.java | 75 +++++++++++++++++++ 3 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 37483b564..49726c835 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -92,11 +92,11 @@ public interface BiomeProvider { return StreamSupport.stream(getBiomes().spliterator(), false); } - default BiomeProvider caching(int minY, int maxY) { + default CachingBiomeProvider caching(int minY, int maxY) { return new CachingBiomeProvider(this, minY, maxY); } - default BiomeProvider caching(WorldProperties worldProperties) { + default CachingBiomeProvider caching(WorldProperties worldProperties) { return caching(worldProperties.getMinHeight(), worldProperties.getMaxHeight()); } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index 08877f968..bf954f2cd 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -18,9 +18,9 @@ import java.util.Optional; * This is for use in chunk generators, it makes the assumption that the seed remains the same for the duration of its use! */ public class CachingBiomeProvider implements BiomeProvider, Handle { - private final BiomeProvider delegate; - private final int minY; - private final int maxY; + protected final BiomeProvider delegate; + protected final int minY; + protected final int maxY; private final Map cache = new HashMap<>(); private final Map> columnCache = new HashMap<>(); diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java new file mode 100644 index 000000000..deb74d97b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java @@ -0,0 +1,75 @@ +package com.dfsek.terra.api.world.biome.generation; + +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.info.WorldProperties; + +import net.jafama.FastMath; + +import java.util.Optional; + + +/** + * A biome provider implementation that lazily evaluates biomes, and caches them. + *

+ * This is for use in chunk generators, it makes the assumption that the seed remains the same for the duration of its use! + *

+ * The cache works the best when all biomes are within one chunk! This is because internally, there are two caches, one constant-size one + * for the chunk, and a slower dynamically-sized cache for out-of-chunk biomes. + */ +public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { + private final Biome[][][] cache; + private final Column[][] columnCache = new Column<>[16][16]; + + private final int chunkX; + private final int chunkZ; + + protected ChunkLocalCachingBiomeProvider(BiomeProvider delegate, WorldProperties worldProperties, int chunkX, int chunkZ) { + super(delegate, worldProperties.getMinHeight(), worldProperties.getMaxHeight()); + this.cache = new Biome[16][maxY - minY][16]; + this.chunkX = chunkX; + this.chunkZ = chunkZ; + } + + @Override + public BiomeProvider getHandle() { + return delegate; + } + + @Override + public Biome getBiome(int x, int y, int z, long seed) { + if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) { + Biome biome = cache[x & 15][y - minY][z & 15]; + if(biome == null) { + biome = delegate.getBiome(x, y, z, seed); + cache[x & 15][y - minY][z & 15] = biome; + } + return biome; + } + + return super.getBiome(x, y, z, seed); + } + + @Override + public Optional getBaseBiome(int x, int z, long seed) { + return delegate.getBaseBiome(x, z, seed); + } + + @Override + public Column getColumn(int x, int z, long seed, int min, int max) { + if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) { + Column column = columnCache[x & 15][z & 15]; + if(column == null) { + column = delegate.getColumn(x, z, seed, min, max); + columnCache[x & 15][z & 15] = column; + } + return column; + } + return super.getColumn(x, z, seed, min, max); + } + + @Override + public Iterable getBiomes() { + return delegate.getBiomes(); + } +} From 881477c42f8993fcc66491c634f01b492f06e225 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 21:50:04 -0700 Subject: [PATCH 058/220] use ChunkLocalCachingBiomeProvider --- .../dfsek/terra/api/world/biome/generation/BiomeProvider.java | 4 ++++ .../biome/generation/ChunkLocalCachingBiomeProvider.java | 2 +- .../terra/fabric/generation/FabricChunkGeneratorWrapper.java | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 49726c835..43b70f4a3 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -99,4 +99,8 @@ public interface BiomeProvider { default CachingBiomeProvider caching(WorldProperties worldProperties) { return caching(worldProperties.getMinHeight(), worldProperties.getMaxHeight()); } + + default ChunkLocalCachingBiomeProvider caching(WorldProperties worldProperties, int chunkX, int chunkZ) { + return new ChunkLocalCachingBiomeProvider(this, worldProperties, chunkX, chunkZ); + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java index deb74d97b..075b0b446 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java @@ -19,7 +19,7 @@ import java.util.Optional; */ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { private final Biome[][][] cache; - private final Column[][] columnCache = new Column<>[16][16]; + private final Column[][] columnCache = new Column[16][16]; private final int chunkX; private final int chunkZ; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 391e31b4e..92bdf3fe7 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -92,9 +92,10 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C public CompletableFuture populateBiomes(Registry biomeRegistry, Executor executor, NoiseConfig noiseConfig, Blender blender, StructureAccessor structureAccessor, Chunk chunk) { if(chunk instanceof net.minecraft.world.chunk.ProtoChunk) { + ChunkPos pos = chunk.getPos(); ((BiomeProviderHolder) chunk) .setBiomeProvider(pack.getBiomeProvider() - .caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld())); + .caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(), pos.x, pos.z)); } return super.populateBiomes(biomeRegistry, executor, noiseConfig, blender, structureAccessor, chunk); } From a33982a43280f6af136f5a814b238d35b2832a77 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 23:30:53 -0700 Subject: [PATCH 059/220] add carving.update-palette option --- .../chunkgenerator/config/palette/BiomePaletteTemplate.java | 6 +++++- .../addons/chunkgenerator/config/palette/PaletteInfo.java | 3 ++- .../chunkgenerator/generation/NoiseChunkGenerator3D.java | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) 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 3497bdd75..9bab84bb5 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 @@ -59,6 +59,10 @@ public class BiomePaletteTemplate implements ObjectTemplate { } }; + @Value("carving.update-palette") + @Default + private boolean updatePalette = false; + public BiomePaletteTemplate(Platform platform) { this.platform = platform; } @Override @@ -79,6 +83,6 @@ public class BiomePaletteTemplate implements ObjectTemplate { slantLayers.put(threshold, layer.getPalette()); } - return new PaletteInfo(builder.build(), SlantHolder.of(slantLayers, minThreshold), oceanPalette, seaLevel, slantDepth); + return new PaletteInfo(builder.build(), SlantHolder.of(slantLayers, minThreshold), oceanPalette, seaLevel, slantDepth, updatePalette); } } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/PaletteInfo.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/PaletteInfo.java index d866446a3..caf3c4802 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/PaletteInfo.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/PaletteInfo.java @@ -17,5 +17,6 @@ public record PaletteInfo(PaletteHolder paletteHolder, SlantHolder slantHolder, Palette ocean, int seaLevel, - int maxSlantDepth) implements Properties { + int maxSlantDepth, + boolean updatePaletteWhenCarving) implements Properties { } 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 de4354198..147f3c9d8 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 @@ -90,6 +90,8 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { data = PaletteUtil.getPalette(x, y, z, sampler, paletteInfo, paletteLevel).get(paletteLevel, cx, y, cz, seed); chunk.setBlock(x, y, z, data); + } else if(paletteInfo.updatePaletteWhenCarving()) { + paletteLevel = 0; } paletteLevel++; From 779834267ee766573372fe019a064d166bc44d6b Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 11 Jun 2022 23:56:28 -0700 Subject: [PATCH 060/220] fix BiomeProviderHolder NPE --- .../dfsek/terra/fabric/generation/BiomeProviderHolder.java | 4 ++-- .../fabric/generation/FabricChunkGeneratorWrapper.java | 4 ++-- .../dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java | 7 +++---- .../dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java | 4 ++-- .../mixin/implementations/world/ChunkRegionMixin.java | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java index d3aa529e8..2204a59fc 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java @@ -4,7 +4,7 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider; public interface BiomeProviderHolder { - void setBiomeProvider(BiomeProvider biomeProvider); + void terra$setHeldBiomeProvider(BiomeProvider biomeProvider); - BiomeProvider getBiomeProvider(); + BiomeProvider terra$getHeldBiomeProvider(); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 92bdf3fe7..c0faf5181 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -94,7 +94,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C if(chunk instanceof net.minecraft.world.chunk.ProtoChunk) { ChunkPos pos = chunk.getPos(); ((BiomeProviderHolder) chunk) - .setBiomeProvider(pack.getBiomeProvider() + .terra$setHeldBiomeProvider(pack.getBiomeProvider() .caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(), pos.x, pos.z)); } return super.populateBiomes(biomeRegistry, executor, noiseConfig, blender, structureAccessor, chunk); @@ -138,7 +138,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); BiomeProvider biomeProvider; if(chunk instanceof BiomeProviderHolder providerHolder) { - biomeProvider = providerHolder.getBiomeProvider(); + biomeProvider = providerHolder.terra$getHeldBiomeProvider(); if(biomeProvider == null) { biomeProvider = pack.getBiomeProvider().caching(world); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java index b24dfbf6b..8f69f0523 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java @@ -7,7 +7,6 @@ import com.dfsek.terra.fabric.generation.BiomeProviderHolder; import net.minecraft.server.world.ServerWorld; import net.minecraft.world.ChunkRegion; import net.minecraft.world.chunk.ChunkStatus; -import net.minecraft.world.chunk.ProtoChunk; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -31,18 +30,18 @@ public class ChunkRegionMixin { @Inject(method = "", at = @At("RETURN")) public void addProvider(ServerWorld world, List chunks, ChunkStatus status, int placementRadius, CallbackInfo ci) { if(centerPos instanceof BiomeProviderHolder providerHolder) { - biomeProvider = providerHolder.getBiomeProvider(); + biomeProvider = providerHolder.terra$getHeldBiomeProvider(); } } - public void provider$setBiomeProvider(BiomeProvider provider) { + public void provider$terra$setHeldBiomeProvider(BiomeProvider provider) { if(this.biomeProvider != null) { throw new IllegalStateException("Already set biome provider for chunk " + this); } this.biomeProvider = provider; } - public BiomeProvider provider$getBiomeProvider() { + public BiomeProvider provider$terra$getHeldBiomeProvider() { return biomeProvider; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java index 6818d353f..0b0684947 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java @@ -14,14 +14,14 @@ import org.spongepowered.asm.mixin.Mixin; public class ProtoChunkMixin { private BiomeProvider biomeProvider; - public void provider$setBiomeProvider(BiomeProvider provider) { + public void provider$terra$setHeldBiomeProvider(BiomeProvider provider) { if(this.biomeProvider != null) { throw new IllegalStateException("Already set biome provider for chunk " + this); } this.biomeProvider = provider; } - public BiomeProvider provider$getBiomeProvider() { + public BiomeProvider provider$terra$getHeldBiomeProvider() { return biomeProvider; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java index 7b1562d59..5805ebc1c 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -131,7 +131,7 @@ public abstract class ChunkRegionMixin { } public BiomeProvider terraWorld$getBiomeProvider() { - BiomeProvider provider = ((BiomeProviderHolder) this).getBiomeProvider(); + BiomeProvider provider = ((BiomeProviderHolder) this).terra$getHeldBiomeProvider(); if(provider != null) { return provider; } From 5409725709f2538e7dccba5e82c2d1bf9be8bacd Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 12 Jun 2022 00:10:44 -0700 Subject: [PATCH 061/220] fix palette level when caves use palettes --- .../addons/chunkgenerator/generation/NoiseChunkGenerator3D.java | 1 + 1 file changed, 1 insertion(+) 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 147f3c9d8..7a5e83575 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 @@ -92,6 +92,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { chunk.setBlock(x, y, z, data); } else if(paletteInfo.updatePaletteWhenCarving()) { paletteLevel = 0; + continue; } paletteLevel++; From 7d6746ad47465c5aceb69ef031531266cb64ca0c Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 12 Jun 2022 01:02:16 -0700 Subject: [PATCH 062/220] allow metaconfiguration on PaletteLayerLoader --- .../terra/addons/palette/palette/PaletteLayerLoader.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerLoader.java b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerLoader.java index f0ad5cbd1..0e12682ab 100644 --- a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerLoader.java +++ b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerLoader.java @@ -12,20 +12,21 @@ import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.util.collection.ProbabilityCollection; public class PaletteLayerLoader implements ObjectTemplate { @Value("materials") - private ProbabilityCollection collection; + private @Meta ProbabilityCollection<@Meta BlockState> collection; @Value("sampler") @Default - private NoiseSampler sampler = null; + private @Meta NoiseSampler sampler = null; @Value("layers") - private int layers; + private @Meta int layers; @Override public PaletteLayerHolder get() { From 0aadfdb3561cd40ee629ea04c742dd108cc1cfa3 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 12 Jun 2022 01:14:35 -0700 Subject: [PATCH 063/220] allow meta on updatePalette --- .../chunkgenerator/config/palette/BiomePaletteTemplate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9bab84bb5..f95d9dffa 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 @@ -61,7 +61,7 @@ public class BiomePaletteTemplate implements ObjectTemplate { @Value("carving.update-palette") @Default - private boolean updatePalette = false; + private @Meta boolean updatePalette = false; public BiomePaletteTemplate(Platform platform) { this.platform = platform; } From 9d6ad582d84913606a19db88d81031f6ca3dbd98 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 12 Jun 2022 01:41:39 -0700 Subject: [PATCH 064/220] more clear palette level logic --- .../generation/NoiseChunkGenerator3D.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) 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 7a5e83575..c06101979 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 @@ -8,11 +8,6 @@ package com.dfsek.terra.addons.chunkgenerator.generation; -import com.dfsek.terra.api.util.Column; - -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - import com.dfsek.terra.addons.chunkgenerator.config.palette.PaletteInfo; import com.dfsek.terra.addons.chunkgenerator.generation.math.PaletteUtil; import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.LazilyEvaluatedInterpolator; @@ -20,6 +15,7 @@ import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; @@ -27,6 +23,9 @@ import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; import com.dfsek.terra.api.world.chunk.generation.util.Palette; import com.dfsek.terra.api.world.info.WorldProperties; +import net.jafama.FastMath; +import org.jetbrains.annotations.NotNull; + public class NoiseChunkGenerator3D implements ChunkGenerator { private final Platform platform; @@ -79,23 +78,24 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { BlockState data; for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { Biome biome = biomeColumn.get(y); - + PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); - + int sea = paletteInfo.seaLevel(); Palette seaPalette = paletteInfo.ocean(); if(sampler.sample(x, y, z) > 0) { if(carver.sample(x, y, z) <= 0) { - data = PaletteUtil.getPalette(x, y, z, sampler, paletteInfo, paletteLevel).get(paletteLevel, cx, y, cz, - seed); + data = PaletteUtil + .getPalette(x, y, z, sampler, paletteInfo, paletteLevel) + .get(paletteLevel, cx, y, cz, seed); chunk.setBlock(x, y, z, data); + paletteLevel++; } else if(paletteInfo.updatePaletteWhenCarving()) { paletteLevel = 0; - continue; + } else { + paletteLevel++; } - - paletteLevel++; } else if(y <= sea) { chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig, seed)); paletteLevel = 0; From 29d8e7eed429fa4b5be83740012b6a253fb23b47 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 13 Jun 2022 10:07:08 -0700 Subject: [PATCH 065/220] caching biome provider in BukkitProtoWorld --- .../com/dfsek/terra/bukkit/world/BukkitProtoWorld.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java index 579fc4825..b2ad43954 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java @@ -1,5 +1,9 @@ package com.dfsek.terra.bukkit.world; +import com.dfsek.terra.api.util.generic.Lazy; + +import com.dfsek.terra.api.world.biome.generation.ChunkLocalCachingBiomeProvider; + import org.bukkit.Location; import org.bukkit.generator.LimitedRegion; import org.slf4j.Logger; @@ -31,9 +35,13 @@ public class BukkitProtoWorld implements ProtoWorld { private final LimitedRegion delegate; private final BlockState air; + private final ChunkLocalCachingBiomeProvider biomeProvider; + public BukkitProtoWorld(LimitedRegion delegate, BlockState air) { this.delegate = delegate; this.air = air; + this.biomeProvider = ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack().getBiomeProvider().caching(new BukkitWorldProperties( + delegate.getWorld()), delegate.getCenterChunkX(), delegate.getCenterChunkZ()); } @Override @@ -90,7 +98,7 @@ public class BukkitProtoWorld implements ProtoWorld { @Override public BiomeProvider getBiomeProvider() { - return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack().getBiomeProvider(); + return biomeProvider; } @Override From 7f05933a1ad8ea9ea4bba9cefe16cebfe5e235e8 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 13 Jun 2022 13:54:10 -0700 Subject: [PATCH 066/220] add palette resolution config options --- ...NoiseChunkGeneratorPackConfigTemplate.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) 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 e636ae400..cd883a2af 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 @@ -5,6 +5,7 @@ import com.dfsek.tectonic.api.config.template.annotations.Default; import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate { @@ -12,6 +13,18 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate { @Default private @Meta int elevationBlend = 4; + @Value("blend.palette.resolution") + @Default + private @Meta int paletteRes = 4; + + @Value("blend.palette.sampler") + @Default + private @Meta NoiseSampler paletteBlendSampler = NoiseSampler.zero(); + + @Value("blend.palette.amplitude") + @Default + private @Meta double paletteBlendAmplitude = 0; + @Value("carving.resolution.horizontal") @Default private @Meta int horizontalRes = 4; @@ -31,4 +44,16 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate { public int getVerticalRes() { return verticalRes; } + + public double getPaletteBlendAmplitude() { + return paletteBlendAmplitude; + } + + public int getPaletteRes() { + return paletteRes; + } + + public NoiseSampler getPaletteBlendSampler() { + return paletteBlendSampler; + } } From 4d6d14a3d8b259c59af0a2b1847aee9014cf0b3d Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 13 Jun 2022 13:56:46 -0700 Subject: [PATCH 067/220] inject palette resolution options --- .../chunkgenerator/NoiseChunkGenerator3DAddon.java | 2 +- .../generation/NoiseChunkGenerator3D.java | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java index a36f9093b..fc44046c1 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java @@ -42,7 +42,7 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { .getOrCreateRegistry(ChunkGeneratorProvider.class) .register(addon.key("NOISE_3D"), pack -> new NoiseChunkGenerator3D(platform, config.getElevationBlend(), config.getHorizontalRes(), - config.getVerticalRes())); + config.getVerticalRes(), config.getPaletteRes(), config.getPaletteBlendSampler(), config.getPaletteBlendAmplitude())); event.getPack() .applyLoader(SlantLayer.class, SlantLayer::new); }) 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 c06101979..bb26ecb44 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 @@ -15,6 +15,7 @@ import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; @@ -37,12 +38,22 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { private final int carverHorizontalResolution; private final int carverVerticalResolution; + private final int paletteRes; + + private final NoiseSampler paletteBlendSampler; + + private final double paletteBlendAmplitude; + public NoiseChunkGenerator3D(Platform platform, int elevationBlend, int carverHorizontalResolution, - int carverVerticalResolution) { + int carverVerticalResolution, int paletteRes, NoiseSampler paletteBlendSampler, + double paletteBlendAmplitude) { this.platform = platform; this.air = platform.getWorldHandle().air(); this.carverHorizontalResolution = carverHorizontalResolution; this.carverVerticalResolution = carverVerticalResolution; + this.paletteRes = paletteRes; + this.paletteBlendSampler = paletteBlendSampler; + this.paletteBlendAmplitude = paletteBlendAmplitude; this.samplerCache = new SamplerProvider(platform, elevationBlend); } From 012209cfcf5ce7dc9e348bfc5b5e3beffe6cf26b Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 13 Jun 2022 15:42:15 -0700 Subject: [PATCH 068/220] implement palette sparse sampling --- .../generation/NoiseChunkGenerator3D.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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 bb26ecb44..d37c7c7e8 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 @@ -57,6 +57,15 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { this.samplerCache = new SamplerProvider(platform, elevationBlend); } + private Biome getBiome(BiomeProvider biomeProvider, int x, int y, int z, long seed) { + long ms = seed; + int mx = FastMath.floorDiv(x + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed++, x, y, z)), paletteRes) * paletteRes; + int my = FastMath.floorDiv(y + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed++, x, y, z)), paletteRes) * paletteRes; + int mz = FastMath.floorDiv(z + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed, x, y, z)), paletteRes) * paletteRes; + + return biomeProvider.getBiome(mx, my, mz, ms); + } + @Override @SuppressWarnings("try") public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world, @@ -85,10 +94,9 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { int cx = xOrig + x; int cz = zOrig + z; - Column biomeColumn = biomeProvider.getColumn(cx, cz, world); BlockState data; for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { - Biome biome = biomeColumn.get(y); + Biome biome = getBiome(biomeProvider, cx, y, cz, seed); PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); From b62c4d742f1605930b05c78cdc3bb114970810b9 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 13 Jun 2022 22:39:39 -0700 Subject: [PATCH 069/220] drastically optimize ChunkInterpolator --- .../noise/BiomeNoiseConfigTemplate.java | 3 +- .../config/noise/BiomeNoiseProperties.java | 5 +- .../config/noise/ThreadLocalNoiseHolder.java | 32 +++++++++++++ .../math/interpolation/ChunkInterpolator.java | 46 +++++++------------ 4 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/ThreadLocalNoiseHolder.java diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java index 14d3c97d2..0e091b44b 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java @@ -6,6 +6,7 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.mutable.MutableInteger; public class BiomeNoiseConfigTemplate implements ObjectTemplate { @@ -39,6 +40,6 @@ public class BiomeNoiseConfigTemplate implements ObjectTemplate holder = ThreadLocal.withInitial(Holder::new); + + public double getNoise(NoiseSampler sampler, int x, int y, int z, long seed) { + Holder holder = this.holder.get(); + + if(holder.init && holder.y == y && holder.z == z && holder.x == x && holder.seed == seed) { + return holder.noise; + } + + double noise = sampler.noise(seed, x, y, z); + holder.noise = noise; + holder.x = x; + holder.y = y; + holder.z = z; + holder.seed = seed; + holder.init = true; + return noise; + } + + private static final class Holder { + int x, y, z; + boolean init = false; + long seed; + double noise; + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 652b64790..cf3ea06b7 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -25,7 +25,6 @@ import java.util.Map; */ public class ChunkInterpolator { private final Interpolator3[][][] interpGrid; - private final long seed; private final int min; private final int max; @@ -42,8 +41,7 @@ public class ChunkInterpolator { public ChunkInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int min, int max) { this.min = min; this.max = max; - this.seed = seed; - + int xOrigin = chunkX << 4; int zOrigin = chunkZ << 4; @@ -65,23 +63,29 @@ public class ChunkInterpolator { for(int y = 0; y < size; y++) { int scaledY = (y << 2) + min; BiomeNoiseProperties generationSettings = column.get(scaledY) - .getContext() - .get(BiomeNoiseProperties.class); - Map genMap = new HashMap<>(); + .getContext() + .get(BiomeNoiseProperties.class); int step = generationSettings.blendStep(); int blend = generationSettings.blendDistance(); + double runningNoise = 0; + double runningDiv = 0; + for(int xi = -blend; xi <= blend; xi++) { for(int zi = -blend; zi <= blend; zi++) { - genMap.computeIfAbsent( - provider.getBiome(absoluteX + (xi * step), scaledY, absoluteZ + (zi * step), seed) - .getContext() - .get(BiomeNoiseProperties.class), - g -> new MutableInteger(0)).increment(); // Increment by 1 + BiomeNoiseProperties properties = provider + .getBiome(absoluteX + (xi * step), scaledY, absoluteZ + (zi * step), seed) + .getContext() + .get(BiomeNoiseProperties.class); + double sample = properties.noiseHolder().getNoise(properties.base(), absoluteX, scaledY, absoluteZ, seed); + runningNoise += sample * properties.blendWeight(); + runningDiv += properties.blendWeight(); } } - double noise = computeNoise(genMap, absoluteX, scaledY, absoluteZ); + + double noise = runningNoise / runningDiv; + noiseStorage[x][z][y] = noise; if(y == size - 1) { noiseStorage[x][z][size] = noise; @@ -111,24 +115,6 @@ public class ChunkInterpolator { return FastMath.max(FastMath.min(value, high), 0); } - public double computeNoise(BiomeNoiseProperties generationSettings, double x, double y, double z) { - return generationSettings.base().noise(seed, x, y, z); - } - - public double computeNoise(Map gens, double x, double y, double z) { - double n = 0; - double div = 0; - for(Map.Entry entry : gens.entrySet()) { - BiomeNoiseProperties gen = entry.getKey(); - int weight = entry.getValue().get(); - double noise = computeNoise(gen, x, y, z); - - n += noise * weight; - div += gen.blendWeight() * weight; - } - return n / div; - } - /** * Gets the noise at a pair of internal chunk coordinates. * From 4f92205085b1ccefc7c3c99ffe2ea3d0c4004754 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 13 Jun 2022 22:45:31 -0700 Subject: [PATCH 070/220] palette blend resolution default to 1 --- .../config/NoiseChunkGeneratorPackConfigTemplate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 cd883a2af..b4b9afc98 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 @@ -15,7 +15,7 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate { @Value("blend.palette.resolution") @Default - private @Meta int paletteRes = 4; + private @Meta int paletteRes = 1; @Value("blend.palette.sampler") @Default From d80d653d3a23ba843a8952b716880a8804afcdc5 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 13 Jun 2022 22:46:22 -0700 Subject: [PATCH 071/220] optimization for when palette resolution is 1 --- .../chunkgenerator/generation/NoiseChunkGenerator3D.java | 3 +++ 1 file changed, 3 insertions(+) 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 d37c7c7e8..b5fea266c 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 @@ -58,6 +58,9 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { } private Biome getBiome(BiomeProvider biomeProvider, int x, int y, int z, long seed) { + if(paletteBlendAmplitude == 1) { + return biomeProvider.getBiome(x, y, z, seed); + } long ms = seed; int mx = FastMath.floorDiv(x + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed++, x, y, z)), paletteRes) * paletteRes; int my = FastMath.floorDiv(y + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed++, x, y, z)), paletteRes) * paletteRes; From 9f6dcfd71b0b00ca92957c6fdbe18a8b289e9fca Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 13 Jun 2022 23:13:41 -0700 Subject: [PATCH 072/220] drastically optimize ChunkLocalCachingBiomeProvider --- .../ChunkLocalCachingBiomeProvider.java | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java index 075b0b446..9e73f3825 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java @@ -1,6 +1,7 @@ package com.dfsek.terra.api.world.biome.generation; import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.util.generic.Construct; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.info.WorldProperties; @@ -18,15 +19,16 @@ import java.util.Optional; * for the chunk, and a slower dynamically-sized cache for out-of-chunk biomes. */ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { - private final Biome[][][] cache; - private final Column[][] columnCache = new Column[16][16]; + private final BiomeChunk[] chunks = new BiomeChunk[9]; + private final Column[] columnCache = new Column[256]; // x + z * 16 private final int chunkX; private final int chunkZ; + private final int height; protected ChunkLocalCachingBiomeProvider(BiomeProvider delegate, WorldProperties worldProperties, int chunkX, int chunkZ) { super(delegate, worldProperties.getMinHeight(), worldProperties.getMaxHeight()); - this.cache = new Biome[16][maxY - minY][16]; + this.height = maxY - minY; this.chunkX = chunkX; this.chunkZ = chunkZ; } @@ -38,11 +40,23 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { @Override public Biome getBiome(int x, int y, int z, long seed) { - if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) { - Biome biome = cache[x & 15][y - minY][z & 15]; + int localChunkX = FastMath.floorDiv(x, 16) - this.chunkX + 1; + int localChunkZ = FastMath.floorDiv(z, 16) - this.chunkZ + 1; + + if(localChunkX >= 0 && localChunkZ >= 0 && localChunkX <= 2 && localChunkZ <= 2) { + int chunkIndex = localChunkX + localChunkZ * 3; + + BiomeChunk chunk = chunks[chunkIndex]; + if(chunk == null) { + chunk = new BiomeChunk(height); + chunks[chunkIndex] = chunk; + } + + int biomeIndex = (x & 15) + 16 * (z & 15) + 256 * (y - minY); + Biome biome = chunk.cache[biomeIndex]; if(biome == null) { biome = delegate.getBiome(x, y, z, seed); - cache[x & 15][y - minY][z & 15] = biome; + chunk.cache[biomeIndex] = biome; } return biome; } @@ -58,10 +72,11 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { @Override public Column getColumn(int x, int z, long seed, int min, int max) { if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) { - Column column = columnCache[x & 15][z & 15]; + int index = (x & 15) + (16 * (z & 15)); + Column column = columnCache[index]; if(column == null) { column = delegate.getColumn(x, z, seed, min, max); - columnCache[x & 15][z & 15] = column; + columnCache[index] = column; } return column; } @@ -72,4 +87,12 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { public Iterable getBiomes() { return delegate.getBiomes(); } + + private static class BiomeChunk { + final Biome[] cache; // x + z * 16 + y * 256 + + private BiomeChunk(int height) { + this.cache = new Biome[16 * 16 * height]; + } + } } From 1aa73bf742e6e7cb4f15aec285b0f9d3a78af64f Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 09:07:41 -0700 Subject: [PATCH 073/220] optimise equals and hashCode of SeededVector --- .../biome/pipeline/BiomePipelineProvider.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java index afcf2d774..56208d669 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -16,6 +16,7 @@ import net.jafama.FastMath; import java.util.Comparator; import java.util.HashSet; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.StreamSupport; @@ -111,5 +112,19 @@ public class BiomePipelineProvider implements BiomeProvider { } private record SeededVector(int x, int z, long seed) { + @Override + public boolean equals(Object obj) { + if(obj instanceof SeededVector that) { + return this.z == that.z && this.x == that.x && this.seed == that.seed; + } + return false; + } + + @Override + public int hashCode() { + int code = x; + code = 31 * code + z; + return 31 * code + ((int) (seed ^ (seed >>> 32))); + } } } From 5799b81414cbc75ef64a65c460250c237c1d9199 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 18:32:43 -0700 Subject: [PATCH 074/220] use chunklocal cache for misses in FabricChunkGeneratorWrapper --- .../terra/fabric/generation/FabricChunkGeneratorWrapper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index c0faf5181..ec5eeef2a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -140,10 +140,10 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C if(chunk instanceof BiomeProviderHolder providerHolder) { biomeProvider = providerHolder.terra$getHeldBiomeProvider(); if(biomeProvider == null) { - biomeProvider = pack.getBiomeProvider().caching(world); + biomeProvider = pack.getBiomeProvider().caching(world, chunk.getPos().x, chunk.getPos().z); } } else { - biomeProvider = pack.getBiomeProvider().caching(world); + biomeProvider = pack.getBiomeProvider().caching(world, chunk.getPos().x, chunk.getPos().z); } delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z); From eac8d3b4e8c4be3a044d5faa2d389ea6c922c257 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 18:34:58 -0700 Subject: [PATCH 075/220] add resolution parameter to Column#forRanges --- .../addons/biome/pipeline/BiomePipelineColumn.java | 2 +- .../generation/feature/FeatureGenerationStage.java | 2 +- .../src/main/java/com/dfsek/terra/api/util/Column.java | 10 ++++------ common/api/src/test/java/util/ColumnTest.java | 6 +++--- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java index 2f9d5f15e..2bae69d45 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java @@ -51,7 +51,7 @@ class BiomePipelineColumn implements Column { } @Override - public void forRanges(IntIntObjConsumer consumer) { + public void forRanges(int resolution, IntIntObjConsumer consumer) { consumer.accept(min, max, biome); } 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 4fbc3f2c9..0c250b35c 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 @@ -50,7 +50,7 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab int tz = cz + chunkZ; world.getBiomeProvider() .getColumn(tx, tz, world) - .forRanges((min, max, biome) -> { + .forRanges(resolution, (min, max, biome) -> { for(int subChunkX = 0; subChunkX < resolution; subChunkX++) { for(int subChunkZ = 0; subChunkZ < resolution; subChunkZ++) { int x = subChunkX + tx; diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index cbabcaaa1..0d781457b 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -3,10 +3,6 @@ package com.dfsek.terra.api.util; import com.dfsek.terra.api.util.function.IntIntObjConsumer; import com.dfsek.terra.api.util.function.IntObjConsumer; -import com.google.common.collect.ImmutableList; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -18,6 +14,7 @@ public interface Column { int getMaxY(); int getX(); + int getZ(); T get(int y); @@ -33,7 +30,8 @@ public interface Column { consumer.accept(y, get(y)); } } - default void forRanges(IntIntObjConsumer consumer) { + + default void forRanges(int resolution, IntIntObjConsumer consumer) { int min = getMinY(); int y = min; @@ -45,7 +43,7 @@ public interface Column { int max = getMaxY() - 1; while(y < max) { - y++; + y += resolution; T current = get(y); if(!current.equals(runningObj)) { diff --git a/common/api/src/test/java/util/ColumnTest.java b/common/api/src/test/java/util/ColumnTest.java index df6f2d53c..bcb3f6064 100644 --- a/common/api/src/test/java/util/ColumnTest.java +++ b/common/api/src/test/java/util/ColumnTest.java @@ -38,7 +38,7 @@ public class ColumnTest { public void testForRanges() { List, Boolean>> list = new ArrayList<>(); - returnPositive.forRanges((min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); + returnPositive.forRanges(1, (min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); assertEquals(List.of( Pair.of(Pair.of(-10, 0), false), @@ -51,7 +51,7 @@ public class ColumnTest { public void testForRangesIndividual() { List, Integer>> list = new ArrayList<>(); - returnY.forRanges((min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); + returnY.forRanges(1, (min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); assertEquals(IntStream.range(-10, 10).mapToObj(i -> Pair.of(Pair.of(i, i + 1), i)).collect(Collectors.toList()), list); @@ -61,7 +61,7 @@ public class ColumnTest { public void testForRangesContiguous() { List, Boolean>> list = new ArrayList<>(); - returnTrue.forRanges((min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); + returnTrue.forRanges(1, (min, max, p) -> list.add(Pair.of(Pair.of(min, max), p))); assertEquals(List.of(Pair.of(Pair.of(-10, 10), true)), list); From 61a40b4825945cf6ad2638acda9cadcab3f3aa04 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 18:56:51 -0700 Subject: [PATCH 076/220] remove unneeded specialised column impl --- .../extrusion/BiomeExtrusionProvider.java | 5 -- .../biome/extrusion/ExtrusionColumn.java | 76 ------------------- .../generation/CachingBiomeProvider.java | 2 +- .../ChunkLocalCachingBiomeProvider.java | 2 +- 4 files changed, 2 insertions(+), 83 deletions(-) delete mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index 5c5007612..e5865e7f9 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -61,9 +61,4 @@ public class BiomeExtrusionProvider implements BiomeProvider { public BiomeProvider getDelegate() { return delegate; } - - @Override - public Column getColumn(int x, int z, long seed, int min, int max) { - return new ExtrusionColumn(min, max, this, x, z, seed); - } } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java deleted file mode 100644 index 52b5a6300..000000000 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/ExtrusionColumn.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.dfsek.terra.addons.biome.extrusion; - -import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.util.function.IntIntObjConsumer; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.api.world.info.WorldProperties; - - -public class ExtrusionColumn implements Column { - private final int min; - private final int max; - private final BiomeExtrusionProvider provider; - private final int x, z; - private final long seed; - private final Column delegate; - - public ExtrusionColumn(int min, int max, BiomeExtrusionProvider provider, int x, int z, long seed) { - this.min = min; - this.max = max; - this.provider = provider; - this.x = x; - this.z = z; - this.seed = seed; - this.delegate = provider.getDelegate().getColumn(x, z, seed, min, max); - } - - @Override - public int getMinY() { - return min; - } - - @Override - public int getMaxY() { - return max; - } - - @Override - public int getX() { - return x; - } - - @Override - public int getZ() { - return z; - } - - @Override - public Biome get(int y) { - return provider.getBiome(x, y, z, seed, delegate.get(y)); - } - - @Override - public void forRanges(IntIntObjConsumer consumer) { - int min = getMinY(); - - int y = min; - - Biome runningObj = get(y); - - int runningMin = min; - - int max = getMaxY() - 1; - - while(y < max) { - y += provider.getResolution(); - Biome current = get(y); - - if(!current.equals(runningObj)) { - consumer.accept(runningMin, y, runningObj); - runningMin = y; - runningObj = current; - } - } - consumer.accept(runningMin, ++y, runningObj); - } -} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index bf954f2cd..ea40118a3 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -53,7 +53,7 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { @Override public Column getColumn(int x, int z, long seed, int min, int max) { - return columnCache.computeIfAbsent(MathUtil.squash(x, z), k -> delegate.getColumn(x, z, seed, min, max)); + return columnCache.computeIfAbsent(MathUtil.squash(x, z), k -> new BiomeColumn(this, min, max, x, z, seed)); } @Override diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java index 9e73f3825..dead2dfaa 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java @@ -75,7 +75,7 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { int index = (x & 15) + (16 * (z & 15)); Column column = columnCache[index]; if(column == null) { - column = delegate.getColumn(x, z, seed, min, max); + column = new BiomeColumn(this, min, max, x, z, seed); columnCache[index] = column; } return column; From 8b12dda60413c95278bafbd2431d8693fa41ea44 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 18:57:01 -0700 Subject: [PATCH 077/220] fix OOBE with low res column --- .../api/src/main/java/com/dfsek/terra/api/util/Column.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index 0d781457b..6537e3d9b 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -42,8 +42,11 @@ public interface Column { int max = getMaxY() - 1; - while(y < max) { + while(true) { y += resolution; + if(y >= max) { + break; + } T current = get(y); if(!current.equals(runningObj)) { From 613b96288a2b77d3aa9e90627b4885171a7d0f5d Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 19:09:43 -0700 Subject: [PATCH 078/220] add primitive overrides to TerraScript items --- .../dfsek/terra/addons/terrascript/parser/lang/Item.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Item.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Item.java index 10065bfc9..27947c291 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Item.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Item.java @@ -13,5 +13,13 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public interface Item { T apply(ImplementationArguments implementationArguments, Scope scope); + default double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + throw new UnsupportedOperationException("Cannot apply " + this + " as double"); + } + + default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + throw new UnsupportedOperationException("Cannot apply " + this + " as double"); + } + Position getPosition(); } From b2cc0d48aa59bb2d23c0d7feb21977d320e7579f Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 21:30:58 -0700 Subject: [PATCH 079/220] use local variable table for terrascript --- .../addons/terrascript/parser/Parser.java | 168 +++++++++++------- .../addons/terrascript/parser/lang/Block.java | 19 -- .../terrascript/parser/lang/Executable.java | 19 ++ .../addons/terrascript/parser/lang/Scope.java | 146 +++++++++++---- .../lang/keywords/looplike/ForKeyword.java | 9 +- .../lang/keywords/looplike/IfKeyword.java | 21 +-- .../variables/VariableAssignmentNode.java | 40 ----- .../variables/VariableDeclarationNode.java | 62 ------- .../variables/assign/BoolAssignmentNode.java | 25 +++ .../variables/assign/NumAssignmentNode.java | 26 +++ .../variables/assign/StrAssignmentNode.java | 21 +++ .../assign/VariableAssignmentNode.java | 32 ++++ .../reference/BoolVariableReferenceNode.java | 22 +++ .../reference/NumVariableReferenceNode.java | 22 +++ .../reference/StrVariableReferenceNode.java | 17 ++ .../VariableReferenceNode.java | 17 +- .../terrascript/script/StructureScript.java | 6 +- 17 files changed, 410 insertions(+), 262 deletions(-) create mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Executable.java delete mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableAssignmentNode.java delete mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableDeclarationNode.java create mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/BoolAssignmentNode.java create mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java create mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/StrAssignmentNode.java create mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java create mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/BoolVariableReferenceNode.java create mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/NumVariableReferenceNode.java create mode 100644 common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/StrVariableReferenceNode.java rename common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/{ => reference}/VariableReferenceNode.java (56%) diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java index 56aa24b87..97ed21410 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java @@ -15,9 +15,12 @@ import java.util.Map; import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.Executable; import com.dfsek.terra.addons.terrascript.parser.lang.Item; import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable.ReturnType; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder; import com.dfsek.terra.addons.terrascript.parser.lang.constants.BooleanConstant; import com.dfsek.terra.addons.terrascript.parser.lang.constants.ConstantExpression; import com.dfsek.terra.addons.terrascript.parser.lang.constants.NumericConstant; @@ -48,12 +51,17 @@ import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.Grea import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.LessThanOrEqualsStatement; import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.LessThanStatement; import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.NotEqualsStatement; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.VariableAssignmentNode; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.VariableDeclarationNode; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.VariableReferenceNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.assign.BoolAssignmentNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.assign.NumAssignmentNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.assign.StrAssignmentNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.assign.VariableAssignmentNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.reference.BoolVariableReferenceNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.reference.NumVariableReferenceNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.reference.StrVariableReferenceNode; import com.dfsek.terra.addons.terrascript.tokenizer.Position; import com.dfsek.terra.addons.terrascript.tokenizer.Token; import com.dfsek.terra.addons.terrascript.tokenizer.Tokenizer; +import com.dfsek.terra.api.util.generic.pair.Pair; @SuppressWarnings("unchecked") @@ -83,11 +91,12 @@ public class Parser { * * @throws ParseException If parsing fails. */ - public Block parse() { - return parseBlock(new Tokenizer(data), new HashMap<>(), false); + public Executable parse() { + ScopeBuilder scopeBuilder = new ScopeBuilder(); + return new Executable(parseBlock(new Tokenizer(data), false, scopeBuilder), scopeBuilder); } - private Keyword parseLoopLike(Tokenizer tokens, Map variableMap, boolean loop) throws ParseException { + private Keyword parseLoopLike(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) throws ParseException { Token identifier = tokens.consume(); ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP); @@ -95,43 +104,43 @@ public class Parser { ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); return switch(identifier.getType()) { - case FOR_LOOP -> parseForLoop(tokens, variableMap, identifier.getPosition()); - case IF_STATEMENT -> parseIfStatement(tokens, variableMap, identifier.getPosition(), loop); - case WHILE_LOOP -> parseWhileLoop(tokens, variableMap, identifier.getPosition()); + case FOR_LOOP -> parseForLoop(tokens, identifier.getPosition(), scopeBuilder); + case IF_STATEMENT -> parseIfStatement(tokens, identifier.getPosition(), loop, scopeBuilder); + case WHILE_LOOP -> parseWhileLoop(tokens, identifier.getPosition(), scopeBuilder); default -> throw new UnsupportedOperationException( "Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition()); }; } - private WhileKeyword parseWhileLoop(Tokenizer tokens, Map variableMap, Position start) { - Returnable first = parseExpression(tokens, true, variableMap); + private WhileKeyword parseWhileLoop(Tokenizer tokens, Position start, ScopeBuilder scopeBuilder) { + Returnable first = parseExpression(tokens, true, scopeBuilder); ParserUtil.checkReturnType(first, Returnable.ReturnType.BOOLEAN); ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); - return new WhileKeyword(parseStatementBlock(tokens, variableMap, true), (Returnable) first, start); // While loop + return new WhileKeyword(parseStatementBlock(tokens, true, scopeBuilder), (Returnable) first, start); // While loop } - private IfKeyword parseIfStatement(Tokenizer tokens, Map variableMap, Position start, boolean loop) { - Returnable condition = parseExpression(tokens, true, variableMap); + private IfKeyword parseIfStatement(Tokenizer tokens, Position start, boolean loop, ScopeBuilder scopeBuilder) { + Returnable condition = parseExpression(tokens, true, scopeBuilder); ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN); ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); Block elseBlock = null; - Block statement = parseStatementBlock(tokens, variableMap, loop); + Block statement = parseStatementBlock(tokens, loop, scopeBuilder); - List, Block>> elseIf = new ArrayList<>(); + List, Block>> elseIf = new ArrayList<>(); while(tokens.hasNext() && tokens.get().getType().equals(Token.Type.ELSE)) { tokens.consume(); // Consume else. if(tokens.get().getType().equals(Token.Type.IF_STATEMENT)) { tokens.consume(); // Consume if. - Returnable elseCondition = parseExpression(tokens, true, variableMap); + Returnable elseCondition = parseExpression(tokens, true, scopeBuilder); ParserUtil.checkReturnType(elseCondition, Returnable.ReturnType.BOOLEAN); - elseIf.add(new IfKeyword.Pair<>((Returnable) elseCondition, parseStatementBlock(tokens, variableMap, loop))); + elseIf.add(Pair.of((Returnable) elseCondition, parseStatementBlock(tokens, loop, scopeBuilder))); } else { - elseBlock = parseStatementBlock(tokens, variableMap, loop); + elseBlock = parseStatementBlock(tokens, loop, scopeBuilder); break; // Else must be last. } } @@ -139,51 +148,51 @@ public class Parser { return new IfKeyword(statement, (Returnable) condition, elseIf, elseBlock, start); // If statement } - private Block parseStatementBlock(Tokenizer tokens, Map variableMap, boolean loop) { + private Block parseStatementBlock(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) { if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) { ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN); - Block block = parseBlock(tokens, variableMap, loop); + Block block = parseBlock(tokens, loop, scopeBuilder); ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_END); return block; } else { Position position = tokens.get().getPosition(); - Block block = new Block(Collections.singletonList(parseItem(tokens, variableMap, loop)), position); + Block block = new Block(Collections.singletonList(parseItem(tokens, loop, scopeBuilder)), position); ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); return block; } } - private ForKeyword parseForLoop(Tokenizer tokens, Map old, Position start) { - Map variableMap = new HashMap<>(old); // New scope + private ForKeyword parseForLoop(Tokenizer tokens, Position start, ScopeBuilder scopeBuilder) { + scopeBuilder = scopeBuilder.sub(); // new scope Token f = tokens.get(); ParserUtil.checkType(f, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.IDENTIFIER); Item initializer; if(f.isVariableDeclaration()) { - VariableDeclarationNode forVar = parseVariableDeclaration(tokens, variableMap); + VariableAssignmentNode forVar = parseVariableDeclaration(tokens, scopeBuilder); Token name = tokens.get(); - if(functions.containsKey(name.getContent()) || variableMap.containsKey(name.getContent())) + if(functions.containsKey(name.getContent()) || scopeBuilder.contains(name.getContent())) throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition()); initializer = forVar; - } else initializer = parseExpression(tokens, true, variableMap); + } else initializer = parseExpression(tokens, true, scopeBuilder); ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); - Returnable conditional = parseExpression(tokens, true, variableMap); + Returnable conditional = parseExpression(tokens, true, scopeBuilder); ParserUtil.checkReturnType(conditional, Returnable.ReturnType.BOOLEAN); ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); Item incrementer; Token token = tokens.get(); - if(variableMap.containsKey(token.getContent())) { // Assume variable assignment - incrementer = parseAssignment(tokens, variableMap); - } else incrementer = parseFunction(tokens, true, variableMap); + if(scopeBuilder.contains(token.getContent())) { // Assume variable assignment + incrementer = parseAssignment(tokens, scopeBuilder); + } else incrementer = parseFunction(tokens, true, scopeBuilder); ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); - return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable) conditional, incrementer, + return new ForKeyword(parseStatementBlock(tokens, true, scopeBuilder), initializer, (Returnable) conditional, incrementer, start); } - private Returnable parseExpression(Tokenizer tokens, boolean full, Map variableMap) { + private Returnable parseExpression(Tokenizer tokens, boolean full, ScopeBuilder scopeBuilder) { boolean booleanInverted = false; // Check for boolean not operator boolean negate = false; if(tokens.get().getType().equals(Token.Type.BOOLEAN_NOT)) { @@ -202,13 +211,21 @@ public class Parser { if(id.isConstant()) { expression = parseConstantExpression(tokens); } else if(id.getType().equals(Token.Type.GROUP_BEGIN)) { // Parse grouped expression - expression = parseGroup(tokens, variableMap); + expression = parseGroup(tokens, scopeBuilder); } else { if(functions.containsKey(id.getContent())) - expression = parseFunction(tokens, false, variableMap); - else if(variableMap.containsKey(id.getContent())) { + expression = parseFunction(tokens, false, scopeBuilder); + else if(scopeBuilder.contains(id.getContent())) { ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER); - expression = new VariableReferenceNode(id.getContent(), id.getPosition(), variableMap.get(id.getContent())); + String varId = id.getContent(); + ReturnType varType = scopeBuilder.getType(varId); + expression = switch(varType) { + case NUMBER -> new NumVariableReferenceNode(id.getPosition(), varType, scopeBuilder.getIndex(varId)); + case STRING -> new StrVariableReferenceNode(id.getPosition(), varType, scopeBuilder.getIndex(varId)); + case BOOLEAN -> new BoolVariableReferenceNode(id.getPosition(), varType, scopeBuilder.getIndex(varId)); + default -> throw new ParseException("Illegal type for variable reference: " + varType, id.getPosition()); + }; + } else throw new ParseException("Unexpected token \" " + id.getContent() + "\"", id.getPosition()); } @@ -221,7 +238,7 @@ public class Parser { } if(full && tokens.get().isBinaryOperator()) { // Parse binary operations - return parseBinaryOperation(expression, tokens, variableMap); + return parseBinaryOperation(expression, tokens, scopeBuilder); } return expression; } @@ -243,25 +260,25 @@ public class Parser { } } - private Returnable parseGroup(Tokenizer tokens, Map variableMap) { + private Returnable parseGroup(Tokenizer tokens, ScopeBuilder scopeBuilder) { ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); - Returnable expression = parseExpression(tokens, true, variableMap); // Parse inside of group as a separate expression + Returnable expression = parseExpression(tokens, true, scopeBuilder); // Parse inside of group as a separate expression ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); return expression; } private BinaryOperation parseBinaryOperation(Returnable left, Tokenizer tokens, - Map variableMap) { + ScopeBuilder scopeBuilder) { Token binaryOperator = tokens.consume(); ParserUtil.checkBinaryOperator(binaryOperator); - Returnable right = parseExpression(tokens, false, variableMap); + Returnable right = parseExpression(tokens, false, scopeBuilder); Token other = tokens.get(); if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType())) { - return assemble(left, parseBinaryOperation(right, tokens, variableMap), binaryOperator); + return assemble(left, parseBinaryOperation(right, tokens, scopeBuilder), binaryOperator); } else if(other.isBinaryOperator()) { - return parseBinaryOperation(assemble(left, right, binaryOperator), tokens, variableMap); + return parseBinaryOperation(assemble(left, right, binaryOperator), tokens, scopeBuilder); } return assemble(left, right, binaryOperator); } @@ -306,7 +323,7 @@ public class Parser { } } - private VariableDeclarationNode parseVariableDeclaration(Tokenizer tokens, Map variableMap) { + private VariableAssignmentNode parseVariableDeclaration(Tokenizer tokens, ScopeBuilder scopeBuilder) { Token type = tokens.consume(); ParserUtil.checkType(type, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE); @@ -315,30 +332,34 @@ public class Parser { ParserUtil.checkVarType(type, returnType); // Check for type mismatch Token identifier = tokens.consume(); ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); - if(functions.containsKey(identifier.getContent()) || variableMap.containsKey(identifier.getContent())) + if(functions.containsKey(identifier.getContent()) || scopeBuilder.contains(identifier.getContent())) throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition()); ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT); - Returnable value = parseExpression(tokens, true, variableMap); + Returnable value = parseExpression(tokens, true, scopeBuilder); ParserUtil.checkReturnType(value, returnType); - - variableMap.put(identifier.getContent(), returnType); - - return new VariableDeclarationNode<>(tokens.get().getPosition(), identifier.getContent(), value, returnType); + + String id = identifier.getContent(); + + return switch(type.getType()) { + case NUMBER -> new NumAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.num(id)); + case STRING -> new StrAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.str(id)); + case BOOLEAN -> new BoolAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.bool(id)); + default -> throw new ParseException("Illegal type for variable assignment: " + type, value.getPosition()); + }; } - private Block parseBlock(Tokenizer tokens, Map superVars, boolean loop) { + private Block parseBlock(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) { List> parsedItems = new ArrayList<>(); - Map parsedVariables = new HashMap<>( - superVars); // New hashmap as to not mutate parent scope's declarations. + scopeBuilder = scopeBuilder.sub(); Token first = tokens.get(); while(tokens.hasNext()) { Token token = tokens.get(); if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end. - Item parsedItem = parseItem(tokens, parsedVariables, loop); + Item parsedItem = parseItem(tokens, loop, scopeBuilder); if(parsedItem != Function.NULL) { parsedItems.add(parsedItem); } @@ -347,7 +368,7 @@ public class Parser { return new Block(parsedItems, first.getPosition()); } - private Item parseItem(Tokenizer tokens, Map variableMap, boolean loop) { + private Item parseItem(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) { Token token = tokens.get(); if(loop) ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, @@ -357,14 +378,14 @@ public class Parser { Token.Type.FAIL); if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc) - return parseLoopLike(tokens, variableMap, loop); + return parseLoopLike(tokens, loop, scopeBuilder); } else if(token.isIdentifier()) { // Parse identifiers - if(variableMap.containsKey(token.getContent())) { // Assume variable assignment - return parseAssignment(tokens, variableMap); - } else return parseFunction(tokens, true, variableMap); + if(scopeBuilder.contains(token.getContent())) { // Assume variable assignment + return parseAssignment(tokens, scopeBuilder); + } else return parseFunction(tokens, true, scopeBuilder); } else if(token.isVariableDeclaration()) { - return parseVariableDeclaration(tokens, variableMap); + return parseVariableDeclaration(tokens, scopeBuilder); } else if(token.getType().equals(Token.Type.RETURN)) return new ReturnKeyword(tokens.consume().getPosition()); else if(token.getType().equals(Token.Type.BREAK)) return new BreakKeyword(tokens.consume().getPosition()); @@ -373,21 +394,30 @@ public class Parser { else throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition()); } - private VariableAssignmentNode parseAssignment(Tokenizer tokens, Map variableMap) { + private VariableAssignmentNode parseAssignment(Tokenizer tokens, ScopeBuilder scopeBuilder) { Token identifier = tokens.consume(); ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT); - Returnable value = parseExpression(tokens, true, variableMap); + Returnable value = parseExpression(tokens, true, scopeBuilder); - ParserUtil.checkReturnType(value, variableMap.get(identifier.getContent())); + String id = identifier.getContent(); - return new VariableAssignmentNode<>(value, identifier.getContent(), identifier.getPosition()); + ParserUtil.checkReturnType(value, scopeBuilder.getType(id)); + + ReturnType type = value.returnType(); + + return switch(type) { + case NUMBER -> new NumAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.getIndex(id)); + case STRING -> new StrAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.getIndex(id)); + case BOOLEAN -> new BoolAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.getIndex(id)); + default -> throw new ParseException("Illegal type for variable assignment: " + type, value.getPosition()); + }; } - private Function parseFunction(Tokenizer tokens, boolean fullStatement, Map variableMap) { + private Function parseFunction(Tokenizer tokens, boolean fullStatement, ScopeBuilder scopeBuilder) { Token identifier = tokens.consume(); ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier @@ -397,7 +427,7 @@ public class Parser { ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); // Second is body begin - List> args = getArgs(tokens, variableMap); // Extract arguments, consume the rest. + List> args = getArgs(tokens, scopeBuilder); // Extract arguments, consume the rest. ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); // Remove body end @@ -425,11 +455,11 @@ public class Parser { throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent()); } - private List> getArgs(Tokenizer tokens, Map variableMap) { + private List> getArgs(Tokenizer tokens, ScopeBuilder scopeBuilder) { List> args = new ArrayList<>(); while(!tokens.get().getType().equals(Token.Type.GROUP_END)) { - args.add(parseExpression(tokens, true, variableMap)); + args.add(parseExpression(tokens, true, scopeBuilder)); ParserUtil.checkType(tokens.get(), Token.Type.SEPARATOR, Token.Type.GROUP_END); if(tokens.get().getType().equals(Token.Type.SEPARATOR)) tokens.consume(); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java index 473d033ef..65a8dbf7e 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java @@ -21,23 +21,8 @@ public class Block implements Item> { this.position = position; } - public ReturnInfo apply(ImplementationArguments implementationArguments) { - return apply(implementationArguments, new Scope()); - } - @Override public ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { - Scope sub = scope.sub(); - for(Item item : items) { - Object result = item.apply(implementationArguments, sub); - if(result instanceof ReturnInfo level) { - if(!level.getLevel().equals(ReturnLevel.NONE)) return level; - } - } - return new ReturnInfo<>(ReturnLevel.NONE, null); - } - - public ReturnInfo applyNoNewScope(ImplementationArguments implementationArguments, Scope scope) { for(Item item : items) { Object result = item.apply(implementationArguments, scope); if(result instanceof ReturnInfo level) { @@ -52,10 +37,6 @@ public class Block implements Item> { return position; } - public List> getItems() { - return items; - } - public enum ReturnLevel { NONE(false), BREAK(false), diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Executable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Executable.java new file mode 100644 index 000000000..6f9c026a0 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Executable.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.addons.terrascript.parser.lang; + + +import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder; + + +public class Executable { + private final Block script; + private final ThreadLocal scope; + + public Executable(Block script, ScopeBuilder scopeBuilder) { + this.script = script; + this.scope = ThreadLocal.withInitial(scopeBuilder::build); + } + + public boolean execute(ImplementationArguments arguments) { + return script.apply(arguments, scope.get()).getLevel() != Block.ReturnLevel.FAIL; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java index a511e2db4..da597898c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java @@ -1,46 +1,124 @@ package com.dfsek.terra.addons.terrascript.parser.lang; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable.ReturnType; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.reference.VariableReferenceNode; +import com.dfsek.terra.api.util.generic.pair.Pair; + +import net.jafama.FastMath; + import java.util.HashMap; import java.util.Map; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable; - public class Scope { - private static final Scope NULL = new Scope() { - @Override - public Variable get(String id) { - throw new IllegalStateException("Cannot get variable from null scope: " + id); + private final double[] num; + private final boolean[] bool; + private final String[] str; + + private Scope(int numSize, int boolSize, int strSize) { + this.num = new double[numSize]; + this.bool = new boolean[boolSize]; + this.str = new String[strSize]; + } + + public double getNum(int index) { + return num[index]; + } + + public boolean getBool(int index) { + return bool[index]; + } + + public String getStr(int index) { + return str[index]; + } + + public void setNum(int index, double value) { + num[index] = value; + } + + public void setBool(int index, boolean value) { + bool[index] = value; + } + + public void setStr(int index, String value) { + str[index] = value; + } + + public static final class ScopeBuilder { + private int numSize, boolSize, strSize = 0; + private final Map> indices; + + private ScopeBuilder parent; + + public ScopeBuilder() { + this.indices = new HashMap<>(); } - @Override - public void put(String id, Variable variable) { - throw new IllegalStateException("Cannot set variable in null scope: " + id); + private ScopeBuilder(ScopeBuilder parent) { + this.parent = parent; + this.numSize = parent.numSize; + this.boolSize = parent.boolSize; + this.strSize = parent.strSize; + this.indices = new HashMap<>(parent.indices); + } + + public Scope build() { + return new Scope(numSize, boolSize, strSize); + } + + public ScopeBuilder sub() { + return new ScopeBuilder(this); + } + + private String check(String id) { + if(indices.containsKey(id)) { + throw new IllegalArgumentException("Variable with ID " + id + " already registered."); + } + return id; + } + public int num(String id) { + int num = numSize; + indices.put(check(id), Pair.of(num, ReturnType.NUMBER)); + numSize++; + if(parent != null) { + parent.numSize = FastMath.max(parent.numSize, numSize); + } + return num; + } + + public int str(String id) { + int str = strSize; + indices.put(check(id), Pair.of(str, ReturnType.STRING)); + strSize++; + if(parent != null) { + parent.strSize = FastMath.max(parent.strSize, strSize); + } + return str; + } + + public int bool(String id) { + int bool = boolSize; + indices.put(check(id), Pair.of(bool, ReturnType.BOOLEAN)); + boolSize++; + if(parent != null) { + parent.boolSize = FastMath.max(parent.boolSize, boolSize); + } + return bool; + } + + public int getIndex(String id) { + return indices.get(id).getLeft(); + } + + public ReturnType getType(String id) { + return indices.get(id).getRight(); + } + + + public boolean contains(String id) { + return indices.containsKey(id); } - }; - - private final Scope parent; - private final Map> variableMap = new HashMap<>(); - - public Scope(Scope parent) { - this.parent = parent; - } - - public Scope() { - this.parent = NULL; - } - - public Variable get(String id) { - Variable var = variableMap.get(id); - return var == null ? parent.get(id) : var; - } - - public void put(String id, Variable variable) { - variableMap.put(id, variable); - } - - - public Scope sub() { - return new Scope(this); } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java index eebd67183..49f874724 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java @@ -33,11 +33,10 @@ public class ForKeyword implements Keyword> { @Override public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { - Scope sub = scope.sub(); - for(initializer.apply(implementationArguments, sub); - statement.apply(implementationArguments, sub); - incrementer.apply(implementationArguments, sub)) { - Block.ReturnInfo level = conditional.applyNoNewScope(implementationArguments, sub); + for(initializer.apply(implementationArguments, scope); + statement.apply(implementationArguments, scope); + incrementer.apply(implementationArguments, scope)) { + Block.ReturnInfo level = conditional.apply(implementationArguments, scope); if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break; if(level.getLevel().isReturnFast()) return level; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java index c3737433e..7d36d114d 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java @@ -7,6 +7,8 @@ package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike; +import com.dfsek.terra.api.util.generic.pair.Pair; + import org.jetbrains.annotations.Nullable; import java.util.List; @@ -58,23 +60,4 @@ public class IfKeyword implements Keyword> { public ReturnType returnType() { return ReturnType.VOID; } - - - public static class Pair { - private final L left; - private final R right; - - public Pair(L left, R right) { - this.left = left; - this.right = right; - } - - public L getLeft() { - return left; - } - - public R getRight() { - return right; - } - } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableAssignmentNode.java deleted file mode 100644 index af833d570..000000000 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableAssignmentNode.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020-2021 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.terrascript.parser.lang.variables; - -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Item; -import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.tokenizer.Position; - - -public class VariableAssignmentNode implements Item { - private final Returnable value; - private final Position position; - private final String identifier; - - public VariableAssignmentNode(Returnable value, String identifier, Position position) { - this.value = value; - this.identifier = identifier; - this.position = position; - } - - @SuppressWarnings("unchecked") - @Override - public synchronized T apply(ImplementationArguments implementationArguments, Scope scope) { - T val = value.apply(implementationArguments, scope); - ((Variable) scope.get(identifier)).setValue(val); - return val; - } - - @Override - public Position getPosition() { - return position; - } -} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableDeclarationNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableDeclarationNode.java deleted file mode 100644 index ceae122a3..000000000 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableDeclarationNode.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2020-2021 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.terrascript.parser.lang.variables; - -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Item; -import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.tokenizer.Position; - - -public class VariableDeclarationNode implements Item { - private final Position position; - private final String identifier; - private final Returnable value; - private final Returnable.ReturnType type; - - public VariableDeclarationNode(Position position, String identifier, Returnable value, Returnable.ReturnType type) { - switch(type) { - case STRING: - case BOOLEAN: - case NUMBER: - break; - default: - throw new IllegalArgumentException("Invalid variable type: " + type); - } - this.position = position; - this.identifier = identifier; - this.value = value; - this.type = type; - } - - @Override - public T apply(ImplementationArguments implementationArguments, Scope scope) { - T result = value.apply(implementationArguments, scope); - scope.put(identifier, switch(type) { - case NUMBER -> new NumberVariable((Number) result, position); - case BOOLEAN -> new BooleanVariable((Boolean) result, position); - case STRING -> new StringVariable((String) result, position); - default -> throw new IllegalStateException("Unexpected value: " + type); - }); - return result; - } - - @Override - public Position getPosition() { - return position; - } - - public Returnable.ReturnType getType() { - return type; - } - - public String getIdentifier() { - return identifier; - } -} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/BoolAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/BoolAssignmentNode.java new file mode 100644 index 000000000..8f0f47ee9 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/BoolAssignmentNode.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.addons.terrascript.parser.lang.variables.assign; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class BoolAssignmentNode extends VariableAssignmentNode { + public BoolAssignmentNode(Returnable value, Position position, int index) { + super(value, position, index); + } + + @Override + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); + } + + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + boolean val = value.applyBoolean(implementationArguments, scope); + scope.setBool(index, val); + return val; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java new file mode 100644 index 000000000..55ebb8aa8 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.addons.terrascript.parser.lang.variables.assign; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class NumAssignmentNode extends VariableAssignmentNode { + public NumAssignmentNode(Returnable value, Position position, int index) { + super(value, position, index); + } + + @Override + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return applyDouble(implementationArguments, scope); + } + + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + double val = value.applyDouble(implementationArguments, scope); + scope.setNum(index, val); + return val; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/StrAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/StrAssignmentNode.java new file mode 100644 index 000000000..ee811dbd8 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/StrAssignmentNode.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.addons.terrascript.parser.lang.variables.assign; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class StrAssignmentNode extends VariableAssignmentNode { + public StrAssignmentNode(Returnable value, Position position, int index) { + super(value, position, index); + } + + @Override + public String apply(ImplementationArguments implementationArguments, Scope scope) { + String val = value.apply(implementationArguments, scope); + scope.setStr(index, val); + return val; + } + +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java new file mode 100644 index 000000000..edfb15ef7 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 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.terrascript.parser.lang.variables.assign; + +import com.dfsek.terra.addons.terrascript.parser.lang.Item; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public abstract class VariableAssignmentNode implements Item { + protected final Returnable value; + private final Position position; + protected final int index; + + + + public VariableAssignmentNode(Returnable value, Position position, int index) { + this.value = value; + this.index = index; + this.position = position; + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/BoolVariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/BoolVariableReferenceNode.java new file mode 100644 index 000000000..c2295f2e2 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/BoolVariableReferenceNode.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.addons.terrascript.parser.lang.variables.reference; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class BoolVariableReferenceNode extends VariableReferenceNode { + public BoolVariableReferenceNode(Position position, ReturnType type, int index) { + super(position, type, index); + } + + @Override + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return scope.getBool(index); + } + + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return scope.getBool(index); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/NumVariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/NumVariableReferenceNode.java new file mode 100644 index 000000000..a266dcca9 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/NumVariableReferenceNode.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.addons.terrascript.parser.lang.variables.reference; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class NumVariableReferenceNode extends VariableReferenceNode { + public NumVariableReferenceNode(Position position, ReturnType type, int index) { + super(position, type, index); + } + + @Override + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return scope.getNum(index); + } + + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return scope.getNum(index); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/StrVariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/StrVariableReferenceNode.java new file mode 100644 index 000000000..d67acc557 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/StrVariableReferenceNode.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.terrascript.parser.lang.variables.reference; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class StrVariableReferenceNode extends VariableReferenceNode { + public StrVariableReferenceNode(Position position, ReturnType type, int index) { + super(position, type, index); + } + + @Override + public String apply(ImplementationArguments implementationArguments, Scope scope) { + return scope.getStr(index); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java similarity index 56% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableReferenceNode.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java index 3d017b364..a115f8b94 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableReferenceNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java @@ -5,23 +5,21 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.variables; +package com.dfsek.terra.addons.terrascript.parser.lang.variables.reference; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; -public class VariableReferenceNode implements Returnable { - private final String identifier; +public abstract class VariableReferenceNode implements Returnable { private final Position position; private final ReturnType type; + protected final int index; - public VariableReferenceNode(String identifier, Position position, ReturnType type) { - this.identifier = identifier; + public VariableReferenceNode(Position position, ReturnType type, int index) { this.position = position; this.type = type; + this.index = index; } @Override @@ -29,11 +27,6 @@ public class VariableReferenceNode implements Returnable { return type; } - @Override - public synchronized Object apply(ImplementationArguments implementationArguments, Scope scope) { - return scope.get(identifier).getValue(); - } - @Override public Position getPosition() { return position; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java index 1bba19e9e..87636fd9e 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java @@ -7,6 +7,8 @@ package com.dfsek.terra.addons.terrascript.script; +import com.dfsek.terra.addons.terrascript.parser.lang.Executable; + import net.jafama.FastMath; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; @@ -51,7 +53,7 @@ import com.dfsek.terra.api.world.WritableWorld; public class StructureScript implements Structure, Keyed { private static final Logger LOGGER = LoggerFactory.getLogger(StructureScript.class); - private final Block block; + private final Executable block; private final RegistryKey id; private final String profile; @@ -146,7 +148,7 @@ public class StructureScript implements Structure, Keyed { private boolean applyBlock(TerraImplementationArguments arguments) { try { - return block.apply(arguments).getLevel() != Block.ReturnLevel.FAIL; + return block.execute(arguments); } catch(RuntimeException e) { LOGGER.error("Failed to generate structure at {}", arguments.getOrigin(), e); return false; From 14e035bf2e1fdbe82e664406c798135f41109ec3 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 21:51:05 -0700 Subject: [PATCH 080/220] use applyDouble and applyBoolean in applicable ops --- .../addons/terrascript/parser/Parser.java | 4 +-- .../lang/constants/BooleanConstant.java | 9 ++++++ .../lang/constants/NumericConstant.java | 9 ++++++ .../parser/lang/functions/Function.java | 10 +++++++ .../lang/operations/BinaryOperation.java | 11 ++----- .../lang/operations/BooleanAndOperation.java | 17 +++++++---- .../lang/operations/BooleanNotOperation.java | 11 +++++-- .../lang/operations/BooleanOrOperation.java | 10 +++++-- .../operations/ConcatenationOperation.java | 12 ++++---- .../lang/operations/DivisionOperation.java | 17 +++++++---- .../lang/operations/ModuloOperation.java | 10 +++++-- .../operations/MultiplicationOperation.java | 10 +++++-- .../lang/operations/NegationOperation.java | 17 +++++++---- .../operations/NumberAdditionOperation.java | 10 +++++-- .../lang/operations/SubtractionOperation.java | 10 +++++-- .../lang/operations/UnaryOperation.java | 9 +----- .../statements/EqualsStatement.java | 30 ++++++++++++------- .../GreaterOrEqualsThanStatement.java | 18 +++++++---- .../statements/GreaterThanStatement.java | 11 +++++-- .../statements/LessThanOrEqualsStatement.java | 12 ++++++-- .../statements/LessThanStatement.java | 12 ++++++-- .../statements/NotEqualsStatement.java | 23 +++++++++----- 22 files changed, 198 insertions(+), 84 deletions(-) diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java index 97ed21410..fae348713 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java @@ -341,11 +341,11 @@ public class Parser { String id = identifier.getContent(); - return switch(type.getType()) { + return switch(value.returnType()) { case NUMBER -> new NumAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.num(id)); case STRING -> new StrAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.str(id)); case BOOLEAN -> new BoolAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.bool(id)); - default -> throw new ParseException("Illegal type for variable assignment: " + type, value.getPosition()); + default -> throw new ParseException("Illegal type for variable declaration: " + type, value.getPosition()); }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java index b61e05364..25cf9cdc2 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java @@ -7,12 +7,21 @@ package com.dfsek.terra.addons.terrascript.parser.lang.constants; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; public class BooleanConstant extends ConstantExpression { + private final boolean constant; public BooleanConstant(Boolean constant, Position position) { super(constant, position); + this.constant = constant; + } + + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return constant; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java index 911f601f2..78164fdc8 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java @@ -7,13 +7,22 @@ package com.dfsek.terra.addons.terrascript.parser.lang.constants; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; public class NumericConstant extends ConstantExpression { + private final double constant; public NumericConstant(Number constant, Position position) { super(constant, position); + this.constant = constant.doubleValue(); + } + + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return constant; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java index da27138b6..ec21b1923 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java @@ -14,6 +14,16 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public interface Function extends Returnable { + @Override + default double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return (Double) apply(implementationArguments, scope); + } + + @Override + default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return (Boolean) apply(implementationArguments, scope); + } + Function NULL = new Function<>() { @Override public ReturnType returnType() { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java index 11a4d74e8..f336b3055 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java @@ -16,8 +16,8 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public abstract class BinaryOperation implements Returnable { - private final Returnable left; - private final Returnable right; + protected final Returnable left; + protected final Returnable right; private final Position start; public BinaryOperation(Returnable left, Returnable right, Position start) { @@ -26,13 +26,6 @@ public abstract class BinaryOperation implements Returnable { this.start = start; } - public abstract O apply(Supplier left, Supplier right); - - @Override - public O apply(ImplementationArguments implementationArguments, Scope scope) { - return apply(() -> left.apply(implementationArguments, scope), () -> right.apply(implementationArguments, scope)); - } - @Override public Position getPosition() { return start; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java index 6018b21d0..b10407a79 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -18,13 +20,18 @@ public class BooleanAndOperation extends BinaryOperation { super(left, right, start); } - @Override - public Boolean apply(Supplier left, Supplier right) { - return left.get() && right.get(); - } - @Override public ReturnType returnType() { return ReturnType.BOOLEAN; } + + @Override + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); + } + + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return left.applyBoolean(implementationArguments, scope) && right.applyBoolean(implementationArguments, scope); + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java index e1b4d2fed..a65e00184 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java @@ -7,7 +7,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -17,8 +19,13 @@ public class BooleanNotOperation extends UnaryOperation { } @Override - public Boolean apply(Boolean input) { - return !input; + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); + } + + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return !input.applyBoolean(implementationArguments, scope); } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java index 90b11cf86..177297972 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,10 +21,14 @@ public class BooleanOrOperation extends BinaryOperation { } @Override - public Boolean apply(Supplier left, Supplier right) { - return left.get() || right.get(); + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); } + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return left.applyBoolean(implementationArguments, scope) || right.applyBoolean(implementationArguments, scope); + } @Override public ReturnType returnType() { return ReturnType.BOOLEAN; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java index 79fd3d103..5edae5f3d 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -18,13 +20,13 @@ public class ConcatenationOperation extends BinaryOperation { super(left, right, position); } - @Override - public String apply(Supplier left, Supplier right) { - return left.get().toString() + right.get().toString(); - } - @Override public Returnable.ReturnType returnType() { return Returnable.ReturnType.STRING; } + + @Override + public Object apply(ImplementationArguments implementationArguments, Scope scope) { + return left.apply(implementationArguments, scope).toString() + right.apply(implementationArguments, scope).toString(); + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java index b6d76c451..e2153559e 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -18,13 +20,18 @@ public class DivisionOperation extends BinaryOperation { super(left, right, position); } - @Override - public Number apply(Supplier left, Supplier right) { - return left.get().doubleValue() / right.get().doubleValue(); - } - @Override public Returnable.ReturnType returnType() { return Returnable.ReturnType.NUMBER; } + + @Override + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return applyDouble(implementationArguments, scope); + } + + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) / right.applyDouble(implementationArguments, scope); + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java index a22439b6d..41cc48662 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,10 +21,14 @@ public class ModuloOperation extends BinaryOperation { } @Override - public Number apply(Supplier left, Supplier right) { - return left.get().doubleValue() % right.get().doubleValue(); + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return applyDouble(implementationArguments, scope); } + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) % right.applyDouble(implementationArguments, scope); + } @Override public ReturnType returnType() { return ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java index 232d8ee52..aeaf9bd90 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,10 +21,14 @@ public class MultiplicationOperation extends BinaryOperation { } @Override - public Number apply(Supplier left, Supplier right) { - return left.get().doubleValue() * right.get().doubleValue(); + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return applyDouble(implementationArguments, scope); } + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) * right.applyDouble(implementationArguments, scope); + } @Override public ReturnType returnType() { return ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java index 2f9ee5161..32d8f39b6 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java @@ -7,7 +7,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -16,13 +18,18 @@ public class NegationOperation extends UnaryOperation { super(input, position); } - @Override - public Number apply(Number input) { - return -input.doubleValue(); - } - @Override public ReturnType returnType() { return ReturnType.NUMBER; } + + @Override + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return applyDouble(implementationArguments, scope); + } + + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return -input.applyDouble(implementationArguments, scope); + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java index 7baa56df3..bb216047a 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,10 +21,14 @@ public class NumberAdditionOperation extends BinaryOperation { } @Override - public Number apply(Supplier left, Supplier right) { - return left.get().doubleValue() + right.get().doubleValue(); + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return applyDouble(implementationArguments, scope); } + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) + right.applyDouble(implementationArguments, scope); + } @Override public ReturnType returnType() { return ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java index 70e6709b7..e31b2b5de 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,10 +21,14 @@ public class SubtractionOperation extends BinaryOperation { } @Override - public Number apply(Supplier left, Supplier right) { - return left.get().doubleValue() - right.get().doubleValue(); + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return applyDouble(implementationArguments, scope); } + @Override + public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) - right.applyDouble(implementationArguments, scope); + } @Override public ReturnType returnType() { return ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java index b8e9c1770..5071e95ea 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java @@ -14,7 +14,7 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public abstract class UnaryOperation implements Returnable { - private final Returnable input; + protected final Returnable input; private final Position position; public UnaryOperation(Returnable input, Position position) { @@ -22,13 +22,6 @@ public abstract class UnaryOperation implements Returnable { this.position = position; } - public abstract T apply(T input); - - @Override - public T apply(ImplementationArguments implementationArguments, Scope scope) { - return apply(input.apply(implementationArguments, scope)); - } - @Override public Position getPosition() { return position; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java index 9c9b73e0f..82a045742 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java @@ -7,6 +7,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; + import net.jafama.FastMath; import java.util.function.Supplier; @@ -24,20 +27,25 @@ public class EqualsStatement extends BinaryOperation { super(left, right, position); } - @Override - public Boolean apply(Supplier left, Supplier right) { - Object leftUnwrapped = left.get(); - Object rightUnwrapped = right.get(); - if(leftUnwrapped instanceof Number l && rightUnwrapped instanceof Number r) { - return FastMath.abs(l.doubleValue() - r.doubleValue()) <= EPSILON; - } - - return leftUnwrapped.equals(rightUnwrapped); - } - @Override public Returnable.ReturnType returnType() { return Returnable.ReturnType.BOOLEAN; } + + @Override + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); + } + + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + Object leftValue = left.apply(implementationArguments, scope); + Object rightValue = right.apply(implementationArguments, scope); + if(leftValue instanceof Number l && rightValue instanceof Number r) { + return FastMath.abs(l.doubleValue() - r.doubleValue()) <= EPSILON; + } + + return leftValue.equals(rightValue); + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java index 2c795b1c9..10c60a305 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,14 +21,18 @@ public class GreaterOrEqualsThanStatement extends BinaryOperation left, Supplier right) { - return left.get().doubleValue() >= right.get().doubleValue(); - } - - @Override public Returnable.ReturnType returnType() { return Returnable.ReturnType.BOOLEAN; } + + @Override + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); + } + + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) >= right.applyDouble(implementationArguments, scope); + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java index a6c7d8e52..0bb3e5500 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,11 +21,16 @@ public class GreaterThanStatement extends BinaryOperation { super(left, right, position); } + @Override - public Boolean apply(Supplier left, Supplier right) { - return left.get().doubleValue() > right.get().doubleValue(); + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); } + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) > right.applyDouble(implementationArguments, scope); + } @Override public Returnable.ReturnType returnType() { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java index d798a6590..ef2aa8346 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,12 +21,16 @@ public class LessThanOrEqualsStatement extends BinaryOperation super(left, right, position); } + @Override - public Boolean apply(Supplier left, Supplier right) { - return left.get().doubleValue() <= right.get().doubleValue(); + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); } - + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) <= right.applyDouble(implementationArguments, scope); + } @Override public Returnable.ReturnType returnType() { return Returnable.ReturnType.BOOLEAN; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java index 04bca475c..f06e395b1 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; import java.util.function.Supplier; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.tokenizer.Position; @@ -19,12 +21,16 @@ public class LessThanStatement extends BinaryOperation { super(left, right, position); } + @Override - public Boolean apply(Supplier left, Supplier right) { - return left.get().doubleValue() < right.get().doubleValue(); + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); } - + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + return left.applyDouble(implementationArguments, scope) < right.applyDouble(implementationArguments, scope); + } @Override public Returnable.ReturnType returnType() { return Returnable.ReturnType.BOOLEAN; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java index 20fb34fe3..aaecd56bc 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java @@ -7,6 +7,9 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; + import net.jafama.FastMath; import java.util.function.Supplier; @@ -24,16 +27,20 @@ public class NotEqualsStatement extends BinaryOperation { } @Override - public Boolean apply(Supplier left, Supplier right) { - Object leftUnwrapped = left.get(); - Object rightUnwrapped = right.get(); - if(leftUnwrapped instanceof Number l && rightUnwrapped instanceof Number r) { - return FastMath.abs(l.doubleValue() - r.doubleValue()) > EPSILON; - } - - return !leftUnwrapped.equals(rightUnwrapped); + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + return applyBoolean(implementationArguments, scope); } + @Override + public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { + Object leftValue = left.apply(implementationArguments, scope); + Object rightValue = right.apply(implementationArguments, scope); + if(leftValue instanceof Number l && rightValue instanceof Number r) { + return FastMath.abs(l.doubleValue() - r.doubleValue()) > EPSILON; + } + + return !leftValue.equals(rightValue); + } @Override public Returnable.ReturnType returnType() { From 3122962dc16f6bafa163dd4ab51c8d0f636e01fc Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 21:54:19 -0700 Subject: [PATCH 081/220] fix Function#applyDouble --- .../addons/terrascript/parser/lang/functions/Function.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java index ec21b1923..86780eb55 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java @@ -16,7 +16,7 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public interface Function extends Returnable { @Override default double applyDouble(ImplementationArguments implementationArguments, Scope scope) { - return (Double) apply(implementationArguments, scope); + return ((Number) apply(implementationArguments, scope)).doubleValue(); } @Override From 8c9afc45929ee3818b8c8e17828e5021fcb8e3e3 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 22:01:54 -0700 Subject: [PATCH 082/220] recursively update variable table size --- .../addons/terrascript/parser/lang/Scope.java | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java index da597898c..946abbfea 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java @@ -82,9 +82,7 @@ public class Scope { int num = numSize; indices.put(check(id), Pair.of(num, ReturnType.NUMBER)); numSize++; - if(parent != null) { - parent.numSize = FastMath.max(parent.numSize, numSize); - } + updateNumSize(numSize); return num; } @@ -92,9 +90,7 @@ public class Scope { int str = strSize; indices.put(check(id), Pair.of(str, ReturnType.STRING)); strSize++; - if(parent != null) { - parent.strSize = FastMath.max(parent.strSize, strSize); - } + updateStrSize(strSize); return str; } @@ -102,12 +98,31 @@ public class Scope { int bool = boolSize; indices.put(check(id), Pair.of(bool, ReturnType.BOOLEAN)); boolSize++; - if(parent != null) { - parent.boolSize = FastMath.max(parent.boolSize, boolSize); - } + updateBoolSize(boolSize); return bool; } + private void updateBoolSize(int size) { + this.boolSize = FastMath.max(boolSize, size); + if(parent != null) { + parent.updateBoolSize(size); + } + } + + private void updateNumSize(int size) { + this.numSize = FastMath.max(numSize, size); + if(parent != null) { + parent.updateNumSize(size); + } + } + + private void updateStrSize(int size) { + this.strSize = FastMath.max(strSize, size); + if(parent != null) { + parent.updateStrSize(size); + } + } + public int getIndex(String id) { return indices.get(id).getLeft(); } From e5fa4fd1f1080430177d4fa77b37d3f290836bda Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 22:18:31 -0700 Subject: [PATCH 083/220] remove decimal on whole numbers (keeps parity with old scripts) --- .../lang/operations/ConcatenationOperation.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java index 5edae5f3d..17e233b84 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; @@ -27,6 +25,17 @@ public class ConcatenationOperation extends BinaryOperation { @Override public Object apply(ImplementationArguments implementationArguments, Scope scope) { - return left.apply(implementationArguments, scope).toString() + right.apply(implementationArguments, scope).toString(); + return toString(left.apply(implementationArguments, scope)) + toString(right.apply(implementationArguments, scope)); + } + + private static String toString(Object object) { + String s = object.toString(); + if(object instanceof Double) { + int l = s.length(); + if(s.charAt(l - 2) == '.' && s.charAt(l - 1) == '0') { + s = s.substring(0, s.length() - 2); + } + } + return s; } } From 7d92d273cfc7a13e28b45ec4c0d6b4e16f4e4d1d Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 22:42:10 -0700 Subject: [PATCH 084/220] dont use range iterator in MatchPattern --- .../terra/addons/feature/locator/patterns/MatchPattern.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java index 3ef1c3fbb..e92950a53 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java @@ -25,7 +25,7 @@ public class MatchPattern implements Pattern { @Override public boolean matches(int y, Column column) { - for(int i : range) { + for(int i = range.getMin(); i < range.getMax(); i++) { if(!matches.test(column.getBlock(y + i))) return false; } return true; From 11cf4c3a953631fd4a22488d077f5f72aa9c5f6d Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 23:23:00 -0700 Subject: [PATCH 085/220] add NetherFossilOptimization --- .../mixin/fix/NetherFossilOptimization.java | 42 ++++++++ .../src/main/resources/terra.mixins.json | 101 +++++++++--------- 2 files changed, 93 insertions(+), 50 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/NetherFossilOptimization.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/NetherFossilOptimization.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/NetherFossilOptimization.java new file mode 100644 index 000000000..770b042dd --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/NetherFossilOptimization.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.fabric.mixin.fix; + +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.structure.NetherFossilGenerator; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.random.ChunkRandom; +import net.minecraft.world.EmptyBlockView; +import net.minecraft.world.gen.HeightContext; +import net.minecraft.world.gen.chunk.VerticalBlockSample; +import net.minecraft.world.gen.heightprovider.HeightProvider; +import net.minecraft.world.gen.structure.NetherFossilStructure; +import net.minecraft.world.gen.structure.Structure; +import net.minecraft.world.gen.structure.Structure.Context; +import net.minecraft.world.gen.structure.Structure.StructurePosition; +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.CallbackInfoReturnable; + +import java.util.Optional; + + +/** + * Disable fossil generation in Terra worlds, as they are very expensive due to consistently triggering cache misses. + * + * Currently, on Fabric, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in nether. + */ +@Mixin(NetherFossilStructure.class) +public class NetherFossilOptimization { + @Inject(method = "getStructurePosition", at = @At("HEAD"), cancellable = true) + public void injectFossilPositions(Context context, CallbackInfoReturnable> cir) { + if(context.chunkGenerator() instanceof FabricChunkGeneratorWrapper) { + cir.setReturnValue(Optional.empty()); + } + } +} diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 85baf5377..ad1d97bb9 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -1,52 +1,53 @@ { - "required": true, - "minVersion": "0.8", - "package": "com.dfsek.terra.fabric.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - "access.MobSpawnerLogicAccessor", - "access.StateAccessor", - "access.StructureAccessorAccessor", - "cache.ChunkRegionMixin", - "cache.ProtoChunkMixin", - "compat.GenerationSettingsFloraFeaturesMixin", - "implementations.BiomeMixin", - "implementations.HandleImplementationMixin", - "implementations.block.BlockMixin", - "implementations.block.entity.BlockEntityMixin", - "implementations.block.entity.LootableContainerBlockEntityMixin", - "implementations.block.entity.MobSpawnerBlockEntityMixin", - "implementations.block.entity.SignBlockEntityMixin", - "implementations.block.state.BlockStateMixin", - "implementations.block.state.PropertyMixin", - "implementations.chunk.ChunkRegionMixin", - "implementations.chunk.WorldChunkMixin", - "implementations.chunk.data.ProtoChunkMixin", - "implementations.entity.EntityMixin", - "implementations.entity.EntityTypeMixin", - "implementations.entity.PlayerEntityMixin", - "implementations.entity.ServerCommandSourceMixin", - "implementations.inventory.LockableContainerBlockEntityMixin", - "implementations.inventory.item.ItemMixin", - "implementations.inventory.item.ItemStackMixin", - "implementations.inventory.meta.EnchantmentMixin", - "implementations.inventory.meta.ItemStackDamageableMixin", - "implementations.inventory.meta.ItemStackMetaMixin", - "implementations.world.ChunkRegionMixin", - "implementations.world.ServerWorldMixin", - "lifecycle.DataPackContentsMixin", - "lifecycle.MinecraftServerMixin", - "lifecycle.NoiseConfigMixin", - "lifecycle.RegistryMixin" - ], - "client": [ - "lifecycle.client.MinecraftClientMixin" - ], - "server": [ - "lifecycle.server.ServerMainMixin" - ], - "injectors": { - "defaultRequire": 1 - }, - "refmap": "terra-refmap.json" + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.fabric.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "access.MobSpawnerLogicAccessor", + "access.StateAccessor", + "access.StructureAccessorAccessor", + "cache.ChunkRegionMixin", + "cache.ProtoChunkMixin", + "compat.GenerationSettingsFloraFeaturesMixin", + "fix.NetherFossilOptimization", + "implementations.BiomeMixin", + "implementations.HandleImplementationMixin", + "implementations.block.BlockMixin", + "implementations.block.entity.BlockEntityMixin", + "implementations.block.entity.LootableContainerBlockEntityMixin", + "implementations.block.entity.MobSpawnerBlockEntityMixin", + "implementations.block.entity.SignBlockEntityMixin", + "implementations.block.state.BlockStateMixin", + "implementations.block.state.PropertyMixin", + "implementations.chunk.ChunkRegionMixin", + "implementations.chunk.WorldChunkMixin", + "implementations.chunk.data.ProtoChunkMixin", + "implementations.entity.EntityMixin", + "implementations.entity.EntityTypeMixin", + "implementations.entity.PlayerEntityMixin", + "implementations.entity.ServerCommandSourceMixin", + "implementations.inventory.LockableContainerBlockEntityMixin", + "implementations.inventory.item.ItemMixin", + "implementations.inventory.item.ItemStackMixin", + "implementations.inventory.meta.EnchantmentMixin", + "implementations.inventory.meta.ItemStackDamageableMixin", + "implementations.inventory.meta.ItemStackMetaMixin", + "implementations.world.ChunkRegionMixin", + "implementations.world.ServerWorldMixin", + "lifecycle.DataPackContentsMixin", + "lifecycle.MinecraftServerMixin", + "lifecycle.NoiseConfigMixin", + "lifecycle.RegistryMixin" + ], + "client": [ + "lifecycle.client.MinecraftClientMixin" + ], + "server": [ + "lifecycle.server.ServerMainMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "terra-refmap.json" } \ No newline at end of file From 589e46477ee2991873bf3f22f76d4656ee99851f Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 14 Jun 2022 23:56:02 -0700 Subject: [PATCH 086/220] fix low res column --- common/api/src/main/java/com/dfsek/terra/api/util/Column.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index 6537e3d9b..4610bbf8d 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -44,7 +44,7 @@ public interface Column { while(true) { y += resolution; - if(y >= max) { + if(y > max) { break; } T current = get(y); @@ -55,7 +55,7 @@ public interface Column { runningObj = current; } } - consumer.accept(runningMin, ++y, runningObj); + consumer.accept(runningMin, getMaxY(), runningObj); } default List asList() { From df4636428c98831d93eaf49a42ab43267607cbf2 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 00:09:10 -0700 Subject: [PATCH 087/220] remove unneeded fabric permissions API dependency --- buildSrc/src/main/kotlin/Versions.kt | 1 - platforms/fabric/build.gradle.kts | 13 +++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 059705b8c..b52cca994 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -22,7 +22,6 @@ object Versions { const val fabricAPI = "0.55.1+1.19" const val minecraft = "1.19" const val yarn = "$minecraft+build.1" - const val permissionsAPI = "0.1-SNAPSHOT" const val mixin = "0.11.2+mixin.0.8.5" const val loom = "0.12-SNAPSHOT" } diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index ea24493c6..7cc2685d2 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -11,6 +11,10 @@ plugins { dependencies { shadedApi(project(":common:implementation:base")) + "compileOnly"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") + "annotationProcessor"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") + "annotationProcessor"("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") + minecraft("com.mojang:minecraft:${Versions.Fabric.minecraft}") mappings("net.fabricmc:yarn:${Versions.Fabric.yarn}:v2") @@ -22,14 +26,7 @@ dependencies { include(module) } - include(modImplementation("me.lucko", "fabric-permissions-api", Versions.Fabric.permissionsAPI)) - include("me.lucko", "fabric-permissions-api", Versions.Fabric.permissionsAPI) - - "compileOnly"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - "annotationProcessor"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - "annotationProcessor"("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") - - include(modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud)) + modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) } From 23a35f809713706b0b2c0f19ee56912f847d9812 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 18:59:12 -0700 Subject: [PATCH 088/220] implement blockstate cache in Column --- .../feature/locator/locators/PatternLocator.java | 7 ++++++- .../addons/feature/locator/patterns/MatchPattern.java | 8 ++++++-- .../terra/api/world/chunk/generation/util/Column.java | 11 ++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java index f3f525af9..575b2328e 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java @@ -13,6 +13,8 @@ import com.dfsek.terra.api.structure.feature.Locator; import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.world.chunk.generation.util.Column; +import net.jafama.FastMath; + public class PatternLocator implements Locator { private final Pattern pattern; @@ -25,6 +27,9 @@ public class PatternLocator implements Locator { @Override public BinaryColumn getSuitableCoordinates(Column column) { - return new BinaryColumn(search, y -> pattern.matches(y, column)); + int min = FastMath.max(column.getMinY(), search.getMin()); + int max = FastMath.min(column.getMaxY(), search.getMax()); + if(min >= max) return BinaryColumn.getNull(); + return new BinaryColumn(min, max, y -> pattern.matches(y, column)); } } diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java index e92950a53..d68ece62e 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java @@ -13,6 +13,8 @@ import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.world.chunk.generation.util.Column; +import net.jafama.FastMath; + public class MatchPattern implements Pattern { private final Range range; @@ -25,8 +27,10 @@ public class MatchPattern implements Pattern { @Override public boolean matches(int y, Column column) { - for(int i = range.getMin(); i < range.getMax(); i++) { - if(!matches.test(column.getBlock(y + i))) return false; + int min = FastMath.max(column.getMinY(), range.getMin() + y); + int max = FastMath.min(column.getMaxY(), range.getMax() + y); + for(int i = min; i < max; i++) { + if(!matches.test(column.getBlock(i))) return false; } return true; } diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index a3ee0c92f..962e77084 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -27,6 +27,8 @@ public class Column { private final int max; private final T world; + private final BlockState[] cache; + public Column(int x, int z, T world) { this(x, z, world, world.getMinHeight(), world.getMaxHeight()); } @@ -37,6 +39,7 @@ public class Column { this.world = world; this.max = max; this.min = min; + this.cache = new BlockState[world.getMaxHeight() - world.getMinHeight()]; } public int getX() { @@ -48,7 +51,13 @@ public class Column { } public BlockState getBlock(int y) { - return world.getBlockState(x, y, z); + int i = y - world.getMinHeight(); + BlockState state = cache[i]; + if(state == null) { + state = world.getBlockState(x, y, z); + cache[i] = state; + } + return state; } public T getWorld() { From d73872a1c6e07578787630fbe80e5b1814a2db8c Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 19:55:06 -0700 Subject: [PATCH 089/220] properly access 3d biomes in LazilyEvaluatedInterpolator --- .../LazilyEvaluatedInterpolator.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java index 34c20ad97..acec30493 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java @@ -3,16 +3,13 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; import net.jafama.FastMath; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; -import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import static com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.Interpolator.lerp; public class LazilyEvaluatedInterpolator { - private final Double[][][] samples; - - private final NoiseSampler[][] samplers; + private final Double[] samples; // private final int chunkX; private final int chunkZ; @@ -25,12 +22,14 @@ public class LazilyEvaluatedInterpolator { private final long seed; private final int min; + private final int zMul, yMul; public LazilyEvaluatedInterpolator(BiomeProvider biomeProvider, int cx, int cz, int max, int min, int horizontalRes, int verticalRes, long seed) { int hSamples = FastMath.ceilToInt(16.0 / horizontalRes); int vSamples = FastMath.ceilToInt((double) (max - min) / verticalRes); - samples = new Double[hSamples + 1][vSamples + 1][hSamples + 1]; - samplers = new NoiseSampler[hSamples + 1][hSamples + 1]; + this.zMul = (hSamples + 1); + this.yMul = zMul * zMul; + samples = new Double[yMul * (vSamples + 1)]; this.chunkX = cx << 4; this.chunkZ = cz << 4; this.horizontalRes = horizontalRes; @@ -41,19 +40,19 @@ public class LazilyEvaluatedInterpolator { } private double sample(int x, int y, int z, int ox, int oy, int oz) { - Double sample = samples[x][y][z]; + int index = x + (z * zMul) + (y * yMul); + Double sample = samples[index]; if(sample == null) { int xi = ox + chunkX; int zi = oz + chunkZ; - NoiseSampler sampler = samplers[x][z]; - if(sampler == null) { - sampler = biomeProvider.getBiome(xi, y, zi, seed).getContext().get(BiomeNoiseProperties.class).carving(); - samplers[x][z] = sampler; - } - - sample = sampler.noise(seed, xi, oy, zi); - samples[x][y][z] = sample; + sample = biomeProvider + .getBiome(xi, y, zi, seed) + .getContext() + .get(BiomeNoiseProperties.class) + .carving() + .noise(seed, xi, oy, zi); + samples[index] = sample; } return sample; } From 2001b4c6f825ebb4ef54998a1c9647c88810cc7e Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 20:03:32 -0700 Subject: [PATCH 090/220] remove TerraScript PerformanceTest --- .../test/java/structure/PerformanceTest.java | 90 ------------------- .../src/test/resources/performance.tesf | 25 ------ 2 files changed, 115 deletions(-) delete mode 100644 common/addons/structure-terrascript-loader/src/test/java/structure/PerformanceTest.java delete mode 100644 common/addons/structure-terrascript-loader/src/test/resources/performance.tesf diff --git a/common/addons/structure-terrascript-loader/src/test/java/structure/PerformanceTest.java b/common/addons/structure-terrascript-loader/src/test/java/structure/PerformanceTest.java deleted file mode 100644 index cc2ed4372..000000000 --- a/common/addons/structure-terrascript-loader/src/test/java/structure/PerformanceTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package structure; - -import net.jafama.FastMath; -import org.apache.commons.io.IOUtils; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.List; - -import com.dfsek.terra.addons.terrascript.parser.Parser; -import com.dfsek.terra.addons.terrascript.parser.lang.Block; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; -import com.dfsek.terra.addons.terrascript.parser.lang.Returnable.ReturnType; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.UnaryNumberFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.UnaryStringFunctionBuilder; -import com.dfsek.terra.addons.terrascript.tokenizer.Position; - - -public class PerformanceTest { - public static void main(String... args) throws IOException { - Parser parser = new Parser( - IOUtils.toString(PerformanceTest.class.getResourceAsStream("/performance.tesf"), Charset.defaultCharset())); - - parser.registerFunction("assert", new FunctionBuilder() { - @Override - public AssertFunction build(List> argumentList, Position position) { - return new AssertFunction(position, (Returnable) argumentList.get(0)); - } - - @Override - public int argNumber() { - return 1; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - return switch(position) { - case 0 -> ReturnType.BOOLEAN; - default -> null; - }; - } - - }).registerFunction("print", - new UnaryStringFunctionBuilder(System.out::println)) - .registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue()))); - - Block block = parser.parse(); - - for(int i = 0; i < 20; i++) { - long s = System.nanoTime(); - - block.apply(null, new Scope()); - - long e = System.nanoTime(); - long d = e - s; - - System.out.println("Took " + ((double) d) / 1000000 + "ms"); - } - } - - public static final class AssertFunction implements Function { - private final Position position; - private final Returnable arg; - - public AssertFunction(Position position, Returnable arg) { - this.position = position; - this.arg = arg; - } - - @Override - public Void apply(ImplementationArguments implementationArguments, Scope scope) { - if(!arg.apply(implementationArguments, scope)) throw new IllegalStateException(); - return null; - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } - } -} diff --git a/common/addons/structure-terrascript-loader/src/test/resources/performance.tesf b/common/addons/structure-terrascript-loader/src/test/resources/performance.tesf deleted file mode 100644 index 45527678c..000000000 --- a/common/addons/structure-terrascript-loader/src/test/resources/performance.tesf +++ /dev/null @@ -1,25 +0,0 @@ -num epsilon = 0.001; - -for(num n = 1; n < 1000000; n = n + 1) { - - num x = n; - - num root = 0; - - while(true) { - root = 0.5 * (x + (n / x)); - - num diff = root - x; - if(diff < 0) diff = -diff; - - if(diff < epsilon) break; - - x = root; - } - - num diff = root - sqrt(n); - - if(diff < 0) diff = -diff; - - assert(diff <= epsilon); -} \ No newline at end of file From 2c4485757582a92fc117b81fff3972c9b8d76e8e Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 20:23:05 -0700 Subject: [PATCH 091/220] fix palette fuzz noise config --- .../NoiseChunkGenerator3DAddon.java | 1 + .../generation/NoiseChunkGenerator3D.java | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java index fc44046c1..c0a4fb934 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java @@ -35,6 +35,7 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { platform.getEventManager() .getHandler(FunctionalEventHandler.class) .register(addon, ConfigPackPreLoadEvent.class) + .priority(1000) .then(event -> { NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate()); 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 b5fea266c..6151b5ce7 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 @@ -57,16 +57,15 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { this.samplerCache = new SamplerProvider(platform, elevationBlend); } - private Biome getBiome(BiomeProvider biomeProvider, int x, int y, int z, long seed) { + private Biome getBiome(double noiseX, double noiseZ, BiomeProvider biomeProvider, int x, int y, int z, long seed) { if(paletteBlendAmplitude == 1) { return biomeProvider.getBiome(x, y, z, seed); } - long ms = seed; - int mx = FastMath.floorDiv(x + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed++, x, y, z)), paletteRes) * paletteRes; - int my = FastMath.floorDiv(y + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed++, x, y, z)), paletteRes) * paletteRes; - int mz = FastMath.floorDiv(z + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed, x, y, z)), paletteRes) * paletteRes; + int mx = FastMath.floorDiv(x + (int) (paletteBlendAmplitude * noiseX), paletteRes) * paletteRes; + int my = FastMath.floorDiv(y + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed + 2, x, y, z)), paletteRes) * paletteRes; + int mz = FastMath.floorDiv(z + (int) (paletteBlendAmplitude * noiseZ), paletteRes) * paletteRes; - return biomeProvider.getBiome(mx, my, mz, ms); + return biomeProvider.getBiome(mx, my, mz, seed); } @Override @@ -92,6 +91,8 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { seed); for(int x = 0; x < 16; x++) { for(int z = 0; z < 16; z++) { + double paletteNoiseX = paletteBlendSampler.noise(seed, x, z); + double paletteNoiseZ = paletteBlendSampler.noise(seed + 1, x, z); int paletteLevel = 0; int cx = xOrig + x; @@ -99,7 +100,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { BlockState data; for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { - Biome biome = getBiome(biomeProvider, cx, y, cz, seed); + Biome biome = getBiome(paletteNoiseX, paletteNoiseZ, biomeProvider, cx, y, cz, seed); PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); From 7b23aa796f2bff50e6827f6ec06ac98a77ceb400 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 21:43:02 -0700 Subject: [PATCH 092/220] fix OOBE in NoiseChunkGenerator3D when using low res palette --- .../generation/NoiseChunkGenerator3D.java | 15 +++++++++------ .../java/com/dfsek/terra/api/util/MathUtil.java | 4 ++++ 2 files changed, 13 insertions(+), 6 deletions(-) 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 6151b5ce7..8cabf55ef 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 @@ -17,6 +17,7 @@ import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.util.MathUtil; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; @@ -57,15 +58,15 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { this.samplerCache = new SamplerProvider(platform, elevationBlend); } - private Biome getBiome(double noiseX, double noiseZ, BiomeProvider biomeProvider, int x, int y, int z, long seed) { + private Biome getBiome(int min, int max, double noiseX, double noiseZ, BiomeProvider biomeProvider, int x, int y, int z, long seed) { if(paletteBlendAmplitude == 1) { return biomeProvider.getBiome(x, y, z, seed); } - int mx = FastMath.floorDiv(x + (int) (paletteBlendAmplitude * noiseX), paletteRes) * paletteRes; - int my = FastMath.floorDiv(y + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed + 2, x, y, z)), paletteRes) * paletteRes; - int mz = FastMath.floorDiv(z + (int) (paletteBlendAmplitude * noiseZ), paletteRes) * paletteRes; + int mx = ((x + (int) (paletteBlendAmplitude * noiseX)) / paletteRes) * paletteRes; + int my = ((y + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed + 2, x, y, z))) / paletteRes) * paletteRes; + int mz = ((z + (int) (paletteBlendAmplitude * noiseZ)) / paletteRes) * paletteRes; - return biomeProvider.getBiome(mx, my, mz, seed); + return biomeProvider.getBiome(mx, MathUtil.clamp(min, my, max), mz, seed); } @Override @@ -76,6 +77,8 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { platform.getProfiler().push("chunk_base_3d"); int xOrig = (chunkX << 4); int zOrig = (chunkZ << 4); + int min = world.getMinHeight(); + int max = world.getMaxHeight() - 1; Sampler3D sampler = samplerCache.getChunk(chunkX, chunkZ, world, biomeProvider); @@ -100,7 +103,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { BlockState data; for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { - Biome biome = getBiome(paletteNoiseX, paletteNoiseZ, biomeProvider, cx, y, cz, seed); + Biome biome = getBiome(min, max, paletteNoiseX, paletteNoiseZ, biomeProvider, cx, y, cz, seed); PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java index e24de0e03..3c95df139 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java @@ -87,6 +87,10 @@ public final class MathUtil { return FastMath.min(FastMath.max(in, -1), 1); } + public static int clamp(int min, int i, int max) { + return FastMath.max(FastMath.min(i, max), min); + } + /** * Compute the value in a normally distributed data set that has probability p. * From b7c381b0f9c7ddf8d27b2c606ff51205f19592a5 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 21:46:20 -0700 Subject: [PATCH 093/220] dont use column in ChunkInterpolator --- .../math/interpolation/ChunkInterpolator.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index cf3ea06b7..1b4e10879 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -8,16 +8,10 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; -import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.util.mutable.MutableInteger; -import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import net.jafama.FastMath; -import java.util.HashMap; -import java.util.Map; - /** * Class to abstract away the Interpolators needed to generate a chunk.
@@ -41,7 +35,7 @@ public class ChunkInterpolator { public ChunkInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int min, int max) { this.min = min; this.max = max; - + int xOrigin = chunkX << 4; int zOrigin = chunkZ << 4; @@ -59,12 +53,11 @@ public class ChunkInterpolator { for(int z = 0; z < 5; z++) { int scaledZ = z << 2; int absoluteZ = zOrigin + scaledZ; - Column column = provider.getColumn(absoluteX, absoluteZ, seed, min, max); for(int y = 0; y < size; y++) { int scaledY = (y << 2) + min; - BiomeNoiseProperties generationSettings = column.get(scaledY) - .getContext() - .get(BiomeNoiseProperties.class); + BiomeNoiseProperties generationSettings = provider.getBiome(absoluteX, scaledY, absoluteZ, seed) + .getContext() + .get(BiomeNoiseProperties.class); int step = generationSettings.blendStep(); int blend = generationSettings.blendDistance(); From 72ad5b65df71d6579289170cff52e613c54c9e74 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 21:49:24 -0700 Subject: [PATCH 094/220] remove unneeded floorToInt in BiomePipelineProvider --- .../addons/biome/pipeline/BiomePipelineProvider.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java index 56208d669..30526fbaf 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -86,9 +86,9 @@ public class BiomePipelineProvider implements BiomeProvider { z += mutator.noise(seed + 2, x, z) * noiseAmp; - x = FastMath.floorToInt(FastMath.floorDiv(x, resolution)); + x = FastMath.floorDiv(x, resolution); - z = FastMath.floorToInt(FastMath.floorDiv(z, resolution)); + z = FastMath.floorDiv(z, resolution); int fdX = FastMath.floorDiv(x, pipeline.getSize()); int fdZ = FastMath.floorDiv(z, pipeline.getSize()); @@ -111,6 +111,11 @@ public class BiomePipelineProvider implements BiomeProvider { return new BiomePipelineColumn(this, min, max, x, z, seed); } + @Override + public int resolution() { + return resolution; + } + private record SeededVector(int x, int z, long seed) { @Override public boolean equals(Object obj) { From c31925f3833406d130304776e6901a5ec9c1ce3d Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 21:49:41 -0700 Subject: [PATCH 095/220] add default #resolution method in BiomeProvider --- .../dfsek/terra/api/world/biome/generation/BiomeProvider.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 43b70f4a3..ed83669ae 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -103,4 +103,8 @@ public interface BiomeProvider { default ChunkLocalCachingBiomeProvider caching(WorldProperties worldProperties, int chunkX, int chunkZ) { return new ChunkLocalCachingBiomeProvider(this, worldProperties, chunkX, chunkZ); } + + default int resolution() { + return 1; + } } From cfeeb432ea34ad19ac3dd25664308ef312d3c6a1 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 21:54:47 -0700 Subject: [PATCH 096/220] fully implement resolution in BiomeExtrusionProvider --- .../extrusion/BiomeExtrusionProvider.java | 28 +++++++++---------- .../biome/pipeline/BiomePipelineProvider.java | 5 ++-- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index e5865e7f9..9d219eda8 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -1,16 +1,14 @@ package com.dfsek.terra.addons.biome.extrusion; -import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; -import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.api.world.info.WorldProperties; - import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + public class BiomeExtrusionProvider implements BiomeProvider { private final BiomeProvider delegate; @@ -28,6 +26,14 @@ public class BiomeExtrusionProvider implements BiomeProvider { @Override public Biome getBiome(int x, int y, int z, long seed) { + x /= resolution; + y /= resolution; + z /= resolution; + + x *= resolution; + y *= resolution; + z *= resolution; + Biome delegated = delegate.getBiome(x, y, z, seed); for(Extrusion extrusion : extrusions) { @@ -42,19 +48,13 @@ public class BiomeExtrusionProvider implements BiomeProvider { return delegate.getBaseBiome(x, z, seed); } - public Biome getBiome(int x, int y, int z, long seed, Biome biome) { - for(Extrusion extrusion : extrusions) { - biome = extrusion.extrude(biome, x, y, z, seed); - } - return biome; - } - @Override public Iterable getBiomes() { return biomes; } - public int getResolution() { + @Override + public int resolution() { return resolution; } diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java index 30526fbaf..395e8d24e 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -86,9 +86,8 @@ public class BiomePipelineProvider implements BiomeProvider { z += mutator.noise(seed + 2, x, z) * noiseAmp; - x = FastMath.floorDiv(x, resolution); - - z = FastMath.floorDiv(z, resolution); + x /= resolution; + z /= resolution; int fdX = FastMath.floorDiv(x, pipeline.getSize()); int fdZ = FastMath.floorDiv(z, pipeline.getSize()); From 9081f3a0046afa059e7c7db72e5217fdee7f187c Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 23:08:12 -0700 Subject: [PATCH 097/220] use resolution in CachingBiomeProviders --- .../generation/CachingBiomeProvider.java | 5 +++ .../ChunkLocalCachingBiomeProvider.java | 42 ++++++++++++++----- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index ea40118a3..cb2781509 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -60,4 +60,9 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { public Iterable getBiomes() { return delegate.getBiomes(); } + + @Override + public int resolution() { + return delegate.resolution(); + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java index dead2dfaa..4e365b453 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java @@ -1,14 +1,13 @@ package com.dfsek.terra.api.world.biome.generation; -import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.util.generic.Construct; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.api.world.info.WorldProperties; - import net.jafama.FastMath; import java.util.Optional; +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.info.WorldProperties; + /** * A biome provider implementation that lazily evaluates biomes, and caches them. @@ -20,17 +19,25 @@ import java.util.Optional; */ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { private final BiomeChunk[] chunks = new BiomeChunk[9]; - private final Column[] columnCache = new Column[256]; // x + z * 16 + private final Column[] columnCache; // x + z * 16 private final int chunkX; private final int chunkZ; private final int height; + private final int zMul; + private final int yMul; + private final int resolution; + protected ChunkLocalCachingBiomeProvider(BiomeProvider delegate, WorldProperties worldProperties, int chunkX, int chunkZ) { super(delegate, worldProperties.getMinHeight(), worldProperties.getMaxHeight()); this.height = maxY - minY; this.chunkX = chunkX; this.chunkZ = chunkZ; + this.resolution = delegate.resolution(); + this.zMul = 16 / resolution; + this.yMul = zMul * zMul; + this.columnCache = new Column[yMul]; } @Override @@ -43,16 +50,21 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { int localChunkX = FastMath.floorDiv(x, 16) - this.chunkX + 1; int localChunkZ = FastMath.floorDiv(z, 16) - this.chunkZ + 1; + if(localChunkX >= 0 && localChunkZ >= 0 && localChunkX <= 2 && localChunkZ <= 2) { int chunkIndex = localChunkX + localChunkZ * 3; BiomeChunk chunk = chunks[chunkIndex]; if(chunk == null) { - chunk = new BiomeChunk(height); + chunk = new BiomeChunk(height / resolution, yMul); chunks[chunkIndex] = chunk; } + + int scaledX = FastMath.floorDiv(x & 15, resolution); + int scaledY = FastMath.floorDiv(y - minY, resolution); + int scaledZ = FastMath.floorDiv(z & 15, resolution); - int biomeIndex = (x & 15) + 16 * (z & 15) + 256 * (y - minY); + int biomeIndex = scaledX + zMul * scaledZ + yMul * scaledY; Biome biome = chunk.cache[biomeIndex]; if(biome == null) { biome = delegate.getBiome(x, y, z, seed); @@ -71,8 +83,11 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { @Override public Column getColumn(int x, int z, long seed, int min, int max) { + int scaledX = (x & 15) / resolution; + int scaledZ = (z & 15) / resolution; + if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) { - int index = (x & 15) + (16 * (z & 15)); + int index = scaledX + (zMul * scaledZ); Column column = columnCache[index]; if(column == null) { column = new BiomeColumn(this, min, max, x, z, seed); @@ -88,11 +103,16 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { return delegate.getBiomes(); } + @Override + public int resolution() { + return resolution; + } + private static class BiomeChunk { final Biome[] cache; // x + z * 16 + y * 256 - private BiomeChunk(int height) { - this.cache = new Biome[16 * 16 * height]; + private BiomeChunk(int height, int widthSq) { + this.cache = new Biome[widthSq * height]; } } } From c83924a7a421170362c00ee3e0b319aa82722360 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 15 Jun 2022 23:38:29 -0700 Subject: [PATCH 098/220] remove unneeded resolution application --- .../addons/biome/extrusion/BiomeExtrusionProvider.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index 9d219eda8..85a4cc72c 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -26,14 +26,6 @@ public class BiomeExtrusionProvider implements BiomeProvider { @Override public Biome getBiome(int x, int y, int z, long seed) { - x /= resolution; - y /= resolution; - z /= resolution; - - x *= resolution; - y *= resolution; - z *= resolution; - Biome delegated = delegate.getBiome(x, y, z, seed); for(Extrusion extrusion : extrusions) { From 80583e15969b6e1215cb83800371f855f09e5d21 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 01:53:02 -0700 Subject: [PATCH 099/220] add alternative methods for interacting with Context --- .../NoiseChunkGenerator3DAddon.java | 13 +++++++--- .../generation/NoiseChunkGenerator3D.java | 20 +++++++++------ .../math/interpolation/ChunkInterpolator.java | 7 +++--- .../interpolation/ElevationInterpolator.java | 6 +++-- .../LazilyEvaluatedInterpolator.java | 9 +++++-- .../generation/math/samplers/Sampler3D.java | 9 ++++--- .../math/samplers/SamplerProvider.java | 9 +++++-- .../dfsek/terra/api/properties/Context.java | 25 +++++++++++++++++++ .../terra/api/properties/PropertyKey.java | 15 +++++++++++ 9 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 common/api/src/main/java/com/dfsek/terra/api/properties/PropertyKey.java diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java index c0a4fb934..45d2a6520 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java @@ -9,7 +9,9 @@ package com.dfsek.terra.addons.chunkgenerator; import com.dfsek.terra.addons.chunkgenerator.config.NoiseChunkGeneratorPackConfigTemplate; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseConfigTemplate; +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.addons.chunkgenerator.config.palette.BiomePaletteTemplate; +import com.dfsek.terra.addons.chunkgenerator.config.palette.PaletteInfo; import com.dfsek.terra.addons.chunkgenerator.config.palette.SlantLayer; import com.dfsek.terra.addons.chunkgenerator.generation.NoiseChunkGenerator3D; import com.dfsek.terra.addons.manifest.api.AddonInitializer; @@ -19,6 +21,8 @@ import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; 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.properties.Context; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider; @@ -32,6 +36,8 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { @Override public void initialize() { + PropertyKey paletteInfoPropertyKey = Context.create(PaletteInfo.class); + PropertyKey noisePropertiesPropertyKey = Context.create(BiomeNoiseProperties.class); platform.getEventManager() .getHandler(FunctionalEventHandler.class) .register(addon, ConfigPackPreLoadEvent.class) @@ -43,7 +49,8 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { .getOrCreateRegistry(ChunkGeneratorProvider.class) .register(addon.key("NOISE_3D"), pack -> new NoiseChunkGenerator3D(platform, config.getElevationBlend(), config.getHorizontalRes(), - config.getVerticalRes(), config.getPaletteRes(), config.getPaletteBlendSampler(), config.getPaletteBlendAmplitude())); + config.getVerticalRes(), config.getPaletteRes(), config.getPaletteBlendSampler(), config.getPaletteBlendAmplitude(), + noisePropertiesPropertyKey, paletteInfoPropertyKey)); event.getPack() .applyLoader(SlantLayer.class, SlantLayer::new); }) @@ -54,8 +61,8 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { .register(addon, ConfigurationLoadEvent.class) .then(event -> { if(event.is(Biome.class)) { - event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomePaletteTemplate(platform)).get()); - event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomeNoiseConfigTemplate()).get()); + event.getLoadedObject(Biome.class).getContext().put(paletteInfoPropertyKey, event.load(new BiomePaletteTemplate(platform)).get()); + event.getLoadedObject(Biome.class).getContext().put(noisePropertiesPropertyKey, event.load(new BiomeNoiseConfigTemplate()).get()); } }) .failThrough(); 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 8cabf55ef..7d6ae9841 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 @@ -8,6 +8,7 @@ package com.dfsek.terra.addons.chunkgenerator.generation; +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.addons.chunkgenerator.config.palette.PaletteInfo; import com.dfsek.terra.addons.chunkgenerator.generation.math.PaletteUtil; import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.LazilyEvaluatedInterpolator; @@ -16,7 +17,7 @@ import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerPro import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.util.MathUtil; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; @@ -44,10 +45,13 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { private final NoiseSampler paletteBlendSampler; private final double paletteBlendAmplitude; + private final PropertyKey paletteInfoPropertyKey; + private final PropertyKey noisePropertiesKey; public NoiseChunkGenerator3D(Platform platform, int elevationBlend, int carverHorizontalResolution, int carverVerticalResolution, int paletteRes, NoiseSampler paletteBlendSampler, - double paletteBlendAmplitude) { + double paletteBlendAmplitude, PropertyKey noisePropertiesKey, + PropertyKey paletteInfoPropertyKey) { this.platform = platform; this.air = platform.getWorldHandle().air(); this.carverHorizontalResolution = carverHorizontalResolution; @@ -55,7 +59,9 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { this.paletteRes = paletteRes; this.paletteBlendSampler = paletteBlendSampler; this.paletteBlendAmplitude = paletteBlendAmplitude; - this.samplerCache = new SamplerProvider(platform, elevationBlend); + this.paletteInfoPropertyKey = paletteInfoPropertyKey; + this.noisePropertiesKey = noisePropertiesKey; + this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey); } private Biome getBiome(int min, int max, double noiseX, double noiseZ, BiomeProvider biomeProvider, int x, int y, int z, long seed) { @@ -88,7 +94,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { chunkX, chunkZ, world.getMaxHeight(), - world.getMinHeight(), + noisePropertiesKey, world.getMinHeight(), carverHorizontalResolution, carverVerticalResolution, seed); @@ -105,7 +111,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { Biome biome = getBiome(min, max, paletteNoiseX, paletteNoiseZ, biomeProvider, cx, y, cz, seed); - PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); + PaletteInfo paletteInfo = biome.getContext().get(paletteInfoPropertyKey); int sea = paletteInfo.seaLevel(); Palette seaPalette = paletteInfo.ocean(); @@ -139,7 +145,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { Biome biome = biomeProvider.getBiome(x, y, z, world.getSeed()); Sampler3D sampler = samplerCache.get(x, z, world, biomeProvider); - PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); + PaletteInfo paletteInfo = biome.getContext().get(paletteInfoPropertyKey); int fdX = FastMath.floorMod(x, 16); int fdZ = FastMath.floorMod(z, 16); @@ -160,7 +166,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { @Override public Palette getPalette(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider) { - return biomeProvider.getBiome(x, y, z, world.getSeed()).getContext().get(PaletteInfo.class).paletteHolder().getPalette(y); + return biomeProvider.getBiome(x, y, z, world.getSeed()).getContext().get(paletteInfoPropertyKey).paletteHolder().getPalette(y); } public SamplerProvider samplerProvider() { diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 1b4e10879..c674253c0 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -8,6 +8,7 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import net.jafama.FastMath; @@ -32,7 +33,7 @@ public class ChunkInterpolator { * @param min * @param max */ - public ChunkInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int min, int max) { + public ChunkInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int min, int max, PropertyKey noisePropertiesKey) { this.min = min; this.max = max; @@ -57,7 +58,7 @@ public class ChunkInterpolator { int scaledY = (y << 2) + min; BiomeNoiseProperties generationSettings = provider.getBiome(absoluteX, scaledY, absoluteZ, seed) .getContext() - .get(BiomeNoiseProperties.class); + .get(noisePropertiesKey); int step = generationSettings.blendStep(); int blend = generationSettings.blendDistance(); @@ -70,7 +71,7 @@ public class ChunkInterpolator { BiomeNoiseProperties properties = provider .getBiome(absoluteX + (xi * step), scaledY, absoluteZ + (zi * step), seed) .getContext() - .get(BiomeNoiseProperties.class); + .get(noisePropertiesKey); double sample = properties.noiseHolder().getNoise(properties.base(), absoluteX, scaledY, absoluteZ, seed); runningNoise += sample * properties.blendWeight(); runningDiv += properties.blendWeight(); diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java index 352ea7d1c..d4664673b 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java @@ -8,13 +8,15 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; public class ElevationInterpolator { private final double[][] values = new double[18][18]; - public ElevationInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int smooth) { + public ElevationInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int smooth, + PropertyKey noisePropertiesKey) { int xOrigin = chunkX << 4; int zOrigin = chunkZ << 4; @@ -30,7 +32,7 @@ public class ElevationInterpolator { .getBaseBiome(bx, bz, seed) .orElseGet(() -> provider.getBiome(bx, 0, bz, seed)) // kind of a hack .getContext() - .get(BiomeNoiseProperties.class); + .get(noisePropertiesKey); } } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java index acec30493..be72fb42f 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java @@ -1,5 +1,7 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; +import com.dfsek.terra.api.properties.PropertyKey; + import net.jafama.FastMath; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; @@ -18,13 +20,16 @@ public class LazilyEvaluatedInterpolator { private final int verticalRes; private final BiomeProvider biomeProvider; + private final PropertyKey noisePropertiesKey; private final long seed; private final int min; private final int zMul, yMul; - public LazilyEvaluatedInterpolator(BiomeProvider biomeProvider, int cx, int cz, int max, int min, int horizontalRes, int verticalRes, + public LazilyEvaluatedInterpolator(BiomeProvider biomeProvider, int cx, int cz, int max, + PropertyKey noisePropertiesKey, int min, int horizontalRes, int verticalRes, long seed) { + this.noisePropertiesKey = noisePropertiesKey; int hSamples = FastMath.ceilToInt(16.0 / horizontalRes); int vSamples = FastMath.ceilToInt((double) (max - min) / verticalRes); this.zMul = (hSamples + 1); @@ -49,7 +54,7 @@ public class LazilyEvaluatedInterpolator { sample = biomeProvider .getBiome(xi, y, zi, seed) .getContext() - .get(BiomeNoiseProperties.class) + .get(noisePropertiesKey) .carving() .noise(seed, xi, oy, zi); samples[index] = sample; diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java index ea98b0af6..1bca2d4a5 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java @@ -7,6 +7,9 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers; +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.properties.PropertyKey; + import net.jafama.FastMath; import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.ChunkInterpolator; @@ -18,10 +21,10 @@ public class Sampler3D { private final ChunkInterpolator interpolator; private final ElevationInterpolator elevationInterpolator; - public Sampler3D(int x, int z, long seed, int minHeight, int maxHeight, BiomeProvider provider, int elevationSmooth) { + public Sampler3D(int x, int z, long seed, int minHeight, int maxHeight, BiomeProvider provider, int elevationSmooth, PropertyKey noisePropertiesKey) { this.interpolator = new ChunkInterpolator(seed, x, z, provider, - minHeight, maxHeight); - this.elevationInterpolator = new ElevationInterpolator(seed, x, z, provider, elevationSmooth); + minHeight, maxHeight, noisePropertiesKey); + this.elevationInterpolator = new ElevationInterpolator(seed, x, z, provider, elevationSmooth, noisePropertiesKey); } public double sample(double x, double y, double z) { diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java index 30fcb016a..7a8ca167e 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java @@ -17,6 +17,9 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers; +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.properties.PropertyKey; + import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import net.jafama.FastMath; @@ -31,10 +34,12 @@ import com.dfsek.terra.api.world.info.WorldProperties; public class SamplerProvider { private final Cache cache; private final int elevationSmooth; + private final PropertyKey noisePropertiesKey; - public SamplerProvider(Platform platform, int elevationSmooth) { + public SamplerProvider(Platform platform, int elevationSmooth, PropertyKey noisePropertiesKey) { this.elevationSmooth = elevationSmooth; cache = CacheBuilder.newBuilder().maximumSize(platform.getTerraConfig().getSamplerCache()).build(); + this.noisePropertiesKey = noisePropertiesKey; } public Sampler3D get(int x, int z, WorldProperties world, BiomeProvider provider) { @@ -48,7 +53,7 @@ public class SamplerProvider { try { return cache.get(context, () -> new Sampler3D(context.cx, context.cz, context.seed, context.minHeight, context.maxHeight, provider, - elevationSmooth)); + elevationSmooth, noisePropertiesKey)); } catch(ExecutionException e) { throw new RuntimeException(e); } diff --git a/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java b/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java index 3b7f1fa40..b5a1f408f 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java +++ b/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java @@ -9,10 +9,15 @@ package com.dfsek.terra.api.properties; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; public class Context { private final Map, Properties> map = new HashMap<>(); + private final AtomicReference list = new AtomicReference<>(new Properties[size.get()]); + private static final AtomicInteger size = new AtomicInteger(0); + private static final Map, PropertyKey> properties = new HashMap<>(); @SuppressWarnings("unchecked") public T get(Class clazz) { @@ -28,6 +33,26 @@ public class Context { return this; } + @SuppressWarnings("unchecked") + public static PropertyKey create(Class clazz) { + return (PropertyKey) properties.computeIfAbsent(clazz, c -> new PropertyKey<>(size.getAndIncrement(), clazz)); + } + + public Context put(PropertyKey key, T properties) { + list.updateAndGet(p -> { + if(p.length == size.get()) return p; + Properties[] p2 = new Properties[size.get()]; + System.arraycopy(p, 0, p2, 0, p.length); + return p2; + })[key.key] = properties; + return this; + } + + @SuppressWarnings("unchecked") + public T get(PropertyKey key) { + return (T) list.get()[key.key]; + } + public boolean has(Class test) { return map.containsKey(test); } diff --git a/common/api/src/main/java/com/dfsek/terra/api/properties/PropertyKey.java b/common/api/src/main/java/com/dfsek/terra/api/properties/PropertyKey.java new file mode 100644 index 000000000..9c2daefe2 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/properties/PropertyKey.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.api.properties; + +public class PropertyKey { + protected final int key; + private final Class clazz; + + protected PropertyKey(int key, Class clazz) { + this.key = key; + this.clazz = clazz; + } + + public Class getTypeClass() { + return clazz; + } +} From 099d5f60c83099f9098baa250630dd89f1d70002 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 01:56:44 -0700 Subject: [PATCH 100/220] use propertykey for features --- .../generation/feature/FeatureGenerationAddon.java | 5 ++++- .../generation/feature/FeatureGenerationStage.java | 7 +++++-- .../generation/feature/config/FeatureStageTemplate.java | 9 +++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) 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 c3db72aac..74eed4f98 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 @@ -28,6 +28,8 @@ import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; 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.properties.Context; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.structure.feature.Feature; import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.world.biome.Biome; @@ -49,12 +51,13 @@ public class FeatureGenerationAddon implements AddonInitializer { @SuppressWarnings("unchecked") @Override public void initialize() { + PropertyKey biomeFeaturesKey = Context.create(BiomeFeatures.class); platform.getEventManager() .getHandler(FunctionalEventHandler.class) .register(addon, ConfigPackPreLoadEvent.class) .then(event -> event.getPack() .getOrCreateRegistry(STAGE_TYPE_KEY) - .register(addon.key("FEATURE"), () -> new FeatureStageTemplate(platform))) + .register(addon.key("FEATURE"), () -> new FeatureStageTemplate(platform, biomeFeaturesKey))) .failThrough(); platform.getEventManager() 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 0c250b35c..0a7a0c9b4 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 @@ -9,6 +9,7 @@ package com.dfsek.terra.addons.generation.feature; import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures; import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.registry.key.StringIdentifiable; import com.dfsek.terra.api.util.Rotation; import com.dfsek.terra.api.util.vector.Vector3Int; @@ -29,12 +30,14 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab private final String profile; private final int resolution; + private final PropertyKey biomeFeaturesKey; - public FeatureGenerationStage(Platform platform, String id, int resolution) { + public FeatureGenerationStage(Platform platform, String id, int resolution, PropertyKey biomeFeaturesKey) { this.platform = platform; this.id = id; this.profile = "feature_stage:" + id; this.resolution = resolution; + this.biomeFeaturesKey = biomeFeaturesKey; } @Override @@ -58,7 +61,7 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab long coordinateSeed = (seed * 31 + x) * 31 + z; Column column = world.column(x, z); biome.getContext() - .get(BiomeFeatures.class) + .get(biomeFeaturesKey) .getFeatures() .getOrDefault(this, Collections.emptyList()) .forEach(feature -> { 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 b1604cc1a..62e7006db 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,11 +8,13 @@ import com.dfsek.tectonic.api.exception.ValidationException; import com.dfsek.terra.addons.generation.feature.FeatureGenerationStage; import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; public class FeatureStageTemplate implements ObjectTemplate, ValidatedConfigTemplate { private final Platform platform; + private final PropertyKey biomeFeaturesKey; @Value("id") private String id; @@ -20,12 +22,15 @@ public class FeatureStageTemplate implements ObjectTemplate, Va @Default private int resolution = 4; - public FeatureStageTemplate(Platform platform) { this.platform = platform; } + public FeatureStageTemplate(Platform platform, PropertyKey biomeFeaturesKey) { + this.platform = platform; + this.biomeFeaturesKey = biomeFeaturesKey; + } @Override public FeatureGenerationStage get() { - return new FeatureGenerationStage(platform, id, resolution); + return new FeatureGenerationStage(platform, id, resolution, biomeFeaturesKey); } @Override From e13f8163a2101a1102da4eef1fff5943603297fb Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 02:01:24 -0700 Subject: [PATCH 101/220] simplify ChunkRegionMixin height accessors --- .../fabric/mixin/implementations/world/ChunkRegionMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java index 5805ebc1c..293b7f345 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -109,7 +109,7 @@ public abstract class ChunkRegionMixin { } public int terraWorld$getMaxHeight() { - return (((ChunkRegion) (Object) this).getBottomY()) + ((ChunkRegion) (Object) this).getHeight(); + return world.getTopY(); } @Intrinsic(displace = true) @@ -123,7 +123,7 @@ public abstract class ChunkRegionMixin { } public int terraWorld$getMinHeight() { - return ((ChunkRegion) (Object) this).getBottomY(); + return world.getBottomY(); } public ChunkGenerator terraWorld$getGenerator() { From 355805347b5c1a1766806f6e663a3f167e47db86 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 02:04:31 -0700 Subject: [PATCH 102/220] fix feature context registration --- .../terra/addons/generation/feature/FeatureGenerationAddon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 74eed4f98..ac0475d7e 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 @@ -87,7 +87,7 @@ public class FeatureGenerationAddon implements AddonInitializer { featureGenerationStages.forEach(stage -> features.put(stage, template.get(stage.getID(), List.class))); - event.getLoadedObject(Biome.class).getContext().put(new BiomeFeatures(features)); + event.getLoadedObject(Biome.class).getContext().put(biomeFeaturesKey, new BiomeFeatures(features)); } }) .failThrough(); From c96e908a1efc1d9a5055314942c17c73572c129f Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 15:59:25 -0700 Subject: [PATCH 103/220] fix Fabric entity spawning --- .../terra/fabric/entity/DelegateEntity.java | 52 +++++++++ .../fabric/entity/DelegateEntityHolder.java | 10 ++ .../FabricChunkGeneratorWrapper.java | 12 +- .../mixin/access/ChunkRegionAccessor.java | 15 +++ .../mixin/entity_holder/ProtoChunkMixin.java | 46 ++++++++ .../world/ChunkRegionMixin.java | 42 +++---- .../src/main/resources/terra.mixins.json | 104 +++++++++--------- 7 files changed, 210 insertions(+), 71 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntity.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntityHolder.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/ChunkRegionAccessor.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/entity_holder/ProtoChunkMixin.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntity.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntity.java new file mode 100644 index 000000000..449e43102 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntity.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.fabric.entity; + +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; + +import net.minecraft.world.ServerWorldAccess; + + +public class DelegateEntity implements Entity { + private Vector3 position; + private ServerWorld world; + private final EntityType type; + + public DelegateEntity(Vector3 position, ServerWorld world, EntityType type) { + this.world = world; + this.position = position; + this.type = type; + } + + @Override + public Vector3 position() { + return position; + } + + @Override + public void position(Vector3 position) { + this.position = position; + } + + @Override + public ServerWorld world() { + return world; + } + + @Override + public void world(ServerWorld world) { + this.world = world; + } + + @Override + public Object getHandle() { + return this; + } + + public net.minecraft.entity.Entity createMinecraftEntity(ServerWorldAccess world) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) type).create(world.toServerWorld()); + entity.setPos(position.getX(), position.getY(), position.getZ()); + return entity; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntityHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntityHolder.java new file mode 100644 index 000000000..46ea6c8f0 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntityHolder.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.fabric.entity; + +import java.util.List; + + +public interface DelegateEntityHolder { + List getAndClearTerraEntities(); + + void addTerraEntity(DelegateEntity entity); +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index ec5eeef2a..b3eaecf45 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -27,6 +27,8 @@ import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; import com.dfsek.terra.fabric.data.Codecs; +import com.dfsek.terra.fabric.entity.DelegateEntityHolder; +import com.dfsek.terra.fabric.mixin.access.ChunkRegionAccessor; import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; import com.dfsek.terra.fabric.util.FabricAdapter; @@ -95,7 +97,8 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C ChunkPos pos = chunk.getPos(); ((BiomeProviderHolder) chunk) .terra$setHeldBiomeProvider(pack.getBiomeProvider() - .caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(), pos.x, pos.z)); + .caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(), pos.x, + pos.z)); } return super.populateBiomes(biomeRegistry, executor, noiseConfig, blender, structureAccessor, chunk); } @@ -116,6 +119,13 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public void populateEntities(ChunkRegion region) { + ((ChunkRegionAccessor) region) + .getChunks() + .forEach( + chunk -> ((DelegateEntityHolder) chunk) + .getAndClearTerraEntities() + .forEach(entity -> chunk.addEntity(entity.createMinecraftEntity(region))) + ); if(!this.settings.value().mobGenerationDisabled()) { ChunkPos chunkPos = region.getCenterPos(); RegistryEntry registryEntry = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1)); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/ChunkRegionAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/ChunkRegionAccessor.java new file mode 100644 index 000000000..2c471cf0e --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/ChunkRegionAccessor.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.fabric.mixin.access; + +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.chunk.Chunk; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + + +@Mixin(ChunkRegion.class) +public interface ChunkRegionAccessor { + @Accessor("chunks") + List getChunks(); +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/entity_holder/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/entity_holder/ProtoChunkMixin.java new file mode 100644 index 000000000..899475f16 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/entity_holder/ProtoChunkMixin.java @@ -0,0 +1,46 @@ +package com.dfsek.terra.fabric.mixin.entity_holder; + +import com.dfsek.terra.fabric.entity.DelegateEntity; +import com.dfsek.terra.fabric.entity.DelegateEntityHolder; + +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.HeightLimitView; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.ProtoChunk; +import net.minecraft.world.chunk.UpgradeData; +import net.minecraft.world.gen.chunk.BlendingData; +import net.minecraft.world.tick.SimpleTickScheduler; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + + +@Mixin(ProtoChunk.class) +@Implements(@Interface(iface = DelegateEntityHolder.class, prefix = "terra$")) +public class ProtoChunkMixin { + private AtomicReference> terra$entities; + + @Inject(method = "*", at = @At("RETURN")) + public void injectConstructor(CallbackInfo ci) { + this.terra$entities = new AtomicReference<>(new ArrayList<>()); + } + + public List terra$getAndClearTerraEntities() { + return terra$entities.getAndSet(new ArrayList<>()); + } + + public void terra$addTerraEntity(DelegateEntity entity) { + this.terra$entities.updateAndGet(list -> { + list.add(entity); + return list; + }); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java index 293b7f345..bae1c94b8 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -28,6 +28,8 @@ import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.fabric.entity.DelegateEntity; +import com.dfsek.terra.fabric.entity.DelegateEntityHolder; import com.dfsek.terra.fabric.generation.BiomeProviderHolder; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.generation.TerraBiomeSource; @@ -47,13 +49,15 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.ArrayList; import java.util.List; @Mixin(ChunkRegion.class) @Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$")) public abstract class ChunkRegionMixin { - private ConfigPack config; + private ConfigPack terra$config; + @Shadow @Final @@ -70,27 +74,28 @@ public abstract class ChunkRegionMixin { @Final private MultiTickScheduler fluidTickScheduler; - @SuppressWarnings("deprecation") - private final Lazy caching = Lazy.lazy(() -> ((TerraBiomeSource) ((ChunkRegion) (Object) this) - .toServerWorld() - .getChunkManager() - .getChunkGenerator() - .getBiomeSource()).getProvider().caching((ProtoWorld) this)); + @Shadow + public abstract net.minecraft.server.world.ServerWorld toServerWorld(); + @Shadow + public abstract Chunk getChunk(int chunkX, int chunkZ); + + private Lazy caching; + + @SuppressWarnings("deprecation") @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) { - this.config = ((ServerWorld) world).getPack(); + this.terra$config = ((ServerWorld) world).getPack(); + this.caching = Lazy.lazy(() -> ((TerraBiomeSource) ((ChunkRegion) (Object) this) + .toServerWorld() + .getChunkManager() + .getChunkGenerator() + .getBiomeSource()).getProvider().caching((ProtoWorld) this)); } - public Entity terraWorld$spawnEntity(Vector3 location, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(null); - entity.setPos(location.getX(), location.getY(), location.getZ()); - ((ChunkRegion) (Object) this).spawnEntity(entity); - return (Entity) entity; - } @Intrinsic(displace = true) public void terraWorld$setBlockState(int x, int y, int z, BlockState data, boolean physics) { @@ -139,10 +144,9 @@ public abstract class ChunkRegionMixin { } public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(null); - entity.setPos(x, y, z); - ((ChunkRegion) (Object) this).spawnEntity(entity); - return (Entity) entity; + DelegateEntity entity = new DelegateEntity(Vector3.of(x, y, z), (ServerWorld) this.toServerWorld(), entityType); + ((DelegateEntityHolder) getChunk((int) x / 16, (int) z / 16)).addTerraEntity(entity); + return entity; } public int terraWorld$centerChunkX() { @@ -158,6 +162,6 @@ public abstract class ChunkRegionMixin { } public ConfigPack terraWorld$getPack() { - return config; + return terra$config; } } diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index ad1d97bb9..82b9818df 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -1,53 +1,55 @@ { - "required": true, - "minVersion": "0.8", - "package": "com.dfsek.terra.fabric.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - "access.MobSpawnerLogicAccessor", - "access.StateAccessor", - "access.StructureAccessorAccessor", - "cache.ChunkRegionMixin", - "cache.ProtoChunkMixin", - "compat.GenerationSettingsFloraFeaturesMixin", - "fix.NetherFossilOptimization", - "implementations.BiomeMixin", - "implementations.HandleImplementationMixin", - "implementations.block.BlockMixin", - "implementations.block.entity.BlockEntityMixin", - "implementations.block.entity.LootableContainerBlockEntityMixin", - "implementations.block.entity.MobSpawnerBlockEntityMixin", - "implementations.block.entity.SignBlockEntityMixin", - "implementations.block.state.BlockStateMixin", - "implementations.block.state.PropertyMixin", - "implementations.chunk.ChunkRegionMixin", - "implementations.chunk.WorldChunkMixin", - "implementations.chunk.data.ProtoChunkMixin", - "implementations.entity.EntityMixin", - "implementations.entity.EntityTypeMixin", - "implementations.entity.PlayerEntityMixin", - "implementations.entity.ServerCommandSourceMixin", - "implementations.inventory.LockableContainerBlockEntityMixin", - "implementations.inventory.item.ItemMixin", - "implementations.inventory.item.ItemStackMixin", - "implementations.inventory.meta.EnchantmentMixin", - "implementations.inventory.meta.ItemStackDamageableMixin", - "implementations.inventory.meta.ItemStackMetaMixin", - "implementations.world.ChunkRegionMixin", - "implementations.world.ServerWorldMixin", - "lifecycle.DataPackContentsMixin", - "lifecycle.MinecraftServerMixin", - "lifecycle.NoiseConfigMixin", - "lifecycle.RegistryMixin" - ], - "client": [ - "lifecycle.client.MinecraftClientMixin" - ], - "server": [ - "lifecycle.server.ServerMainMixin" - ], - "injectors": { - "defaultRequire": 1 - }, - "refmap": "terra-refmap.json" + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.fabric.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "access.ChunkRegionAccessor", + "access.MobSpawnerLogicAccessor", + "access.StateAccessor", + "access.StructureAccessorAccessor", + "cache.ChunkRegionMixin", + "cache.ProtoChunkMixin", + "compat.GenerationSettingsFloraFeaturesMixin", + "entity_holder.ProtoChunkMixin", + "fix.NetherFossilOptimization", + "implementations.BiomeMixin", + "implementations.HandleImplementationMixin", + "implementations.block.BlockMixin", + "implementations.block.entity.BlockEntityMixin", + "implementations.block.entity.LootableContainerBlockEntityMixin", + "implementations.block.entity.MobSpawnerBlockEntityMixin", + "implementations.block.entity.SignBlockEntityMixin", + "implementations.block.state.BlockStateMixin", + "implementations.block.state.PropertyMixin", + "implementations.chunk.ChunkRegionMixin", + "implementations.chunk.WorldChunkMixin", + "implementations.chunk.data.ProtoChunkMixin", + "implementations.entity.EntityMixin", + "implementations.entity.EntityTypeMixin", + "implementations.entity.PlayerEntityMixin", + "implementations.entity.ServerCommandSourceMixin", + "implementations.inventory.LockableContainerBlockEntityMixin", + "implementations.inventory.item.ItemMixin", + "implementations.inventory.item.ItemStackMixin", + "implementations.inventory.meta.EnchantmentMixin", + "implementations.inventory.meta.ItemStackDamageableMixin", + "implementations.inventory.meta.ItemStackMetaMixin", + "implementations.world.ChunkRegionMixin", + "implementations.world.ServerWorldMixin", + "lifecycle.DataPackContentsMixin", + "lifecycle.MinecraftServerMixin", + "lifecycle.NoiseConfigMixin", + "lifecycle.RegistryMixin" + ], + "client": [ + "lifecycle.client.MinecraftClientMixin" + ], + "server": [ + "lifecycle.server.ServerMainMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "terra-refmap.json" } \ No newline at end of file From 01ba75a29bb3df9be2a422c4935261a970e0eb70 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 16:17:12 -0700 Subject: [PATCH 104/220] refactor mixins --- .../FabricChunkGeneratorWrapper.java | 3 +- .../cache/ChunkRegionMixin.java | 4 +- .../cache/ProtoChunkMixin.java | 4 +- .../GenerationSettingsFloraFeaturesMixin.java | 4 +- .../entity_holder/ProtoChunkMixin.java | 13 +---- .../{ => terra}/BiomeMixin.java | 2 +- .../HandleImplementationMixin.java | 2 +- .../{ => terra}/block/BlockMixin.java | 2 +- .../block/entity/BlockEntityMixin.java | 2 +- .../LootableContainerBlockEntityMixin.java | 2 +- .../entity/MobSpawnerBlockEntityMixin.java | 2 +- .../block/entity/SignBlockEntityMixin.java | 2 +- .../block/state/BlockStateMixin.java | 2 +- .../block/state/PropertyMixin.java | 2 +- .../{ => terra}/chunk/ChunkRegionMixin.java | 2 +- .../{ => terra}/chunk/WorldChunkMixin.java | 2 +- .../chunk/data/ProtoChunkMixin.java | 4 +- .../{ => terra}/entity/EntityMixin.java | 5 +- .../{ => terra}/entity/EntityTypeMixin.java | 2 +- .../{ => terra}/entity/PlayerEntityMixin.java | 2 +- .../entity/ServerCommandSourceMixin.java | 2 +- .../LockableContainerBlockEntityMixin.java | 2 +- .../{ => terra}/inventory/item/ItemMixin.java | 2 +- .../inventory/item/ItemStackMixin.java | 2 +- .../inventory/meta/EnchantmentMixin.java | 2 +- .../meta/ItemStackDamageableMixin.java | 2 +- .../inventory/meta/ItemStackMetaMixin.java | 2 +- .../{ => terra}/package-info.java | 2 +- .../{ => terra}/world/ChunkRegionMixin.java | 9 ++- .../{ => terra}/world/ServerWorldMixin.java | 2 +- .../BiomeProviderHolder.java | 2 +- .../FloraFeatureHolder.java | 2 +- .../entity/DelegateEntity.java | 2 +- .../entity/DelegateEntityHolder.java | 2 +- .../dfsek/terra/fabric/util/BiomeUtil.java | 1 + .../src/main/resources/terra.mixins.json | 56 +++++++++---------- 36 files changed, 72 insertions(+), 83 deletions(-) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/{ => implementations}/cache/ChunkRegionMixin.java (92%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/{ => implementations}/cache/ProtoChunkMixin.java (86%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/{ => implementations}/compat/GenerationSettingsFloraFeaturesMixin.java (89%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/{ => implementations}/entity_holder/ProtoChunkMixin.java (70%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/BiomeMixin.java (94%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/HandleImplementationMixin.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/block/BlockMixin.java (95%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/block/entity/BlockEntityMixin.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/block/entity/LootableContainerBlockEntityMixin.java (94%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/block/entity/MobSpawnerBlockEntityMixin.java (98%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/block/entity/SignBlockEntityMixin.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/block/state/BlockStateMixin.java (97%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/block/state/PropertyMixin.java (93%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/chunk/ChunkRegionMixin.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/chunk/WorldChunkMixin.java (97%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/chunk/data/ProtoChunkMixin.java (91%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/entity/EntityMixin.java (93%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/entity/EntityTypeMixin.java (93%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/entity/PlayerEntityMixin.java (94%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/entity/ServerCommandSourceMixin.java (97%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/inventory/LockableContainerBlockEntityMixin.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/inventory/item/ItemMixin.java (95%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/inventory/item/ItemStackMixin.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/inventory/meta/EnchantmentMixin.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/inventory/meta/ItemStackDamageableMixin.java (95%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/inventory/meta/ItemStackMetaMixin.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/package-info.java (92%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/world/ChunkRegionMixin.java (95%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/{ => terra}/world/ServerWorldMixin.java (98%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/{generation => mixin_ifaces}/BiomeProviderHolder.java (83%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/{util => mixin_ifaces}/FloraFeatureHolder.java (81%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/{ => mixin_ifaces}/entity/DelegateEntity.java (96%) rename platforms/fabric/src/main/java/com/dfsek/terra/fabric/{ => mixin_ifaces}/entity/DelegateEntityHolder.java (76%) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index b3eaecf45..9ac53ba7a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -27,7 +27,8 @@ import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; import com.dfsek.terra.fabric.data.Codecs; -import com.dfsek.terra.fabric.entity.DelegateEntityHolder; +import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; +import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntityHolder; import com.dfsek.terra.fabric.mixin.access.ChunkRegionAccessor; import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; import com.dfsek.terra.fabric.util.FabricAdapter; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ChunkRegionMixin.java similarity index 92% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ChunkRegionMixin.java index 8f69f0523..f16ca763d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ChunkRegionMixin.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.fabric.mixin.cache; +package com.dfsek.terra.fabric.mixin.implementations.cache; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.Chunk; -import com.dfsek.terra.fabric.generation.BiomeProviderHolder; +import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; import net.minecraft.server.world.ServerWorld; import net.minecraft.world.ChunkRegion; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ProtoChunkMixin.java similarity index 86% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ProtoChunkMixin.java index 0b0684947..f212c8866 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/cache/ProtoChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ProtoChunkMixin.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.fabric.mixin.cache; +package com.dfsek.terra.fabric.mixin.implementations.cache; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.fabric.generation.BiomeProviderHolder; +import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; import net.minecraft.world.chunk.ProtoChunk; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/compat/GenerationSettingsFloraFeaturesMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java similarity index 89% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/compat/GenerationSettingsFloraFeaturesMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java index f625fb1ba..39236239f 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/compat/GenerationSettingsFloraFeaturesMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java @@ -1,6 +1,6 @@ -package com.dfsek.terra.fabric.mixin.compat; +package com.dfsek.terra.fabric.mixin.implementations.compat; -import com.dfsek.terra.fabric.util.FloraFeatureHolder; +import com.dfsek.terra.fabric.mixin_ifaces.FloraFeatureHolder; import net.minecraft.world.biome.GenerationSettings; import net.minecraft.world.gen.feature.ConfiguredFeature; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/entity_holder/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity_holder/ProtoChunkMixin.java similarity index 70% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/entity_holder/ProtoChunkMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity_holder/ProtoChunkMixin.java index 899475f16..ad9e0823b 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/entity_holder/ProtoChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity_holder/ProtoChunkMixin.java @@ -1,16 +1,9 @@ -package com.dfsek.terra.fabric.mixin.entity_holder; +package com.dfsek.terra.fabric.mixin.implementations.entity_holder; -import com.dfsek.terra.fabric.entity.DelegateEntity; -import com.dfsek.terra.fabric.entity.DelegateEntityHolder; +import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntity; +import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntityHolder; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.HeightLimitView; -import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.ProtoChunk; -import net.minecraft.world.chunk.UpgradeData; -import net.minecraft.world.gen.chunk.BlendingData; -import net.minecraft.world.tick.SimpleTickScheduler; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/BiomeMixin.java similarity index 94% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/BiomeMixin.java index aedbe6332..7ad40e91f 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/BiomeMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations; +package com.dfsek.terra.fabric.mixin.implementations.terra; import net.minecraft.world.biome.Biome; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/HandleImplementationMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/HandleImplementationMixin.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/HandleImplementationMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/HandleImplementationMixin.java index edf5d7e69..09ddf21a7 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/HandleImplementationMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/HandleImplementationMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.mixin.implementations; +package com.dfsek.terra.fabric.mixin.implementations.terra; import net.minecraft.block.Block; import net.minecraft.block.BlockState; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/BlockMixin.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/BlockMixin.java index 8f0167ab6..271615c01 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/BlockMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.block; +package com.dfsek.terra.fabric.mixin.implementations.terra.block; import net.minecraft.block.Block; import net.minecraft.block.Blocks; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/BlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/BlockEntityMixin.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/BlockEntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/BlockEntityMixin.java index cb501f580..a8fc2a580 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/BlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/BlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.block.entity; +package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/LootableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java similarity index 94% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/LootableContainerBlockEntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java index ffa217be9..40755991e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/LootableContainerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.block.entity; +package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; import net.minecraft.block.entity.LootableContainerBlockEntity; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/MobSpawnerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java similarity index 98% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/MobSpawnerBlockEntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java index 2f0363190..07fdd9630 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/MobSpawnerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.block.entity; +package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/SignBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/SignBlockEntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java index 675748135..2006246d8 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/SignBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.block.entity; +package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.text.Text; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/BlockStateMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java similarity index 97% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/BlockStateMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java index 4963fc4cb..361dd8ae4 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/BlockStateMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.mixin.implementations.block.state; +package com.dfsek.terra.fabric.mixin.implementations.terra.block.state; import com.google.common.collect.ImmutableMap; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/PropertyMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/PropertyMixin.java similarity index 93% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/PropertyMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/PropertyMixin.java index c0cb10943..7665662be 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/PropertyMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/PropertyMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.mixin.implementations.block.state; +package com.dfsek.terra.fabric.mixin.implementations.terra.block.state; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/ChunkRegionMixin.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/ChunkRegionMixin.java index 0acb33459..4da5c28cf 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/ChunkRegionMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.chunk; +package com.dfsek.terra.fabric.mixin.implementations.terra.chunk; import net.minecraft.util.math.BlockPos; import net.minecraft.world.ChunkRegion; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/WorldChunkMixin.java similarity index 97% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/WorldChunkMixin.java index f89d96b62..885d0aae2 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/WorldChunkMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.chunk; +package com.dfsek.terra.fabric.mixin.implementations.terra.chunk; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.WorldChunk; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java similarity index 91% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java index a65a4f4d8..afae72689 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java @@ -15,12 +15,10 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.chunk.data; +package com.dfsek.terra.fabric.mixin.implementations.terra.chunk.data; import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; -import com.dfsek.terra.fabric.generation.BiomeProviderHolder; import net.minecraft.util.math.BlockPos; import net.minecraft.world.HeightLimitView; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityMixin.java similarity index 93% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityMixin.java index 42b006cb1..beeaf0d57 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityMixin.java @@ -15,18 +15,15 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.entity; +package com.dfsek.terra.fabric.mixin.implementations.terra.entity; import net.minecraft.entity.Entity; -import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import java.util.UUID; - import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.fabric.util.FabricAdapter; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityTypeMixin.java similarity index 93% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityTypeMixin.java index 3acee886c..27ea5a462 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityTypeMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.entity; +package com.dfsek.terra.fabric.mixin.implementations.terra.entity; import net.minecraft.entity.EntityType; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/PlayerEntityMixin.java similarity index 94% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/PlayerEntityMixin.java index daf784d88..8298cb4e7 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/PlayerEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.entity; +package com.dfsek.terra.fabric.mixin.implementations.terra.entity; import net.minecraft.entity.player.PlayerEntity; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/ServerCommandSourceMixin.java similarity index 97% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/ServerCommandSourceMixin.java index 23cf991c0..a8fdb8958 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/ServerCommandSourceMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.entity; +package com.dfsek.terra.fabric.mixin.implementations.terra.entity; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.server.command.ServerCommandSource; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java index bb9ccf63b..e888e511a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.inventory; +package com.dfsek.terra.fabric.mixin.implementations.terra.inventory; import net.minecraft.block.entity.LockableContainerBlockEntity; import net.minecraft.item.Items; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemMixin.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemMixin.java index a7d5da4ed..111aa95fa 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.inventory.item; +package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.item; import net.minecraft.item.Item; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemStackMixin.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemStackMixin.java index dcddca234..3dafd81be 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemStackMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.inventory.item; +package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java index 3d10a2241..ddc2e6936 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; +package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta; import net.minecraft.enchantment.Enchantment; import net.minecraft.util.registry.Registry; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java index 217ff86ba..4749b8b4d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; +package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta; import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java index 60c33fc68..0fe8f7686 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; +package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/package-info.java similarity index 92% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/package-info.java index 262b1c464..64552f11a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/package-info.java @@ -20,4 +20,4 @@ * interfaces in Minecraft classes. */ -package com.dfsek.terra.fabric.mixin.implementations; \ No newline at end of file +package com.dfsek.terra.fabric.mixin.implementations.terra; \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java index bae1c94b8..471598bc9 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.world; +package com.dfsek.terra.fabric.mixin.implementations.terra.world; import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.block.state.BlockState; @@ -28,9 +28,9 @@ import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.fabric.entity.DelegateEntity; -import com.dfsek.terra.fabric.entity.DelegateEntityHolder; -import com.dfsek.terra.fabric.generation.BiomeProviderHolder; +import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntity; +import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntityHolder; +import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.generation.TerraBiomeSource; import com.dfsek.terra.fabric.util.FabricUtil; @@ -49,7 +49,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.ArrayList; import java.util.List; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ServerWorldMixin.java similarity index 98% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ServerWorldMixin.java index 6e1c97f9e..048b38d8e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ServerWorldMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.world; +package com.dfsek.terra.fabric.mixin.implementations.terra.world; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldAccess; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/BiomeProviderHolder.java similarity index 83% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/BiomeProviderHolder.java index 2204a59fc..ce0865420 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BiomeProviderHolder.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/BiomeProviderHolder.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.generation; +package com.dfsek.terra.fabric.mixin_ifaces; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FloraFeatureHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/FloraFeatureHolder.java similarity index 81% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FloraFeatureHolder.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/FloraFeatureHolder.java index 9b2157d72..5f4697d99 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FloraFeatureHolder.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/FloraFeatureHolder.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.util; +package com.dfsek.terra.fabric.mixin_ifaces; import net.minecraft.world.gen.feature.ConfiguredFeature; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntity.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntity.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntity.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntity.java index 449e43102..e8c60990c 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntity.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntity.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.entity; +package com.dfsek.terra.fabric.mixin_ifaces.entity; import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.EntityType; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntityHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntityHolder.java similarity index 76% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntityHolder.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntityHolder.java index 46ea6c8f0..a09544121 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/entity/DelegateEntityHolder.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntityHolder.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.entity; +package com.dfsek.terra.fabric.mixin_ifaces.entity; import java.util.List; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java index d1d2ec9a9..cf3d08a61 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -6,6 +6,7 @@ import com.dfsek.terra.fabric.FabricEntryPoint; import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; import com.dfsek.terra.fabric.config.VanillaBiomeProperties; +import com.dfsek.terra.fabric.mixin_ifaces.FloraFeatureHolder; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 82b9818df..5d8ed8c86 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -8,35 +8,35 @@ "access.MobSpawnerLogicAccessor", "access.StateAccessor", "access.StructureAccessorAccessor", - "cache.ChunkRegionMixin", - "cache.ProtoChunkMixin", - "compat.GenerationSettingsFloraFeaturesMixin", - "entity_holder.ProtoChunkMixin", + "implementations.cache.ChunkRegionMixin", + "implementations.cache.ProtoChunkMixin", + "implementations.compat.GenerationSettingsFloraFeaturesMixin", + "implementations.entity_holder.ProtoChunkMixin", "fix.NetherFossilOptimization", - "implementations.BiomeMixin", - "implementations.HandleImplementationMixin", - "implementations.block.BlockMixin", - "implementations.block.entity.BlockEntityMixin", - "implementations.block.entity.LootableContainerBlockEntityMixin", - "implementations.block.entity.MobSpawnerBlockEntityMixin", - "implementations.block.entity.SignBlockEntityMixin", - "implementations.block.state.BlockStateMixin", - "implementations.block.state.PropertyMixin", - "implementations.chunk.ChunkRegionMixin", - "implementations.chunk.WorldChunkMixin", - "implementations.chunk.data.ProtoChunkMixin", - "implementations.entity.EntityMixin", - "implementations.entity.EntityTypeMixin", - "implementations.entity.PlayerEntityMixin", - "implementations.entity.ServerCommandSourceMixin", - "implementations.inventory.LockableContainerBlockEntityMixin", - "implementations.inventory.item.ItemMixin", - "implementations.inventory.item.ItemStackMixin", - "implementations.inventory.meta.EnchantmentMixin", - "implementations.inventory.meta.ItemStackDamageableMixin", - "implementations.inventory.meta.ItemStackMetaMixin", - "implementations.world.ChunkRegionMixin", - "implementations.world.ServerWorldMixin", + "implementations.terra.BiomeMixin", + "implementations.terra.HandleImplementationMixin", + "implementations.terra.block.BlockMixin", + "implementations.terra.block.entity.BlockEntityMixin", + "implementations.terra.block.entity.LootableContainerBlockEntityMixin", + "implementations.terra.block.entity.MobSpawnerBlockEntityMixin", + "implementations.terra.block.entity.SignBlockEntityMixin", + "implementations.terra.block.state.BlockStateMixin", + "implementations.terra.block.state.PropertyMixin", + "implementations.terra.chunk.ChunkRegionMixin", + "implementations.terra.chunk.WorldChunkMixin", + "implementations.terra.chunk.data.ProtoChunkMixin", + "implementations.terra.entity.EntityMixin", + "implementations.terra.entity.EntityTypeMixin", + "implementations.terra.entity.PlayerEntityMixin", + "implementations.terra.entity.ServerCommandSourceMixin", + "implementations.terra.inventory.LockableContainerBlockEntityMixin", + "implementations.terra.inventory.item.ItemMixin", + "implementations.terra.inventory.item.ItemStackMixin", + "implementations.terra.inventory.meta.EnchantmentMixin", + "implementations.terra.inventory.meta.ItemStackDamageableMixin", + "implementations.terra.inventory.meta.ItemStackMetaMixin", + "implementations.terra.world.ChunkRegionMixin", + "implementations.terra.world.ServerWorldMixin", "lifecycle.DataPackContentsMixin", "lifecycle.MinecraftServerMixin", "lifecycle.NoiseConfigMixin", From ba179c09910d5b6c6be8c05c153ad77927e0bfb0 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 16:37:14 -0700 Subject: [PATCH 105/220] add BeeMoveGoalsUnsynchronizedRandomAccessFix --- ...oveGoalsUnsynchronizedRandomAccessFix.java | 29 +++++++++++++++++++ .../src/main/resources/terra.mixins.json | 5 ++-- 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java new file mode 100644 index 000000000..5f1cf35d4 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.fabric.mixin.fix; + +import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.fabric.util.FabricUtil; + +import net.minecraft.entity.passive.BeeEntity.MoveToFlowerGoal; +import net.minecraft.entity.passive.BeeEntity.MoveToHiveGoal; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.random.CheckedRandom; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + + +/** + * Bees spawning uses world.random without synchronization. This causes issues when spawning bees during world generation. + */ +@Mixin({ + MoveToHiveGoal.class, + MoveToFlowerGoal.class +}) +public class BeeMoveGoalsUnsynchronizedRandomAccessFix { + @Redirect(method = "", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;random:Lnet/minecraft/util/math/random/Random;")) + public Random redirectRandomAccess(World instance) { + return new CheckedRandom(FabricEntryPoint.getPlatform().getServer().getTicks()); // replace with new random seeded by tick time. + } +} diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 5d8ed8c86..1a5f4ce8b 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -8,13 +8,14 @@ "access.MobSpawnerLogicAccessor", "access.StateAccessor", "access.StructureAccessorAccessor", + "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", + "fix.NetherFossilOptimization", "implementations.cache.ChunkRegionMixin", "implementations.cache.ProtoChunkMixin", "implementations.compat.GenerationSettingsFloraFeaturesMixin", "implementations.entity_holder.ProtoChunkMixin", - "fix.NetherFossilOptimization", "implementations.terra.BiomeMixin", - "implementations.terra.HandleImplementationMixin", + "implementations.terra.HandleImplementationMixin", "implementations.terra.block.BlockMixin", "implementations.terra.block.entity.BlockEntityMixin", "implementations.terra.block.entity.LootableContainerBlockEntityMixin", From 34b1aca556fe54f1b630b97b9b1d131746e33887 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 16:46:44 -0700 Subject: [PATCH 106/220] fix Minecraft bee issue --- .../FabricChunkGeneratorWrapper.java | 37 +++++-------- ...oveGoalsUnsynchronizedRandomAccessFix.java | 6 +-- .../entity_holder/ProtoChunkMixin.java | 39 -------------- .../terra/world/ChunkRegionMixin.java | 47 +++++++++-------- .../mixin_ifaces/entity/DelegateEntity.java | 52 ------------------- .../entity/DelegateEntityHolder.java | 10 ---- .../src/main/resources/terra.mixins.json | 1 - 7 files changed, 41 insertions(+), 151 deletions(-) delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity_holder/ProtoChunkMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntity.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntityHolder.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 9ac53ba7a..a452fdc07 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -17,22 +17,6 @@ package com.dfsek.terra.fabric.generation; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; -import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; -import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; -import com.dfsek.terra.api.world.info.WorldProperties; -import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.fabric.data.Codecs; -import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; -import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntityHolder; -import com.dfsek.terra.fabric.mixin.access.ChunkRegionAccessor; -import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; -import com.dfsek.terra.fabric.util.FabricAdapter; - import com.mojang.serialization.Codec; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -69,6 +53,20 @@ import java.util.Optional; 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; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; +import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; +import com.dfsek.terra.api.world.info.WorldProperties; +import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.fabric.data.Codecs; +import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; +import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; +import com.dfsek.terra.fabric.util.FabricAdapter; + public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class); @@ -120,13 +118,6 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public void populateEntities(ChunkRegion region) { - ((ChunkRegionAccessor) region) - .getChunks() - .forEach( - chunk -> ((DelegateEntityHolder) chunk) - .getAndClearTerraEntities() - .forEach(entity -> chunk.addEntity(entity.createMinecraftEntity(region))) - ); if(!this.settings.value().mobGenerationDisabled()) { ChunkPos chunkPos = region.getCenterPos(); RegistryEntry registryEntry = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1)); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java index 5f1cf35d4..ced25c46b 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java @@ -1,11 +1,7 @@ package com.dfsek.terra.fabric.mixin.fix; -import com.dfsek.terra.fabric.FabricEntryPoint; -import com.dfsek.terra.fabric.util.FabricUtil; - import net.minecraft.entity.passive.BeeEntity.MoveToFlowerGoal; import net.minecraft.entity.passive.BeeEntity.MoveToHiveGoal; -import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.random.CheckedRandom; import net.minecraft.util.math.random.Random; import net.minecraft.world.World; @@ -13,6 +9,8 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import com.dfsek.terra.fabric.FabricEntryPoint; + /** * Bees spawning uses world.random without synchronization. This causes issues when spawning bees during world generation. diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity_holder/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity_holder/ProtoChunkMixin.java deleted file mode 100644 index ad9e0823b..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity_holder/ProtoChunkMixin.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations.entity_holder; - -import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntity; -import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntityHolder; - -import net.minecraft.world.chunk.ProtoChunk; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - - -@Mixin(ProtoChunk.class) -@Implements(@Interface(iface = DelegateEntityHolder.class, prefix = "terra$")) -public class ProtoChunkMixin { - private AtomicReference> terra$entities; - - @Inject(method = "*", at = @At("RETURN")) - public void injectConstructor(CallbackInfo ci) { - this.terra$entities = new AtomicReference<>(new ArrayList<>()); - } - - public List terra$getAndClearTerraEntities() { - return terra$entities.getAndSet(new ArrayList<>()); - } - - public void terra$addTerraEntity(DelegateEntity entity) { - this.terra$entities.updateAndGet(list -> { - list.add(entity); - return list; - }); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java index 471598bc9..2c6f0253b 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -17,24 +17,6 @@ package com.dfsek.terra.fabric.mixin.implementations.terra.world; -import com.dfsek.terra.api.block.entity.BlockEntity; -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.entity.Entity; -import com.dfsek.terra.api.entity.EntityType; -import com.dfsek.terra.api.util.generic.Lazy; -import com.dfsek.terra.api.util.vector.Vector3; -import com.dfsek.terra.api.world.ServerWorld; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntity; -import com.dfsek.terra.fabric.mixin_ifaces.entity.DelegateEntityHolder; -import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.generation.TerraBiomeSource; -import com.dfsek.terra.fabric.util.FabricUtil; - import net.minecraft.block.FluidBlock; import net.minecraft.fluid.Fluid; import net.minecraft.util.math.BlockPos; @@ -44,13 +26,33 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.tick.MultiTickScheduler; import net.minecraft.world.tick.OrderedTick; -import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +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; 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; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; +import com.dfsek.terra.fabric.util.FabricUtil; + @Mixin(ChunkRegion.class) @Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$")) @@ -143,9 +145,10 @@ public abstract class ChunkRegionMixin { } public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { - DelegateEntity entity = new DelegateEntity(Vector3.of(x, y, z), (ServerWorld) this.toServerWorld(), entityType); - ((DelegateEntityHolder) getChunk((int) x / 16, (int) z / 16)).addTerraEntity(entity); - return entity; + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(world); + entity.setPos(x, y, z); + ((ChunkRegion) (Object) this).spawnEntity(entity); + return (Entity) entity; } public int terraWorld$centerChunkX() { diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntity.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntity.java deleted file mode 100644 index e8c60990c..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntity.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.fabric.mixin_ifaces.entity; - -import com.dfsek.terra.api.entity.Entity; -import com.dfsek.terra.api.entity.EntityType; -import com.dfsek.terra.api.util.vector.Vector3; -import com.dfsek.terra.api.world.ServerWorld; - -import net.minecraft.world.ServerWorldAccess; - - -public class DelegateEntity implements Entity { - private Vector3 position; - private ServerWorld world; - private final EntityType type; - - public DelegateEntity(Vector3 position, ServerWorld world, EntityType type) { - this.world = world; - this.position = position; - this.type = type; - } - - @Override - public Vector3 position() { - return position; - } - - @Override - public void position(Vector3 position) { - this.position = position; - } - - @Override - public ServerWorld world() { - return world; - } - - @Override - public void world(ServerWorld world) { - this.world = world; - } - - @Override - public Object getHandle() { - return this; - } - - public net.minecraft.entity.Entity createMinecraftEntity(ServerWorldAccess world) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) type).create(world.toServerWorld()); - entity.setPos(position.getX(), position.getY(), position.getZ()); - return entity; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntityHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntityHolder.java deleted file mode 100644 index a09544121..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/entity/DelegateEntityHolder.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.fabric.mixin_ifaces.entity; - -import java.util.List; - - -public interface DelegateEntityHolder { - List getAndClearTerraEntities(); - - void addTerraEntity(DelegateEntity entity); -} diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 1a5f4ce8b..417a4fed7 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -13,7 +13,6 @@ "implementations.cache.ChunkRegionMixin", "implementations.cache.ProtoChunkMixin", "implementations.compat.GenerationSettingsFloraFeaturesMixin", - "implementations.entity_holder.ProtoChunkMixin", "implementations.terra.BiomeMixin", "implementations.terra.HandleImplementationMixin", "implementations.terra.block.BlockMixin", From baccd04c8df0a7363e4360a7200fd94730ea3da7 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 17:21:46 -0700 Subject: [PATCH 107/220] use correct y value in LazilyEvaluatedInterpolator --- .../math/interpolation/LazilyEvaluatedInterpolator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java index be72fb42f..0b6bf41bf 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java @@ -44,15 +44,15 @@ public class LazilyEvaluatedInterpolator { this.min = min; } - private double sample(int x, int y, int z, int ox, int oy, int oz) { - int index = x + (z * zMul) + (y * yMul); + private double sample(int xIndex, int yIndex, int zIndex, int ox, int oy, int oz) { + int index = xIndex + (zIndex * zMul) + (yIndex * yMul); Double sample = samples[index]; if(sample == null) { int xi = ox + chunkX; int zi = oz + chunkZ; sample = biomeProvider - .getBiome(xi, y, zi, seed) + .getBiome(xi, oy, zi, seed) .getContext() .get(noisePropertiesKey) .carving() From bcae15225f32df39aacbf26dae02d42bfde23285 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 17:47:54 -0700 Subject: [PATCH 108/220] fix matchpattern when min >= max --- .../terra/addons/feature/locator/patterns/MatchPattern.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java index d68ece62e..ecc3d50ae 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java @@ -29,6 +29,7 @@ public class MatchPattern implements Pattern { public boolean matches(int y, Column column) { int min = FastMath.max(column.getMinY(), range.getMin() + y); int max = FastMath.min(column.getMaxY(), range.getMax() + y); + if(max <= min) return false; for(int i = min; i < max; i++) { if(!matches.test(column.getBlock(i))) return false; } From 727f7ce2fb79a124b35545543ac96a1e030448fa Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 20:16:53 -0700 Subject: [PATCH 109/220] bump locator addon version --- common/addons/config-locators/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/addons/config-locators/build.gradle.kts b/common/addons/config-locators/build.gradle.kts index 99485164c..50fc70400 100644 --- a/common/addons/config-locators/build.gradle.kts +++ b/common/addons/config-locators/build.gradle.kts @@ -1,4 +1,4 @@ -version = version("1.0.0") +version = version("1.1.0") dependencies { compileOnlyApi(project(":common:addons:manifest-addon-loader")) From cfdce200dd188b70302ad20726872564bd89d6d0 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 20:17:11 -0700 Subject: [PATCH 110/220] bump feature stage addon version --- common/addons/generation-stage-feature/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/addons/generation-stage-feature/build.gradle.kts b/common/addons/generation-stage-feature/build.gradle.kts index 9d0aac37f..84c179738 100644 --- a/common/addons/generation-stage-feature/build.gradle.kts +++ b/common/addons/generation-stage-feature/build.gradle.kts @@ -1,4 +1,4 @@ -version = version("1.0.0") +version = version("1.1.0") dependencies { compileOnlyApi(project(":common:addons:manifest-addon-loader")) From ef0692977cc84ba110a5833d95f4f4938aca4e47 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 20:17:42 -0700 Subject: [PATCH 111/220] bump terrascript addon version --- common/addons/structure-terrascript-loader/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/addons/structure-terrascript-loader/build.gradle.kts b/common/addons/structure-terrascript-loader/build.gradle.kts index 62422cc79..18d4019b9 100644 --- a/common/addons/structure-terrascript-loader/build.gradle.kts +++ b/common/addons/structure-terrascript-loader/build.gradle.kts @@ -1,6 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -version = version("1.0.1") +version = version("1.1.0") dependencies { api("commons-io:commons-io:2.7") From e1ce5e117c15880c61d86b3627bf10dddeeba016 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 21:57:50 -0700 Subject: [PATCH 112/220] apply vanilla biome particle config --- .../src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java index cf3d08a61..39f6901e9 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -151,6 +151,8 @@ public final class BiomeUtil { builder.precipitation(vanilla.getPrecipitation()); } + vanilla.getParticleConfig().ifPresent(effects::particleConfig); + return builder .temperature(vanilla.getTemperature()) .downfall(vanilla.getDownfall()) From 7574c356a074197c9233469abdd1fcbf8295a95d Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 21:58:48 -0700 Subject: [PATCH 113/220] apply particles on Bukkit --- .../com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java | 2 ++ .../com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java index d7a03ef1e..7ca26995a 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java @@ -155,6 +155,8 @@ public class NMSBiomeInjector { } else { effects.grassColorOverride(vanillaBiomeProperties.getGrassColor()); } + + vanilla.getAmbientParticle().ifPresent(effects::ambientParticle); builder.specialEffects(effects.build()); diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java index 2da3c3f85..3121bfa2b 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java @@ -149,6 +149,8 @@ public class NMSBiomeInjector { // grass effects.grassColorOverride(vanillaBiomeProperties.getGrassColor()); } + + vanilla.getAmbientParticle().ifPresent(effects::ambientParticle); builder.specialEffects(effects.build()); From 36682bc04c498025dd3b7d7bdb6dc69947d35fb2 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 22:02:08 -0700 Subject: [PATCH 114/220] add biome sound configs --- .../dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java | 4 ++++ .../dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java | 6 +++++- .../main/java/com/dfsek/terra/fabric/util/BiomeUtil.java | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java index 7ca26995a..3c69226d8 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java @@ -156,6 +156,10 @@ public class NMSBiomeInjector { effects.grassColorOverride(vanillaBiomeProperties.getGrassColor()); } + vanilla.getAmbientLoop().ifPresent(effects::ambientLoopSound); + vanilla.getAmbientAdditions().ifPresent(effects::ambientAdditionsSound); + vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound); + vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic); vanilla.getAmbientParticle().ifPresent(effects::ambientParticle); builder.specialEffects(effects.build()); diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java index 3121bfa2b..4ed328fff 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java @@ -149,7 +149,11 @@ public class NMSBiomeInjector { // grass effects.grassColorOverride(vanillaBiomeProperties.getGrassColor()); } - + + vanilla.getAmbientLoop().ifPresent(effects::ambientLoopSound); + vanilla.getAmbientAdditions().ifPresent(effects::ambientAdditionsSound); + vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound); + vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic); vanilla.getAmbientParticle().ifPresent(effects::ambientParticle); builder.specialEffects(effects.build()); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java index 39f6901e9..421b321f4 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -150,7 +150,11 @@ public final class BiomeUtil { builder.precipitation(vanilla.getPrecipitation()); } - + + vanilla.getLoopSound().ifPresent(effects::loopSound); + vanilla.getAdditionsSound().ifPresent(effects::additionsSound); + vanilla.getMoodSound().ifPresent(effects::moodSound); + vanilla.getMusic().ifPresent(effects::music); vanilla.getParticleConfig().ifPresent(effects::particleConfig); return builder From 036a166909073304a5c095f8585aede03190a93e Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 23:40:52 -0700 Subject: [PATCH 115/220] fix ParserTest --- .../src/test/java/structure/ParserTest.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java b/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java index b502a3563..e50589dfb 100644 --- a/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java +++ b/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java @@ -8,12 +8,15 @@ package structure; +import com.dfsek.terra.addons.terrascript.parser.lang.Executable; + import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.charset.Charset; import java.util.List; +import java.util.Objects; import com.dfsek.terra.addons.terrascript.parser.Parser; import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; @@ -29,7 +32,7 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public class ParserTest { @Test public void parse() throws IOException, ParseException { - Parser parser = new Parser(IOUtils.toString(getClass().getResourceAsStream("/test.tesf"), Charset.defaultCharset())); + Parser parser = new Parser(IOUtils.toString(Objects.requireNonNull(getClass().getResourceAsStream("/test.tesf")), Charset.defaultCharset())); parser.registerFunction("test", new FunctionBuilder() { @Override @@ -54,13 +57,13 @@ public class ParserTest { }); long l = System.nanoTime(); - Block block = parser.parse(); + Executable block = parser.parse(); long t = System.nanoTime() - l; System.out.println("Took " + (double) t / 1000000); - block.apply(null, new Scope()); + block.execute(null); - block.apply(null, new Scope()); + block.execute(null); } private static class Test1 implements Function { From fce8c823be7c5a2e84ca19f0f9b0b8136e5eda77 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 23:53:21 -0700 Subject: [PATCH 116/220] bump fabric api version --- buildSrc/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index b52cca994..a2e0a7cd5 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -19,7 +19,7 @@ object Versions { object Fabric { const val fabricLoader = "0.14.2" - const val fabricAPI = "0.55.1+1.19" + const val fabricAPI = "0.56.0+1.19" const val minecraft = "1.19" const val yarn = "$minecraft+build.1" const val mixin = "0.11.2+mixin.0.8.5" From cacfd66cf718d6f3e4c6e842016578454b8ae034 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 23:55:22 -0700 Subject: [PATCH 117/220] pull all fabric versions to Versions.kt --- buildSrc/src/main/kotlin/Versions.kt | 2 ++ platforms/fabric/build.gradle.kts | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index a2e0a7cd5..b9520ba61 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -24,6 +24,8 @@ object Versions { const val yarn = "$minecraft+build.1" const val mixin = "0.11.2+mixin.0.8.5" const val loom = "0.12-SNAPSHOT" + const val loomQuiltflower = "1.7.1" + const val minotaur = "1.1.0" } object Bukkit { diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 7cc2685d2..a89870146 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -3,9 +3,9 @@ import com.modrinth.minotaur.TaskModrinthUpload import net.fabricmc.loom.task.RemapJarTask plugins { - id("fabric-loom").version(Versions.Fabric.loom) - id("com.modrinth.minotaur").version("1.1.0") - id("io.github.juuxel.loom-quiltflower") version "1.7.1" + id("fabric-loom") version Versions.Fabric.loom + id("com.modrinth.minotaur") version Versions.Fabric.minotaur + id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower } dependencies { From 5df016e43e73f7048271dcb05e7f398c95048de7 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 16 Jun 2022 23:58:25 -0700 Subject: [PATCH 118/220] pull bukkit versions to Versions.kt --- buildSrc/src/main/kotlin/Versions.kt | 4 +++- platforms/bukkit/build.gradle.kts | 5 ++--- platforms/bukkit/common/build.gradle.kts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index b9520ba61..04bf401fe 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -29,8 +29,10 @@ object Versions { } object Bukkit { - const val paper = "1.18-R0.1-SNAPSHOT" + const val paper = "1.18.2-R0.1-SNAPSHOT" const val paperLib = "1.0.5" + const val minecraft = "1.19" + const val reflectionRemapper = "0.1.0-SNAPSHOT" } object Sponge { diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index 146321dff..e0a1bc48a 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -8,7 +8,6 @@ plugins { id("xyz.jpenilla.run-paper") version "1.0.6" } -val mcVersion = "1.18.2" val testDir = "target/server" val testMem = "3G" @@ -24,7 +23,7 @@ dependencies { shaded(project(":platforms:bukkit:common")) shaded(project(":platforms:bukkit:nms:v1_18_R2", configuration = "reobf")) shaded(project(":platforms:bukkit:nms:v1_19_R1", configuration = "reobf")) - shaded("xyz.jpenilla", "reflection-remapper", "0.1.0-SNAPSHOT") + shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper) } val throttleCoreCount = 0 @@ -45,7 +44,7 @@ if(throttleCoreCount > 0) { fun downloadPaperclip(url: String, dir: String) { - val clip = URL(url.replace("%version%", mcVersion)) + val clip = URL(url.replace("%version%", Versions.Bukkit.minecraft)) val clipReadableByteChannel = Channels.newChannel(clip.openStream()) val clipFile = file("$testDir/$dir/paperclip.jar") val clipOutputStream = clipFile.outputStream() diff --git a/platforms/bukkit/common/build.gradle.kts b/platforms/bukkit/common/build.gradle.kts index b29891d4d..a806ce672 100644 --- a/platforms/bukkit/common/build.gradle.kts +++ b/platforms/bukkit/common/build.gradle.kts @@ -9,7 +9,7 @@ dependencies { because("Minecraft 1.17+ includes slf4j 1.8.0-beta4, so we need to shade it for other versions.") } - compileOnly("io.papermc.paper:paper-api:1.18.2-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:${Versions.Bukkit.paper}") shadedApi("io.papermc", "paperlib", Versions.Bukkit.paperLib) shadedApi("com.google.guava:guava:30.0-jre") From ab78bea9aadd048a24e4805f35cba9d0499a5028 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 17 Jun 2022 00:00:46 -0700 Subject: [PATCH 119/220] pull CLI versions to Versions.kt --- buildSrc/src/main/kotlin/Versions.kt | 6 ++++++ platforms/cli/build.gradle.kts | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 04bf401fe..73eb8b2d2 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -40,4 +40,10 @@ object Versions { const val mixin = "0.8.2" const val minecraft = "1.17.1" } + + object CLI { + const val nbt = "6.1" + const val logback = "1.2.9" + const val commonsIO = "2.7" + } } \ No newline at end of file diff --git a/platforms/cli/build.gradle.kts b/platforms/cli/build.gradle.kts index 36eb49cdf..90e180480 100644 --- a/platforms/cli/build.gradle.kts +++ b/platforms/cli/build.gradle.kts @@ -3,13 +3,13 @@ repositories { } dependencies { - shadedApi("commons-io:commons-io:2.7") - shadedApi("com.github.Querz:NBT:6.1") + shadedApi("commons-io:commons-io:${Versions.CLI.commonsIO}") + shadedApi("com.github.Querz:NBT:${Versions.CLI.nbt}") shadedApi(project(":common:implementation:base")) shadedImplementation("com.google.guava:guava:31.0.1-jre") - shadedImplementation("ch.qos.logback:logback-classic:1.2.9") + shadedImplementation("ch.qos.logback:logback-classic:${Versions.CLI.logback}") implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) } From 529cd463de59be4fb3c305609d5f987ce7eaa05f Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 17 Jun 2022 00:40:49 -0700 Subject: [PATCH 120/220] add cli run task --- platforms/cli/build.gradle.kts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/platforms/cli/build.gradle.kts b/platforms/cli/build.gradle.kts index 90e180480..677d2f585 100644 --- a/platforms/cli/build.gradle.kts +++ b/platforms/cli/build.gradle.kts @@ -1,7 +1,13 @@ +plugins { + application +} + repositories { maven { url = uri("https://jitpack.io/") } } +val javaMainClass = "com.dfsek.terra.cli.TerraCLI" + dependencies { shadedApi("commons-io:commons-io:${Versions.CLI.commonsIO}") shadedApi("com.github.Querz:NBT:${Versions.CLI.nbt}") @@ -18,7 +24,15 @@ tasks.withType() { entryCompression = ZipEntryCompression.STORED manifest { attributes( - "Main-Class" to "com.dfsek.terra.cli.TerraCLI", + "Main-Class" to javaMainClass, ) } -} \ No newline at end of file +} + +application { + mainClass.set(javaMainClass) +} + +tasks.getByName("run").setProperty("workingDir", file("./run")) + +addonDir(project.file("./run/addons"), tasks.named("run").get()) From d2055d60fdce116da4c0f9af8fd06ea62067ca3f Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 17 Jun 2022 00:53:34 -0700 Subject: [PATCH 121/220] optimize caching biomes in CLIWorld --- .../java/com/dfsek/terra/cli/world/CLIWorld.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java index c385ff8eb..4191ba5a8 100644 --- a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java @@ -1,5 +1,7 @@ package com.dfsek.terra.cli.world; +import com.dfsek.terra.api.world.biome.generation.ChunkLocalCachingBiomeProvider; + import com.google.common.collect.Streams; import net.jafama.FastMath; import net.querz.mca.MCAFile; @@ -85,8 +87,9 @@ public class CLIWorld implements ServerWorld, NBTSerializable stage.populate(protoWorld)); if(num % 240 == 239) { long time = System.nanoTime(); @@ -224,10 +227,12 @@ public class CLIWorld implements ServerWorld, NBTSerializable Date: Fri, 17 Jun 2022 01:22:07 -0700 Subject: [PATCH 122/220] clean up --- .../dfsek/terra/cli/generator/CLIChunkGenerator.java | 12 ------------ .../main/java/com/dfsek/terra/cli/world/Region.java | 1 - 2 files changed, 13 deletions(-) delete mode 100644 platforms/cli/src/main/java/com/dfsek/terra/cli/generator/CLIChunkGenerator.java diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/generator/CLIChunkGenerator.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/generator/CLIChunkGenerator.java deleted file mode 100644 index 0b58929b3..000000000 --- a/platforms/cli/src/main/java/com/dfsek/terra/cli/generator/CLIChunkGenerator.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.cli.generator; - -import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; - - -public class CLIChunkGenerator implements GeneratorWrapper { - @Override - public ChunkGenerator getHandle() { - return null; - } -} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/Region.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/Region.java index 0f644d515..9d84ce197 100644 --- a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/Region.java +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/Region.java @@ -16,7 +16,6 @@ public class Region implements NBTSerializable { this.z = z; this.world = world; this.chunks = new CLIChunk[32 * 32]; - ; } public CLIChunk get(int x, int z) { From 46c03438b3708cda0a2f52d3150e1793033cea13 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 17 Jun 2022 01:34:11 -0700 Subject: [PATCH 123/220] add optimization for AdjacentPatternLocator --- .../locators/AdjacentPatternLocator.java | 21 ++++++++++++------- .../locator/patterns/MatchPattern.java | 19 +++++++++++++++-- .../feature/locator/patterns/Pattern.java | 9 ++++++++ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java index 55fc2c2b3..ab1de182f 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java @@ -11,6 +11,8 @@ import com.dfsek.terra.addons.feature.locator.patterns.Pattern; import com.dfsek.terra.api.structure.feature.BinaryColumn; import com.dfsek.terra.api.structure.feature.Locator; import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.World; +import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.chunk.generation.util.Column; @@ -31,16 +33,19 @@ public class AdjacentPatternLocator implements Locator { } private boolean isValid(int y, Column column) { + WritableWorld world = column.getWorld(); + int x = column.getX(); + int z = column.getZ(); if(matchAll) { - return pattern.matches(y, column.adjacent(0, -1)) && - pattern.matches(y, column.adjacent(0, 1)) && - pattern.matches(y, column.adjacent(-1, 0)) && - pattern.matches(y, column.adjacent(1, 0)); + return pattern.matches(world, x, y, z - 1) && + pattern.matches(world, x, y, z + 1) && + pattern.matches(world, x - 1, y, z) && + pattern.matches(world, x + 1, y, z); } else { - return pattern.matches(y, column.adjacent(0, -1)) || - pattern.matches(y, column.adjacent(0, 1)) || - pattern.matches(y, column.adjacent(-1, 0)) || - pattern.matches(y, column.adjacent(1, 0)); + return pattern.matches(world, x, y, z - 1) || + pattern.matches(world, x, y, z + 1) || + pattern.matches(world, x - 1, y, z) || + pattern.matches(world, x + 1, y, z); } } } diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java index ecc3d50ae..8e58eddb7 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java @@ -7,14 +7,18 @@ package com.dfsek.terra.addons.feature.locator.patterns; +import com.dfsek.terra.api.world.ServerWorld; + +import com.dfsek.terra.api.world.WritableWorld; + +import net.jafama.FastMath; + import java.util.function.Predicate; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.world.chunk.generation.util.Column; -import net.jafama.FastMath; - public class MatchPattern implements Pattern { private final Range range; @@ -35,4 +39,15 @@ public class MatchPattern implements Pattern { } return true; } + + @Override + public boolean matches(WritableWorld world, int x, int y, int z) { + int min = FastMath.max(world.getMinHeight(), range.getMin() + y); + int max = FastMath.min(world.getMinHeight(), range.getMax() + y); + if(max <= min) return false; + for(int i = min; i < max; i++) { + if(!matches.test(world.getBlockState(x, y, z))) return false; + } + return true; + } } diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java index dbe909943..86850378e 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java @@ -7,12 +7,21 @@ package com.dfsek.terra.addons.feature.locator.patterns; +import com.dfsek.terra.api.world.ReadableWorld; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.World; +import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.chunk.generation.util.Column; public interface Pattern { boolean matches(int y, Column column); + default boolean matches(WritableWorld world, int x, int y, int z) { + return matches(y, world.column(x, z)); + } + + default Pattern and(Pattern that) { return (y, column) -> this.matches(y, column) && that.matches(y, column); } From 21ec335db97388d8e3ccbd4212cafa2ac15155d1 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 17 Jun 2022 01:44:21 -0700 Subject: [PATCH 124/220] store cache between same column instances with different clamps --- .../terra/api/world/chunk/generation/util/Column.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index 962e77084..cf4ff761f 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -30,16 +30,20 @@ public class Column { private final BlockState[] cache; public Column(int x, int z, T world) { - this(x, z, world, world.getMinHeight(), world.getMaxHeight()); + this(x, z, world, world.getMinHeight(), world.getMaxHeight(), new BlockState[world.getMaxHeight() - world.getMinHeight()]); } public Column(int x, int z, T world, int min, int max) { + this(x, z, world, min, max, new BlockState[world.getMaxHeight() - world.getMinHeight()]); + } + + private Column(int x, int z, T world, int min, int max, BlockState[] cache) { this.x = x; this.z = z; this.world = world; this.max = max; this.min = min; - this.cache = new BlockState[world.getMaxHeight() - world.getMinHeight()]; + this.cache = cache; } public int getX() { @@ -80,7 +84,7 @@ public class Column { public Column clamp(int min, int max) { if(min >= max) throw new IllegalArgumentException("Min greater than or equal to max: " + min + ", " + max); - return new Column<>(x, z, world, min, max); + return new Column<>(x, z, world, min, max, cache); } public BinaryColumn newBinaryColumn(IntToBooleanFunction function) { From 4dd43ea86d8be7a0331532bca2d0df5d402bf879 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 17 Jun 2022 16:28:32 -0700 Subject: [PATCH 125/220] collapse single-entry probability collections to singletons --- .../terra/config/loaders/ProbabilityCollectionLoader.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java index 01cda5c4b..902bc16d4 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java @@ -49,6 +49,14 @@ public class ProbabilityCollectionLoader implements TypeLoader> map = (List>) o; + if(map.size() == 1) { + Map entry = map.get(0); + if(entry.size() == 1) { + for(Object value : entry.keySet()) { + return new ProbabilityCollection.Singleton<>(configLoader.loadType(generic, value, depthTracker)); + } + } + } for(int i = 0; i < map.size(); i++) { Map l = map.get(i); for(Entry entry : l.entrySet()) { From 915dcf9b9b0a5e5ee7fdc9d95f9bab60c3f010bd Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 17 Jun 2022 17:39:27 -0700 Subject: [PATCH 126/220] cache biome providers on Bukkit --- .../BukkitChunkGeneratorWrapper.java | 37 ++++++++++++++++--- .../terra/bukkit/world/BukkitProtoWorld.java | 9 ++--- .../bukkit/world/BukkitWorldProperties.java | 13 +++++++ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java index ac7444da2..98a89f136 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java @@ -17,11 +17,13 @@ package com.dfsek.terra.bukkit.generator; -import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; +import com.dfsek.terra.api.world.biome.generation.ChunkLocalCachingBiomeProvider; +import com.dfsek.terra.api.world.info.WorldProperties; -import org.bukkit.Location; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import org.bukkit.World; -import org.bukkit.block.data.BlockData; import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.LimitedRegion; @@ -49,6 +51,31 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener private final BlockState air; private ChunkGenerator delegate; private ConfigPack pack; + private final LoadingCache biomeProviderCache = CacheBuilder.newBuilder() + .maximumSize(128) + .build(new CacheLoader<>() { + @Override + public @NotNull ChunkLocalCachingBiomeProvider load(@NotNull SeededVector key) { + return pack.getBiomeProvider().caching(key.worldProperties, key.x, key.z); + } + }); + + private record SeededVector(int x, int z, WorldProperties worldProperties) { + @Override + public boolean equals(Object obj) { + if(obj instanceof SeededVector that) { + return this.z == that.z && this.x == that.x && this.worldProperties.equals(that.worldProperties); + } + return false; + } + + @Override + public int hashCode() { + int code = x; + code = 31 * code + z; + return 31 * code + worldProperties.hashCode(); + } + } public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack, BlockState air) { this.delegate = delegate; @@ -68,7 +95,7 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener @Override public void generateNoise(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull ChunkData chunkData) { BukkitWorldProperties properties = new BukkitWorldProperties(worldInfo); - delegate.generateChunkData(new BukkitProtoChunk(chunkData), properties, pack.getBiomeProvider().caching(properties), x, z); + delegate.generateChunkData(new BukkitProtoChunk(chunkData), properties, biomeProviderCache.getUnchecked(new SeededVector(x, z, new BukkitWorldProperties(worldInfo))), x, z); } @Override @@ -79,7 +106,7 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener @Override public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull LimitedRegion limitedRegion) { - generationStage.populate(new BukkitProtoWorld(limitedRegion, air)); + generationStage.populate(new BukkitProtoWorld(limitedRegion, air, biomeProviderCache.getUnchecked(new SeededVector(x, z, new BukkitWorldProperties(worldInfo))))); } }) .collect(Collectors.toList()); diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java index b2ad43954..f544ba3c2 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java @@ -1,7 +1,5 @@ package com.dfsek.terra.bukkit.world; -import com.dfsek.terra.api.util.generic.Lazy; - import com.dfsek.terra.api.world.biome.generation.ChunkLocalCachingBiomeProvider; import org.bukkit.Location; @@ -35,13 +33,12 @@ public class BukkitProtoWorld implements ProtoWorld { private final LimitedRegion delegate; private final BlockState air; - private final ChunkLocalCachingBiomeProvider biomeProvider; + private final BiomeProvider biomeProvider; - public BukkitProtoWorld(LimitedRegion delegate, BlockState air) { + public BukkitProtoWorld(LimitedRegion delegate, BlockState air, BiomeProvider provider) { this.delegate = delegate; this.air = air; - this.biomeProvider = ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack().getBiomeProvider().caching(new BukkitWorldProperties( - delegate.getWorld()), delegate.getCenterChunkX(), delegate.getCenterChunkZ()); + this.biomeProvider = provider; } @Override 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 e324a62d7..7bd4106c6 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 @@ -31,4 +31,17 @@ public class BukkitWorldProperties implements WorldProperties { public int getMinHeight() { return delegate.getMinHeight(); } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(obj instanceof WorldProperties that) { + return this.delegate.equals(that.getHandle()); + } + return false; + } } From 522d4e4d3ac0ef90d9534551edbbe371c5221c4d Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 17 Jun 2022 17:51:30 -0700 Subject: [PATCH 127/220] use vanilla getBaseColumn --- .../bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java | 7 +++++-- .../bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java index 0f8504c44..b4ee58521 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java @@ -81,7 +81,7 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { return vanilla.getSeaLevel(); } - @Override //fillFromNoise + @Override public @NotNull CompletableFuture fillFromNoise(@NotNull Executor executor, @NotNull Blender blender, @NotNull StructureFeatureManager structureAccessor, @NotNull ChunkAccess chunk) { return vanilla.fillFromNoise(executor, blender, structureAccessor, chunk); @@ -97,8 +97,9 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { return ChunkGenerator.CODEC; } - @Override // getColumn + @Override public @NotNull NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height) { + /* BlockState[] array = new BlockState[height.getHeight()]; WorldProperties properties = new NMSWorldProperties(seed, height); BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); @@ -107,6 +108,8 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { .getHandle()).getState(); } return new NoiseColumn(getMinY(), array); + */ + return vanilla.getBaseColumn(x, z, height); } @Override // withSeed diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java index b95a7f53c..f99530f5a 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java @@ -16,6 +16,7 @@ import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeManager; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkGenerator; @@ -33,6 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; @@ -129,6 +131,7 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { @Override public @NotNull NoiseColumn getBaseColumn(int x, int z, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) { + /* BlockState[] array = new BlockState[world.getHeight()]; WorldProperties properties = new NMSWorldProperties(seed, world); BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); @@ -137,6 +140,9 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { .getHandle()).getState(); } return new NoiseColumn(getMinY(), array); + + */ + return vanilla.getBaseColumn(x, z, world, noiseConfig); } @Override From 1d8c012ae5598d533a6f8195ea289de00104e5fe Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 00:56:58 -0700 Subject: [PATCH 128/220] fix MatchPattern --- .../terra/addons/feature/locator/patterns/MatchPattern.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java index 8e58eddb7..111744cd9 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java @@ -43,10 +43,10 @@ public class MatchPattern implements Pattern { @Override public boolean matches(WritableWorld world, int x, int y, int z) { int min = FastMath.max(world.getMinHeight(), range.getMin() + y); - int max = FastMath.min(world.getMinHeight(), range.getMax() + y); + int max = FastMath.min(world.getMaxHeight(), range.getMax() + y); if(max <= min) return false; for(int i = min; i < max; i++) { - if(!matches.test(world.getBlockState(x, y, z))) return false; + if(!matches.test(world.getBlockState(x, i, z))) return false; } return true; } From 4c6c284b9352b84311aecaa224a127e241764106 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 01:10:18 -0700 Subject: [PATCH 129/220] properly clamp max Y in LazilyEvaluatedInterpolator --- .../math/interpolation/LazilyEvaluatedInterpolator.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java index 0b6bf41bf..908a185f1 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java @@ -23,7 +23,7 @@ public class LazilyEvaluatedInterpolator { private final PropertyKey noisePropertiesKey; private final long seed; - private final int min; + private final int min, max; private final int zMul, yMul; public LazilyEvaluatedInterpolator(BiomeProvider biomeProvider, int cx, int cz, int max, @@ -42,6 +42,7 @@ public class LazilyEvaluatedInterpolator { this.biomeProvider = biomeProvider; this.seed = seed; this.min = min; + this.max = max; } private double sample(int xIndex, int yIndex, int zIndex, int ox, int oy, int oz) { @@ -51,12 +52,14 @@ public class LazilyEvaluatedInterpolator { int xi = ox + chunkX; int zi = oz + chunkZ; + int y = FastMath.min(max, oy); + sample = biomeProvider - .getBiome(xi, oy, zi, seed) + .getBiome(xi, y, zi, seed) .getContext() .get(noisePropertiesKey) .carving() - .noise(seed, xi, oy, zi); + .noise(seed, xi, y, zi); samples[index] = sample; } return sample; From 6a95810e6546e1f7b8c28230af7b05c14ac4a49e Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 01:16:36 -0700 Subject: [PATCH 130/220] use max-1 as max Y in LazilyEvaluatedInterpolator --- .../math/interpolation/LazilyEvaluatedInterpolator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java index 908a185f1..97a6a147c 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java @@ -42,7 +42,7 @@ public class LazilyEvaluatedInterpolator { this.biomeProvider = biomeProvider; this.seed = seed; this.min = min; - this.max = max; + this.max = max - 1; } private double sample(int xIndex, int yIndex, int zIndex, int ox, int oy, int oz) { From 642372eaa1b31dabb017ab8608a8495773fed94f Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 01:28:48 -0700 Subject: [PATCH 131/220] add caffeine as API --- common/api/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/api/build.gradle.kts b/common/api/build.gradle.kts index b31c8b89e..fae96eac5 100644 --- a/common/api/build.gradle.kts +++ b/common/api/build.gradle.kts @@ -5,6 +5,6 @@ dependencies { api("com.dfsek.tectonic", "common", Versions.Libraries.tectonic) - + api("com.github.ben-manes.caffeine:caffeine:3.1.0") implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) } \ No newline at end of file From 7de66fecf8db90cf8b774356aa6915499c87c380 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 02:01:06 -0700 Subject: [PATCH 132/220] remove ChunkLocalCachingBiomeProvider --- .../world/biome/generation/BiomeProvider.java | 16 +-- .../generation/CachingBiomeProvider.java | 80 ++++++++---- .../ChunkLocalCachingBiomeProvider.java | 118 ------------------ .../BukkitChunkGeneratorWrapper.java | 16 +-- .../terra/bukkit/world/BukkitProtoWorld.java | 2 - .../v1_18_R2/NMSChunkGeneratorDelegate.java | 2 +- .../v1_19_R1/NMSChunkGeneratorDelegate.java | 2 +- .../com/dfsek/terra/cli/world/CLIWorld.java | 4 +- .../FabricChunkGeneratorWrapper.java | 12 +- .../terra/world/ChunkRegionMixin.java | 19 +-- 10 files changed, 71 insertions(+), 200 deletions(-) delete mode 100644 common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index ed83669ae..09c6f3dbd 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -92,17 +92,13 @@ public interface BiomeProvider { return StreamSupport.stream(getBiomes().spliterator(), false); } - default CachingBiomeProvider caching(int minY, int maxY) { - return new CachingBiomeProvider(this, minY, maxY); - } - - default CachingBiomeProvider caching(WorldProperties worldProperties) { - return caching(worldProperties.getMinHeight(), worldProperties.getMaxHeight()); - } - - default ChunkLocalCachingBiomeProvider caching(WorldProperties worldProperties, int chunkX, int chunkZ) { - return new ChunkLocalCachingBiomeProvider(this, worldProperties, chunkX, chunkZ); + default CachingBiomeProvider caching() { + if(this instanceof CachingBiomeProvider cachingBiomeProvider) { + return cachingBiomeProvider; + } + return new CachingBiomeProvider(this); } + default int resolution() { return 1; diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index cb2781509..0cd489960 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -1,14 +1,11 @@ package com.dfsek.terra.api.world.biome.generation; import com.dfsek.terra.api.Handle; -import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.util.MathUtil; -import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.api.world.info.WorldProperties; -import java.util.HashMap; -import java.util.Map; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; + import java.util.Optional; @@ -19,15 +16,23 @@ import java.util.Optional; */ public class CachingBiomeProvider implements BiomeProvider, Handle { protected final BiomeProvider delegate; - protected final int minY; - protected final int maxY; - private final Map cache = new HashMap<>(); - private final Map> columnCache = new HashMap<>(); + private final int res; + private final LoadingCache cache; + private final LoadingCache> baseCache; - protected CachingBiomeProvider(BiomeProvider delegate, int minY, int maxY) { + protected CachingBiomeProvider(BiomeProvider delegate) { this.delegate = delegate; - this.minY = minY; - this.maxY = maxY; + this.res = delegate.resolution(); + this.cache = Caffeine + .newBuilder() + .maximumSize(98304) // 1 full chunk (high res) + .build(vec -> delegate.getBiome(vec.x * res, vec.y * res, vec.z * res, vec.seed)); + + this.baseCache = Caffeine + .newBuilder() + .maximumSize(256) // 1 full chunk (high res) + .build(vec -> delegate.getBaseBiome(vec.x * res, vec.z * res, vec.seed)); + } @Override @@ -37,23 +42,12 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { @Override public Biome getBiome(int x, int y, int z, long seed) { - if(y >= maxY || y < minY) throw new IllegalArgumentException("Y out of range: " + y + " (min: " + minY + ", max: " + maxY + ")"); - Biome[] biomes = cache.computeIfAbsent(MathUtil.squash(x, z), key -> new Biome[maxY - minY]); - int yi = y - minY; - if(biomes[yi] == null) { - biomes[yi] = delegate.getBiome(x, y, z, seed); - } - return biomes[yi]; + return cache.get(new SeededVector3(x / res, y / res, z / res, seed)); } @Override public Optional getBaseBiome(int x, int z, long seed) { - return delegate.getBaseBiome(x, z, seed); - } - - @Override - public Column getColumn(int x, int z, long seed, int min, int max) { - return columnCache.computeIfAbsent(MathUtil.squash(x, z), k -> new BiomeColumn(this, min, max, x, z, seed)); + return baseCache.get(new SeededVector2(x / res, z / res, seed)); } @Override @@ -65,4 +59,38 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { public int resolution() { return delegate.resolution(); } + + private record SeededVector3(int x, int y, int z, long seed) { + @Override + public boolean equals(Object obj) { + if(obj instanceof SeededVector3 that) { + return this.y == that.y && this.z == that.z && this.x == that.x && this.seed == that.seed; + } + return false; + } + + @Override + public int hashCode() { + int code = x; + code = 31 * code + y; + code = 31 * code + z; + return 31 * code + ((int) (seed ^ (seed >>> 32))); + } + } + private record SeededVector2(int x, int z, long seed) { + @Override + public boolean equals(Object obj) { + if(obj instanceof SeededVector2 that) { + return this.z == that.z && this.x == that.x && this.seed == that.seed; + } + return false; + } + + @Override + public int hashCode() { + int code = x; + code = 31 * code + z; + return 31 * code + ((int) (seed ^ (seed >>> 32))); + } + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java deleted file mode 100644 index 4e365b453..000000000 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/ChunkLocalCachingBiomeProvider.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.dfsek.terra.api.world.biome.generation; - -import net.jafama.FastMath; - -import java.util.Optional; - -import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.api.world.info.WorldProperties; - - -/** - * A biome provider implementation that lazily evaluates biomes, and caches them. - *

- * This is for use in chunk generators, it makes the assumption that the seed remains the same for the duration of its use! - *

- * The cache works the best when all biomes are within one chunk! This is because internally, there are two caches, one constant-size one - * for the chunk, and a slower dynamically-sized cache for out-of-chunk biomes. - */ -public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { - private final BiomeChunk[] chunks = new BiomeChunk[9]; - private final Column[] columnCache; // x + z * 16 - - private final int chunkX; - private final int chunkZ; - private final int height; - - private final int zMul; - private final int yMul; - private final int resolution; - - protected ChunkLocalCachingBiomeProvider(BiomeProvider delegate, WorldProperties worldProperties, int chunkX, int chunkZ) { - super(delegate, worldProperties.getMinHeight(), worldProperties.getMaxHeight()); - this.height = maxY - minY; - this.chunkX = chunkX; - this.chunkZ = chunkZ; - this.resolution = delegate.resolution(); - this.zMul = 16 / resolution; - this.yMul = zMul * zMul; - this.columnCache = new Column[yMul]; - } - - @Override - public BiomeProvider getHandle() { - return delegate; - } - - @Override - public Biome getBiome(int x, int y, int z, long seed) { - int localChunkX = FastMath.floorDiv(x, 16) - this.chunkX + 1; - int localChunkZ = FastMath.floorDiv(z, 16) - this.chunkZ + 1; - - - if(localChunkX >= 0 && localChunkZ >= 0 && localChunkX <= 2 && localChunkZ <= 2) { - int chunkIndex = localChunkX + localChunkZ * 3; - - BiomeChunk chunk = chunks[chunkIndex]; - if(chunk == null) { - chunk = new BiomeChunk(height / resolution, yMul); - chunks[chunkIndex] = chunk; - } - - int scaledX = FastMath.floorDiv(x & 15, resolution); - int scaledY = FastMath.floorDiv(y - minY, resolution); - int scaledZ = FastMath.floorDiv(z & 15, resolution); - - int biomeIndex = scaledX + zMul * scaledZ + yMul * scaledY; - Biome biome = chunk.cache[biomeIndex]; - if(biome == null) { - biome = delegate.getBiome(x, y, z, seed); - chunk.cache[biomeIndex] = biome; - } - return biome; - } - - return super.getBiome(x, y, z, seed); - } - - @Override - public Optional getBaseBiome(int x, int z, long seed) { - return delegate.getBaseBiome(x, z, seed); - } - - @Override - public Column getColumn(int x, int z, long seed, int min, int max) { - int scaledX = (x & 15) / resolution; - int scaledZ = (z & 15) / resolution; - - if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) { - int index = scaledX + (zMul * scaledZ); - Column column = columnCache[index]; - if(column == null) { - column = new BiomeColumn(this, min, max, x, z, seed); - columnCache[index] = column; - } - return column; - } - return super.getColumn(x, z, seed, min, max); - } - - @Override - public Iterable getBiomes() { - return delegate.getBiomes(); - } - - @Override - public int resolution() { - return resolution; - } - - private static class BiomeChunk { - final Biome[] cache; // x + z * 16 + y * 256 - - private BiomeChunk(int height, int widthSq) { - this.cache = new Biome[widthSq * height]; - } - } -} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java index 98a89f136..a1c7a6ef1 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java @@ -17,12 +17,8 @@ package com.dfsek.terra.bukkit.generator; -import com.dfsek.terra.api.world.biome.generation.ChunkLocalCachingBiomeProvider; import com.dfsek.terra.api.world.info.WorldProperties; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import org.bukkit.World; import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BlockPopulator; @@ -51,14 +47,6 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener private final BlockState air; private ChunkGenerator delegate; private ConfigPack pack; - private final LoadingCache biomeProviderCache = CacheBuilder.newBuilder() - .maximumSize(128) - .build(new CacheLoader<>() { - @Override - public @NotNull ChunkLocalCachingBiomeProvider load(@NotNull SeededVector key) { - return pack.getBiomeProvider().caching(key.worldProperties, key.x, key.z); - } - }); private record SeededVector(int x, int z, WorldProperties worldProperties) { @Override @@ -95,7 +83,7 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener @Override public void generateNoise(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull ChunkData chunkData) { BukkitWorldProperties properties = new BukkitWorldProperties(worldInfo); - delegate.generateChunkData(new BukkitProtoChunk(chunkData), properties, biomeProviderCache.getUnchecked(new SeededVector(x, z, new BukkitWorldProperties(worldInfo))), x, z); + delegate.generateChunkData(new BukkitProtoChunk(chunkData), properties, pack.getBiomeProvider(), x, z); } @Override @@ -106,7 +94,7 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener @Override public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull LimitedRegion limitedRegion) { - generationStage.populate(new BukkitProtoWorld(limitedRegion, air, biomeProviderCache.getUnchecked(new SeededVector(x, z, new BukkitWorldProperties(worldInfo))))); + generationStage.populate(new BukkitProtoWorld(limitedRegion, air, pack.getBiomeProvider())); } }) .collect(Collectors.toList()); diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java index f544ba3c2..52b3c5855 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java @@ -1,7 +1,5 @@ package com.dfsek.terra.bukkit.world; -import com.dfsek.terra.api.world.biome.generation.ChunkLocalCachingBiomeProvider; - import org.bukkit.Location; import org.bukkit.generator.LimitedRegion; import org.slf4j.Logger; diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java index b4ee58521..4bc41052c 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java @@ -141,7 +141,7 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { public int getBaseHeight(int x, int z, Heightmap.@NotNull Types heightmap, @NotNull LevelHeightAccessor world) { WorldProperties properties = new NMSWorldProperties(seed, world); int y = properties.getMaxHeight(); - BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); + BiomeProvider biomeProvider = pack.getBiomeProvider(); while(y >= getMinY() && !heightmap.isOpaque().test( ((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) { y--; diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java index f99530f5a..860bfa5a0 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java @@ -121,7 +121,7 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { public int getBaseHeight(int x, int z, @NotNull Types heightmap, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) { WorldProperties properties = new NMSWorldProperties(seed, world); int y = properties.getMaxHeight(); - BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); + BiomeProvider biomeProvider = pack.getBiomeProvider(); while(y >= getMinY() && !heightmap.isOpaque().test( ((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) { y--; diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java index 4191ba5a8..e281efd0e 100644 --- a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java @@ -1,7 +1,5 @@ package com.dfsek.terra.cli.world; -import com.dfsek.terra.api.world.biome.generation.ChunkLocalCachingBiomeProvider; - import com.google.common.collect.Streams; import net.jafama.FastMath; import net.querz.mca.MCAFile; @@ -87,7 +85,7 @@ public class CLIWorld implements ServerWorld, NBTSerializable stage.populate(protoWorld)); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index a452fdc07..92a6a17f0 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -95,9 +95,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C if(chunk instanceof net.minecraft.world.chunk.ProtoChunk) { ChunkPos pos = chunk.getPos(); ((BiomeProviderHolder) chunk) - .terra$setHeldBiomeProvider(pack.getBiomeProvider() - .caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(), pos.x, - pos.z)); + .terra$setHeldBiomeProvider(pack.getBiomeProvider()); } return super.populateBiomes(biomeRegistry, executor, noiseConfig, blender, structureAccessor, chunk); } @@ -142,10 +140,10 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C if(chunk instanceof BiomeProviderHolder providerHolder) { biomeProvider = providerHolder.terra$getHeldBiomeProvider(); if(biomeProvider == null) { - biomeProvider = pack.getBiomeProvider().caching(world, chunk.getPos().x, chunk.getPos().z); + biomeProvider = pack.getBiomeProvider(); } } else { - biomeProvider = pack.getBiomeProvider().caching(world, chunk.getPos().x, chunk.getPos().z); + biomeProvider = pack.getBiomeProvider(); } delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z); @@ -208,7 +206,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public int getHeight(int x, int z, Type heightmap, HeightLimitView height, NoiseConfig noiseConfig) { WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); - BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); + BiomeProvider biomeProvider = pack.getBiomeProvider(); int min = height.getBottomY(); for(int y = height.getTopY() - 1; y >= min; y--) { if(heightmap @@ -222,7 +220,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height, NoiseConfig noiseConfig) { BlockState[] array = new BlockState[height.getHeight()]; WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); - BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); + BiomeProvider biomeProvider = pack.getBiomeProvider(); for(int y = height.getTopY() - 1; y >= height.getBottomY(); y--) { array[y - height.getBottomY()] = (BlockState) delegate.getBlock(properties, x, y, z, biomeProvider); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java index 2c6f0253b..2ae60ac90 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -75,26 +75,13 @@ public abstract class ChunkRegionMixin { @Final private MultiTickScheduler fluidTickScheduler; - @Shadow - public abstract net.minecraft.server.world.ServerWorld toServerWorld(); - @Shadow - public abstract Chunk getChunk(int chunkX, int chunkZ); - - private Lazy caching; - - @SuppressWarnings("deprecation") @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) { this.terra$config = ((ServerWorld) world).getPack(); - this.caching = Lazy.lazy(() -> ((TerraBiomeSource) ((ChunkRegion) (Object) this) - .toServerWorld() - .getChunkManager() - .getChunkGenerator() - .getBiomeSource()).getProvider().caching((ProtoWorld) this)); } @@ -137,11 +124,7 @@ public abstract class ChunkRegionMixin { } public BiomeProvider terraWorld$getBiomeProvider() { - BiomeProvider provider = ((BiomeProviderHolder) this).terra$getHeldBiomeProvider(); - if(provider != null) { - return provider; - } - return caching.value(); + return terra$config.getBiomeProvider(); } public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { From 8a2024e8d83e9e66765efefb09e5a2eb681f7011 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 02:02:38 -0700 Subject: [PATCH 133/220] remove BiomeProviderHolder --- .../FabricChunkGeneratorWrapper.java | 22 +-------- .../cache/ChunkRegionMixin.java | 47 ------------------- .../cache/ProtoChunkMixin.java | 27 ----------- .../terra/world/ChunkRegionMixin.java | 3 -- .../mixin_ifaces/BiomeProviderHolder.java | 10 ---- .../src/main/resources/terra.mixins.json | 2 - 6 files changed, 1 insertion(+), 110 deletions(-) delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ChunkRegionMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ProtoChunkMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/BiomeProviderHolder.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 92a6a17f0..04e87e4bc 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -64,7 +64,6 @@ import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; import com.dfsek.terra.fabric.data.Codecs; import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; -import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; import com.dfsek.terra.fabric.util.FabricAdapter; @@ -89,17 +88,6 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C this.biomeSource = biomeSource; } - @Override - public CompletableFuture populateBiomes(Registry biomeRegistry, Executor executor, NoiseConfig noiseConfig, - Blender blender, StructureAccessor structureAccessor, Chunk chunk) { - if(chunk instanceof net.minecraft.world.chunk.ProtoChunk) { - ChunkPos pos = chunk.getPos(); - ((BiomeProviderHolder) chunk) - .terra$setHeldBiomeProvider(pack.getBiomeProvider()); - } - return super.populateBiomes(biomeRegistry, executor, noiseConfig, blender, structureAccessor, chunk); - } - public Registry getNoiseRegistry() { return noiseRegistry; } @@ -136,15 +124,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C StructureAccessor structureAccessor, Chunk chunk) { return CompletableFuture.supplyAsync(() -> { ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); - BiomeProvider biomeProvider; - if(chunk instanceof BiomeProviderHolder providerHolder) { - biomeProvider = providerHolder.terra$getHeldBiomeProvider(); - if(biomeProvider == null) { - biomeProvider = pack.getBiomeProvider(); - } - } else { - biomeProvider = pack.getBiomeProvider(); - } + BiomeProvider biomeProvider = pack.getBiomeProvider(); delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z); PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ChunkRegionMixin.java deleted file mode 100644 index f16ca763d..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ChunkRegionMixin.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations.cache; - -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.api.world.chunk.Chunk; -import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; - -import net.minecraft.server.world.ServerWorld; -import net.minecraft.world.ChunkRegion; -import net.minecraft.world.chunk.ChunkStatus; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -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; - -import java.util.List; - - -@Mixin(ChunkRegion.class) -@Implements(@Interface(iface = BiomeProviderHolder.class, prefix = "provider$")) -public class ChunkRegionMixin { - @Shadow - @Final - private net.minecraft.world.chunk.Chunk centerPos; - private BiomeProvider biomeProvider; - - @Inject(method = "", at = @At("RETURN")) - public void addProvider(ServerWorld world, List chunks, ChunkStatus status, int placementRadius, CallbackInfo ci) { - if(centerPos instanceof BiomeProviderHolder providerHolder) { - biomeProvider = providerHolder.terra$getHeldBiomeProvider(); - } - } - - public void provider$terra$setHeldBiomeProvider(BiomeProvider provider) { - if(this.biomeProvider != null) { - throw new IllegalStateException("Already set biome provider for chunk " + this); - } - this.biomeProvider = provider; - } - - public BiomeProvider provider$terra$getHeldBiomeProvider() { - return biomeProvider; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ProtoChunkMixin.java deleted file mode 100644 index f212c8866..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/cache/ProtoChunkMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations.cache; - -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; - -import net.minecraft.world.chunk.ProtoChunk; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - - -@Mixin(ProtoChunk.class) -@Implements(@Interface(iface = BiomeProviderHolder.class, prefix = "provider$")) -public class ProtoChunkMixin { - private BiomeProvider biomeProvider; - - public void provider$terra$setHeldBiomeProvider(BiomeProvider provider) { - if(this.biomeProvider != null) { - throw new IllegalStateException("Already set biome provider for chunk " + this); - } - this.biomeProvider = provider; - } - - public BiomeProvider provider$terra$getHeldBiomeProvider() { - return biomeProvider; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java index 2ae60ac90..7a5ebf822 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -43,14 +43,11 @@ import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.EntityType; -import com.dfsek.terra.api.util.generic.Lazy; import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.generation.TerraBiomeSource; -import com.dfsek.terra.fabric.mixin_ifaces.BiomeProviderHolder; import com.dfsek.terra.fabric.util.FabricUtil; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/BiomeProviderHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/BiomeProviderHolder.java deleted file mode 100644 index ce0865420..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/BiomeProviderHolder.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.fabric.mixin_ifaces; - -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; - - -public interface BiomeProviderHolder { - void terra$setHeldBiomeProvider(BiomeProvider biomeProvider); - - BiomeProvider terra$getHeldBiomeProvider(); -} diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 417a4fed7..4e8614ba3 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -10,8 +10,6 @@ "access.StructureAccessorAccessor", "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", "fix.NetherFossilOptimization", - "implementations.cache.ChunkRegionMixin", - "implementations.cache.ProtoChunkMixin", "implementations.compat.GenerationSettingsFloraFeaturesMixin", "implementations.terra.BiomeMixin", "implementations.terra.HandleImplementationMixin", From 78d34498d9c00dafffcb8f49134db676e67c54c5 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 02:33:25 -0700 Subject: [PATCH 134/220] add caching option to config pack --- .../api/world/biome/generation/CachingBiomeProvider.java | 3 +++ .../java/com/dfsek/terra/config/pack/ConfigPackImpl.java | 2 +- .../com/dfsek/terra/config/pack/ConfigPackTemplate.java | 8 ++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index 0cd489960..e503dd54c 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -5,6 +5,7 @@ import com.dfsek.terra.api.world.biome.Biome; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; +import com.github.benmanes.caffeine.cache.Scheduler; import java.util.Optional; @@ -25,6 +26,8 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { this.res = delegate.resolution(); this.cache = Caffeine .newBuilder() + .scheduler(Scheduler.disabledScheduler()) + .initialCapacity(98304) .maximumSize(98304) // 1 full chunk (high res) .build(vec -> delegate.getBiome(vec.x * res, vec.y * res, vec.z * res, vec.seed)); diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java index 887e697ae..9061b8d0c 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java @@ -231,7 +231,7 @@ public class ConfigPackImpl implements ConfigPack { ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate(); selfLoader.load(packPostTemplate, packManifest); - seededBiomeProvider = packPostTemplate.getProviderBuilder(); + seededBiomeProvider = template.getBiomeCache() ? packPostTemplate.getProviderBuilder().caching() : packPostTemplate.getProviderBuilder(); checkDeadEntries(); } diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java index b41005a25..3aa0a8c27 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java @@ -107,6 +107,10 @@ public class ConfigPackTemplate implements ConfigTemplate { @Value("generator") private @Meta ChunkGeneratorProvider generatorProvider; + @Value("cache.biome.enable") + @Default + private boolean biomeCache = false; + public boolean disableCarvers() { return disableCarvers; } @@ -182,4 +186,8 @@ public class ConfigPackTemplate implements ConfigTemplate { public Map getLocatable() { return locatable; } + + public boolean getBiomeCache() { + return biomeCache; + } } From c49202017fb204b5c97f5a8e7c04be79b5832afe Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 03:14:53 -0700 Subject: [PATCH 135/220] implement BaseBiomeColumn --- .../biome/extrusion/BaseBiomeColumn.java | 51 +++++++++++++++++++ .../extrusion/BiomeExtrusionProvider.java | 19 +++++-- 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BaseBiomeColumn.java diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BaseBiomeColumn.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BaseBiomeColumn.java new file mode 100644 index 000000000..6dcad812f --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BaseBiomeColumn.java @@ -0,0 +1,51 @@ +package com.dfsek.terra.addons.biome.extrusion; + +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.world.biome.Biome; + + +class BaseBiomeColumn implements Column { + private final BiomeExtrusionProvider biomeProvider; + private final Biome base; + private final int min; + private final int max; + + private final int x; + private final int z; + private final long seed; + + protected BaseBiomeColumn(BiomeExtrusionProvider biomeProvider, Biome base, int min, int max, int x, int z, long seed) { + this.biomeProvider = biomeProvider; + this.base = base; + this.min = min; + this.max = max; + this.x = x; + this.z = z; + this.seed = seed; + } + + @Override + public int getMinY() { + return min; + } + + @Override + public int getMaxY() { + return max; + } + + @Override + public int getX() { + return x; + } + + @Override + public int getZ() { + return z; + } + + @Override + public Biome get(int y) { + return biomeProvider.extrude(base, x, y, z, seed); + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index 85a4cc72c..605063428 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -6,9 +6,12 @@ import java.util.Set; import java.util.stream.Collectors; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.github.benmanes.caffeine.cache.LoadingCache; + public class BiomeExtrusionProvider implements BiomeProvider { private final BiomeProvider delegate; @@ -27,12 +30,22 @@ public class BiomeExtrusionProvider implements BiomeProvider { @Override public Biome getBiome(int x, int y, int z, long seed) { Biome delegated = delegate.getBiome(x, y, z, seed); + + return extrude(delegated, x, y, z, seed); + } + public Biome extrude(Biome original, int x, int y, int z, long seed) { for(Extrusion extrusion : extrusions) { - delegated = extrusion.extrude(delegated, x, y, z, seed); + original = extrusion.extrude(original, x, y, z, seed); } - - return delegated; + return original; + } + + @Override + public Column getColumn(int x, int z, long seed, int min, int max) { + return delegate.getBaseBiome(x, z, seed) + .map(base -> (Column) new BaseBiomeColumn(this, base, min, max, x, z, seed)) + .orElseGet(() -> BiomeProvider.super.getColumn(x, z, seed, min, max)); } @Override From 15fec550c794abd1f6ab36fd53f1ce7a5d77f085 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 03:31:23 -0700 Subject: [PATCH 136/220] use column in ChunkInterpolator and NoiseChunkGenerator3D --- .../NoiseChunkGenerator3DAddon.java | 2 +- ...NoiseChunkGeneratorPackConfigTemplate.java | 25 --------------- .../generation/NoiseChunkGenerator3D.java | 31 +++---------------- .../math/interpolation/ChunkInterpolator.java | 6 +++- 4 files changed, 11 insertions(+), 53 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java index 45d2a6520..32bb4c628 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java @@ -49,7 +49,7 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { .getOrCreateRegistry(ChunkGeneratorProvider.class) .register(addon.key("NOISE_3D"), pack -> new NoiseChunkGenerator3D(platform, config.getElevationBlend(), config.getHorizontalRes(), - config.getVerticalRes(), config.getPaletteRes(), config.getPaletteBlendSampler(), config.getPaletteBlendAmplitude(), + config.getVerticalRes(), noisePropertiesPropertyKey, paletteInfoPropertyKey)); event.getPack() .applyLoader(SlantLayer.class, SlantLayer::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 b4b9afc98..e636ae400 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 @@ -5,7 +5,6 @@ import com.dfsek.tectonic.api.config.template.annotations.Default; import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.terra.api.config.meta.Meta; -import com.dfsek.terra.api.noise.NoiseSampler; public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate { @@ -13,18 +12,6 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate { @Default private @Meta int elevationBlend = 4; - @Value("blend.palette.resolution") - @Default - private @Meta int paletteRes = 1; - - @Value("blend.palette.sampler") - @Default - private @Meta NoiseSampler paletteBlendSampler = NoiseSampler.zero(); - - @Value("blend.palette.amplitude") - @Default - private @Meta double paletteBlendAmplitude = 0; - @Value("carving.resolution.horizontal") @Default private @Meta int horizontalRes = 4; @@ -44,16 +31,4 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate { public int getVerticalRes() { return verticalRes; } - - public double getPaletteBlendAmplitude() { - return paletteBlendAmplitude; - } - - public int getPaletteRes() { - return paletteRes; - } - - public NoiseSampler getPaletteBlendSampler() { - return paletteBlendSampler; - } } 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 7d6ae9841..5bb104239 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 @@ -18,6 +18,7 @@ import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.properties.PropertyKey; +import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.util.MathUtil; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; @@ -40,41 +41,22 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { private final int carverHorizontalResolution; private final int carverVerticalResolution; - private final int paletteRes; - - private final NoiseSampler paletteBlendSampler; - - private final double paletteBlendAmplitude; private final PropertyKey paletteInfoPropertyKey; private final PropertyKey noisePropertiesKey; public NoiseChunkGenerator3D(Platform platform, int elevationBlend, int carverHorizontalResolution, - int carverVerticalResolution, int paletteRes, NoiseSampler paletteBlendSampler, - double paletteBlendAmplitude, PropertyKey noisePropertiesKey, + int carverVerticalResolution, + PropertyKey noisePropertiesKey, PropertyKey paletteInfoPropertyKey) { this.platform = platform; this.air = platform.getWorldHandle().air(); this.carverHorizontalResolution = carverHorizontalResolution; this.carverVerticalResolution = carverVerticalResolution; - this.paletteRes = paletteRes; - this.paletteBlendSampler = paletteBlendSampler; - this.paletteBlendAmplitude = paletteBlendAmplitude; this.paletteInfoPropertyKey = paletteInfoPropertyKey; this.noisePropertiesKey = noisePropertiesKey; this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey); } - private Biome getBiome(int min, int max, double noiseX, double noiseZ, BiomeProvider biomeProvider, int x, int y, int z, long seed) { - if(paletteBlendAmplitude == 1) { - return biomeProvider.getBiome(x, y, z, seed); - } - int mx = ((x + (int) (paletteBlendAmplitude * noiseX)) / paletteRes) * paletteRes; - int my = ((y + (int) (paletteBlendAmplitude * paletteBlendSampler.noise(seed + 2, x, y, z))) / paletteRes) * paletteRes; - int mz = ((z + (int) (paletteBlendAmplitude * noiseZ)) / paletteRes) * paletteRes; - - return biomeProvider.getBiome(mx, MathUtil.clamp(min, my, max), mz, seed); - } - @Override @SuppressWarnings("try") public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world, @@ -83,8 +65,6 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { platform.getProfiler().push("chunk_base_3d"); int xOrig = (chunkX << 4); int zOrig = (chunkZ << 4); - int min = world.getMinHeight(); - int max = world.getMaxHeight() - 1; Sampler3D sampler = samplerCache.getChunk(chunkX, chunkZ, world, biomeProvider); @@ -100,16 +80,15 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { seed); for(int x = 0; x < 16; x++) { for(int z = 0; z < 16; z++) { - double paletteNoiseX = paletteBlendSampler.noise(seed, x, z); - double paletteNoiseZ = paletteBlendSampler.noise(seed + 1, x, z); int paletteLevel = 0; int cx = xOrig + x; int cz = zOrig + z; BlockState data; + Column biomeColumn = biomeProvider.getColumn(cx, cz, world); for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { - Biome biome = getBiome(min, max, paletteNoiseX, paletteNoiseZ, biomeProvider, cx, y, cz, seed); + Biome biome = biomeColumn.get(y); PaletteInfo paletteInfo = biome.getContext().get(paletteInfoPropertyKey); diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index c674253c0..57829ffa2 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -9,6 +9,8 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.api.properties.PropertyKey; +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import net.jafama.FastMath; @@ -54,9 +56,11 @@ public class ChunkInterpolator { for(int z = 0; z < 5; z++) { int scaledZ = z << 2; int absoluteZ = zOrigin + scaledZ; + + Column biomeColumn = provider.getColumn(absoluteX, absoluteZ, seed, min, max); for(int y = 0; y < size; y++) { int scaledY = (y << 2) + min; - BiomeNoiseProperties generationSettings = provider.getBiome(absoluteX, scaledY, absoluteZ, seed) + BiomeNoiseProperties generationSettings = biomeColumn.get(scaledY) .getContext() .get(noisePropertiesKey); From 3000547ee9f7691fa6405785798b246e5b72ac73 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 23:31:52 -0700 Subject: [PATCH 137/220] cache column in ChunkInterpolator --- .../NoiseChunkGenerator3DAddon.java | 7 ++-- .../generation/NoiseChunkGenerator3D.java | 15 ++++++-- .../math/interpolation/ChunkInterpolator.java | 38 +++++++++++++++---- .../generation/math/samplers/Sampler3D.java | 10 ++--- .../math/samplers/SamplerProvider.java | 6 ++- 5 files changed, 55 insertions(+), 21 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java index 32bb4c628..cd81f9555 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java @@ -48,9 +48,10 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { event.getPack() .getOrCreateRegistry(ChunkGeneratorProvider.class) .register(addon.key("NOISE_3D"), - pack -> new NoiseChunkGenerator3D(platform, config.getElevationBlend(), config.getHorizontalRes(), - config.getVerticalRes(), - noisePropertiesPropertyKey, paletteInfoPropertyKey)); + pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(), + config.getHorizontalRes(), + config.getVerticalRes(), noisePropertiesPropertyKey, + paletteInfoPropertyKey)); event.getPack() .applyLoader(SlantLayer.class, SlantLayer::new); }) 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 5bb104239..24be708af 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 @@ -16,10 +16,9 @@ import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.util.MathUtil; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; @@ -44,7 +43,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { private final PropertyKey paletteInfoPropertyKey; private final PropertyKey noisePropertiesKey; - public NoiseChunkGenerator3D(Platform platform, int elevationBlend, int carverHorizontalResolution, + public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBlend, int carverHorizontalResolution, int carverVerticalResolution, PropertyKey noisePropertiesKey, PropertyKey paletteInfoPropertyKey) { @@ -54,7 +53,15 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { this.carverVerticalResolution = carverVerticalResolution; this.paletteInfoPropertyKey = paletteInfoPropertyKey; this.noisePropertiesKey = noisePropertiesKey; - this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey); + int maxBlend = pack + .getBiomeProvider() + .stream() + .map(biome -> biome.getContext().get(noisePropertiesKey)) + .mapToInt(properties -> properties.blendDistance() * properties.blendStep()) + .max() + .orElse(0); + + this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey, maxBlend); } @Override diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 57829ffa2..89fe55afe 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -35,7 +35,8 @@ public class ChunkInterpolator { * @param min * @param max */ - public ChunkInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int min, int max, PropertyKey noisePropertiesKey) { + public ChunkInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int min, int max, + PropertyKey noisePropertiesKey, int maxBlend) { this.min = min; this.max = max; @@ -50,19 +51,31 @@ public class ChunkInterpolator { double[][][] noiseStorage = new double[5][5][size + 1]; + int maxBlendAndChunk = 17 + 2 * maxBlend; + + @SuppressWarnings("unchecked") + Column[] columns = new Column[maxBlendAndChunk * maxBlendAndChunk]; + for(int x = 0; x < 5; x++) { int scaledX = x << 2; int absoluteX = xOrigin + scaledX; for(int z = 0; z < 5; z++) { int scaledZ = z << 2; int absoluteZ = zOrigin + scaledZ; - - Column biomeColumn = provider.getColumn(absoluteX, absoluteZ, seed, min, max); + + int index = (scaledX + maxBlend) + maxBlendAndChunk * (scaledZ + maxBlend); + Column biomeColumn = columns[index]; + + if(biomeColumn == null) { + biomeColumn = provider.getColumn(absoluteX, absoluteZ, seed, min, max); + columns[index] = biomeColumn; + } + for(int y = 0; y < size; y++) { int scaledY = (y << 2) + min; BiomeNoiseProperties generationSettings = biomeColumn.get(scaledY) - .getContext() - .get(noisePropertiesKey); + .getContext() + .get(noisePropertiesKey); int step = generationSettings.blendStep(); int blend = generationSettings.blendDistance(); @@ -72,8 +85,19 @@ public class ChunkInterpolator { for(int xi = -blend; xi <= blend; xi++) { for(int zi = -blend; zi <= blend; zi++) { - BiomeNoiseProperties properties = provider - .getBiome(absoluteX + (xi * step), scaledY, absoluteZ + (zi * step), seed) + int blendX = (xi * step); + int blendZ = (zi * step); + + int localIndex = (scaledX + maxBlend + blendX) + maxBlendAndChunk * (scaledZ + maxBlend + blendZ); + Column column = columns[localIndex]; + + if(column == null) { + column = provider.getColumn(absoluteX + blendX, absoluteZ + blendZ, seed, min, max); + columns[localIndex] = column; + } + + BiomeNoiseProperties properties = column + .get(scaledY) .getContext() .get(noisePropertiesKey); double sample = properties.noiseHolder().getNoise(properties.base(), absoluteX, scaledY, absoluteZ, seed); diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java index 1bca2d4a5..15a480969 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java @@ -7,13 +7,12 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers; -import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; -import com.dfsek.terra.api.properties.PropertyKey; - import net.jafama.FastMath; +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.ChunkInterpolator; import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.ElevationInterpolator; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; @@ -21,9 +20,10 @@ public class Sampler3D { private final ChunkInterpolator interpolator; private final ElevationInterpolator elevationInterpolator; - public Sampler3D(int x, int z, long seed, int minHeight, int maxHeight, BiomeProvider provider, int elevationSmooth, PropertyKey noisePropertiesKey) { + public Sampler3D(int x, int z, long seed, int minHeight, int maxHeight, BiomeProvider provider, int elevationSmooth, + PropertyKey noisePropertiesKey, int maxBlend) { this.interpolator = new ChunkInterpolator(seed, x, z, provider, - minHeight, maxHeight, noisePropertiesKey); + minHeight, maxHeight, noisePropertiesKey, maxBlend); this.elevationInterpolator = new ElevationInterpolator(seed, x, z, provider, elevationSmooth, noisePropertiesKey); } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java index 7a8ca167e..90a24c691 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java @@ -35,11 +35,13 @@ public class SamplerProvider { private final Cache cache; private final int elevationSmooth; private final PropertyKey noisePropertiesKey; + private final int maxBlend; - public SamplerProvider(Platform platform, int elevationSmooth, PropertyKey noisePropertiesKey) { + public SamplerProvider(Platform platform, int elevationSmooth, PropertyKey noisePropertiesKey, int maxBlend) { this.elevationSmooth = elevationSmooth; cache = CacheBuilder.newBuilder().maximumSize(platform.getTerraConfig().getSamplerCache()).build(); this.noisePropertiesKey = noisePropertiesKey; + this.maxBlend = maxBlend; } public Sampler3D get(int x, int z, WorldProperties world, BiomeProvider provider) { @@ -53,7 +55,7 @@ public class SamplerProvider { try { return cache.get(context, () -> new Sampler3D(context.cx, context.cz, context.seed, context.minHeight, context.maxHeight, provider, - elevationSmooth, noisePropertiesKey)); + elevationSmooth, noisePropertiesKey, maxBlend)); } catch(ExecutionException e) { throw new RuntimeException(e); } From 901b58f56a42d201670ffc1879a1b67003a3611d Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 23:52:27 -0700 Subject: [PATCH 138/220] use Caffeine cache in SamplerProvider --- .../math/samplers/SamplerProvider.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java index 90a24c691..11ce0167f 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java @@ -17,16 +17,13 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers; -import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; -import com.dfsek.terra.api.properties.PropertyKey; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import net.jafama.FastMath; -import java.util.concurrent.ExecutionException; - +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.info.WorldProperties; @@ -38,8 +35,11 @@ public class SamplerProvider { private final int maxBlend; public SamplerProvider(Platform platform, int elevationSmooth, PropertyKey noisePropertiesKey, int maxBlend) { + cache = Caffeine + .newBuilder() + .maximumSize(platform.getTerraConfig().getSamplerCache()) + .build(); this.elevationSmooth = elevationSmooth; - cache = CacheBuilder.newBuilder().maximumSize(platform.getTerraConfig().getSamplerCache()).build(); this.noisePropertiesKey = noisePropertiesKey; this.maxBlend = maxBlend; } @@ -52,13 +52,8 @@ public class SamplerProvider { public Sampler3D getChunk(int cx, int cz, WorldProperties world, BiomeProvider provider) { WorldContext context = new WorldContext(cx, cz, world.getSeed(), world.getMinHeight(), world.getMaxHeight()); - try { - return cache.get(context, - () -> new Sampler3D(context.cx, context.cz, context.seed, context.minHeight, context.maxHeight, provider, - elevationSmooth, noisePropertiesKey, maxBlend)); - } catch(ExecutionException e) { - throw new RuntimeException(e); - } + return cache.get(context, c -> new Sampler3D(c.cx, c.cz, c.seed, c.minHeight, c.maxHeight, provider, + elevationSmooth, noisePropertiesKey, maxBlend)); } private record WorldContext(int cx, int cz, long seed, int minHeight, int maxHeight) { From 2daac8156560aba051c99f5e8c18c9eb85f99994 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 23:53:48 -0700 Subject: [PATCH 139/220] update to cloud 1.7.0 --- buildSrc/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 73eb8b2d2..ca7ad4360 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -4,7 +4,7 @@ object Versions { const val paralithic = "0.7.0" const val strata = "1.1.1" - const val cloud = "1.7.0-SNAPSHOT" + const val cloud = "1.7.0" const val slf4j = "1.7.36" const val log4j_slf4j_impl = "2.14.1" From 2f2fb54dea7e67cec4ab89a402d167c517132b54 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 18 Jun 2022 23:58:37 -0700 Subject: [PATCH 140/220] create biome tag API module --- common/addons/biome-tag-api/README.md | 4 ++++ common/addons/biome-tag-api/build.gradle.kts | 5 +++++ 2 files changed, 9 insertions(+) create mode 100644 common/addons/biome-tag-api/README.md create mode 100644 common/addons/biome-tag-api/build.gradle.kts diff --git a/common/addons/biome-tag-api/README.md b/common/addons/biome-tag-api/README.md new file mode 100644 index 000000000..3df487fbc --- /dev/null +++ b/common/addons/biome-tag-api/README.md @@ -0,0 +1,4 @@ +# Biome Tag API + +This addon contains an API to allow other addons to quickly query +Biome tags, by baking queries and using Contexts on biomes. \ No newline at end of file diff --git a/common/addons/biome-tag-api/build.gradle.kts b/common/addons/biome-tag-api/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/biome-tag-api/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} From dff2388b37b482089e0016d355ca226d0635d74f Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 00:19:07 -0700 Subject: [PATCH 141/220] implement biome query API --- .../addons/biome/tag/BiomeTagAPIAddon.java | 48 +++++++++++++++++++ .../addons/biome/tag/api/BiomeQueries.java | 17 +++++++ .../biome/tag/impl/BiomeTagFlattener.java | 20 ++++++++ .../addons/biome/tag/impl/BiomeTagHolder.java | 26 ++++++++++ .../addons/biome/tag/impl/SingleTagQuery.java | 31 ++++++++++++ .../src/main/resources/terra.addon.yml | 12 +++++ 6 files changed, 154 insertions(+) create mode 100644 common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeTagAPIAddon.java create mode 100644 common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java create mode 100644 common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java create mode 100644 common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java create mode 100644 common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java create mode 100644 common/addons/biome-tag-api/src/main/resources/terra.addon.yml diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeTagAPIAddon.java b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeTagAPIAddon.java new file mode 100644 index 000000000..a79e3bc76 --- /dev/null +++ b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeTagAPIAddon.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.addons.biome.tag; + +import com.dfsek.terra.addons.biome.tag.impl.BiomeTagFlattener; +import com.dfsek.terra.addons.biome.tag.impl.BiomeTagHolder; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.properties.Context; +import com.dfsek.terra.api.properties.PropertyKey; +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.Collection; + + +public class BiomeTagAPIAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + public static PropertyKey BIOME_TAG_KEY = Context.create(BiomeTagHolder.class); + + @Override + public void initialize() { + + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPostLoadEvent.class) + .then(event -> { + Collection biomes = event + .getPack() + .getRegistry(Biome.class) + .entries(); + + BiomeTagFlattener flattener = new BiomeTagFlattener(biomes + .stream() + .flatMap(biome -> biome.getTags().stream()) + .toList()); + + biomes.forEach(biome -> biome.getContext().put(BIOME_TAG_KEY, new BiomeTagHolder(biome, flattener))); + }) + .global(); + } +} diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java new file mode 100644 index 000000000..4bd17bf94 --- /dev/null +++ b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.biome.tag.api; + +import com.dfsek.terra.addons.biome.tag.impl.SingleTagQuery; +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.function.Predicate; + + +public final class BiomeQueries { + private BiomeQueries() { + + } + + public static Predicate has(String tag) { + return new SingleTagQuery(tag); + } +} diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java new file mode 100644 index 000000000..5e135f0a5 --- /dev/null +++ b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.addons.biome.tag.impl; + +import java.util.List; + + +public class BiomeTagFlattener { + private final List tags; + + public BiomeTagFlattener(List tags) { + this.tags = tags; + } + + public int index(String tag) { + return tags.indexOf(tag); + } + + public int size() { + return tags.size(); + } +} diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java new file mode 100644 index 000000000..4ed84ef58 --- /dev/null +++ b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.addons.biome.tag.impl; + +import com.dfsek.terra.api.properties.Properties; +import com.dfsek.terra.api.world.biome.Biome; + + +public class BiomeTagHolder implements Properties { + private final boolean[] tags; + private final BiomeTagFlattener flattener; + + public BiomeTagHolder(Biome biome, BiomeTagFlattener flattener) { + this.tags = new boolean[flattener.size()]; + this.flattener = flattener; + for(String tag : biome.getTags()) { + tags[flattener.index(tag)] = true; + } + } + + boolean get(int index) { + return tags[index]; + } + + public BiomeTagFlattener getFlattener() { + return flattener; + } +} diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java new file mode 100644 index 000000000..ce9934307 --- /dev/null +++ b/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.addons.biome.tag.impl; + +import com.dfsek.terra.addons.biome.tag.BiomeTagAPIAddon; +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.function.Predicate; + + +public class SingleTagQuery implements Predicate { + private int tagIndex = -1; + private final String tag; + + public SingleTagQuery(String tag) { + this.tag = tag; + } + + @Override + public boolean test(Biome biome) { + if(tagIndex < 0) { + tagIndex = biome + .getContext() + .get(BiomeTagAPIAddon.BIOME_TAG_KEY) + .getFlattener() + .index(tag); + } + return biome + .getContext() + .get(BiomeTagAPIAddon.BIOME_TAG_KEY) + .get(tagIndex); + } +} diff --git a/common/addons/biome-tag-api/src/main/resources/terra.addon.yml b/common/addons/biome-tag-api/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..3a6eef5cb --- /dev/null +++ b/common/addons/biome-tag-api/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: biome-tag-api +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.biome.tag.BiomeTagAPIAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file From 92d173cb89a7d7315469e44acecc6b17347352d4 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 00:20:42 -0700 Subject: [PATCH 142/220] rename tag addon to query addon --- common/addons/biome-query-api/README.md | 4 ++++ .../{biome-tag-api => biome-query-api}/build.gradle.kts | 0 .../dfsek/terra/addons/biome/tag/BiomeQueryAPIAddon.java} | 2 +- .../com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java | 0 .../terra/addons/biome/tag/impl/BiomeTagFlattener.java | 0 .../dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java | 0 .../dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java | 6 +++--- .../src/main/resources/terra.addon.yml | 0 common/addons/biome-tag-api/README.md | 4 ---- 9 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 common/addons/biome-query-api/README.md rename common/addons/{biome-tag-api => biome-query-api}/build.gradle.kts (100%) rename common/addons/{biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeTagAPIAddon.java => biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeQueryAPIAddon.java} (96%) rename common/addons/{biome-tag-api => biome-query-api}/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java (100%) rename common/addons/{biome-tag-api => biome-query-api}/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java (100%) rename common/addons/{biome-tag-api => biome-query-api}/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java (100%) rename common/addons/{biome-tag-api => biome-query-api}/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java (78%) rename common/addons/{biome-tag-api => biome-query-api}/src/main/resources/terra.addon.yml (100%) delete mode 100644 common/addons/biome-tag-api/README.md diff --git a/common/addons/biome-query-api/README.md b/common/addons/biome-query-api/README.md new file mode 100644 index 000000000..e8e2a800c --- /dev/null +++ b/common/addons/biome-query-api/README.md @@ -0,0 +1,4 @@ +# Biome Query API + +This addon contains an API to allow other addons to quickly query +Biome data, by baking queries and using Contexts on biomes. \ No newline at end of file diff --git a/common/addons/biome-tag-api/build.gradle.kts b/common/addons/biome-query-api/build.gradle.kts similarity index 100% rename from common/addons/biome-tag-api/build.gradle.kts rename to common/addons/biome-query-api/build.gradle.kts diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeTagAPIAddon.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeQueryAPIAddon.java similarity index 96% rename from common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeTagAPIAddon.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeQueryAPIAddon.java index a79e3bc76..52b50e146 100644 --- a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeTagAPIAddon.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeQueryAPIAddon.java @@ -15,7 +15,7 @@ import com.dfsek.terra.api.world.biome.Biome; import java.util.Collection; -public class BiomeTagAPIAddon implements AddonInitializer { +public class BiomeQueryAPIAddon implements AddonInitializer { @Inject private Platform platform; diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java similarity index 100% rename from common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java similarity index 100% rename from common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java similarity index 100% rename from common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java diff --git a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java similarity index 78% rename from common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java index ce9934307..bdcdfbb83 100644 --- a/common/addons/biome-tag-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java @@ -1,6 +1,6 @@ package com.dfsek.terra.addons.biome.tag.impl; -import com.dfsek.terra.addons.biome.tag.BiomeTagAPIAddon; +import com.dfsek.terra.addons.biome.tag.BiomeQueryAPIAddon; import com.dfsek.terra.api.world.biome.Biome; import java.util.function.Predicate; @@ -19,13 +19,13 @@ public class SingleTagQuery implements Predicate { if(tagIndex < 0) { tagIndex = biome .getContext() - .get(BiomeTagAPIAddon.BIOME_TAG_KEY) + .get(BiomeQueryAPIAddon.BIOME_TAG_KEY) .getFlattener() .index(tag); } return biome .getContext() - .get(BiomeTagAPIAddon.BIOME_TAG_KEY) + .get(BiomeQueryAPIAddon.BIOME_TAG_KEY) .get(tagIndex); } } diff --git a/common/addons/biome-tag-api/src/main/resources/terra.addon.yml b/common/addons/biome-query-api/src/main/resources/terra.addon.yml similarity index 100% rename from common/addons/biome-tag-api/src/main/resources/terra.addon.yml rename to common/addons/biome-query-api/src/main/resources/terra.addon.yml diff --git a/common/addons/biome-tag-api/README.md b/common/addons/biome-tag-api/README.md deleted file mode 100644 index 3df487fbc..000000000 --- a/common/addons/biome-tag-api/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Biome Tag API - -This addon contains an API to allow other addons to quickly query -Biome tags, by baking queries and using Contexts on biomes. \ No newline at end of file From abca785b1ee16843512083245264a72762bd52de Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 00:25:54 -0700 Subject: [PATCH 143/220] refactor query addon package --- .../addons/biome/{tag => query}/BiomeQueryAPIAddon.java | 6 +++--- .../terra/addons/biome/{tag => query}/api/BiomeQueries.java | 4 ++-- .../addons/biome/{tag => query}/impl/BiomeTagFlattener.java | 2 +- .../addons/biome/{tag => query}/impl/BiomeTagHolder.java | 2 +- .../addons/biome/{tag => query}/impl/SingleTagQuery.java | 4 ++-- .../biome-query-api/src/main/resources/terra.addon.yml | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) rename common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/{tag => query}/BiomeQueryAPIAddon.java (91%) rename common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/{tag => query}/api/BiomeQueries.java (70%) rename common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/{tag => query}/impl/BiomeTagFlattener.java (87%) rename common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/{tag => query}/impl/BiomeTagHolder.java (93%) rename common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/{tag => query}/impl/SingleTagQuery.java (86%) diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeQueryAPIAddon.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/BiomeQueryAPIAddon.java similarity index 91% rename from common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeQueryAPIAddon.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/BiomeQueryAPIAddon.java index 52b50e146..3004cb0e1 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/BiomeQueryAPIAddon.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/BiomeQueryAPIAddon.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.addons.biome.tag; +package com.dfsek.terra.addons.biome.query; -import com.dfsek.terra.addons.biome.tag.impl.BiomeTagFlattener; -import com.dfsek.terra.addons.biome.tag.impl.BiomeTagHolder; +import com.dfsek.terra.addons.biome.query.impl.BiomeTagFlattener; +import com.dfsek.terra.addons.biome.query.impl.BiomeTagHolder; import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java similarity index 70% rename from common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java index 4bd17bf94..83b1ebf18 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/api/BiomeQueries.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java @@ -1,6 +1,6 @@ -package com.dfsek.terra.addons.biome.tag.api; +package com.dfsek.terra.addons.biome.query.api; -import com.dfsek.terra.addons.biome.tag.impl.SingleTagQuery; +import com.dfsek.terra.addons.biome.query.impl.SingleTagQuery; import com.dfsek.terra.api.world.biome.Biome; import java.util.function.Predicate; diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/BiomeTagFlattener.java similarity index 87% rename from common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/BiomeTagFlattener.java index 5e135f0a5..98a416295 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagFlattener.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/BiomeTagFlattener.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.addons.biome.tag.impl; +package com.dfsek.terra.addons.biome.query.impl; import java.util.List; diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/BiomeTagHolder.java similarity index 93% rename from common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/BiomeTagHolder.java index 4ed84ef58..0e4ab707b 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/BiomeTagHolder.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/BiomeTagHolder.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.addons.biome.tag.impl; +package com.dfsek.terra.addons.biome.query.impl; import com.dfsek.terra.api.properties.Properties; import com.dfsek.terra.api.world.biome.Biome; diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java similarity index 86% rename from common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java rename to common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java index bdcdfbb83..d2dfc4b23 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/tag/impl/SingleTagQuery.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java @@ -1,6 +1,6 @@ -package com.dfsek.terra.addons.biome.tag.impl; +package com.dfsek.terra.addons.biome.query.impl; -import com.dfsek.terra.addons.biome.tag.BiomeQueryAPIAddon; +import com.dfsek.terra.addons.biome.query.BiomeQueryAPIAddon; import com.dfsek.terra.api.world.biome.Biome; import java.util.function.Predicate; diff --git a/common/addons/biome-query-api/src/main/resources/terra.addon.yml b/common/addons/biome-query-api/src/main/resources/terra.addon.yml index 3a6eef5cb..8a55ce2dc 100644 --- a/common/addons/biome-query-api/src/main/resources/terra.addon.yml +++ b/common/addons/biome-query-api/src/main/resources/terra.addon.yml @@ -1,10 +1,10 @@ schema-version: 1 contributors: - Terra contributors -id: biome-tag-api +id: biome-query-api version: @VERSION@ entrypoints: - - "com.dfsek.terra.addons.biome.tag.BiomeTagAPIAddon" + - "com.dfsek.terra.addons.biome.query.BiomeQueryAPIAddon" website: issues: https://github.com/PolyhedralDev/Terra/issues source: https://github.com/PolyhedralDev/Terra From 41fc28e1e94eafdd8b6360467557cc2fb5adf61c Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 00:34:03 -0700 Subject: [PATCH 144/220] use biome query API in ReplaceExtrusion --- .../addons/biome-provider-extrusion/build.gradle.kts | 1 + .../biome/extrusion/extrusions/ReplaceExtrusion.java | 11 +++++++---- .../src/main/resources/terra.addon.yml | 4 +++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/common/addons/biome-provider-extrusion/build.gradle.kts b/common/addons/biome-provider-extrusion/build.gradle.kts index 9d0aac37f..7615a16d0 100644 --- a/common/addons/biome-provider-extrusion/build.gradle.kts +++ b/common/addons/biome-provider-extrusion/build.gradle.kts @@ -2,4 +2,5 @@ version = version("1.0.0") dependencies { compileOnlyApi(project(":common:addons:manifest-addon-loader")) + compileOnlyApi(project(":common:addons:biome-query-api")) } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java index 91efd92aa..bc45ac40c 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java @@ -2,6 +2,7 @@ package com.dfsek.terra.addons.biome.extrusion.extrusions; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.addons.biome.query.api.BiomeQueries; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.util.collection.ProbabilityCollection; @@ -22,19 +23,21 @@ public class ReplaceExtrusion implements Extrusion { private final ProbabilityCollection biomes; - private final String tag; + private final Predicate hasTag; public ReplaceExtrusion(NoiseSampler sampler, Range range, ProbabilityCollection biomes, String tag) { this.sampler = sampler; this.range = range; this.biomes = biomes; - this.tag = tag; + this.hasTag = BiomeQueries.has(tag); } @Override public Biome extrude(Biome original, int x, int y, int z, long seed) { - if(!original.getTags().contains(tag)) return original; - return range.ifInRange(y, () -> biomes.get(sampler, x, y, z, seed).get(original), original); + if(hasTag.test(original)) { + return range.ifInRange(y, () -> biomes.get(sampler, x, y, z, seed).get(original), original); + } + return original; } @Override diff --git a/common/addons/biome-provider-extrusion/src/main/resources/terra.addon.yml b/common/addons/biome-provider-extrusion/src/main/resources/terra.addon.yml index ea0dd68c1..21992a6d1 100644 --- a/common/addons/biome-provider-extrusion/src/main/resources/terra.addon.yml +++ b/common/addons/biome-provider-extrusion/src/main/resources/terra.addon.yml @@ -9,4 +9,6 @@ website: issues: https://github.com/PolyhedralDev/Terra/issues source: https://github.com/PolyhedralDev/Terra docs: https://terra.polydev.org -license: MIT License \ No newline at end of file +license: MIT License +depends: + biome-query-api: "1.+" \ No newline at end of file From 33ca98ccaf52a611912fb5a8ee5afc60dd2397bc Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 01:01:12 -0700 Subject: [PATCH 145/220] dont shade caffeine into pipeline addon --- common/addons/biome-provider-pipeline/build.gradle.kts | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/addons/biome-provider-pipeline/build.gradle.kts b/common/addons/biome-provider-pipeline/build.gradle.kts index ec1104ce3..2629ac476 100644 --- a/common/addons/biome-provider-pipeline/build.gradle.kts +++ b/common/addons/biome-provider-pipeline/build.gradle.kts @@ -2,13 +2,11 @@ version = version("1.0.1") dependencies { compileOnlyApi(project(":common:addons:manifest-addon-loader")) - implementation("com.github.ben-manes.caffeine:caffeine:3.1.0") implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) } tasks.named("shadowJar") { - relocate("com.github.benmanes.caffeine", "com.dfsek.terra.addons.biome.pipeline.lib.caffeine") relocate("net.jafama", "com.dfsek.terra.addons.biome.pipeline.lib.jafama") } \ No newline at end of file From 865ec58d70785c9f856786b5c06ac5ef2e37edf7 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 02:05:36 -0700 Subject: [PATCH 146/220] fix Column erroneously caching --- .../world/chunk/generation/util/Column.java | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index cf4ff761f..2f5cf9d19 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -27,24 +27,18 @@ public class Column { private final int max; private final T world; - private final BlockState[] cache; - public Column(int x, int z, T world) { - this(x, z, world, world.getMinHeight(), world.getMaxHeight(), new BlockState[world.getMaxHeight() - world.getMinHeight()]); + this(x, z, world, world.getMinHeight(), world.getMaxHeight()); } public Column(int x, int z, T world, int min, int max) { - this(x, z, world, min, max, new BlockState[world.getMaxHeight() - world.getMinHeight()]); - } - - private Column(int x, int z, T world, int min, int max, BlockState[] cache) { this.x = x; this.z = z; this.world = world; this.max = max; this.min = min; - this.cache = cache; } + public int getX() { return x; @@ -55,13 +49,7 @@ public class Column { } public BlockState getBlock(int y) { - int i = y - world.getMinHeight(); - BlockState state = cache[i]; - if(state == null) { - state = world.getBlockState(x, y, z); - cache[i] = state; - } - return state; + return world.getBlockState(x, y, z); } public T getWorld() { @@ -84,7 +72,7 @@ public class Column { public Column clamp(int min, int max) { if(min >= max) throw new IllegalArgumentException("Min greater than or equal to max: " + min + ", " + max); - return new Column<>(x, z, world, min, max, cache); + return new Column<>(x, z, world, min, max); } public BinaryColumn newBinaryColumn(IntToBooleanFunction function) { From 536733911bb8c18abbf961324179df5aa6ef0c12 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 17:50:47 -0700 Subject: [PATCH 147/220] meta annotate BiomeExtrusionTemplate --- .../biome/extrusion/config/BiomeExtrusionTemplate.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java index b2fd24ed6..527e7d981 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java @@ -6,6 +6,7 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.terra.addons.biome.extrusion.BiomeExtrusionProvider; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import java.util.List; @@ -13,14 +14,14 @@ import java.util.List; public class BiomeExtrusionTemplate implements ObjectTemplate { @Value("provider") - private BiomeProvider provider; + private @Meta BiomeProvider provider; @Value("resolution") @Default - private int resolution = 4; + private @Meta int resolution = 4; @Value("extrusions") - private List extrusions; + private @Meta List<@Meta Extrusion> extrusions; @Override public BiomeProvider get() { From 98a9035ae82cef75c945b123bea3a10e97309571 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 21:24:22 -0700 Subject: [PATCH 148/220] begin architectury implementation --- buildSrc/src/main/kotlin/DependencyConfig.kt | 1 + buildSrc/src/main/kotlin/Versions.kt | 7 + platforms/forge/build.gradle.kts | 88 +++++++ platforms/forge/gradle.properties | 1 + .../com/dfsek/terra/forge/ForgeAddon.java | 80 ++++++ .../dfsek/terra/forge/ForgeEntryPoint.java | 56 ++++ .../com/dfsek/terra/forge/PlatformImpl.java | 169 ++++++++++++ .../config/PostLoadCompatibilityOptions.java | 28 ++ .../config/PreLoadCompatibilityOptions.java | 60 +++++ .../forge/config/VanillaBiomeProperties.java | 76 ++++++ .../com/dfsek/terra/forge/data/Codecs.java | 65 +++++ .../FabricChunkGeneratorWrapper.java | 246 ++++++++++++++++++ .../forge/generation/TerraBiomeSource.java | 86 ++++++ .../terra/forge/handle/FabricItemHandle.java | 58 +++++ .../terra/forge/handle/FabricWorldHandle.java | 59 +++++ .../mixin/access/ChunkRegionAccessor.java | 15 ++ .../mixin/access/MobSpawnerLogicAccessor.java | 30 +++ .../forge/mixin/access/StateAccessor.java | 35 +++ .../access/StructureAccessorAccessor.java | 30 +++ ...oveGoalsUnsynchronizedRandomAccessFix.java | 27 ++ .../mixin/fix/NetherFossilOptimization.java | 29 +++ .../GenerationSettingsFloraFeaturesMixin.java | 32 +++ .../implementations/terra/BiomeMixin.java | 31 +++ .../terra/HandleImplementationMixin.java | 61 +++++ .../terra/block/BlockMixin.java | 44 ++++ .../terra/block/entity/BlockEntityMixin.java | 54 ++++ .../LootableContainerBlockEntityMixin.java | 35 +++ .../entity/MobSpawnerBlockEntityMixin.java | 131 ++++++++++ .../block/entity/SignBlockEntityMixin.java | 65 +++++ .../terra/block/state/BlockStateMixin.java | 83 ++++++ .../terra/block/state/PropertyMixin.java | 43 +++ .../terra/chunk/ChunkRegionMixin.java | 58 +++++ .../terra/chunk/WorldChunkMixin.java | 75 ++++++ .../terra/chunk/data/ProtoChunkMixin.java | 53 ++++ .../terra/entity/EntityMixin.java | 55 ++++ .../terra/entity/EntityTypeMixin.java | 29 +++ .../terra/entity/PlayerEntityMixin.java | 31 +++ .../entity/ServerCommandSourceMixin.java | 66 +++++ .../LockableContainerBlockEntityMixin.java | 47 ++++ .../terra/inventory/item/ItemMixin.java | 43 +++ .../terra/inventory/item/ItemStackMixin.java | 76 ++++++ .../inventory/meta/EnchantmentMixin.java | 53 ++++ .../meta/ItemStackDamageableMixin.java | 55 ++++ .../inventory/meta/ItemStackMetaMixin.java | 65 +++++ .../implementations/terra/package-info.java | 23 ++ .../terra/world/ChunkRegionMixin.java | 149 +++++++++++ .../terra/world/ServerWorldMixin.java | 102 ++++++++ .../lifecycle/DataPackContentsMixin.java | 28 ++ .../mixin/lifecycle/MinecraftServerMixin.java | 32 +++ .../mixin/lifecycle/NoiseConfigMixin.java | 31 +++ .../forge/mixin/lifecycle/RegistryMixin.java | 20 ++ .../client/MinecraftClientMixin.java | 41 +++ .../forge/mixin/lifecycle/package-info.java | 22 ++ .../lifecycle/server/ServerMainMixin.java | 40 +++ .../mixin_ifaces/FloraFeatureHolder.java | 10 + .../com/dfsek/terra/forge/util/BiomeUtil.java | 169 ++++++++++++ .../dfsek/terra/forge/util/FabricAdapter.java | 185 +++++++++++++ .../dfsek/terra/forge/util/FabricUtil.java | 61 +++++ .../dfsek/terra/forge/util/LifecycleUtil.java | 100 +++++++ .../terra/forge/util/ProtoPlatformBiome.java | 55 ++++ .../com/dfsek/terra/forge/util/SeedHack.java | 29 +++ .../com/dfsek/terra/forge/util/TagUtil.java | 103 ++++++++ .../src/main/resources/META-INF/mods.toml | 24 ++ .../src/main/resources/assets/terra/icon.png | Bin 0 -> 129860 bytes .../resources/assets/terra/lang/en_us.json | 4 + .../src/main/resources/terra.mixins.json | 53 ++++ settings.gradle.kts | 2 + 67 files changed, 3814 insertions(+) create mode 100644 platforms/forge/build.gradle.kts create mode 100644 platforms/forge/gradle.properties create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/config/VanillaBiomeProperties.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricItemHandle.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricWorldHandle.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/ChunkRegionAccessor.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/MobSpawnerLogicAccessor.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StateAccessor.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StructureAccessorAccessor.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/BiomeMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/HandleImplementationMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/BlockMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/BlockEntityMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/BlockStateMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/PropertyMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/ChunkRegionMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/WorldChunkMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityTypeMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/PlayerEntityMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/ServerCommandSourceMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemStackMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/package-info.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/MinecraftServerMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/client/MinecraftClientMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/package-info.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/server/ServerMainMixin.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin_ifaces/FloraFeatureHolder.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricAdapter.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricUtil.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/SeedHack.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java create mode 100644 platforms/forge/src/main/resources/META-INF/mods.toml create mode 100644 platforms/forge/src/main/resources/assets/terra/icon.png create mode 100644 platforms/forge/src/main/resources/assets/terra/lang/en_us.json create mode 100644 platforms/forge/src/main/resources/terra.mixins.json diff --git a/buildSrc/src/main/kotlin/DependencyConfig.kt b/buildSrc/src/main/kotlin/DependencyConfig.kt index ecc0a8229..a507eb96c 100644 --- a/buildSrc/src/main/kotlin/DependencyConfig.kt +++ b/buildSrc/src/main/kotlin/DependencyConfig.kt @@ -34,6 +34,7 @@ fun Project.configureDependencies() { maven("https://repo.codemc.org/repository/maven-public") maven("https://repo.codemc.io/repository/nms/") maven("https://papermc.io/repo/repository/maven-public/") + maven ( "https://files.minecraftforge.net/maven/" ) } dependencies { diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index ca7ad4360..42a262e15 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -28,6 +28,13 @@ object Versions { const val minotaur = "1.1.0" } + object Forge { + const val minecraft = "1.19" + const val forge = "$minecraft-41.0.38" + const val yarn = "$minecraft+build.1" + const val architecuryLoom = "0.12.0-SNAPSHOT" + } + object Bukkit { const val paper = "1.18.2-R0.1-SNAPSHOT" const val paperLib = "1.0.5" diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts new file mode 100644 index 000000000..73aee97a0 --- /dev/null +++ b/platforms/forge/build.gradle.kts @@ -0,0 +1,88 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.modrinth.minotaur.TaskModrinthUpload +import net.fabricmc.loom.task.RemapJarTask +import java.util.Date + +plugins { + id("dev.architectury.loom") version Versions.Forge.architecuryLoom + id("com.modrinth.minotaur") version Versions.Fabric.minotaur +} + +loom { + mixin { + defaultRefmapName.set("terra-refmap.json") + } + + forge { + mixinConfigs.set(listOf("terra.mixins.json")) + + } + +} + +dependencies { + shadedApi(project(":common:implementation:base")) + + forge("net.minecraftforge:forge:${Versions.Forge.forge}") + + minecraft("com.mojang:minecraft:${Versions.Forge.minecraft}") + mappings("net.fabricmc:yarn:${Versions.Forge.yarn}:v2") +} + + + + + +addonDir(project.file("./run/config/Terra/addons"), tasks.named("runClient").get()) +addonDir(project.file("./run/config/Terra/addons"), tasks.named("runServer").get()) + +tasks.withType().configureEach { + options.release.set(17) +} + +tasks.getByName("shadowJar") { + exclude("org/slf4j/**") +} + +val remapped = tasks.register("remapShadedJar") { + dependsOn("installAddons") + group = "loom" + val shadowJar = tasks.getByName("shadowJar") + dependsOn(shadowJar) + inputFile.set(shadowJar.archiveFile) + archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-shaded\\.jar$"), "-shaded-mapped.jar")) + addNestedDependencies.set(true) +} + +tasks.named("assemble").configure { + dependsOn("remapShadedJar") +} + +tasks.withType { + finalizedBy(remapped) + manifest { + attributes( + mapOf( + "Specification-Title" to "terra", + "Specification-Vendor" to "Terra Contributors", + "Specification-Version" to "1", + "Implementation-Title" to project.name, + "Implementation-Version" to "@VERSION@", + "Implementation-Vendor" to "Terra Contributors", + "Implementation-Timestamp" to Date().toString() + ) + ) + } +} + +tasks.register("publishModrinth") { + dependsOn("remapShadedJar") + group = "loom" + token = System.getenv("MODRINTH_SECRET") + projectId = "FIlZB9L0" + versionNumber = "${project.version}-forge" + uploadFile = remapped.get().archiveFile.get().asFile + releaseType = "beta" + addGameVersion(Versions.Forge.minecraft) + addLoader("forge") +} \ No newline at end of file diff --git a/platforms/forge/gradle.properties b/platforms/forge/gradle.properties new file mode 100644 index 000000000..82425854e --- /dev/null +++ b/platforms/forge/gradle.properties @@ -0,0 +1 @@ +loom.platform=forge diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java new file mode 100644 index 000000000..320c03fe2 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java @@ -0,0 +1,80 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.version.Version; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.forge.config.PostLoadCompatibilityOptions; +import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.forge.config.VanillaBiomeProperties; + + +public final class ForgeAddon implements BaseAddon { + private static final Version VERSION = Versions.getVersion(1, 0, 0); + private static final Logger logger = LoggerFactory.getLogger(ForgeAddon.class); + private final PlatformImpl terraForgePlugin; + + public ForgeAddon(PlatformImpl terraForgePlugin) { + this.terraForgePlugin = terraForgePlugin; + } + + @Override + public void initialize() { + terraForgePlugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions()))) + .global(); + + terraForgePlugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigPackPostLoadEvent.class) + .then(event -> event.getPack().getContext().put(event.loadTemplate(new PostLoadCompatibilityOptions()))) + .priority(100) + .global(); + + terraForgePlugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigurationLoadEvent.class) + .then(event -> { + if(event.is(Biome.class)) { + event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties())); + } + }) + .global(); + } + + @Override + public Version getVersion() { + return VERSION; + } + + @Override + public String getID() { + return "terra-fabric"; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java new file mode 100644 index 000000000..22194ac6e --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -0,0 +1,56 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.forge.data.Codecs; + +@Mod("terra") +public class ForgeEntryPoint { + private static final Logger logger = LoggerFactory.getLogger(ForgeEntryPoint.class); + + private static final PlatformImpl TERRA_PLUGIN = new PlatformImpl(); + + + public static PlatformImpl getPlatform() { + return TERRA_PLUGIN; + } + + public static void register() { // register the things + Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); + Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); + } + + public ForgeEntryPoint() { + IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); + + modEventBus.addListener(this::commonSetup); + } + + private void commonSetup(final FMLCommonSetupEvent event) { + logger.info("Initializing Terra Forge mod..."); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java new file mode 100644 index 000000000..3e3791142 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -0,0 +1,169 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.Version; +import com.dfsek.tectonic.api.TypeRegistry; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import net.minecraft.MinecraftVersion; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.world.biome.Biome.Precipitation; +import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; +import net.minecraftforge.fml.loading.FMLLoader; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.addon.EphemeralAddon; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.api.world.biome.PlatformBiome; +import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.handle.FabricItemHandle; +import com.dfsek.terra.forge.handle.FabricWorldHandle; +import com.dfsek.terra.forge.util.BiomeUtil; +import com.dfsek.terra.forge.util.ProtoPlatformBiome; + + +public class PlatformImpl extends AbstractPlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); + private final ItemHandle itemHandle = new FabricItemHandle(); + private final WorldHandle worldHandle = new FabricWorldHandle(); + private final Lazy dataFolder = Lazy.lazy(() -> new File("./config/Terra")); + private MinecraftServer server; + + public PlatformImpl() { + load(); + } + + public void setServer(MinecraftServer server) { + this.server = server; + } + + public MinecraftServer getServer() { + return server; + } + + @Override + public boolean reload() { + getTerraConfig().load(this); + getRawConfigRegistry().clear(); + boolean succeed = getRawConfigRegistry().loadAll(this); + + + if(server != null) { + server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { + LOGGER.warn("Failed to execute reload", throwable); + return null; + }).join(); + BiomeUtil.registerBiomes(); + server.getWorlds().forEach(world -> { + if(world.getChunkManager().getChunkGenerator() instanceof FabricChunkGeneratorWrapper chunkGeneratorWrapper) { + getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { + chunkGeneratorWrapper.setPack(pack); + LOGGER.info("Replaced pack in chunk generator for world {}", world); + }); + } + }); + } + return succeed; + } + + @Override + protected Iterable platformAddon() { + List addons = new ArrayList<>(); + + addons.add(new ForgeAddon(this)); + + String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); + try { + addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft")); + } catch(ParseException e) { + try { + addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft")); + } catch(ParseException ex) { + LOGGER.warn("Failed to parse Minecraft version", e); + } + } + + FMLLoader.getLoadingModList().getMods().forEach(mod -> { + String id = mod.getModId(); + if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; + Version version = Versions.getVersion(mod.getVersion().getMajorVersion(), mod.getVersion().getMinorVersion(), mod.getVersion().getIncrementalVersion()); + addons.add(new EphemeralAddon(version, "forge:" + id)); + }); + + return addons; + } + + @Override + public @NotNull String platformName() { + return "Fabric"; + } + + @Override + public @NotNull WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public @NotNull File getDataFolder() { + return dataFolder.value(); + } + + @Override + public @NotNull ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public void register(TypeRegistry registry) { + super.register(registry); + registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker)) + .registerLoader(Identifier.class, (type, o, loader, depthTracker) -> { + Identifier identifier = Identifier.tryParse((String) o); + if(identifier == null) + throw new LoadException("Invalid identifier: " + o, depthTracker); + return identifier; + }) + .registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase( + Locale.ROOT))) + .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase( + Locale.ROOT))); + } + + + private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException { + Identifier identifier = Identifier.tryParse(id); + if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure. + return new ProtoPlatformBiome(identifier); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java new file mode 100644 index 000000000..1a8ad12ba --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java @@ -0,0 +1,28 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; + +import com.dfsek.terra.api.properties.Properties; + + +@SuppressWarnings("FieldMayBeFinal") +public class PostLoadCompatibilityOptions implements ConfigTemplate, Properties { + +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java new file mode 100644 index 000000000..bf7c3b7bc --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java @@ -0,0 +1,60 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.properties.Properties; + + +@SuppressWarnings("FieldMayBeFinal") +public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties { + @Value("fabric.use-vanilla-biomes") + @Default + private boolean vanillaBiomes = false; + + @Value("fabric.beard.enable") + @Default + private boolean beard = true; + + @Value("fabric.beard.threshold") + @Default + private double beardThreshold = 0.5; + + @Value("fabric.beard.air-threshold") + @Default + private double airThreshold = -0.5; + + public boolean useVanillaBiomes() { + return vanillaBiomes; + } + + public boolean isBeard() { + return beard; + } + + public double getBeardThreshold() { + return beardThreshold; + } + + public double getAirThreshold() { + return airThreshold; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/VanillaBiomeProperties.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/VanillaBiomeProperties.java new file mode 100644 index 000000000..b4baa1882 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/VanillaBiomeProperties.java @@ -0,0 +1,76 @@ +package com.dfsek.terra.forge.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import net.minecraft.world.biome.Biome.Precipitation; +import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; + +import com.dfsek.terra.api.properties.Properties; + + +public class VanillaBiomeProperties implements ConfigTemplate, Properties { + @Value("colors.grass") + @Default + private Integer grassColor = null; + + @Value("colors.fog") + @Default + private Integer fogColor = null; + + @Value("colors.water") + @Default + private Integer waterColor = null; + + @Value("colors.water-fog") + @Default + private Integer waterFogColor = null; + + @Value("colors.foliage") + @Default + private Integer foliageColor = null; + + @Value("colors.sky") + @Default + private Integer skyColor = null; + + @Value("colors.modifier") + @Default + private GrassColorModifier modifier = null; + + @Value("climate.precipitation") + @Default + private Precipitation precipitation = null; + + public Integer getFogColor() { + return fogColor; + } + + public Integer getFoliageColor() { + return foliageColor; + } + + public Integer getGrassColor() { + return grassColor; + } + + public Integer getWaterColor() { + return waterColor; + } + + public Integer getWaterFogColor() { + return waterFogColor; + } + + public Integer getSkyColor() { + return skyColor; + } + + public Precipitation getPrecipitation() { + return precipitation; + } + + public GrassColorModifier getModifier() { + return modifier; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java new file mode 100644 index 000000000..95bf25e1a --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java @@ -0,0 +1,65 @@ +package com.dfsek.terra.forge.data; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.forge.ForgeEntryPoint; +import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.TerraBiomeSource; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.util.dynamic.RegistryOps; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; + + +public final class Codecs { + public static final Codec TERRA_REGISTRY_KEY = RecordCodecBuilder + .create(registryKey -> registryKey.group(Codec.STRING.fieldOf("namespace") + .stable() + .forGetter(RegistryKey::getNamespace), + Codec.STRING.fieldOf("id") + .stable() + .forGetter(RegistryKey::getID)) + .apply(registryKey, registryKey.stable(RegistryKey::of))); + + public static final Codec CONFIG_PACK = RecordCodecBuilder + .create(config -> config.group(TERRA_REGISTRY_KEY.fieldOf("pack") + .stable() + .forGetter(ConfigPack::getRegistryKey)) + .apply(config, config.stable(id -> ForgeEntryPoint.getPlatform() + .getConfigRegistry() + .get(id) + .orElseThrow(() -> new IllegalArgumentException( + "No such config pack " + + id))))); + + public static final Codec TERRA_BIOME_SOURCE = RecordCodecBuilder + .create(instance -> instance.group(RegistryOps.createRegistryCodec(Registry.BIOME_KEY) + .fieldOf("biome_registry") + .stable() + .forGetter(TerraBiomeSource::getBiomeRegistry), + CONFIG_PACK.fieldOf("pack") + .stable() + .forGetter(TerraBiomeSource::getPack)) + .apply(instance, instance.stable(TerraBiomeSource::new))); + + public static final Codec FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder + .create( + instance -> instance.group( + RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY) + .fieldOf("structure_registry") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getNoiseRegistry), + TERRA_BIOME_SOURCE.fieldOf("biome_source") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getBiomeSource), + CONFIG_PACK.fieldOf("pack") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getPack), + ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getSettings) + ).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new)) + ); +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java new file mode 100644 index 000000000..e31bb40b2 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java @@ -0,0 +1,246 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.generation; + +import com.mojang.serialization.Codec; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.structure.StructureSet; +import net.minecraft.util.Util; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.random.CheckedRandom; +import net.minecraft.util.math.random.ChunkRandom; +import net.minecraft.util.math.random.RandomSeed; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.HeightLimitView; +import net.minecraft.world.Heightmap.Type; +import net.minecraft.world.SpawnHelper; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.source.BiomeAccess; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.gen.GenerationStep.Carver; +import net.minecraft.world.gen.StructureAccessor; +import net.minecraft.world.gen.StructureWeightSampler; +import net.minecraft.world.gen.chunk.Blender; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import net.minecraft.world.gen.chunk.VerticalBlockSample; +import net.minecraft.world.gen.densityfunction.DensityFunction.UnblendedNoisePos; +import net.minecraft.world.gen.noise.NoiseConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Optional; +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; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; +import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; +import com.dfsek.terra.api.world.info.WorldProperties; +import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.forge.data.Codecs; +import com.dfsek.terra.forge.mixin.access.StructureAccessorAccessor; +import com.dfsek.terra.forge.util.FabricAdapter; + + +public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { + private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class); + + private final TerraBiomeSource biomeSource; + private final Registry noiseRegistry; + private final RegistryEntry settings; + private ChunkGenerator delegate; + private ConfigPack pack; + + public FabricChunkGeneratorWrapper(Registry noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack, + RegistryEntry settingsSupplier) { + super(noiseRegistry, Optional.empty(), biomeSource); + this.noiseRegistry = noiseRegistry; + this.pack = configPack; + this.settings = settingsSupplier; + + this.delegate = pack.getGeneratorProvider().newInstance(pack); + logger.info("Loading world with config pack {}", pack.getID()); + this.biomeSource = biomeSource; + } + + public Registry getNoiseRegistry() { + return noiseRegistry; + } + + @Override + protected Codec getCodec() { + return Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER; + } + + @Override + public void buildSurface(ChunkRegion region, StructureAccessor structures, NoiseConfig noiseConfig, Chunk chunk) { + // no op + } + + @Override + public void populateEntities(ChunkRegion region) { + if(!this.settings.value().mobGenerationDisabled()) { + ChunkPos chunkPos = region.getCenterPos(); + RegistryEntry registryEntry = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1)); + ChunkRandom chunkRandom = new ChunkRandom(new CheckedRandom(RandomSeed.getSeed())); + chunkRandom.setPopulationSeed(region.getSeed(), chunkPos.getStartX(), chunkPos.getStartZ()); + SpawnHelper.populateEntities(region, registryEntry, chunkPos, chunkRandom); + } + } + + @Override + public int getWorldHeight() { + return settings.value().generationShapeConfig().height(); + } + + + @Override + public CompletableFuture populateNoise(Executor executor, Blender blender, NoiseConfig noiseConfig, + StructureAccessor structureAccessor, Chunk chunk) { + return CompletableFuture.supplyAsync(() -> { + ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); + BiomeProvider biomeProvider = pack.getBiomeProvider(); + delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z); + + PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class); + if(compatibilityOptions.isBeard()) { + beard(structureAccessor, chunk, world, biomeProvider, compatibilityOptions); + } + return chunk; + }, Util.getMainWorkerExecutor()); + } + + private void beard(StructureAccessor structureAccessor, Chunk chunk, WorldProperties world, BiomeProvider biomeProvider, + PreLoadCompatibilityOptions compatibilityOptions) { + StructureWeightSampler structureWeightSampler = StructureWeightSampler.method_42695(structureAccessor, chunk.getPos()); + double threshold = compatibilityOptions.getBeardThreshold(); + double airThreshold = compatibilityOptions.getAirThreshold(); + int xi = chunk.getPos().x << 4; + int zi = chunk.getPos().z << 4; + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { + int depth = 0; + for(int y = world.getMaxHeight(); y >= world.getMinHeight(); y--) { + double noise = structureWeightSampler.sample(new UnblendedNoisePos(x + xi, y, z + zi)); + if(noise > threshold) { + chunk.setBlockState(new BlockPos(x, y, z), (BlockState) delegate + .getPalette(x + xi, y, z + zi, world, biomeProvider) + .get(depth, x + xi, y, z + zi, world.getSeed()), false); + depth++; + } else if(noise < airThreshold) { + chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.getDefaultState(), false); + } else { + depth = 0; + } + } + } + } + } + + @Override + public void generateFeatures(StructureWorldAccess world, Chunk chunk, StructureAccessor structureAccessor) { + super.generateFeatures(world, chunk, structureAccessor); + pack.getStages().forEach(populator -> { + if(!(populator instanceof Chunkified)) { + populator.populate((ProtoWorld) world); + } + }); + } + + @Override + public int getSeaLevel() { + return settings.value().seaLevel(); + } + + @Override + public int getMinimumY() { + return settings.value().generationShapeConfig().minimumY(); + } + + + @Override + public int getHeight(int x, int z, Type heightmap, HeightLimitView height, NoiseConfig noiseConfig) { + WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); + BiomeProvider biomeProvider = pack.getBiomeProvider(); + int min = height.getBottomY(); + for(int y = height.getTopY() - 1; y >= min; y--) { + if(heightmap + .getBlockPredicate() + .test((BlockState) delegate.getBlock(properties, x, y, z, biomeProvider))) return y + 1; + } + return min; + } + + @Override + public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height, NoiseConfig noiseConfig) { + BlockState[] array = new BlockState[height.getHeight()]; + WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); + BiomeProvider biomeProvider = pack.getBiomeProvider(); + for(int y = height.getTopY() - 1; y >= height.getBottomY(); y--) { + array[y - height.getBottomY()] = (BlockState) delegate.getBlock(properties, x, y, z, biomeProvider); + } + return new VerticalBlockSample(height.getBottomY(), array); + } + + @Override + public void getDebugHudText(List text, NoiseConfig noiseConfig, BlockPos pos) { + + } + + public ConfigPack getPack() { + return pack; + } + + public void setPack(ConfigPack pack) { + this.pack = pack; + this.delegate = pack.getGeneratorProvider().newInstance(pack); + biomeSource.setPack(pack); + + logger.debug("Loading world with config pack {}", pack.getID()); + } + + @Override + public void carve(ChunkRegion chunkRegion, long seed, NoiseConfig noiseConfig, BiomeAccess world, StructureAccessor structureAccessor, + Chunk chunk, Carver carverStep) { + // no op + } + + @Override + public ChunkGenerator getHandle() { + return delegate; + } + + public RegistryEntry getSettings() { + return settings; + } + + @Override + public TerraBiomeSource getBiomeSource() { + return biomeSource; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java new file mode 100644 index 000000000..b43b38ce8 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java @@ -0,0 +1,86 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.generation; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.forge.data.Codecs; +import com.dfsek.terra.forge.util.ProtoPlatformBiome; + +import com.dfsek.terra.forge.util.SeedHack; + +import com.mojang.serialization.Codec; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.biome.source.BiomeSource; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.stream.StreamSupport; + + +public class TerraBiomeSource extends BiomeSource { + + private static final Logger LOGGER = LoggerFactory.getLogger(TerraBiomeSource.class); + private final Registry biomeRegistry; + private ConfigPack pack; + + public TerraBiomeSource(Registry biomes, ConfigPack pack) { + super(StreamSupport + .stream(pack.getBiomeProvider() + .getBiomes() + .spliterator(), false) + .map(b -> biomes.getOrCreateEntry(((ProtoPlatformBiome) b.getPlatformBiome()).getDelegate()))); + this.biomeRegistry = biomes; + this.pack = pack; + + LOGGER.debug("Biomes: " + getBiomes()); + } + + @Override + protected Codec getCodec() { + return Codecs.TERRA_BIOME_SOURCE; + } + + @Override + public RegistryEntry getBiome(int biomeX, int biomeY, int biomeZ, MultiNoiseSampler noiseSampler) { + return biomeRegistry + .entryOf(((ProtoPlatformBiome) pack + .getBiomeProvider() + .getBiome(biomeX << 2, biomeY << 2, biomeZ << 2, SeedHack.getSeed(noiseSampler)) + .getPlatformBiome()).getDelegate() + ); + } + + public BiomeProvider getProvider() { + return pack.getBiomeProvider(); + } + + public Registry getBiomeRegistry() { + return biomeRegistry; + } + + public ConfigPack getPack() { + return pack; + } + + public void setPack(ConfigPack pack) { + this.pack = pack; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricItemHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricItemHandle.java new file mode 100644 index 000000000..cc7b0d1a6 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricItemHandle.java @@ -0,0 +1,58 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.handle; + +import com.dfsek.terra.forge.ForgeEntryPoint; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.command.argument.ItemStackArgumentType; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +import java.util.Set; +import java.util.stream.Collectors; + +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.item.Enchantment; + + +public class FabricItemHandle implements ItemHandle { + + @Override + public Item createItem(String data) { + try { + return (Item) new ItemStackArgumentType(new CommandRegistryAccess( + ForgeEntryPoint.getPlatform().getServer().getRegistryManager())).parse(new StringReader(data)).getItem(); + } catch(CommandSyntaxException e) { + throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); + } + } + + @Override + public Enchantment getEnchantment(String id) { + return (Enchantment) (Registry.ENCHANTMENT.get(Identifier.tryParse(id))); + } + + @Override + public Set getEnchantments() { + return Registry.ENCHANTMENT.stream().map(enchantment -> (Enchantment) enchantment).collect(Collectors.toSet()); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricWorldHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricWorldHandle.java new file mode 100644 index 000000000..dd47858b8 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricWorldHandle.java @@ -0,0 +1,59 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.handle; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.block.Blocks; +import net.minecraft.command.argument.BlockArgumentParser; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraftforge.registries.ForgeRegistries; +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.handle.WorldHandle; + + +public class FabricWorldHandle implements WorldHandle { + + private static final BlockState AIR = (BlockState) Blocks.AIR.getDefaultState(); + + @Override + public @NotNull BlockState createBlockState(@NotNull String data) { + try { + net.minecraft.block.BlockState state = BlockArgumentParser.block(Registry.BLOCK, data, true).blockState(); + if(state == null) throw new IllegalArgumentException("Invalid data: " + data); + return (BlockState) state; + } catch(CommandSyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public @NotNull BlockState air() { + return AIR; + } + + @Override + public @NotNull EntityType getEntity(@NotNull String id) { + Identifier identifier = Identifier.tryParse(id); + if(identifier == null) identifier = Identifier.tryParse(id); + return (EntityType) ForgeRegistries.ENTITIES.getHolder(identifier).orElseThrow().value(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/ChunkRegionAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/ChunkRegionAccessor.java new file mode 100644 index 000000000..58624dfe9 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/ChunkRegionAccessor.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.forge.mixin.access; + +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.chunk.Chunk; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + + +@Mixin(ChunkRegion.class) +public interface ChunkRegionAccessor { + @Accessor("chunks") + List getChunks(); +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/MobSpawnerLogicAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/MobSpawnerLogicAccessor.java new file mode 100644 index 000000000..20a900005 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/MobSpawnerLogicAccessor.java @@ -0,0 +1,30 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.access; + +import net.minecraft.world.MobSpawnerEntry; +import net.minecraft.world.MobSpawnerLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + + +@Mixin(MobSpawnerLogic.class) +public interface MobSpawnerLogicAccessor { + @Accessor("spawnEntry") + MobSpawnerEntry getSpawnEntry(); +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StateAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StateAccessor.java new file mode 100644 index 000000000..947118da9 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StateAccessor.java @@ -0,0 +1,35 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.access; + +import net.minecraft.state.State; +import net.minecraft.state.property.Property; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; +import java.util.function.Function; + + +@Mixin(State.class) +public interface StateAccessor { + @Accessor("PROPERTY_MAP_PRINTER") + static Function, Comparable>, String> getPropertyMapPrinter() { + throw new UnsupportedOperationException(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StructureAccessorAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StructureAccessorAccessor.java new file mode 100644 index 000000000..12ca75c9d --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StructureAccessorAccessor.java @@ -0,0 +1,30 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.access; + +import net.minecraft.world.WorldAccess; +import net.minecraft.world.gen.StructureAccessor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + + +@Mixin(StructureAccessor.class) +public interface StructureAccessorAccessor { + @Accessor + WorldAccess getWorld(); +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java new file mode 100644 index 000000000..53b2ac21d --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.forge.mixin.fix; + +import com.dfsek.terra.forge.ForgeEntryPoint; + +import net.minecraft.entity.passive.BeeEntity.MoveToFlowerGoal; +import net.minecraft.entity.passive.BeeEntity.MoveToHiveGoal; +import net.minecraft.util.math.random.CheckedRandom; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + + +/** + * Bees spawning uses world.random without synchronization. This causes issues when spawning bees during world generation. + */ +@Mixin({ + MoveToHiveGoal.class, + MoveToFlowerGoal.class +}) +public class BeeMoveGoalsUnsynchronizedRandomAccessFix { + @Redirect(method = "", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;random:Lnet/minecraft/util/math/random/Random;")) + public Random redirectRandomAccess(World instance) { + return new CheckedRandom(ForgeEntryPoint.getPlatform().getServer().getTicks()); // replace with new random seeded by tick time. + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java new file mode 100644 index 000000000..c8def7e88 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.forge.mixin.fix; + +import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; + +import net.minecraft.world.gen.structure.NetherFossilStructure; +import net.minecraft.world.gen.structure.Structure.Context; +import net.minecraft.world.gen.structure.Structure.StructurePosition; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; + + +/** + * Disable fossil generation in Terra worlds, as they are very expensive due to consistently triggering cache misses. + * + * Currently, on Fabric, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in nether. + */ +@Mixin(NetherFossilStructure.class) +public class NetherFossilOptimization { + @Inject(method = "getStructurePosition", at = @At("HEAD"), cancellable = true) + public void injectFossilPositions(Context context, CallbackInfoReturnable> cir) { + if(context.chunkGenerator() instanceof FabricChunkGeneratorWrapper) { + cir.setReturnValue(Optional.empty()); + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java new file mode 100644 index 000000000..19639e48a --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.forge.mixin.implementations.compat; + +import com.dfsek.terra.forge.mixin_ifaces.FloraFeatureHolder; + +import net.minecraft.world.biome.GenerationSettings; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + + +@Mixin(GenerationSettings.class) +@Implements(@Interface(iface = FloraFeatureHolder.class, prefix = "terra$")) +public class GenerationSettingsFloraFeaturesMixin { + private List> flora; + + public void terra$setFloraFeatures(List> features) { + this.flora = features; + } + + @Inject(method = "getFlowerFeatures", cancellable = true, at = @At("HEAD")) + public void inject(CallbackInfoReturnable>> cir) { + if(flora != null) { + cir.setReturnValue(flora); + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/BiomeMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/BiomeMixin.java new file mode 100644 index 000000000..3bf07cffc --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/BiomeMixin.java @@ -0,0 +1,31 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra; + +import net.minecraft.world.biome.Biome; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.world.biome.PlatformBiome; + + +@Mixin(Biome.class) +@Implements(@Interface(iface = PlatformBiome.class, prefix = "terra$")) +public abstract class BiomeMixin { +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/HandleImplementationMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/HandleImplementationMixin.java new file mode 100644 index 000000000..936af09b3 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/HandleImplementationMixin.java @@ -0,0 +1,61 @@ +package com.dfsek.terra.forge.mixin.implementations.terra; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.LockableContainerBlockEntity; +import net.minecraft.block.entity.LootableContainerBlockEntity; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.ProtoChunk; +import net.minecraft.world.chunk.WorldChunk; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.Handle; + + +/** + * A ton of Minecraft classes must implement Handle identically, we can just take care of it here + */ +@Mixin({ + ServerWorld.class, + ChunkRegion.class, + + Block.class, + BlockState.class, + + BlockEntity.class, + LootableContainerBlockEntity.class, + LockableContainerBlockEntity.class, + + ProtoChunk.class, + WorldChunk.class, + + Entity.class, + EntityType.class, + + ServerCommandSource.class, + + Item.class, + ItemStack.class, + Enchantment.class, + + Biome.class +}) +@Implements(@Interface(iface = Handle.class, prefix = "terra$")) +public class HandleImplementationMixin { + @Intrinsic + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/BlockMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/BlockMixin.java new file mode 100644 index 000000000..8df67e40a --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/BlockMixin.java @@ -0,0 +1,44 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.block; + +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.block.BlockType; + + +@Mixin(Block.class) +@Implements(@Interface(iface = BlockType.class, prefix = "terra$")) +public abstract class BlockMixin { + public com.dfsek.terra.api.block.state.BlockState terra$getDefaultState() { + return (com.dfsek.terra.api.block.state.BlockState) ((Block) (Object) this).getDefaultState(); + } + + public boolean terra$isSolid() { + return ((Block) (Object) this).getDefaultState().isOpaque(); + } + + @SuppressWarnings("ConstantConditions") + public boolean terra$isWater() { + return ((Object) this) == Blocks.WATER; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/BlockEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/BlockEntityMixin.java new file mode 100644 index 000000000..272c18812 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/BlockEntityMixin.java @@ -0,0 +1,54 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.block.entity; + +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; + + +@Mixin(net.minecraft.block.entity.BlockEntity.class) +@Implements(@Interface(iface = BlockEntity.class, prefix = "terra$")) +public abstract class BlockEntityMixin { + public boolean terra$update(boolean applyPhysics) { + if(((net.minecraft.block.entity.BlockEntity) (Object) this).hasWorld()) //noinspection ConstantConditions + ((net.minecraft.block.entity.BlockEntity) (Object) this).getWorld().getChunk( + ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos()).setBlockEntity( + (net.minecraft.block.entity.BlockEntity) (Object) this); + return true; + } + + public int terra$getX() { + return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getX(); + } + + public int terra$getY() { + return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getY(); + } + + public int terra$getZ() { + return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getZ(); + } + + public BlockState terra$getBlockState() { + return (BlockState) ((net.minecraft.block.entity.BlockEntity) (Object) this).getCachedState(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java new file mode 100644 index 000000000..123541696 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java @@ -0,0 +1,35 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.block.entity; + +import net.minecraft.block.entity.LootableContainerBlockEntity; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.inventory.Inventory; + + +@Mixin(LootableContainerBlockEntity.class) +@Implements(@Interface(iface = Container.class, prefix = "terra$")) +public abstract class LootableContainerBlockEntityMixin extends BlockEntityMixin { + public Inventory terra$getInventory() { + return (Inventory) this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java new file mode 100644 index 000000000..60bafaefb --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java @@ -0,0 +1,131 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.block.entity; + +import com.dfsek.terra.forge.ForgeEntryPoint; +import com.dfsek.terra.forge.mixin.access.MobSpawnerLogicAccessor; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.MobSpawnerLogic; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.block.entity.MobSpawner; +import com.dfsek.terra.api.block.entity.SerialState; +import com.dfsek.terra.api.entity.EntityType; + + +@Mixin(MobSpawnerBlockEntity.class) +@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$")) +public abstract class MobSpawnerBlockEntityMixin extends BlockEntity { + private MobSpawnerBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Shadow + public abstract MobSpawnerLogic getLogic(); + + public EntityType terra$getSpawnedType() { + return (EntityType) Registry.ENTITY_TYPE.get( + Identifier.tryParse(((MobSpawnerLogicAccessor) getLogic()).getSpawnEntry().getNbt().getString("id"))); + } + + public void terra$setSpawnedType(@NotNull EntityType creatureType) { + getLogic().setEntityId((net.minecraft.entity.EntityType) creatureType); + } + + public int terra$getDelay() { + return 0; + } + + public void terra$setDelay(int delay) { + + } + + public int terra$getMinSpawnDelay() { + return 0; + } + + public void terra$setMinSpawnDelay(int delay) { + + } + + public int terra$getMaxSpawnDelay() { + return 0; + } + + public void terra$setMaxSpawnDelay(int delay) { + + } + + public int terra$getSpawnCount() { + return 0; + } + + public void terra$setSpawnCount(int spawnCount) { + + } + + public int terra$getMaxNearbyEntities() { + return 0; + } + + public void terra$setMaxNearbyEntities(int maxNearbyEntities) { + + } + + public int terra$getRequiredPlayerRange() { + return 0; + } + + public void terra$setRequiredPlayerRange(int requiredPlayerRange) { + + } + + public int terra$getSpawnRange() { + return 0; + } + + public void terra$setSpawnRange(int spawnRange) { + + } + + public void terra$applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + switch(k) { + case "type" -> terra$setSpawnedType(ForgeEntryPoint.getPlatform().getWorldHandle().getEntity(v)); + case "delay" -> terra$setDelay(Integer.parseInt(v)); + case "min_delay" -> terra$setMinSpawnDelay(Integer.parseInt(v)); + case "max_delay" -> terra$setMaxSpawnDelay(Integer.parseInt(v)); + case "spawn_count" -> terra$setSpawnCount(Integer.parseInt(v)); + case "spawn_range" -> terra$setSpawnRange(Integer.parseInt(v)); + case "max_nearby" -> terra$setMaxNearbyEntities(Integer.parseInt(v)); + case "required_player_range" -> terra$setRequiredPlayerRange(Integer.parseInt(v)); + default -> throw new IllegalArgumentException("Invalid property: " + k); + } + }); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java new file mode 100644 index 000000000..400a176ca --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java @@ -0,0 +1,65 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.block.entity; + +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.text.Text; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.block.entity.SerialState; +import com.dfsek.terra.api.block.entity.Sign; + + +@Mixin(SignBlockEntity.class) +@Implements(@Interface(iface = Sign.class, prefix = "terra$")) +public abstract class SignBlockEntityMixin { + @Shadow + @Final + private Text[] texts; + + @Shadow + public abstract void setTextOnRow(int row, Text text); + + public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { + setTextOnRow(index, Text.literal(line)); + } + + public @NotNull String[] terra$getLines() { + String[] lines = new String[texts.length]; + for(int i = 0; i < texts.length; i++) { + lines[i] = texts[i].getString(); + } + return lines; + } + + public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException { + return texts[index].getString(); + } + + public void terra$applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); + terra$setLine(Integer.parseInt(k.substring(4)), v); + }); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/BlockStateMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/BlockStateMixin.java new file mode 100644 index 000000000..c0076820c --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/BlockStateMixin.java @@ -0,0 +1,83 @@ +package com.dfsek.terra.forge.mixin.implementations.terra.block.state; + + +import com.dfsek.terra.forge.mixin.access.StateAccessor; +import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.MapCodec; +import net.minecraft.block.AbstractBlock.AbstractBlockState; +import net.minecraft.block.Block; +import net.minecraft.state.State; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.stream.Collectors; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.block.state.properties.Property; + + +@Mixin(AbstractBlockState.class) +@Implements(@Interface(iface = BlockState.class, prefix = "terra$")) +public abstract class BlockStateMixin extends State { + private BlockStateMixin(Block owner, ImmutableMap, Comparable> entries, + MapCodec codec) { + super(owner, entries, codec); + } + + @Shadow + public abstract Block getBlock(); + + @Shadow + public abstract boolean isAir(); + + public boolean terra$matches(BlockState other) { + return getBlock() == ((net.minecraft.block.BlockState) other).getBlock(); + } + + @Intrinsic + public > boolean terra$has(Property property) { + if(property instanceof net.minecraft.state.property.Property minecraftProperty) { + return contains(minecraftProperty); + } + return false; + } + + @SuppressWarnings("unchecked") + @Intrinsic + public > T terra$get(Property property) { + return get((net.minecraft.state.property.Property) property); + } + + @SuppressWarnings("unchecked") + @Intrinsic + public > BlockState terra$set(Property property, T value) { + return (BlockState) with((net.minecraft.state.property.Property) property, value); + } + + @Intrinsic + public BlockType terra$getBlockType() { + return (BlockType) getBlock(); + } + + @Intrinsic + public String terra$getAsString(boolean properties) { + StringBuilder data = new StringBuilder(Registry.BLOCK.getId(getBlock()).toString()); + if(properties && !getEntries().isEmpty()) { + data.append('['); + data.append( + getEntries().entrySet().stream().map(StateAccessor.getPropertyMapPrinter()).collect(Collectors.joining(","))); + data.append(']'); + } + return data.toString(); + } + + @Intrinsic + public boolean terra$isAir() { + return isAir(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/PropertyMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/PropertyMixin.java new file mode 100644 index 000000000..ce7d41e20 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/PropertyMixin.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.forge.mixin.implementations.terra.block.state; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Interface.Remap; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Collection; + +import com.dfsek.terra.api.block.state.properties.Property; + + +@Mixin(net.minecraft.state.property.Property.class) +@Implements(@Interface(iface = Property.class, prefix = "terra$", remap = Remap.NONE)) +public abstract class PropertyMixin { + @Shadow + @Final + private Class type; + @Shadow + @Final + private String name; + + @Shadow + public abstract Collection getValues(); + + @Intrinsic + public Collection terra$values() { + return getValues(); + } + + @Intrinsic + public Class terra$getType() { + return type; + } + + @Intrinsic + public String terra$getID() { + return name; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/ChunkRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/ChunkRegionMixin.java new file mode 100644 index 000000000..96bbe0715 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/ChunkRegionMixin.java @@ -0,0 +1,58 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.chunk; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ChunkRegion; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.chunk.Chunk; + + +@Mixin(ChunkRegion.class) +@Implements(@Interface(iface = Chunk.class, prefix = "terraChunk$")) +public abstract class ChunkRegionMixin { + + @Shadow + @Final + private net.minecraft.world.chunk.Chunk centerPos; + + public void terraChunk$setBlock(int x, int y, int z, @NotNull BlockState blockState, boolean physics) { + ((ChunkRegion) (Object) this).setBlockState(new BlockPos(x + (centerPos.getPos().x << 4), y, z + (centerPos.getPos().z << 4)), + (net.minecraft.block.BlockState) blockState, 0); + } + + public @NotNull BlockState terraChunk$getBlock(int x, int y, int z) { + return (BlockState) ((ChunkRegion) (Object) this).getBlockState( + new BlockPos(x + (centerPos.getPos().x << 4), y, z + (centerPos.getPos().z << 4))); + } + + public int terraChunk$getX() { + return centerPos.getPos().x; + } + + public int terraChunk$getZ() { + return centerPos.getPos().z; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/WorldChunkMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/WorldChunkMixin.java new file mode 100644 index 000000000..b6aecff61 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/WorldChunkMixin.java @@ -0,0 +1,75 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.chunk; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.WorldChunk; +import org.jetbrains.annotations.NotNull; +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; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.chunk.Chunk; + + +@Mixin(WorldChunk.class) +@Implements(@Interface(iface = Chunk.class, prefix = "terra$")) +public abstract class WorldChunkMixin { + @Final + @Shadow + net.minecraft.world.World world; + + @Shadow + public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos); + + @Shadow + @Nullable + public abstract net.minecraft.block.BlockState setBlockState(BlockPos pos, net.minecraft.block.BlockState state, boolean moved); + + public void terra$setBlock(int x, int y, int z, BlockState data, boolean physics) { + setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) data, false); + } + + public void terra$setBlock(int x, int y, int z, @NotNull BlockState blockState) { + ((net.minecraft.world.chunk.Chunk) (Object) this).setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) blockState, + false); + } + + @Intrinsic + public @NotNull BlockState terra$getBlock(int x, int y, int z) { + return (BlockState) getBlockState(new BlockPos(x, y, z)); + } + + public int terra$getX() { + return ((net.minecraft.world.chunk.Chunk) (Object) this).getPos().x; + } + + public int terra$getZ() { + return ((net.minecraft.world.chunk.Chunk) (Object) this).getPos().z; + } + + public ServerWorld terra$getWorld() { + return (ServerWorld) world; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java new file mode 100644 index 000000000..918df4f42 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java @@ -0,0 +1,53 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.chunk.data; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.HeightLimitView; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + + +@Mixin(net.minecraft.world.chunk.ProtoChunk.class) +@Implements(@Interface(iface = ProtoChunk.class, prefix = "terra$")) +public abstract class ProtoChunkMixin { + @Shadow + public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos); + + @Shadow + public abstract HeightLimitView getHeightLimitView(); + + public void terra$setBlock(int x, int y, int z, @NotNull BlockState blockState) { + ((net.minecraft.world.chunk.Chunk) (Object) this).setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) blockState, + false); + } + + public @NotNull BlockState terra$getBlock(int x, int y, int z) { + return (BlockState) getBlockState(new BlockPos(x, y, z)); + } + + public int terra$getMaxHeight() { + return getHeightLimitView().getTopY(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java new file mode 100644 index 000000000..96e7be2d5 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java @@ -0,0 +1,55 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.entity; + +import com.dfsek.terra.forge.util.FabricAdapter; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; + + +@Mixin(Entity.class) +@Implements(@Interface(iface = com.dfsek.terra.api.entity.Entity.class, prefix = "terra$")) +public abstract class EntityMixin { + @Shadow + public net.minecraft.world.World world; + + @Shadow + private BlockPos blockPos; + + @Shadow + public abstract void teleport(double destX, double destY, double destZ); + + public Vector3 terra$position() { + return FabricAdapter.adapt(blockPos); + } + + public void terra$position(Vector3 location) { + teleport(location.getX(), location.getY(), location.getZ()); + } + + public ServerWorld terra$world() { + return (ServerWorld) world; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityTypeMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityTypeMixin.java new file mode 100644 index 000000000..1c73c1efb --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityTypeMixin.java @@ -0,0 +1,29 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.entity; + +import net.minecraft.entity.EntityType; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + + +@Mixin(EntityType.class) +@Implements(@Interface(iface = com.dfsek.terra.api.entity.EntityType.class, prefix = "terra$")) +public abstract class EntityTypeMixin { +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/PlayerEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/PlayerEntityMixin.java new file mode 100644 index 000000000..f08df6293 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/PlayerEntityMixin.java @@ -0,0 +1,31 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.entity; + +import net.minecraft.entity.player.PlayerEntity; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.entity.Player; + + +@Mixin(PlayerEntity.class) +@Implements(@Interface(iface = Player.class, prefix = "terra$")) +public abstract class PlayerEntityMixin extends EntityMixin { +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/ServerCommandSourceMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/ServerCommandSourceMixin.java new file mode 100644 index 000000000..ce91be261 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/ServerCommandSourceMixin.java @@ -0,0 +1,66 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.entity; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Optional; + +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.Player; + + +@Mixin(ServerCommandSource.class) +@Implements(@Interface(iface = CommandSender.class, prefix = "terra$")) +public abstract class ServerCommandSourceMixin { + @Shadow + public abstract void sendFeedback(Text message, boolean broadcastToOps); + + @Shadow + public abstract ServerPlayerEntity getPlayer() throws CommandSyntaxException; + + @Shadow + @Nullable + public abstract net.minecraft.entity.@Nullable Entity getEntity(); + + public void terra$sendMessage(String message) { + sendFeedback(Text.literal(message), true); + } + + @Nullable + public Optional terra$getEntity() { + return Optional.ofNullable((Entity) getEntity()); + } + + public Optional terra$getPlayer() { + try { + return Optional.ofNullable((Player) getPlayer()); + } catch(CommandSyntaxException e) { + return Optional.empty(); + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java new file mode 100644 index 000000000..40f6111db --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java @@ -0,0 +1,47 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.inventory; + +import net.minecraft.block.entity.LockableContainerBlockEntity; +import net.minecraft.item.Items; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.inventory.Inventory; +import com.dfsek.terra.api.inventory.ItemStack; + + +@Mixin(LockableContainerBlockEntity.class) +@Implements(@Interface(iface = Inventory.class, prefix = "terra$")) +public class LockableContainerBlockEntityMixin { + @SuppressWarnings("ConstantConditions") + public void terra$setItem(int slot, ItemStack newStack) { + ((LockableContainerBlockEntity) (Object) this).setStack(slot, (net.minecraft.item.ItemStack) (Object) newStack); + } + + public int terra$getSize() { + return ((LockableContainerBlockEntity) (Object) this).size(); + } + + @SuppressWarnings("ConstantConditions") + public ItemStack terra$getItem(int slot) { + net.minecraft.item.ItemStack itemStack = ((LockableContainerBlockEntity) (Object) this).getStack(slot); + return itemStack.getItem() == Items.AIR ? null : (ItemStack) (Object) itemStack; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemMixin.java new file mode 100644 index 000000000..e48b5341c --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemMixin.java @@ -0,0 +1,43 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.inventory.item; + +import net.minecraft.item.Item; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.inventory.ItemStack; + + +@Mixin(Item.class) +@Implements(@Interface(iface = com.dfsek.terra.api.inventory.Item.class, prefix = "terra$")) +public abstract class ItemMixin { + @Shadow + public abstract int getMaxDamage(); + + @SuppressWarnings("ConstantConditions") + public ItemStack terra$newItemStack(int amount) { + return (ItemStack) (Object) new net.minecraft.item.ItemStack((Item) (Object) this, amount); + } + + public double terra$getMaxDurability() { + return getMaxDamage(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemStackMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemStackMixin.java new file mode 100644 index 000000000..7bb42595a --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemStackMixin.java @@ -0,0 +1,76 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.inventory.item; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.item.ItemMeta; + + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = com.dfsek.terra.api.inventory.ItemStack.class, prefix = "terra$")) +public abstract class ItemStackMixin { + @Shadow + public abstract int getCount(); + + @Shadow + public abstract void setCount(int count); + + @Shadow + public abstract net.minecraft.item.Item getItem(); + + @Shadow + public abstract boolean isDamageable(); + + @Shadow + public abstract void setNbt(@Nullable NbtCompound tag); + + public int terra$getAmount() { + return getCount(); + } + + public void terra$setAmount(int i) { + setCount(i); + } + + public Item terra$getType() { + return (Item) getItem(); + } + + public ItemMeta terra$getItemMeta() { + return (ItemMeta) this; + } + + @SuppressWarnings("ConstantConditions") + public void terra$setItemMeta(ItemMeta meta) { + setNbt(((ItemStack) (Object) meta).getNbt()); + } + + @Intrinsic + public boolean terra$isDamageable() { + return isDamageable(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java new file mode 100644 index 000000000..358cd7a95 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java @@ -0,0 +1,53 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.inventory.meta; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Objects; + +import com.dfsek.terra.api.inventory.ItemStack; + + +@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); + + @Shadow + public abstract boolean canCombine(Enchantment other); + + @SuppressWarnings("ConstantConditions") + public boolean terra$canEnchantItem(ItemStack itemStack) { + return isAcceptableItem((net.minecraft.item.ItemStack) (Object) itemStack); + } + + public boolean terra$conflictsWith(com.dfsek.terra.api.inventory.item.Enchantment other) { + return !canCombine((Enchantment) other); + } + + public String terra$getID() { + return Objects.requireNonNull(Registry.ENCHANTMENT.getId((Enchantment) (Object) this)).toString(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java new file mode 100644 index 000000000..d70b1732d --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java @@ -0,0 +1,55 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.inventory.meta; + +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.inventory.item.Damageable; + + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = Damageable.class, prefix = "terra$")) +public abstract class ItemStackDamageableMixin { + @Shadow + public abstract boolean isDamaged(); + + @Shadow + public abstract int getDamage(); + + @Shadow + public abstract void setDamage(int damage); + + @Intrinsic + public int terra$getDamage() { + return getDamage(); + } + + @Intrinsic + public void terra$setDamage(int damage) { + setDamage(damage); + } + + public boolean terra$hasDamage() { + return isDamaged(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java new file mode 100644 index 000000000..17bf068a1 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java @@ -0,0 +1,65 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.inventory.meta; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtList; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.api.inventory.item.ItemMeta; + + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$")) +public abstract class ItemStackMetaMixin { + @Shadow + public abstract boolean hasEnchantments(); + + @Shadow + public abstract NbtList getEnchantments(); + + @Shadow + public abstract void addEnchantment(net.minecraft.enchantment.Enchantment enchantment, int level); + + public void terra$addEnchantment(Enchantment enchantment, int level) { + addEnchantment((net.minecraft.enchantment.Enchantment) enchantment, level); + } + + @Intrinsic(displace = true) + public Map terra$getEnchantments() { + if(!hasEnchantments()) return Collections.emptyMap(); + Map map = new HashMap<>(); + + getEnchantments().forEach(enchantment -> { + NbtCompound eTag = (NbtCompound) enchantment; + map.put((Enchantment) Registry.ENCHANTMENT.get(eTag.getInt("id")), eTag.getInt("lvl")); + }); + return map; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/package-info.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/package-info.java new file mode 100644 index 000000000..0899793d3 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +/** + * Mixins in this package implement Terra + * interfaces in Minecraft classes. + */ + +package com.dfsek.terra.forge.mixin.implementations.terra; \ No newline at end of file diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java new file mode 100644 index 000000000..6ba8768ab --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -0,0 +1,149 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.world; + +import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import net.minecraft.block.FluidBlock; +import net.minecraft.fluid.Fluid; +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.tick.MultiTickScheduler; +import net.minecraft.world.tick.OrderedTick; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +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; + +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; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.forge.util.FabricUtil; + + +@Mixin(ChunkRegion.class) +@Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$")) +public abstract class ChunkRegionMixin { + private ConfigPack terra$config; + + + @Shadow + @Final + private net.minecraft.server.world.ServerWorld world; + + @Shadow + @Final + private long seed; + @Shadow + @Final + private Chunk centerPos; + + @Shadow + @Final + private MultiTickScheduler fluidTickScheduler; + + + @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) { + this.terra$config = ((ServerWorld) world).getPack(); + } + + + @Intrinsic(displace = true) + public void terraWorld$setBlockState(int x, int y, int z, BlockState data, boolean physics) { + BlockPos pos = new BlockPos(x, y, z); + ((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( + (net.minecraft.block.BlockState) data).getFluid(), pos)); + } + } + + @Intrinsic + public long terraWorld$getSeed() { + return seed; + } + + public int terraWorld$getMaxHeight() { + return world.getTopY(); + } + + @Intrinsic(displace = true) + public BlockState terraWorld$getBlockState(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return (BlockState) ((ChunkRegion) (Object) this).getBlockState(pos); + } + + public BlockEntity terraWorld$getBlockEntity(int x, int y, int z) { + return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); + } + + public int terraWorld$getMinHeight() { + return world.getBottomY(); + } + + public ChunkGenerator terraWorld$getGenerator() { + return ((FabricChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle(); + } + + public BiomeProvider terraWorld$getBiomeProvider() { + return terra$config.getBiomeProvider(); + } + + public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(world); + entity.setPos(x, y, z); + ((ChunkRegion) (Object) this).spawnEntity(entity); + return (Entity) entity; + } + + public int terraWorld$centerChunkX() { + return centerPos.getPos().x; + } + + public int terraWorld$centerChunkZ() { + return centerPos.getPos().z; + } + + public ServerWorld terraWorld$getWorld() { + return (ServerWorld) world; + } + + public ConfigPack terraWorld$getPack() { + return terra$config; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java new file mode 100644 index 000000000..fc9158d4c --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java @@ -0,0 +1,102 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.implementations.terra.world; + +import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.TerraBiomeSource; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.WorldAccess; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.Chunk; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.forge.util.FabricUtil; + + +@Mixin(net.minecraft.server.world.ServerWorld.class) +@Implements(@Interface(iface = ServerWorld.class, prefix = "terra$")) +public abstract class ServerWorldMixin { + public Entity terra$spawnEntity(double x, double y, double z, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(null); + entity.setPos(x, y, z); + ((net.minecraft.server.world.ServerWorld) (Object) this).spawnEntity(entity); + return (Entity) entity; + } + + public void terra$setBlockState(int x, int y, int z, BlockState data, boolean physics) { + BlockPos pos = new BlockPos(x, y, z); + ((net.minecraft.server.world.ServerWorld) (Object) this).setBlockState(pos, (net.minecraft.block.BlockState) data, + physics ? 3 : 1042); + } + + @Intrinsic + public long terra$getSeed() { + return ((net.minecraft.server.world.ServerWorld) (Object) this).getSeed(); + } + + public int terra$getMaxHeight() { + return (((net.minecraft.server.world.ServerWorld) (Object) this).getBottomY()) + + ((net.minecraft.server.world.ServerWorld) (Object) this).getHeight(); + } + + public Chunk terra$getChunkAt(int x, int z) { + return (Chunk) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunk(x, z); + } + + public BlockState terra$getBlockState(int x, int y, int z) { + return (BlockState) ((net.minecraft.server.world.ServerWorld) (Object) this).getBlockState(new BlockPos(x, y, z)); + } + + public BlockEntity terra$getBlockEntity(int x, int y, int z) { + return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); + } + + public int terra$getMinHeight() { + return ((net.minecraft.server.world.ServerWorld) (Object) this).getBottomY(); + } + + public ChunkGenerator terra$getGenerator() { + return ((FabricChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() + .getChunkGenerator()).getHandle(); + } + + public BiomeProvider terra$getBiomeProvider() { + return ((TerraBiomeSource) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() + .getChunkGenerator() + .getBiomeSource()).getProvider(); + } + + public ConfigPack terra$getPack() { + net.minecraft.world.gen.chunk.ChunkGenerator generator = + (((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager()).getChunkGenerator(); + if(generator instanceof FabricChunkGeneratorWrapper fabricChunkGeneratorWrapper) { + return fabricChunkGeneratorWrapper.getPack(); + } + return null; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java new file mode 100644 index 000000000..fefb67df4 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.forge.mixin.lifecycle; + +import com.dfsek.terra.forge.util.BiomeUtil; +import com.dfsek.terra.forge.util.TagUtil; +import net.minecraft.server.DataPackContents; +import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.Biome; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(DataPackContents.class) +public class DataPackContentsMixin { + /* + * #refresh populates all tags in the registries + */ + @Inject(method = "refresh(Lnet/minecraft/util/registry/DynamicRegistryManager;)V", at = @At("RETURN")) + private void injectReload(DynamicRegistryManager dynamicRegistryManager, CallbackInfo ci) { + TagUtil.registerWorldPresetTags(dynamicRegistryManager.get(Registry.WORLD_PRESET_KEY)); + + Registry biomeRegistry = dynamicRegistryManager.get(Registry.BIOME_KEY); + TagUtil.registerBiomeTags(biomeRegistry); + BiomeUtil.registerFlora(biomeRegistry); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/MinecraftServerMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/MinecraftServerMixin.java new file mode 100644 index 000000000..a524a9df7 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/MinecraftServerMixin.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.forge.mixin.lifecycle; + +import com.dfsek.terra.forge.ForgeEntryPoint; + +import com.mojang.datafixers.DataFixer; +import net.minecraft.resource.ResourcePackManager; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.SaveLoader; +import net.minecraft.server.WorldGenerationProgressListenerFactory; +import net.minecraft.util.ApiServices; +import net.minecraft.world.level.storage.LevelStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.net.Proxy; + + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + @Inject(method = "(Ljava/lang/Thread;Lnet/minecraft/world/level/storage/LevelStorage$Session;" + + "Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/server/SaveLoader;Ljava/net/Proxy;" + + "Lcom/mojang/datafixers/DataFixer;Lnet/minecraft/util/ApiServices;" + + "Lnet/minecraft/server/WorldGenerationProgressListenerFactory;)V", + at = @At("RETURN")) + private void injectConstructor(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager, + SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices, + WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { + ForgeEntryPoint.getPlatform().setServer((MinecraftServer) (Object) this); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java new file mode 100644 index 000000000..67008fbba --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.forge.mixin.lifecycle; + +import com.dfsek.terra.forge.util.SeedHack; + +import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import net.minecraft.world.gen.noise.NoiseConfig; +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; + + +/** + * Hack to map noise sampler to seeds + */ +@Mixin(NoiseConfig.class) +public class NoiseConfigMixin { + @Shadow + @Final + private MultiNoiseSampler multiNoiseSampler; + + @Inject(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At("TAIL")) + private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, Registry noiseRegistry, long seed, CallbackInfo ci) { + SeedHack.register(multiNoiseSampler, seed); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java new file mode 100644 index 000000000..18633dc0f --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.forge.mixin.lifecycle; + + +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.dfsek.terra.forge.ForgeEntryPoint; + + +// Register Terra things to the builtin registries. +@Mixin(Registry.class) +public class RegistryMixin { + @Inject(method = "", at = @At("RETURN")) + private static void registerTerraGenerators(CallbackInfo ci) { + ForgeEntryPoint.register(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/client/MinecraftClientMixin.java new file mode 100644 index 000000000..ee2e01268 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/client/MinecraftClientMixin.java @@ -0,0 +1,41 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.lifecycle.client; + +import com.dfsek.terra.forge.util.LifecycleUtil; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.RunArgs; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin { + @Inject(method = "", at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/util/WindowProvider;createWindow" + + "(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)" + + "Lnet/minecraft/client/util/Window;", + // sorta arbitrary position, after mod init, before window opens + shift = At.Shift.BEFORE)) + public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { + LifecycleUtil.initialize(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/package-info.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/package-info.java new file mode 100644 index 000000000..eba8981f7 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/package-info.java @@ -0,0 +1,22 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +/** + * Mixins that inject behavior into the client/server lifecycle. + */ + +package com.dfsek.terra.forge.mixin.lifecycle; \ No newline at end of file diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/server/ServerMainMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/server/ServerMainMixin.java new file mode 100644 index 000000000..70d93969e --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/server/ServerMainMixin.java @@ -0,0 +1,40 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.mixin.lifecycle.server; + +import com.dfsek.terra.forge.util.LifecycleUtil; + +import net.minecraft.server.Main; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(Main.class) +public class ServerMainMixin { + @Inject(method = "main([Ljava/lang/String;)V", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/resource/ResourcePackManager;(Lnet/minecraft/resource/ResourceType;" + + "[Lnet/minecraft/resource/ResourcePackProvider;)V") + // after registry manager creation + ) + private static void injectConstructor(String[] args, CallbackInfo ci) { + LifecycleUtil.initialize(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin_ifaces/FloraFeatureHolder.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin_ifaces/FloraFeatureHolder.java new file mode 100644 index 000000000..2797691f4 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin_ifaces/FloraFeatureHolder.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.forge.mixin_ifaces; + +import net.minecraft.world.gen.feature.ConfiguredFeature; + +import java.util.List; + + +public interface FloraFeatureHolder { + void setFloraFeatures(List> features); +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java new file mode 100644 index 000000000..9e4c1e257 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java @@ -0,0 +1,169 @@ +package com.dfsek.terra.forge.util; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.forge.ForgeEntryPoint; +import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.forge.config.VanillaBiomeProperties; + +import com.dfsek.terra.forge.mixin_ifaces.FloraFeatureHolder; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.biome.Biome.Builder; +import net.minecraft.world.biome.BiomeEffects; +import net.minecraft.world.biome.GenerationSettings; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + + +public final class BiomeUtil { + private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class); + + private static final Map> + TERRA_BIOME_MAP = new HashMap<>(); + + private BiomeUtil() { + + } + + public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) { + return pack.getID() + .toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT); + } + + public static void registerBiomes() { + logger.info("Registering biomes..."); + ForgeEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. + pack.getCheckedRegistry(Biome.class) + .forEach((id, biome) -> registerBiome(biome, pack, id)); + }); + registerFlora(BuiltinRegistries.BIOME); + logger.info("Terra biomes registered."); + } + + /** + * Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate. + * + * @param biome The Terra BiomeBuilder. + * @param pack The ConfigPack this biome belongs to. + */ + private static void registerBiome(Biome biome, ConfigPack pack, + com.dfsek.terra.api.registry.key.RegistryKey id) { + Registry registry = BuiltinRegistries.BIOME; + RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(registry); + + + if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); + } else { + net.minecraft.world.biome.Biome minecraftBiome = createBiome(biome, registry.get(vanilla)); + + Identifier identifier = new Identifier("terra", createBiomeID(pack, id)); + + if(registry.containsId(identifier)) { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(FabricUtil.getEntry(registry, identifier) + .orElseThrow() + .getKey() + .orElseThrow()); + } else { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry, + registerKey(identifier).getValue(), + minecraftBiome).getKey().orElseThrow()); + } + + TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); + } + } + + public static void registerFlora(Registry biomes) { + logger.info("Injecting flora into Terra biomes..."); + TERRA_BIOME_MAP + .forEach((vb, terraBiomes) -> + biomes.getOrEmpty(vb) + .ifPresentOrElse(vanilla -> terraBiomes + .forEach(tb -> biomes.getOrEmpty(tb) + .ifPresentOrElse( + terra -> { + List> flowerFeatures = List.copyOf(vanilla.getGenerationSettings().getFlowerFeatures()); + logger.debug("Injecting flora into biome {} : {}", tb, flowerFeatures); + ((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures(flowerFeatures); + }, + () -> logger.error( + "No such biome: {}", + tb))), + () -> logger.error("No vanilla biome: {}", vb))); + + } + + public static Map> getTerraBiomeMap() { + return Map.copyOf(TERRA_BIOME_MAP); + } + + private static RegistryKey registerKey(Identifier identifier) { + return RegistryKey.of(Registry.BIOME_KEY, identifier); + } + + public static net.minecraft.world.biome.Biome createBiome(Biome biome, net.minecraft.world.biome.Biome vanilla) { + GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); + + BiomeEffects.Builder effects = new BiomeEffects.Builder(); + + net.minecraft.world.biome.Biome.Builder builder = new Builder(); + + if(biome.getContext().has(VanillaBiomeProperties.class)) { + VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); + + effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) + .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) + .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) + .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())) + .grassColorModifier( + Objects.requireNonNullElse(vanillaBiomeProperties.getModifier(), vanilla.getEffects().getGrassColorModifier())); + + + if(vanillaBiomeProperties.getGrassColor() == null) { + vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); + } else { + effects.grassColor(vanillaBiomeProperties.getGrassColor()); + } + + if(vanillaBiomeProperties.getFoliageColor() == null) { + vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); + } else { + effects.foliageColor(vanillaBiomeProperties.getFoliageColor()); + } + + builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation())); + + } else { + effects.waterColor(vanilla.getWaterColor()) + .waterFogColor(vanilla.getWaterFogColor()) + .fogColor(vanilla.getFogColor()) + .skyColor(vanilla.getSkyColor()); + vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); + vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); + + builder.precipitation(vanilla.getPrecipitation()); + } + + vanilla.getLoopSound().ifPresent(effects::loopSound); + vanilla.getAdditionsSound().ifPresent(effects::additionsSound); + vanilla.getMoodSound().ifPresent(effects::moodSound); + vanilla.getMusic().ifPresent(effects::music); + vanilla.getParticleConfig().ifPresent(effects::particleConfig); + + return builder + .temperature(vanilla.getTemperature()) + .downfall(vanilla.getDownfall()) + .effects(effects.build()) + .spawnSettings(vanilla.getSpawnSettings()) + .generationSettings(generationSettings.build()) + .build(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricAdapter.java new file mode 100644 index 000000000..b7bc9f010 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricAdapter.java @@ -0,0 +1,185 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.util; + +import net.minecraft.block.enums.BlockHalf; +import net.minecraft.block.enums.WallShape; +import net.minecraft.block.enums.WireConnection; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.HeightLimitView; + +import com.dfsek.terra.api.block.state.properties.enums.Axis; +import com.dfsek.terra.api.block.state.properties.enums.Half; +import com.dfsek.terra.api.block.state.properties.enums.RailShape; +import com.dfsek.terra.api.block.state.properties.enums.RedstoneConnection; +import com.dfsek.terra.api.block.state.properties.enums.WallHeight; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.info.WorldProperties; + + +public final class FabricAdapter { + public static BlockPos adapt(Vector3 v) { + return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); + } + + public static Vector3 adapt(BlockPos pos) { + return Vector3.of(pos.getX(), pos.getY(), pos.getZ()); + } + + public static Direction adapt(com.dfsek.terra.api.block.state.properties.enums.Direction direction) { + return switch(direction) { + case SOUTH -> Direction.SOUTH; + case NORTH -> Direction.NORTH; + case WEST -> Direction.WEST; + case EAST -> Direction.EAST; + case UP -> Direction.UP; + case DOWN -> Direction.DOWN; + }; + } + + public static WorldProperties adapt(HeightLimitView height, long seed) { + return new WorldProperties() { + @Override + public long getSeed() { + return seed; + } + + @Override + public int getMaxHeight() { + return height.getTopY(); + } + + @Override + public int getMinHeight() { + return height.getBottomY(); + } + + @Override + public Object getHandle() { + return height; + } + }; + } + + public static com.dfsek.terra.api.block.state.properties.enums.Direction adapt(Direction direction) { + return switch(direction) { + case SOUTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.SOUTH; + case NORTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.NORTH; + case WEST -> com.dfsek.terra.api.block.state.properties.enums.Direction.WEST; + case EAST -> com.dfsek.terra.api.block.state.properties.enums.Direction.EAST; + case UP -> com.dfsek.terra.api.block.state.properties.enums.Direction.UP; + case DOWN -> com.dfsek.terra.api.block.state.properties.enums.Direction.DOWN; + }; + } + + public static WallHeight adapt(WallShape shape) { + return switch(shape) { + case LOW -> WallHeight.LOW; + case NONE -> WallHeight.NONE; + case TALL -> WallHeight.TALL; + }; + } + + public static WallShape adapt(WallHeight shape) { + return switch(shape) { + case LOW -> WallShape.LOW; + case NONE -> WallShape.NONE; + case TALL -> WallShape.TALL; + }; + } + + public static RedstoneConnection adapt(WireConnection connection) { + return switch(connection) { + case NONE -> RedstoneConnection.NONE; + case UP -> RedstoneConnection.UP; + case SIDE -> RedstoneConnection.SIDE; + }; + } + + public static WireConnection adapt(RedstoneConnection connection) { + return switch(connection) { + case NONE -> WireConnection.NONE; + case UP -> WireConnection.UP; + case SIDE -> WireConnection.SIDE; + }; + } + + + public static Half adapt(BlockHalf half) { + return switch(half) { + case BOTTOM -> Half.BOTTOM; + case TOP -> Half.TOP; + }; + } + + public static BlockHalf adapt(Half half) { + return switch(half) { + case TOP -> BlockHalf.TOP; + case BOTTOM -> BlockHalf.BOTTOM; + default -> throw new IllegalStateException(); + }; + } + + public static RailShape adapt(net.minecraft.block.enums.RailShape railShape) { + return switch(railShape) { + case EAST_WEST -> RailShape.EAST_WEST; + case NORTH_EAST -> RailShape.NORTH_EAST; + case NORTH_WEST -> RailShape.NORTH_WEST; + case SOUTH_EAST -> RailShape.SOUTH_EAST; + case SOUTH_WEST -> RailShape.SOUTH_WEST; + case NORTH_SOUTH -> RailShape.NORTH_SOUTH; + case ASCENDING_EAST -> RailShape.ASCENDING_EAST; + case ASCENDING_NORTH -> RailShape.ASCENDING_NORTH; + case ASCENDING_SOUTH -> RailShape.ASCENDING_SOUTH; + case ASCENDING_WEST -> RailShape.ASCENDING_WEST; + }; + } + + public static net.minecraft.block.enums.RailShape adapt(RailShape railShape) { + return switch(railShape) { + case EAST_WEST -> net.minecraft.block.enums.RailShape.EAST_WEST; + case NORTH_EAST -> net.minecraft.block.enums.RailShape.NORTH_EAST; + case NORTH_WEST -> net.minecraft.block.enums.RailShape.NORTH_WEST; + case SOUTH_EAST -> net.minecraft.block.enums.RailShape.SOUTH_EAST; + case SOUTH_WEST -> net.minecraft.block.enums.RailShape.SOUTH_WEST; + case NORTH_SOUTH -> net.minecraft.block.enums.RailShape.NORTH_SOUTH; + case ASCENDING_EAST -> net.minecraft.block.enums.RailShape.ASCENDING_EAST; + case ASCENDING_NORTH -> net.minecraft.block.enums.RailShape.ASCENDING_NORTH; + case ASCENDING_SOUTH -> net.minecraft.block.enums.RailShape.ASCENDING_SOUTH; + case ASCENDING_WEST -> net.minecraft.block.enums.RailShape.ASCENDING_WEST; + }; + } + + + public static Axis adapt(Direction.Axis axis) { + return switch(axis) { + case X -> Axis.X; + case Y -> Axis.Y; + case Z -> Axis.Z; + }; + } + + public static Direction.Axis adapt(Axis axis) { + return switch(axis) { + case Z -> Direction.Axis.Z; + case Y -> Direction.Axis.Y; + case X -> Direction.Axis.X; + }; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricUtil.java new file mode 100644 index 000000000..8f854186f --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricUtil.java @@ -0,0 +1,61 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.util; + +import net.minecraft.block.entity.LootableContainerBlockEntity; +import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.WorldAccess; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.block.entity.MobSpawner; +import com.dfsek.terra.api.block.entity.Sign; + + +public final class FabricUtil { + private FabricUtil() { + + } + + public static BlockEntity createState(WorldAccess worldAccess, BlockPos pos) { + net.minecraft.block.entity.BlockEntity entity = worldAccess.getBlockEntity(pos); + if(entity instanceof SignBlockEntity) { + return (Sign) entity; + } else if(entity instanceof MobSpawnerBlockEntity) { + return (MobSpawner) entity; + } else if(entity instanceof LootableContainerBlockEntity) { + return (Container) entity; + } + return null; + } + + public static Optional> getEntry(Registry registry, Identifier identifier) { + return registry.getOrEmpty(identifier) + .flatMap(registry::getKey) + .map(registry::getOrCreateEntry); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java new file mode 100644 index 000000000..560a200bc --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java @@ -0,0 +1,100 @@ +package com.dfsek.terra.forge.util; + +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.forge.ForgeEntryPoint; +import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.TerraBiomeSource; + +import net.minecraft.structure.StructureSet; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.source.MultiNoiseBiomeSource; +import net.minecraft.world.biome.source.TheEndBiomeSource; +import net.minecraft.world.dimension.DimensionOptions; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.dimension.DimensionTypes; +import net.minecraft.world.gen.WorldPreset; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import net.minecraft.world.gen.chunk.NoiseChunkGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; + + +public class LifecycleUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleUtil.class); + + private static final List PRESETS = new ArrayList<>(); + public static void initialize() { + ForgeEntryPoint.getPlatform().getEventManager().callEvent( + new PlatformInitializationEvent()); + BiomeUtil.registerBiomes(); + + + LOGGER.info("Registering Terra world types..."); + + Registry dimensionTypeRegistry = BuiltinRegistries.DIMENSION_TYPE; + Registry chunkGeneratorSettingsRegistry = BuiltinRegistries.CHUNK_GENERATOR_SETTINGS; + Registry structureSetRegistry = BuiltinRegistries.STRUCTURE_SET; + Registry noiseParametersRegistry = BuiltinRegistries.NOISE_PARAMETERS; + Registry biomeRegistry = BuiltinRegistries.BIOME; + + RegistryEntry theNetherDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_NETHER); + RegistryEntry + netherChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.NETHER); + DimensionOptions netherDimensionOptions = new DimensionOptions(theNetherDimensionType, + new NoiseChunkGenerator(structureSetRegistry, + noiseParametersRegistry, + MultiNoiseBiomeSource.Preset.NETHER.getBiomeSource( + biomeRegistry), + netherChunkGeneratorSettings)); + RegistryEntry theEndDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_END); + RegistryEntry endChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry( + ChunkGeneratorSettings.END); + DimensionOptions endDimensionOptions = new DimensionOptions(theEndDimensionType, + new NoiseChunkGenerator(structureSetRegistry, noiseParametersRegistry, + new TheEndBiomeSource(biomeRegistry), + endChunkGeneratorSettings)); + + RegistryEntry overworldDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.OVERWORLD); + + RegistryEntry overworld = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.OVERWORLD); + ForgeEntryPoint + .getPlatform() + .getRawConfigRegistry() + .forEach((id, pack) -> { + Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( + Locale.ROOT)); + + PRESETS.add(generatorID); + + TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); + ChunkGenerator generator = new FabricChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); + + DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); + WorldPreset preset = new WorldPreset( + Map.of( + DimensionOptions.OVERWORLD, dimensionOptions, + DimensionOptions.NETHER, netherDimensionOptions, + DimensionOptions.END, endDimensionOptions + ) + ); + BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, generatorID, preset); + LOGGER.info("Registered world type \"{}\"", generatorID); + } + ); + } + + public static List getPresets() { + return PRESETS; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java new file mode 100644 index 000000000..b67932f0b --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java @@ -0,0 +1,55 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.util; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.biome.Biome; + +import java.util.Objects; + +import com.dfsek.terra.api.world.biome.PlatformBiome; + + +public class ProtoPlatformBiome implements PlatformBiome { + private final Identifier identifier; + + private RegistryKey delegate; + + public ProtoPlatformBiome(Identifier identifier) { + this.identifier = identifier; + } + + public RegistryKey get(Registry registry) { + return FabricUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow(); + } + + @Override + public Object getHandle() { + return identifier; + } + + public RegistryKey getDelegate() { + return delegate; + } + + public void setDelegate(RegistryKey delegate) { + this.delegate = Objects.requireNonNull(delegate); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/SeedHack.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/SeedHack.java new file mode 100644 index 000000000..5eaf38093 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/SeedHack.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.forge.util; + +import it.unimi.dsi.fastutil.objects.Object2LongMap; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Holder for hacky biome source seed workaround + */ +public class SeedHack { + private static final Logger LOGGER = LoggerFactory.getLogger(SeedHack.class); + + private static final Object2LongMap seedMap = new Object2LongOpenHashMap<>(); + + public static long getSeed(MultiNoiseSampler sampler) { + if(!seedMap.containsKey(sampler)) { + throw new IllegalArgumentException("Sampler is not registered: " + sampler); + } + return seedMap.getLong(sampler); + } + + public static void register(MultiNoiseSampler sampler, long seed) { + LOGGER.info("Registered seed {} to sampler {}", seed, sampler.hashCode()); + seedMap.put(sampler, seed); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java new file mode 100644 index 000000000..27b33a210 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java @@ -0,0 +1,103 @@ +package com.dfsek.terra.forge.util; + +import com.google.common.collect.ImmutableMap; +import net.minecraft.tag.TagKey; +import net.minecraft.tag.WorldPresetTags; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.WorldPreset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public final class TagUtil { + private static final Logger logger = LoggerFactory.getLogger(TagUtil.class); + + private TagUtil() { + + } + + private static Map, List>> tagsToMutableMap(Registry registry) { + return registry + .streamTagsAndEntries() + .collect(HashMap::new, + (map, pair) -> + map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), + HashMap::putAll); + } + + public static void registerWorldPresetTags(Registry registry) { + logger.info("Doing preset tag garbage...."); + Map, List>> collect = tagsToMutableMap(registry); + + LifecycleUtil + .getPresets() + .forEach(id -> FabricUtil + .getEntry(registry, id) + .ifPresentOrElse( + preset -> collect + .computeIfAbsent(WorldPresetTags.NORMAL, tag -> new ArrayList<>()) + .add(preset), + () -> logger.error("Preset {} does not exist!", id))); + + registry.clearTags(); + registry.populateTags(ImmutableMap.copyOf(collect)); + } + + public static void registerBiomeTags(Registry registry) { + logger.info("Doing biome tag garbage...."); + Map, List>> collect = tagsToMutableMap(registry); + + BiomeUtil + .getTerraBiomeMap() + .forEach((vb, terraBiomes) -> + FabricUtil + .getEntry(registry, vb) + .ifPresentOrElse( + vanilla -> terraBiomes + .forEach(tb -> FabricUtil + .getEntry(registry, tb) + .ifPresentOrElse( + terra -> { + logger.debug( + vanilla.getKey() + .orElseThrow() + .getValue() + + " (vanilla for " + + terra.getKey() + .orElseThrow() + .getValue() + + ": " + + vanilla.streamTags() + .toList()); + + vanilla.streamTags() + .forEach( + tag -> collect + .computeIfAbsent( + tag, + t -> new ArrayList<>()) + .add(terra)); + }, + () -> logger.error( + "No such biome: {}", + tb))), + () -> logger.error("No vanilla biome: {}", vb))); + + registry.clearTags(); + registry.populateTags(ImmutableMap.copyOf(collect)); + + if(logger.isDebugEnabled()) { + registry.streamEntries() + .map(e -> e.registryKey().getValue() + ": " + + e.streamTags().reduce("", (s, t) -> t.id() + ", " + s, String::concat)) + .forEach(logger::debug); + } + } +} diff --git a/platforms/forge/src/main/resources/META-INF/mods.toml b/platforms/forge/src/main/resources/META-INF/mods.toml new file mode 100644 index 000000000..ae314f8d3 --- /dev/null +++ b/platforms/forge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,24 @@ +modLoader = "javafml" +loaderVersion = "[41,)" +license = "GNU General Public License, v3.0" +issueTrackerURL="https://github.com/PolyhedralDev/Terra/issues" + +[[mods]] +modId = "terra" +version = "@VERSION@" +displayName = "Terra" +description = "@DESCRIPTION@" + +[[dependencies.terra]] +modId = "forge" +mandatory = true +versionRange = "[41,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.terra]] +modId = "minecraft" +mandatory = true +versionRange = "[1.19,)" +ordering = "NONE" +side = "BOTH" \ No newline at end of file diff --git a/platforms/forge/src/main/resources/assets/terra/icon.png b/platforms/forge/src/main/resources/assets/terra/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f458866a0d1cd397e5fa592ef1707a97722f1f GIT binary patch literal 129860 zcmYIQ1yoeu*A*2JC6tgZX{5UmX#r_zkWvuoZk6s(hHem~K{}P82c$t-y1}7i7`{8` z@Bb}vxf~wv-FNPZefHUxP}LW5*!M{9-MDcBTR~o0{l<-32H@}SyLZ4R3_Cu(;Gf%X zB$Xv^+^C4Yk1#<8|ED&SS69Aq!;|60jrRdJZk&UU-ml-d;lg?2#^$RVH-r;!+#s?~ zZBP>h-?(F{C?|d63iT(mIsX&5@`i%6q^A4S_NAM9N~Fs??!3T_UHa#rnRX+wKiK5p22{@C7c*Xid8Czj-c+mdwx1`vy9b#tkUF*>bR zlz3Yw^YwG7rr)*HWx(=SoEvHOon}9o}YBBL?wCg z4h$q8le_(9Y40PoG9JvC1X-AZ1rJiu{6vEc6ToFoV{SK`ILWmDe`f}85fl9YE{=z>?Z{(79z{;gV2KQ%Xj}8^S65i39_;I;_)}B zD~28Uwqmvq#6Js*6`AEl;yB5YD9#1IcfEi?@4&dxuw0t{+u&bq?iJ)Oe-mxGu!^!R z3j`jip;1O#0;<6LK!jVXYMB{pFd-*F@&9(`k-vp5Lz_s4ICMVkIuyZp_h)KN%ACE|1wIe{;BF*z4;+LSGe3%lz}j_DA0npk`Q-YAyJf z=w3)YUuxvHzHsIg4n0M)WsWaTQU4D>i1|?vtcd(r;JSlys(Y1dP85rb=9CqaN6qLl4=`d;yPsf*hI9r3BhTaTO4-&OsI*<^Q)U_Vg{}luzK;2f{=k?D%xG zw;Lmy@~em9U6|1;fBtfNSV-ZwOSb9~1vR6`Lbv{B*4qo_z=zs_y{Dmcl2=K_gz)Bw z5e3R8dWuh$obgVz9?sv#$GCh`cEeT#%FTrZwO`Lb|L+~QJ^-tJUW0v|iCvaRQ>|LF z8^P)F+wCzd8EY`K3SN{@VVXLq6^TRSd$goJ4>Ea1Ldrw;p9`Wj>9VJgJlH*8l5O1@ zP;WGo=x-{&l-|m@Fa!}dMR8&k;X9Fm9&jOQUjL2($~kv95cuDA>c0Y^yLjgKBJjyG z4J0^)nJ{Vk|ND`UG3juNn}SBg^mKE30y4^K8RqGV zz6mnf)%%GH7UJ9k^sV@OvOaitdnYO69OG@}N;g7@{(H{@dt%7skD~?RkJ&!+bdQ4l z1TM{oSux{%;(fWT_$vevjgmtxc7o#MVo+|H|F>;>O=kwwj1cMN?MeGhs+D0Y>VkFa z@s5?y47?%nrmow}o7l-LV;>3E$WbCvvOCuY zfSW2Lr)m~D^*rE{^}GJKCCjKw2j^2CCss6a^5MUn{RV2H!w|6rt=L}1Ks-uuCh7IcUqm}ZuJG5?GtiYI{+&38xk45up@+QK05;7TYG z*S0S)3-J`ORz9#?Ah0@WYS2!QftCo?eZ4OGr)O2}g3nwUL z5tB*07JOn8eMa}3;v54kRX_)a*7W}$R>MnU6eWiQB!Ke&K5a{QY?(c>fY+h0O1A)~$h~#m$e|2w$N*?!`C29^ahne)Z!pW+NoQyjm#8cP;|9`qe5}@!JO%%>M!_Ecayh!+^j>^+GmUG`4ZCZORF_a`eep% z)qQHRb0g+av7310ZeJCsE$AuJ&4msv0*bhMS1Z{n{X zowz-S9rCJ)QF8Z_=CXK7QU2G#dAxyMVY61U*p{UPAE{tiT1oF2Eai3sOdqxx2nU z^3%$mBoLP5jU9c#W8(-n@%R#)r6T*dN;0pWJpfsA`->d+vbeILTFoN}`~!h*!f6J> zqrfYL@3wo>tgu|}|4+LUp^t*0o!h_gof(>y5RF>5>Ln~QSTm|+sv!7ft39TlMZ1G` z8xnK70}a`>(ji!{$z-gpHumISkEk$QQtLGyxcPkacmqlZ!~cpNW7s1o=Z6-wISa&g z-IX2OW7ch&p?BV;wc5A}@^VcHeY0yn#!V5kU+X!KbF$^p-OL@rAMVDR<(6!uJXO1H z&7WL4ecck6)?o%zFG#?x=#2hzOPnE7UH~Xu^rMYb+irpQ5JS;YhN{QosP?xWUEf~2&nLvbqkLNRG?mr%twj#mH#$zf#W+bl zHwySVkWAAkTB;JnKiOMV1N^-BT>HxCMPA*IJqPSJC&e`PVGqnsS)jmqH9_ns}n zyEaINBLV#&#nj6Dl|P9K&O&d4l)GC$p|PP`vyz2mZ4v33&1H1+YgR#a-K@L<_uBi1 z=4aTjeYYsOi{9wI#+907{}*bnh(Q|kMl>HeRCYh~aqBc5lVCy=dv#V?Wmg~iYHt7;L%P-+e)F3g-})@a|ow5i}*_4y=iZIwjX6XOzkr5i@SSmsK1itE(;iyYi+z3X2z z{3^94ro^vyvirlQReg9;WVh-w3@dm`;4w8G4goPD^r@_SZ{8w%PZ0JA;RnDX6ME`u-@eV7bxleeS~ZEth+Qm^R?3 z`CyXx;JkwNZ)Ay*KrAMy=b!F1-Ih7zc$7YlRGdB?e^9a_Y~+$t&x!lR<2Z4_yYE5_ z(=j8rq1lqHc0S%o5%FS}^pYd12ie+vu(HgB%3;3$YS@BqVaM&$Q?EDDU$$F{Y}62j zBj4gCcLnrSs>GvWIixy9$Opn>_ZFm_q+ZRAc(P7AW*<3pDc`GYcSDYklUJ9r*Km?EZdt@{!QU~$)^ZiSVLE@9+lziLZu7>YZ zCAZRF?v9MIap)`h^MTChOPTg<3-{8^i)zh&(i{cXx<3ESTfg4g*BiXhwAXp{?PU^yB7|eWpphhIuUsNN`&t%X-bLh^F&ozSUXxdF5MNsbs}yx^K1_z0{?A zdqhGe`W$~T1)0|l_1e(r!9ulR=3Ff4Iwy@Yj(z39xc%5PhqdjTVxK*L z_m)_AQwMG;?W^F0w_R~E^`77a!(MY@Eh$S3{k?U-McpIVHqIo4`{NRwKN3%D6McUn z+r;*)Y+goq!!KEDNqIDl33bfosN_w2E5&52HxjduQRXilc;Ufnx>;9Hkr1zsCW*6H z|0|#=SP5&;A;w%;zxu;CB*qR$Z|l0R+2nC{b=CBkkj96G3en{`&3B%)il7j{TLPr5 z19_z`ZF-0*ck8Hbcb)qsK}{Tqr~U)S{KPo0$`9hcbDP9)P`ZQ1B(}Y^6dWybyvL#v z1;k}rz#F^JV4aAHK7c0W1f9@709NE=>a+`5>gai`!w_RajB|PV&yc157T(R??q9tY z-Hc$xkV~uC=8prSY^y%Bg)0_Zy_8l4RJ0O|dO`vnoMLgY@{?q=S2{s`2R#`bNo`18 z`?3K(&~;i6cLs~!{a5qfKo>k5KDo&TI4c~eBlRZ|85SKdg>qt>d(_zyR^Qne{YRthM%Xs=!bX?)}x)kYsY4u4h0_~8uGr8dJ6V zTNk2W$~5#38tPy}EL?Bz{;?(`i}S7Cu0%H4;IDj}`7jyx7}srgb|OXI{+23enJ!XZ#S3DfzhuWGY68zK; zF2{$s8}e5eE)4mg44__yn=N~t4j$h#sZ-2eVLxefzO~4KsvEdb$CpAl(OTT&yi&rc zO4oO*NRtT%wKH8nyNQwJu%%S_jALhMg-+O(#VB6IDRb}BGbgDVmo|88ZY8Ob5AnjG zSM;1S7nBp>ggjVFDvN(x%!*4*STNKK9cd!owd8b+G=gLI=Tnp^)XeZ}E-5~$Qc1`% z)v?BI&lF>;#U1Y!j6bx}bY0&&+uIlZxlnO4DDT4XukokRaA4eOb3d9o?Pa<-o==$~ zh2E$lN-dcv#yGGn)7WKC^hxQRi+0CT9C=%Q%5@~(L6^FRms~U;HC+1a9HK!i^VX(zL!5dY#Hmt-npfGQ0%UtCyaHbwoQmAFS_gBMumj)L6&D?ie_Z|g z>~rK-g{m6G2!t}6Xc$}^z<`19Dkaiy<5arg^X_lYR40Knu!~|59Cr(_3q57D$yiVO zwg?TE(=70d5C17ZI0|>nwyb`Ukoop82D;SqxL6w|qbc#B#?N6Pe)po_6bpb~iQtn> z|69H6pXhW(L(T9J$L_{qL&29?tAU?&wWWjCBvhopUMrW~w`#Rc%N`Tg2%A#C4-4Xn zIf*!~s`1J;0T)gZ`}{IK+kv;VFH~S+K~IM;$o{_b>Qcu-CA>wXc?wEMbH%n}kI3%~ zR!@+ieuTqplGH5;(|p)4_cBg;@?ppj{0sR}*}kf9vdjl!&2WD{%IC4Jg2)lzjeZBS z3u8aQjsDl9zPrZ?<8Ew12ojoPXELk#j0*4y1nlweQ`-X13IitaFp-{CV#bV*^o1gqU&d zk#W7&;Z2PyBoeZm?=%aVHLlEryP!Rn`xc|JE z0zRyN8`NT42v{pl^w^!QQ)E+t(0PWFt>TP&6{K}OK59x~q^5CxOxQ3Yj0@YPs=(l} zkx(tYaY%CZm5|`n$(oSpOPEdm7KjOkGN1;6|jhF^Hu)v50B z5wEl1E-i9h-EOVbnKoYtKvrSO1-n8TQ?&86DHF9OdSNI2Km<08zg!XstQYn~btXycqQTj`gP2<&UbKXzDfc*Tj z$PWZzIiV7fefKUYt~mFkSQ9{5_~+}Ux`M31k%u_TT6+-m%a6r8$NA?Xc+p-@SxH~W z9o@gBmmgm1T`t>&N_4$)XNk$37+?9T58dcuTso1?wXEwzO}9M8Sc5~&nRNaUH73Mc zcU2z*cX0(UpyT9gN_!jnxL8NwPT|uU3nvGHfSIa&72$oNe_!uQ*sG+$EPEyj4}yai zE3#%m%!Ch(ah2~8Fa8k(?B7S?e_WF(8Fa~ha`d}>#)s1xvDO3!;j^wzuVEYDGn~0k zClg5{%l3z=(L1pkTg_)j3O!7o_Jo9ih0Zwj{YfVv$^Ya>p3%5=as&XKxPUl)^|y48Qsqv0a_!&B=AZ*~Bti1;E2?@?*?!f6 zJJ+d$@-D1A0yntp3!vL2l)wJExOGX zySCajI#fxolk<+145T@J-hO-W)#lwi5>SS^^P(QbGlou>k#KY5dQ;}$UL3ri6;BWp zec3*E`M3M4VKRWg+RuVKUAC3y;l}2(6%vEkDU7e-~~Cv zN+rDa+ezcDJoQ%CYS z$dVqHV=fJRiFWFXVj5-f(Ak%pV7aTE81aW|%GEZVSg7j&k8QV$htYC;?>B@8>)R*s zmg`Noe}e!dA`9p6i7S{SlntF`T6bb?fq+?3uGi?q(9aK76U&ktvcH3Fs%o>v1zoOe zHohNm*xU~{)rxTW$F#LYzDg3zplJFwG?mtxCz^hG3u;J8<*Zd83*3g#jFh*P-MMah z46LjA6T{~S^Wjr!!m$xe;@#(&;9`HvouBjjlRrdYViBnzKz;tP6GK3@DJ*E%1cZvu7c7v@l$$`E&^xK>tYr3y345EwB{lngJ$%&1 z;i`&}?-VwNoM8ZSAd-7ye+xMNpGA9J3qVj*fk8~ll+nVPvx>FTu3LOWf$G(8#80hG ztdb>vdJuv#7E71xHf4XDB$by1{Bth92pPQW`EPIeZ~V=Sk+^pcHp2&IFQcc(o+W0) zS=LK+6*=?XN7;YZP4`hp(}WVKsywJ$ny#)*=7Vz&9<#fhNSp_G967kZ6NPfN{5OZN zM-wM!Pgy70tmfdh?%K=Gcz*s-8iwu97es)<6&{6mcX%ucP^jV|A=nGG5{;%|6?&hC zNrdMYNRj3fhvvFaR@nLA#Lep{`S~7N*+;qe)M&?6;m<&LO3syn0F$TO2V&cndA`&S zl|!ue+B35qO-bzXS~Ofjk<3Cot84zQcSbA8U2&nD9jU=d0gX@#T$)u8Zd{ zf1+UMpIcC$J9zhw5t5x>b5$a7a}R&Z$jDT)Nm;#RRJP1uHuTmrDa0G|ug`crmXG`~ z7f_By84Z2&FOP=sp$PJoGl#~uk&k{d9=r<|=hKUBpT*_DJ!T8-dZ7WJ_AaDh#1BxjuQ$>kf%~`? zeWXEW>EyLE=sL~pKdQM`l9TtX)2Gl+UR7G<6yt*M8@Vf^)X8;2*_QKX<>+ zUcKvfjbSSS0llrTKfU3@E?c`*ODKoum)S~-_Sf+Y`!4K--!epk-b3NibvH;D{n!g4q!hVe5m8=xpaU6g?Q`*=4#Ed)Q$|A52rmoL*A7uSJtuBt3TQ@@ zRRX5JTL`_&HZGX>Ag{G<2j>)kUVt4}{;e@gT zWF;Rl9@Q*~Q78HWP@V?o$tdI*(*FTksZ{4iUF%#+x4zZ^8qqQAu=O7(51tNvd7ZZ3 z@;0;o8hwiOMr%ulWM8GAH6@PXvU2ElOk z(ns|}tjCg|g{wDR>q zm;t4B`(PpsYRd&%i#kB^%b=b^hV%^@Cjc-Ew)`|L>DjfZro~EV=nEMRf%~|oB%Vax z9kV2R;-&4WdzCiojV!|mM&Es->x%oAA!!qGhc`{mfCQL9Bp~CbG0k}X@o&m7K7U2p z+gUlpt5xSCZJl&s$Og?bUZ&9Y;}K`uTx-5;b_5wCyG#LPC41E>9UQVP{O-migO(GK zE@n&5f}<%hL*l#jd10PcGtkCH_(S+tKx`nC3jRR$GX8_I! zUk3s=u^heTJ|KZGKqO{7FdCus_~Z9{C+Y&lu|cAUG(eCxij^!l>vXzUCb8_Vqjvtn z{Ony%U@BFZGv*aD9cy_gY)P8u-vm7T?#h|teYgEvUAM<#{mSYYPXAd3#AnRSm7GaS z@3iQj0=(jud%oHuBa0jn7g~N9pC9t=Qf+H@S1K|2G^5&#X$sI`Xx))Hn^R)Ky2=6F z(w@rsJ~3UMW_~l8|^qq!X|dUi~f$Z~p!~1qvKQmRYJ;({^E{ zq!aqRo+&%OkpGd+RZ64{8qVkz2nv>|{0LvEbO2b?(^T2SFU2KE1z=bZGV>5!QZ-T9?HD5*__`EySKBjUk7la`^W?@2!IML`0M(2p9gS^tljmx?Vd!@{~TVY zMrCq>k~Xlv432}sh97r1)cP*Igiq+-FFbd8Lm#w!^$_pTXy?JAYz3?0HHY+$M35C0 z;Dv7g#1+%Oh0Zn%Np#7^H9L|Ga#oO+-aX9-tHHyD8-@fS3$8y%ZSXC=opp^}#TAEL zs=q4mLx-6_N$!oKV8l%7jZ&f_+=zXj2MLWA16pt5{A9iK^xup!@71RwMGFd2Raf)B za*D@1K54n>V)mMp#(C?q^tp~LnIA;&)8U#3-c3sT=1I^h-(25HMa5HBDdd+#-F zYSjEg0l6!t18?pspJxD3J{8di6!t)IwiaKk|Cb4LRK{?Z4s3cuXQZi#15jroWp8FH zeb8#qgXE%Ti5MfQaOq%3LdUwV;!?n_W||$#;2#!Ti=4NKd-=~iMB#D{U&^ltiFchM zEl9Zj<^;F*Kqe5e2D6%^$3hUA7%rax`v2!^<5k*=uQm8(b_m^tG5QG23P!2^MlHo*Kkl3gO z45YNTiCv-4wa0kJXBk|Qy&@EMjRqRJ(H%$s(w9B*44cL)0Og;_+0B4XQF1Ni9$4hl zNlX4n5_Pr7!7=W+glE%?9|13SHt_w4cY)XKK|`XP-%lOyzDSGRyVfhZdTR zu6A*+pUY(2-^xMK(2eh5!?^W=OqYQlhhVpdLrtW8vzp|9?!&K0ko@W!p^UW=5a}}6cTn}0Kd~{NQ@tHLFASiw zyw!!VW&G18ee(2i&!POCBfcL4aeyBf_lrJ}!by0@g|#FTjfN_fTf%ze{6mb1Zmb3m z5sY!ii36Zd`-O<9&}>5a$zH5`eakWvxq2ISmef|&C9WHa8Cg;m0+35pF!jZvjLgyK zIdy3(ThMv(_lkk?jm}e4MY_)pY%vH$XsLGjZ-`k1?IHTO1ij3{pJ6A**)J7yw z?uF|~Z@VWDO-=S3EGz>Vgt$WY^rhhnTsmL$mG|Ly2SdOwb16leXL=d_th@XaG(5yQ z+RU2+y26q9M*>Z~QfG-%R=8Z6nzmFSaOpcsKFrRS+0kHXpw+NtN-#h04C*c}JU`f9 zdelVzHicPcCl|8=O2U42k_pBJsub{9icq9V6QZu3HF&Z|wH(#jn=p#A2FGG-!*|2g zgOMMq#8w$`qH(8&cCv}jj1ck?jmX_H2GviG;2MqsD| z;#AVf@OM?|_*=7}AaRn8ZV}QD_!q1r4ktDK?;0cA}eh!g=zIDc^@!Cv=<=Ss3D8H@Q$X zAc;lqgnmEaR^HRffy1>PJsR9onGxMLi&zP#-Fq*p5tji9$tMvT7Ail zg)bjX2u#v0Y7hj=J>C8-7R|GV3|f?Ld&A$=)Y#y8I%q(o9)Y;0#hdy8MPt3`<@Y(X z6z?xbYOz0;)jT|rs^)9d!?gf?#CW{;dKecpl?)H49KH~r1#<1#JyAUwen-eAP)}s( zN$0=X@aG#~pY2WqJ;mPCDczIGA_dQ$egq0K2L#FhI4O2H^X=1=Dkwa|?zNot&V}JK zQl3;10|UWa>7)B%!moR0oTIZ5mur4r9uInO!Q$ z`GZV|DaC?7+HiN(woXW(s%7Q<;U}DBKTsRrg&*sZ)M`P=E8gCHKh{YRYlMGtua`_vO6)hziR zhfJV`z8#!i>zAd7H7h2P9_gLjhc-NU>&Q5Z`(1nqIe;O{%bDzEglA9j4xK+Z*nQ!p zw-p)7;Zq>HB#qV}y6&5Bgpeiyy`b14BH%0(3+QI{;(FU!DaqH|Qnoq@|H6hpcbf!( zEVB{1HDhGaZ5N)L?U(8y?g5i9XKkL(10sw)HxJcv*&%yj0OrX^4_at26!H~Sd90-2 zfbhin%I~VOwXoXJ)QDIa(W2?QWmVvv><`knzHeVS7yywPujH62Eje&lM&RbEQYxQ1 zRN1cCUF__OcP&)j>};4vjnUo-0qxmZm(@I|^wEgIZabjr^o?~9>d2wweiZoD0RO1~ z^+))RaY~*(zw{tLgeMyj+1A4)yn_Rr)UObab!H5I_$ttz8=T0q-ds7Z{}NvF@%>lh=h|^W?tpyk_Qx3r%n5 zsBH?rY;_>j+YCLa`!)ONLU%8;iN$Q%doH`@QwLNPeHY)gJjeb2iIsx>E zo#5O%P_o1iiKQOgUTCo=4#GUagg2lv)zRoBTw`NulDnzrtUnWMG()GKV?Ak9&w_%8kjDB9$lv;qHzg3{){+*W*v}G40linV10Sw-6$Etvl;&Z7;`n|qy`aW%F*cR^K)%%VWbdW$=Bnwk zz}B}e7QK!tXuV!}rx>PrT7|?E8}|9YoMaOV1S-qvj3RMNp_q%FPLBR&h@hoD6F*uB z;;VYbc3>l*e}E8wkxRiZjs-kL9&HjpvsnP8V2+bATVR8knD`f2ee-5fm!6_~xs zz1jDc`a4!7`9NZ)29$h}_~>M$#Y30$_W?DmrpTPf-ztq#f2e?>vNf3d-lPcul5D zVIrWiqe#Y;NY{=<oTm&p}M`} zI-Bqq$RhLM9*wP}#2a3K=H9s0%GqNZ1es(v-4et&>Gtpm~sp791(gR-y~ zFO3g{Yj>)YJF zOU|y3N4|98)RVUWfHdR}dL*tekF3$F$XLJi8Cz{I@&!}0!BZBhG`n7A0;qynP=DEd zHLlXE+U03iZ`H~jp#IFB&TC|sMW$haBmsDYzh zua);8x)=4qg&}=T(&2*|L(^|mgX!b4vwJKp8IeF#=-le!?OpCV4CX-DM6{)69_~#3 z=gGe{e6`x=(WOr#%E=ibvv^U|%S9)KE)M=yqraP#U1wBTPlKtSY<9I8F1fd*S0Lxy zCqV*QW5L`2i^mus(T@&Iy-)Tl&ms00@Xb;2(j((A0%(gRWBHd$Yteztb!K(u4Hq6H zV=z)T2cuG5pnRV2cJnkg6?(@SiBi87;{c7V7vLKSMLyl~RU9Qg0+bQIL;Dxw+au8G zJvZGwD`r)$FR}+)&o(V>o>jjf(uionm>c1qiGS)OC7+>?q6xY;pzX_|P0}`*+;L4B1x=0X+_g?OrL+6UAjHi)T-PE_cQ3Eddtu2F<%7*Q)gH zS9KhLrN+1UW=9;!;4Dokp+RtOXC-ac^CW9PO7`EUy|?k^r`Sin-RIN=p@<(pKffp8 zkg%l$qv@|pG7s8agFy%R9#pzpwBB}d)~-ma&6c`>O7`K?%*Gv*q;QZUBzC~-b)-ib zm{*HL;xM^w2biaT|`(e z+i@_-o47aMI7Sj0L=+R?Ed=!g>S{uzGN1tkmDC}^d)gTjlv~OJPD^iUfTYdu7G~3w zsJ!1);s#}ua&+=J(8&Oy&js<>)?)%u)of?FaN!|Xh_W+s2ESUc$leG;5x~Tb45o~}HAl#(aJ@p?>9h~6M1MG#P&Lk+3 z`-1x_|4Z=jSVHIC^UN%a_u5W5tI^y0h8;x7a&<>M@N+jfXkCNV>KY|S3 z6VR&yz)AFR+|*&Wuy}V_*fVvb+XS=BsuT|&9~3-D>MCw!Cn!DJB>yTq(#&l+MG(VB z_tZ!0u9vv=jA0XK&;}2O*M7_T;{1$m(2#>Ui5LNYmI&{~xs;lxK%FiiyFQpwV;~o9 zku*E^p{bYC;dkq&s!qgHKiCh4jI-rZw1+!x^?Ft3(wsA&n&w9wbMFOxE=V5CacKw; zHX?f%!KLw5%v&@yYKG0*4+cnx9c&tNL%2M9*!x`Zxv3#x7DNFAzcg@B%Xc#3km2Dl zE<9_C&?CYfCFqsn$mBPV&;vnhESy3CPXHeDD2QVH`*#7Y8WzbOCsHiYT!6SLTsjMieyez$saz9;u5ysJe^pCU1_xu;~h zMVX)eeD7|^fj7f1oZb%e$aX=gTPtQ~eOLyV`uWh*S!i48X@Bm~3?$^3=)T54og>)| z0TcLM|Hs~*ixDQq{XjhS^~oG-3e`ZK`;dF21|{cV5jmfc-3rhMoh2SIIReQZ71ycHf`9*+UCA*spB1)J@u2W zOD7=4OaO|044~-GMGc5j6mCoeYdivkGrfaiA4;^8VYfWf2%4i#Kx|+Q>l>v+6P>Vy zc+7w2sAyVq1g(4KW*}wBNC%yot0pin3X!=>SFf1ORr@@XpEmtb77BmSBuOday~Aune)S|Szyu?z z+@`a8o4LGDt)i{#KFjVh@udEq_XT!tidBRUj>5CX+5eG zj|A!TitbG~4p)bTxI}2?EEr)r9_LBvk>R>Te>YR#n8Uytx?d38aDkHV*b|+_zT*cP zl7Z|>sjC@Sf>+`SXCrEiXwPp1G)8|gSF5*UgApnnu>mTxLT@J#@^@x4iIc6T1v-GZ z@rF(716cu;nO;;=>A(guV(q1`Hi|sHR_(okVVEXT_GE%HC1=I~HShuM!+ou)SM*vi7RXB_dfmyjM5FCX5y{V;8lC zj8{hYLEA%&YI)lmOp+*!d}p!&QTeH@p}@}iBH)|;W1}+#mWY$Q!6Un}3&TyyA74WdR43XG(@EjS&dR~o z?OY3+q$QHmJom!}wqoa4pLKGHJNrD24viHMtJ5N^aA5zG@iME`7+1VF5qh_wVwim@@^=dO zORtFzMa1Lh%?A^guAUjc?RCXbaJ*vw4>fEXoIiZ)2K(rzF!ktw&9HU-zRGjQWEFTX z34vE9R2J9o$E~0@v#}mPwI1sa`Dz+X!n2KxLkIl;&{RH!m%mk7I$fqv= z$%h7QGi zVmXcTPXdrQk+|wMyK7mc#)pAbY^(Z>7C&0s4;DtbvA%_8p;XDN-@zc%1)Mf5yImb? ztZht)=sT3(tfz`lG3T61ncmx+%+4Nb{QW8)L*f-s;7Y+mP~7n~?_+}wXeU+fxccfY zjEuZCz@+PHlgEYAQd`TvuY9s1rEUGyo?`AMMQMDybuOtgZm;T`SwN-2-Lsb4);Iiv zMX8f1dut9Ur21Wc%nc2Nw-gEY zPdeJKf;ZcGb(nweD|)q^%UhUOUVF9cM=&VG=?D5)<{kt500SuHHWbe^U zl?N0@GoM8C_|dIrk^xn^)N+B@fVTDH=Z+}%rxSyyeJ*Uh{IH>&)kPGGYBQ2ouCyK_ zQFSDP%2y^fym9v)$Bsj=#%PARvMtJ-DO|Gbg;?~T$WI^&OfGj!&1-vTtQ7)Q0g!5k z*-!KvKkW~^<Tf_;X!+(dQ8(%)D`*Y#|1cjmJ^#4h@xf20zfsSx1E4*`dS0sqmPO7ko`FX zH)ZHJEM|%@I`^ZzyfuENFq8DE$&dltXV#(Kww3mZXN>_c1xZrHBD1=CgxY=GmISny zs`s3IOb6=c`A%;3rkO5}iFpIx%xc~7xG2<|Uh62WV?JkWJpItRPWYXT1{}vzp&&O; zdX>)6^#E`0iVk&vp{VR$OD0Dt;oSb*G=hNRXeJ$ktoa3I{(b^5*G52(qj(&jFQaT9 z`Gn^_XCW=v0hdtYO5F(#LeAhxIS4*PgjwEwVj4TwA-761baPTqZ)@F|!lBYWvY};q z3}AGK+)B5|S4r8%yChv2nXM}{m>w!6v}!4owDUZ*`7RnwJB=5b>2U9?7M9b;K(cHc z+1xL6jxT4 zr?MIF_a;bDls;TTxAGp{A^j>lTk@C~=MA-4#)Cp0=5+jGE`iqtTl1%{u#fn*h^yi0 z0LW>k^C>$ShaE13X0#`@`3g|atZ@g!dP%@zB`XY0%m5oitvkfL_FioyP2E3K zO7?vkt5E-P?oMHG_ot^7mL*IEMcoq*$yQ)mw1Mo9(lah7$WP9}1oHC(a>w)^s-G-z zab(hglN*K^+f&fmD7E?c_p)$-`a||bG~J|EDp~kQmt(tth4M>b@K80Qm$^Zw{{Or$eJ4hmm{CsiLX%lmvh~e%&`4*?;1a)x zjxF=Ek_Eg-el#wBQ?J~HR|my(g&cK9?b6>Y7f8-xy+hbA}X z%W$LtjUg%Y7IP(NFyl1IkqKyx%~X}Fw5Y?1(bcyXY_mH|9;1%MW>n(1ECPMw357i3mALCr)RvW;|rt?k_pz{72YV!2bUx{#NeT>Y=1UO`zMwC z_>(5_o)mFL()2D;b+y&XBftL&mCb?qR`99s~H-CMK-c z*o>%$%vSy`>&9)rYPXLT)*}-zqLuoY`KuJ93N19}OTZ%Im0%N;0oh%bi_=LXtLvT> z3SD`&z5lqTFY*8ix=wHqjjo?do>%VaT%tL4yI|cj3cN`ny*h&g#VSwprnKReDx3td zr9dNvnB)B@eloY+`l+u+D?i1GtA@cRw`25X>zBXba&&GWE&<}bKk`@LwZUxy`}7v7jM zqQP<#rQ`Q3x?_!%pMzo@_w=NiinA>uJvhLSXqV><;>$FC6q+gcIplL3QwYmq%n+M_ zeia1i7W|H!ugb0cPdRp_OS?iFUjy1=bzh>%ggf?BhIaP463(!`v})RerxP5<5m6He z--+L(X;kyAX|nPMDPUKJPKBvf%r;BJ z#7}t%0bi3#rSh>{nDpZ?F_WG~Oue4AHT{O8Ws`l{*Ff0aL=6#x9Gp8=5tC|)xkc8+ zcOp*|O@P8b;>AO5m4mESHh4%>tp^f)l>4OdS|Sqm%KItkuvspAOU=6*68B}EA$MD` z!Va5%9<3JWKrmmSq^|~}W2Q;&;5Uyfp_J9JuAE4qd&Qd?afH@3p=cD_yIJ+G4R6=( zGRC~CH;eFIsY9K|nfrT`0!W4-m=u65j;-xz)GPef^FW~enGU7@Xb_#X_SXAu{)I}n zCi^iTb_`*IT^565*Lp~|_KA0`b@#{37VmZ3e5uL);7xb$P*GY z{AQBL>x=9U9{S6qI;YyLdU6@)2EY&~3DFqGArqw<&EDCgMUd_i($%(ezE`K={%#F+PbfAM|!VP1*A#n zO7Bg2FCn2LC4dNo4l2?+hy+nONDoD7K+vFoM7j{^H#DUS2ndM2J3jyMez{*9L(heC z_FikQIe)9_ea{NVJ0Bp!=5jtGb&mYyACe+0I38?Z!+aPF%DEBG+e2@4CTmSsfUiPG z12ot~H{_{{=d5NIS^PNhG7*(nA)({0PK|Biy~;X|OPC7#u$hsM{F-*9cZd$XdW7-b z_Dh|~gvqux1tL=?i%yL=vq{XjeG{~1-e38?ZlW}KjlUxYh@0RC0A4rd?K(u0LfCzK-HSap$(s83JdE_5+Oy-fTnDi=_|h|Rb~7Jfd(s)~`fy<^h=xvxUa&7ePx!56*(%PE1V2O@gi z{^XnG(=GjGdiPB{GKBmp{-K=>+ob4|6PW-pY~;Hf9b zlfReFxVEiD8e=K(pS6zKtU!r{ig1OYGXrG>h-Y2oK(NQ|5_^{kexkSjKe<#^46=W- zIPeaj6^&q@^Ee!m{TBqB@M6F)8&-Sk-_*b@DD*5qKREf)Beik5gGk_nyXxG20 z3P2hN|5C5hSH1;!(EVZYSRVdF=1F-?{p%-xfaam8*5YvG{G)V@x7!*!n0Gg zW~QlEepR5R>rcI_->#e`TI|Ea7Jt{N%^B>e80G)$+>#^)VgzgcS8=B)NPGz{Y_>Y&d4XG zb^B}Mema*XUohy}E%DUps~(w>QlJ=dxGC5Wx%F$MRkG=(LuC}@8H@|r9tXc|m&UFg zq>8a(KwkwK`+@TSbcx3&Iex>N3?K}eXZ2h3SVrf_v8Y?%GYXhFwjz3|9KM@Mzfv=2 z^X06~j1oRc_LxU69xiT2=JmRigJRlS;9qWxbPX9JqVcD+nfFLR?k*V4yu#)Q{e>p)8byYfQrp` z+T~1SK0Om|HGY(x?~U-4E;^aaWca3W>U3ao zU9+c|ky7?J$R*6`NgFa2Im42pdE_504U2688N?%O$b9L8ymr}{I@c`UUDy8V0aGh9G>itrJC8zw9gtEs-t`pEDpeC=w9ORxl56CZZ zqf<4)+AhqPOR|UwId;|BwE0!N5`~j&Gl~(i_SA30Z2lm_w$LugEZtmZv+M3{F{=Pw ztAALT3CFU=I0Lz@JG=k2k3Xd}4wVP0PLRdD{|pjApRKRKxVrtRlB)`yn&k>L+1 zQ;jc+ARn7cIQ7#5X8zKCf9x^_N`cb_DK<`ikgaqBF2_PPF5PvFcd3h1Ow=_d3ZCk- zS-`r5k4T9izUXQ9LB{Nk=(3U!$l>x-CdHMAvgXlCvOvmhwKkiUv2Jg?!P4h>Ny8Qm6#3hD3cpX>c&PQ{tD~C(~+vT7=QL;AAMxH@P>UeCr7T3$Q7|a1>nJ z?7JS}v=Y}6=PjCvW{gFIuoBpUmN-$R5BKhn*(@K>HhC zhcr`K8uPqG(!D-NWBtULd&`*USFdF5d!%OK$Fk$j7I*W8Wb=Pcyj@r5-dOFQ9}zdW zuHhN?fhh*q#>ICp_)bEc{;U5)-SoN7~l0*P8lrNR_dKrgI(x zQ~Sa(>zaY^RhndyhhT`tw-DYEO(r(uKQ-peY^yMuf4|m%yHsd0doL3KHl4=Ly>2 z>&pxO1Z;1_L1C#apS|zG-uPkS0x5X5x4d%yT^&hBINRLH2IjNi*nUFeIsn7HeHhyL zS8&;2AB^~<^>>G#un=P+UE*NS9cbP!zO@lFlwG`2J{|TrtNUH+(UZYhXIFqFE8}5m z!f1M=-K%@Ta)7jL^xcCRwr^oZR=4)By$F70G!M-E^LMuDX?Zx>R3WJS+PD>msPydE z-ne}hcZ=x7tQ;HHS4MGvT63LO+J2E^!39UOe!9H&){k&UKKc~hx^6~%iV#h$_iQ^r z1qP1F7c0ig{=t7uO|l<|{S!fZOZ&sIseL3b_`ulhtW;Xz5%0DMHvKS|?`Q93A21D4 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

C7Im@Ow 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 Date: Sun, 19 Jun 2022 22:11:12 -0700 Subject: [PATCH 149/220] architectury launches now --- platforms/forge/build.gradle.kts | 92 +++++------------- .../src/main/resources/assets/terra/icon.png | Bin 129860 -> 0 bytes .../resources/assets/terra/lang/en_us.json | 4 - .../forge/src/main/resources/pack.mcmeta | 6 ++ .../src/main/resources/terra.mixins.json | 76 +++++++-------- settings.gradle.kts | 14 ++- 6 files changed, 78 insertions(+), 114 deletions(-) delete mode 100644 platforms/forge/src/main/resources/assets/terra/icon.png delete mode 100644 platforms/forge/src/main/resources/assets/terra/lang/en_us.json create mode 100644 platforms/forge/src/main/resources/pack.mcmeta diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 73aee97a0..31c5632f2 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -1,11 +1,19 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import com.modrinth.minotaur.TaskModrinthUpload +import java.util.* import net.fabricmc.loom.task.RemapJarTask -import java.util.Date plugins { id("dev.architectury.loom") version Versions.Forge.architecuryLoom - id("com.modrinth.minotaur") version Versions.Fabric.minotaur +} + +dependencies { + shadedApi(project(":common:implementation:base")) + forgeRuntimeLibrary(project(":common:implementation:base")) + + forge(group = "net.minecraftforge", name = "forge", version = Versions.Forge.forge) + + minecraft("com.mojang:minecraft:${Versions.Forge.minecraft}") + mappings("net.fabricmc:yarn:${Versions.Forge.yarn}:v2") } loom { @@ -17,72 +25,22 @@ loom { mixinConfigs.set(listOf("terra.mixins.json")) } - } -dependencies { - shadedApi(project(":common:implementation:base")) - - forge("net.minecraftforge:forge:${Versions.Forge.forge}") - - minecraft("com.mojang:minecraft:${Versions.Forge.minecraft}") - mappings("net.fabricmc:yarn:${Versions.Forge.yarn}:v2") -} +tasks { + jar { + manifest { + attributes( + mapOf( + "Implementation-Title" to rootProject.name, + "Implementation-Version" to project.version, + ) + ) + } + } - - - - -addonDir(project.file("./run/config/Terra/addons"), tasks.named("runClient").get()) -addonDir(project.file("./run/config/Terra/addons"), tasks.named("runServer").get()) - -tasks.withType().configureEach { - options.release.set(17) -} - -tasks.getByName("shadowJar") { - exclude("org/slf4j/**") -} - -val remapped = tasks.register("remapShadedJar") { - dependsOn("installAddons") - group = "loom" - val shadowJar = tasks.getByName("shadowJar") - dependsOn(shadowJar) - inputFile.set(shadowJar.archiveFile) - archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-shaded\\.jar$"), "-shaded-mapped.jar")) - addNestedDependencies.set(true) -} - -tasks.named("assemble").configure { - dependsOn("remapShadedJar") -} - -tasks.withType { - finalizedBy(remapped) - manifest { - attributes( - mapOf( - "Specification-Title" to "terra", - "Specification-Vendor" to "Terra Contributors", - "Specification-Version" to "1", - "Implementation-Title" to project.name, - "Implementation-Version" to "@VERSION@", - "Implementation-Vendor" to "Terra Contributors", - "Implementation-Timestamp" to Date().toString() - ) - ) + remapJar { + inputFile.set(shadowJar.get().archiveFile) + archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") } } - -tasks.register("publishModrinth") { - dependsOn("remapShadedJar") - group = "loom" - token = System.getenv("MODRINTH_SECRET") - projectId = "FIlZB9L0" - versionNumber = "${project.version}-forge" - uploadFile = remapped.get().archiveFile.get().asFile - releaseType = "beta" - addGameVersion(Versions.Forge.minecraft) - addLoader("forge") -} \ No newline at end of file diff --git a/platforms/forge/src/main/resources/assets/terra/icon.png b/platforms/forge/src/main/resources/assets/terra/icon.png deleted file mode 100644 index a8f458866a0d1cd397e5fa592ef1707a97722f1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 129860 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%0DMHvKS|?`Q93A21D4 z;WVl8Dw5_-xBsgq9}IAC)V{}lp* z%zu+_Ux48E54(G1EL>g&c4%01QM$zL>X2E}K*IaU7t>j(1~QRm*KHAsW}Qo!p*&an z&VEYz)x71tZTlp^HIh%d&noaW&gVy7fZxE4 zesZ7dqaG2hDSo2o$d(&$ME0LBVGEs;jMfi4Eef2(u*hPI){d%`;YyKPayK_@=l8wk z%}X=8{>Qt3nFa7%LrE`7dRpw*eg**L-V2}w%o?sWj)f2-2!I}#ZAQDt46X>^%2~4n zY9j`7I}HEDlE36TtJ?b3JLF!?~k230OVHFJLDd zKr3;&_21!#7ros%p~|cD%aKW;!JF-K#ev|Z^Zun&H}vb$W{7#(DXL>iE|hH2@1;pf ziqt1vNNP-%5bF#$(uYNPp*6@3c2=>jEp>vwYXuIxGiQHq!{F_4ttKc$i)v~tR;Jwm zg-FeZJmbhmpRk0^GYXAko@JQPl1{#G1%GLULdL&H*8Gof=u1gX74xJ#=4%X8W4Xl& zyX-f1_1&dLDkA8Bu$u>B7Sz3xjljMHd#>ExtB^6lP{6bw4yG$Ax5oVchC_iTrP+wF zboO$e_}0I9i7Mzy67jc!n!n&Z~j?SFV~;M{}_7OL&oYZ642SFKYg=lBKP0;8}=Ih6hM2+~wAud9V3Hzogjv zo5mww)-kA2*Q zKO$Jy{WV*eJ`Nn?G9SiJck`2Z#?u$yVCdD1e|GmrK@Lbwuz{!qu!Fx8z0R=jq>U1!@b_I&<)950YLL$**4y629 zXmd{IqNS9lA%TC-e>V-a7WV^Ad@gn8^PPhT*%!BQS0*ZXoWi-Ur88dJI+Eimojsf# z1iB~7uBkOHAJi{kxa*~^a#vZ`0gAIcGhhXoAK}u9{&!jTt&>Ps2-1)Jb*W zP-dotFIP#*HcOtxfTms;e&ALSQU#-B>`D9j%T0%Dd-|JyMfO{uMtJ@k@-V8wsn-kNq2O3CB(Tjy zV_U!&@#pkW&lI#y^!|dF$w@EdnRDa86F)czyABp5?4_n z+p$AlO9P^yE7W7{al8((5KiRfH<%35*M_<_eu8o6*V{M6+@v>_RRNw zR*kC7*<8V`chuW~7%`-eA9uLBaR=}35{srm4{iCU-XOdl{FAFbP9c zhKJl4`IaFo2=jvLGj)89=4Qujx}~HLkF>!em72$UUHckv6UgE!sCdyVVzA;lH zkbR?;y!|FwU8dFab0(9m2Vj3Ucg*ep&ygHf)ibv zPXg4o%@hlRG4vlCOoZ`r_Jk?WEl~%&Z(18 zfNy@?#58wX{+PT+F))e-~dDc3u`0zeVBr$SRzo&=m#C_+D>+?1QQ>ZD&a@R z=fnG}VE#5*NtlWSqt`2o`S$TQB{lxm0IV1_unlrypdyUt;@)1LJKfad0qqGuG?JT! zKiT!Xv*1*@?*S_9DXl+e;m~S`#Lo)G)=yK_`Dht!3b-H~O$T`y+yUc;gIc&yOaO)$ zz~9%$C!}IqOfaW-{JLa4A8eCN1m@c#!f0D@C8MQJV~R7rHaQ}f^PW;vL_>&;TcnyS zTz!$%SL(hEU~Q#2ugrG=yUd&Y^M{M+19N*0k-=dcz`%QHes?A;vd&RV#mF#M_WNSO zOXu$5j#~hLU=lYcP-SD@u8X;|y6p&T@~Hqr_p_XE-z5&DDt}{WavpM!DejSPRmsqR zf1SkB=hFCW%qR!SP7BdJEaJ24FDGgLy_P$b|5NN8a(vX?PCx8@Tisp}+~Tx;4BOh>aEf*WrG}6S#^pLLpayrFOvUSrPHjN?CH5 z2DKeKo0vsy6sV;0A$MsZoy$ucl;g6u)sG&M{&X)Js7z4T?xb05qwt8bh#USUBQjuB z7Z8Mj@i>-pRWQlV5uidhqY^`2_`DsH@mO?Pnf!qJTA1{iJ|e-Z1Q26mHX_Ij(iM3v zO8@J)^gmuq2`YByD7BKG;Ud=k^7MkR}Rxp0a@~;LL_$v*Xwi=M8 z2%zZI9P>qWe&`DLO4Dp2(_FpRv5XMc3?Icx4JZ@~b%z!roYdFtmb5!GxvZHta z7kqPezZOt4G48iL!r^2%8!ECwq0F|t5T!=7uJ0t+)g`wV11}W(4IWV4U1iw^R`gp# zoNwNM(H^r#6!*nX9i{^w^jL8*C^@2KCx;h~X4D}^UB_#YAnK^_PM{&sggiqVFsCu! z=b+UHR*&vlj<8`nF8Z_;YbE+rk(6j2$VCe+SUWwsU7Dm@1O61HaOfMCE|Ss9rD@z=8@6N z<)LXAwB~^;ZPKoL^QltMDd27$_b7ba z((>}R=ZvCX1I#CKj}GHNMkBDN)n?TzER-;F*E}}zLG`GNd14>xs^E=b?f2#%H<}J( zFz}al{tW4rM9mRU3nQQSjP5N1uLP*d(#OZV)4xsvUlg##OGp~s(y-tlw?)zg_OEay zPkA-96f~-bQ}H_ZnY2PM>3-AC9owS=-8h&u0$`U8BrXohmzX%vCFHPEL0dj2VcjsV zRd-SYv#B;le>7a#9;x=eA=0b^MD6gGh@nh%P~7_%h{GO*6-VstKEN?wN6~CPu(#w8e|Bn1BArqo`)E;)qv>@Na+TmaIqzmM;M05UhS26Gxcyo z*Eb%KU$!?G)gS3BNu0$NK*5_Nn0_mQt#10H=XY-x^&9pa4_JtU)2dE!QhOpVNkU^s3w7<_%}ivdx+SEq61X9?`y5~nxqUZ@!7R%eEg5?9he`Jgp~=X)B|ObvC8TS>+F}5&&0R zJHRwhj2?5txnC1;uL^(xhe;^dd}0Qp6|u8H3`$aVW;3edt(2;k@rp6ue=hg@1Z$}@+Tv;oPu#n!>(#TYS{(QyghO;6_ z!rQETA6(PBCR6#gF#X7#scqq#R|NEu`Qj_hLpjsdYj+%L{bE00%N1ZEmTUJe{_E`+ zNYpGD%6uBd7f@lJv$X+M0kmcSv7p}4bz6HKv=fn%oqZ%eO!bIME5r=pciZ84huZx| zw?HhYhllhJKm;KiS^CmHf66qWfatJr_H1^)me@8%_%cO|OPD6^;3vNqoSJaOAX0tt zZ1DOWR&x1@!7*u1V6KqRUYIKV^iu=F!yeoQu@DkYmYh)5+ED zAfyw(Ho?G{xnj-_5L3K{soY8;`e0H zJjD-3Bv|)bfSbrbFsz{Q&paecj5!(g4?I&Qq0yPfY@N2LC>&`5QbG;4*s=z%xNbkQ z(Lz+&O!L}`Bu-6J?gYv4bokj4X4=voV$Y9AQC_TLgUZgpt|FfulQ&2s{W9cE;#3nB zIeBdz(`wTtyvs6nTE?C~QiJcAT_qzlSvQ|@Tpwu=kX)dh#>lCdFE(6y zKK1;1lpDhp8B^kCWRd5z+MbqnYc^BaMj@-STdD3a!MYxVDy8p#-&q1D-wQ+Ffc#{? zn)VlD)0(9y==J1V{6B{$JSa++Q{y}+Odk3EXzm0n*_q`U$p<&DNoBE`e!DEg#p@vR zx=l&D-~+;3!5)Ygz#pCwQkShP`+s_6d3cJ)`n3-k$Pc{b;@7H!#z3`NH!QE#eMeGv zx#V(xCY}x*JKi!fJcd0_D`&dTL8lQ6i=LyuWU~=$rvQca?SzTJYCcVo%|mKJgiJ;Y z6Z67DJ;JR{8bf@{{GFDc(Ve*>-jSBZUPg0BMTo&FV!%(#f9d%QQ~HPKw;4en)bIW$ zC$SHJiA0ldzk$$vK1{7S&z_;=yYE^b2sU$ScLn%}3kv_%h7$2C#YuG=#biOCeG9p;l2_4Q6wR;el z@1TR){LMCw9NXhgwT#6T_~P}>V0Qw$ny3l+axbjbWqN!*ZmcO?^@~Snt?NBq z4`cg$mqC!zr1Xzk@nIC+q{YQ0w)X}fEYc_~nJaKFA8ohEjHZ6iCPZVY!&}972{1>& za*J?-{$c>50Z&GZjxEUuK0IGsj<*S#@d|-Kyk#6nc zb&$JpYwZXL4L|!ae)M5?!_;!{&!fr6lfoban}(TRMf3YIJ{2K#+>ZGZj2^k4HC~8H z?1KT59|=D>$lTT~wHWriTXR_u>HAVZo8ZL3s@k{Cpu4fmU1bn+`j{flT#v%cucqSx@lA( zy7$AROrk_cQqz;h_WnfS`_h>pbm(sBetPmVd?D1s-^{Dn)33@;4g$9oxJo<~iX_QO zPCdYcskLuF*9S0J3x#>Ozt6MYobI+!T7wU~`}Hexu5>ne&f3NYugQoD zCZv2dKbfp;yk|Q~yJ6PhXk-tjazm|Wmo~%f64$D3S{SZ`7<}#|F7RMJ0k-tVWx^L( zeQtg?7Iu`agIU~3#O82 zh#Xwus;b+YlI}f{b%n2l8~h*Az<*THvbnBrS>ZL#^lnx%SP;;*=~ef28{@?xB|VoJ z@;SGrA_oKptLFdLpNn+!*q;IDsuN4xp~u*gUvB;ro~Y;d)+Oo#sH=J=_shIn&nyp} zr~S)A4CMsI8dfc7tNZ*-ek#t(0bT`qJ!oiNt6w}s%9@QXz_AkO83(>5w`2{b%8_5cw6w}sTH>0>>PU@X>-Z44Ge`?iT7;W zQTvq+l4qv2JtV1DyN$pOFzjTPYCC#H0@_{@A<8LL+ff)lRl%6tPXWITuOYKuyhVnW z$G~gIiT|y*G9a6E>7EOFjLewsb`pSujPmwT92DS8L1R7ykP{R9oJ!?mU^5GdxeIm| zUIher@KM)%9N0Y75??5Fq-={S2+1S!DfF|NV>qt^E*S&};SxFZN~T>AU0og311s~? z&4x)THE(TyO$;Xr*9zM~=<0VEFW;%&2GiC40qYbGz;-A*gYWEJJ;Hv^bcq9iDB=v) zt<<(4z<9HO!IK0?T1i?^7qTxTuA_w};IBBq9{xFgNn7-A;oiR6NIt|a2GI>0+m`26 zUsIF#($6Q(NncVcLw5M_31VTwALCaCB#rL8z;aQckFb<3rbBA-vAr&@MjOfwZOjw{ zTA6wN8(V{vqKjWX7U_T9^c<=8xOU=_Yr%>}s5og>pACrMa;xNCSXKg_b;~<E9#KHzPUy+KJ;gF6wo! zM%v==Xt6SsUeuz$(yqg-jxg9KQ`phM;y%Ey9E$myN@jb`j;#n( zWqY)LI_?C~!%)q(n*W6u1i8$K!|yJ4&e6#*VU4L+2B2Q5S>?xUolCB;8$Tsvk3(An z+h7uA-xEUegYUz-#*4?WTN*)u?OTlKj?t7YUb>Z6*+rEiR4s059(VR%Elf7qwNGvM z*3pzTHh{BtU>B!)vdu27BGeMp83(`X++N}*H@@!Ar|I$zm}UNB!y;`lHmycvK56l7 zmR%OWMjJCJp$kb?o%+a-eqClD{FV-2bAeblfPRK*vRHgG;0J47#3={vszi?RA9r3E zU1XZbEq)o?35eXgl1BXJ;s8Zi)6LUG4lv2ylfKNjCT~a8h6hhgp8a~hpZuDumD;*% z6DkZ%)59Z<*<@bzfFY2tDnY6|KpxHqhrC_1lz6R%V>-XI2~6n#LQX_9$(H@37z?}k zwAJ{EDV*ZU$HsvLf!IIoOCXFS>Yjw3M#gw}e>K7b`J4O>8A^!*aswO~MJyP4vlT8Q zHOomO=?4OM@F%zN9!85-@g>{yud^NVTAdE5{8q9<6 z(|b@q3%LVXF3+>93>f=GCpZJhm5#6w4e5aU2qxLU#WJ6@Xa|2FJSLu#{(F|SKmf{B z&PoP+>{vhJO9%8}YyOBm3~wkZNbrwCu>RAYrR{!CN1I!IH3`hXCPMSTq5iYY-ohhu zKh3jxpAnJK^QO~fXgxT09)9tg>C^0eF*!j|cLx91kg{Qwp4lcdmhk}xV8}##B?!2M zlLvMYPoRH;FGE4LVO4Z|LXNLVO7msX|CqHjrUh;0#-N6+Ms-S1k6_qu*1PRvNT-e! zEPqw(K~GzGZ_9(&OssFey!{K3kE862yvLOn7*oUZ*%BIes8DauU^Uk~BW^orUACofj0^Uo%aK7q37(Cg~7e^47@hH4M$GS`5>(4~s) zn=01=(`@X)IK{ng*#1>3#S-;-{Wo@tyBlB#-e*m$_Ky-&Q|2nB6j-axLA~)&9s1(R zQ1O>ZEkwu86m%Xfg$wL7dhjEJAm<+Ear>El`=CAkj0(jY4m(q35d&j6opi*~UzbYzv-h%DDc03%)S?7fsJYkolBx$N?2BZmSY zQW~^@A_53wU@A6Ls1Hb0Zyth;Y$RI0jshZO$>JW?r=jkSycC#Y>{zyeKKb#;!v53w zz5ax&B7-?f`Dn_Wu-I-fMi0&4UVF%F!RJ5 zaKEP^On<-#v|Jt_;R1LRPnsn-v-YpJBK2yYu(S^3q`Jf=V_-)+$oxk0<}D7fW=kyO zD=l+Rbl@}}Y`%uvdhMb_6LoU2%1upEYsG4jV9*uKGfX#m#^Z8mQW33j9>5uKcRb^t z_Ha3m6IJ9=={2ta-;J%oe}bcrc2;}pO zQ00$oyt@|{%ddhYAUhsv9`n%X_GV0$iOzrH-78f><{fwTOL3^e)kz7>N zO^u-R3r%Suy47?U3pb;864>LO>7BXZt`SZ>>T!$;@Nck?icPGZPNwzrI>zy--}KDt zjDY%-nnZIy-@qd3y1pR`+d;%w)05?=RA4%knB>riYiSC65zZ*c_E~#UNeWt!Q}56o zHldvTMge{qvan7Ze?9Zd4}`}foZQ&;pVZ25M(26xDl7r=!;f5+T`*(;Ug6KF{dRXG zXi6^~E}sZu3S$9hEUVUSH`p}gcaClFclszEu!E$ZxPxSW|Jxl2iZ=);7!Kb*GRrQO z9Ok+883+-rc6%&-BZ1oF`%HoZ~IE5r&ra>^v%OPeJnbpC(b_Z{cp&(5Jp0 z)|3>O`M9HO))IV-06zw;NWS}%e54tmZVMq#dYin4HqLNp;GLpjy{#UxfYIx0BsAbgTP+j z0D8?^z3jO!MLSLxX9}$4`Rr5E^_g%vqT_CeFv8=@OEMmIk=a(V9;JSDGu!^Dfo}Os z+~+2ee5s8zlUlsUM~Z=fw$E}vj1m(Q4n}!*BYKFpw4oT8>8Z(^?S7KsP8g5vAh zjZYH$(@N1|AXWMI@94_oduhxFU_B4!)x;&^R>^|2V(mw&v;I06I=rvo;AINzskFCm z&3Ptf7mH(EYB4FWS5WI(>x7%%Nnu5EJ93z>61$OUzt(M+xG#G%AH*6AfRXIMz^jOF zvt<7^C{%)FSLV=zb%88m4dvw{+0^-MoCKd$_iPx9K^39E;RwasqpVvw?-C*$X zz27&WK5)#_nVXpT#S+Q`+_O$mn)8shsGLyl*o}z&ioKK0zoU1*Y_j1bFM*Z>#&4(g zM=h$(89rz|D3;f=c+|B7Kh|uqY+XZ)r}m?W3@tH)oWP7EE1%mK->>%@~nZ#i?4Uu$?wn#D-a8dXo8r1c7ah=Wnp^UgXv!tE1> zV?E;#pwY8NXVgdaYvH<@dt3a<{NDe4VaS2D>?ebZIlid)1=^*X!|YV|>~0fBdT$)e zK}r>%f#ert-9P(*nd=YVThdBj#{7eb6K}AdEPI?{Uhy};cuBs*i0ud{oIG(@JMq`I z0s2V)m@37i2M%JE&4SLli`A!A6X#9S5IZg0LK>=$H*WJSp~ap6^=(5;`&zd|9(TSL z^@y^KNus4BE06~!sVEz`6;Z||F28AZArbthRYT02YD+4u_}Ol-;6P%(I9WRe&08`@sYL z6K}c<2Rf45j%CrW*KDAH`R2Tme;Y>LPs%}yM(!YASSO}DS|rE|HP^wA?9*|+)>Et( zE&9#5(aCCNwpV~7yROvUSg~}O=uZUd2vzbw*a47GPh3QQzBS9@weBCFPI4?chqOJ~ z8C#$ker=)o+eP=)A`L#-QsVaVgLn^#s0C%khc-WlpCze}?c$G^hJ#WqOV6~1V3rD2 z&k(v_wXb=#-yHHAOk+7={7@56ed&~rybgbkXAiC7e5Sm(MkwdJ(9ab6jj2JMgz@yTVj==_yGh&&L zxz|dTliG&K(T6naw;O?V%)r4IGmJuam~9!K((pclTqUleNy>Z>27e43KX-zgXY5fW zVFL+sFUe*mW(FKnH^DBoWFhT^`H!286d>;P#xyVA;gI@R`8}a=sU=#bt6k9-JN%=F zDpC0a$1gysvcZCG(wq7K1Mz&A#Qk4hE)x{YyCI@;o7JsyM&03krvxjaa*{!IVmuYv zlkAE+bcu6e+l<~9c5sA0r~_Gp|1~fvKMUdkV`@obijDfA)+NcjkE2}X5ZXG+vduE` zKJx93p%%a9AI-@(m+$hmm^3`|Yn8-1thf0Ss)CH`+toof6sOs*TnNjt-JhQ(pMpK>!Zax3qt2zh}u)olF^}&NhqZ=__G`A z)dYi!FYOoiR?zEu&0V+ECq2@(CH7l`x^&;YQbwD~W~Wt?DnVZ>FYJQ-P5|CWq} zYg+5$#hMl-s*N5usa@ZG-^>rMD{oQ5A_xD_P(D>sV?*nSEAAGBz-`X8@m+pHyPm5% z#%fw{S+@Q2(X3uyxoN0nJFIa8Im9^rJZ?^zKj}fW=>hi$C?LHF{*y-dqR8O2=GIb*2hYMAzhzaz24Sl~0tUg_q0pA$e2S3yq z{BlXhIfPCucqhmcO|Hy5rFFgyR^KEK zZ>vobyMk}kKpTI22$Hm0u=^z0<+sVn@Xog<3S!!N|FNCHl9DiVk$Ivd)Ex+-PJyBCx1DZ-{ zMv&~qxK6r}+;JAOA`l-2yv0#~F(fLse{9Gn9>3}%nU~bIfBfp@&0Nm$C{$-~XA|W0 zZ@!M(KvgM?ENo!E6F<#Jd+L6=_L-|iQBdbNWN4;Irg1KznEc~rIR}RrF!p zN#lJUbh6f~P-;mdfzU7R;Xoze@3kH1DWuv)0*BJEuk~r_?x6Ko}YEX(hI^`c#oDytW4v3m$(}pi>n`Kd$k((%_r{!cVb?PjES2)o{PFF zZ5=cE^Lh~%L+@{s`wnf%Wyyp0`u_qi9*>Y1UDfkX19G(u=I!J8yf6W{6x1Uiw{IGm zEuu}%oM63BZeZ~9 zk?JYZ$rn0EWIQl-al@I12`GAbhniS#Z?GUHn;c_*XDbN#7OlDL!9(_-s;HY!^+@Ya z$v6ziEc(uj_5F7ic1n6bSqzhX4&l@AvR2IUFU?rsi{8n&bm{`?m~k*>NTrzYbAxqB z^-2wkIAJo<=Ja0(b~>pZ%##Hw*J^$1g*IF6942_${RRo3X`7k7cR-;5iPs-qqy zYu35kHuMw?lJl6C&Xx6~8S@$?%bW@@=X6rvy%l#}!+M&M*B)T0JnyD687RjRMiwvM zGV1wuPU13b$tsD79q`rD`ozkc$CX`*sO@`iszK6ePyTW6MJHTrUc|qXOd25 zF8$rjbc!%@bztB=!vX@vkMKjci_Ld6#TPQMzX#INP@)R*X%-1^T6&-?fAcCMt4+C`J37|UXG2YcihSB-i`73sha1t=PvCyb zFOJFQM1M)Ua{aa`jf|$otjJ7Mzegc7*c8N-D(lVs`tB#@v>IP08eZMnPYfZ%cJT6^ zZlk7ZlsM;UC)e=3+f3-ITp2R~bgs=wMZ3d~SM@k&3M^&>;G5flhQ5xKefP^*AXPh6 z!p(-+B^!;j9g%t-5YjsT7MSQ(5V&h6cmcJIr7zqpmuoDSXR=Q${yqrplqpkH$$T2{ zeio4sui_i;*RdhHzs|qp=F*QVkIx*L7KGOfpib1Uk=1*cOrqkaIxW9Pn7G%)b9v2@ z;X&6x&Fc{SL$-+nE8}2!?LoHmj@qA347v4#?D~+c#m7c?Nvs=;8}?%Jxv2G4fat{P zpyH?aE~$$p7?uP!=ZuH)tblvqqrzGKkHd8R&@!utlD3XhxtYipqwCe|g!;lkZoRC~ zAi7e5Z7GKsSWpR*J5X!SIcbn4CSMIwYVQbrCV68TSxUn(Qsd2B&#eEb&VDhM;DufN zY}$*zbBk5p^xcerh{?g1lxQ`^X4J=lZth%>KN~HYUCsEIQR*ZojMy6`8<#pi%2TJ3 zrbf`W5hGpq;EF3ULMFi#GwrkGfi*Og@faAodkpEj_sjA9s<*{a-dJEKJI66XWnc=l z`2Tfa`5!bD_pS~?P^H+Gq=-5`n9K`MSJ_%HT`6i8r3-bxD(+y6^iHpN;L-`}dm`;2 zb}zF77QY$urVJOlRIZqD1!QSs4kdIIUV%Hp`PAECbXyW^2>_xXm~Mf{v0|c$_dI>s zH}STp>00@h6!#DmnucQoil`>%j8DK0v7-^dO?g^VH6YKY9rTj@L=vRK1ZYwruca{`&5GHBp@(TaLTOw^%r^PY z!KtP`^7hrNIGZ1$rT~WdfPtJE!*Qx-7HuDVw3dzEa2NW_CpySzU@Yu zJK7qdinON+S(b&FC}uS9OMVrI-^rqwCgC6O%_{wwP0FDWFpo|Js0iz>IoZhuw=M>^ z<3MqHj0O%?;s+99(%I!L`rS8l zU$?kRjB_}^ZHm-$ zE_v7s0cBn5H8Y}*(n!|76sLUh@4HdD_^F&Wqxs{_v!r(}6D0XPZ*D%_>%M|f-UyN_ zubC8yA)vE0ACU*Pl;uAJN5{==-J5~ut#4nQaKp}P=Dyl+JI2||1v0w=>zz8hUUfV5 z<{1VqmZL9IYrhzU5-p8;cH_%-lUf&85)Doe(lvX2Y1D^gO+>NZ+rQ`IM)=StL*vgQ z69K>Og4{XKnbOVk!)0GY{i>V_q4#PR&{~sI*0gNQ$mUmlYwWvdQ!L6+ZyuC{_axZ~ z5LHTwnE9l}RukB|4{Jj(Q8%E#{l0(4-~vYtkx$4!7->Tho~3ANC{0V-w@3 zbgjSXljrs8nfTkew0XGA^4Ujpe$Wqx|Kib(B2*Gw1Ohw1YdrO;b4*pEqVVkt| zHEC%~kn^|CViDcT(s}B23#v6-BLW#P>f*i2d8BE~n zfNWlL^NuF?{l&J+UBjr+M&9aNx_DU3fVnuc3l&+L4=L2d&1->fN!=@$9W1#fdYLA8 z`}dW){lgHcxei$up2fj=}DTX^CFOPIxQw?HAP5(ZeLCuFn6WP*NECpBj2@6Xy`t zFV?X%Hh^txq<+8iikuFE$ZlYMgA4El0$SMB&(jLC!jKLL@~N|6x`4U~J*j7St@*ef zI3%OaVsX-r^Sfq+S=?{nmwLMmY{K?^xTFGGBMi|zj$$0TQq85ylXpzhHu~?c9J;9n zn0hnT#Ui85TLg#v>d^R)tMrsIO8U+#LSq?TybrABGF3wrNtZAoWm9~-o%+|#AFj^C zXXbO1Je=uX9ta}G=Z!y4i`MtD@m(oi4dR#InJhVo;vhvSVOvx&DZ||(Ejv#KaEUos zptEw-I(<6SxOZT`lD{Ul6XfHV(Feu0l!Q!+z$$WrI${8M_OY`Aoo0&!&6KDvUFpaI zY6Xu*M*_9$Y# zzWnB90?YJv)qp~Y8vM~7$zGGdd=yt&fMsrgLnWchqTL9i-Np3rBk#O9@3Uswy56eJT?j;~2egMEHmFKRMV-J`9-XNMJ>W4Pb0~tWQM80I#>Ob`8a7aTp z8fK&K3G9T3($=9-mL8l!YM(?Ye_ESmM*3a_Q`4^Dx(8pxXA92JZY%ncS{LRiX(`(H z#Z_S3pwIYP#N|~jqx|EG(xm|fdT!xljj%V@<#ZU2NIbm10Lw}+CTGBECzMey{AcA2 z!PYct2t(bf>!va($`IS~If0ND4lqL9Q+kj<;JK`?X6GCfEf!Q{pbkj?($Us&ieDrQ z29E0%Z?s=%%K68Fonj;b^iBzs(YRD^8V zGBU4`2$#BKX0NNvY>~a!HA2^QajmR`Y=uj-(JiQdW z^r7<&W<>K%@U$l08j)todQX)@A#FObMkYciUr|hD%A#|*!4x$$dp_7+r-lZmHAGqE zY%eYAlSg+5ii}64)lt{OTu;xN6?@cNlw==W|f)uQJ+}9bdjcx1F{C5C19b zX?#{YUgJW2ATx)x7IN1(8Xy}iU-u2o_9fN+WMbLVUdjSe(j+hPt3@f!UlMTmwq9hM zPtq)H`G&(}N0*Ft4K$4G2_n76`cdD?4DlXZ#R2hYoqh&*@zGy_Y*F&t4AV^sAZ-0u zX92JnC-8E$aN#usdHD390d?$xjUI75`Pz@=?doW5hRRd1P=p{pz@~zyp&Oit$koeH>okTIc2B2nR19RRiyeoh}YGZYR+j^o)HGz=lgJ|aSJ|1fm z)-N!3B!AeJE?F{p(Y-3&@LgDzL&Iueo9J)Pqys348Su=7A9#*6m^ALz+_OG)DIT>4 z2CExKlL8>qY#(Z&L;MUVOQhmECSt}EYHiCCuG5$vS$h!v(9ks3l3aVSzVMkh%VvXV zmt?{|XJgO3dS@{p-qNa->@VaqZ;wuh)v|;O@ZgUEEO{(6hcv$Wjme*DWW#D5eQ83l0u&jsdgy?P92By|awGn3{da z6kv4JLq1Ecn=Ib`1olOrL1U)_>%N+DQhfRIYwvBA_GxSRr^Ax!4iV+8cE9~thkQ4B z6<>3zZjVP)+^ym*uuc68d&2WUg_rC=fj6~hs0r}q*t!Na=^t<{T^Q=``9MA&XiOiM z{77s5lWE_X6i3U1>~5ce}R9jKC%I7;)&QDMC^~m)h*;`{k?cXj{}zI^AGpG z-o|+kyU08z(J@Dm`msTV)z{_7~^3p_AFxm9g$yT9GNP+KwU|?&cNf$cgwg zBw1xAVpcUUElb=-InwId0gadFCO?um4BU9D&hdO@2S{br>)D719fZ%`{Hemb4dSlQ z4y}aX%_m7;o&xh^Rvg}F#$Vf#dBz1B$&5``y})MI&w%43speAJ2#HAQ;&q7n3f3n9 zNTnF$nI0|TJRu`J))VN1^?86kpAjheVs^yOf=MrvV6!u;mU^h$WCOr=Z^%Gt50P%D zC380TN>>Wn)hXCvdiC*2^msA~7#j24_+EG$)$buqqvc5R!MoQ2$RIiki9U)PN@A}C zu-1qUkR2S^4#rPY@OKWfKIb%dc%Bk2lWsB{E7X{fT5u6Y`ZZVjMIHk}*a{dnZ_7bM z0jiJwF5vc5MWt&=Pgv93E3>8e-R4Ne|5&R;K};wk1Xh}-45S-O~KN= za(v_^7yK+qk6I|`Artvq8j6;$tpLVTGcs01>dzib^ld{ zo1uYg*ZDOGFjQEo#P}fN?9=~{avdiKcom!j)U!|G&Xoaud`dB4;~R2@a9*@K-sA-b z6L*y!+4!~a#0f*e8{}NQVLU1SUH#yv@hA0U6N-bX%CGqv*Lj=Yrx)S*d~d>Kz3sP) z;2FRIFDqEbkj*C7QlaJE72+ptF}rRglJD-}9DVueK>p+UmItV6NR8J@-iXGkj8qoU z&{*&nAIDjMEMeR5^KXPfp3O|Hq8h?H4z@Qu8Q8Sultc^!vqquMNn50+|QA1P1T44m=BO%0nU0m zUom3JCnhQ6UeqhY#?4O9RuvHQ2*eS^*P{FZuALM3w&jALP5zV*fPaROQw~V!S2@`7 z?h2m9%+Va~^-+jDN%B_0^NwXJd8rG$@+}X?U|nM#-LBa_XiNB@p%0iCKIBiYk{lrSEWkdyj+#rtPs%Zi-80i4Uh<7fEO$PoE};t zUi?dMfzi}`4U6O3PB;AgZRPJS?_WeqmWKgA$biuxpv}aqp9Fq;6tw29a{x%fK#F7d z#TKyr;jmyQ`{y{yBqy9w}&AM(KQk!(^erlDo04lGE14^upW zFTGf;c9}ER+t6f!-o4F0`L%s$zT|2>dOJu`(g8Hqd}a$9p84ZV6_2c;aV(bK+67z| zV$tMW+nELNE?*H>^|Tx*dmiS(7Ar}Wg7;pCJVz+)@LI8agvE@?{a0W~QHb=c4Z0r(9!;euA8O7u(VB-XTf{WxXqE&CwI9uC8^5jJkKE zgk{i-2@%DPaNvl2_LWodg$U^r(S*=q5k_D_?yszYqp^6n_cuc>IoS^#S8nL7aLZ90wk_$CFt^=SUZTU^W6rbWN?bDG>} z5G`9sXrFlj9Y807mr!nf=Jq3ptA7bpt)jN)rf3l7m4izK)uMk?+U+| zUgaRF%-iT8zd5;1UAw1aRsm47wwXl&A3t|Ci2Fx-{^M3Fy3_4t0RN@=hHLd(0uw3o zq!2Jm69()&>1p!#FwM{1YDIQM+M6{m`WyHKKA9CAx{78I35|M`O^ME0`k+UX?!*TG z#t?wXKt0!-9->+DG|hmLlV!-5N2oitb7;?TeF#aXK8l~1jDo)M60eck4Eol({G`y^ zAXc%ee2RvN?=5D-Y%^5Ti5!#%fm8bCIk$mwZQ z18lzTDe_ZL$54WR|5cO83wB2CDiH>MP3c?4^?MSp1N_aTgsbv=Hy-_QWx*r<&oNV7 za;rQCa_)WQOHRM`U380FE=0KJJ=? z4xrWj&S>>eIRw;ap>K->XH=T~FNWxyirgKd@OAh7PYULz|qSTw!2k z030MLq#bTJ!5)v+DLi$6$NC@>$Zq!+dF%j8#C+(xlg9E-Ow|X5uE6XWx4CMN9?pC| z$=Az9{*7I(oS-Obt)IZ(bu;RLArRyrAhP8uWcJa}7mY)Aa@EA49PT$xmierDMoHSe z^ByF3el^WIJA-^*7thbH-B_Qh5|VHlnN~#J3FbJ#5Bl!Eo8xkCBD?9NRaRg{wG%3# zd}cX@`P_q%(C_v%CDnNlF~};-Pq@r_3BG2YqQ zWB|qyEgDfNk~fJyUF($O>hl+v#-Y5l>|c$#P0JUf<7C7=@t(3*~RrWG?m>EPILIpZ<(t{Vw2;p~!?>>z8cd!|mJG?+MW%y|U_$y_thoD>QB_z8t0&{Grm%yK*6{cZBdW57O zJdy9eI2A_~!I2%C2B`~47(YESEpIA%_jP+v2JP^pkEsI;zfRLSvzD%N8OP9N=kCMo3|?Qz zo|*>{eVYuNVJeUFd*j4`T$BElA1mf3Qf$`&*5!WPS`}VuL8R`@Dcwe!`HD~(?B$1V z_Av12vK3{te<_5U4YU2~a0_05aby&juG4?Al*vD;zP8~CM|czd{StGpN|D;PgC!>x z_ixRYx^AZC`)UND?NeQJMAj$_p5l1c?V1R{Xu3dnSRbDeRaAmXN?>_ zkUo!`V)*!U@ohEyWibzAHEs&C4|P z@tbxhHQw~@ei*_(p|0s(gSKMA>}VTCDa0aNetJ=$@*(j~@AJ%8gLc}?=q}C}S`JhX zqkHiN>=3t8LwWtx=X>6`K4m=y_< z<2o=7dY9cR3n7|MBR{>O7;}5PU}^-m%Sq~#6Nw7aq7oZ>SGJn^c(QOejS`Y4B(X0N znkyzlg7zr2F88UJYmZL~wy@Zv?SeX~) z#P&X|Uiws0u+^{GzAjykIq%2H^t_2Ig>>V=sh#81!fJ}jSvAm$y$RkbM3=&?-KK|1 z!<5aDd^U-NI85iOPxuBOrmq@G+lJPt#$ucaQRyJ0^7IwYEcqAOpF4vlSWhDhXUUhG z*lSYLotGB-AP3qAM4f8?CwraZ)NLfb83q%cu6!!Ba^10Hp8oQC{d}~vH7nW7TKPLX zqV>v8nY%w;4CcCGfk^txK1qsTa_sVBO5)NZW8QzY)dC@<>Vmkn+fe$xFIQl-<=CHkO)Bf0eKb1U1~&WsYTF-P zSJ<(ot4s?-Fue{NTp-`41TTFYC8=eG z3ogrUF25uQH+u+!Jj%sP+I>?gxzBq4D$!2pn*4W-ieEy7mhkf3(b8mvx<~9c=_vue zn(xpFrGeUclI6e(o^dPci}nkNvl085xt#XeCg&jA@T?4{RE5b89UUfluCpeco*Cii zg|zKfPG0gAU$JH<+i9~H$H#5Hn~FkS9yM&G9?Pq_W~#mxcomPCdM9NKo7THwdO~g; z&?h}VAp=iZd*nU|6Zypt*kvbox0FYoD#jn4Shee5EZlsa5ar#Iq_T?+wYt&8QKO;_bk=JvrY3Y$-oyZ`>ZxZWZ z2qRn8Ucu=VIV$W3COWhfp!>3Cq~oOyVP6c}l*KNwca4kni2!8xwO9zq`sKe=^Khe(z@Sthn6-;QUofV z9S;U#=h}QioC%c7Bop{!O(gz`Lb0C;lzo|0j8gEm^r$j(yZSF7fhl4VJ)myE_9gEJ z1JNn`f-~z3`_<$7?oym}42nQ#lMT-?SIP$0o-pARgW$Iu*NI<$3*J<4`cJ7OZAbBw zB2Oya7xJFY|9hZat5vk;t9L+Li^RE~GUKuGo51?`LfCJzEdTR0k-Hg{n^c2Cjhmw1 z(0lkBJ=~x2ghP#~Qf}<1qsDIw{z9D3<5zZE6vhj7o7mYohQ@B166lWW&uQO%BOPG1HQXjnJep zZxdY9XPhYBm-mj>RYKHJ#E|77nFMCEhMI0WveZ(_6FKed_hn*#hrk{j_#D?vvU8gz zOjHtY;bV4j{$5JwT&a3@o6ui`OyA<>99G~5)=GjWtqU3Lw>=cB>S#u#y(@tIc&B-U z!Q~6sV({!Yj&=N3VH4+ue6t%8y&c=SI4$h#Gskb);8u{wP@MRvocOrW%-RbWLg>k` zIO%a`Rt8^VkbwH@PZ#&5H*YLs6B1YVI~tN3b-rC-gBU0t@Q9xZK2=y%TmS4z5%~V; zsk{V+fy(ByM<`S@>JqY4*Tl@f6XPKHtA@oAzWU*T4aWa+(Xe@K&t--Bk1sF4hAb=8 z8qO?R$%=wRyMKcZ-XN$w zb2>xtHZHq%eN8*WlRNeZLJ+z|M!>%oU~MkE(qg!HJlS^z`XrCdiqG(JN%^waB(NOJ z)YmejO zrgnblzw5$_XLF)XmMg-5D;Ab@ih({tJvNJ_vP?Q@ecLgSe^5itFyhtY)PJ--SYM1Y zZb6_~%jixm^e~JO7tvyFs)}1-hQ5RhBtv0}pQ_=gvO7#{A*zmhayLCT=xL39yg>%Yb^R(da<0gYmvEM$FT8Xn7 z#fp3eQZ!1@^!6aHjx?@pcP{0oAE4;J`tWY8p(Uy!_?eJ}&aS`tZRY+;fMPP=&hne& z<1rZ;dJ@H?%WsHksp+Hrv}NG_yS|kCw&nILMRwWg-A&bVwbWnn5D)iFX>)@;X7}D= zmVz@fJt;l=Vs%sJsgH^&221gf#NV7hm8@WLQfe}v}z!b>)q%aRX^wvlM(cD=7wY3w;+fYw$YIq_n04E+pvZrO_*#_`StZ$oHX70hWp30hU9a z=4HT`q~+3c%1gX}j#%fF(Tb9&z zeb4WX)#(|F+Z13?2u-_z=mp>9;t%|E$b>>C0iP}26__Uh^N}#rj>Al4-t^t_AlsA5 zH~H+s2^2P}Dj2XH6~AVf=#T>0i3_3ikk?-mFwNO=%3EHe2P@nY_o7naFRBbyQ= zgAYlX%dt%S5}h?@y-yIH5gH_lXU#S)IwUxe@h@g;N=l$buT!dGsWg_!BX3(Ew5l_c zFi(#4?QgNsrra<`YrH*ur((+mY;L*&$@y@h>~E+2U6-}G z(!8)_z{_EF5K_L;in9nYbxYw~ytH;9vJQ4oUt! zQS7{6Y%kR~Yz(UbV~6*%>^JF%OvU1y{nu6ZGO~()5~lziZ4vPOU2U=?FM>0GR%)DG zFs{urHF0kA8maw({x|SVccf2q&xJM5vR0GczW?Ya@{Yi!9>+}!fBF-s)QUa^{07$P z57Mk zwGe5w_491!ZnASBga>@ zaL`7C*0`#Se`4JF<2yS26gYM-2jeR0{e3rz=f|}b{03&O5PGKYQcI9D+M^)=$XjpZ znx(jGpD5hSd35vx(dYV*amDZpV`orr=oDo5^2^FUh?64h;OPupWs-s^Eim;8;eYqO zYQ6MfpgmNu-CQ-qG)8{fg+4tu>Li)qt5rjU%k+oP$|b{O<635|jMck@eQ|iXrl598 zcvQ_i4LJ%K&h)wkZprL*pob#yN}@6E1AhI27IOl<2sRm2UZ8#`iRHar;_GMxiU=3B z*L4L7x>noNV?opD>P8e~81(LwgjOwlAmn&M)_85^{MK{H()fjjyZdSGR3#VhX=8#) z^^$pV_vf0ycZ(v91~TPAj*fdSS8veDV58;9qZXpD2MG=#9Yd#2C{IzeS?$j=A5A#7 z+ve8YiNG;)?&>{t=H8nZb${*|Pnfg<(pi2+nPV(%!cK_9p0OU5l8@R5!#C6a)S3Ji z=mq&ckH~OL4G%J+I(-$iuSn-#7?wVYDlor<1Ux`b{32j|-pN$Kl1u}u?U56SKoyak zykg(d92#qz>tRPCmCQzMo`mW|W);Y?;*N}zZ+%l9VDIhhfm-H^Dn|W>VOscDHM&O( zC$A~DQ>7i^{Mv5;oc7FG;z({fwg>u*XnpHovOhy%5_9t-uKBb?6X9H?o3;(R||fI3E|l$sBMhDMDqjFbvFY(=O@ zANCQVX96rWq}z`3Pjx6ooy;p4=p6|S~X%ZLrT)Fz!OJnL>Ni1fCm`mIhVKOMIb zXq0o&@i~r2bbB*$NBfge?TZy%UZmO$uI)?aKe)9dU4-M|e{ zQs-L(s`WV9+_Zbn9$_Nw`)SKPV3Z+u!mMH3m8fTTY+R_vqM6E@iaTFLc?WCdfOa-^ z;dm``bh6K*7IO)3=hp$P;K8AAJ;=YbmLz%0 znm#Qr!YTh@!@xd?*I{}q{U2j8B$Lb8)W@J1vYetwM9m9<71{EY-pX4X+I`BjpbBcX zAcN}|nWLCZ77x`Kpm(rxme{$;e&WE6eAKG6_UpmIDGFIL3Uxe0C?~nivEYVChssYM z#%326r_9~ERZBtn;ZTSN*H(n}xahXqey~~Aj&GX6Wd3dwCD71GwJY|QInA8c;~l?d zbK#wW34`-lQ@i~2V(0v+QMTtPd_DItjtcBev7*dqf>{c}DT>~OJ=$a+5%uYQt39Fo zT~Rgr0gETDo&_CT45c5KI-Q+a3V>pYk*N*$HEpA|8q0^O;=tzDaUj{GD$`U3^!)x1$Llz2~Xx0zfDDyJ&1j z8v$74MZ-qXvvB8hPy7qqd~T$SKg%Gu7pfRkfZ0-pa|Q9>syQo{sGt@h}n(3 zANuD;Pr?+VG*qeXtB$*qnRFAbwCJnOW>Nq4p0(cxY1_;>vZr;+Rz2U2fGYQs<;4?p z#_DXPEnh--mt3Y3Fhv8@4nSMg|FrVpT__XFE9|PJS(iLlM5!s6Z!HUZEUvOIiUd|d zg8s8ufY_o=wH1o=)nzwj&x_Nx&ru|Inmh%-R@kN!uJ!guTua`>*`L7T1_N-|CFF!~ zt6%!&f1RB2X~q^Egkz;LY42)Tb0~lV2#qp!mHN9oDxL@w=hQ;4negW5G_960^-wSf z)+_f%fXHjO=ji|kj=0{kOt*iME--KE#yisCyGFzj@fquN^pBtPXydG6yxXfrQI6Gf z)nJrrt+Nf$pBZ4;t||QqeE1FUFtMVYX0AkE$GE~vfC>`es5)IHL~&&JhM|LcCFgVgIzB%S93RB!q&xNE3su`w_!9)zK4KV_}?`{`;DPs)1VRz`muvrj8P zqaL~`(&hhi@x$4hf>xfe11I|Uf9_Nm?{(PlsHAS^eMIQXqy^#{890ZRM+N8=Pu*fu zFZcP}nk?E4&i2Yr0sF!4ef_#RPMmI}2T(O#N1_X~qA+b_UNzEpf$h_@h`%3+)~U;1 zDa0pp%A)DMh5hay3(oT-ygi_+bH;Ykk5$L~()Ai8d1j9liS}5R`3Up*gB!gJrm%uVldA^!@RM|f*&s7f|Q~3>W<4wQH;z(9@}(#vStZF z>(A0?Fz9Sb`ZB-iD?UnP2|R{cDt(9TEptM$vov#cXUJ)6^%_^wxU6qWj3|f|CiBzT z5c(^1ONvI7Lh#HwXySjH67Tw|YqyZV*lWy-+W(lDoaAZ_)Zyg{>Zy?4K3WEpTjufO zFvJ<%+SoGp;w;S@gQ2#H@SrdfiJrSZKT#mO4|e~%jMkz^MfL*K-f&D)nd7wtx_2LbqZ)CQVMF?=C1Klo_W4mU}&7weu z3C^MdXhDFX`><*(tjaQ*GJ2QTS?8K^zC<25MgNhr$4~7u0Kx#RN*RfQyuW&I8dbNM`bsmwkE`^QL1+Mu%ADQ1-*bO8Bl&fZ(D+mIek7aiF!J*dip~(UIPv6%(@_e#O*ep6>Y(Z*~yPL ze%`~RHOr_@CziWhvpP=4EU_BD!9!REG0J}v+{n2h)-$8}b7Zo{EbD6m5L|ZI-1%t$ z{&JL+xBAxu0vHc~md`&jCM0T~q!ZU31HvZCgrw2l9z=Kc@IlQivbxhNFq_H3SDn$< z)P39A-iM*knC^EUy$-Zm&o)-p)l#AF{JWuoZ|59a%LwKzLT{Pti#G*r=7DFntD%HL|&xy7Mbtb6%Gk{+TT|&_} z>$sX2$N~{1L=m=$wq*X2VX@Sq?;R!Sxn?ryI^8mb>WTU$h7@Yyj^@mWD^*wgE?49Mm~=xNIm2^ z;7aLf!~oqD(9{P#AbgoYBVru_)VG5yaJ8;Q!E5mNUd{S5`@lKlD6S*xWY3s-%lqq%c#oe zeh~!l^DWrgLf~cY^)F?bbOOvsYxQiji0CK-nN`&iaP*pgrVX;!0y_n!?|cp$ zWZM0Hnv9KABL0X~jDzZt{&p9X){{)N@ywsUVZuc;64ts&%e8AlhC2*{o0!{UqhRIw z%8oaWnGq|UO<9~-r+uz|zWuq+x4*@#0|Cq59+ z7ld-R?6V8sB-C%m?X4*%e{*V*b=FABB zFD8H%^gs)jLT5f3Jy3WesUPo~!Mx2|nWtAONSoS_j~ZyB!Me7b%)f66rar_|fpHOD zIiV7)C2Jg411z=Yh@T{!!p?Yfd@DINSvPmZ>zYspT?{l`WPo{+q&tJ7R!pI3m zc&m{0h0BxJknVc*;)~(w|BJISU`~BJUbx%jzL%govhF(3(G2|R_qj1uEAMYR*OhaMR#ROan@W2}ICE1_EQ@saXhr0CDVMx zxq}ibwB~-c)ztkP=Gm{gm<~cP@VbrD3p@P4cgRleY$^`*O<}Bk^#mZocKe-|s71q1 zLmr*!?*ht2V~B9XO&SBhg0dX!ZO<3jqah@vE06axgViDgS#$2=S!+6hrJV}2GbppK zHAmZTFn+Cf7T7P;Ol;;)eSMK68^wK885G}T2+{VBtV;}-P1?i@kAp}7s)v^F-&588 zOF3yodY8WzF{+WpA8_pmYfP=K*H4DiqjTk=uLK2&Ha+M#y7R7z)l1b=Uh^6Tzv1Y=ZW4M8=yt| zag4%h1c3q~)6K2ZH+-A%b&Q=4j2(2@@tDk^px!_K;>kUfqC#+7P7e4i|2YYdaPDfIl_{;v< z*7i7QeKOZup=b_h8Sn?++W_r`aCLXY)cNf;umgx&TQc8iBj`!DoM2S@mGHNOMZ*e( z;7dp!4H6G7?6>K*;ohMPpsy*d%>t99;*T;4Rx4D~NxI-Mfy{tUzOYOy}r33ej-pcIk9D{@%s*eEr zJ10-*^rTf%2P;%@W~>6Evm7)g)e z`OYb$I>I-*r>!0|+OE_I6sc2Okvh(NdIU&b-h?t~^p=-aqez)5`3C!yQD_E?bLWMo(d z&^bA_kSz=`ic?B9J0YvzfAV>s?5AGNf+#7lbBJ}A7tbAo#fCvG2!A%RrF(4QIDgz5 zm`Me*p>}(ppud&?=LjYO#{MiFSbC9UT(iZb(HJbCoJZpOg6M`c{{|{@TknBaTk5V4 zM-|YZV*;f(Kzkk7XO2a~Dxo^n72_{Eg+_>Wu9FRdKR43OLBruwGxnn~GSOA=B^gzgYUO>;+OOp-o@uV~ ze0?cHd7Gnur&3ZQaw2XBMo*g7k9UN+kdxh~Yr|c+H$zCu5RvICQ92n)j z?x&(`3s@iK$(}YE;o4BoUWq3Aytn6gu^q9%Zfc~|0esWz3`VaY1Q#|9`?tL!YOj(| zD1^pqI_7yeAbsiLiz2YRjIe|G9a>d{MBkB*nJ~`p&w%QuE672IEX0^CekPiTPgCMB zR9WPYa7b2cT=afYU7y?^Y=(zv5>;t4{C0)F`c1h!TuY^)6Vb=WFxEOTbay<_S-K>{oO}LO zRETng-2ZdI!6|kw27JD+!1MlD*U^(<*A=GzU?$(;N4?L?jIXcy^0!)OMD~KTTo_+i zde@!0i-4Z#*zJvnz7mbR_My2^og_d?k|6n#No1;8hl zpW^IaX8E#CQ(afS_?))B;J18dZ=1?r>~GM^>ToLu1#WAMkOC%Ef79444}Re`>Bg(x z(M2KJPp&jrxm}Fo0--461r|g{Vm&|$g+(D;!de0GG9Qe4M(Zbijst6RmU|dTTML*8 zM21WS+FnJ}LrA+Fx0HrQS*x4`1dg94hdlJ>rgDo4+_f<4Zpn{yH=-I6AUuMwJSyVk zNW??!s*ep2yTiZp5~8hleHFg3WiKIUwjY|BUUW%xsI$ry*(?fKE6S8C zKNqTq>A=iM!{SD;JvPQkDsVP(fge{|!~`=|L_E$Dwu4Ac^X}0>_f&!qu>w=r=MR3_ zVJ(f=i2&70W=H!@mya^oXPNg=b0KcvrcZ7qi zf7a=Xj)V*VDg0+6kZN`6pCYbWYIz*f=2k8jBXe%f`AUOaoSp(By;%NXy&D$-+hy$6oh8qrL*U` zln7|yp>d(V0jXb5h5B!+2LJ$(DqUE$F%ET6Ag(!iIk916ETzi;lVSdBSoxi3_#cJ$ zwk&dr#JNPuPu5KGZ!o~y1?i;Wz88vUC<9IGo+vBxMrzjKs^ufkR*45V2(SE(r$6mu;>pBfoKkUbhxhq;-3l zes^6_1%zx`g->Y4;a8bFEnkW7M=C+zEqJq?y?|vLJQX}mk@yqx znJtljguIsJg0XSG_R;96E)O<_f68z6-HG>O>o&fPNAz{SOfa%V2@olYC#DGHeE)O&>32^?dDF+lSA3>BA8U^G8~mrLf_N*Ci@cJ7JFW{>ia49I^7^f!bjeNF$X|Sr?(9YbJI8+|MH`^;u8Bu^Z^EwM z;{M83d*>kxu4M(x){TFF+CNRt65^CEeU`O&Qjl5`$MLzRYA=XAYibDF;)*kGPB8E7 zaoR`%%OSwVklDyr!s)c+^S{wyeryG2U>akYU{PjNbfLBFFXPMegrnNbs2w_Jrygk| z*JVR9?65!Bbdixt({lKGSs;Wu!=Dr~^IfBQW$^62x7fkl5@&@*52}EE%5HeHtuijC z1Nd}}ng zNDMPCx-nL;^c6Cca|=U6;Emgo07jaoMKI7KP#~WxPy11Pwim{sBS-m>+(%oVv^p78 zr{t|msD$YhPgLDF(xH5|3>B8cYBceK#0W2uWVw!Tt7Qgi%v2$6rg%L(APMfEjk^t8 zwspdX`%$&6T+gU9Q|zTu?}mzRM^Yrn-r}-mr?Y#67+xH-P~P^~{@3>igEamVo1s_3 zbq6)zq8`wcpkSlOOS`74aDZTFv>K;IZc$q7OO)A3-{9#Tv6z=V2@?POL-eFL%t4)M zyIMFtirMJdQG11a{bI}DS%3$*R?I;cg-yQMO%KS}{@FjhZA1AkuRT_A# zwsRXYsuBR=e)}c1R^R51mkXg8B^?oh36GGqz-9VKqp@Z(|9L;DLn|37SkU^-)|qAs z-P}Qpp;R26{Q`pwo0O3G-qSijx^3r`*P{wVxgbfGyJB9xUuF8_LFs zxBJro4TYCFUTqnrvkfA0uaZGGf_^RA(~ps5ca*pM6*D^uUFC{gGpUOouxBYSA0^B4 z86Gr#TfP-Qiva%0--EhqSXA~* z^nVEvh`1>sEMYN}dLeU2mic;3b^G#x^*3K<2@ZDH0U_v zYFl*7F0;!~ytv4JV~V?%5EJ^WIBUsRxRx4kNDTTUD>+_10C>%5TeOh*8*d63N$5WSBfwfr1fq<8JAPX|hiq3h4YQ!~<*pfv#_hq;W%~g3eVro({y5u_B zpR`V^xWcK`04zpO7xPk1y4|~I{f+n6tK=s{e#gNFMdvw8X(PuhDUuH}Rz{Ck!>9h? zbtuK74FTB~4bHSJ*cpm?qeZo-if74BgO=~SLI9++<;xc^;en;uX8?i=R9N2g-84L% zOF$S1HctgZl}>dY55D@D@1Cq2P%j{&1gPVDxYGjEGciQAzqx+x#}Gp3xOi=>3v_e` zzOqr{kXL~C2$7NDX69RyM?9ffG-6)fp3FpoNT-Qtj80>v{hcnfj_X6dv;*Z>vA}p9 z`#vyX0AwvwGes2(4Fp^rZ)^$k%#Gs9^Lz6FtNwBApN(r1btN6FSUv_yJecPq^}M5M zMFKo!IPs4%;zE<)+doXK*nhRPWC*Tt%w4|KVZlkHMc*$^wd-5*g!^?)dRMzreSqc4 zrNJFP8MH_J{cfJ?yDb0aLKnU?mFFBQP2VG)Poo|$=eZ)dy_N`&XFQPSQxq+w5IQ#L zLu(8)D`Hrj7gG|S?a7XVSm&(!E3c3b#hTKgnzs!-2Z$gkY^B>|NT&#Fld#b+%oKl5 z5`Ue7atI>(&9@v&f+MQv-TeZ8TH(OBwj9I2Hw6M7C+&A%)=m*uQT|au2CQWdz z44+t4>Oo18~v970? z{kBcMJn6Mfb$FWl5niUzcy9cBw>Wk(IO^51J{>%if6~mdr$cSn7yU*j*aNSJu z2Mj5SmfB{XQ~snNoF*fVm)G173i_6R(LyTnI%wn4x|Q0pK=q#Xj9AgFUw;ocsk~Cs zhl!H_$(P^ihkKD6()sf2u3l+RSd~TwVcA-MGx{d{)jpmzlxLEQPLuoQ0~`v${fX9P z11c?jvnF^{PJ@YwqfcAWLm=e(WSxP4JxfxzyjuMm{wW?@G+cdVN84jkywHUE|9CnR ze<;8A|J(N^vW_iVma)bZLYC~=h3uq~iN-#%WF1?|u2dLgHz;aiFbts*5`)6nBC;o2 z_?>xwzK`Euz&-c5&$-U)dOcs)$KQ7sh&h{nBaM5lB|473#ObbE0^9!L)xF;8_$vFR z1F0^f3jw3uT17Qv-5Ll=Iobm(={P@oI@exxN0*LLy@yPGJSX_;^@DLq>a_9mVLp?C zofo0vdMp=ybg%=JX~Mb_KnH#nYRDURZXx70e5dtpsLOnjCv?sj-Kxpn2#CB6Df>o-_VXLU@k0k3XHU4}Rx0jzYQxUWI z@Zh|)ks&gSv0c6dw+{HkXvR)GAM>JZra73eMU3+49bMMmGN!SqLz2}alaRR(meAIc za#w3;l8vL(e--5oht7BUZ>)NBYpqYNCLQL72DjJa@%ay2{!Jo~*e+g5MSphYnU&$) zDo)n>F95gl>1j@9WIbO?`A7r*!#MY%bT)V-`KDm?!JANd%2@DWL}>S8{6#-25&%h>pCY3+~u1z5SKetOIf_O!?2dw8smD z;GD_^R2#|c(UGgyuZ06+7!4>Ck$9N=_SV8g)aLfU-C1{5D&m_nl@Id7mLG^l_SWp( zrFOEfwt6r{=chtT;J#s3g$gsE-r%HOYGN8|WpYH##n`I_vnF=gQ<1pMDm&@%>*c(W z0kIgZ^nWFqpy2q!5nr%$yQxjyU`Fc7b6%*drHst(_=tM5bGO!L#d`csr=6sr75`>a0^^<_U>+-32|pUqT;@^_WH|560nK1 z>aX7wx<1fw_+Lw$Z{J?THg&kkiO%^6-K4(^Pz^mzcMi{i=LS?CFuTX38$74!hRn+t zx9+bj+(8Oj{CxJH5x@9@9y4SDi)`b%sP%-Jd_va@GPJbwjd9RIzcHA?G(WKb13+yl z6X?--wwrebKaUF!3+-IFXtdvweJ*mVj*l%Z139&LZVa1$ZvbaC?0B$dTlbZ56u-IIX36QI#$y}>Nd>A3p`QAFc)YbU;Tpa&7&(hN)&e{`g&MMq+G9uG%^aV zLsYrqLQSVM&?D!QZu;wu2b}aD+@n&C4^DJInbbK30$1ryzoiC|-xnIq@+*j;hu!N7yq%A znh_~!r}Bu_HE1}d<_7ZX?mve6$VB*pJB^k0-NZ6k`ovpz(7;Q0lA4oYKh&a;x)ltRpI*! z>M$TlULQ=C4%ZW&9yxjnb$;l3>WGTHze{c?qb^whYal=&^$khb4Jd$0V|+iw*2>VM zX1xOJPHC`NbWY^MV1MjoW<$sstYL6c5;Ss(yWfY;vbK{N*OVUK0JT6nJ*Q;F@yE|hf-JRT z(7b#c4=XYA+lKM5xp(buO@7c+%c)>njx(Qh$M0L{&p>aDD2Rd-@~s|-a3i~v5jAFN zmdUNEiGMprfd`ALRl8|I4GNNA2hmjMpzg{b?TAD77|VSlk?Fhn<3q5|lsL{rjCCRC zHVk{O($Mzes0u?M?Q5<>OhPbIVWmoBnf@`DQ9Yga21XbR09_lQ`iIG*N`Lb0mwK6K zrqwRoz7Ngj9wU3{B3Jc@71d8KHoG#Wl5ZN8j5^t(XKS>5+>49bbJ(lpc|Yey0thtX zv<>cR5(6D5KZOgCdqjV8S;@`cQ!R)Hb|0Vr)GNKw_%d0UQYAq~^u9N+yR_O?494Ya z)5gzUs;mk0Xs?cm&}0Ny-a2y2nB3C};6oVD)Zg}Obv2@JpT#e_j^W>w#fBTR8JG#D zejJRgzQR6ri*c{X%y`O*CGnq7=HJ$R--V4-diT5lroT66U20^Jmqs_&l%yv-$Dgo^ zS^lD?%Y6cBlUY6Dkt|DO_0rq#yOLkDc}-f>7%q%c_j&IvA-~bD{zpqt9lNh0anvsH z;ZY4)$vG6xq8vE4qg2ha!l|jGyd3MTz%H>zsmDeZD^H(MJ>0{xJ`N*$5+*rf2 z6B}PYOz)&pxtN#BsTRB@5pQ+&|D$OB!~jh%UjCdI?m`9R z^tsbK3Wo^+t6wqV>T4+kkc~j z2sq4_phH$2GSM(}MaTc(EJ}MKdH|sp;}}2Bs%R0IE=^i|&Pa`s8US)*^3doDVc>&t zS1h4$;0q4V<5Roiv#e+aShw`ZLH^}>Q+7s}SGijpI?eQpKW|YPlqZ2P7Bg&ImB;cW zTvAg&cPN$0nf@z=ugYOUpS8NEU})>DX1iTHdqR|W3ei8R;csrPCQ>B63R%v+es?r^ z+v6LkN`TWh9;TlanyLQYhUJDCTdMCDJo23yMmdXuI9%Zb4sPq?u3)d3bDA_RFFK)I z?S@``s@NafoG*|Dv6zUhSSS}xws~UcfH3>gA`7lNqIHiNU{x*S{(F3y}-tp(YPd#@77!N;k2FT_1JL^*BkJRwFwM}NV z0&c@Liozfn0KgfzkM}C=I`jmv4fUBtXAY2o2_HormQ$HrEWIckuIG)vL99>syJmiU^f-Tddddj=59 z=I*)IE~Rss!s&`r%O_UporAk`KQ<1}>of#h)2-P^6B*dhtd)K7d$SCf%GaP!4Q=~w zF0bTf0`aJ4usSEju<#n)#@+W9bCe$Q=zm4<*f}fwP78E9y#%am!cBlT6yKao*{&!{ z;W&%^i%Bq%g4LPi2& zp!Q$6Lk7)?t@IZJ+@b~r&Wxv0x|kJE>!oWoexRZzT$dpeY&N;nEu|!n(M|h=Cb+cT zcCKj+`YG7A_Hc$1gb!mT>Mxj0k(a&!^C&m%YovtRY!y-WIU4eco!{;X480rD-+AO( zWQ&~%`JBKP<^B(Jz(0=lf?}ZUXWL;SKUi>}>3nf<1`2!zR;QC+;&>0-M6*TbCu}-3 zMH64|QI(miD?K(PMc_}zRVguczSHobe_zt7dFi&bKGS27L>8mR%ZS&;_-5!>wfW2joidTdp;)6aWb3sVa0uP|YxT4DyK1x#tz#ba=t%y0q z5}chf0UKdJaR=YnERBB{ZR{rv-A?6-n27Xg%jT{-&k36-h228C_^FMrC4ZlBuigLj z7q(rLVkiE!(Bc?=d16F^PVZ4QuOV5)*)uaQ@X70s7I`-R5VXpm)LKvJt6}s7a9YHS zLtr&v?*U-4f7^}z@mrl4&ARS|RAE@FG zC9AHI&qEXS@*QszZqm7vO##R6nSgt)_UB6p?z?Ux-$0of`^B=qo_)K9e~jF&1;*8d zh~&?W0z?$&N}8OHa{i9z^9oXgvDDv(*%S_6_nKDr*qXD6g8ulBq?=zQ{}$#yy-TcQ zo79;DpCAC`H329;ddfEWQ24EL(|)UK>s<$yPSpJZDMY~3&Vvs-F|Yf8Fah4;G83iZ z9uD%;nTyMu*UB-FXZr&)a6)eZOPlmomSi4sio;sGt(T37USG6H3!h57B;#aXShG5#0Ir&;>1*m{ny<(t|FeTG0mo zK9w!7=YX;o!w)%x+5qpQ73nf{NSJ5$k*jq&NM4X5TSpP>i2-{@22(y2d8C%KpoKs|*z& zxDszUe(13pAp)M8c4|Z;b))`^C3j_npZJWs_t$sYYU0$R1=OJ0`C!fX_S@(#U(w?Cbt{(|0) zfa$)lB)S|>UrjU4LL$&Ufdms1tlAihc=bXOz<)Sj&*xqxF>%9lYToGBUWrw>Lcbb9 z>$0c%Z$!b(D_srb%(Q#0hroLB;hIa0^Sg1>2zj45eO~uXrs(woTm5MS<@>yjbN4^S zpH$~?!><~@@2-O|(bRiJUv|qIKIbE!6l<@BFo;)ZPa%fRg%Gm%G!DKdLB4e$8ejxV z%JrdKpHU^+A=v(ZfhQmxLagP-O#p%ZpR?t}<}#OgZm z!-*cGh7xL4QYZ)NaY>!f!qLq%<4d@1jAtacZ@px{e)Tqjg;V}Nq5jA!HMTy4pVFCr zQEn9c2zos#U;x1R=7O*hEyjg4^$b{1e25|4jJU?H(}#=*$+7P7wq2w4B+v*E6}lXT zWFa=0$(4%ok|5^th&7Ac^B}~4-NWTH9$mxtSG1sL7$M6RLwgoeAjyM06uGpKPRcQB z&}&y$M$_?RJJmCV$Y{BxRpq_d6m0{{e>osMQ{nK zq{i=dvYx*fJhhY&yp;=2_E6E37-RUpv3;evc+FhqQ2TIiBkYyfFHXkx|L+yZ)GGKx z#KFO2%7mX`ZhxYy)OjMDQYL#G({Ya@kNYM3aF=Br%U>1K@0^2wiT!&U?W4y+`Xqn5@H;euhJBoJ#i;dkGtgtW* z=H%*XB4f?MbIz9e(LFiSuI3DhWv0hbF0|LdaRCiFS2K`UUcYQLVAYh0c5HPG^KN)# z(_kq>ax0s4W!JOcPo{Ns7BhzJPj5Xqb3@$y#5n12DKr=--;1x%SdVaZzuLYiS&Rbp z8Ouswzv9ba9xprXOU1Kw%&tW>7a&byGlMd^17^%0jR$fcRqC<8Kry3~zoXl{q!%S4 z^5uFWDZ&ZdnAu%Gi9URSW(iqf?c$=~b>E+RJpoYD@6a+E6(BGnKvw-$Smc5yc(;!>i8V9>z;vW%hhlFA{H&7VXb_2 z+82vwUomTK)VxoDwQtu7Mw@AFL4XIga1cheg@S(7FI>fuR$YaY{mx0FAm}$+u=p5M zv%$#b9@_VmMuso!%p$ZZ!$m%mSL_D$q4CKL2EV41x%iJVL|^-b_~+RI&)NmJEKQ3V1@E0r&dXb-o6)?Aq&X^g zGr?KtRgiLIO$bh-y8ci&{7VNKT&5UZeJ3K;=gG*_gg=Z7KD|bRotuiS)de;R&|);H23UBD zyci;2Vhb{>9Epaq#(>)d`MOm7kmlBbB1_Z-Y%h(^f>b=dnNI*q2Rb)T3^WTq8(=zV zu|MMp+*qFO8omelFko{Xa?L8nhw&u7x`Y0u_%kQ;8Ru{xyFop~$xvFYJZDo5Y^-Gy zBu3Az1xTZff~dWItWkEU11o=y*0-+HZ>fJT-QwG~D|(O^*#~l#ig(V|e3Jaz`KRdP z5}j(>4zO;`F!&g}<`1RY9h5*z61bawn*~a14C>oFWCOYm(0NAYiqa_@{@B$3H%ztr zQ&7)x0ThYWB>#Dul{jT?WDAAE^6Y}C`9;;#qGD++`c)Y1k3CgfH-w%OV>F;_tKhcT zLyylwwAO6gpr+buqxS@HB>`2usE5MzEt+N!wexo?C$|HpPcBvBX_xDbJzMw%aAM`| zk;QPuUnL%ZtQ2s-x9Jexee6!EGv3TK?or~ut`9T;Hazi*HgdEBQG672o%{*`HSI1Q zZ$G#MQN@L#|H+upJSJ$>9TG$TL}JdT@EC3SMlb1)2HB`coORt1V|nLPI3-u1d>_?D6uHDa#w<89ZD?5p@q`HXKwNOEq#Mi zI=^GuasTSSols7n#D7cE{T^MrF#?DHx(2J_2Xa}%8D^shUTh(Xl2>HYiL1(uPgi`y z^&9?Tbwbm5-h*`&tLDXxc!!+Q{`2VFF47ViQHx;0{`5hH>B7y={_EqwT~xD>?SY6r zV-W{X0%gOt5onwSm+r+E(bg+!`l2Fr0S(bsbnFwoYOtts9PRp3`Jg8YQ?NG)OsSD_ zQs*Qq0~d_uoq1co>vAey=p<_Fm2-kRCv|mDZ!C-YC`(h`othD`CiQi=|ecH!rKQg-}VZtVUy=J)t~k48H3&5G&M7c}+)eQ>4WiT#TQq7Iua`kflpF+qm3 zpx-!C4UAnNtU*3D$BZG^@4WKXB&VB-T*_-eA!X?9o;~X{lT#e#ATDBp*-{5#d3+QX z_hB($SbkQqq;d7Ipb!YmJIcNXA~GUr&nhl) zv4Vi6p4=sJK+}{h%{=QfM5!mDRyDR~GQZ0SO+O7ZAG->kL+tI00MOHwZtZbl}>D z%soY>WIPD(O0wJzxfTNtqoR9zyYkXMw(@PkYrHZ*UKgV#>ahSt!s8%s|UL_5t- zRWk$8Lk+;XW@-PGTl{(Y6In@f)q;I1gZh^pBeA!U&=dcBzLLOFsFQl%(S@ zc?~3+P~8_?{^uAAlxLc(EJu}l(MysQ>=vL!8f3sW&kDvu&ZDDk|f=GL88}2*e$}V6Je*F4*a*J#v|AHqh>t| zAdz$fW=(6cado#=J+MpiJTkGuRqQG2RFE&<{l0Veu`%ETwR*b%TFGi+cBUKhEbza~wm3LU!JFr=kd?5f~gxjJIT-a5nWr1FT;Io_RW z`FO!-M?lfH@R{|Y<5~W3il0smslfWZQ-sliPANo)* z7HTJcpZJgA)j`Kl2+zhVSB}_Kv>HkB!Q5_+6vFQ+B}QGoqhK~taM|gMBH;92!}R|r ze~1o-Kqh17o(_T6OHh6l7op2K^BR>XuYl*~!0CCKiL>B9F74#PGo)YO_}ZlDZ$x03 zfZOk51(nI^oOSquel{lK3VS5R=%_VtzsMPkT1?9_V!1R9nq`^pIwcl>BypOKNcnjz zUA$U^FElLt#-aijga#TzzUYmCT$J}475Pya6hvLp3J4C%+tUWt#0U~oBF1?*25LI6 z8M?wIB~r;}7*{_#&kT|dUpbsGJUdo=st6^$WT3<(X~v}8nHyF78O=+-zY_74k49n5 zvu`ddaLc^yDwl5qsRyqPF#eCq$Lu}V)rVa3gkuzTG6df$OM-$oRO(*hOKN;`7d3uN zRk<6&A)5r3!Oj3K_^H^-f1Xuz&@t(UmHKNc0va>d4Rd^hA6Dv3F$;VYfm?%Zs$U;= z*^7!dR>8XbfA}2`5WdlmP~m`Fjs|H%kq?FEL2g6bdPj`rhI_)J)T*F~NCgQdSQ{B4(6K_kl& z7|$Z!t)?KoSb4CKxTPOZYvytrhOz_m&S`3^?mlUyy?eA1rx7&C6~hBULx{a))LV^fFIba;BC58{*yF z;apDTFcPHrUuITrddye=1!kv31u-?$8D%?o7MF!3_FP(ne7QzqGRNIZ-6-B$D7pKV zDymh6*MVe87o)|Y^dbftNkcUrmmJ87dDogZ(fuhnThIDH9o)e@u;;(iV;F|G8N1Z< ziB58xbMNPyJHZ5vvL?8=`6E;-saam9cB?xX#cN@wr7T1P7V)l9=eJeHiJdvWbCDm5 zLB2(l`!S9G*T{~VV|{*Lu^&7OO~ATd zQ7)b1KRD31h!3&Y<&~pW6?ABB?1YNNB(4YldLK`&-F;Pm&|+FXQ<3Em;KfrCh>oA< zj4y8v4E7r>-O#o52Bt3sq@-=-@Lm~5Y={W%jc5i;;BTg4u)Kt|)L_7i5!D>O1CUe{ zTOz~$Q&jy2^Jhx6w4BiJL82J81F54eiTub;>^SD0zt|+5}2D7s8P{WtL;+4VpCK>t`=fq7x710kSR0^w2 zEErnu>bG(}5w@tweEaR4kQXtlwQ~=Zf@M8c>^n6oQ9A{B0>M+M*^#WTF79q8B*QN7 zVxtq$mZ&Tlao?XWeQwlW-LSa1kctMmizP%>aY~0W^^9Nx%7$=`bd;FP!qg6noH&yY zeX3|(zd=BcdgUZDNXjrw#5}!DNPwfLYEk{z`P_Ty|1AEML90iVI1!0Y98-9!_)>$v zjXwgrz@KQ*yAB$k$@co_S{)K=gy6HtqVoGuL%=z5=%rox)}>PMC!w*VuhI@W67xwL zYIK0298in|Hk~wZmj)3EfF1lDQ=?C*pG5V+Lh`eg?6|@OgxeEal?7*YuK8%*d_sTN z1wrhCTbqyIvoD9x_a+l24K7V?5U*Oa?spMyMhB*!AW1!x_(S1dN{l{|M6W_E*MbQDi>{XJcwNFmB1@oM(ahZsFjuvHfd^y_;RFe`(w;TuDc&+)gM z=w|daN>5)tQ9<0OxFvmKv}EfU{glYxCs_8#8Yz6pi&!{2t|h18&v1kL7?4z)BYjcB zvPmYDkU|eoqHQFwajWpq*qaVDyC$_KnWsp(J+Z0CxI*Eg0$6JSA?)1Uh3o*$aNf5( z`Z4gUox%oek7uj7K8{6lIlPDm!ZAnz=`0YAYBaj);zb_>uvuwRJ^Q)R3k^B2J4p6|EsqK_3K2V* zdLoWk8>5GdOx`Hs`9H*CoCRY5zvjkl4iauEkuNmf%nBn0x+xXfO&l&fkqRGpd{(5aAEGu5pg z-D;!)d>4pf&D!WtwQS~kxnyk@!E<=o00Gh;-)cW)#NT?3whEX@eoF)=xD9V}yIIVt z8kIw*%iw-fXn67>7Qd)t|N9p8i3!)9prqkm$^PueH_!XUR z_@ls6b8~XxhT@L}(Qo6N9PMnzuy4a7^*$K}-4G)xH!?#4C_Frraqlf?pp>38zm#yg z+g`CaWvv_3MiD;Ufp__Gd3K@Le>nZiz~nMOn$)PqZ?0DnbwJxwDrt803?lK1oCw88 zcRl1wPy-|txEH|fyHrTp5X2FKt|!>Q6N6CNWzU~L#~c^K)xymex}j5L5FntIPBch- zlvmU}axJ_4)TYt!zgAJ+*-cK-;gtiM_z&;=OG+&EBFH=S2MKA+W#$_}Y%idxXO9aq z*YV9Y;q00L=#3zG;O(Ns%oiXMEoz%;vZpozU4{X(!%b6NaM#e6R_ne<5 zJ;7KR$G&{_bT12ozx6V&v(32l!FSF8%QOn2355b1>DG!(*F~^Z%NlK_N)h?y?y5ez zsITDzSK-3`>F6BNZv;x2ApX-Ow9zO|XaJtOJk8e415fr*T@V{1vA6*DI%nGqH=FZL z7y6Ty0EqBIgHI@Kozq!GPVO>&ODRR3r@Ceu%bn#p`Ekej%52N)0~zos1k@xcJ4_AW z#SePZD)b6}hrJ30`_|C*bP|ZHzFOP)tI%EuV0<7mGyV77S6lnSUmFIjLBCQT+&zB= zYJ)hj?Xc|f|DH&_{%TK@xRZOX7YW{0e3k{+SsAfvWv&sB1Gv~m7-KX4ZA}EwEtRKq zH&f|7&T8aX@Xxv<(0-*FZyoi$ms4pya4~7n$N__vncS;YhBOQS>ed9W$(63Wf`ObV z=I}FST`mTGu`Al)Q47cn`&Ynlk>Guubt6rVXsi)al}PDWGGss@=RZKM$ltO{E+09W z;bl#$M|a6Rp%;}%j1gmarP+7jV=|)!|9<6|;81*c!+4A`YPdlK0t%~5j2VzkZaModR4-uC4(_uQ2|D{tFn@ZTOR+@i^6b8 zxJBS$by}J!=iP#U(y${K*2YPxAiQ}CD@!|dgTf?4A+;v37)19(6so(ZJPOj8fL@HO z6H!LK5)WQO{Mg`}NAb=$yDj9q0wp8}Btw25-fE2d#zIitFyGLujMiO=|Ah&^^g|}D zR-L}Oof+WAz&V}S@m!ToVdFylVXsASTRmsa|Hv}QQxO)w)Z@GC2htQcxnof1sLBNc z>#vJfnVS>@8;paZT4983erAZn$DuYMozwWA%ZB=y>{3Zoj&`JiSxQ$GO@HJ-`Atd%M(fb3j0cCva<{<3i z4k_@n%--K7PFi_@R&irXbe>k3F|JY&CRxs6__x&xG=ueGRtx^lU=$?SsB`wn z^^@RUOG4$si1JpdgUSz16HFuF6nUXS{G-=e=vEaZ%RSP%lgz4sp09<=B)Q6WErMEu zW*cBkz<&y+rG0)C$u;^S_NOnUOHJz8s_-icDbJ1UKrq>CI#m|!W@ z%a8d6r9*DfVKxU#JBh4Jle&ydW?$yw=I;ZMjeR3bKB$s+TdOdV0{;{cf`Zu?)OSA0BxIf2TbK5xjpr;lxhEoD};`&|wjtXGc zdx94*I@8ogyy6GOqFo0K{LsME6%_7x!O>OGkx7@0wvK=4Z&Cs$+O_+aNGv1ZAqJfhCNU5mG>09 zMFpb71Qxhi%c;8#Ts$QmMOjCpA&_iQ`bu^-5&{skMS7diV8b zG%;yU9OqNHKy#K(Ib= zKUoTynd;ef*I_Y;x?uVNXkTlHt8Pbujso!hoH*E%L*(m&Ak50ZZ3?Pn-LD8Xa`k_Y zL)1`%IzPxQrCMHPawexjLP!cvHeTj|L`G*7L2nYS+#C#lFq{jqiG@NU8LRjoZxC7F zKV5xX>-7dL^ykhK7)YaF!RyPh1evvhpOh|fk5HhiyQ512c3Q+1$mV*eEHU~X zxc0!-o8V^`z8}r&(1;?HK`ANboi1J59rh-}CSQA{^lNpCp|QsbtiZN34Bo=D;>k@$ zCu;ZAp@T+2U~7x&i{i zF0f+tq$W1OgW$UH{S~+ShJBD?F>pIx5u8^XU)a9v^NVQz{`kK~u;r*BKCLaz;;bh$ zE)i#;zf8M*`kXPHBJDP;F0Ej?*cUx6heaKmm&_mp=Y@*uo#k!A?>nIVyp>fSBK#}= zX;SuC+6E+#zP0K$6-c}3%2E^?GoC)i{Es6$)}H{m5o{-C{|mQo4*}V{u|CryH^SjAkONy|)VY zTD>IQ-+{YIi_A$ex5{y9R%AK|$94GZc*apdch5cwyckk9je_Yt)X7jj`z|v zvwt+DF~=mXWoEeNfiwjW{-rj2{9d*Wjsgxk@+l9p-pPAeMK z;^YGVIDEV}H%S!wdr-U4ZrkOng7PB7YkHkipuHR9HVU)|XXcn0lhNbAQbj<7Q3J>R zNuwaB?7hIhAApfQx1siAZt@M-w+PLcgeU+0y^=>v+*zpnp^BdOGca8xFDibl7;An` zjrsntw|y-~dFB&Z_hDJoyFbs0fB=U{kVQ?#Q}9SGGSSx;gx|3e7wNsdpFxc<_nk@OuvR@OB&bSUC=CR?&?rnuD_b!2;x<^Zvc4j8R;+R$Z|0U^&yI zK%#W52J3E5q?!X4O%vcBYez2Z+pGFSTgL&({O-;NCQz2pDu{CH$6j_TF9c2Ov;n2A z!u&D!jQ5NVytIR^uEBt+akpNC{0PIDo@cFe-!2Jy^Z5Jh0us+n-y){_)F+VD4MrG$ z*ZN}w*a7b?xAeF9_x<4#oe82dSX}bJiKel*L4Wuo!wsza;rnZ00q?&zXPygYOsrp% zwkHU!CuM_KBPD_sY%@EcAxDF!5wXBT-7)}H)SQhlGK=^>rx+-=q}-nb)78mye?Dtt zEbv8lGMMdcIDp#zcbZ(T47cPZv&C64Y4;~3gL`XiJJ-WpXDQw2V^&)~(_vhfTLh@F zh5%<_GH><5I~+XXPlvu*PNjGAls!nsgFzs`D;Tmhy;WcmXQ9m$+(UyAujE_5&U)X< zN_9zeFdW<)slZSo#9&q81WRJ&0(+#lnB|2U)boIoH&^RWDFrOzW32kRX86ZM@n-B^ zD+AJ?V`leS8tRfl@Iwo2BzTtJcc*LI`1<1=G~m-=b`1ml#lN+m%(Z}p#zojmW>Egh zO@2Wj4E5V@$KhRVtuPoP;$?S2&2@?Ao?QDELZF^P4C`T2q=uOgTXw$zMoP>ON89bb z|9vXEFR00%%7lONeH9=&Eiy3j&UB|SBL^hT;>3W>ovIwpb-9X4@v)))lmVmn$&R#~ z7BkoYYQNspeQi26kO`djk4hS7nMC9Kk>i z#sR=$fr}TIY+%CS1=>nR$54TZ5!0Rdp1-tApp5A&2*SI_#K2v3qeH=x6AWUq^Dh|M ze!b8~hJ!N`RvQMaSh77Ib$=SKN_Zc(7oD&0*PoYCf#Vefg!{g-HQeX@;q$%HaKl3U zAt@CmSo|qFwG4WD?v)mU3o+b+Y1VAYmBGYHeDDuXr#4!H#VzuzB4{ZJ(lvyDiZd;o zV3uqV?fhaPZAZS|Zi0mo*<;@NPq7YsB5^16%_UmiAz;=9K|qSE@e%AH@p)iS$6C5x z-{nB`N(aU2qeuU0%apc2@w!m|0~{}kbLH%xYt*(v;G)?I40#BF*@vT zQeq_Fi>wZ}teUxtK_~2MfeUcIa@O!Op%e#Z+c3M*A%teG&U{ChKF4DzW>cJSs`o{S zAxR`4&Vf(xG4LxfUe6{ETKF$I@zDY~@{JzE90MH%C@LR?f#GvXbhk5@mMrKMk_zpC z3)pkT9-6bMqAXc!aO0UrSg7f-!o~8~N%T+S|a}C(#)tQz# zOR_dtCN^3^t;9h>B^6?d`;C9);!9-iHHekglFsS_?!(XmHY#G)6A^E7rte#(j@8Pa zv~~k6?|QV=CH$(^WN_K;+vH|#(HoI({ETubgAi|lCcBO>HpXS=6d1B&A_`O3oVP-8 zU9TWe#&u*$6d_IV-YX_t=$rtnnJ~jO5Gf(B9jkcZ2yy^olyH0KQ@E>(j3K#e-1Zv% zuPRT|@l{auZVUm)%Z~uRd@9+xDGRhyL|ICQEr2#+?_d2n4P`7T_ z;J?+y9ouY16Vt&wDRIE~QRF{`5r(SKI`0kp%P3E1c{So-1bsYrA;LVF!PQo?7^?g7 zpD@BT+lWv0!CZ)zK?-lukt?{caOD>27w)JA^MaU&YH=wyD0oH6yIatJYbdywkmYnT zwY%4OR~edm;6uACR=IGH3^N8L2)I_5F>7e&d6Jx`M2A)mT;j>xM@EFx-IqS$Z|#&= zc+m|js$8JB_sh5neHoip$9}=*!Mgs;Qp-*H8=xw_jIj2^bNkuk1~>P-pXHX^nk1_) zV>-4WdSo@v@M?_W7t$-%)`_0`9W_8}MdjKw-QS-r3VL%Ij&qu&pV>B4wX#XL zpk;{HDen?FQelrSfdKi)y}QQnAkP+qMiMt8pz!mDgzB65F1vZb7ka1^(U)+X4gBk| z_I8bQ04)_x&Irvs#w2t@$S~nUOgEmW0iuxs;_?KPVaJ7IKw`No18yl97hlAOyXb+o zhVUMWXVZh{hm0pVUznJNk3p^fr6Nl`cFr4_s1SkY&R$4r0l{3-S*C>C*z>PdW zoSO#p#Pafe0TD-67a_xJ=XYr9)5Vn_{wY4HkEBKz)L;L8Z%KG# zL3sDd;$BA@-eJ3QHH9r?@ONdj?|F8syKX|ka?)f?4Yx=I6l2na4f$eUR4rxL)FyK| zZ?rR;#sx$S0}<)bKdnv?tPQK%8r37z8k6)7^@cmLh!C43N|5}+2!k-$_Ze038&W9l zNYYAAb)Y??X>CJ!e(Ew|tj}u%n@do*=m9w@sl$B44?-IE_^6if2U1G%|z5&Dc9`UU@7UyTrdH9|1gC9l1^ z)!R(Wv-eVdQTHMl)oBEX!Yhbr(Rky!%%5eg+&V7GCmeqOAYrSTT+Ll1_50cm*mY zl4Bkiq#y=9{iv59vXCYI0@9y<2x}h)roeSR_lc%*p}~UbjyaGK#Qkay_YyXUgo+3@ zr*rmMU`lT2T9;kZV0bEw3zJRjQt0_ot%@i;m=dP+j5;O}Oa|hlY^nh1q zG?|?P*J%N54e&+WgaN~`T9>erm&F;J3q18v?L^rsvHyK_!uo5PylB`8kLGgt+LeY= z{TMJWh7!~LHLCZu;MfGAK3<9io72Tv?_K6f71qXu5gcE9#_Y0w4)H!|@2tWlV6lPD zJ?14Yz~v^lyoEmVawm~(9w@n-3l+uo$5gj&Dg1tCcNEf%+=OM49)nSC^Zkt=3La6# z=a%lNf)k#-`8pKmzy7eD-X*O-Yk3>I^BW!>BDP@0&lAn1nIX5F-=}+m)hO-8zqoE= zU{fk{GYU`*=f%ApKP-kD(0grsUsrquk(mIXT}ig&6#Flz{>cj#X8o zA*P26&+=Y_!IxJr7yeGtoo}E4VH&xmY=C&axw+~&OhpNX$ z%gvvpr2vrKfs_;*V@Rr}p_J2{)lf|X)-xY4oj@Oi`9JmV6PwvcMQ809n6=rf3tK&= zaa{#EtbmDC|NTI_{@xg+jq}udvaH{mG<{2YxZ6W}0W|TxEaASb(6^7h#_xrbXgbv|-dGfvmruZ31Z~&QlV3N73SjW8o^O9nJdDK!Cf7|_4#Fq1)B-j6~;;kPe zE%gb0+9#_dMj8x&$J+JMOV7Y*;3z3ptmZHtYP}Cxtjz3?;=(n_A^2}n6W8}cZu|$k z94WHA>}iB;XN#>Y5YEOgX(;aZF9@zuqR@di%999+FF?IYP^VBGjV1E@1blhwG0hQf*#h!I!hA68^okJ zmn?#ftWjdgrBqv;Y(C(clW?n|s{eaDXc^embNLrA&)@_k*EoTPm=bgTEHGKv-qAHW zWig-Ne|lJkV5@mQ%93ab69dg}PQ^VMBT`FOz&o=_$N2*65%9G@nS#UfRT0-J$u--z zhr-t^IcmeWH{~wiRJX0saLLZp*%mwp!MpF~;HNhjRFE$1_p%qXbwlr^%=p^>%A)qX z8yApRv1i-v`>J30&H3MxLcyT2jmJ!1uAlrm>8Hjdr{wD_Yfz=*x}J67M|C@+jCw6t z#^+v!PI3Q25w(O|;*_;uMbJ^9e-<*DY^(fY!A<#3Hx=eNfUR#R zxJ`z5yn`Bo$pl`kt4dc$pp<(3Bl8X9;Bd#|5JWPU-2|n#iE*p_%`#UYJ*POT{K0_m zPMc0``6Nlfrjm3W@+l2A&=<^1$VqiTi(yXkeN zr1~S4A5hibDolpj+ati!F9u3@H{zW1 zLgH^EIGAs+kp%{xi30RV0T;OL_4y7GG-^pNLmA)l2b#Ag;E4|a$HL$S#uGihL0da7 zS{&j)fk?5tq)HD*f%EZ4O*KeQU<>YvuQ&4Dq7nGD8Pllqs!Y4jNPNR3mvE$GApAD| zrhA6|cd6L<*F5Q~ua={n1#DAw|2rrY)~oXFI5*da7g_vEF9lkNq2#6IIUALG+J~vL zDHhl+^r}Ui9;@;?vIn$gDP7Po0+ad0;1&1c&BEBl)VOBRz&ifGSf$68-PX52hz65u zes~O#yFJ2fj>xhX1COQl?#c3%^Yv)0NNA}!17shaFfP1ul_^6D4Z#5zR;>Z|4?Z_H z+V9wZ=e!M`TR%Q`o-=rDYNNmb|Kl) zKV0Q}`XHzBStxq-)fG{o@Q~jTu`_t)eMxdvxD=inI_qoqfxh7y4nPGe2We#ZFI%hXhw&{6_ua*dQk$S^m;hF}OSwvJc?3T877T(y zNuf8p-jG@$e4$_#b~41xf#p%nq`W6{@;LuaEC>&zdfl=k4Sta=6wA6g>|N??;Oj@I zYhDp<0s&c=hQX;%s?csMG(KFy8%&m(`RG|ff|-C5fn=`|DeX0xO9#{6pmrJ(+qaG* zVhm3tMprgj2&Q4BVB(!3uKH_ z6s`jH)zpicVXdK^pM%r%$b)K*mpu9NjOgpt?mB!HaDztHp|083C~jy_4_;vHZKBFU z3_-{PyfQ-9uCq!lBIIjGQ#QR8xb6!eIrp9>2Y;9F8~e+Eczdh9f{d}JX+#CxVB2^r zTMFBr7J@vcrESvU9FJ&TM%qc5mXKc;s8w7CTABXRhJXEg-4fg@66;l~AccIS7Q)R0 z3AYqGX7#T8@N?n+fsA9`oyGq+eD~ayg3U;Ro^uthj9p-sZlZMK4L}Dz!VWcm!N1W1Ginlc3t!My&jR*_ zyWIvmbBoag_xlY9jjBV8dnNF*9@w*HS7z^Nd2jTM^DY|6cAqg9zhcx0rW)+&-k#dn zrh{z&Q_trqSsETQ8fIk%1bP1pQ5)XAS3`0%iB2z|;C0yd<&gmcUV5}m#{gtm3@sr<RIp>;iA}| zzEjUEZu?~L~PX?+Hx zIje2(Nv@>AqDm4s{H4V415EZgmvSwaa!|F&_dNSC9-m8LtrFo!mr4yj;Fp!;40)6F z>efHku(vN6E*1qLJUD_^E}Q3D<{5Me$t&UTb&U6`R3#Q>6@Y4Cjskn5kSrGsbLjhd zh|VjSesv)h6gZAl=*{fG{ZMpQU?7P;mv6d`!U+aYQol-GelAoTN}%PNqolbYQyuE% zM}J|N#87|^1{Sy<)cRKvu>X>EK}m!Sjg_C^&&5q)!7v=b!-Y5BUutDI6C}Mu4*sED z`wYh=iTp&npm(!p7MrF7z|RzQ*9;Dl>YpMo(sjS~#heofL{od>VZ!hFAhY#FPSQ(& z*9OSGdxTiy0kH7PvW+XJCte*LV=!FIr)`D?mS!(jN>Lk!Be$bH$ck?U;`pL)%qg5F zJrIx-Ag=1wf-}!t!&UEpv8-|0$FL3oILfrTd@sZ+nyJBkdXl<`eNv*UHu_d`E~%%4 z_Qrg2i&w41Wxz)CAA|7-B#e;&g`^9AFDf6$*}{48O$`@5r~8m+ z=Do3~CrJ#)j2J%p`B1r`QGf9~1}q*E51$wC$Q{gL!8Lxpj1dknBgN~0hi|PZ@I<1D z!cZ7XruV|&zKKgbnD2b4XnqVBjuWY)&2Ye&>O4z1@@kOd)Krc2P=e45aR0J})zRF) zcVR}HKsR2ab3vyq2xGhV5?u+I_+}_ehxF|vnr1-5!nAKVnI2ClRa$;bM}L6=u}%>n z{ze2#>GApaJ>IMF<5_`9APWY2N-`l>si~W2aOz?3rx1mS=|RCQ$7nkckUX~wICLC1 zh#n3q=R>s)t6%%k#-j9886FIRZs9lcX->~WjBW^(ltA5M@3I6?4&EwX8+YpOfD7gN zdm%~_4ko^3(46rlP5?3(f`4S_)X1x6l$&RmYsfKKVI4wLm1%a-5D&dpgl=pEu$R*Q zkMdU(W+ZZTY_la{7{Y`tEBJ_Sx zbAoHu&rYOg1&Pb2mu)QJrE1ZY?i{Taj70Y6Z6-CUYu&#%!buBbhZM~a$6@q0!;2Ax z?fHZ&{D{Khf9A7EhKGQSh=Q8y_e~KlyuGr3nSg(tYjFA&*GwPdPm36^70Ji34`A^# zjU%c7;VS{C+eyfErGd4*2UAd9@($yn;j^+ zt4=S0a!cU35z=(W<&y^Gh+b^s$;8kL4lYC*;DJ^4cE#9zd;Gn4Cy}mW>CpwFy_Pyj zkkr2; znO86n%}4&%zW%+J!XlOgtTuTTx618D7V8p#4Y)CeC@)+EgYcX-?y#nGxm9&89BJH% z-3^RjHU-w zM#QPn0slKINPYLA?s-y4!HQONp`VRb%+8=TE+Wh*bes)nq%=2MIgF+gs%aUg1_xBz z$wcTb8OINP0bYjI@L2(OK4M(H%@0gJTn#dP7PKxilUlUf-2>}dHm2Rg2Y#I zup`|^1AC($vpMsjz1Cejp*8C&=B}oiM2nQ(K#NR@*f!8noMfQ=nx4YRP@jM7aGLnP z5+_xyYdugF%z%SmGq;bK-Cv4M_Y{54IlW~1^aD0Djt~bv^RlPuqes6c682v7LLL~T zypajG>gbLi-DX#M-u9h?YTcVg?i8{y5cBnEC5b%I>Onm|P!89wF`B(+> z@Wc9loPvl=g{WOvzy1&t?$Rul06?vZ{H%Q}6XJbCaye=xrb6QassnRs@laF=#p1yV zV3h)BN_}G@D2=*A$9nAtkAu>!<*~oX3feSn6xa`k*(zd;6+YfP;uQi_`*GS&-O@af{-P5>=~)fX-WG-4b~s^Z8n2K&;I85U?pLnESx~xD zDo{k7+&?lV0*M}%8hTNKA7YTzoWivfy9K;@pUV|oU{_`xgPzN|V+356h!<4|Zn>Kh!&#OoSHK3pbH~#G43UoM^=q)>eA-sz zAQY)>b|G5jz_ht0ej5SA;(NaA+<@*Q0>(|2z;ohY&s3`^|B}aLUWc8qtM470G!YE5 z$z7|+K?^+5F(Pu`$G62^ES&;??li2&?#4%PpdOAlrNe$wbHSPo1c8D+QiOL^uY8+8 zH)tR(_i2*@5~MnUYS0}Eq|1VyH=FaDsXDCcWL)Ubof@1(kt67b2o7w7%eHkHI%C_Z z-;J}5LE!n_hGoDWb*qaobI13X?|iw*8L6tdh>=IR*;Af6Z z&KdE5HIq25wM&Zpd4s=sSzLR*Gv2Bn)$KZP{=ZYi6Z5|Z)uQ|pb7W0mipIsOirs-c z90GTOC{b-Pw`=@Bjr-s-z2D;Fz~;G zJai*c#;DOaDvlD>1oodoOcXEf(n`ak=oon`tkisz3&fYn19J^n$?w2-3Xp4Yc$B=o z9#oBww4^q{0NH9tv~Ye`Lj7X_ja95W?VkpG1j_!RdFtSG#j<&kWnOZx1oIqjbsg~K z@U7Er=!#~u$`b*0gg7l=yLw03=wcl6;im=BH3>7GwAVv=|t15JDt*Bb|E^IL8k z#7$;lHE%}Zb7mbqJk5)&6lDSmNzJER03}4;5%G@QJjJa}xvh11@Gx9pr5UEYS5>BSNf}L;~YesKjQUvgLr7$7byZYba zbmEL350l&$W1TI3#i-WAhEH%10wOT;C-L~IH*a$>i~bR%9P&=BlWp!$M#}NfE~SD` z4%wCZ(fz+byHxfEuP*J%cY*noHGDPt>@nyIJr)e7Q=pG$2YqS%2yi<>4cCl>>Yp;u z?C$5c*%j<2&}+69c0y`dHA6WD z&#i>V`I)WG@dVo3lVR#$Gc@`NFae1ow{go2-UipN$?Gey$*hyTfRpMy{i?V$`-y71 zL8m7Gx9IoNa_Gj(KL+&gs&vL%Y0m`7VDr%_-r;N(YEs$RQC*Z--i8kKmio7M!uLpY zC^uHi%<7hQ3Sr~60G$X8c2Y*lWKZ&Id0vnm2LVhH!6({nesxf<6_%gSZ^mH)!zU1P zvfe{dGPG$H81~KqW6Zloo>cC?$Q8_V+t5(!+-h>a7UMSsu8|==8bs$3V6VoU!Q&=u zw&@9Rg03;tkU#nXbk$wZVHNjXS{**|aT4n81~mY;#sxRvyNC%l@QXprqyo`+t@g-E zi{f`qH{kN*+98^MZAr;3;HazXM|V1tr!#63R&fbNBkx>FDE*7Jl)W3+R$h_*s3^qgsa(ahZTCn3iRkfLoz(Si zz(6B3hpy3q&QFv)NJh=+;3E4o}>k z0#?$_@{sFXGSFF%Rv(ks%f#A!DfrQQceMI0cVvJoY#t9X#KE;oNBVGjsWOEc-@;nx z$E!8B>e?Q{#U~B8FA7%Y4SL%vLj%)PW%~b-(*uXGK#|nevz&qRq#G+ zR~A*KP8cw^2zhn~it9os_%okPrajn^zY*gofYUf0n$%E{KyKO7exB?e9 zp@lnAe+Z7SNdAE5tdmylt)u@-!;b+MslOjYoNwDsxOXQUe`MdjDOWz7k6_;08}QLA zDh;nE-T|)Y=B>9eAq6QyUO$CQ;z3f6#Y5o@*%w+23;Pn>70THuJH^0bimC)jLOFkM z2fw}Tohk@EHch#PD<<DbACBz0QfhQYsu!BxEPw_QvT3b5l?u*a#TpO%vCMbUtkSXZGD zLDNd*8ue;0O7BnKi13)~Ta)Mj6s;=vo30azZZ|%~DtBRwPs<6i03kQ-6}cJ&DQszz z$Jp7E8?PVZTrw|Np8J4dGDklFf4Q=5V&^Ke8-jX9ENQ;VmEuURa3B<`mjBuOj@qg? zManJF>b%v3l`0jey`I_sWsIQjjXgeP1L4wV-2xb%(s0FZUZ5v9SuPwDuRUjp{#}{p zPhZT00~-#AEj)9g=UAGZ+qbGOC<_XeKbGN~{|iQj6-iDaq+n>%)XFQCvKaFHnn2<$ zM%A?=!gcd+7&R(uIl=8hVyLU>1p%Kv_;vle8@?(qPJ}&vKKw35R8h5E5m2fQD1BNq zMxIwCvI3s88rD??8QL(ImWxFRe(x57P9hX?mCT!NM+x`F`&&FR%8gk>zS9-G{Fv4Y zJ_h}2zTXFmSbW5HeuGV-sW9}lGVzEQ$VSyn4Zu+q{Yp-@=|UyHkQf7wnS9(MkZ#o% z$O)!mjpz(0G9do0n*24j3SqHCvVMRWWxi7I&Su$4CNbKGcws#H z_bOW0E!?O;YS`I+ty9)g46C(Rtkt+^`Mt|KOB$zc|yOmN*bcAzZgmD2CWu=y47 z?@LaqKU`3tYc_t(4{%X5-&}PrM}r;st@`Nz2rDW-3797*nUn2j`&G)Bsoe0UhWx2$ zGF){No2sPmDWQ5J$98Wt%VJjD7?j;d?}j$)6J)PoFg=8EY@vDu_{9G^_j zS`}iUjI5&4H#+D>*+2{@fEiD0R-of$1?LZi2&v_M1~N``nE)tDuMl5MCfcIo$NUBU zd;ZD5zA`xmd@9svf6i2d52o{zOXc&fg}q2WE^xr8JhcT0;(@ku01*M080)8}zlos! z5mJFv^wImWJh#DLQ?Rs32rn-wO3mEwd_WIb>J0+%aZUwvkfS|6)VqBRN6gAe^;wv# z2Vz(PNSE;E`X^s?mtHb*&ok+yY|v9Uz0ZN+J*L|Ol9;mtR#SmBKQUi(#R442fvE&k z*z;RCS|(C;CKWwADnD&>XI0cheu-`G8cqQqn|DCwCTIn+NqrItIH#p*w!(n4HO6T4 zKQ4Yn1DdCx;-|&2`0b9j8RN?de@5W@f}fD3|G>EdCX;`ENxk6rH3ktX3loHUq&eJJ zyupNWky!=c=br}AR^rg6T-_+QZ$)OD%3(qs9`?a3|BLbLoVs_JMF6TjZUbM@t0sz=BK*s4ZnX=Gf(?uaafbz(5}()OFA$wd+rK_~2fn8!a-5gUdHyYh_G|n7 zYRE5&zjoD+dxwB&gR@E+OYPcZGcp<-^LGB8>Ll(l2AslS;b}^(fDWz*Fbqu)BEU>^ z`{Sz=!?pa;GlJQwGFS+x2&YiEXb0741$V)I!Mk9dljU0I8+@F<&lASq%CGZ8zZRx= zQ42VeS&QJVQnnLdn=n8|~2vLSt_03sPqwR1Zk?%ZjylbZ8|EjOGi!HF~PYd1VpaDv4%}q z)(zzgwpQc6hu-k-H8M^fIDdL+p-G7TPvv9tr^}%&+)Scpi^LAVa!^9;29m`uA~agf*ubY99ZnUm%#l1$ZAHFs)%9DAur_ zcLUxo4_@x`J)g||DAt*b`?^($HWxy%8nVFu-+3aSQ!QTmE$VnlE0`xL>l|Go`D&tv zg`o3`&PCWa=$TY5n))Z1#ka_I7c~C$beTj7P6I1A^HV97B;2gu4=d{)?(2vh=T}F$ zb$()wYC+Ng3|FQ)JAvcYbDh@F?%7Y#0i7Cu9+;o3kCC2DSh0K;bcx{cdfSHFkn=CWJE{}`?YWS@+E>>p<{y(eCQx70$}CI zg6HF0g(-NaY1F^F07CBpKlW84CI}}Bc<@yY01kmC&AJ=X))(V6Oo`PY^}zAR28FJ3 z1m<##>jdSE;Lx}&U9zly!~OmyJ6&UUx>7+k`6%>CwqG#YQC~oVdrr9)CM#7?4crFM znO@t!l9c zr*Uu5FpkzOv6d2JReNPG(0Ah*4((WhPzQdHIl-+(K}EDG`70TSIu2lhPA7JR^o zd)WEM)gHd~<_Q|2N(Xwb#mgOIdk%P{R`-`GpPLj;pElxqu~5M@-Yh@;H~8W`_=2_h z?4L~nPHqUm1F2ngsB*jQmYT77K50D4V@6#QrPkbUmGGVT6ai#aD8kpn`vrp6)TVDq zovAZ7MSEd}y)S-wBQ@v2-`+U;ZaLcq zHlzoBt{IDKDpu8z`?q~`M5Gx44YmKHS;GDZ{@kS!ChpKe7V3U4yMj##5-{3hi%%}o z1-Z%q^hmb{LbFFabkWgNY=>7XulX=1`3*!gbS$qKzWvrOoWcdAlpQFm(Kbs!)KODw z(gW{55@t5MpRapE{CSIaQ%EgfQ~gc{1;`GGDmGi+cFvfV39GvW)OkW;W;)+E^f|CX z|GCubt*ovGvF3}zn;?|Zq3BWC1HoV?zuV&!SrqT{3LNSKvQJht-S(Tgz{vgx8?>pD zhUq~cH@}ltixX`}|=tV}Ce*s2=g{aR5*rf@&IXF6F&SazD_5 zNaZ@Wy&yE)$3{C`7IFzz%UQQbPIot7f4^FC0YK+6ZS|aX=5hn z2F8m5f3pWFI)ZEX=AiotKKf=_BbH7(;WiF(j%%_>M+8ql4PQj@GA};2w!)k0J8`zY zdfrXo=i=xGMX}Ok8~KttquXiwC#BtIlIoSmON-NObNW~>z~|adH4S{M$NK$=G(7Ql z5yZdtt+eI%u4$FNF6uy3i!?-GGlU?hz(V+Br{1#Y?VXZq0ngZpO$Uh79RiIu@K2Bo zodR{Jqqdyd^#`kgtsf55V{1Uvq~)IB5NFh@2$BogfNWQrvy1KEPDXux+pKK}7k)%C||(6CSP=9_Vl zgP`;`CU`rn{Y=e$RSeq7PwBD-*mOMe27EX2(1u8BLw8n^iMt3`v8m+AP43LecPXH< zTS;>itx4(97mzF2^=UNi)bIl{VThF;AuuZd#sEj)bDq~BJST`xFTC(QwrUbGJ@Tug zt%TPs1py6Ks!qA-$peX>@jAxOdw*3(5t_GLu$cq;=2gSGUQVdu&4V?{&$yyT0Tb{T zdUAeZwR8^J79;|MgmKP{A3aA>DOS<)Gc?j>xsK=>B!&SO!Z-u=)e{9lKm@y6zNX-L zl!o;9kHuKA{KD24NO+)7j6dbxZSOLOe1OrK(=s#vp$1DK-`Ld7CN7g3aWntwgnJ=8!Q%WG;8+?;O1g0Ro|wOmANV@J9NN@qC{%vl&%GP9lFAqT73izUvFn-aas| zTXOQaeRKQ_uMtH6zGykQbq7$%^)!@N?S>T`E9Qu>FoTJ0WQ>pK{;|O<`t3&N``*&a zq8c2hh+iyu2J@uiMQhzKOtrpM*boSA%3FBe<^q~XPgVI1?G#vU@$d&Mbe>YkF7il1 zML%F!xQFm`R~B#rxRm-|n4tpyI2*tVmh`UDK;*t>{~tItA8c}m5y98+7lLFpGJlXQex69v;75|6`+XI+~lafVH)53Rn-sF`~slrz|#Z%a|{d@BPk{y)scy50gzaKaQ<$4m6i5E~eL@EN5em2^YW{KD=ZD$3Gx~9@nFA1*mIpT@O z3SjtHhkR6D5FYE2VvPjR6wy2$`SxGKZt87hcGbHaX++o2*hcP1Yjx}~tNV>Tc6`JE zZ1_;CKQJ~RSi8e(EbPgzG&%T2D);MmdwYaFp)JZ+b$c|_am02fOj3lvAb!dL!wl?A zjtkGgR2;Ha`)zpQ2#h&U9rueIzQ+s`i*wW8Di?`A(*w2ZcXPYOgU-f$QDY{}0n~>^ zZ20{8E!}G>dT?hky2cpJCMebWQt?VPc*p+XXHc}Vf2+}v9P1iqkGxV2*aTuN10>9( z76eZXAK;cBLG6*n*%SODUTk3Qe4uInGjl2$%R&X)yg@1+WXB|0ER`nufNB-V`Cqj< zGA8#ki$uZx+d=8Qf#k4?G;4W0fMQ>;)w1~!jc1{GR2lK$Q5I1P@Wws4ZC%EQ{l`jK zWX}2Zl|5Z*@LuN~wOtdP>dyd(7HX&8FK<*VE`RW-i;}`hDu3Bjzvs#G5;JtDlMU$l zzW#(sdF^PBaue$}62Dpds*Dn7KqL@lhSxpsfBOKE2wZyymDz{`*HJJp`LAZxDZe2a zPQ*2P?F`h#>cKmlK8J1F`}xy1#H}ZoU)w!3H-)^w|3dwM8)Da6e1n&=)u}V{yC01G zLE#IcX6Qwa7zMkWj6f?!X^9daLLj&u0TgHh1~2_$9##y?xhoN8#lX@yVTmlLN$LrMY`|js(OPDND=G zqSw8D)19QtHwieSa{kqKMs2ax87qr=XGp_9Lxq147*=A7&xx>Ea_rO|hEAv%X8GP`$Lhu~HE5^6af_#PVv(=Grt1W*uyHqX3t;FG z25|H9pl+k;bvJn+cnB6eBNE2;mFw||K*H=T&LmyQD>2T{$ zOw7Vy;1`Jr24kT0VY*x`Y}2ik7iw_BQ=UXm<5w}*C0ZF`2Yo;bDDrd>auCfsAJyci z6Jm_5wL#;8-n-5CKu=aLH4Hj=o4>~&O$;Sn8Ug!3VD|jv5x*00kI`mTMBpevSH}GV zvRX89FSwrOi2{EG>WRu`G_ZTQR4yBXywXH{_~25>XMm9xe*1umc0s7znC@Tth*-oHd8bW7DzM+6g>e6 zv;baSFBQ123@N&b*Y4+1E$LKnktBJYN_gpqjRE(hbb4&^(ndypO9~g=)CJadkZE({ zY*L}0z!?-doQE42?+ntR?;sHJ)YSJrl65-W1g>+EC*M6GnBUehDU1N+a$n#_DVNdv!-s_MLZZCJ9o-|c8geYC+&83? znR^vkHPByTfqQKLG-^0T0>*o*6m|$>H3j$@^*o{S02kRwNs`NsDaJX}2Wvp3*dK;C z)W1x)x%2t5Q|I$>L3IIWe;hNLuXBx`?2j8!cg?Ew{wR3Zm0FqrEwN-aak*xi!Z2cC zqC~6!gK=W?N& zciuaPV3v;sCHz0zGyJ*Xz>VnI4=jki*SE4^9F{9u{P{&rqg&7li5&o6e&!|PhxNBQ zeq&(;ZvnpqF7qOS7m-?)U-~v=;tgG^HXgu-O9K#@qGSGuWRBti8OxS>$BsxOQzYkDLz zQ(*+;Ue==jNSyC|71#Z)UGVip()8=k0V*_gjaOeUMd~F8PmKN_12&zshL#o!T7Va= zpG#!;J^p~JVF>F@>w}{VXZw=HUd}6G46MJBYCc!RW`7w{zT9^CnK05K5Irc?_-GJE z{qZ;Fw5rjpC{NF_jWiGjvzzaU<3u3u>$1odWg^sf&;XMw99~@rG_}|j9qC#>U zdR$-m!uCgyCkyH43lI#>;D>~2!FTNMgx;0gm)*~DZ1&mStNSD%QiRw4MU}jv=sR3_ z;_Ev2!4~rD=d)C^Y=e}7e zQtC*GPIq!I*{K#eM^1c5boK4!&m|YtlWbGaOh)#-ZPlJ#@K7DN8l|yOZ55&@Pju?> zS}U{mSbU0Gyzi_iAHN=Fzh3MX_>H;R^#$97Vyws?{^ZfpQz5!Ri=@@C5jjNYb5!&O ztmKFHe$oO;-UKM@dni|fQ1>jB(!Vk<$i*LBeX)rDv$%U?iq8hiH_CC_qO5Y)o(qEP z$S)qKPaXQ{+SW#x=hT$PK_1Boe%c1DP#G$d zutH=o)cE9(N!yW4?&%3?rABYq#EP^#B2@+@7T#2**O1g}ba<#C;{Mraeld4RADurX zbNIpeyZbd+Kxw7O3O!iaMGPzh81U17DkjK zt#7Fs2egSl1-9kY$zyitXS+AnTgJO0 zVa)QoPN-u02Y=d-hl7|CvSsd6eS2aW?lZ7MRCcpc@JTZ^0VA9_i1j^1Hm^&(nE@(E)rLKHmOM6PcBCg9K8YbD- zTBF&sp*eAxreHY!h2bzdt@?a|Uf6)g>R4%~_bx+C&H8({Yfnw$04E(BMgleebADQU z%8`Xkezmv3J*lr7+wGFO$VIIj%miL{1kjSuc<42HC?TZc4WcUSl3~A;gqDN{7ZQ#Z zr+3QSNaZ=9x;^Wkc}$->{PE10cKCXb-72VHxD~O54}s#nDS7%T<5i{QMT!z8hbBIU z){2a|z}c2Mm(!0&h75D5FQ5YAr;EE1c~;rLdP(QHJ$0xzcdEzy^0ljY@gdu%sT0@q z?VDY)fO_-U-!Vp*KeJfOh3iFIcGlm|?@kDRe;n@K%fcjfE6x(-CM+p6${99*RC~-qlNepjd6T z{c!RRC)8y8yWb*ztUzX8``bvweE-D$6W)s6{t-1q=tjyjzJWkwA3c;Wma0f|AZqP@ zujkFXkvAB<3f)G@cDxj^5AZoJrE>PZSX?G}EvNYsXE_0$Qc zbp-tCQ^~U0PCG*l#FIvFO2Q?hytm~1nx8K+*)YPXv3)(^%Ld&LZUehT0I*s(Lc~80zK57NW zN+hr4{eFSaVIw^8iBGO3_J+3_c*MrCQ=3=>ae7p{Q`p`4aG^gMyk98z^*OcrDIQni@3l76BO%{ zR3Xj(`}R95cG44tEw|`+(>r8`a?Fz6q1TlXLEk+oBesqLt%*&p1YM@I{);6&3i#5b z*NTKGb6f%63PFl$%N(b_!N2*!|2~uNJ*UMR{B^||8s*BReHykYZH|Bav5xAB-2s0ZBR!)@AnRkngIjbC2TVp1$2jc$<8qIfh)5LPvpWlvoVW$hpC0n``bE+ zx<7p6#|9O!c$Dgh)7exK(Ik!NhaCHi<<%jkFT|4>EKr$m^|BxK35Pcuv?hcNdD;_2 zg=j@8-~KFd?c&!9Bsyma<^)r~Ty@pF=5|-cY z|L?~?e8*D?>)#5f&=Q?ufwGYIoI0}?uC21tDr=w!Dx%V+Pf&wK>t2J}^BrYc0?I*8#kp8^d{j>? z$&(H%s`Eg}{>3)a)<9n&O4Fd#FbyRH=JT2NyB%g$P9{8B3z)R0PK%$4{(BQc?|3pj z`IK9BGQ}_+sP*mS=ErUbjc-LGS4$R&1gd+yRN5Hf)TnMcL84T3rI9D@e`=C`Z&>vW zb|(2{2OwQklJzx(4J55DenUTl-8BueyCP-4HT`U^-@ROqF1JZ_XNNeDWqnl*qK=vN z(0CP#0cplGy5puq01>&hvBdt<)e>2}BbVpd=#uzdHSteQy0q%@FypeL{}_9&HRX!4 z2@gXEX68Nq8l4YpY|xFALpl8`96Y}mo57l5lG39^rT>nSse2IlzY_>l3ETAJ`FXg3 zKG8Hj>W!nM8TSC8VcdgKZm3V+j&Zx#8AQ!%!@I(Hk^g4(v~H4c60w}>F`yx^H36Et z$JTQ@#CTHX9Mgew{UW;D1;XqO&-TY}BhqJed&Mwk1oJ=)phMpfMg7)7nqvq5lxR zAzd|aj-Ya0#)8vO!jRcE_C=qF9(#d4)$Wymyp4| z1i8F)Gkl2ho`Yz+4cW$&x4T4in%6_+83NR2i9;D(zBnvo-0dop3y}3?} z;g8MH)^Afqq$oL*r4s}C@n-Df(_J#^Vg2tDQIE`ZF=xCNm}AFG`+SSlD_dJ)u4Tb3 z!)nr7>hEjHoSGIxe3WDbuH#o)!GPyVwaRp6aLJz2Rb8d#SK&JxnUrt^8Tz#LeQ&jW z%d$qLCxgaa-7<%(^0okbnZ<2iFg&xW0KAj`!beAhBh_OVkfy<<=@25CIy@T zY+7I6GPf;3iOq!HPkG72beR|6rxSlh)1&TS3Dz5;zxU{?ZjZWiSF${$>gBUc+S6jU zL|c^_a-l!#HCVdLP}5=_la#iFbL7dM_p_qaYkpCX7dUZRh`$`IT;`I#pCRT*`cDx$9U=T1{*VsL@X^Kn| zEv5ZJ$l%B+-S+O38wN?L!s6PTNOt<`u#=wAX zjVIS_>*sEC>*6}N^Pl#X=uOv|Is0>$9A@*~xIhZ8;SlS6pMJ_3RMKGDZ0}HwWXYEA z#~=Hj5?Z@+R-}x%h@QVF-fd%P67y~E+j&h{U&3y@+P;=}v<jM9bTxg zjLgxh?$0ap_!CBVHJ<@0T0F{O&mXmq=dtl2>Z@V7EVe7JU$8KA1Z3j#Umtc~lMZH( zOc>+hq2x`!-uLICVl@;@?x75*G|DDPiK*}k6M+#>H)5&%@6k<&e=@w&#AcrNe&0ei zp;Oa1^4Cdm*)gz(+@dvi%4zDcHi~D`3~rD_)bz(^E786j+(Q3lC}EO}4NmuFQVT2! zDz$+dgR03Y)gfc`Bs+BL!-L%CN^N_?Y5TBhgGLunP62iIiyy%cy=tF zYCGy4MS=6e=d%a_>iK{{2`%Gg_xqE)XjP{TZCZTlk=*z0a^$<5P`Ux!v8ngfZ^A^b z@NJ}2_8fMJ7UId^u1&*<;0}r#BvpElTsPHfCPSOtD?^`n z2?L5YBXUm5Z_rVGvz9yKX`Fd+Xdq9wP4PV|=Z4m# zvd0Uq{jbcaPpHnUYL9Ya_sMYX!HVZYE~t$O0mSnvV2S|Gh{rnO8F5L@s6~S5FI+sq=lZGNj_=JkC$*QKIj3XPiz{9qMex&No^8dKCP(I(LWi&wZ*Uo@Zdq&uR#i(%k zji8NFZZP;^npR2_0{%H~d<`sDu0;Bvj}Ui;%ESnc>QeqPY&)y-|%1zIbWc%`_tJB;sBE7{|W~2TR=pC;F#&Fa9Ub7R$62=iQ zvCym)@$avRJ7Ibc<%`BFb776mM11$A>eN?A-Lv1S55FKtCM*rV;J)BXs1v*TqoMZS zWpSgxqwdt1BClOG;@QtSeXu)Gz{N<*t6!DOO*=*qB514Xc;7jhmbg7D(9ifHzj!$O zvNnPrv(&Qh@xO9IOp=dwkNM17oN%r@OAMM{C%1yeKw!CcR&Jff+z6K^(tHvzcbcV< zmDdup56j6IP%jB8HVBQ+{Eh!}=g_--LNcrBMfsN(1fUxODegkPk2l5bi2JTa`fS zjr6cUX!}q3e4dI4wm3<{ z!lcsGD(yD1)-t;`7_Yn@V!`xLgZ`()NjoWRV24&Khhs^NWvu4i_E0fX|&n1VeC=8^S9)5bOb0yO*6hfMgO8{2*7u%;jEEip*_#f{YhuPZGYPBSr$M81vll{dn(-k^6{dB&b8Kg6O%s23Qb^yP zF=myzk>aPTmxd-tM?Nx3G#$+U*qJNN2Q}?;lKVoaPcJz2qQfA1YH+-_E$eMV{Uw^G^}qCZKMXS*wHou*lNO&ojP?MZE`)BoDcpplg&r9Ndp&JEQs z8kJ_vy&Yw8tC}WH{pgNP(?*LT_KP2y?-%<>`94|Jq2>Cp=N3CZx16;+82`m)G4guC z|EqwR*_0jqy+L{*TW#c0p;WwTZr2_(9~I>+HG8< zJDX-a$N{t(5f6#32n>7IhVC!f1mY(3D1qarlPwFMyM^l)WmLMRTHHMd_mP*fZBIez zJzt;giU>zyjxl`HZygZ>r zy1f2Sel?@Vm)}TW@_Qi4xA7*>9BqpL8$$q-;40z zE!y$|q3PP=Yx`w7$i?>z`kNb2V>juWMr;>PnkAhwRIl?wcbR^a9NH#}akRt?n6UOr zD` z!^FQVr2ug02ThM0eg*BjR)1nRt)`qqFFt{uTKj?ul|JI1onxPGxn@=M4(p%6bivyR z3Tu4o0=KQMy?l?6M+QY7XoZx6z@y1lyEza|>ojbf+DNRVuDGCnViQk~lferj-JWHu zwtlVHg>6mkdi<$L0~Z@~J@_lqsrb<0qmbi8y#`%ga}>C@S1@r=9>X%b#8%c4c~ppN_S#3g|p((z$K_3PDz=2!n(Wm33hO~=?^|9$?&EjssS2F!6G z-&Rg3H1g(Z*IL09PJVfKd_Ebk^T?9ALjSBy&qSLoh6l=5CN<$PT=X8ozP6*u-XmHV z&+gwCOS{cwF=n4qBXZW-6K~AsHdO^5DFI#ig&)g!fdhnr1Ka%)Cd||Gl6@jj?u8;R za4c~AKJ*ZbO+%j|4!+$5(%%mZQ=hhtmT_9tz0(*I>20CnQkD*ngADk)&;}solyjXE za_i`}h^mt+5-f*0+cqlQ!gDK-WIoLD%c#8unQ9|4NOwwme;}giAhr`OL9_xD?`iX@x)U2`} zO6l@TldJZWQQnSgsD7z4@_^s zF%Xpy4n=njn^uAl@_%|?u#VUMKc>Ds9?JcF|Fj$;OSUXoLbfJEBztA2$dX}Qn?`L;`Kp^$A`h3&kitek*$kb} zbL{@IPo>i1&fOn=Vc7|1CEx?Lvq#QSi$k;Tk$k(o@eCRC2F}mY29q)O@EuchBoNG= zd-aS%3xjmaN71u{ExZod%!@UW#KzMC8Ft6OPP`_OU6rW`37FB@L*F*XqtRU1HCQ!D z{X(L-{1p05W3S}$+DslFD9X_y;YoLeu~W58bG=ef6G}SfVZp+~bvK~5j0?j+(rzrg zRr|J;+QYu$3*xWuG~Ycyp@g4E`(>WbyL%YFxL;s1LVFnlrzeAm0k+Fd-9q%;S67#9 z_702KmiiS?6?N;&dew2r{o3x-d;PJFpy z*wI)W=D0h1ouV>tG_giZbl63uE7WIYD!Znd;SFITtMQhCX~>=%xn{VPl}$jejX>R&X1-r19j}V z>4-4ZQ3d52JyIJ*&??u(zvbSL*pWFo6t5@(+uMzb7f(sc>9r38d+*du@fr7O=2M4fGNpzH=uQMlhH>8-%%nCsL+VIHx+H%{ z{ztx-`e78LO!DhAwo=?qz3is(%f)@eBffs6b&b#i0Y=?G^-u^zllrJ+m%oUW`ty33 zawL|Nsr*)c;l4KQI7d`n%1tsXi{QQ6p6m6)>J;&rtoU7WkL*mt&e-3fQ4S^GF2!#v zu~S@SB?R*7C#&Q_sj+^UhKY|-^@D=a*N3)~q1uRr`2EQ=2pnusvc}5Y&V!ZMu0d)8 zaVO|yrTWs4l=a!lQ4WLpxie6?fEX_Rfva`}rWrwZ$mww-YXqoC5^mcf5HUZ%QYvS{ zIBC|u7GOHP=D@K&w1=~zQDf-J^6>7;5s02hC>B<)HRwG{8ivt<&iQ^Ns90nB`_?k& z@b4N$c|*3zhg*z zc)2QM4~^TM)5*+3x+RIO9b9`?*rgaxUe~ELq@bFp5rZqfJuEoieD;agwK|R4O{zk< zr6}FL3R{=JkqTsZ($F$W^~uWT8T|3VIv>zP-932*`aZLiWad-9$y%ylqLP*2TF^GS zP>bMO!RM{Kd=vd_Oq8}!0R^qJ`*7sebrWB%ICb!ar)<*Za%}7ttLOO+WNb9E;or%x zv&b-A(}V8a2j^9UCE#6}_+TZ`oo5~vZ8omx36~_40xl`y(&wA(Qi)px`FW*!o#B

C7Im@Ow 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 Date: Sun, 19 Jun 2022 22:46:46 -0700 Subject: [PATCH 150/220] graceful fallback if resource cannot be loaded --- .../src/main/java/com/dfsek/terra/AbstractPlatform.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java index fe04ef97e..81933014f 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java @@ -111,8 +111,12 @@ public abstract class AbstractPlatform implements Platform { logger.info("Loading config.yml"); File configFile = new File(getDataFolder(), "config.yml"); if(!configFile.exists()) { - logger.info("Writing new config.yml..."); - FileUtils.copyInputStreamToFile(stream, configFile); + logger.info("Dumping config.yml..."); + if(stream == null) { + logger.warn("Could not find config.yml in JAR"); + } else { + FileUtils.copyInputStreamToFile(stream, configFile); + } } } catch(IOException e) { logger.error("Error loading config.yml resource from jar", e); From 924783adb2d48c445ec6c5ede933ea5fe39b7639 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 22:47:06 -0700 Subject: [PATCH 151/220] clean up buildscript --- platforms/forge/build.gradle.kts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 31c5632f2..14eaa5bde 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -1,14 +1,9 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import java.util.* -import net.fabricmc.loom.task.RemapJarTask - plugins { id("dev.architectury.loom") version Versions.Forge.architecuryLoom } dependencies { shadedApi(project(":common:implementation:base")) - forgeRuntimeLibrary(project(":common:implementation:base")) forge(group = "net.minecraftforge", name = "forge", version = Versions.Forge.forge) @@ -23,10 +18,11 @@ loom { forge { mixinConfigs.set(listOf("terra.mixins.json")) - } } + + tasks { jar { manifest { From 08299602320517d371528541518e4f307dc14f0a Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 23:08:52 -0700 Subject: [PATCH 152/220] simplify Fabric buildscript --- platforms/fabric/build.gradle.kts | 52 +++++++------------------------ 1 file changed, 12 insertions(+), 40 deletions(-) diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index a89870146..9a98e394e 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -1,10 +1,5 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import com.modrinth.minotaur.TaskModrinthUpload -import net.fabricmc.loom.task.RemapJarTask - plugins { id("fabric-loom") version Versions.Fabric.loom - id("com.modrinth.minotaur") version Versions.Fabric.minotaur id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower } @@ -38,44 +33,21 @@ loom { } - addonDir(project.file("./run/config/Terra/addons"), tasks.named("runClient").get()) addonDir(project.file("./run/config/Terra/addons"), tasks.named("runServer").get()) -tasks.withType().configureEach { - options.release.set(17) -} -tasks.getByName("shadowJar") { - exclude("org/slf4j/**") -} +tasks { + compileJava { + options.release.set(17) + } -val remapped = tasks.register("remapShadedJar") { - dependsOn("installAddons") - group = "fabric" - val shadowJar = tasks.getByName("shadowJar") - dependsOn(shadowJar) - inputFile.set(shadowJar.archiveFile) - archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-shaded\\.jar$"), "-shaded-mapped.jar")) - addNestedDependencies.set(true) + shadowJar { + exclude("org/slf4j/**") + } + + remapJar { + inputFile.set(shadowJar.get().archiveFile) + archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") + } } - -tasks.named("assemble").configure { - dependsOn("remapShadedJar") -} - -tasks.withType { - finalizedBy(remapped) -} - -tasks.register("publishModrinth") { - dependsOn("remapShadedJar") - group = "fabric" - token = System.getenv("MODRINTH_SECRET") - projectId = "FIlZB9L0" - versionNumber = "${project.version}-fabric" - uploadFile = remapped.get().archiveFile.get().asFile - releaseType = "beta" - addGameVersion(Versions.Fabric.minecraft) - addLoader("fabric") -} \ No newline at end of file From cb4c8f28ef793d0fa66d15bfb435a16200603d3f Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Jun 2022 23:27:30 -0700 Subject: [PATCH 153/220] clean up bukkit buildscript --- platforms/bukkit/build.gradle.kts | 194 +++--------------------------- 1 file changed, 18 insertions(+), 176 deletions(-) diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index e0a1bc48a..7221c9f90 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -1,20 +1,9 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import java.net.URL -import java.nio.channels.Channels -import java.nio.file.Files -import java.nio.file.StandardCopyOption plugins { id("xyz.jpenilla.run-paper") version "1.0.6" } -val testDir = "target/server" -val testMem = "3G" - -val paperBuild = 350 -val paperURL = "https://papermc.io/api/v2/projects/paper/versions/%version%/builds/$paperBuild/downloads/paper-%version%-$paperBuild.jar" -val purpurURL = "https://api.purpurmc.org/v2/purpur/%version%/latest/download" - repositories { maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") } @@ -26,174 +15,27 @@ dependencies { shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper) } -val throttleCoreCount = 0 - -val jvmFlags = mutableListOf( - "-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200", - "-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch", - "-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M", - "-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4", - "-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90", - "-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem", - "-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs", - "-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", /*"-javaagent:paperclip.jar"*/ - ) -if(throttleCoreCount > 0) { - jvmFlags.add("-XX:ActiveProcessorCount=$throttleCoreCount") -} - - -fun downloadPaperclip(url: String, dir: String) { - val clip = URL(url.replace("%version%", Versions.Bukkit.minecraft)) - val clipReadableByteChannel = Channels.newChannel(clip.openStream()) - val clipFile = file("$testDir/$dir/paperclip.jar") - val clipOutputStream = clipFile.outputStream() - val clipFileChannel = clipOutputStream.channel - clipFileChannel.transferFrom(clipReadableByteChannel, 0, Long.MAX_VALUE) -} - -fun copyTerra(dir: String) { - file("$testDir/$dir").walk().forEach { - if (it.name.startsWith("Terra-bukkit") && it.name.endsWith(".jar")) it.delete() // Delete old Terra jar(s) - } - copy { - from("$buildDir/libs/Terra-bukkit-$version-shaded.jar") - into("$testDir/$dir/plugins/") - } -} - -fun installServer(dir: String) { - // clean - file("$testDir/$dir").deleteRecursively() - file("$testDir/$dir/plugins").mkdirs() - // Cloning test setup. - gitClone("https://github.com/PolyhedralDev/WorldGenTestServer") - // Copying plugins - Files.move( - file("WorldGenTestServer/plugins").toPath(), - file("$testDir/$dir/plugins").toPath(), - StandardCopyOption.REPLACE_EXISTING - ) - // Copying config - val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText() - file("$testDir/$dir/server.properties").writeText(serverText) - val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText() - file("$testDir/$dir/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT")) - - println("By proceeding, you are agreeing to the Minecraft EULA: https://account.mojang.com/documents/minecraft_eula") - file("$testDir/$dir/eula.txt").writeText("eula=true") - - // clean up - file("WorldGenTestServer").deleteRecursively() -} - -fun deleteFolder(folder: File) { - if (folder.exists()) folder.deleteRecursively() -} - -fun deleteFile(file: File) { - if (file.exists()) file.delete() -} - -tasks.create("cleanWorlds") { - group = "bukkit" - doFirst { - deleteFolder(file("$testDir/paper/world")) - deleteFolder(file("$testDir/paper/world_nether")) - deleteFolder(file("$testDir/paper/world_the_end")) - - deleteFolder(file("$testDir/purpur/world")) - deleteFolder(file("$testDir/purpur/world_nether")) - deleteFolder(file("$testDir/purpur/world_the_end")) - } -} - -tasks.create("updatePaper") { - group = "bukkit" - doFirst { - deleteFile(file("$testDir/paper/paperclip.jar")) - downloadPaperclip(paperURL, "paper") - } -} - -tasks.create("updatePurpur") { - group = "bukkit" - doFirst { - deleteFile(file("$testDir/paper/paperclip.jar")) - downloadPaperclip(purpurURL, "purpur") - } -} - -tasks.create("installPaper") { - group = "bukkit" - dependsOn("shadowJar") - doFirst { - installServer("paper") - // Downloading latest paper jar. - downloadPaperclip(paperURL, "paper") - } -} - -tasks.create("installPurpur") { - group = "bukkit" - dependsOn("shadowJar") - doFirst { - installServer("purpur") - // Downloading latest paper jar. - downloadPaperclip(purpurURL, "purpur") - } -} - -task(name = "runPaper") { - group = "bukkit" - standardInput = System.`in` - dependsOn("shadowJar") - // Copy Terra into dir - doFirst { - copyTerra("paper") +tasks { + shadowJar { + relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats") + relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib") + relocate("com.google.common", "com.dfsek.terra.lib.google.common") + relocate("org.apache.logging.slf4j", "com.dfsek.terra.lib.slf4j-over-log4j") + exclude("org/slf4j/**") + exclude("org/checkerframework/**") + exclude("org/jetbrains/annotations/**") + exclude("org/intellij/**") + exclude("com/google/errorprone/**") + exclude("com/google/j2objc/**") + exclude("javax/**") } - mainClass.set("io.papermc.paperclip.Paperclip") - jvmArgs = jvmFlags - maxHeapSize = testMem - minHeapSize = testMem - args = listOf("nogui") - workingDir = file("$testDir/paper") - classpath = files("$testDir/paper/paperclip.jar") -} - -task(name = "runPurpur") { - group = "bukkit" - standardInput = System.`in` - dependsOn("shadowJar") - // Copy Terra into dir - doFirst { - copyTerra("purpur") + runServer { + minecraftVersion("1.19") + dependsOn(shadowJar) + pluginJars(shadowJar.get().archiveFile) } - - mainClass.set("io.papermc.paperclip.Paperclip") - jvmArgs = jvmFlags - maxHeapSize = testMem - minHeapSize = testMem - //args = listOf("nogui") - workingDir = file("$testDir/purpur") - classpath = files("$testDir/purpur/paperclip.jar") -} - -tasks.named("shadowJar") { - relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats") - relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib") - relocate("com.google.common", "com.dfsek.terra.lib.google.common") - relocate("org.apache.logging.slf4j", "com.dfsek.terra.lib.slf4j-over-log4j") - exclude("org/slf4j/**") - exclude("org/checkerframework/**") - exclude("org/jetbrains/annotations/**") - exclude("org/intellij/**") - exclude("com/google/errorprone/**") - exclude("com/google/j2objc/**") - exclude("javax/**") } -addonDir(project.file("./target/server/paper/plugins/Terra/addons"), tasks.named("runPaper").get()) -addonDir(project.file("./target/server/purpur/plugins/Terra/addons"), tasks.named("runPurpur").get()) +addonDir(project.file("./target/server/paper/plugins/Terra/addons"), tasks.named("runServer").get()) From c6428cff66763ef18dac2c165a42f1c9d02ac829 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 13:58:45 -0700 Subject: [PATCH 154/220] make slf4j compileOnlyAPI --- common/api/build.gradle.kts | 2 +- platforms/fabric/build.gradle.kts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/common/api/build.gradle.kts b/common/api/build.gradle.kts index fae96eac5..fe36f682e 100644 --- a/common/api/build.gradle.kts +++ b/common/api/build.gradle.kts @@ -1,6 +1,6 @@ dependencies { api("ca.solo-studios", "strata", Versions.Libraries.strata) - api("org.slf4j", "slf4j-api", Versions.Libraries.slf4j) + compileOnlyApi("org.slf4j", "slf4j-api", Versions.Libraries.slf4j) api("cloud.commandframework", "cloud-core", Versions.Libraries.cloud) api("com.dfsek.tectonic", "common", Versions.Libraries.tectonic) diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 9a98e394e..401cea107 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -41,10 +41,6 @@ tasks { compileJava { options.release.set(17) } - - shadowJar { - exclude("org/slf4j/**") - } remapJar { inputFile.set(shadowJar.get().archiveFile) From f3329bbff1ad57cdd49261e962e180f38f1c94ac Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 18:33:28 -0700 Subject: [PATCH 155/220] rename mixin configs --- platforms/fabric/src/main/resources/fabric.mod.json | 2 +- .../resources/{terra.mixins.json => terra.fabric.mixins.json} | 0 platforms/forge/build.gradle.kts | 2 +- .../resources/{terra.mixins.json => terra.forge.mixins.json} | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename platforms/fabric/src/main/resources/{terra.mixins.json => terra.fabric.mixins.json} (100%) rename platforms/forge/src/main/resources/{terra.mixins.json => terra.forge.mixins.json} (100%) diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index dcc277954..e6e490c1a 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -21,7 +21,7 @@ ] }, "mixins": [ - "terra.mixins.json" + "terra.fabric.mixins.json" ], "depends": { "fabricloader": ">=0.14.2", diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.fabric.mixins.json similarity index 100% rename from platforms/fabric/src/main/resources/terra.mixins.json rename to platforms/fabric/src/main/resources/terra.fabric.mixins.json diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 14eaa5bde..63db47bf2 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -17,7 +17,7 @@ loom { } forge { - mixinConfigs.set(listOf("terra.mixins.json")) + mixinConfigs.set(listOf("terra.forge.mixins.json")) } } diff --git a/platforms/forge/src/main/resources/terra.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json similarity index 100% rename from platforms/forge/src/main/resources/terra.mixins.json rename to platforms/forge/src/main/resources/terra.forge.mixins.json From e85afd7dd6c9b7db17257ef60f687f4d251cee60 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 19:37:17 -0700 Subject: [PATCH 156/220] convert most lifecycle mixins to event listeners --- .../mixin/lifecycle/NoiseConfigMixin.java | 5 +-- .../dfsek/terra/forge/ForgeEntryPoint.java | 6 ++- .../com/dfsek/terra/forge/PlatformImpl.java | 11 +++-- .../mixin/access/ChunkRegionAccessor.java | 15 ------- .../mixin/lifecycle/MinecraftServerMixin.java | 32 --------------- .../mixin/lifecycle/NoiseConfigMixin.java | 24 +++++++---- .../client/MinecraftClientMixin.java | 41 ------------------- .../lifecycle/server/ServerMainMixin.java | 40 ------------------ .../main/resources/terra.forge.mixins.json | 4 -- 9 files changed, 27 insertions(+), 151 deletions(-) delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/ChunkRegionAccessor.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/MinecraftServerMixin.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/client/MinecraftClientMixin.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/server/ServerMainMixin.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java index 6f9af2ed8..b1ddda34f 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java @@ -1,10 +1,7 @@ package com.dfsek.terra.fabric.mixin.lifecycle; -import com.dfsek.terra.fabric.util.SeedHack; - import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; import net.minecraft.util.registry.Registry; -import net.minecraft.world.biome.source.util.MultiNoiseUtil; import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import net.minecraft.world.gen.noise.NoiseConfig; @@ -15,6 +12,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.dfsek.terra.fabric.util.SeedHack; + /** * Hack to map noise sampler to seeds diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 22194ac6e..e2aeef71e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -27,9 +27,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.dfsek.terra.forge.data.Codecs; +import com.dfsek.terra.forge.util.LifecycleUtil; @Mod("terra") public class ForgeEntryPoint { + public static final String MODID = "terra"; + private static final Logger logger = LoggerFactory.getLogger(ForgeEntryPoint.class); private static final PlatformImpl TERRA_PLUGIN = new PlatformImpl(); @@ -50,7 +53,8 @@ public class ForgeEntryPoint { modEventBus.addListener(this::commonSetup); } - private void commonSetup(final FMLCommonSetupEvent event) { + private void commonSetup(FMLCommonSetupEvent event) { logger.info("Initializing Terra Forge mod..."); + LifecycleUtil.initialize(); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index 3e3791142..3e15ce880 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -29,7 +29,10 @@ import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; +import net.minecraftforge.common.ForgeConfig.Common; import net.minecraftforge.fml.loading.FMLLoader; +import net.minecraftforge.fml.loading.targets.FMLServerLaunchHandler; +import net.minecraftforge.server.ServerLifecycleHooks; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,18 +61,13 @@ public class PlatformImpl extends AbstractPlatform { private final ItemHandle itemHandle = new FabricItemHandle(); private final WorldHandle worldHandle = new FabricWorldHandle(); private final Lazy dataFolder = Lazy.lazy(() -> new File("./config/Terra")); - private MinecraftServer server; public PlatformImpl() { load(); } - public void setServer(MinecraftServer server) { - this.server = server; - } - public MinecraftServer getServer() { - return server; + return ServerLifecycleHooks.getCurrentServer(); } @Override @@ -78,6 +76,7 @@ public class PlatformImpl extends AbstractPlatform { getRawConfigRegistry().clear(); boolean succeed = getRawConfigRegistry().loadAll(this); + MinecraftServer server = getServer(); if(server != null) { server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/ChunkRegionAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/ChunkRegionAccessor.java deleted file mode 100644 index 58624dfe9..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/ChunkRegionAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.forge.mixin.access; - -import net.minecraft.world.ChunkRegion; -import net.minecraft.world.chunk.Chunk; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.List; - - -@Mixin(ChunkRegion.class) -public interface ChunkRegionAccessor { - @Accessor("chunks") - List getChunks(); -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/MinecraftServerMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/MinecraftServerMixin.java deleted file mode 100644 index a524a9df7..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/MinecraftServerMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.forge.mixin.lifecycle; - -import com.dfsek.terra.forge.ForgeEntryPoint; - -import com.mojang.datafixers.DataFixer; -import net.minecraft.resource.ResourcePackManager; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.SaveLoader; -import net.minecraft.server.WorldGenerationProgressListenerFactory; -import net.minecraft.util.ApiServices; -import net.minecraft.world.level.storage.LevelStorage; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.net.Proxy; - - -@Mixin(MinecraftServer.class) -public class MinecraftServerMixin { - @Inject(method = "(Ljava/lang/Thread;Lnet/minecraft/world/level/storage/LevelStorage$Session;" + - "Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/server/SaveLoader;Ljava/net/Proxy;" + - "Lcom/mojang/datafixers/DataFixer;Lnet/minecraft/util/ApiServices;" + - "Lnet/minecraft/server/WorldGenerationProgressListenerFactory;)V", - at = @At("RETURN")) - private void injectConstructor(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager, - SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices, - WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { - ForgeEntryPoint.getPlatform().setServer((MinecraftServer) (Object) this); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java index 67008fbba..ca1f00a99 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java @@ -2,17 +2,18 @@ package com.dfsek.terra.forge.mixin.lifecycle; import com.dfsek.terra.forge.util.SeedHack; -import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; -import net.minecraft.util.registry.Registry; +import net.minecraft.util.math.random.RandomSplitter; import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; -import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.NoiseHypercube; +import net.minecraft.world.gen.densityfunction.DensityFunction; import net.minecraft.world.gen.noise.NoiseConfig; 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; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.List; /** @@ -22,10 +23,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public class NoiseConfigMixin { @Shadow @Final - private MultiNoiseSampler multiNoiseSampler; + private long legacyWorldSeed; - @Inject(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At("TAIL")) - private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, Registry noiseRegistry, long seed, CallbackInfo ci) { - SeedHack.register(multiNoiseSampler, seed); + @Redirect(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At(value = "NEW", target = "net/minecraft/world/biome/source/util/MultiNoiseUtil$MultiNoiseSampler.")) + private MultiNoiseSampler t(DensityFunction densityFunction, DensityFunction densityFunction2, DensityFunction densityFunction3, + DensityFunction densityFunction4, DensityFunction densityFunction5, DensityFunction densityFunction6, + List list) { + MultiNoiseSampler sampler = new MultiNoiseSampler(densityFunction, densityFunction2, densityFunction3, densityFunction4, + densityFunction5, densityFunction6, list); + SeedHack.register(sampler, legacyWorldSeed); + return null; } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/client/MinecraftClientMixin.java deleted file mode 100644 index ee2e01268..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/client/MinecraftClientMixin.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.mixin.lifecycle.client; - -import com.dfsek.terra.forge.util.LifecycleUtil; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.RunArgs; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - - -@Mixin(MinecraftClient.class) -public class MinecraftClientMixin { - @Inject(method = "", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/util/WindowProvider;createWindow" + - "(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)" + - "Lnet/minecraft/client/util/Window;", - // sorta arbitrary position, after mod init, before window opens - shift = At.Shift.BEFORE)) - public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { - LifecycleUtil.initialize(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/server/ServerMainMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/server/ServerMainMixin.java deleted file mode 100644 index 70d93969e..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/server/ServerMainMixin.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.mixin.lifecycle.server; - -import com.dfsek.terra.forge.util.LifecycleUtil; - -import net.minecraft.server.Main; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - - -@Mixin(Main.class) -public class ServerMainMixin { - @Inject(method = "main([Ljava/lang/String;)V", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/resource/ResourcePackManager;(Lnet/minecraft/resource/ResourceType;" + - "[Lnet/minecraft/resource/ResourcePackProvider;)V") - // after registry manager creation - ) - private static void injectConstructor(String[] args, CallbackInfo ci) { - LifecycleUtil.initialize(); - } -} diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index e1dd26479..77d2c9e44 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -4,7 +4,6 @@ "package": "com.dfsek.terra.forge.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "access.ChunkRegionAccessor", "access.MobSpawnerLogicAccessor", "access.StateAccessor", "access.StructureAccessorAccessor", @@ -36,15 +35,12 @@ "implementations.terra.world.ChunkRegionMixin", "implementations.terra.world.ServerWorldMixin", "lifecycle.DataPackContentsMixin", - "lifecycle.MinecraftServerMixin", "lifecycle.NoiseConfigMixin", "lifecycle.RegistryMixin" ], "client": [ - "lifecycle.client.MinecraftClientMixin" ], "server": [ - "lifecycle.server.ServerMainMixin" ], "injectors": { "defaultRequire": 1 From cce9b69c45aa96f5245d85d28ea1ec6ce8b8b2fa Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 20:05:02 -0700 Subject: [PATCH 157/220] load terra data on RegisterEvent --- .../com/dfsek/terra/forge/ForgeEntryPoint.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index e2aeef71e..64b58c67d 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -19,10 +19,15 @@ package com.dfsek.terra.forge; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.ForgeRegistries.Keys; +import net.minecraftforge.registries.RegisterEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,10 +56,18 @@ public class ForgeEntryPoint { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); modEventBus.addListener(this::commonSetup); + modEventBus.addListener(EventPriority.LOWEST, this::registerBiomes); } private void commonSetup(FMLCommonSetupEvent event) { logger.info("Initializing Terra Forge mod..."); - LifecycleUtil.initialize(); + } + + private void registerBiomes(RegisterEvent event) { + event.register(Keys.BIOMES, helper -> { + logger.info("Loading Terra data..."); + LifecycleUtil.initialize(); + }); + event.register(Keys.BLOCKS, helper -> logger.debug("Block registration detected.")); } } From 14273268c897d8432787d263fd80d50ef11c6edf Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 21:03:30 -0700 Subject: [PATCH 158/220] remove RegistryMixin --- .../dfsek/terra/forge/ForgeEntryPoint.java | 9 ++++----- .../forge/mixin/lifecycle/RegistryMixin.java | 20 ------------------- .../main/resources/terra.forge.mixins.json | 3 +-- 3 files changed, 5 insertions(+), 27 deletions(-) delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 64b58c67d..d00d3622f 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -17,6 +17,8 @@ package com.dfsek.terra.forge; +import com.dfsek.terra.api.util.generic.Lazy; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraftforge.eventbus.api.EventPriority; @@ -47,11 +49,6 @@ public class ForgeEntryPoint { return TERRA_PLUGIN; } - public static void register() { // register the things - Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); - Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); - } - public ForgeEntryPoint() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); @@ -60,6 +57,8 @@ public class ForgeEntryPoint { } private void commonSetup(FMLCommonSetupEvent event) { + Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); + Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); logger.info("Initializing Terra Forge mod..."); } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java deleted file mode 100644 index 18633dc0f..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.forge.mixin.lifecycle; - - -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.dfsek.terra.forge.ForgeEntryPoint; - - -// Register Terra things to the builtin registries. -@Mixin(Registry.class) -public class RegistryMixin { - @Inject(method = "", at = @At("RETURN")) - private static void registerTerraGenerators(CallbackInfo ci) { - ForgeEntryPoint.register(); - } -} diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index 77d2c9e44..e68b6351b 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -35,8 +35,7 @@ "implementations.terra.world.ChunkRegionMixin", "implementations.terra.world.ServerWorldMixin", "lifecycle.DataPackContentsMixin", - "lifecycle.NoiseConfigMixin", - "lifecycle.RegistryMixin" + "lifecycle.NoiseConfigMixin" ], "client": [ ], From a47541cfeb9ba5fb234379ff735053f308bb26f0 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 21:34:52 -0700 Subject: [PATCH 159/220] use annotation event subscriptions --- .../com/dfsek/terra/forge/ForgeEntryPoint.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index d00d3622f..36dc78fe4 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -25,6 +25,8 @@ import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.ForgeRegistries; @@ -37,6 +39,7 @@ import com.dfsek.terra.forge.data.Codecs; import com.dfsek.terra.forge.util.LifecycleUtil; @Mod("terra") +@EventBusSubscriber(bus = Bus.MOD) public class ForgeEntryPoint { public static final String MODID = "terra"; @@ -50,19 +53,15 @@ public class ForgeEntryPoint { } public ForgeEntryPoint() { - IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); - - modEventBus.addListener(this::commonSetup); - modEventBus.addListener(EventPriority.LOWEST, this::registerBiomes); - } - - private void commonSetup(FMLCommonSetupEvent event) { Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); - logger.info("Initializing Terra Forge mod..."); + IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); + + modEventBus.register(this); } - private void registerBiomes(RegisterEvent event) { + @SubscribeEvent(priority = EventPriority.LOWEST) + public void registerBiomes(RegisterEvent event) { event.register(Keys.BIOMES, helper -> { logger.info("Loading Terra data..."); LifecycleUtil.initialize(); From c120ab76d06f9a9d74e9502355f240c73900902f Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 21:35:32 -0700 Subject: [PATCH 160/220] Revert "remove RegistryMixin" This reverts commit 14273268 --- .../dfsek/terra/forge/ForgeEntryPoint.java | 7 +++++-- .../forge/mixin/lifecycle/RegistryMixin.java | 20 +++++++++++++++++++ .../main/resources/terra.forge.mixins.json | 3 ++- 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 36dc78fe4..692bc838d 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -17,8 +17,6 @@ package com.dfsek.terra.forge; -import com.dfsek.terra.api.util.generic.Lazy; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraftforge.eventbus.api.EventPriority; @@ -52,6 +50,11 @@ public class ForgeEntryPoint { return TERRA_PLUGIN; } + public static void register() { // register the things + Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); + Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); + } + public ForgeEntryPoint() { Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java new file mode 100644 index 000000000..18633dc0f --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.forge.mixin.lifecycle; + + +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.dfsek.terra.forge.ForgeEntryPoint; + + +// Register Terra things to the builtin registries. +@Mixin(Registry.class) +public class RegistryMixin { + @Inject(method = "", at = @At("RETURN")) + private static void registerTerraGenerators(CallbackInfo ci) { + ForgeEntryPoint.register(); + } +} diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index e68b6351b..77d2c9e44 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -35,7 +35,8 @@ "implementations.terra.world.ChunkRegionMixin", "implementations.terra.world.ServerWorldMixin", "lifecycle.DataPackContentsMixin", - "lifecycle.NoiseConfigMixin" + "lifecycle.NoiseConfigMixin", + "lifecycle.RegistryMixin" ], "client": [ ], From 13497a02a4f37a3743460689a211c28541e1a2e7 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 21:46:06 -0700 Subject: [PATCH 161/220] register stuff with events --- .../dfsek/terra/forge/ForgeEntryPoint.java | 10 ++-------- .../forge/mixin/lifecycle/RegistryMixin.java | 20 ------------------- .../main/resources/terra.forge.mixins.json | 3 +-- 3 files changed, 3 insertions(+), 30 deletions(-) delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 692bc838d..305dee743 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -50,16 +50,8 @@ public class ForgeEntryPoint { return TERRA_PLUGIN; } - public static void register() { // register the things - Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); - Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); - } - public ForgeEntryPoint() { - Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); - Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); - modEventBus.register(this); } @@ -69,6 +61,8 @@ public class ForgeEntryPoint { logger.info("Loading Terra data..."); LifecycleUtil.initialize(); }); + event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER)); + event.register(Registry.BIOME_SOURCE_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE)); event.register(Keys.BLOCKS, helper -> logger.debug("Block registration detected.")); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java deleted file mode 100644 index 18633dc0f..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/RegistryMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.forge.mixin.lifecycle; - - -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.dfsek.terra.forge.ForgeEntryPoint; - - -// Register Terra things to the builtin registries. -@Mixin(Registry.class) -public class RegistryMixin { - @Inject(method = "", at = @At("RETURN")) - private static void registerTerraGenerators(CallbackInfo ci) { - ForgeEntryPoint.register(); - } -} diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index 77d2c9e44..e68b6351b 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -35,8 +35,7 @@ "implementations.terra.world.ChunkRegionMixin", "implementations.terra.world.ServerWorldMixin", "lifecycle.DataPackContentsMixin", - "lifecycle.NoiseConfigMixin", - "lifecycle.RegistryMixin" + "lifecycle.NoiseConfigMixin" ], "client": [ ], From a0225d6ece8217cf5bee8cebbf840faef6c5205b Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 22:59:59 -0700 Subject: [PATCH 162/220] legitimately evil hack to fix forge weirdness --- .../dfsek/terra/forge/AwfulForgeHacks.java | 80 +++++++++++++++++++ .../dfsek/terra/forge/ForgeEntryPoint.java | 8 +- 2 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java new file mode 100644 index 000000000..2a362dadf --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java @@ -0,0 +1,80 @@ +package com.dfsek.terra.forge; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.FileVisitOption; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.jar.JarFile; +import java.util.stream.Stream; + + +/** + * Forge is really wacky and screws with class resolution in the addon loader. Loading every single Terra class *manually* on startup + * fixes it. If you know of a better way to fix this, PLEASE let us know. + */ +public final class AwfulForgeHacks { + private static final Logger LOGGER = LoggerFactory.getLogger(AwfulForgeHacks.class); + + /** + * Forge tampers with code source to make the *normal* way of getting the current JAR file useless, so this awful hack is + * needed. + * + * + * Class.class.getProtectionDomain() + * .getCodeSource() + * .getLocation() + * .toURI() + * .getPath() + * + * + */ + public static JarFile getTerraJar() throws IOException { + LOGGER.info("Scanning for Terra JAR..."); + return Files.walk(Path.of("./", "mods"), 1, FileVisitOption.FOLLOW_LINKS) + .filter(it -> it.getFileName().toString().endsWith(".jar")) + .peek(path -> LOGGER.info("Found mod: {}", path)) + .map(Path::toFile) + .flatMap(path -> { + try { + return Stream.of(new JarFile(path)); + } catch(IOException e) { + LOGGER.error("Malformed mod JAR: {}: {}", path, e); + return Stream.of(); + } + }) + .filter(jar -> jar + .stream() + .anyMatch(entry -> entry + .getName() + .equals(ForgeEntryPoint.class.getName().replace('.', '/') + ".class"))) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Could not find Terra JAR")); + + } + + public static void loadAllTerraClasses() { + + try(JarFile jar = getTerraJar()) { + jar.stream() + .forEach(jarEntry -> { + if(jarEntry.getName().startsWith("com/dfsek/terra/forge/mixin")) { + return; + } + if(jarEntry.getName().endsWith(".class")) { + String name = jarEntry.getName().replace('/', '.'); + name = name.substring(0, name.length() - 6); + try { + Class.forName(name); + } catch(ClassNotFoundException | NoClassDefFoundError e) { + LOGGER.warn("Failed to load class {}: {}", name, e); + } + } + }); + } catch(IOException e) { + throw new IllegalStateException("Could not load all Terra classes", e); + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 305dee743..1f20dd2e3 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -39,12 +39,16 @@ import com.dfsek.terra.forge.util.LifecycleUtil; @Mod("terra") @EventBusSubscriber(bus = Bus.MOD) public class ForgeEntryPoint { + static { + AwfulForgeHacks.loadAllTerraClasses(); + TERRA_PLUGIN = new PlatformImpl(); + } + public static final String MODID = "terra"; private static final Logger logger = LoggerFactory.getLogger(ForgeEntryPoint.class); - private static final PlatformImpl TERRA_PLUGIN = new PlatformImpl(); - + private static final PlatformImpl TERRA_PLUGIN; public static PlatformImpl getPlatform() { return TERRA_PLUGIN; From e1656bac205d665df610b4bff5db4dd8699b75f9 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 23:25:03 -0700 Subject: [PATCH 163/220] create registry sanity check --- .../dfsek/terra/forge/AwfulForgeHacks.java | 69 +++++++++++++------ .../dfsek/terra/forge/ForgeEntryPoint.java | 20 ++++-- .../dfsek/terra/forge/util/LifecycleUtil.java | 22 +++--- 3 files changed, 73 insertions(+), 38 deletions(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java index 2a362dadf..5565fd1ba 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java @@ -7,6 +7,8 @@ import java.io.IOException; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; import java.util.jar.JarFile; import java.util.stream.Stream; @@ -23,13 +25,12 @@ public final class AwfulForgeHacks { * needed. * * - * Class.class.getProtectionDomain() - * .getCodeSource() - * .getLocation() - * .toURI() - * .getPath() + * Class.class.getProtectionDomain() + * .getCodeSource() + * .getLocation() + * .toURI() + * .getPath() * - * */ public static JarFile getTerraJar() throws IOException { LOGGER.info("Scanning for Terra JAR..."); @@ -52,29 +53,55 @@ public final class AwfulForgeHacks { .equals(ForgeEntryPoint.class.getName().replace('.', '/') + ".class"))) .findFirst() .orElseThrow(() -> new IllegalStateException("Could not find Terra JAR")); - + } public static void loadAllTerraClasses() { try(JarFile jar = getTerraJar()) { jar.stream() - .forEach(jarEntry -> { - if(jarEntry.getName().startsWith("com/dfsek/terra/forge/mixin")) { - return; - } - if(jarEntry.getName().endsWith(".class")) { - String name = jarEntry.getName().replace('/', '.'); - name = name.substring(0, name.length() - 6); - try { - Class.forName(name); - } catch(ClassNotFoundException | NoClassDefFoundError e) { - LOGGER.warn("Failed to load class {}: {}", name, e); - } - } - }); + .forEach(jarEntry -> { + if(jarEntry.getName().startsWith("com/dfsek/terra/forge/mixin")) { + return; + } + if(jarEntry.getName().endsWith(".class")) { + String name = jarEntry.getName().replace('/', '.'); + name = name.substring(0, name.length() - 6); + try { + Class.forName(name); + } catch(ClassNotFoundException | NoClassDefFoundError e) { + LOGGER.warn("Failed to load class {}: {}", name, e); + } + } + }); } catch(IOException e) { throw new IllegalStateException("Could not load all Terra classes", e); } } + + public enum RegistryStep { + BLOCK, + BIOME, + WORLD_TYPE, + DONE; + } + + + public static class RegistrySanityCheck { + private final AtomicReference step = new AtomicReference<>(RegistryStep.BLOCK); + + public void progress(RegistryStep expected, Runnable action) { + step.getAndUpdate(s -> { + if(s != expected) { + LOGGER.error("Registry sanity check failed, expected to find {}, found {}", expected, step); + } + action.run(); + RegistryStep[] registrySteps = RegistryStep.values(); + if(s.ordinal() < registrySteps.length - 1) { + return registrySteps[s.ordinal() + 1]; + } + return s; + }); + } + } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 1f20dd2e3..2e963734f 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -17,6 +17,9 @@ package com.dfsek.terra.forge; +import com.dfsek.terra.forge.AwfulForgeHacks.RegistrySanityCheck; +import com.dfsek.terra.forge.AwfulForgeHacks.RegistryStep; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraftforge.eventbus.api.EventPriority; @@ -25,9 +28,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries.Keys; import net.minecraftforge.registries.RegisterEvent; import org.slf4j.Logger; @@ -36,9 +37,14 @@ import org.slf4j.LoggerFactory; import com.dfsek.terra.forge.data.Codecs; import com.dfsek.terra.forge.util.LifecycleUtil; +import java.util.concurrent.atomic.AtomicReference; + + @Mod("terra") @EventBusSubscriber(bus = Bus.MOD) public class ForgeEntryPoint { + private final RegistrySanityCheck sanityCheck = new RegistrySanityCheck(); + static { AwfulForgeHacks.loadAllTerraClasses(); TERRA_PLUGIN = new PlatformImpl(); @@ -61,12 +67,12 @@ public class ForgeEntryPoint { @SubscribeEvent(priority = EventPriority.LOWEST) public void registerBiomes(RegisterEvent event) { - event.register(Keys.BIOMES, helper -> { - logger.info("Loading Terra data..."); - LifecycleUtil.initialize(); - }); + event.register(Keys.BLOCKS, helper -> sanityCheck.progress(RegistryStep.BLOCK, () -> logger.debug("Block registration detected."))); + event.register(Keys.BIOMES, helper -> sanityCheck.progress(RegistryStep.BIOME, LifecycleUtil::initialize)); + event.register(Registry.WORLD_PRESET_KEY, helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> LifecycleUtil.registerWorldTypes(helper))); + + event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER)); event.register(Registry.BIOME_SOURCE_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE)); - event.register(Keys.BLOCKS, helper -> logger.debug("Block registration detected.")); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java index 560a200bc..7ff4b1a1b 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java @@ -21,6 +21,7 @@ import net.minecraft.world.gen.WorldPreset; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import net.minecraft.world.gen.chunk.NoiseChunkGenerator; +import net.minecraftforge.registries.RegisterEvent.RegisterHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,16 +39,17 @@ public class LifecycleUtil { ForgeEntryPoint.getPlatform().getEventManager().callEvent( new PlatformInitializationEvent()); BiomeUtil.registerBiomes(); - - + } + + public static void registerWorldTypes(RegisterHelper helper) { LOGGER.info("Registering Terra world types..."); - + Registry dimensionTypeRegistry = BuiltinRegistries.DIMENSION_TYPE; Registry chunkGeneratorSettingsRegistry = BuiltinRegistries.CHUNK_GENERATOR_SETTINGS; Registry structureSetRegistry = BuiltinRegistries.STRUCTURE_SET; Registry noiseParametersRegistry = BuiltinRegistries.NOISE_PARAMETERS; Registry biomeRegistry = BuiltinRegistries.BIOME; - + RegistryEntry theNetherDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_NETHER); RegistryEntry netherChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.NETHER); @@ -64,9 +66,9 @@ public class LifecycleUtil { new NoiseChunkGenerator(structureSetRegistry, noiseParametersRegistry, new TheEndBiomeSource(biomeRegistry), endChunkGeneratorSettings)); - + RegistryEntry overworldDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.OVERWORLD); - + RegistryEntry overworld = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.OVERWORLD); ForgeEntryPoint .getPlatform() @@ -74,12 +76,12 @@ public class LifecycleUtil { .forEach((id, pack) -> { Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( Locale.ROOT)); - + PRESETS.add(generatorID); - + TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); ChunkGenerator generator = new FabricChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); - + DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); WorldPreset preset = new WorldPreset( Map.of( @@ -88,7 +90,7 @@ public class LifecycleUtil { DimensionOptions.END, endDimensionOptions ) ); - BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, generatorID, preset); + helper.register(generatorID, preset); LOGGER.info("Registered world type \"{}\"", generatorID); } ); From 7c2982aa0a2bfed411dc08f8abb5db0edf8fc8b9 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 20 Jun 2022 23:33:14 -0700 Subject: [PATCH 164/220] use registerhelper to register biomes --- .../dfsek/terra/forge/ForgeEntryPoint.java | 2 +- .../com/dfsek/terra/forge/PlatformImpl.java | 2 +- .../com/dfsek/terra/forge/util/BiomeUtil.java | 25 ++++++++----------- .../dfsek/terra/forge/util/LifecycleUtil.java | 4 +-- .../terra/forge/util/ProtoPlatformBiome.java | 6 +++++ 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 2e963734f..2c7da3437 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -68,7 +68,7 @@ public class ForgeEntryPoint { @SubscribeEvent(priority = EventPriority.LOWEST) public void registerBiomes(RegisterEvent event) { event.register(Keys.BLOCKS, helper -> sanityCheck.progress(RegistryStep.BLOCK, () -> logger.debug("Block registration detected."))); - event.register(Keys.BIOMES, helper -> sanityCheck.progress(RegistryStep.BIOME, LifecycleUtil::initialize)); + event.register(Keys.BIOMES, helper -> sanityCheck.progress(RegistryStep.BIOME, () -> LifecycleUtil.initialize(helper))); event.register(Registry.WORLD_PRESET_KEY, helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> LifecycleUtil.registerWorldTypes(helper))); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index 3e15ce880..0e5c4119e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -83,7 +83,7 @@ public class PlatformImpl extends AbstractPlatform { LOGGER.warn("Failed to execute reload", throwable); return null; }).join(); - BiomeUtil.registerBiomes(); + //BiomeUtil.registerBiomes(); server.getWorlds().forEach(world -> { if(world.getChunkManager().getChunkGenerator() instanceof FabricChunkGeneratorWrapper chunkGeneratorWrapper) { getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java index 9e4c1e257..5612372b4 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java @@ -16,6 +16,8 @@ import net.minecraft.world.biome.Biome.Builder; import net.minecraft.world.biome.BiomeEffects; import net.minecraft.world.biome.GenerationSettings; import net.minecraft.world.gen.feature.ConfiguredFeature; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegisterEvent.RegisterHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,11 +39,11 @@ public final class BiomeUtil { .toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT); } - public static void registerBiomes() { + public static void registerBiomes(RegisterHelper helper) { logger.info("Registering biomes..."); ForgeEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. pack.getCheckedRegistry(Biome.class) - .forEach((id, biome) -> registerBiome(biome, pack, id)); + .forEach((id, biome) -> registerBiome(biome, pack, id, helper)); }); registerFlora(BuiltinRegistries.BIOME); logger.info("Terra biomes registered."); @@ -54,27 +56,22 @@ public final class BiomeUtil { * @param pack The ConfigPack this biome belongs to. */ private static void registerBiome(Biome biome, ConfigPack pack, - com.dfsek.terra.api.registry.key.RegistryKey id) { - Registry registry = BuiltinRegistries.BIOME; - RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(registry); + com.dfsek.terra.api.registry.key.RegistryKey id, RegisterHelper helper) { + RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(ForgeRegistries.BIOMES); if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); } else { - net.minecraft.world.biome.Biome minecraftBiome = createBiome(biome, registry.get(vanilla)); + net.minecraft.world.biome.Biome minecraftBiome = createBiome(biome, ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value()); Identifier identifier = new Identifier("terra", createBiomeID(pack, id)); - if(registry.containsId(identifier)) { - ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(FabricUtil.getEntry(registry, identifier) - .orElseThrow() - .getKey() - .orElseThrow()); + if(ForgeRegistries.BIOMES.containsKey(identifier)) { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow()); } else { - ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry, - registerKey(identifier).getValue(), - minecraftBiome).getKey().orElseThrow()); + helper.register(registerKey(identifier).getValue(), minecraftBiome); + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow()); } TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java index 7ff4b1a1b..209d95057 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java @@ -35,10 +35,10 @@ public class LifecycleUtil { private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleUtil.class); private static final List PRESETS = new ArrayList<>(); - public static void initialize() { + public static void initialize(RegisterHelper helper) { ForgeEntryPoint.getPlatform().getEventManager().callEvent( new PlatformInitializationEvent()); - BiomeUtil.registerBiomes(); + BiomeUtil.registerBiomes(helper); } public static void registerWorldTypes(RegisterHelper helper) { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java index b67932f0b..49fbbb211 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java @@ -26,6 +26,8 @@ import java.util.Objects; import com.dfsek.terra.api.world.biome.PlatformBiome; +import net.minecraftforge.registries.IForgeRegistry; + public class ProtoPlatformBiome implements PlatformBiome { private final Identifier identifier; @@ -40,6 +42,10 @@ public class ProtoPlatformBiome implements PlatformBiome { return FabricUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow(); } + public RegistryKey get(IForgeRegistry registry) { + return registry.getHolder(identifier).orElseThrow().getKey().orElseThrow(); + } + @Override public Object getHandle() { return identifier; From 111eb6b5931cccce0f854c020715866a677f0abf Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 07:22:07 -0700 Subject: [PATCH 165/220] fix NoiseConfigMixin --- .../terra/forge/mixin/lifecycle/NoiseConfigMixin.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java index ca1f00a99..7360045af 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java @@ -2,15 +2,20 @@ package com.dfsek.terra.forge.mixin.lifecycle; import com.dfsek.terra.forge.util.SeedHack; +import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; +import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters; import net.minecraft.util.math.random.RandomSplitter; +import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; import net.minecraft.world.biome.source.util.MultiNoiseUtil.NoiseHypercube; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import net.minecraft.world.gen.densityfunction.DensityFunction; import net.minecraft.world.gen.noise.NoiseConfig; 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.Redirect; import java.util.List; @@ -25,13 +30,13 @@ public class NoiseConfigMixin { @Final private long legacyWorldSeed; - @Redirect(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At(value = "NEW", target = "net/minecraft/world/biome/source/util/MultiNoiseUtil$MultiNoiseSampler.")) + @Redirect(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At(value = "NEW", target = "(Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Ljava/util/List;)Lnet/minecraft/world/biome/source/util/MultiNoiseUtil$MultiNoiseSampler;")) private MultiNoiseSampler t(DensityFunction densityFunction, DensityFunction densityFunction2, DensityFunction densityFunction3, DensityFunction densityFunction4, DensityFunction densityFunction5, DensityFunction densityFunction6, List list) { MultiNoiseSampler sampler = new MultiNoiseSampler(densityFunction, densityFunction2, densityFunction3, densityFunction4, densityFunction5, densityFunction6, list); SeedHack.register(sampler, legacyWorldSeed); - return null; + return sampler; } } From 546431bbef8fc8a1280910e266a33186fef9632b Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 09:59:16 -0700 Subject: [PATCH 166/220] clean up adapter --- .../FabricChunkGeneratorWrapper.java | 6 +- .../terra/entity/EntityMixin.java | 4 +- .../dfsek/terra/forge/util/FabricAdapter.java | 185 ------------------ .../dfsek/terra/forge/util/ForgeAdapter.java | 56 ++++++ 4 files changed, 61 insertions(+), 190 deletions(-) delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricAdapter.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeAdapter.java diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java index e31bb40b2..f58b12deb 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java @@ -64,7 +64,7 @@ import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; import com.dfsek.terra.forge.data.Codecs; import com.dfsek.terra.forge.mixin.access.StructureAccessorAccessor; -import com.dfsek.terra.forge.util.FabricAdapter; +import com.dfsek.terra.forge.util.ForgeAdapter; public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { @@ -185,7 +185,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public int getHeight(int x, int z, Type heightmap, HeightLimitView height, NoiseConfig noiseConfig) { - WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); + WorldProperties properties = ForgeAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); BiomeProvider biomeProvider = pack.getBiomeProvider(); int min = height.getBottomY(); for(int y = height.getTopY() - 1; y >= min; y--) { @@ -199,7 +199,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height, NoiseConfig noiseConfig) { BlockState[] array = new BlockState[height.getHeight()]; - WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); + WorldProperties properties = ForgeAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); BiomeProvider biomeProvider = pack.getBiomeProvider(); for(int y = height.getTopY() - 1; y >= height.getBottomY(); y--) { array[y - height.getBottomY()] = (BlockState) delegate.getBlock(properties, x, y, z, biomeProvider); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java index 96e7be2d5..a300693b7 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java @@ -17,7 +17,7 @@ package com.dfsek.terra.forge.mixin.implementations.terra.entity; -import com.dfsek.terra.forge.util.FabricAdapter; +import com.dfsek.terra.forge.util.ForgeAdapter; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.mixin.Implements; @@ -42,7 +42,7 @@ public abstract class EntityMixin { public abstract void teleport(double destX, double destY, double destZ); public Vector3 terra$position() { - return FabricAdapter.adapt(blockPos); + return ForgeAdapter.adapt(blockPos); } public void terra$position(Vector3 location) { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricAdapter.java deleted file mode 100644 index b7bc9f010..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricAdapter.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.util; - -import net.minecraft.block.enums.BlockHalf; -import net.minecraft.block.enums.WallShape; -import net.minecraft.block.enums.WireConnection; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.HeightLimitView; - -import com.dfsek.terra.api.block.state.properties.enums.Axis; -import com.dfsek.terra.api.block.state.properties.enums.Half; -import com.dfsek.terra.api.block.state.properties.enums.RailShape; -import com.dfsek.terra.api.block.state.properties.enums.RedstoneConnection; -import com.dfsek.terra.api.block.state.properties.enums.WallHeight; -import com.dfsek.terra.api.util.vector.Vector3; -import com.dfsek.terra.api.world.info.WorldProperties; - - -public final class FabricAdapter { - public static BlockPos adapt(Vector3 v) { - return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - } - - public static Vector3 adapt(BlockPos pos) { - return Vector3.of(pos.getX(), pos.getY(), pos.getZ()); - } - - public static Direction adapt(com.dfsek.terra.api.block.state.properties.enums.Direction direction) { - return switch(direction) { - case SOUTH -> Direction.SOUTH; - case NORTH -> Direction.NORTH; - case WEST -> Direction.WEST; - case EAST -> Direction.EAST; - case UP -> Direction.UP; - case DOWN -> Direction.DOWN; - }; - } - - public static WorldProperties adapt(HeightLimitView height, long seed) { - return new WorldProperties() { - @Override - public long getSeed() { - return seed; - } - - @Override - public int getMaxHeight() { - return height.getTopY(); - } - - @Override - public int getMinHeight() { - return height.getBottomY(); - } - - @Override - public Object getHandle() { - return height; - } - }; - } - - public static com.dfsek.terra.api.block.state.properties.enums.Direction adapt(Direction direction) { - return switch(direction) { - case SOUTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.SOUTH; - case NORTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.NORTH; - case WEST -> com.dfsek.terra.api.block.state.properties.enums.Direction.WEST; - case EAST -> com.dfsek.terra.api.block.state.properties.enums.Direction.EAST; - case UP -> com.dfsek.terra.api.block.state.properties.enums.Direction.UP; - case DOWN -> com.dfsek.terra.api.block.state.properties.enums.Direction.DOWN; - }; - } - - public static WallHeight adapt(WallShape shape) { - return switch(shape) { - case LOW -> WallHeight.LOW; - case NONE -> WallHeight.NONE; - case TALL -> WallHeight.TALL; - }; - } - - public static WallShape adapt(WallHeight shape) { - return switch(shape) { - case LOW -> WallShape.LOW; - case NONE -> WallShape.NONE; - case TALL -> WallShape.TALL; - }; - } - - public static RedstoneConnection adapt(WireConnection connection) { - return switch(connection) { - case NONE -> RedstoneConnection.NONE; - case UP -> RedstoneConnection.UP; - case SIDE -> RedstoneConnection.SIDE; - }; - } - - public static WireConnection adapt(RedstoneConnection connection) { - return switch(connection) { - case NONE -> WireConnection.NONE; - case UP -> WireConnection.UP; - case SIDE -> WireConnection.SIDE; - }; - } - - - public static Half adapt(BlockHalf half) { - return switch(half) { - case BOTTOM -> Half.BOTTOM; - case TOP -> Half.TOP; - }; - } - - public static BlockHalf adapt(Half half) { - return switch(half) { - case TOP -> BlockHalf.TOP; - case BOTTOM -> BlockHalf.BOTTOM; - default -> throw new IllegalStateException(); - }; - } - - public static RailShape adapt(net.minecraft.block.enums.RailShape railShape) { - return switch(railShape) { - case EAST_WEST -> RailShape.EAST_WEST; - case NORTH_EAST -> RailShape.NORTH_EAST; - case NORTH_WEST -> RailShape.NORTH_WEST; - case SOUTH_EAST -> RailShape.SOUTH_EAST; - case SOUTH_WEST -> RailShape.SOUTH_WEST; - case NORTH_SOUTH -> RailShape.NORTH_SOUTH; - case ASCENDING_EAST -> RailShape.ASCENDING_EAST; - case ASCENDING_NORTH -> RailShape.ASCENDING_NORTH; - case ASCENDING_SOUTH -> RailShape.ASCENDING_SOUTH; - case ASCENDING_WEST -> RailShape.ASCENDING_WEST; - }; - } - - public static net.minecraft.block.enums.RailShape adapt(RailShape railShape) { - return switch(railShape) { - case EAST_WEST -> net.minecraft.block.enums.RailShape.EAST_WEST; - case NORTH_EAST -> net.minecraft.block.enums.RailShape.NORTH_EAST; - case NORTH_WEST -> net.minecraft.block.enums.RailShape.NORTH_WEST; - case SOUTH_EAST -> net.minecraft.block.enums.RailShape.SOUTH_EAST; - case SOUTH_WEST -> net.minecraft.block.enums.RailShape.SOUTH_WEST; - case NORTH_SOUTH -> net.minecraft.block.enums.RailShape.NORTH_SOUTH; - case ASCENDING_EAST -> net.minecraft.block.enums.RailShape.ASCENDING_EAST; - case ASCENDING_NORTH -> net.minecraft.block.enums.RailShape.ASCENDING_NORTH; - case ASCENDING_SOUTH -> net.minecraft.block.enums.RailShape.ASCENDING_SOUTH; - case ASCENDING_WEST -> net.minecraft.block.enums.RailShape.ASCENDING_WEST; - }; - } - - - public static Axis adapt(Direction.Axis axis) { - return switch(axis) { - case X -> Axis.X; - case Y -> Axis.Y; - case Z -> Axis.Z; - }; - } - - public static Direction.Axis adapt(Axis axis) { - return switch(axis) { - case Z -> Direction.Axis.Z; - case Y -> Direction.Axis.Y; - case X -> Direction.Axis.X; - }; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeAdapter.java new file mode 100644 index 000000000..469b80349 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeAdapter.java @@ -0,0 +1,56 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.forge.util; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.HeightLimitView; + +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.info.WorldProperties; + + +public final class ForgeAdapter { + + public static Vector3 adapt(BlockPos pos) { + return Vector3.of(pos.getX(), pos.getY(), pos.getZ()); + } + + public static WorldProperties adapt(HeightLimitView height, long seed) { + return new WorldProperties() { + @Override + public long getSeed() { + return seed; + } + + @Override + public int getMaxHeight() { + return height.getTopY(); + } + + @Override + public int getMinHeight() { + return height.getBottomY(); + } + + @Override + public Object getHandle() { + return height; + } + }; + } +} From 0c02e4cb9a32ee4d79ef7cd614ca4666f2342e40 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 09:59:54 -0700 Subject: [PATCH 167/220] rename architectury implementation util class --- .../mixin/implementations/terra/world/ChunkRegionMixin.java | 4 ++-- .../mixin/implementations/terra/world/ServerWorldMixin.java | 4 ++-- .../terra/forge/util/{FabricUtil.java => ForgeUtil.java} | 6 ++---- .../java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java | 2 +- .../src/main/java/com/dfsek/terra/forge/util/TagUtil.java | 6 +++--- 5 files changed, 10 insertions(+), 12 deletions(-) rename platforms/forge/src/main/java/com/dfsek/terra/forge/util/{FabricUtil.java => ForgeUtil.java} (94%) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java index 6ba8768ab..d766b82e2 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -48,7 +48,7 @@ import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.forge.util.FabricUtil; +import com.dfsek.terra.forge.util.ForgeUtil; @Mixin(ChunkRegion.class) @@ -109,7 +109,7 @@ public abstract class ChunkRegionMixin { } public BlockEntity terraWorld$getBlockEntity(int x, int y, int z) { - return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); + return ForgeUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); } public int terraWorld$getMinHeight() { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java index fc9158d4c..bec9c2f36 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java @@ -35,7 +35,7 @@ import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.Chunk; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.forge.util.FabricUtil; +import com.dfsek.terra.forge.util.ForgeUtil; @Mixin(net.minecraft.server.world.ServerWorld.class) @@ -73,7 +73,7 @@ public abstract class ServerWorldMixin { } public BlockEntity terra$getBlockEntity(int x, int y, int z) { - return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); + return ForgeUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); } public int terra$getMinHeight() { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeUtil.java similarity index 94% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricUtil.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeUtil.java index 8f854186f..cb577de6f 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/FabricUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeUtil.java @@ -25,8 +25,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.WorldAccess; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.Optional; @@ -36,8 +34,8 @@ import com.dfsek.terra.api.block.entity.MobSpawner; import com.dfsek.terra.api.block.entity.Sign; -public final class FabricUtil { - private FabricUtil() { +public final class ForgeUtil { + private ForgeUtil() { } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java index 49fbbb211..e06ebf0f8 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java @@ -39,7 +39,7 @@ public class ProtoPlatformBiome implements PlatformBiome { } public RegistryKey get(Registry registry) { - return FabricUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow(); + return ForgeUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow(); } public RegistryKey get(IForgeRegistry registry) { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java index 27b33a210..4486aad0b 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java @@ -38,7 +38,7 @@ public final class TagUtil { LifecycleUtil .getPresets() - .forEach(id -> FabricUtil + .forEach(id -> ForgeUtil .getEntry(registry, id) .ifPresentOrElse( preset -> collect @@ -57,11 +57,11 @@ public final class TagUtil { BiomeUtil .getTerraBiomeMap() .forEach((vb, terraBiomes) -> - FabricUtil + ForgeUtil .getEntry(registry, vb) .ifPresentOrElse( vanilla -> terraBiomes - .forEach(tb -> FabricUtil + .forEach(tb -> ForgeUtil .getEntry(registry, tb) .ifPresentOrElse( terra -> { From aeb2da4ede8ad21e1377c94bc534806f37e2ab56 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 10:25:23 -0700 Subject: [PATCH 168/220] refactor chunk generator wrapper name --- .../java/com/dfsek/terra/forge/PlatformImpl.java | 7 ++----- .../java/com/dfsek/terra/forge/data/Codecs.java | 14 +++++++------- ...rapper.java => ForgeChunkGeneratorWrapper.java} | 8 ++++---- .../forge/mixin/fix/NetherFossilOptimization.java | 4 ++-- .../terra/world/ChunkRegionMixin.java | 4 ++-- .../terra/world/ServerWorldMixin.java | 10 +++++----- .../com/dfsek/terra/forge/util/LifecycleUtil.java | 4 ++-- 7 files changed, 24 insertions(+), 27 deletions(-) rename platforms/forge/src/main/java/com/dfsek/terra/forge/generation/{FabricChunkGeneratorWrapper.java => ForgeChunkGeneratorWrapper.java} (96%) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index 0e5c4119e..ca0d34af8 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -29,9 +29,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; -import net.minecraftforge.common.ForgeConfig.Common; import net.minecraftforge.fml.loading.FMLLoader; -import net.minecraftforge.fml.loading.targets.FMLServerLaunchHandler; import net.minecraftforge.server.ServerLifecycleHooks; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -49,10 +47,9 @@ import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.api.util.generic.Lazy; import com.dfsek.terra.api.world.biome.PlatformBiome; -import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; import com.dfsek.terra.forge.handle.FabricItemHandle; import com.dfsek.terra.forge.handle.FabricWorldHandle; -import com.dfsek.terra.forge.util.BiomeUtil; import com.dfsek.terra.forge.util.ProtoPlatformBiome; @@ -85,7 +82,7 @@ public class PlatformImpl extends AbstractPlatform { }).join(); //BiomeUtil.registerBiomes(); server.getWorlds().forEach(world -> { - if(world.getChunkManager().getChunkGenerator() instanceof FabricChunkGeneratorWrapper chunkGeneratorWrapper) { + if(world.getChunkManager().getChunkGenerator() instanceof ForgeChunkGeneratorWrapper chunkGeneratorWrapper) { getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { chunkGeneratorWrapper.setPack(pack); LOGGER.info("Replaced pack in chunk generator for world {}", world); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java index 95bf25e1a..d93e176e7 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java @@ -3,7 +3,7 @@ package com.dfsek.terra.forge.data; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.registry.key.RegistryKey; import com.dfsek.terra.forge.ForgeEntryPoint; -import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; import com.dfsek.terra.forge.generation.TerraBiomeSource; import com.mojang.serialization.Codec; @@ -44,22 +44,22 @@ public final class Codecs { .forGetter(TerraBiomeSource::getPack)) .apply(instance, instance.stable(TerraBiomeSource::new))); - public static final Codec FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder + public static final Codec FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder .create( instance -> instance.group( RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY) .fieldOf("structure_registry") .stable() - .forGetter(FabricChunkGeneratorWrapper::getNoiseRegistry), + .forGetter(ForgeChunkGeneratorWrapper::getNoiseRegistry), TERRA_BIOME_SOURCE.fieldOf("biome_source") .stable() - .forGetter(FabricChunkGeneratorWrapper::getBiomeSource), + .forGetter(ForgeChunkGeneratorWrapper::getBiomeSource), CONFIG_PACK.fieldOf("pack") .stable() - .forGetter(FabricChunkGeneratorWrapper::getPack), + .forGetter(ForgeChunkGeneratorWrapper::getPack), ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings") .stable() - .forGetter(FabricChunkGeneratorWrapper::getSettings) - ).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new)) + .forGetter(ForgeChunkGeneratorWrapper::getSettings) + ).apply(instance, instance.stable(ForgeChunkGeneratorWrapper::new)) ); } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java index f58b12deb..c38547524 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java @@ -67,8 +67,8 @@ import com.dfsek.terra.forge.mixin.access.StructureAccessorAccessor; import com.dfsek.terra.forge.util.ForgeAdapter; -public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { - private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class); +public class ForgeChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { + private static final Logger logger = LoggerFactory.getLogger(ForgeChunkGeneratorWrapper.class); private final TerraBiomeSource biomeSource; private final Registry noiseRegistry; @@ -76,8 +76,8 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C private ChunkGenerator delegate; private ConfigPack pack; - public FabricChunkGeneratorWrapper(Registry noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack, - RegistryEntry settingsSupplier) { + public ForgeChunkGeneratorWrapper(Registry noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack, + RegistryEntry settingsSupplier) { super(noiseRegistry, Optional.empty(), biomeSource); this.noiseRegistry = noiseRegistry; this.pack = configPack; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java index c8def7e88..297d1acfc 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java @@ -1,6 +1,6 @@ package com.dfsek.terra.forge.mixin.fix; -import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; import net.minecraft.world.gen.structure.NetherFossilStructure; import net.minecraft.world.gen.structure.Structure.Context; @@ -22,7 +22,7 @@ import java.util.Optional; public class NetherFossilOptimization { @Inject(method = "getStructurePosition", at = @At("HEAD"), cancellable = true) public void injectFossilPositions(Context context, CallbackInfoReturnable> cir) { - if(context.chunkGenerator() instanceof FabricChunkGeneratorWrapper) { + if(context.chunkGenerator() instanceof ForgeChunkGeneratorWrapper) { cir.setReturnValue(Optional.empty()); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java index d766b82e2..22f3733a0 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -17,7 +17,7 @@ package com.dfsek.terra.forge.mixin.implementations.terra.world; -import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; import net.minecraft.block.FluidBlock; import net.minecraft.fluid.Fluid; import net.minecraft.util.math.BlockPos; @@ -117,7 +117,7 @@ public abstract class ChunkRegionMixin { } public ChunkGenerator terraWorld$getGenerator() { - return ((FabricChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle(); + return ((ForgeChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle(); } public BiomeProvider terraWorld$getBiomeProvider() { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java index bec9c2f36..698d49bfe 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java @@ -17,7 +17,7 @@ package com.dfsek.terra.forge.mixin.implementations.terra.world; -import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; import com.dfsek.terra.forge.generation.TerraBiomeSource; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldAccess; @@ -81,8 +81,8 @@ public abstract class ServerWorldMixin { } public ChunkGenerator terra$getGenerator() { - return ((FabricChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() - .getChunkGenerator()).getHandle(); + return ((ForgeChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() + .getChunkGenerator()).getHandle(); } public BiomeProvider terra$getBiomeProvider() { @@ -94,8 +94,8 @@ public abstract class ServerWorldMixin { public ConfigPack terra$getPack() { net.minecraft.world.gen.chunk.ChunkGenerator generator = (((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager()).getChunkGenerator(); - if(generator instanceof FabricChunkGeneratorWrapper fabricChunkGeneratorWrapper) { - return fabricChunkGeneratorWrapper.getPack(); + if(generator instanceof ForgeChunkGeneratorWrapper forgeChunkGeneratorWrapper) { + return forgeChunkGeneratorWrapper.getPack(); } return null; } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java index 209d95057..ac0efc605 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java @@ -2,7 +2,7 @@ package com.dfsek.terra.forge.util; import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.forge.ForgeEntryPoint; -import com.dfsek.terra.forge.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; import com.dfsek.terra.forge.generation.TerraBiomeSource; import net.minecraft.structure.StructureSet; @@ -80,7 +80,7 @@ public class LifecycleUtil { PRESETS.add(generatorID); TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); - ChunkGenerator generator = new FabricChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); + ChunkGenerator generator = new ForgeChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); WorldPreset preset = new WorldPreset( From e2bb2d8712f76d14445b97a8b2758977581b0903 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 10:25:52 -0700 Subject: [PATCH 169/220] refactor handles --- .../src/main/java/com/dfsek/terra/forge/PlatformImpl.java | 8 ++++---- .../{FabricItemHandle.java => ForgeItemHandle.java} | 2 +- .../{FabricWorldHandle.java => ForgeWorldHandle.java} | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename platforms/forge/src/main/java/com/dfsek/terra/forge/handle/{FabricItemHandle.java => ForgeItemHandle.java} (97%) rename platforms/forge/src/main/java/com/dfsek/terra/forge/handle/{FabricWorldHandle.java => ForgeWorldHandle.java} (97%) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index ca0d34af8..53f42ee5a 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -48,15 +48,15 @@ import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.api.util.generic.Lazy; import com.dfsek.terra.api.world.biome.PlatformBiome; import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.handle.FabricItemHandle; -import com.dfsek.terra.forge.handle.FabricWorldHandle; +import com.dfsek.terra.forge.handle.ForgeItemHandle; +import com.dfsek.terra.forge.handle.ForgeWorldHandle; import com.dfsek.terra.forge.util.ProtoPlatformBiome; public class PlatformImpl extends AbstractPlatform { private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); - private final ItemHandle itemHandle = new FabricItemHandle(); - private final WorldHandle worldHandle = new FabricWorldHandle(); + private final ItemHandle itemHandle = new ForgeItemHandle(); + private final WorldHandle worldHandle = new ForgeWorldHandle(); private final Lazy dataFolder = Lazy.lazy(() -> new File("./config/Terra")); public PlatformImpl() { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricItemHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java similarity index 97% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricItemHandle.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java index cc7b0d1a6..b68ad4478 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricItemHandle.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java @@ -34,7 +34,7 @@ import com.dfsek.terra.api.inventory.Item; import com.dfsek.terra.api.inventory.item.Enchantment; -public class FabricItemHandle implements ItemHandle { +public class ForgeItemHandle implements ItemHandle { @Override public Item createItem(String data) { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricWorldHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java similarity index 97% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricWorldHandle.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java index dd47858b8..b139af0e8 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/FabricWorldHandle.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java @@ -30,7 +30,7 @@ import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.handle.WorldHandle; -public class FabricWorldHandle implements WorldHandle { +public class ForgeWorldHandle implements WorldHandle { private static final BlockState AIR = (BlockState) Blocks.AIR.getDefaultState(); From 752f57bbeaf9797064c56fc7d8ee1eb2d66738ab Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 10:26:20 -0700 Subject: [PATCH 170/220] fix addon ID --- .../forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java index 320c03fe2..499ae6533 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java @@ -75,6 +75,6 @@ public final class ForgeAddon implements BaseAddon { @Override public String getID() { - return "terra-fabric"; + return "terra-forge"; } } From 32b2f15f3b3cab36b324bf2a2a166f0a9da6a8ca Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 10:26:58 -0700 Subject: [PATCH 171/220] fix chunk generator codec name --- .../src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java | 4 +--- .../src/main/java/com/dfsek/terra/forge/data/Codecs.java | 2 +- .../terra/forge/generation/ForgeChunkGeneratorWrapper.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 2c7da3437..e8f701fd0 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -37,8 +37,6 @@ import org.slf4j.LoggerFactory; import com.dfsek.terra.forge.data.Codecs; import com.dfsek.terra.forge.util.LifecycleUtil; -import java.util.concurrent.atomic.AtomicReference; - @Mod("terra") @EventBusSubscriber(bus = Bus.MOD) @@ -72,7 +70,7 @@ public class ForgeEntryPoint { event.register(Registry.WORLD_PRESET_KEY, helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> LifecycleUtil.registerWorldTypes(helper))); - event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER)); + event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.FORGE_CHUNK_GENERATOR_WRAPPER)); event.register(Registry.BIOME_SOURCE_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE)); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java index d93e176e7..f30006e12 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java @@ -44,7 +44,7 @@ public final class Codecs { .forGetter(TerraBiomeSource::getPack)) .apply(instance, instance.stable(TerraBiomeSource::new))); - public static final Codec FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder + public static final Codec FORGE_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder .create( instance -> instance.group( RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java index c38547524..ce649eba0 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java @@ -94,7 +94,7 @@ public class ForgeChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.Ch @Override protected Codec getCodec() { - return Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER; + return Codecs.FORGE_CHUNK_GENERATOR_WRAPPER; } @Override From 37c358e3d1fba86321675be72191e78e2fdfb388 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 11:12:35 -0700 Subject: [PATCH 172/220] rename all platform references --- .../src/main/java/com/dfsek/terra/forge/PlatformImpl.java | 2 +- .../terra/forge/config/PreLoadCompatibilityOptions.java | 8 ++++---- .../terra/forge/mixin/fix/NetherFossilOptimization.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index 53f42ee5a..6426c5685 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -122,7 +122,7 @@ public class PlatformImpl extends AbstractPlatform { @Override public @NotNull String platformName() { - return "Fabric"; + return "Forge"; } @Override diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java index bf7c3b7bc..1b8acf3ae 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java @@ -26,19 +26,19 @@ import com.dfsek.terra.api.properties.Properties; @SuppressWarnings("FieldMayBeFinal") public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties { - @Value("fabric.use-vanilla-biomes") + @Value("forge.use-vanilla-biomes") @Default private boolean vanillaBiomes = false; - @Value("fabric.beard.enable") + @Value("forge.beard.enable") @Default private boolean beard = true; - @Value("fabric.beard.threshold") + @Value("forge.beard.threshold") @Default private double beardThreshold = 0.5; - @Value("fabric.beard.air-threshold") + @Value("forge.beard.air-threshold") @Default private double airThreshold = -0.5; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java index 297d1acfc..d72e59761 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java @@ -16,7 +16,7 @@ import java.util.Optional; /** * Disable fossil generation in Terra worlds, as they are very expensive due to consistently triggering cache misses. * - * Currently, on Fabric, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in nether. + * Currently, on Forge, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in nether. */ @Mixin(NetherFossilStructure.class) public class NetherFossilOptimization { From e1cbb29ae43d9e5e3b595b0c0aa8902c6bb43bcd Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 14:46:50 -0700 Subject: [PATCH 173/220] begin splitting mixins into common --- buildSrc/src/main/kotlin/Versions.kt | 9 +++++++++ platforms/fabric/build.gradle.kts | 15 +++++++++++++-- .../FabricChunkGeneratorWrapper.java | 3 ++- .../mixin/access/ChunkRegionAccessor.java | 15 --------------- .../entity/MobSpawnerBlockEntityMixin.java | 3 ++- .../terra/block/state/BlockStateMixin.java | 3 ++- .../main/resources/terra.fabric.mixins.json | 6 +----- platforms/forge/build.gradle.kts | 2 +- .../main/resources/terra.forge.mixins.json | 2 +- platforms/mod-common/README.md | 4 ++++ platforms/mod-common/build.gradle.kts | 18 ++++++++++++++++++ .../mixin/access/MobSpawnerLogicAccessor.java | 2 +- .../mod}/mixin/access/StateAccessor.java | 2 +- .../access/StructureAccessorAccessor.java | 2 +- .../src/main/resources/fabric.mod.json | 8 ++++++++ .../main/resources/terra.common.mixins.json | 19 +++++++++++++++++++ 16 files changed, 83 insertions(+), 30 deletions(-) delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/ChunkRegionAccessor.java create mode 100644 platforms/mod-common/README.md create mode 100644 platforms/mod-common/build.gradle.kts rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/access/MobSpawnerLogicAccessor.java (95%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/access/StateAccessor.java (96%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/access/StructureAccessorAccessor.java (95%) create mode 100644 platforms/mod-common/src/main/resources/fabric.mod.json create mode 100644 platforms/mod-common/src/main/resources/terra.common.mixins.json diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 42a262e15..f0b5efc0f 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -28,6 +28,15 @@ object Versions { const val minotaur = "1.1.0" } + object Mod { + const val minecraft = "1.19" + const val yarn = "$minecraft+build.1" + const val fabricLoader = "0.14.2" + + const val architecuryLoom = "0.12.0-SNAPSHOT" + const val architectutyPlugin = "3.4-SNAPSHOT" + } + object Forge { const val minecraft = "1.19" const val forge = "$minecraft-41.0.38" diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 401cea107..b8a3b4562 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -1,8 +1,16 @@ plugins { - id("fabric-loom") version Versions.Fabric.loom + id("dev.architectury.loom") version Versions.Mod.architecuryLoom + id("architectury-plugin") version Versions.Mod.architectutyPlugin id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower } +configurations { + val common by creating + create("shadowCommon") + compileClasspath.get().extendsFrom(common) + runtimeClasspath.get().extendsFrom(common) +} + dependencies { shadedApi(project(":common:implementation:base")) @@ -10,6 +18,9 @@ dependencies { "annotationProcessor"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") "annotationProcessor"("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") + "common"(project(path = ":platforms:mod-common", configuration = "namedElements")) { isTransitive = false } + "shadowCommon"(project(path = ":platforms:mod-common", configuration = "transformProductionFabric")) { isTransitive = false } + minecraft("com.mojang:minecraft:${Versions.Fabric.minecraft}") mappings("net.fabricmc:yarn:${Versions.Fabric.yarn}:v2") @@ -28,7 +39,7 @@ dependencies { loom { accessWidenerPath.set(file("src/main/resources/terra.accesswidener")) mixin { - defaultRefmapName.set("terra-refmap.json") + defaultRefmapName.set("terra-fabric-refmap.json") } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 04e87e4bc..8ae3c3afe 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -17,6 +17,8 @@ package com.dfsek.terra.fabric.generation; +import com.dfsek.terra.mod.mixin.access.StructureAccessorAccessor; + import com.mojang.serialization.Codec; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -63,7 +65,6 @@ import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; import com.dfsek.terra.fabric.data.Codecs; -import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; import com.dfsek.terra.fabric.util.FabricAdapter; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/ChunkRegionAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/ChunkRegionAccessor.java deleted file mode 100644 index 2c471cf0e..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/ChunkRegionAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.fabric.mixin.access; - -import net.minecraft.world.ChunkRegion; -import net.minecraft.world.chunk.Chunk; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.List; - - -@Mixin(ChunkRegion.class) -public interface ChunkRegionAccessor { - @Accessor("chunks") - List getChunks(); -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java index 07fdd9630..0bb1b6120 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java @@ -17,6 +17,8 @@ package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; +import com.dfsek.terra.mod.mixin.access.MobSpawnerLogicAccessor; + import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -35,7 +37,6 @@ 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.fabric.FabricEntryPoint; -import com.dfsek.terra.fabric.mixin.access.MobSpawnerLogicAccessor; @Mixin(MobSpawnerBlockEntity.class) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java index 361dd8ae4..86552bda4 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java @@ -1,6 +1,8 @@ package com.dfsek.terra.fabric.mixin.implementations.terra.block.state; +import com.dfsek.terra.mod.mixin.access.StateAccessor; + import com.google.common.collect.ImmutableMap; import com.mojang.serialization.MapCodec; import net.minecraft.block.AbstractBlock.AbstractBlockState; @@ -18,7 +20,6 @@ import java.util.stream.Collectors; import com.dfsek.terra.api.block.BlockType; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.properties.Property; -import com.dfsek.terra.fabric.mixin.access.StateAccessor; @Mixin(AbstractBlockState.class) diff --git a/platforms/fabric/src/main/resources/terra.fabric.mixins.json b/platforms/fabric/src/main/resources/terra.fabric.mixins.json index 4e8614ba3..f18482bf5 100644 --- a/platforms/fabric/src/main/resources/terra.fabric.mixins.json +++ b/platforms/fabric/src/main/resources/terra.fabric.mixins.json @@ -4,10 +4,6 @@ "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "access.ChunkRegionAccessor", - "access.MobSpawnerLogicAccessor", - "access.StateAccessor", - "access.StructureAccessorAccessor", "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", "fix.NetherFossilOptimization", "implementations.compat.GenerationSettingsFloraFeaturesMixin", @@ -49,5 +45,5 @@ "injectors": { "defaultRequire": 1 }, - "refmap": "terra-refmap.json" + "refmap": "terra-fabric-refmap.json" } \ No newline at end of file diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 63db47bf2..1f630bda5 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -13,7 +13,7 @@ dependencies { loom { mixin { - defaultRefmapName.set("terra-refmap.json") + defaultRefmapName.set("terra-forge-refmap.json") } forge { diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index e68b6351b..33af22478 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -44,5 +44,5 @@ "injectors": { "defaultRequire": 1 }, - "refmap": "terra-refmap.json" + "refmap": "terra-forge-refmap.json" } \ No newline at end of file diff --git a/platforms/mod-common/README.md b/platforms/mod-common/README.md new file mode 100644 index 000000000..f92b8b043 --- /dev/null +++ b/platforms/mod-common/README.md @@ -0,0 +1,4 @@ +# mixin-common + +This project contains mixins shared between Forge & Fabric, as +well as glue code. \ No newline at end of file diff --git a/platforms/mod-common/build.gradle.kts b/platforms/mod-common/build.gradle.kts new file mode 100644 index 000000000..bb7de895f --- /dev/null +++ b/platforms/mod-common/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id("dev.architectury.loom") version Versions.Mod.architecuryLoom + id("architectury-plugin") version Versions.Mod.architectutyPlugin +} + +dependencies { + shadedApi(project(":common:implementation:base")) + + modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") + + minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") + mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") +} + +architectury { + common("fabric", "forge") + minecraft = Versions.Mod.minecraft +} \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/MobSpawnerLogicAccessor.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/MobSpawnerLogicAccessor.java index 28cda62be..5289cd427 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/MobSpawnerLogicAccessor.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.access; +package com.dfsek.terra.mod.mixin.access; import net.minecraft.world.MobSpawnerEntry; import net.minecraft.world.MobSpawnerLogic; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StateAccessor.java similarity index 96% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StateAccessor.java index 1ec51c2dc..0cee6cbaf 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StateAccessor.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.access; +package com.dfsek.terra.mod.mixin.access; import net.minecraft.state.State; import net.minecraft.state.property.Property; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StructureAccessorAccessor.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StructureAccessorAccessor.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StructureAccessorAccessor.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StructureAccessorAccessor.java index da33618d2..b64b47faa 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StructureAccessorAccessor.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StructureAccessorAccessor.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.access; +package com.dfsek.terra.mod.mixin.access; import net.minecraft.world.WorldAccess; import net.minecraft.world.gen.StructureAccessor; diff --git a/platforms/mod-common/src/main/resources/fabric.mod.json b/platforms/mod-common/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..2f4b9b0de --- /dev/null +++ b/platforms/mod-common/src/main/resources/fabric.mod.json @@ -0,0 +1,8 @@ +{ + "schemaVersion": 1, + "id": "terra-common", + "version": "1.0.0", + "mixins": [ + "terra.common.mixins.json" + ] +} \ No newline at end of file diff --git a/platforms/mod-common/src/main/resources/terra.common.mixins.json b/platforms/mod-common/src/main/resources/terra.common.mixins.json new file mode 100644 index 000000000..ee399c73e --- /dev/null +++ b/platforms/mod-common/src/main/resources/terra.common.mixins.json @@ -0,0 +1,19 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.mod.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "access.MobSpawnerLogicAccessor", + "access.StateAccessor", + "access.StructureAccessorAccessor" + ], + "client": [ + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "terra-common-refmap.json" +} \ No newline at end of file From 1a1000bbef66bf0fb2c6cbb8525e0bc4fc556979 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 15:38:28 -0700 Subject: [PATCH 174/220] fix forge build --- platforms/fabric/build.gradle.kts | 8 ++++++-- platforms/forge/build.gradle.kts | 27 ++++++++++++++++++++++++++- platforms/mod-common/build.gradle.kts | 6 ++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index b8a3b4562..2af355a9a 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -4,9 +4,13 @@ plugins { id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower } +architectury { + fabric() +} + + configurations { val common by creating - create("shadowCommon") compileClasspath.get().extendsFrom(common) runtimeClasspath.get().extendsFrom(common) } @@ -19,7 +23,7 @@ dependencies { "annotationProcessor"("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") "common"(project(path = ":platforms:mod-common", configuration = "namedElements")) { isTransitive = false } - "shadowCommon"(project(path = ":platforms:mod-common", configuration = "transformProductionFabric")) { isTransitive = false } + shaded(project(path = ":platforms:mod-common", configuration = "transformProductionFabric")) { isTransitive = false } minecraft("com.mojang:minecraft:${Versions.Fabric.minecraft}") mappings("net.fabricmc:yarn:${Versions.Fabric.yarn}:v2") diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 1f630bda5..9fcf26433 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -1,10 +1,30 @@ plugins { id("dev.architectury.loom") version Versions.Forge.architecuryLoom + id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower +} + +architectury { + platformSetupLoomIde() + forge() +} + +configurations { + val common by creating + compileClasspath.get().extendsFrom(common) + runtimeClasspath.get().extendsFrom(common) } dependencies { shadedApi(project(":common:implementation:base")) + "common"(project(path = ":platforms:mod-common", configuration = "namedElements")) { isTransitive = false } + shaded(project(path = ":platforms:mod-common", configuration = "transformProductionForge")) { isTransitive = false } + "developmentForge"(project(":platforms:mod-common", configuration = "namedElements")) { + isTransitive = false + } + + forge(group = "net.minecraftforge", name = "forge", version = Versions.Forge.forge) minecraft("com.mojang:minecraft:${Versions.Forge.minecraft}") @@ -17,7 +37,8 @@ loom { } forge { - mixinConfigs.set(listOf("terra.forge.mixins.json")) + mixinConfig("terra.common.mixins.json") + mixinConfig("terra.forge.mixins.json") } } @@ -34,6 +55,10 @@ tasks { ) } } + + shadowJar { + exclude("fabric.mod.json") + } remapJar { inputFile.set(shadowJar.get().archiveFile) diff --git a/platforms/mod-common/build.gradle.kts b/platforms/mod-common/build.gradle.kts index bb7de895f..33a503818 100644 --- a/platforms/mod-common/build.gradle.kts +++ b/platforms/mod-common/build.gradle.kts @@ -3,6 +3,12 @@ plugins { id("architectury-plugin") version Versions.Mod.architectutyPlugin } +loom { + mixin { + defaultRefmapName.set("terra-common-refmap.json") + } +} + dependencies { shadedApi(project(":common:implementation:base")) From 2a6d130d2074642280fd98c0e63b2d941cf24428 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 15:48:09 -0700 Subject: [PATCH 175/220] move world handle into common module --- .../com/dfsek/terra/fabric/PlatformImpl.java | 4 +- .../com/dfsek/terra/forge/PlatformImpl.java | 4 +- .../terra/forge/handle/ForgeWorldHandle.java | 59 ------------------- .../mod/handle/MinecraftWorldHandle.java} | 8 +-- 4 files changed, 6 insertions(+), 69 deletions(-) delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java => mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java} (89%) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java index fef99d2cd..2ba5701f0 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java @@ -49,14 +49,14 @@ import com.dfsek.terra.api.util.generic.Lazy; import com.dfsek.terra.api.world.biome.PlatformBiome; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.handle.FabricItemHandle; -import com.dfsek.terra.fabric.handle.FabricWorldHandle; +import com.dfsek.terra.mod.handle.MinecraftWorldHandle; import com.dfsek.terra.fabric.util.ProtoPlatformBiome; public class PlatformImpl extends AbstractPlatform { private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); private final ItemHandle itemHandle = new FabricItemHandle(); - private final WorldHandle worldHandle = new FabricWorldHandle(); + private final WorldHandle worldHandle = new MinecraftWorldHandle(); private final Lazy dataFolder = Lazy.lazy(() -> new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra")); private MinecraftServer server; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index 6426c5685..2b414715a 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -49,14 +49,14 @@ import com.dfsek.terra.api.util.generic.Lazy; import com.dfsek.terra.api.world.biome.PlatformBiome; import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; import com.dfsek.terra.forge.handle.ForgeItemHandle; -import com.dfsek.terra.forge.handle.ForgeWorldHandle; import com.dfsek.terra.forge.util.ProtoPlatformBiome; +import com.dfsek.terra.mod.handle.MinecraftWorldHandle; public class PlatformImpl extends AbstractPlatform { private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); private final ItemHandle itemHandle = new ForgeItemHandle(); - private final WorldHandle worldHandle = new ForgeWorldHandle(); + private final WorldHandle worldHandle = new MinecraftWorldHandle(); private final Lazy dataFolder = Lazy.lazy(() -> new File("./config/Terra")); public PlatformImpl() { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java deleted file mode 100644 index b139af0e8..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.handle; - -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.block.Blocks; -import net.minecraft.command.argument.BlockArgumentParser; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; -import net.minecraftforge.registries.ForgeRegistries; -import org.jetbrains.annotations.NotNull; - -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.entity.EntityType; -import com.dfsek.terra.api.handle.WorldHandle; - - -public class ForgeWorldHandle implements WorldHandle { - - private static final BlockState AIR = (BlockState) Blocks.AIR.getDefaultState(); - - @Override - public @NotNull BlockState createBlockState(@NotNull String data) { - try { - net.minecraft.block.BlockState state = BlockArgumentParser.block(Registry.BLOCK, data, true).blockState(); - if(state == null) throw new IllegalArgumentException("Invalid data: " + data); - return (BlockState) state; - } catch(CommandSyntaxException e) { - throw new IllegalArgumentException(e); - } - } - - @Override - public @NotNull BlockState air() { - return AIR; - } - - @Override - public @NotNull EntityType getEntity(@NotNull String id) { - Identifier identifier = Identifier.tryParse(id); - if(identifier == null) identifier = Identifier.tryParse(id); - return (EntityType) ForgeRegistries.ENTITIES.getHolder(identifier).orElseThrow().value(); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java similarity index 89% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java index ac7a0e248..13eef4b2d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java @@ -15,16 +15,12 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.handle; +package com.dfsek.terra.mod.handle; -import com.dfsek.terra.fabric.FabricEntryPoint; - -import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.Blocks; import net.minecraft.command.argument.BlockArgumentParser; import net.minecraft.util.Identifier; -import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; import org.jetbrains.annotations.NotNull; @@ -33,7 +29,7 @@ import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.handle.WorldHandle; -public class FabricWorldHandle implements WorldHandle { +public class MinecraftWorldHandle implements WorldHandle { private static final BlockState AIR = (BlockState) Blocks.AIR.getDefaultState(); From 2a24fa56d7f2169e9f08b332c9096f868698b32e Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 16:01:59 -0700 Subject: [PATCH 176/220] move seedhack into common --- .../fabric/generation/TerraBiomeSource.java | 5 +--- .../mixin/lifecycle/NoiseConfigMixin.java | 4 +-- .../com/dfsek/terra/fabric/util/SeedHack.java | 29 ------------------- .../mixin/lifecycle/NoiseConfigMixin.java | 10 ++----- .../com/dfsek/terra/mod}/util/SeedHack.java | 2 +- 5 files changed, 6 insertions(+), 44 deletions(-) delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/SeedHack.java rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/util/SeedHack.java (96%) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java index 17aaa343f..dec7784ff 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java @@ -22,11 +22,9 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.fabric.data.Codecs; import com.dfsek.terra.fabric.util.ProtoPlatformBiome; -import com.dfsek.terra.fabric.util.SeedHack; +import com.dfsek.terra.mod.util.SeedHack; import com.mojang.serialization.Codec; -import it.unimi.dsi.fastutil.objects.Object2LongMap; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.biome.source.BiomeSource; @@ -34,7 +32,6 @@ import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; import java.util.stream.StreamSupport; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java index b1ddda34f..b24bfd489 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java @@ -1,5 +1,7 @@ package com.dfsek.terra.fabric.mixin.lifecycle; +import com.dfsek.terra.mod.util.SeedHack; + import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; @@ -12,8 +14,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.dfsek.terra.fabric.util.SeedHack; - /** * Hack to map noise sampler to seeds diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/SeedHack.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/SeedHack.java deleted file mode 100644 index f0c59fc00..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/SeedHack.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.fabric.util; - -import it.unimi.dsi.fastutil.objects.Object2LongMap; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * Holder for hacky biome source seed workaround - */ -public class SeedHack { - private static final Logger LOGGER = LoggerFactory.getLogger(SeedHack.class); - - private static final Object2LongMap seedMap = new Object2LongOpenHashMap<>(); - - public static long getSeed(MultiNoiseSampler sampler) { - if(!seedMap.containsKey(sampler)) { - throw new IllegalArgumentException("Sampler is not registered: " + sampler); - } - return seedMap.getLong(sampler); - } - - public static void register(MultiNoiseSampler sampler, long seed) { - LOGGER.info("Registered seed {} to sampler {}", seed, sampler.hashCode()); - seedMap.put(sampler, seed); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java index 7360045af..41a113f9e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java @@ -1,25 +1,19 @@ package com.dfsek.terra.forge.mixin.lifecycle; -import com.dfsek.terra.forge.util.SeedHack; - -import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; -import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters; -import net.minecraft.util.math.random.RandomSplitter; -import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; import net.minecraft.world.biome.source.util.MultiNoiseUtil.NoiseHypercube; -import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import net.minecraft.world.gen.densityfunction.DensityFunction; import net.minecraft.world.gen.noise.NoiseConfig; 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.Redirect; import java.util.List; +import com.dfsek.terra.mod.util.SeedHack; + /** * Hack to map noise sampler to seeds diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/SeedHack.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/SeedHack.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/util/SeedHack.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/SeedHack.java index 5eaf38093..74f9173ab 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/SeedHack.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/SeedHack.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.util; +package com.dfsek.terra.mod.util; import it.unimi.dsi.fastutil.objects.Object2LongMap; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; From 7c2908e5cafde28d81908c184eb79f0064aba7c6 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 17:53:46 -0700 Subject: [PATCH 177/220] move most mod code into mod common --- .../dfsek/terra/fabric/FabricEntryPoint.java | 5 +- .../com/dfsek/terra/fabric/PlatformImpl.java | 52 +--- .../config/PostLoadCompatibilityOptions.java | 28 -- .../fabric/config/VanillaBiomeProperties.java | 76 ------ .../terra/fabric/handle/FabricItemHandle.java | 57 ---- ...oveGoalsUnsynchronizedRandomAccessFix.java | 27 -- .../mixin/fix/NetherFossilOptimization.java | 42 --- .../GenerationSettingsFloraFeaturesMixin.java | 32 --- .../implementations/terra/BiomeMixin.java | 31 --- .../terra/HandleImplementationMixin.java | 61 ----- .../terra/block/BlockMixin.java | 44 ---- .../terra/block/entity/BlockEntityMixin.java | 54 ---- .../LootableContainerBlockEntityMixin.java | 35 --- .../block/entity/SignBlockEntityMixin.java | 65 ----- .../terra/block/state/PropertyMixin.java | 43 --- .../terra/chunk/ChunkRegionMixin.java | 58 ----- .../terra/chunk/WorldChunkMixin.java | 75 ------ .../terra/chunk/data/ProtoChunkMixin.java | 53 ---- .../terra/entity/EntityMixin.java | 55 ---- .../terra/entity/EntityTypeMixin.java | 29 --- .../terra/entity/PlayerEntityMixin.java | 31 --- .../entity/ServerCommandSourceMixin.java | 66 ----- .../LockableContainerBlockEntityMixin.java | 47 ---- .../terra/inventory/item/ItemMixin.java | 43 --- .../terra/inventory/item/ItemStackMixin.java | 76 ------ .../inventory/meta/EnchantmentMixin.java | 53 ---- .../meta/ItemStackDamageableMixin.java | 55 ---- .../inventory/meta/ItemStackMetaMixin.java | 65 ----- .../implementations/terra/package-info.java | 23 -- .../mixin_ifaces/FloraFeatureHolder.java | 10 - .../dfsek/terra/fabric/util/BiomeUtil.java | 17 +- .../terra/fabric/util/FabricAdapter.java | 185 ------------- .../dfsek/terra/fabric/util/FabricUtil.java | 61 ----- .../terra/fabric/util/LifecycleUtil.java | 6 +- .../com/dfsek/terra/fabric/util/TagUtil.java | 8 +- .../main/resources/terra.fabric.mixins.json | 27 -- .../com/dfsek/terra/forge/ForgeAddon.java | 80 ------ .../dfsek/terra/forge/ForgeEntryPoint.java | 9 +- .../com/dfsek/terra/forge/PlatformImpl.java | 52 +--- .../config/PreLoadCompatibilityOptions.java | 60 ----- .../com/dfsek/terra/forge/data/Codecs.java | 65 ----- .../ForgeChunkGeneratorWrapper.java | 246 ------------------ .../forge/generation/TerraBiomeSource.java | 86 ------ .../mixin/access/MobSpawnerLogicAccessor.java | 30 --- .../forge/mixin/access/StateAccessor.java | 35 --- .../access/StructureAccessorAccessor.java | 30 --- .../entity/MobSpawnerBlockEntityMixin.java | 131 ---------- .../terra/block/state/BlockStateMixin.java | 83 ------ .../terra/world/ChunkRegionMixin.java | 149 ----------- .../terra/world/ServerWorldMixin.java | 102 -------- .../com/dfsek/terra/forge/util/BiomeUtil.java | 24 +- .../dfsek/terra/forge/util/LifecycleUtil.java | 12 +- .../terra/forge/util/ProtoPlatformBiome.java | 61 ----- .../com/dfsek/terra/forge/util/TagUtil.java | 8 +- .../main/resources/terra.forge.mixins.json | 30 --- .../com/dfsek/terra/mod/CommonPlatform.java | 24 ++ .../com/dfsek/terra/mod/MinecraftAddon.java} | 50 ++-- .../java/com/dfsek/terra/mod/ModPlatform.java | 56 ++++ .../config/PostLoadCompatibilityOptions.java | 2 +- .../config/PreLoadCompatibilityOptions.java | 10 +- .../terra/mod/config}/ProtoPlatformBiome.java | 6 +- .../mod}/config/VanillaBiomeProperties.java | 2 +- .../com/dfsek/terra/mod}/data/Codecs.java | 33 +-- .../MinecraftChunkGeneratorWrapper.java} | 22 +- .../mod}/generation/TerraBiomeSource.java | 6 +- .../mod/handle/MinecraftItemHandle.java} | 9 +- ...oveGoalsUnsynchronizedRandomAccessFix.java | 8 +- .../mixin/fix/NetherFossilOptimization.java | 8 +- .../GenerationSettingsFloraFeaturesMixin.java | 4 +- .../implementations/terra/BiomeMixin.java | 2 +- .../terra/HandleImplementationMixin.java | 2 +- .../terra/block/BlockMixin.java | 2 +- .../terra/block/entity/BlockEntityMixin.java | 2 +- .../LootableContainerBlockEntityMixin.java | 2 +- .../entity/MobSpawnerBlockEntityMixin.java | 9 +- .../block/entity/SignBlockEntityMixin.java | 2 +- .../terra/block/state/BlockStateMixin.java | 2 +- .../terra/block/state/PropertyMixin.java | 2 +- .../terra/chunk/ChunkRegionMixin.java | 2 +- .../terra/chunk/WorldChunkMixin.java | 2 +- .../terra/chunk/data/ProtoChunkMixin.java | 2 +- .../terra/entity/EntityMixin.java | 6 +- .../terra/entity/EntityTypeMixin.java | 2 +- .../terra/entity/PlayerEntityMixin.java | 2 +- .../entity/ServerCommandSourceMixin.java | 2 +- .../LockableContainerBlockEntityMixin.java | 2 +- .../terra/inventory/item/ItemMixin.java | 2 +- .../terra/inventory/item/ItemStackMixin.java | 2 +- .../inventory/meta/EnchantmentMixin.java | 2 +- .../meta/ItemStackDamageableMixin.java | 2 +- .../inventory/meta/ItemStackMetaMixin.java | 2 +- .../implementations/terra/package-info.java | 2 +- .../terra/world/ChunkRegionMixin.java | 10 +- .../terra/world/ServerWorldMixin.java | 18 +- .../mod}/mixin_ifaces/FloraFeatureHolder.java | 2 +- .../terra/mod/util/MinecraftAdapter.java} | 4 +- .../dfsek/terra/mod/util/MinecraftUtil.java} | 43 +-- .../main/resources/terra.common.mixins.json | 29 ++- 98 files changed, 320 insertions(+), 3071 deletions(-) delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/NetherFossilOptimization.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/BiomeMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/HandleImplementationMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/BlockMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/BlockEntityMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/PropertyMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/ChunkRegionMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/WorldChunkMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityTypeMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/PlayerEntityMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/ServerCommandSourceMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemStackMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/package-info.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/FloraFeatureHolder.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/MobSpawnerLogicAccessor.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StateAccessor.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StructureAccessorAccessor.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/BlockStateMixin.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java create mode 100644 platforms/mod-common/src/main/java/com/dfsek/terra/mod/CommonPlatform.java rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java => mod-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java} (55%) create mode 100644 platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/config/PostLoadCompatibilityOptions.java (95%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/config/PreLoadCompatibilityOptions.java (88%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric/util => mod-common/src/main/java/com/dfsek/terra/mod/config}/ProtoPlatformBiome.java (89%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/config/VanillaBiomeProperties.java (97%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/data/Codecs.java (79%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java => mod-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java} (91%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/generation/TerraBiomeSource.java (95%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java => mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java} (87%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java (79%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/fix/NetherFossilOptimization.java (73%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java (89%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/BiomeMixin.java (94%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/HandleImplementationMixin.java (96%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/block/BlockMixin.java (95%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/block/entity/BlockEntityMixin.java (96%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java (94%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java (94%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java (96%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/block/state/BlockStateMixin.java (97%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/block/state/PropertyMixin.java (93%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/chunk/ChunkRegionMixin.java (97%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/chunk/WorldChunkMixin.java (97%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java (96%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/entity/EntityMixin.java (90%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/entity/EntityTypeMixin.java (93%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/entity/PlayerEntityMixin.java (94%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/entity/ServerCommandSourceMixin.java (97%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java (96%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/inventory/item/ItemMixin.java (95%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/inventory/item/ItemStackMixin.java (96%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java (96%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java (95%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java (96%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/package-info.java (92%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/world/ChunkRegionMixin.java (93%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/implementations/terra/world/ServerWorldMixin.java (85%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/mixin_ifaces/FloraFeatureHolder.java (81%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge/util/ForgeAdapter.java => mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java} (95%) rename platforms/{forge/src/main/java/com/dfsek/terra/forge/util/ForgeUtil.java => mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java} (64%) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java index 66348ed53..d85b330e0 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -28,11 +28,10 @@ import net.fabricmc.api.ModInitializer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; -import net.minecraft.world.gen.WorldPresets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.dfsek.terra.fabric.data.Codecs; +import com.dfsek.terra.mod.data.Codecs; public class FabricEntryPoint implements ModInitializer { @@ -46,7 +45,7 @@ public class FabricEntryPoint implements ModInitializer { } public static void register() { // register the things - Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); + Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER); Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java index 2ba5701f0..efa3bfe17 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java @@ -20,17 +20,14 @@ package com.dfsek.terra.fabric; import ca.solostudios.strata.Versions; import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.version.Version; -import com.dfsek.tectonic.api.TypeRegistry; -import com.dfsek.tectonic.api.depth.DepthTracker; -import com.dfsek.tectonic.api.exception.LoadException; + import com.dfsek.terra.fabric.util.BiomeUtil; +import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.ModPlatform; + import net.fabricmc.loader.api.FabricLoader; import net.minecraft.MinecraftVersion; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.world.biome.Biome.Precipitation; -import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,29 +35,26 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Locale; -import com.dfsek.terra.AbstractPlatform; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.api.util.generic.Lazy; -import com.dfsek.terra.api.world.biome.PlatformBiome; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.handle.FabricItemHandle; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.handle.MinecraftItemHandle; import com.dfsek.terra.mod.handle.MinecraftWorldHandle; -import com.dfsek.terra.fabric.util.ProtoPlatformBiome; -public class PlatformImpl extends AbstractPlatform { +public class PlatformImpl extends ModPlatform { private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); - private final ItemHandle itemHandle = new FabricItemHandle(); + private final ItemHandle itemHandle = new MinecraftItemHandle(); private final WorldHandle worldHandle = new MinecraftWorldHandle(); private final Lazy dataFolder = Lazy.lazy(() -> new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra")); private MinecraftServer server; public PlatformImpl() { + CommonPlatform.initialize(this); load(); } @@ -68,6 +62,7 @@ public class PlatformImpl extends AbstractPlatform { this.server = server; } + @Override public MinecraftServer getServer() { return server; } @@ -86,7 +81,7 @@ public class PlatformImpl extends AbstractPlatform { }).join(); BiomeUtil.registerBiomes(); server.getWorlds().forEach(world -> { - if(world.getChunkManager().getChunkGenerator() instanceof FabricChunkGeneratorWrapper chunkGeneratorWrapper) { + if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { chunkGeneratorWrapper.setPack(pack); LOGGER.info("Replaced pack in chunk generator for world {}", world); @@ -101,7 +96,7 @@ public class PlatformImpl extends AbstractPlatform { protected Iterable platformAddon() { List addons = new ArrayList<>(); - addons.add(new FabricAddon(this)); + super.platformAddon().forEach(addons::add); String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); try { @@ -150,27 +145,4 @@ public class PlatformImpl extends AbstractPlatform { public @NotNull ItemHandle getItemHandle() { return itemHandle; } - - @Override - public void register(TypeRegistry registry) { - super.register(registry); - registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker)) - .registerLoader(Identifier.class, (type, o, loader, depthTracker) -> { - Identifier identifier = Identifier.tryParse((String) o); - if(identifier == null) - throw new LoadException("Invalid identifier: " + o, depthTracker); - return identifier; - }) - .registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase( - Locale.ROOT))) - .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase( - Locale.ROOT))); - } - - - private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException { - Identifier identifier = Identifier.tryParse(id); - if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure. - return new ProtoPlatformBiome(identifier); - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java deleted file mode 100644 index 9a13e0029..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.config; - -import com.dfsek.tectonic.api.config.template.ConfigTemplate; - -import com.dfsek.terra.api.properties.Properties; - - -@SuppressWarnings("FieldMayBeFinal") -public class PostLoadCompatibilityOptions implements ConfigTemplate, Properties { - -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java deleted file mode 100644 index 889c9148f..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.dfsek.terra.fabric.config; - -import com.dfsek.tectonic.api.config.template.ConfigTemplate; -import com.dfsek.tectonic.api.config.template.annotations.Default; -import com.dfsek.tectonic.api.config.template.annotations.Value; -import net.minecraft.world.biome.Biome.Precipitation; -import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; - -import com.dfsek.terra.api.properties.Properties; - - -public class VanillaBiomeProperties implements ConfigTemplate, Properties { - @Value("colors.grass") - @Default - private Integer grassColor = null; - - @Value("colors.fog") - @Default - private Integer fogColor = null; - - @Value("colors.water") - @Default - private Integer waterColor = null; - - @Value("colors.water-fog") - @Default - private Integer waterFogColor = null; - - @Value("colors.foliage") - @Default - private Integer foliageColor = null; - - @Value("colors.sky") - @Default - private Integer skyColor = null; - - @Value("colors.modifier") - @Default - private GrassColorModifier modifier = null; - - @Value("climate.precipitation") - @Default - private Precipitation precipitation = null; - - public Integer getFogColor() { - return fogColor; - } - - public Integer getFoliageColor() { - return foliageColor; - } - - public Integer getGrassColor() { - return grassColor; - } - - public Integer getWaterColor() { - return waterColor; - } - - public Integer getWaterFogColor() { - return waterFogColor; - } - - public Integer getSkyColor() { - return skyColor; - } - - public Precipitation getPrecipitation() { - return precipitation; - } - - public GrassColorModifier getModifier() { - return modifier; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java deleted file mode 100644 index beb2ee7a2..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.handle; - -import com.dfsek.terra.fabric.FabricEntryPoint; - -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.command.argument.ItemStackArgumentType; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - -import java.util.Set; -import java.util.stream.Collectors; - -import com.dfsek.terra.api.handle.ItemHandle; -import com.dfsek.terra.api.inventory.Item; -import com.dfsek.terra.api.inventory.item.Enchantment; - - -public class FabricItemHandle implements ItemHandle { - - @Override - public Item createItem(String data) { - try { - return (Item) new ItemStackArgumentType(new CommandRegistryAccess(FabricEntryPoint.getPlatform().getServer().getRegistryManager())).parse(new StringReader(data)).getItem(); - } catch(CommandSyntaxException e) { - throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); - } - } - - @Override - public Enchantment getEnchantment(String id) { - return (Enchantment) (Registry.ENCHANTMENT.get(Identifier.tryParse(id))); - } - - @Override - public Set getEnchantments() { - return Registry.ENCHANTMENT.stream().map(enchantment -> (Enchantment) enchantment).collect(Collectors.toSet()); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java deleted file mode 100644 index ced25c46b..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.fabric.mixin.fix; - -import net.minecraft.entity.passive.BeeEntity.MoveToFlowerGoal; -import net.minecraft.entity.passive.BeeEntity.MoveToHiveGoal; -import net.minecraft.util.math.random.CheckedRandom; -import net.minecraft.util.math.random.Random; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import com.dfsek.terra.fabric.FabricEntryPoint; - - -/** - * Bees spawning uses world.random without synchronization. This causes issues when spawning bees during world generation. - */ -@Mixin({ - MoveToHiveGoal.class, - MoveToFlowerGoal.class -}) -public class BeeMoveGoalsUnsynchronizedRandomAccessFix { - @Redirect(method = "", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;random:Lnet/minecraft/util/math/random/Random;")) - public Random redirectRandomAccess(World instance) { - return new CheckedRandom(FabricEntryPoint.getPlatform().getServer().getTicks()); // replace with new random seeded by tick time. - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/NetherFossilOptimization.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/NetherFossilOptimization.java deleted file mode 100644 index 770b042dd..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/fix/NetherFossilOptimization.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.fabric.mixin.fix; - -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; - -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.structure.NetherFossilGenerator; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.random.ChunkRandom; -import net.minecraft.world.EmptyBlockView; -import net.minecraft.world.gen.HeightContext; -import net.minecraft.world.gen.chunk.VerticalBlockSample; -import net.minecraft.world.gen.heightprovider.HeightProvider; -import net.minecraft.world.gen.structure.NetherFossilStructure; -import net.minecraft.world.gen.structure.Structure; -import net.minecraft.world.gen.structure.Structure.Context; -import net.minecraft.world.gen.structure.Structure.StructurePosition; -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.CallbackInfoReturnable; - -import java.util.Optional; - - -/** - * Disable fossil generation in Terra worlds, as they are very expensive due to consistently triggering cache misses. - * - * Currently, on Fabric, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in nether. - */ -@Mixin(NetherFossilStructure.class) -public class NetherFossilOptimization { - @Inject(method = "getStructurePosition", at = @At("HEAD"), cancellable = true) - public void injectFossilPositions(Context context, CallbackInfoReturnable> cir) { - if(context.chunkGenerator() instanceof FabricChunkGeneratorWrapper) { - cir.setReturnValue(Optional.empty()); - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java deleted file mode 100644 index 39236239f..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations.compat; - -import com.dfsek.terra.fabric.mixin_ifaces.FloraFeatureHolder; - -import net.minecraft.world.biome.GenerationSettings; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.List; - - -@Mixin(GenerationSettings.class) -@Implements(@Interface(iface = FloraFeatureHolder.class, prefix = "terra$")) -public class GenerationSettingsFloraFeaturesMixin { - private List> flora; - - public void terra$setFloraFeatures(List> features) { - this.flora = features; - } - - @Inject(method = "getFlowerFeatures", cancellable = true, at = @At("HEAD")) - public void inject(CallbackInfoReturnable>> cir) { - if(flora != null) { - cir.setReturnValue(flora); - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/BiomeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/BiomeMixin.java deleted file mode 100644 index 7ad40e91f..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/BiomeMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra; - -import net.minecraft.world.biome.Biome; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -import com.dfsek.terra.api.world.biome.PlatformBiome; - - -@Mixin(Biome.class) -@Implements(@Interface(iface = PlatformBiome.class, prefix = "terra$")) -public abstract class BiomeMixin { -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/HandleImplementationMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/HandleImplementationMixin.java deleted file mode 100644 index 09ddf21a7..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/HandleImplementationMixin.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations.terra; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.LockableContainerBlockEntity; -import net.minecraft.block.entity.LootableContainerBlockEntity; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.world.ChunkRegion; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.chunk.ProtoChunk; -import net.minecraft.world.chunk.WorldChunk; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; - -import com.dfsek.terra.api.Handle; - - -/** - * A ton of Minecraft classes must implement Handle identically, we can just take care of it here - */ -@Mixin({ - ServerWorld.class, - ChunkRegion.class, - - Block.class, - BlockState.class, - - BlockEntity.class, - LootableContainerBlockEntity.class, - LockableContainerBlockEntity.class, - - ProtoChunk.class, - WorldChunk.class, - - Entity.class, - EntityType.class, - - ServerCommandSource.class, - - Item.class, - ItemStack.class, - Enchantment.class, - - Biome.class -}) -@Implements(@Interface(iface = Handle.class, prefix = "terra$")) -public class HandleImplementationMixin { - @Intrinsic - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/BlockMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/BlockMixin.java deleted file mode 100644 index 271615c01..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/BlockMixin.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.block; - -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -import com.dfsek.terra.api.block.BlockType; - - -@Mixin(Block.class) -@Implements(@Interface(iface = BlockType.class, prefix = "terra$")) -public abstract class BlockMixin { - public com.dfsek.terra.api.block.state.BlockState terra$getDefaultState() { - return (com.dfsek.terra.api.block.state.BlockState) ((Block) (Object) this).getDefaultState(); - } - - public boolean terra$isSolid() { - return ((Block) (Object) this).getDefaultState().isOpaque(); - } - - @SuppressWarnings("ConstantConditions") - public boolean terra$isWater() { - return ((Object) this) == Blocks.WATER; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/BlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/BlockEntityMixin.java deleted file mode 100644 index a8fc2a580..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/BlockEntityMixin.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; - -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -import com.dfsek.terra.api.block.entity.BlockEntity; -import com.dfsek.terra.api.block.state.BlockState; - - -@Mixin(net.minecraft.block.entity.BlockEntity.class) -@Implements(@Interface(iface = BlockEntity.class, prefix = "terra$")) -public abstract class BlockEntityMixin { - public boolean terra$update(boolean applyPhysics) { - if(((net.minecraft.block.entity.BlockEntity) (Object) this).hasWorld()) //noinspection ConstantConditions - ((net.minecraft.block.entity.BlockEntity) (Object) this).getWorld().getChunk( - ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos()).setBlockEntity( - (net.minecraft.block.entity.BlockEntity) (Object) this); - return true; - } - - public int terra$getX() { - return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getX(); - } - - public int terra$getY() { - return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getY(); - } - - public int terra$getZ() { - return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getZ(); - } - - public BlockState terra$getBlockState() { - return (BlockState) ((net.minecraft.block.entity.BlockEntity) (Object) this).getCachedState(); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java deleted file mode 100644 index 40755991e..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; - -import net.minecraft.block.entity.LootableContainerBlockEntity; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -import com.dfsek.terra.api.block.entity.Container; -import com.dfsek.terra.api.inventory.Inventory; - - -@Mixin(LootableContainerBlockEntity.class) -@Implements(@Interface(iface = Container.class, prefix = "terra$")) -public abstract class LootableContainerBlockEntityMixin extends BlockEntityMixin { - public Inventory terra$getInventory() { - return (Inventory) this; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java deleted file mode 100644 index 2006246d8..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; - -import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.text.Text; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import com.dfsek.terra.api.block.entity.SerialState; -import com.dfsek.terra.api.block.entity.Sign; - - -@Mixin(SignBlockEntity.class) -@Implements(@Interface(iface = Sign.class, prefix = "terra$")) -public abstract class SignBlockEntityMixin { - @Shadow - @Final - private Text[] texts; - - @Shadow - public abstract void setTextOnRow(int row, Text text); - - public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { - setTextOnRow(index, Text.literal(line)); - } - - public @NotNull String[] terra$getLines() { - String[] lines = new String[texts.length]; - for(int i = 0; i < texts.length; i++) { - lines[i] = texts[i].getString(); - } - return lines; - } - - public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException { - return texts[index].getString(); - } - - public void terra$applyState(String state) { - SerialState.parse(state).forEach((k, v) -> { - if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); - terra$setLine(Integer.parseInt(k.substring(4)), v); - }); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/PropertyMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/PropertyMixin.java deleted file mode 100644 index 7665662be..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/PropertyMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations.terra.block.state; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Interface.Remap; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Collection; - -import com.dfsek.terra.api.block.state.properties.Property; - - -@Mixin(net.minecraft.state.property.Property.class) -@Implements(@Interface(iface = Property.class, prefix = "terra$", remap = Remap.NONE)) -public abstract class PropertyMixin { - @Shadow - @Final - private Class type; - @Shadow - @Final - private String name; - - @Shadow - public abstract Collection getValues(); - - @Intrinsic - public Collection terra$values() { - return getValues(); - } - - @Intrinsic - public Class terra$getType() { - return type; - } - - @Intrinsic - public String terra$getID() { - return name; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/ChunkRegionMixin.java deleted file mode 100644 index 4da5c28cf..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/ChunkRegionMixin.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.chunk; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.ChunkRegion; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.world.chunk.Chunk; - - -@Mixin(ChunkRegion.class) -@Implements(@Interface(iface = Chunk.class, prefix = "terraChunk$")) -public abstract class ChunkRegionMixin { - - @Shadow - @Final - private net.minecraft.world.chunk.Chunk centerPos; - - public void terraChunk$setBlock(int x, int y, int z, @NotNull BlockState blockState, boolean physics) { - ((ChunkRegion) (Object) this).setBlockState(new BlockPos(x + (centerPos.getPos().x << 4), y, z + (centerPos.getPos().z << 4)), - (net.minecraft.block.BlockState) blockState, 0); - } - - public @NotNull BlockState terraChunk$getBlock(int x, int y, int z) { - return (BlockState) ((ChunkRegion) (Object) this).getBlockState( - new BlockPos(x + (centerPos.getPos().x << 4), y, z + (centerPos.getPos().z << 4))); - } - - public int terraChunk$getX() { - return centerPos.getPos().x; - } - - public int terraChunk$getZ() { - return centerPos.getPos().z; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/WorldChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/WorldChunkMixin.java deleted file mode 100644 index 885d0aae2..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/WorldChunkMixin.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.chunk; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.WorldChunk; -import org.jetbrains.annotations.NotNull; -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; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.world.ServerWorld; -import com.dfsek.terra.api.world.chunk.Chunk; - - -@Mixin(WorldChunk.class) -@Implements(@Interface(iface = Chunk.class, prefix = "terra$")) -public abstract class WorldChunkMixin { - @Final - @Shadow - net.minecraft.world.World world; - - @Shadow - public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos); - - @Shadow - @Nullable - public abstract net.minecraft.block.BlockState setBlockState(BlockPos pos, net.minecraft.block.BlockState state, boolean moved); - - public void terra$setBlock(int x, int y, int z, BlockState data, boolean physics) { - setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) data, false); - } - - public void terra$setBlock(int x, int y, int z, @NotNull BlockState blockState) { - ((net.minecraft.world.chunk.Chunk) (Object) this).setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) blockState, - false); - } - - @Intrinsic - public @NotNull BlockState terra$getBlock(int x, int y, int z) { - return (BlockState) getBlockState(new BlockPos(x, y, z)); - } - - public int terra$getX() { - return ((net.minecraft.world.chunk.Chunk) (Object) this).getPos().x; - } - - public int terra$getZ() { - return ((net.minecraft.world.chunk.Chunk) (Object) this).getPos().z; - } - - public ServerWorld terra$getWorld() { - return (ServerWorld) world; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java deleted file mode 100644 index afae72689..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.chunk.data; - -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.HeightLimitView; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - - -@Mixin(net.minecraft.world.chunk.ProtoChunk.class) -@Implements(@Interface(iface = ProtoChunk.class, prefix = "terra$")) -public abstract class ProtoChunkMixin { - @Shadow - public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos); - - @Shadow - public abstract HeightLimitView getHeightLimitView(); - - public void terra$setBlock(int x, int y, int z, @NotNull BlockState blockState) { - ((net.minecraft.world.chunk.Chunk) (Object) this).setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) blockState, - false); - } - - public @NotNull BlockState terra$getBlock(int x, int y, int z) { - return (BlockState) getBlockState(new BlockPos(x, y, z)); - } - - public int terra$getMaxHeight() { - return getHeightLimitView().getTopY(); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityMixin.java deleted file mode 100644 index beeaf0d57..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityMixin.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.entity; - -import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import com.dfsek.terra.api.util.vector.Vector3; -import com.dfsek.terra.api.world.ServerWorld; -import com.dfsek.terra.fabric.util.FabricAdapter; - - -@Mixin(Entity.class) -@Implements(@Interface(iface = com.dfsek.terra.api.entity.Entity.class, prefix = "terra$")) -public abstract class EntityMixin { - @Shadow - public net.minecraft.world.World world; - - @Shadow - private BlockPos blockPos; - - @Shadow - public abstract void teleport(double destX, double destY, double destZ); - - public Vector3 terra$position() { - return FabricAdapter.adapt(blockPos); - } - - public void terra$position(Vector3 location) { - teleport(location.getX(), location.getY(), location.getZ()); - } - - public ServerWorld terra$world() { - return (ServerWorld) world; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityTypeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityTypeMixin.java deleted file mode 100644 index 27ea5a462..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/EntityTypeMixin.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.entity; - -import net.minecraft.entity.EntityType; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - - -@Mixin(EntityType.class) -@Implements(@Interface(iface = com.dfsek.terra.api.entity.EntityType.class, prefix = "terra$")) -public abstract class EntityTypeMixin { -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/PlayerEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/PlayerEntityMixin.java deleted file mode 100644 index 8298cb4e7..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/PlayerEntityMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.entity; - -import net.minecraft.entity.player.PlayerEntity; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -import com.dfsek.terra.api.entity.Player; - - -@Mixin(PlayerEntity.class) -@Implements(@Interface(iface = Player.class, prefix = "terra$")) -public abstract class PlayerEntityMixin extends EntityMixin { -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/ServerCommandSourceMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/ServerCommandSourceMixin.java deleted file mode 100644 index a8fdb8958..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/entity/ServerCommandSourceMixin.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.entity; - -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Optional; - -import com.dfsek.terra.api.command.CommandSender; -import com.dfsek.terra.api.entity.Entity; -import com.dfsek.terra.api.entity.Player; - - -@Mixin(ServerCommandSource.class) -@Implements(@Interface(iface = CommandSender.class, prefix = "terra$")) -public abstract class ServerCommandSourceMixin { - @Shadow - public abstract void sendFeedback(Text message, boolean broadcastToOps); - - @Shadow - public abstract ServerPlayerEntity getPlayer() throws CommandSyntaxException; - - @Shadow - @Nullable - public abstract net.minecraft.entity.@Nullable Entity getEntity(); - - public void terra$sendMessage(String message) { - sendFeedback(Text.literal(message), true); - } - - @Nullable - public Optional terra$getEntity() { - return Optional.ofNullable((Entity) getEntity()); - } - - public Optional terra$getPlayer() { - try { - return Optional.ofNullable((Player) getPlayer()); - } catch(CommandSyntaxException e) { - return Optional.empty(); - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java deleted file mode 100644 index e888e511a..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.inventory; - -import net.minecraft.block.entity.LockableContainerBlockEntity; -import net.minecraft.item.Items; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -import com.dfsek.terra.api.inventory.Inventory; -import com.dfsek.terra.api.inventory.ItemStack; - - -@Mixin(LockableContainerBlockEntity.class) -@Implements(@Interface(iface = Inventory.class, prefix = "terra$")) -public class LockableContainerBlockEntityMixin { - @SuppressWarnings("ConstantConditions") - public void terra$setItem(int slot, ItemStack newStack) { - ((LockableContainerBlockEntity) (Object) this).setStack(slot, (net.minecraft.item.ItemStack) (Object) newStack); - } - - public int terra$getSize() { - return ((LockableContainerBlockEntity) (Object) this).size(); - } - - @SuppressWarnings("ConstantConditions") - public ItemStack terra$getItem(int slot) { - net.minecraft.item.ItemStack itemStack = ((LockableContainerBlockEntity) (Object) this).getStack(slot); - return itemStack.getItem() == Items.AIR ? null : (ItemStack) (Object) itemStack; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemMixin.java deleted file mode 100644 index 111aa95fa..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.item; - -import net.minecraft.item.Item; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import com.dfsek.terra.api.inventory.ItemStack; - - -@Mixin(Item.class) -@Implements(@Interface(iface = com.dfsek.terra.api.inventory.Item.class, prefix = "terra$")) -public abstract class ItemMixin { - @Shadow - public abstract int getMaxDamage(); - - @SuppressWarnings("ConstantConditions") - public ItemStack terra$newItemStack(int amount) { - return (ItemStack) (Object) new net.minecraft.item.ItemStack((Item) (Object) this, amount); - } - - public double terra$getMaxDurability() { - return getMaxDamage(); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemStackMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemStackMixin.java deleted file mode 100644 index 3dafd81be..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/item/ItemStackMixin.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.item; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import com.dfsek.terra.api.inventory.Item; -import com.dfsek.terra.api.inventory.item.ItemMeta; - - -@Mixin(ItemStack.class) -@Implements(@Interface(iface = com.dfsek.terra.api.inventory.ItemStack.class, prefix = "terra$")) -public abstract class ItemStackMixin { - @Shadow - public abstract int getCount(); - - @Shadow - public abstract void setCount(int count); - - @Shadow - public abstract net.minecraft.item.Item getItem(); - - @Shadow - public abstract boolean isDamageable(); - - @Shadow - public abstract void setNbt(@Nullable NbtCompound tag); - - public int terra$getAmount() { - return getCount(); - } - - public void terra$setAmount(int i) { - setCount(i); - } - - public Item terra$getType() { - return (Item) getItem(); - } - - public ItemMeta terra$getItemMeta() { - return (ItemMeta) this; - } - - @SuppressWarnings("ConstantConditions") - public void terra$setItemMeta(ItemMeta meta) { - setNbt(((ItemStack) (Object) meta).getNbt()); - } - - @Intrinsic - public boolean terra$isDamageable() { - return isDamageable(); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java deleted file mode 100644 index ddc2e6936..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta; - -import net.minecraft.enchantment.Enchantment; -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Objects; - -import com.dfsek.terra.api.inventory.ItemStack; - - -@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); - - @Shadow - public abstract boolean canCombine(Enchantment other); - - @SuppressWarnings("ConstantConditions") - public boolean terra$canEnchantItem(ItemStack itemStack) { - return isAcceptableItem((net.minecraft.item.ItemStack) (Object) itemStack); - } - - public boolean terra$conflictsWith(com.dfsek.terra.api.inventory.item.Enchantment other) { - return !canCombine((Enchantment) other); - } - - public String terra$getID() { - return Objects.requireNonNull(Registry.ENCHANTMENT.getId((Enchantment) (Object) this)).toString(); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java deleted file mode 100644 index 4749b8b4d..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta; - -import net.minecraft.item.ItemStack; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import com.dfsek.terra.api.inventory.item.Damageable; - - -@Mixin(ItemStack.class) -@Implements(@Interface(iface = Damageable.class, prefix = "terra$")) -public abstract class ItemStackDamageableMixin { - @Shadow - public abstract boolean isDamaged(); - - @Shadow - public abstract int getDamage(); - - @Shadow - public abstract void setDamage(int damage); - - @Intrinsic - public int terra$getDamage() { - return getDamage(); - } - - @Intrinsic - public void terra$setDamage(int damage) { - setDamage(damage); - } - - public boolean terra$hasDamage() { - return isDamaged(); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java deleted file mode 100644 index 0fe8f7686..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtList; -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import com.dfsek.terra.api.inventory.item.Enchantment; -import com.dfsek.terra.api.inventory.item.ItemMeta; - - -@Mixin(ItemStack.class) -@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$")) -public abstract class ItemStackMetaMixin { - @Shadow - public abstract boolean hasEnchantments(); - - @Shadow - public abstract NbtList getEnchantments(); - - @Shadow - public abstract void addEnchantment(net.minecraft.enchantment.Enchantment enchantment, int level); - - public void terra$addEnchantment(Enchantment enchantment, int level) { - addEnchantment((net.minecraft.enchantment.Enchantment) enchantment, level); - } - - @Intrinsic(displace = true) - public Map terra$getEnchantments() { - if(!hasEnchantments()) return Collections.emptyMap(); - Map map = new HashMap<>(); - - getEnchantments().forEach(enchantment -> { - NbtCompound eTag = (NbtCompound) enchantment; - map.put((Enchantment) Registry.ENCHANTMENT.get(eTag.getInt("id")), eTag.getInt("lvl")); - }); - return map; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/package-info.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/package-info.java deleted file mode 100644 index 64552f11a..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -/** - * Mixins in this package implement Terra - * interfaces in Minecraft classes. - */ - -package com.dfsek.terra.fabric.mixin.implementations.terra; \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/FloraFeatureHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/FloraFeatureHolder.java deleted file mode 100644 index 5f4697d99..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin_ifaces/FloraFeatureHolder.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.fabric.mixin_ifaces; - -import net.minecraft.world.gen.feature.ConfiguredFeature; - -import java.util.List; - - -public interface FloraFeatureHolder { - void setFloraFeatures(List> features); -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java index 421b321f4..678d7777a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -3,10 +3,13 @@ package com.dfsek.terra.fabric.util; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.fabric.FabricEntryPoint; -import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.fabric.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; + +import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; +import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.util.MinecraftUtil; -import com.dfsek.terra.fabric.mixin_ifaces.FloraFeatureHolder; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; @@ -66,10 +69,10 @@ public final class BiomeUtil { Identifier identifier = new Identifier("terra", createBiomeID(pack, id)); if(registry.containsId(identifier)) { - ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(FabricUtil.getEntry(registry, identifier) - .orElseThrow() - .getKey() - .orElseThrow()); + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(MinecraftUtil.getEntry(registry, identifier) + .orElseThrow() + .getKey() + .orElseThrow()); } else { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry, registerKey(identifier).getValue(), diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java deleted file mode 100644 index da6c3f6f8..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.util; - -import net.minecraft.block.enums.BlockHalf; -import net.minecraft.block.enums.WallShape; -import net.minecraft.block.enums.WireConnection; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.HeightLimitView; - -import com.dfsek.terra.api.block.state.properties.enums.Axis; -import com.dfsek.terra.api.block.state.properties.enums.Half; -import com.dfsek.terra.api.block.state.properties.enums.RailShape; -import com.dfsek.terra.api.block.state.properties.enums.RedstoneConnection; -import com.dfsek.terra.api.block.state.properties.enums.WallHeight; -import com.dfsek.terra.api.util.vector.Vector3; -import com.dfsek.terra.api.world.info.WorldProperties; - - -public final class FabricAdapter { - public static BlockPos adapt(Vector3 v) { - return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - } - - public static Vector3 adapt(BlockPos pos) { - return Vector3.of(pos.getX(), pos.getY(), pos.getZ()); - } - - public static Direction adapt(com.dfsek.terra.api.block.state.properties.enums.Direction direction) { - return switch(direction) { - case SOUTH -> Direction.SOUTH; - case NORTH -> Direction.NORTH; - case WEST -> Direction.WEST; - case EAST -> Direction.EAST; - case UP -> Direction.UP; - case DOWN -> Direction.DOWN; - }; - } - - public static WorldProperties adapt(HeightLimitView height, long seed) { - return new WorldProperties() { - @Override - public long getSeed() { - return seed; - } - - @Override - public int getMaxHeight() { - return height.getTopY(); - } - - @Override - public int getMinHeight() { - return height.getBottomY(); - } - - @Override - public Object getHandle() { - return height; - } - }; - } - - public static com.dfsek.terra.api.block.state.properties.enums.Direction adapt(Direction direction) { - return switch(direction) { - case SOUTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.SOUTH; - case NORTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.NORTH; - case WEST -> com.dfsek.terra.api.block.state.properties.enums.Direction.WEST; - case EAST -> com.dfsek.terra.api.block.state.properties.enums.Direction.EAST; - case UP -> com.dfsek.terra.api.block.state.properties.enums.Direction.UP; - case DOWN -> com.dfsek.terra.api.block.state.properties.enums.Direction.DOWN; - }; - } - - public static WallHeight adapt(WallShape shape) { - return switch(shape) { - case LOW -> WallHeight.LOW; - case NONE -> WallHeight.NONE; - case TALL -> WallHeight.TALL; - }; - } - - public static WallShape adapt(WallHeight shape) { - return switch(shape) { - case LOW -> WallShape.LOW; - case NONE -> WallShape.NONE; - case TALL -> WallShape.TALL; - }; - } - - public static RedstoneConnection adapt(WireConnection connection) { - return switch(connection) { - case NONE -> RedstoneConnection.NONE; - case UP -> RedstoneConnection.UP; - case SIDE -> RedstoneConnection.SIDE; - }; - } - - public static WireConnection adapt(RedstoneConnection connection) { - return switch(connection) { - case NONE -> WireConnection.NONE; - case UP -> WireConnection.UP; - case SIDE -> WireConnection.SIDE; - }; - } - - - public static Half adapt(BlockHalf half) { - return switch(half) { - case BOTTOM -> Half.BOTTOM; - case TOP -> Half.TOP; - }; - } - - public static BlockHalf adapt(Half half) { - return switch(half) { - case TOP -> BlockHalf.TOP; - case BOTTOM -> BlockHalf.BOTTOM; - default -> throw new IllegalStateException(); - }; - } - - public static RailShape adapt(net.minecraft.block.enums.RailShape railShape) { - return switch(railShape) { - case EAST_WEST -> RailShape.EAST_WEST; - case NORTH_EAST -> RailShape.NORTH_EAST; - case NORTH_WEST -> RailShape.NORTH_WEST; - case SOUTH_EAST -> RailShape.SOUTH_EAST; - case SOUTH_WEST -> RailShape.SOUTH_WEST; - case NORTH_SOUTH -> RailShape.NORTH_SOUTH; - case ASCENDING_EAST -> RailShape.ASCENDING_EAST; - case ASCENDING_NORTH -> RailShape.ASCENDING_NORTH; - case ASCENDING_SOUTH -> RailShape.ASCENDING_SOUTH; - case ASCENDING_WEST -> RailShape.ASCENDING_WEST; - }; - } - - public static net.minecraft.block.enums.RailShape adapt(RailShape railShape) { - return switch(railShape) { - case EAST_WEST -> net.minecraft.block.enums.RailShape.EAST_WEST; - case NORTH_EAST -> net.minecraft.block.enums.RailShape.NORTH_EAST; - case NORTH_WEST -> net.minecraft.block.enums.RailShape.NORTH_WEST; - case SOUTH_EAST -> net.minecraft.block.enums.RailShape.SOUTH_EAST; - case SOUTH_WEST -> net.minecraft.block.enums.RailShape.SOUTH_WEST; - case NORTH_SOUTH -> net.minecraft.block.enums.RailShape.NORTH_SOUTH; - case ASCENDING_EAST -> net.minecraft.block.enums.RailShape.ASCENDING_EAST; - case ASCENDING_NORTH -> net.minecraft.block.enums.RailShape.ASCENDING_NORTH; - case ASCENDING_SOUTH -> net.minecraft.block.enums.RailShape.ASCENDING_SOUTH; - case ASCENDING_WEST -> net.minecraft.block.enums.RailShape.ASCENDING_WEST; - }; - } - - - public static Axis adapt(Direction.Axis axis) { - return switch(axis) { - case X -> Axis.X; - case Y -> Axis.Y; - case Z -> Axis.Z; - }; - } - - public static Direction.Axis adapt(Axis axis) { - return switch(axis) { - case Z -> Direction.Axis.Z; - case Y -> Direction.Axis.Y; - case X -> Direction.Axis.X; - }; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java deleted file mode 100644 index 7e00aa900..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric.util; - -import net.minecraft.block.entity.LootableContainerBlockEntity; -import net.minecraft.block.entity.MobSpawnerBlockEntity; -import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryEntry; -import net.minecraft.world.WorldAccess; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Optional; - -import com.dfsek.terra.api.block.entity.BlockEntity; -import com.dfsek.terra.api.block.entity.Container; -import com.dfsek.terra.api.block.entity.MobSpawner; -import com.dfsek.terra.api.block.entity.Sign; - - -public final class FabricUtil { - private FabricUtil() { - - } - - public static BlockEntity createState(WorldAccess worldAccess, BlockPos pos) { - net.minecraft.block.entity.BlockEntity entity = worldAccess.getBlockEntity(pos); - if(entity instanceof SignBlockEntity) { - return (Sign) entity; - } else if(entity instanceof MobSpawnerBlockEntity) { - return (MobSpawner) entity; - } else if(entity instanceof LootableContainerBlockEntity) { - return (Container) entity; - } - return null; - } - - public static Optional> getEntry(Registry registry, Identifier identifier) { - return registry.getOrEmpty(identifier) - .flatMap(registry::getKey) - .map(registry::getOrCreateEntry); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/LifecycleUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/LifecycleUtil.java index 2e935d889..d91d4e263 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/LifecycleUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/LifecycleUtil.java @@ -2,8 +2,8 @@ package com.dfsek.terra.fabric.util; import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.fabric.FabricEntryPoint; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.generation.TerraBiomeSource; import net.minecraft.structure.StructureSet; import net.minecraft.util.Identifier; @@ -78,7 +78,7 @@ public class LifecycleUtil { PRESETS.add(generatorID); TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); - ChunkGenerator generator = new FabricChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); + ChunkGenerator generator = new MinecraftChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); WorldPreset preset = new WorldPreset( diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java index 7a52ff376..78759c4f4 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java @@ -1,5 +1,7 @@ package com.dfsek.terra.fabric.util; +import com.dfsek.terra.mod.util.MinecraftUtil; + import com.google.common.collect.ImmutableMap; import net.minecraft.tag.TagKey; import net.minecraft.tag.WorldPresetTags; @@ -38,7 +40,7 @@ public final class TagUtil { LifecycleUtil .getPresets() - .forEach(id -> FabricUtil + .forEach(id -> MinecraftUtil .getEntry(registry, id) .ifPresentOrElse( preset -> collect @@ -57,11 +59,11 @@ public final class TagUtil { BiomeUtil .getTerraBiomeMap() .forEach((vb, terraBiomes) -> - FabricUtil + MinecraftUtil .getEntry(registry, vb) .ifPresentOrElse( vanilla -> terraBiomes - .forEach(tb -> FabricUtil + .forEach(tb -> MinecraftUtil .getEntry(registry, tb) .ifPresentOrElse( terra -> { diff --git a/platforms/fabric/src/main/resources/terra.fabric.mixins.json b/platforms/fabric/src/main/resources/terra.fabric.mixins.json index f18482bf5..d28c0541c 100644 --- a/platforms/fabric/src/main/resources/terra.fabric.mixins.json +++ b/platforms/fabric/src/main/resources/terra.fabric.mixins.json @@ -4,33 +4,6 @@ "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", - "fix.NetherFossilOptimization", - "implementations.compat.GenerationSettingsFloraFeaturesMixin", - "implementations.terra.BiomeMixin", - "implementations.terra.HandleImplementationMixin", - "implementations.terra.block.BlockMixin", - "implementations.terra.block.entity.BlockEntityMixin", - "implementations.terra.block.entity.LootableContainerBlockEntityMixin", - "implementations.terra.block.entity.MobSpawnerBlockEntityMixin", - "implementations.terra.block.entity.SignBlockEntityMixin", - "implementations.terra.block.state.BlockStateMixin", - "implementations.terra.block.state.PropertyMixin", - "implementations.terra.chunk.ChunkRegionMixin", - "implementations.terra.chunk.WorldChunkMixin", - "implementations.terra.chunk.data.ProtoChunkMixin", - "implementations.terra.entity.EntityMixin", - "implementations.terra.entity.EntityTypeMixin", - "implementations.terra.entity.PlayerEntityMixin", - "implementations.terra.entity.ServerCommandSourceMixin", - "implementations.terra.inventory.LockableContainerBlockEntityMixin", - "implementations.terra.inventory.item.ItemMixin", - "implementations.terra.inventory.item.ItemStackMixin", - "implementations.terra.inventory.meta.EnchantmentMixin", - "implementations.terra.inventory.meta.ItemStackDamageableMixin", - "implementations.terra.inventory.meta.ItemStackMetaMixin", - "implementations.terra.world.ChunkRegionMixin", - "implementations.terra.world.ServerWorldMixin", "lifecycle.DataPackContentsMixin", "lifecycle.MinecraftServerMixin", "lifecycle.NoiseConfigMixin", diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java deleted file mode 100644 index 499ae6533..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge; - -import ca.solostudios.strata.Versions; -import ca.solostudios.strata.version.Version; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.dfsek.terra.api.addon.BaseAddon; -import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; -import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; -import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; -import com.dfsek.terra.api.event.functional.FunctionalEventHandler; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.forge.config.PostLoadCompatibilityOptions; -import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.forge.config.VanillaBiomeProperties; - - -public final class ForgeAddon implements BaseAddon { - private static final Version VERSION = Versions.getVersion(1, 0, 0); - private static final Logger logger = LoggerFactory.getLogger(ForgeAddon.class); - private final PlatformImpl terraForgePlugin; - - public ForgeAddon(PlatformImpl terraForgePlugin) { - this.terraForgePlugin = terraForgePlugin; - } - - @Override - public void initialize() { - terraForgePlugin.getEventManager() - .getHandler(FunctionalEventHandler.class) - .register(this, ConfigPackPreLoadEvent.class) - .then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions()))) - .global(); - - terraForgePlugin.getEventManager() - .getHandler(FunctionalEventHandler.class) - .register(this, ConfigPackPostLoadEvent.class) - .then(event -> event.getPack().getContext().put(event.loadTemplate(new PostLoadCompatibilityOptions()))) - .priority(100) - .global(); - - terraForgePlugin.getEventManager() - .getHandler(FunctionalEventHandler.class) - .register(this, ConfigurationLoadEvent.class) - .then(event -> { - if(event.is(Biome.class)) { - event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties())); - } - }) - .global(); - } - - @Override - public Version getVersion() { - return VERSION; - } - - @Override - public String getID() { - return "terra-forge"; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index e8f701fd0..5208f01ec 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -17,9 +17,6 @@ package com.dfsek.terra.forge; -import com.dfsek.terra.forge.AwfulForgeHacks.RegistrySanityCheck; -import com.dfsek.terra.forge.AwfulForgeHacks.RegistryStep; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraftforge.eventbus.api.EventPriority; @@ -34,8 +31,10 @@ import net.minecraftforge.registries.RegisterEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.dfsek.terra.forge.data.Codecs; +import com.dfsek.terra.forge.AwfulForgeHacks.RegistrySanityCheck; +import com.dfsek.terra.forge.AwfulForgeHacks.RegistryStep; import com.dfsek.terra.forge.util.LifecycleUtil; +import com.dfsek.terra.mod.data.Codecs; @Mod("terra") @@ -70,7 +69,7 @@ public class ForgeEntryPoint { event.register(Registry.WORLD_PRESET_KEY, helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> LifecycleUtil.registerWorldTypes(helper))); - event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.FORGE_CHUNK_GENERATOR_WRAPPER)); + event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER)); event.register(Registry.BIOME_SOURCE_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE)); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index 2b414715a..294fa01d9 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -20,15 +20,8 @@ package com.dfsek.terra.forge; import ca.solostudios.strata.Versions; import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.version.Version; -import com.dfsek.tectonic.api.TypeRegistry; -import com.dfsek.tectonic.api.depth.DepthTracker; -import com.dfsek.tectonic.api.exception.LoadException; import net.minecraft.MinecraftVersion; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.world.biome.Biome.Precipitation; -import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.server.ServerLifecycleHooks; import org.jetbrains.annotations.NotNull; @@ -38,31 +31,31 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Locale; -import com.dfsek.terra.AbstractPlatform; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.api.util.generic.Lazy; -import com.dfsek.terra.api.world.biome.PlatformBiome; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.handle.ForgeItemHandle; -import com.dfsek.terra.forge.util.ProtoPlatformBiome; +import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.ModPlatform; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.handle.MinecraftItemHandle; import com.dfsek.terra.mod.handle.MinecraftWorldHandle; -public class PlatformImpl extends AbstractPlatform { +public class PlatformImpl extends ModPlatform { private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); - private final ItemHandle itemHandle = new ForgeItemHandle(); + private final ItemHandle itemHandle = new MinecraftItemHandle(); private final WorldHandle worldHandle = new MinecraftWorldHandle(); private final Lazy dataFolder = Lazy.lazy(() -> new File("./config/Terra")); public PlatformImpl() { + CommonPlatform.initialize(this); load(); } + @Override public MinecraftServer getServer() { return ServerLifecycleHooks.getCurrentServer(); } @@ -82,7 +75,7 @@ public class PlatformImpl extends AbstractPlatform { }).join(); //BiomeUtil.registerBiomes(); server.getWorlds().forEach(world -> { - if(world.getChunkManager().getChunkGenerator() instanceof ForgeChunkGeneratorWrapper chunkGeneratorWrapper) { + if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { chunkGeneratorWrapper.setPack(pack); LOGGER.info("Replaced pack in chunk generator for world {}", world); @@ -96,8 +89,8 @@ public class PlatformImpl extends AbstractPlatform { @Override protected Iterable platformAddon() { List addons = new ArrayList<>(); - - addons.add(new ForgeAddon(this)); + + super.platformAddon().forEach(addons::add); String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); try { @@ -139,27 +132,4 @@ public class PlatformImpl extends AbstractPlatform { public @NotNull ItemHandle getItemHandle() { return itemHandle; } - - @Override - public void register(TypeRegistry registry) { - super.register(registry); - registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker)) - .registerLoader(Identifier.class, (type, o, loader, depthTracker) -> { - Identifier identifier = Identifier.tryParse((String) o); - if(identifier == null) - throw new LoadException("Invalid identifier: " + o, depthTracker); - return identifier; - }) - .registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase( - Locale.ROOT))) - .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase( - Locale.ROOT))); - } - - - private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException { - Identifier identifier = Identifier.tryParse(id); - if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure. - return new ProtoPlatformBiome(identifier); - } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java deleted file mode 100644 index 1b8acf3ae..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.config; - -import com.dfsek.tectonic.api.config.template.ConfigTemplate; -import com.dfsek.tectonic.api.config.template.annotations.Default; -import com.dfsek.tectonic.api.config.template.annotations.Value; - -import com.dfsek.terra.api.properties.Properties; - - -@SuppressWarnings("FieldMayBeFinal") -public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties { - @Value("forge.use-vanilla-biomes") - @Default - private boolean vanillaBiomes = false; - - @Value("forge.beard.enable") - @Default - private boolean beard = true; - - @Value("forge.beard.threshold") - @Default - private double beardThreshold = 0.5; - - @Value("forge.beard.air-threshold") - @Default - private double airThreshold = -0.5; - - public boolean useVanillaBiomes() { - return vanillaBiomes; - } - - public boolean isBeard() { - return beard; - } - - public double getBeardThreshold() { - return beardThreshold; - } - - public double getAirThreshold() { - return airThreshold; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java deleted file mode 100644 index f30006e12..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/data/Codecs.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.dfsek.terra.forge.data; - -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.registry.key.RegistryKey; -import com.dfsek.terra.forge.ForgeEntryPoint; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.generation.TerraBiomeSource; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.util.dynamic.RegistryOps; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; - - -public final class Codecs { - public static final Codec TERRA_REGISTRY_KEY = RecordCodecBuilder - .create(registryKey -> registryKey.group(Codec.STRING.fieldOf("namespace") - .stable() - .forGetter(RegistryKey::getNamespace), - Codec.STRING.fieldOf("id") - .stable() - .forGetter(RegistryKey::getID)) - .apply(registryKey, registryKey.stable(RegistryKey::of))); - - public static final Codec CONFIG_PACK = RecordCodecBuilder - .create(config -> config.group(TERRA_REGISTRY_KEY.fieldOf("pack") - .stable() - .forGetter(ConfigPack::getRegistryKey)) - .apply(config, config.stable(id -> ForgeEntryPoint.getPlatform() - .getConfigRegistry() - .get(id) - .orElseThrow(() -> new IllegalArgumentException( - "No such config pack " + - id))))); - - public static final Codec TERRA_BIOME_SOURCE = RecordCodecBuilder - .create(instance -> instance.group(RegistryOps.createRegistryCodec(Registry.BIOME_KEY) - .fieldOf("biome_registry") - .stable() - .forGetter(TerraBiomeSource::getBiomeRegistry), - CONFIG_PACK.fieldOf("pack") - .stable() - .forGetter(TerraBiomeSource::getPack)) - .apply(instance, instance.stable(TerraBiomeSource::new))); - - public static final Codec FORGE_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder - .create( - instance -> instance.group( - RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY) - .fieldOf("structure_registry") - .stable() - .forGetter(ForgeChunkGeneratorWrapper::getNoiseRegistry), - TERRA_BIOME_SOURCE.fieldOf("biome_source") - .stable() - .forGetter(ForgeChunkGeneratorWrapper::getBiomeSource), - CONFIG_PACK.fieldOf("pack") - .stable() - .forGetter(ForgeChunkGeneratorWrapper::getPack), - ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings") - .stable() - .forGetter(ForgeChunkGeneratorWrapper::getSettings) - ).apply(instance, instance.stable(ForgeChunkGeneratorWrapper::new)) - ); -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java deleted file mode 100644 index ce649eba0..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.generation; - -import com.mojang.serialization.Codec; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.structure.StructureSet; -import net.minecraft.util.Util; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.random.CheckedRandom; -import net.minecraft.util.math.random.ChunkRandom; -import net.minecraft.util.math.random.RandomSeed; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryEntry; -import net.minecraft.world.ChunkRegion; -import net.minecraft.world.HeightLimitView; -import net.minecraft.world.Heightmap.Type; -import net.minecraft.world.SpawnHelper; -import net.minecraft.world.StructureWorldAccess; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.BiomeAccess; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.gen.GenerationStep.Carver; -import net.minecraft.world.gen.StructureAccessor; -import net.minecraft.world.gen.StructureWeightSampler; -import net.minecraft.world.gen.chunk.Blender; -import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; -import net.minecraft.world.gen.chunk.VerticalBlockSample; -import net.minecraft.world.gen.densityfunction.DensityFunction.UnblendedNoisePos; -import net.minecraft.world.gen.noise.NoiseConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.Optional; -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; -import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; -import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; -import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; -import com.dfsek.terra.api.world.info.WorldProperties; -import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.forge.data.Codecs; -import com.dfsek.terra.forge.mixin.access.StructureAccessorAccessor; -import com.dfsek.terra.forge.util.ForgeAdapter; - - -public class ForgeChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { - private static final Logger logger = LoggerFactory.getLogger(ForgeChunkGeneratorWrapper.class); - - private final TerraBiomeSource biomeSource; - private final Registry noiseRegistry; - private final RegistryEntry settings; - private ChunkGenerator delegate; - private ConfigPack pack; - - public ForgeChunkGeneratorWrapper(Registry noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack, - RegistryEntry settingsSupplier) { - super(noiseRegistry, Optional.empty(), biomeSource); - this.noiseRegistry = noiseRegistry; - this.pack = configPack; - this.settings = settingsSupplier; - - this.delegate = pack.getGeneratorProvider().newInstance(pack); - logger.info("Loading world with config pack {}", pack.getID()); - this.biomeSource = biomeSource; - } - - public Registry getNoiseRegistry() { - return noiseRegistry; - } - - @Override - protected Codec getCodec() { - return Codecs.FORGE_CHUNK_GENERATOR_WRAPPER; - } - - @Override - public void buildSurface(ChunkRegion region, StructureAccessor structures, NoiseConfig noiseConfig, Chunk chunk) { - // no op - } - - @Override - public void populateEntities(ChunkRegion region) { - if(!this.settings.value().mobGenerationDisabled()) { - ChunkPos chunkPos = region.getCenterPos(); - RegistryEntry registryEntry = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1)); - ChunkRandom chunkRandom = new ChunkRandom(new CheckedRandom(RandomSeed.getSeed())); - chunkRandom.setPopulationSeed(region.getSeed(), chunkPos.getStartX(), chunkPos.getStartZ()); - SpawnHelper.populateEntities(region, registryEntry, chunkPos, chunkRandom); - } - } - - @Override - public int getWorldHeight() { - return settings.value().generationShapeConfig().height(); - } - - - @Override - public CompletableFuture populateNoise(Executor executor, Blender blender, NoiseConfig noiseConfig, - StructureAccessor structureAccessor, Chunk chunk) { - return CompletableFuture.supplyAsync(() -> { - ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); - BiomeProvider biomeProvider = pack.getBiomeProvider(); - delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z); - - PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class); - if(compatibilityOptions.isBeard()) { - beard(structureAccessor, chunk, world, biomeProvider, compatibilityOptions); - } - return chunk; - }, Util.getMainWorkerExecutor()); - } - - private void beard(StructureAccessor structureAccessor, Chunk chunk, WorldProperties world, BiomeProvider biomeProvider, - PreLoadCompatibilityOptions compatibilityOptions) { - StructureWeightSampler structureWeightSampler = StructureWeightSampler.method_42695(structureAccessor, chunk.getPos()); - double threshold = compatibilityOptions.getBeardThreshold(); - double airThreshold = compatibilityOptions.getAirThreshold(); - int xi = chunk.getPos().x << 4; - int zi = chunk.getPos().z << 4; - for(int x = 0; x < 16; x++) { - for(int z = 0; z < 16; z++) { - int depth = 0; - for(int y = world.getMaxHeight(); y >= world.getMinHeight(); y--) { - double noise = structureWeightSampler.sample(new UnblendedNoisePos(x + xi, y, z + zi)); - if(noise > threshold) { - chunk.setBlockState(new BlockPos(x, y, z), (BlockState) delegate - .getPalette(x + xi, y, z + zi, world, biomeProvider) - .get(depth, x + xi, y, z + zi, world.getSeed()), false); - depth++; - } else if(noise < airThreshold) { - chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.getDefaultState(), false); - } else { - depth = 0; - } - } - } - } - } - - @Override - public void generateFeatures(StructureWorldAccess world, Chunk chunk, StructureAccessor structureAccessor) { - super.generateFeatures(world, chunk, structureAccessor); - pack.getStages().forEach(populator -> { - if(!(populator instanceof Chunkified)) { - populator.populate((ProtoWorld) world); - } - }); - } - - @Override - public int getSeaLevel() { - return settings.value().seaLevel(); - } - - @Override - public int getMinimumY() { - return settings.value().generationShapeConfig().minimumY(); - } - - - @Override - public int getHeight(int x, int z, Type heightmap, HeightLimitView height, NoiseConfig noiseConfig) { - WorldProperties properties = ForgeAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); - BiomeProvider biomeProvider = pack.getBiomeProvider(); - int min = height.getBottomY(); - for(int y = height.getTopY() - 1; y >= min; y--) { - if(heightmap - .getBlockPredicate() - .test((BlockState) delegate.getBlock(properties, x, y, z, biomeProvider))) return y + 1; - } - return min; - } - - @Override - public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height, NoiseConfig noiseConfig) { - BlockState[] array = new BlockState[height.getHeight()]; - WorldProperties properties = ForgeAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); - BiomeProvider biomeProvider = pack.getBiomeProvider(); - for(int y = height.getTopY() - 1; y >= height.getBottomY(); y--) { - array[y - height.getBottomY()] = (BlockState) delegate.getBlock(properties, x, y, z, biomeProvider); - } - return new VerticalBlockSample(height.getBottomY(), array); - } - - @Override - public void getDebugHudText(List text, NoiseConfig noiseConfig, BlockPos pos) { - - } - - public ConfigPack getPack() { - return pack; - } - - public void setPack(ConfigPack pack) { - this.pack = pack; - this.delegate = pack.getGeneratorProvider().newInstance(pack); - biomeSource.setPack(pack); - - logger.debug("Loading world with config pack {}", pack.getID()); - } - - @Override - public void carve(ChunkRegion chunkRegion, long seed, NoiseConfig noiseConfig, BiomeAccess world, StructureAccessor structureAccessor, - Chunk chunk, Carver carverStep) { - // no op - } - - @Override - public ChunkGenerator getHandle() { - return delegate; - } - - public RegistryEntry getSettings() { - return settings; - } - - @Override - public TerraBiomeSource getBiomeSource() { - return biomeSource; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java deleted file mode 100644 index b43b38ce8..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.generation; - -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.forge.data.Codecs; -import com.dfsek.terra.forge.util.ProtoPlatformBiome; - -import com.dfsek.terra.forge.util.SeedHack; - -import com.mojang.serialization.Codec; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryEntry; -import net.minecraft.world.biome.source.BiomeSource; -import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.stream.StreamSupport; - - -public class TerraBiomeSource extends BiomeSource { - - private static final Logger LOGGER = LoggerFactory.getLogger(TerraBiomeSource.class); - private final Registry biomeRegistry; - private ConfigPack pack; - - public TerraBiomeSource(Registry biomes, ConfigPack pack) { - super(StreamSupport - .stream(pack.getBiomeProvider() - .getBiomes() - .spliterator(), false) - .map(b -> biomes.getOrCreateEntry(((ProtoPlatformBiome) b.getPlatformBiome()).getDelegate()))); - this.biomeRegistry = biomes; - this.pack = pack; - - LOGGER.debug("Biomes: " + getBiomes()); - } - - @Override - protected Codec getCodec() { - return Codecs.TERRA_BIOME_SOURCE; - } - - @Override - public RegistryEntry getBiome(int biomeX, int biomeY, int biomeZ, MultiNoiseSampler noiseSampler) { - return biomeRegistry - .entryOf(((ProtoPlatformBiome) pack - .getBiomeProvider() - .getBiome(biomeX << 2, biomeY << 2, biomeZ << 2, SeedHack.getSeed(noiseSampler)) - .getPlatformBiome()).getDelegate() - ); - } - - public BiomeProvider getProvider() { - return pack.getBiomeProvider(); - } - - public Registry getBiomeRegistry() { - return biomeRegistry; - } - - public ConfigPack getPack() { - return pack; - } - - public void setPack(ConfigPack pack) { - this.pack = pack; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/MobSpawnerLogicAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/MobSpawnerLogicAccessor.java deleted file mode 100644 index 20a900005..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/MobSpawnerLogicAccessor.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.mixin.access; - -import net.minecraft.world.MobSpawnerEntry; -import net.minecraft.world.MobSpawnerLogic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - - -@Mixin(MobSpawnerLogic.class) -public interface MobSpawnerLogicAccessor { - @Accessor("spawnEntry") - MobSpawnerEntry getSpawnEntry(); -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StateAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StateAccessor.java deleted file mode 100644 index 947118da9..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StateAccessor.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.mixin.access; - -import net.minecraft.state.State; -import net.minecraft.state.property.Property; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; -import java.util.function.Function; - - -@Mixin(State.class) -public interface StateAccessor { - @Accessor("PROPERTY_MAP_PRINTER") - static Function, Comparable>, String> getPropertyMapPrinter() { - throw new UnsupportedOperationException(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StructureAccessorAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StructureAccessorAccessor.java deleted file mode 100644 index 12ca75c9d..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/StructureAccessorAccessor.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.mixin.access; - -import net.minecraft.world.WorldAccess; -import net.minecraft.world.gen.StructureAccessor; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - - -@Mixin(StructureAccessor.class) -public interface StructureAccessorAccessor { - @Accessor - WorldAccess getWorld(); -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java deleted file mode 100644 index 60bafaefb..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.mixin.implementations.terra.block.entity; - -import com.dfsek.terra.forge.ForgeEntryPoint; -import com.dfsek.terra.forge.mixin.access.MobSpawnerLogicAccessor; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.block.entity.MobSpawnerBlockEntity; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.MobSpawnerLogic; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import com.dfsek.terra.api.block.entity.MobSpawner; -import com.dfsek.terra.api.block.entity.SerialState; -import com.dfsek.terra.api.entity.EntityType; - - -@Mixin(MobSpawnerBlockEntity.class) -@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$")) -public abstract class MobSpawnerBlockEntityMixin extends BlockEntity { - private MobSpawnerBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Shadow - public abstract MobSpawnerLogic getLogic(); - - public EntityType terra$getSpawnedType() { - return (EntityType) Registry.ENTITY_TYPE.get( - Identifier.tryParse(((MobSpawnerLogicAccessor) getLogic()).getSpawnEntry().getNbt().getString("id"))); - } - - public void terra$setSpawnedType(@NotNull EntityType creatureType) { - getLogic().setEntityId((net.minecraft.entity.EntityType) creatureType); - } - - public int terra$getDelay() { - return 0; - } - - public void terra$setDelay(int delay) { - - } - - public int terra$getMinSpawnDelay() { - return 0; - } - - public void terra$setMinSpawnDelay(int delay) { - - } - - public int terra$getMaxSpawnDelay() { - return 0; - } - - public void terra$setMaxSpawnDelay(int delay) { - - } - - public int terra$getSpawnCount() { - return 0; - } - - public void terra$setSpawnCount(int spawnCount) { - - } - - public int terra$getMaxNearbyEntities() { - return 0; - } - - public void terra$setMaxNearbyEntities(int maxNearbyEntities) { - - } - - public int terra$getRequiredPlayerRange() { - return 0; - } - - public void terra$setRequiredPlayerRange(int requiredPlayerRange) { - - } - - public int terra$getSpawnRange() { - return 0; - } - - public void terra$setSpawnRange(int spawnRange) { - - } - - public void terra$applyState(String state) { - SerialState.parse(state).forEach((k, v) -> { - switch(k) { - case "type" -> terra$setSpawnedType(ForgeEntryPoint.getPlatform().getWorldHandle().getEntity(v)); - case "delay" -> terra$setDelay(Integer.parseInt(v)); - case "min_delay" -> terra$setMinSpawnDelay(Integer.parseInt(v)); - case "max_delay" -> terra$setMaxSpawnDelay(Integer.parseInt(v)); - case "spawn_count" -> terra$setSpawnCount(Integer.parseInt(v)); - case "spawn_range" -> terra$setSpawnRange(Integer.parseInt(v)); - case "max_nearby" -> terra$setMaxNearbyEntities(Integer.parseInt(v)); - case "required_player_range" -> terra$setRequiredPlayerRange(Integer.parseInt(v)); - default -> throw new IllegalArgumentException("Invalid property: " + k); - } - }); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/BlockStateMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/BlockStateMixin.java deleted file mode 100644 index c0076820c..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/BlockStateMixin.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.terra.block.state; - - -import com.dfsek.terra.forge.mixin.access.StateAccessor; -import com.google.common.collect.ImmutableMap; -import com.mojang.serialization.MapCodec; -import net.minecraft.block.AbstractBlock.AbstractBlockState; -import net.minecraft.block.Block; -import net.minecraft.state.State; -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.stream.Collectors; - -import com.dfsek.terra.api.block.BlockType; -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.block.state.properties.Property; - - -@Mixin(AbstractBlockState.class) -@Implements(@Interface(iface = BlockState.class, prefix = "terra$")) -public abstract class BlockStateMixin extends State { - private BlockStateMixin(Block owner, ImmutableMap, Comparable> entries, - MapCodec codec) { - super(owner, entries, codec); - } - - @Shadow - public abstract Block getBlock(); - - @Shadow - public abstract boolean isAir(); - - public boolean terra$matches(BlockState other) { - return getBlock() == ((net.minecraft.block.BlockState) other).getBlock(); - } - - @Intrinsic - public > boolean terra$has(Property property) { - if(property instanceof net.minecraft.state.property.Property minecraftProperty) { - return contains(minecraftProperty); - } - return false; - } - - @SuppressWarnings("unchecked") - @Intrinsic - public > T terra$get(Property property) { - return get((net.minecraft.state.property.Property) property); - } - - @SuppressWarnings("unchecked") - @Intrinsic - public > BlockState terra$set(Property property, T value) { - return (BlockState) with((net.minecraft.state.property.Property) property, value); - } - - @Intrinsic - public BlockType terra$getBlockType() { - return (BlockType) getBlock(); - } - - @Intrinsic - public String terra$getAsString(boolean properties) { - StringBuilder data = new StringBuilder(Registry.BLOCK.getId(getBlock()).toString()); - if(properties && !getEntries().isEmpty()) { - data.append('['); - data.append( - getEntries().entrySet().stream().map(StateAccessor.getPropertyMapPrinter()).collect(Collectors.joining(","))); - data.append(']'); - } - return data.toString(); - } - - @Intrinsic - public boolean terra$isAir() { - return isAir(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java deleted file mode 100644 index 22f3733a0..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ChunkRegionMixin.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.mixin.implementations.terra.world; - -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import net.minecraft.block.FluidBlock; -import net.minecraft.fluid.Fluid; -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.tick.MultiTickScheduler; -import net.minecraft.world.tick.OrderedTick; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -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; - -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; -import com.dfsek.terra.api.entity.Entity; -import com.dfsek.terra.api.entity.EntityType; -import com.dfsek.terra.api.world.ServerWorld; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.forge.util.ForgeUtil; - - -@Mixin(ChunkRegion.class) -@Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$")) -public abstract class ChunkRegionMixin { - private ConfigPack terra$config; - - - @Shadow - @Final - private net.minecraft.server.world.ServerWorld world; - - @Shadow - @Final - private long seed; - @Shadow - @Final - private Chunk centerPos; - - @Shadow - @Final - private MultiTickScheduler fluidTickScheduler; - - - @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) { - this.terra$config = ((ServerWorld) world).getPack(); - } - - - @Intrinsic(displace = true) - public void terraWorld$setBlockState(int x, int y, int z, BlockState data, boolean physics) { - BlockPos pos = new BlockPos(x, y, z); - ((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( - (net.minecraft.block.BlockState) data).getFluid(), pos)); - } - } - - @Intrinsic - public long terraWorld$getSeed() { - return seed; - } - - public int terraWorld$getMaxHeight() { - return world.getTopY(); - } - - @Intrinsic(displace = true) - public BlockState terraWorld$getBlockState(int x, int y, int z) { - BlockPos pos = new BlockPos(x, y, z); - return (BlockState) ((ChunkRegion) (Object) this).getBlockState(pos); - } - - public BlockEntity terraWorld$getBlockEntity(int x, int y, int z) { - return ForgeUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); - } - - public int terraWorld$getMinHeight() { - return world.getBottomY(); - } - - public ChunkGenerator terraWorld$getGenerator() { - return ((ForgeChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle(); - } - - public BiomeProvider terraWorld$getBiomeProvider() { - return terra$config.getBiomeProvider(); - } - - public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(world); - entity.setPos(x, y, z); - ((ChunkRegion) (Object) this).spawnEntity(entity); - return (Entity) entity; - } - - public int terraWorld$centerChunkX() { - return centerPos.getPos().x; - } - - public int terraWorld$centerChunkZ() { - return centerPos.getPos().z; - } - - public ServerWorld terraWorld$getWorld() { - return (ServerWorld) world; - } - - public ConfigPack terraWorld$getPack() { - return terra$config; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java deleted file mode 100644 index 698d49bfe..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/world/ServerWorldMixin.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.mixin.implementations.terra.world; - -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.generation.TerraBiomeSource; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.WorldAccess; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; - -import com.dfsek.terra.api.block.entity.BlockEntity; -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.entity.Entity; -import com.dfsek.terra.api.entity.EntityType; -import com.dfsek.terra.api.world.ServerWorld; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.api.world.chunk.Chunk; -import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.forge.util.ForgeUtil; - - -@Mixin(net.minecraft.server.world.ServerWorld.class) -@Implements(@Interface(iface = ServerWorld.class, prefix = "terra$")) -public abstract class ServerWorldMixin { - public Entity terra$spawnEntity(double x, double y, double z, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(null); - entity.setPos(x, y, z); - ((net.minecraft.server.world.ServerWorld) (Object) this).spawnEntity(entity); - return (Entity) entity; - } - - public void terra$setBlockState(int x, int y, int z, BlockState data, boolean physics) { - BlockPos pos = new BlockPos(x, y, z); - ((net.minecraft.server.world.ServerWorld) (Object) this).setBlockState(pos, (net.minecraft.block.BlockState) data, - physics ? 3 : 1042); - } - - @Intrinsic - public long terra$getSeed() { - return ((net.minecraft.server.world.ServerWorld) (Object) this).getSeed(); - } - - public int terra$getMaxHeight() { - return (((net.minecraft.server.world.ServerWorld) (Object) this).getBottomY()) + - ((net.minecraft.server.world.ServerWorld) (Object) this).getHeight(); - } - - public Chunk terra$getChunkAt(int x, int z) { - return (Chunk) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunk(x, z); - } - - public BlockState terra$getBlockState(int x, int y, int z) { - return (BlockState) ((net.minecraft.server.world.ServerWorld) (Object) this).getBlockState(new BlockPos(x, y, z)); - } - - public BlockEntity terra$getBlockEntity(int x, int y, int z) { - return ForgeUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); - } - - public int terra$getMinHeight() { - return ((net.minecraft.server.world.ServerWorld) (Object) this).getBottomY(); - } - - public ChunkGenerator terra$getGenerator() { - return ((ForgeChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() - .getChunkGenerator()).getHandle(); - } - - public BiomeProvider terra$getBiomeProvider() { - return ((TerraBiomeSource) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() - .getChunkGenerator() - .getBiomeSource()).getProvider(); - } - - public ConfigPack terra$getPack() { - net.minecraft.world.gen.chunk.ChunkGenerator generator = - (((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager()).getChunkGenerator(); - if(generator instanceof ForgeChunkGeneratorWrapper forgeChunkGeneratorWrapper) { - return forgeChunkGeneratorWrapper.getPack(); - } - return null; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java index 5612372b4..c42db1143 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java @@ -1,12 +1,6 @@ package com.dfsek.terra.forge.util; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.forge.ForgeEntryPoint; -import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.forge.config.VanillaBiomeProperties; - -import com.dfsek.terra.forge.mixin_ifaces.FloraFeatureHolder; +import com.dfsek.terra.mod.config.ProtoPlatformBiome; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; @@ -21,7 +15,19 @@ import net.minecraftforge.registries.RegisterEvent.RegisterHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.forge.ForgeEntryPoint; +import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; public final class BiomeUtil { @@ -57,7 +63,7 @@ public final class BiomeUtil { */ private static void registerBiome(Biome biome, ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey id, RegisterHelper helper) { - RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(ForgeRegistries.BIOMES); + RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(BuiltinRegistries.BIOME); if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java index ac0efc605..abaabaa0e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java @@ -1,10 +1,5 @@ package com.dfsek.terra.forge.util; -import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; -import com.dfsek.terra.forge.ForgeEntryPoint; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.generation.TerraBiomeSource; - import net.minecraft.structure.StructureSet; import net.minecraft.util.Identifier; import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters; @@ -30,6 +25,11 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.forge.ForgeEntryPoint; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.generation.TerraBiomeSource; + public class LifecycleUtil { private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleUtil.class); @@ -80,7 +80,7 @@ public class LifecycleUtil { PRESETS.add(generatorID); TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); - ChunkGenerator generator = new ForgeChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); + ChunkGenerator generator = new MinecraftChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); WorldPreset preset = new WorldPreset( diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java deleted file mode 100644 index e06ebf0f8..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ProtoPlatformBiome.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.forge.util; - -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.biome.Biome; - -import java.util.Objects; - -import com.dfsek.terra.api.world.biome.PlatformBiome; - -import net.minecraftforge.registries.IForgeRegistry; - - -public class ProtoPlatformBiome implements PlatformBiome { - private final Identifier identifier; - - private RegistryKey delegate; - - public ProtoPlatformBiome(Identifier identifier) { - this.identifier = identifier; - } - - public RegistryKey get(Registry registry) { - return ForgeUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow(); - } - - public RegistryKey get(IForgeRegistry registry) { - return registry.getHolder(identifier).orElseThrow().getKey().orElseThrow(); - } - - @Override - public Object getHandle() { - return identifier; - } - - public RegistryKey getDelegate() { - return delegate; - } - - public void setDelegate(RegistryKey delegate) { - this.delegate = Objects.requireNonNull(delegate); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java index 4486aad0b..42f001e8e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java @@ -1,5 +1,7 @@ package com.dfsek.terra.forge.util; +import com.dfsek.terra.mod.util.MinecraftUtil; + import com.google.common.collect.ImmutableMap; import net.minecraft.tag.TagKey; import net.minecraft.tag.WorldPresetTags; @@ -38,7 +40,7 @@ public final class TagUtil { LifecycleUtil .getPresets() - .forEach(id -> ForgeUtil + .forEach(id -> MinecraftUtil .getEntry(registry, id) .ifPresentOrElse( preset -> collect @@ -57,11 +59,11 @@ public final class TagUtil { BiomeUtil .getTerraBiomeMap() .forEach((vb, terraBiomes) -> - ForgeUtil + MinecraftUtil .getEntry(registry, vb) .ifPresentOrElse( vanilla -> terraBiomes - .forEach(tb -> ForgeUtil + .forEach(tb -> MinecraftUtil .getEntry(registry, tb) .ifPresentOrElse( terra -> { diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index 33af22478..a1316f288 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -4,36 +4,6 @@ "package": "com.dfsek.terra.forge.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "access.MobSpawnerLogicAccessor", - "access.StateAccessor", - "access.StructureAccessorAccessor", - "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", - "fix.NetherFossilOptimization", - "implementations.compat.GenerationSettingsFloraFeaturesMixin", - "implementations.terra.BiomeMixin", - "implementations.terra.HandleImplementationMixin", - "implementations.terra.block.BlockMixin", - "implementations.terra.block.entity.BlockEntityMixin", - "implementations.terra.block.entity.LootableContainerBlockEntityMixin", - "implementations.terra.block.entity.MobSpawnerBlockEntityMixin", - "implementations.terra.block.entity.SignBlockEntityMixin", - "implementations.terra.block.state.BlockStateMixin", - "implementations.terra.block.state.PropertyMixin", - "implementations.terra.chunk.ChunkRegionMixin", - "implementations.terra.chunk.WorldChunkMixin", - "implementations.terra.chunk.data.ProtoChunkMixin", - "implementations.terra.entity.EntityMixin", - "implementations.terra.entity.EntityTypeMixin", - "implementations.terra.entity.PlayerEntityMixin", - "implementations.terra.entity.ServerCommandSourceMixin", - "implementations.terra.inventory.LockableContainerBlockEntityMixin", - "implementations.terra.inventory.item.ItemMixin", - "implementations.terra.inventory.item.ItemStackMixin", - "implementations.terra.inventory.meta.EnchantmentMixin", - "implementations.terra.inventory.meta.ItemStackDamageableMixin", - "implementations.terra.inventory.meta.ItemStackMetaMixin", - "implementations.terra.world.ChunkRegionMixin", - "implementations.terra.world.ServerWorldMixin", "lifecycle.DataPackContentsMixin", "lifecycle.NoiseConfigMixin" ], diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/CommonPlatform.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/CommonPlatform.java new file mode 100644 index 000000000..97534c8b1 --- /dev/null +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/CommonPlatform.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.mod; + +import java.util.concurrent.atomic.AtomicReference; + + +public final class CommonPlatform { + private static final AtomicReference platform = new AtomicReference<>(); + + public static ModPlatform get() { + ModPlatform modPlatform = platform.get(); + + if(modPlatform == null) { + throw new IllegalStateException("Platform is not yet initialised!"); + } + + return modPlatform; + } + + public static void initialize(ModPlatform modPlatform) { + if(!platform.compareAndSet(null, modPlatform)) { + throw new IllegalStateException("Platform has already been initialized to " + platform.get()); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java similarity index 55% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java index 347244a54..76b13b137 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric; +package com.dfsek.terra.mod; import ca.solostudios.strata.Versions; import ca.solostudios.strata.version.Version; @@ -28,44 +28,44 @@ import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions; -import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.fabric.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.config.PostLoadCompatibilityOptions; +import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; -public final class FabricAddon implements BaseAddon { +public final class MinecraftAddon implements BaseAddon { private static final Version VERSION = Versions.getVersion(1, 0, 0); - private static final Logger logger = LoggerFactory.getLogger(FabricAddon.class); - private final PlatformImpl terraFabricPlugin; + private static final Logger logger = LoggerFactory.getLogger(MinecraftAddon.class); + private final ModPlatform modPlatform; - public FabricAddon(PlatformImpl terraFabricPlugin) { - this.terraFabricPlugin = terraFabricPlugin; + public MinecraftAddon(ModPlatform modPlatform) { + this.modPlatform = modPlatform; } @Override public void initialize() { - terraFabricPlugin.getEventManager() - .getHandler(FunctionalEventHandler.class) - .register(this, ConfigPackPreLoadEvent.class) - .then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions()))) - .global(); + modPlatform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions()))) + .global(); - terraFabricPlugin.getEventManager() - .getHandler(FunctionalEventHandler.class) - .register(this, ConfigPackPostLoadEvent.class) - .then(event -> event.getPack().getContext().put(event.loadTemplate(new PostLoadCompatibilityOptions()))) - .priority(100) - .global(); + modPlatform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigPackPostLoadEvent.class) + .then(event -> event.getPack().getContext().put(event.loadTemplate(new PostLoadCompatibilityOptions()))) + .priority(100) + .global(); - terraFabricPlugin.getEventManager() - .getHandler(FunctionalEventHandler.class) - .register(this, ConfigurationLoadEvent.class) - .then(event -> { + modPlatform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigurationLoadEvent.class) + .then(event -> { if(event.is(Biome.class)) { event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties())); } }) - .global(); + .global(); } @Override diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java new file mode 100644 index 000000000..48fa219c2 --- /dev/null +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java @@ -0,0 +1,56 @@ +package com.dfsek.terra.mod; + +import com.dfsek.tectonic.api.TypeRegistry; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; + +import com.dfsek.terra.AbstractPlatform; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.world.biome.PlatformBiome; + +import com.dfsek.terra.mod.config.ProtoPlatformBiome; + +import net.minecraft.command.CommandSource; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biome.Precipitation; +import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; + +import java.util.List; +import java.util.Locale; + + +public abstract class ModPlatform extends AbstractPlatform { + public abstract MinecraftServer getServer(); + + @Override + public void register(TypeRegistry registry) { + super.register(registry); + registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker)) + .registerLoader(Identifier.class, (type, o, loader, depthTracker) -> { + Identifier identifier = Identifier.tryParse((String) o); + if(identifier == null) + throw new LoadException("Invalid identifier: " + o, depthTracker); + return identifier; + }) + .registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase( + Locale.ROOT))) + .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase( + Locale.ROOT))); + } + + private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException { + Identifier identifier = Identifier.tryParse(id); + if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure. + return new ProtoPlatformBiome(identifier); + } + + @Override + protected Iterable platformAddon() { + return List.of(new MinecraftAddon(this)); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PostLoadCompatibilityOptions.java similarity index 95% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PostLoadCompatibilityOptions.java index 1a8ad12ba..a8b457bf5 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PostLoadCompatibilityOptions.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.config; +package com.dfsek.terra.mod.config; import com.dfsek.tectonic.api.config.template.ConfigTemplate; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PreLoadCompatibilityOptions.java similarity index 88% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PreLoadCompatibilityOptions.java index 8533ef1a0..00825bc5f 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PreLoadCompatibilityOptions.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.config; +package com.dfsek.terra.mod.config; import com.dfsek.tectonic.api.config.template.ConfigTemplate; import com.dfsek.tectonic.api.config.template.annotations.Default; @@ -26,19 +26,19 @@ import com.dfsek.terra.api.properties.Properties; @SuppressWarnings("FieldMayBeFinal") public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties { - @Value("fabric.use-vanilla-biomes") + @Value("minecraft.use-vanilla-biomes") @Default private boolean vanillaBiomes = false; - @Value("fabric.beard.enable") + @Value("minecraft.beard.enable") @Default private boolean beard = true; - @Value("fabric.beard.threshold") + @Value("minecraft.beard.threshold") @Default private double beardThreshold = 0.5; - @Value("fabric.beard.air-threshold") + @Value("minecraft.beard.air-threshold") @Default private double airThreshold = -0.5; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoPlatformBiome.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java similarity index 89% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoPlatformBiome.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java index b8262893a..78542fabe 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoPlatformBiome.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java @@ -15,7 +15,9 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.util; +package com.dfsek.terra.mod.config; + +import com.dfsek.terra.mod.util.MinecraftUtil; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; @@ -37,7 +39,7 @@ public class ProtoPlatformBiome implements PlatformBiome { } public RegistryKey get(Registry registry) { - return FabricUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow(); + return MinecraftUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow(); } @Override diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/VanillaBiomeProperties.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java similarity index 97% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/config/VanillaBiomeProperties.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java index b4baa1882..b37266230 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/VanillaBiomeProperties.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.config; +package com.dfsek.terra.mod.config; import com.dfsek.tectonic.api.config.template.ConfigTemplate; import com.dfsek.tectonic.api.config.template.annotations.Default; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/data/Codecs.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java similarity index 79% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/data/Codecs.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java index a2d2222c7..643ced594 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/data/Codecs.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java @@ -1,10 +1,7 @@ -package com.dfsek.terra.fabric.data; +package com.dfsek.terra.mod.data; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.registry.key.RegistryKey; -import com.dfsek.terra.fabric.FabricEntryPoint; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.generation.TerraBiomeSource; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; @@ -12,6 +9,10 @@ import net.minecraft.util.dynamic.RegistryOps; import net.minecraft.util.registry.Registry; import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.mod.CommonPlatform; + public final class Codecs { public static final Codec TERRA_REGISTRY_KEY = RecordCodecBuilder @@ -27,10 +28,10 @@ public final class Codecs { .create(config -> config.group(TERRA_REGISTRY_KEY.fieldOf("pack") .stable() .forGetter(ConfigPack::getRegistryKey)) - .apply(config, config.stable(id -> FabricEntryPoint.getPlatform() - .getConfigRegistry() - .get(id) - .orElseThrow(() -> new IllegalArgumentException( + .apply(config, config.stable(id -> CommonPlatform.get() + .getConfigRegistry() + .get(id) + .orElseThrow(() -> new IllegalArgumentException( "No such config pack " + id))))); @@ -44,22 +45,22 @@ public final class Codecs { .forGetter(TerraBiomeSource::getPack)) .apply(instance, instance.stable(TerraBiomeSource::new))); - public static final Codec FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder + public static final Codec MINECRAFT_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder .create( instance -> instance.group( RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY) .fieldOf("structure_registry") .stable() - .forGetter(FabricChunkGeneratorWrapper::getNoiseRegistry), + .forGetter(MinecraftChunkGeneratorWrapper::getNoiseRegistry), TERRA_BIOME_SOURCE.fieldOf("biome_source") .stable() - .forGetter(FabricChunkGeneratorWrapper::getBiomeSource), + .forGetter(MinecraftChunkGeneratorWrapper::getBiomeSource), CONFIG_PACK.fieldOf("pack") .stable() - .forGetter(FabricChunkGeneratorWrapper::getPack), + .forGetter(MinecraftChunkGeneratorWrapper::getPack), ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings") .stable() - .forGetter(FabricChunkGeneratorWrapper::getSettings) - ).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new)) + .forGetter(MinecraftChunkGeneratorWrapper::getSettings) + ).apply(instance, instance.stable(MinecraftChunkGeneratorWrapper::new)) ); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java similarity index 91% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java index 8ae3c3afe..1b8af7852 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.generation; +package com.dfsek.terra.mod.generation; import com.dfsek.terra.mod.mixin.access.StructureAccessorAccessor; @@ -63,13 +63,13 @@ import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; import com.dfsek.terra.api.world.info.WorldProperties; -import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.fabric.data.Codecs; -import com.dfsek.terra.fabric.util.FabricAdapter; +import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.mod.data.Codecs; +import com.dfsek.terra.mod.util.MinecraftAdapter; -public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { - private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class); +public class MinecraftChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { + private static final Logger logger = LoggerFactory.getLogger(MinecraftChunkGeneratorWrapper.class); private final TerraBiomeSource biomeSource; private final Registry noiseRegistry; @@ -77,8 +77,8 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C private ChunkGenerator delegate; private ConfigPack pack; - public FabricChunkGeneratorWrapper(Registry noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack, - RegistryEntry settingsSupplier) { + public MinecraftChunkGeneratorWrapper(Registry noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack, + RegistryEntry settingsSupplier) { super(noiseRegistry, Optional.empty(), biomeSource); this.noiseRegistry = noiseRegistry; this.pack = configPack; @@ -95,7 +95,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override protected Codec getCodec() { - return Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER; + return Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER; } @Override @@ -186,7 +186,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public int getHeight(int x, int z, Type heightmap, HeightLimitView height, NoiseConfig noiseConfig) { - WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); + WorldProperties properties = MinecraftAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); BiomeProvider biomeProvider = pack.getBiomeProvider(); int min = height.getBottomY(); for(int y = height.getTopY() - 1; y >= min; y--) { @@ -200,7 +200,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C @Override public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height, NoiseConfig noiseConfig) { BlockState[] array = new BlockState[height.getHeight()]; - WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); + WorldProperties properties = MinecraftAdapter.adapt(height, noiseConfig.getLegacyWorldSeed()); BiomeProvider biomeProvider = pack.getBiomeProvider(); for(int y = height.getTopY() - 1; y >= height.getBottomY(); y--) { array[y - height.getBottomY()] = (BlockState) delegate.getBlock(properties, x, y, z, biomeProvider); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java index dec7784ff..7f1f1d6dd 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java @@ -15,12 +15,12 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.generation; +package com.dfsek.terra.mod.generation; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.fabric.data.Codecs; -import com.dfsek.terra.fabric.util.ProtoPlatformBiome; +import com.dfsek.terra.mod.data.Codecs; +import com.dfsek.terra.mod.config.ProtoPlatformBiome; import com.dfsek.terra.mod.util.SeedHack; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java similarity index 87% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java index b68ad4478..5d26b6c43 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java @@ -15,9 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.handle; - -import com.dfsek.terra.forge.ForgeEntryPoint; +package com.dfsek.terra.mod.handle; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -32,15 +30,16 @@ import java.util.stream.Collectors; import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.inventory.Item; import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.mod.CommonPlatform; -public class ForgeItemHandle implements ItemHandle { +public class MinecraftItemHandle implements ItemHandle { @Override public Item createItem(String data) { try { return (Item) new ItemStackArgumentType(new CommandRegistryAccess( - ForgeEntryPoint.getPlatform().getServer().getRegistryManager())).parse(new StringReader(data)).getItem(); + CommonPlatform.get().getServer().getRegistryManager())).parse(new StringReader(data)).getItem(); } catch(CommandSyntaxException e) { throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java similarity index 79% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java index 53b2ac21d..ba73ff960 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java @@ -1,6 +1,4 @@ -package com.dfsek.terra.forge.mixin.fix; - -import com.dfsek.terra.forge.ForgeEntryPoint; +package com.dfsek.terra.mod.mixin.fix; import net.minecraft.entity.passive.BeeEntity.MoveToFlowerGoal; import net.minecraft.entity.passive.BeeEntity.MoveToHiveGoal; @@ -11,6 +9,8 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import com.dfsek.terra.mod.CommonPlatform; + /** * Bees spawning uses world.random without synchronization. This causes issues when spawning bees during world generation. @@ -22,6 +22,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; public class BeeMoveGoalsUnsynchronizedRandomAccessFix { @Redirect(method = "", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;random:Lnet/minecraft/util/math/random/Random;")) public Random redirectRandomAccess(World instance) { - return new CheckedRandom(ForgeEntryPoint.getPlatform().getServer().getTicks()); // replace with new random seeded by tick time. + return new CheckedRandom(CommonPlatform.get().getServer().getTicks()); // replace with new random seeded by tick time. } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java similarity index 73% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java index d72e59761..f0eb245b8 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/fix/NetherFossilOptimization.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java @@ -1,6 +1,6 @@ -package com.dfsek.terra.forge.mixin.fix; +package com.dfsek.terra.mod.mixin.fix; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; import net.minecraft.world.gen.structure.NetherFossilStructure; import net.minecraft.world.gen.structure.Structure.Context; @@ -16,13 +16,13 @@ import java.util.Optional; /** * Disable fossil generation in Terra worlds, as they are very expensive due to consistently triggering cache misses. * - * Currently, on Forge, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in nether. + * Currently, on Fabric, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in nether. */ @Mixin(NetherFossilStructure.class) public class NetherFossilOptimization { @Inject(method = "getStructurePosition", at = @At("HEAD"), cancellable = true) public void injectFossilPositions(Context context, CallbackInfoReturnable> cir) { - if(context.chunkGenerator() instanceof ForgeChunkGeneratorWrapper) { + if(context.chunkGenerator() instanceof MinecraftChunkGeneratorWrapper) { cir.setReturnValue(Optional.empty()); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java similarity index 89% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java index 19639e48a..df71e733f 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java @@ -1,6 +1,6 @@ -package com.dfsek.terra.forge.mixin.implementations.compat; +package com.dfsek.terra.mod.mixin.implementations.compat; -import com.dfsek.terra.forge.mixin_ifaces.FloraFeatureHolder; +import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; import net.minecraft.world.biome.GenerationSettings; import net.minecraft.world.gen.feature.ConfiguredFeature; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/BiomeMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/BiomeMixin.java similarity index 94% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/BiomeMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/BiomeMixin.java index 3bf07cffc..893921e8e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/BiomeMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/BiomeMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra; +package com.dfsek.terra.mod.mixin.implementations.terra; import net.minecraft.world.biome.Biome; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/HandleImplementationMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/HandleImplementationMixin.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/HandleImplementationMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/HandleImplementationMixin.java index 936af09b3..0257421ca 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/HandleImplementationMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/HandleImplementationMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.mixin.implementations.terra; +package com.dfsek.terra.mod.mixin.implementations.terra; import net.minecraft.block.Block; import net.minecraft.block.BlockState; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/BlockMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/BlockMixin.java similarity index 95% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/BlockMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/BlockMixin.java index 8df67e40a..480e4a86d 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/BlockMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/BlockMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.block; +package com.dfsek.terra.mod.mixin.implementations.terra.block; import net.minecraft.block.Block; import net.minecraft.block.Blocks; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/BlockEntityMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/BlockEntityMixin.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/BlockEntityMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/BlockEntityMixin.java index 272c18812..cfb7b795b 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/BlockEntityMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/BlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.block.entity; +package com.dfsek.terra.mod.mixin.implementations.terra.block.entity; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java similarity index 94% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java index 123541696..ad237b3b8 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.block.entity; +package com.dfsek.terra.mod.mixin.implementations.terra.block.entity; import net.minecraft.block.entity.LootableContainerBlockEntity; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java similarity index 94% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java index 0bb1b6120..f28c27a62 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java @@ -15,9 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity; - -import com.dfsek.terra.mod.mixin.access.MobSpawnerLogicAccessor; +package com.dfsek.terra.mod.mixin.implementations.terra.block.entity; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -36,7 +34,8 @@ import org.spongepowered.asm.mixin.Shadow; 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.fabric.FabricEntryPoint; +import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.mixin.access.MobSpawnerLogicAccessor; @Mixin(MobSpawnerBlockEntity.class) @@ -117,7 +116,7 @@ public abstract class MobSpawnerBlockEntityMixin extends BlockEntity { public void terra$applyState(String state) { SerialState.parse(state).forEach((k, v) -> { switch(k) { - case "type" -> terra$setSpawnedType(FabricEntryPoint.getPlatform().getWorldHandle().getEntity(v)); + case "type" -> terra$setSpawnedType(CommonPlatform.get().getWorldHandle().getEntity(v)); case "delay" -> terra$setDelay(Integer.parseInt(v)); case "min_delay" -> terra$setMinSpawnDelay(Integer.parseInt(v)); case "max_delay" -> terra$setMaxSpawnDelay(Integer.parseInt(v)); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java index 400a176ca..e32d7e053 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.block.entity; +package com.dfsek.terra.mod.mixin.implementations.terra.block.entity; import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.text.Text; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java similarity index 97% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java index 86552bda4..86272efd9 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/block/state/BlockStateMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.mixin.implementations.terra.block.state; +package com.dfsek.terra.mod.mixin.implementations.terra.block.state; import com.dfsek.terra.mod.mixin.access.StateAccessor; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/PropertyMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/PropertyMixin.java similarity index 93% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/PropertyMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/PropertyMixin.java index ce7d41e20..2dd6100d6 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/block/state/PropertyMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/PropertyMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.mixin.implementations.terra.block.state; +package com.dfsek.terra.mod.mixin.implementations.terra.block.state; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/ChunkRegionMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/ChunkRegionMixin.java similarity index 97% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/ChunkRegionMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/ChunkRegionMixin.java index 96bbe0715..7224f25d1 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/ChunkRegionMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/ChunkRegionMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.chunk; +package com.dfsek.terra.mod.mixin.implementations.terra.chunk; import net.minecraft.util.math.BlockPos; import net.minecraft.world.ChunkRegion; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/WorldChunkMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/WorldChunkMixin.java similarity index 97% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/WorldChunkMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/WorldChunkMixin.java index b6aecff61..3fb01104d 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/WorldChunkMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/WorldChunkMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.chunk; +package com.dfsek.terra.mod.mixin.implementations.terra.chunk; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.WorldChunk; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java index 918df4f42..f90e5a3b3 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.chunk.data; +package com.dfsek.terra.mod.mixin.implementations.terra.chunk.data; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java similarity index 90% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java index a300693b7..dce95cf19 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java @@ -15,9 +15,8 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.entity; +package com.dfsek.terra.mod.mixin.implementations.terra.entity; -import com.dfsek.terra.forge.util.ForgeAdapter; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.mixin.Implements; @@ -27,6 +26,7 @@ import org.spongepowered.asm.mixin.Shadow; import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.mod.util.MinecraftAdapter; @Mixin(Entity.class) @@ -42,7 +42,7 @@ public abstract class EntityMixin { public abstract void teleport(double destX, double destY, double destZ); public Vector3 terra$position() { - return ForgeAdapter.adapt(blockPos); + return MinecraftAdapter.adapt(blockPos); } public void terra$position(Vector3 location) { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityTypeMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityTypeMixin.java similarity index 93% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityTypeMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityTypeMixin.java index 1c73c1efb..a79d4fb0d 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/EntityTypeMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityTypeMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.entity; +package com.dfsek.terra.mod.mixin.implementations.terra.entity; import net.minecraft.entity.EntityType; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/PlayerEntityMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/PlayerEntityMixin.java similarity index 94% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/PlayerEntityMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/PlayerEntityMixin.java index f08df6293..ec60c9f69 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/PlayerEntityMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/PlayerEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.entity; +package com.dfsek.terra.mod.mixin.implementations.terra.entity; import net.minecraft.entity.player.PlayerEntity; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/ServerCommandSourceMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/ServerCommandSourceMixin.java similarity index 97% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/ServerCommandSourceMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/ServerCommandSourceMixin.java index ce91be261..f11ee5f73 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/entity/ServerCommandSourceMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/ServerCommandSourceMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.entity; +package com.dfsek.terra.mod.mixin.implementations.terra.entity; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.server.command.ServerCommandSource; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java index 40f6111db..90c0275dc 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.inventory; +package com.dfsek.terra.mod.mixin.implementations.terra.inventory; import net.minecraft.block.entity.LockableContainerBlockEntity; import net.minecraft.item.Items; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java similarity index 95% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java index e48b5341c..51687c45a 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.inventory.item; +package com.dfsek.terra.mod.mixin.implementations.terra.inventory.item; import net.minecraft.item.Item; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemStackMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemStackMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java index 7bb42595a..f41bce58d 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/item/ItemStackMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.inventory.item; +package com.dfsek.terra.mod.mixin.implementations.terra.inventory.item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java index 358cd7a95..d5394870c 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.inventory.meta; +package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta; import net.minecraft.enchantment.Enchantment; import net.minecraft.util.registry.Registry; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java similarity index 95% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java index d70b1732d..599dd232d 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.inventory.meta; +package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta; import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Implements; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java index 17bf068a1..39974ed26 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.mixin.implementations.terra.inventory.meta; +package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/package-info.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/package-info.java similarity index 92% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/package-info.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/package-info.java index 0899793d3..0d7e843de 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/terra/package-info.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/package-info.java @@ -20,4 +20,4 @@ * interfaces in Minecraft classes. */ -package com.dfsek.terra.forge.mixin.implementations.terra; \ No newline at end of file +package com.dfsek.terra.mod.mixin.implementations.terra; \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java similarity index 93% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java index 7a5ebf822..c17a8c1ee 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ChunkRegionMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -15,8 +15,9 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.terra.world; +package com.dfsek.terra.mod.mixin.implementations.terra.world; +import com.dfsek.terra.mod.util.MinecraftUtil; import net.minecraft.block.FluidBlock; import net.minecraft.fluid.Fluid; import net.minecraft.util.math.BlockPos; @@ -47,8 +48,7 @@ import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.util.FabricUtil; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; @Mixin(ChunkRegion.class) @@ -109,7 +109,7 @@ public abstract class ChunkRegionMixin { } public BlockEntity terraWorld$getBlockEntity(int x, int y, int z) { - return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); + return MinecraftUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); } public int terraWorld$getMinHeight() { @@ -117,7 +117,7 @@ public abstract class ChunkRegionMixin { } public ChunkGenerator terraWorld$getGenerator() { - return ((FabricChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle(); + return ((MinecraftChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle(); } public BiomeProvider terraWorld$getBiomeProvider() { diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ServerWorldMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java similarity index 85% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ServerWorldMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java index 048b38d8e..f219db0a1 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/terra/world/ServerWorldMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java @@ -15,8 +15,9 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.implementations.terra.world; +package com.dfsek.terra.mod.mixin.implementations.terra.world; +import com.dfsek.terra.mod.util.MinecraftUtil; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldAccess; import org.spongepowered.asm.mixin.Implements; @@ -33,9 +34,8 @@ import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.Chunk; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.generation.TerraBiomeSource; -import com.dfsek.terra.fabric.util.FabricUtil; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.generation.TerraBiomeSource; @Mixin(net.minecraft.server.world.ServerWorld.class) @@ -73,7 +73,7 @@ public abstract class ServerWorldMixin { } public BlockEntity terra$getBlockEntity(int x, int y, int z) { - return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); + return MinecraftUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); } public int terra$getMinHeight() { @@ -81,8 +81,8 @@ public abstract class ServerWorldMixin { } public ChunkGenerator terra$getGenerator() { - return ((FabricChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() - .getChunkGenerator()).getHandle(); + return ((MinecraftChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() + .getChunkGenerator()).getHandle(); } public BiomeProvider terra$getBiomeProvider() { @@ -94,8 +94,8 @@ public abstract class ServerWorldMixin { public ConfigPack terra$getPack() { net.minecraft.world.gen.chunk.ChunkGenerator generator = (((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager()).getChunkGenerator(); - if(generator instanceof FabricChunkGeneratorWrapper fabricChunkGeneratorWrapper) { - return fabricChunkGeneratorWrapper.getPack(); + if(generator instanceof MinecraftChunkGeneratorWrapper minecraftChunkGeneratorWrapper) { + return minecraftChunkGeneratorWrapper.getPack(); } return null; } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin_ifaces/FloraFeatureHolder.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java similarity index 81% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/mixin_ifaces/FloraFeatureHolder.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java index 2797691f4..4e7c38dec 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin_ifaces/FloraFeatureHolder.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.mixin_ifaces; +package com.dfsek.terra.mod.mixin_ifaces; import net.minecraft.world.gen.feature.ConfiguredFeature; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeAdapter.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java similarity index 95% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeAdapter.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java index 469b80349..2f43913e2 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeAdapter.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.forge.util; +package com.dfsek.terra.mod.util; import net.minecraft.util.math.BlockPos; import net.minecraft.world.HeightLimitView; @@ -24,7 +24,7 @@ import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.world.info.WorldProperties; -public final class ForgeAdapter { +public final class MinecraftAdapter { public static Vector3 adapt(BlockPos pos) { return Vector3.of(pos.getX(), pos.getY(), pos.getZ()); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeUtil.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java similarity index 64% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeUtil.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java index cb577de6f..9f7a36712 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/ForgeUtil.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java @@ -1,21 +1,9 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ +package com.dfsek.terra.mod.util; -package com.dfsek.terra.forge.util; +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.block.entity.MobSpawner; +import com.dfsek.terra.api.block.entity.Sign; import net.minecraft.block.entity.LootableContainerBlockEntity; import net.minecraft.block.entity.MobSpawnerBlockEntity; @@ -28,17 +16,18 @@ import net.minecraft.world.WorldAccess; import java.util.Optional; -import com.dfsek.terra.api.block.entity.BlockEntity; -import com.dfsek.terra.api.block.entity.Container; -import com.dfsek.terra.api.block.entity.MobSpawner; -import com.dfsek.terra.api.block.entity.Sign; - -public final class ForgeUtil { - private ForgeUtil() { +public final class MinecraftUtil { + private MinecraftUtil() { } + public static Optional> getEntry(Registry registry, Identifier identifier) { + return registry.getOrEmpty(identifier) + .flatMap(registry::getKey) + .map(registry::getOrCreateEntry); + } + public static BlockEntity createState(WorldAccess worldAccess, BlockPos pos) { net.minecraft.block.entity.BlockEntity entity = worldAccess.getBlockEntity(pos); if(entity instanceof SignBlockEntity) { @@ -50,10 +39,4 @@ public final class ForgeUtil { } return null; } - - public static Optional> getEntry(Registry registry, Identifier identifier) { - return registry.getOrEmpty(identifier) - .flatMap(registry::getKey) - .map(registry::getOrCreateEntry); - } } diff --git a/platforms/mod-common/src/main/resources/terra.common.mixins.json b/platforms/mod-common/src/main/resources/terra.common.mixins.json index ee399c73e..c8142c28a 100644 --- a/platforms/mod-common/src/main/resources/terra.common.mixins.json +++ b/platforms/mod-common/src/main/resources/terra.common.mixins.json @@ -6,7 +6,34 @@ "mixins": [ "access.MobSpawnerLogicAccessor", "access.StateAccessor", - "access.StructureAccessorAccessor" + "access.StructureAccessorAccessor", + "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", + "fix.NetherFossilOptimization", + "implementations.compat.GenerationSettingsFloraFeaturesMixin", + "implementations.terra.BiomeMixin", + "implementations.terra.HandleImplementationMixin", + "implementations.terra.block.BlockMixin", + "implementations.terra.block.entity.BlockEntityMixin", + "implementations.terra.block.entity.LootableContainerBlockEntityMixin", + "implementations.terra.block.entity.MobSpawnerBlockEntityMixin", + "implementations.terra.block.entity.SignBlockEntityMixin", + "implementations.terra.block.state.BlockStateMixin", + "implementations.terra.block.state.PropertyMixin", + "implementations.terra.chunk.ChunkRegionMixin", + "implementations.terra.chunk.WorldChunkMixin", + "implementations.terra.chunk.data.ProtoChunkMixin", + "implementations.terra.entity.EntityMixin", + "implementations.terra.entity.EntityTypeMixin", + "implementations.terra.entity.PlayerEntityMixin", + "implementations.terra.entity.ServerCommandSourceMixin", + "implementations.terra.inventory.LockableContainerBlockEntityMixin", + "implementations.terra.inventory.item.ItemMixin", + "implementations.terra.inventory.item.ItemStackMixin", + "implementations.terra.inventory.meta.EnchantmentMixin", + "implementations.terra.inventory.meta.ItemStackDamageableMixin", + "implementations.terra.inventory.meta.ItemStackMetaMixin", + "implementations.terra.world.ChunkRegionMixin", + "implementations.terra.world.ServerWorldMixin" ], "client": [ ], From 6ba4a48e29371e311ae6cd74fe370058032a36da Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 18:00:48 -0700 Subject: [PATCH 178/220] move biomeutil stuff into common --- .../lifecycle/DataPackContentsMixin.java | 5 +- .../dfsek/terra/fabric/util/BiomeUtil.java | 109 +--------------- .../com/dfsek/terra/fabric/util/TagUtil.java | 2 +- .../lifecycle/DataPackContentsMixin.java | 4 +- .../com/dfsek/terra/forge/util/BiomeUtil.java | 120 ++---------------- .../com/dfsek/terra/forge/util/TagUtil.java | 2 +- .../dfsek/terra/mod/util/MinecraftUtil.java | 112 ++++++++++++++++ 7 files changed, 133 insertions(+), 221 deletions(-) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java index f2e38a11d..e355e4f2d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java @@ -1,7 +1,8 @@ package com.dfsek.terra.fabric.mixin.lifecycle; -import com.dfsek.terra.fabric.util.BiomeUtil; import com.dfsek.terra.fabric.util.TagUtil; +import com.dfsek.terra.mod.util.MinecraftUtil; + import net.minecraft.server.DataPackContents; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; @@ -23,6 +24,6 @@ public class DataPackContentsMixin { Registry biomeRegistry = dynamicRegistryManager.get(Registry.BIOME_KEY); TagUtil.registerBiomeTags(biomeRegistry); - BiomeUtil.registerFlora(biomeRegistry); + MinecraftUtil.registerFlora(biomeRegistry); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java index 678d7777a..769c9e65b 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -4,9 +4,7 @@ import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.fabric.FabricEntryPoint; import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.mod.config.VanillaBiomeProperties; -import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; import com.dfsek.terra.mod.config.ProtoPlatformBiome; import com.dfsek.terra.mod.util.MinecraftUtil; @@ -14,10 +12,6 @@ import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.biome.Biome.Builder; -import net.minecraft.world.biome.BiomeEffects; -import net.minecraft.world.biome.GenerationSettings; -import net.minecraft.world.gen.feature.ConfiguredFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,25 +21,17 @@ import java.util.*; public final class BiomeUtil { private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class); - private static final Map> - TERRA_BIOME_MAP = new HashMap<>(); - private BiomeUtil() { } - public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) { - return pack.getID() - .toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT); - } - public static void registerBiomes() { logger.info("Registering biomes..."); FabricEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. pack.getCheckedRegistry(Biome.class) .forEach((id, biome) -> registerBiome(biome, pack, id)); }); - registerFlora(BuiltinRegistries.BIOME); + MinecraftUtil.registerFlora(BuiltinRegistries.BIOME); logger.info("Terra biomes registered."); } @@ -64,9 +50,9 @@ public final class BiomeUtil { if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); } else { - net.minecraft.world.biome.Biome minecraftBiome = createBiome(biome, registry.get(vanilla)); + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla)); - Identifier identifier = new Identifier("terra", createBiomeID(pack, id)); + Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); if(registry.containsId(identifier)) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(MinecraftUtil.getEntry(registry, identifier) @@ -75,97 +61,12 @@ public final class BiomeUtil { .orElseThrow()); } else { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry, - registerKey(identifier).getValue(), + MinecraftUtil.registerKey(identifier).getValue(), minecraftBiome).getKey().orElseThrow()); } - TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); + MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); } } - public static void registerFlora(Registry biomes) { - logger.info("Injecting flora into Terra biomes..."); - TERRA_BIOME_MAP - .forEach((vb, terraBiomes) -> - biomes.getOrEmpty(vb) - .ifPresentOrElse(vanilla -> terraBiomes - .forEach(tb -> biomes.getOrEmpty(tb) - .ifPresentOrElse( - terra -> { - List> flowerFeatures = List.copyOf(vanilla.getGenerationSettings().getFlowerFeatures()); - logger.debug("Injecting flora into biome {} : {}", tb, flowerFeatures); - ((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures(flowerFeatures); - }, - () -> logger.error( - "No such biome: {}", - tb))), - () -> logger.error("No vanilla biome: {}", vb))); - - } - - public static Map> getTerraBiomeMap() { - return Map.copyOf(TERRA_BIOME_MAP); - } - - private static RegistryKey registerKey(Identifier identifier) { - return RegistryKey.of(Registry.BIOME_KEY, identifier); - } - - public static net.minecraft.world.biome.Biome createBiome(Biome biome, net.minecraft.world.biome.Biome vanilla) { - GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); - - BiomeEffects.Builder effects = new BiomeEffects.Builder(); - - net.minecraft.world.biome.Biome.Builder builder = new Builder(); - - if(biome.getContext().has(VanillaBiomeProperties.class)) { - VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - - effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) - .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) - .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) - .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())) - .grassColorModifier( - Objects.requireNonNullElse(vanillaBiomeProperties.getModifier(), vanilla.getEffects().getGrassColorModifier())); - - - if(vanillaBiomeProperties.getGrassColor() == null) { - vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); - } else { - effects.grassColor(vanillaBiomeProperties.getGrassColor()); - } - - if(vanillaBiomeProperties.getFoliageColor() == null) { - vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); - } else { - effects.foliageColor(vanillaBiomeProperties.getFoliageColor()); - } - - builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation())); - - } else { - effects.waterColor(vanilla.getWaterColor()) - .waterFogColor(vanilla.getWaterFogColor()) - .fogColor(vanilla.getFogColor()) - .skyColor(vanilla.getSkyColor()); - vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); - vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); - - builder.precipitation(vanilla.getPrecipitation()); - } - - vanilla.getLoopSound().ifPresent(effects::loopSound); - vanilla.getAdditionsSound().ifPresent(effects::additionsSound); - vanilla.getMoodSound().ifPresent(effects::moodSound); - vanilla.getMusic().ifPresent(effects::music); - vanilla.getParticleConfig().ifPresent(effects::particleConfig); - - return builder - .temperature(vanilla.getTemperature()) - .downfall(vanilla.getDownfall()) - .effects(effects.build()) - .spawnSettings(vanilla.getSpawnSettings()) - .generationSettings(generationSettings.build()) - .build(); - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java index 78759c4f4..78c180283 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java @@ -56,7 +56,7 @@ public final class TagUtil { logger.info("Doing biome tag garbage...."); Map, List>> collect = tagsToMutableMap(registry); - BiomeUtil + MinecraftUtil .getTerraBiomeMap() .forEach((vb, terraBiomes) -> MinecraftUtil diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java index fefb67df4..b7db9106a 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java @@ -2,6 +2,8 @@ package com.dfsek.terra.forge.mixin.lifecycle; import com.dfsek.terra.forge.util.BiomeUtil; import com.dfsek.terra.forge.util.TagUtil; +import com.dfsek.terra.mod.util.MinecraftUtil; + import net.minecraft.server.DataPackContents; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; @@ -23,6 +25,6 @@ public class DataPackContentsMixin { Registry biomeRegistry = dynamicRegistryManager.get(Registry.BIOME_KEY); TagUtil.registerBiomeTags(biomeRegistry); - BiomeUtil.registerFlora(biomeRegistry); + MinecraftUtil.registerFlora(biomeRegistry); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java index c42db1143..28fe88ec2 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java @@ -1,49 +1,31 @@ package com.dfsek.terra.forge.util; -import com.dfsek.terra.mod.config.ProtoPlatformBiome; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.biome.Biome.Builder; -import net.minecraft.world.biome.BiomeEffects; -import net.minecraft.world.biome.GenerationSettings; -import net.minecraft.world.gen.feature.ConfiguredFeature; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegisterEvent.RegisterHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.forge.ForgeEntryPoint; import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.mod.config.VanillaBiomeProperties; -import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; +import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.util.MinecraftUtil; public final class BiomeUtil { private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class); - private static final Map> - TERRA_BIOME_MAP = new HashMap<>(); private BiomeUtil() { } - - public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) { - return pack.getID() - .toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT); - } + public static void registerBiomes(RegisterHelper helper) { logger.info("Registering biomes..."); @@ -51,7 +33,7 @@ public final class BiomeUtil { pack.getCheckedRegistry(Biome.class) .forEach((id, biome) -> registerBiome(biome, pack, id, helper)); }); - registerFlora(BuiltinRegistries.BIOME); + MinecraftUtil.registerFlora(BuiltinRegistries.BIOME); logger.info("Terra biomes registered."); } @@ -69,104 +51,18 @@ public final class BiomeUtil { if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); } else { - net.minecraft.world.biome.Biome minecraftBiome = createBiome(biome, ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value()); + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value()); - Identifier identifier = new Identifier("terra", createBiomeID(pack, id)); + Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); if(ForgeRegistries.BIOMES.containsKey(identifier)) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow()); } else { - helper.register(registerKey(identifier).getValue(), minecraftBiome); + helper.register(MinecraftUtil.registerKey(identifier).getValue(), minecraftBiome); ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow()); } - TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); + MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); } } - - public static void registerFlora(Registry biomes) { - logger.info("Injecting flora into Terra biomes..."); - TERRA_BIOME_MAP - .forEach((vb, terraBiomes) -> - biomes.getOrEmpty(vb) - .ifPresentOrElse(vanilla -> terraBiomes - .forEach(tb -> biomes.getOrEmpty(tb) - .ifPresentOrElse( - terra -> { - List> flowerFeatures = List.copyOf(vanilla.getGenerationSettings().getFlowerFeatures()); - logger.debug("Injecting flora into biome {} : {}", tb, flowerFeatures); - ((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures(flowerFeatures); - }, - () -> logger.error( - "No such biome: {}", - tb))), - () -> logger.error("No vanilla biome: {}", vb))); - - } - - public static Map> getTerraBiomeMap() { - return Map.copyOf(TERRA_BIOME_MAP); - } - - private static RegistryKey registerKey(Identifier identifier) { - return RegistryKey.of(Registry.BIOME_KEY, identifier); - } - - public static net.minecraft.world.biome.Biome createBiome(Biome biome, net.minecraft.world.biome.Biome vanilla) { - GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); - - BiomeEffects.Builder effects = new BiomeEffects.Builder(); - - net.minecraft.world.biome.Biome.Builder builder = new Builder(); - - if(biome.getContext().has(VanillaBiomeProperties.class)) { - VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - - effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) - .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) - .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) - .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())) - .grassColorModifier( - Objects.requireNonNullElse(vanillaBiomeProperties.getModifier(), vanilla.getEffects().getGrassColorModifier())); - - - if(vanillaBiomeProperties.getGrassColor() == null) { - vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); - } else { - effects.grassColor(vanillaBiomeProperties.getGrassColor()); - } - - if(vanillaBiomeProperties.getFoliageColor() == null) { - vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); - } else { - effects.foliageColor(vanillaBiomeProperties.getFoliageColor()); - } - - builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation())); - - } else { - effects.waterColor(vanilla.getWaterColor()) - .waterFogColor(vanilla.getWaterFogColor()) - .fogColor(vanilla.getFogColor()) - .skyColor(vanilla.getSkyColor()); - vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); - vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); - - builder.precipitation(vanilla.getPrecipitation()); - } - - vanilla.getLoopSound().ifPresent(effects::loopSound); - vanilla.getAdditionsSound().ifPresent(effects::additionsSound); - vanilla.getMoodSound().ifPresent(effects::moodSound); - vanilla.getMusic().ifPresent(effects::music); - vanilla.getParticleConfig().ifPresent(effects::particleConfig); - - return builder - .temperature(vanilla.getTemperature()) - .downfall(vanilla.getDownfall()) - .effects(effects.build()) - .spawnSettings(vanilla.getSpawnSettings()) - .generationSettings(generationSettings.build()) - .build(); - } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java index 42f001e8e..38a1e2237 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java @@ -56,7 +56,7 @@ public final class TagUtil { logger.info("Doing biome tag garbage...."); Map, List>> collect = tagsToMutableMap(registry); - BiomeUtil + MinecraftUtil .getTerraBiomeMap() .forEach((vb, terraBiomes) -> MinecraftUtil diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java index 9f7a36712..80178c3be 100644 --- a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java @@ -5,6 +5,10 @@ import com.dfsek.terra.api.block.entity.Container; import com.dfsek.terra.api.block.entity.MobSpawner; import com.dfsek.terra.api.block.entity.Sign; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; + import net.minecraft.block.entity.LootableContainerBlockEntity; import net.minecraft.block.entity.MobSpawnerBlockEntity; import net.minecraft.block.entity.SignBlockEntity; @@ -12,12 +16,29 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.WorldAccess; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biome.Builder; +import net.minecraft.world.biome.BiomeEffects; +import net.minecraft.world.biome.GenerationSettings; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; import java.util.Optional; public final class MinecraftUtil { + public static final Logger logger = LoggerFactory.getLogger(MinecraftUtil.class); + public static final Map> + TERRA_BIOME_MAP = new HashMap<>(); + private MinecraftUtil() { } @@ -39,4 +60,95 @@ public final class MinecraftUtil { } return null; } + + public static void registerFlora(Registry biomes) { + logger.info("Injecting flora into Terra biomes..."); + TERRA_BIOME_MAP + .forEach((vb, terraBiomes) -> + biomes.getOrEmpty(vb) + .ifPresentOrElse(vanilla -> terraBiomes + .forEach(tb -> biomes.getOrEmpty(tb) + .ifPresentOrElse( + terra -> { + List> flowerFeatures = List.copyOf(vanilla.getGenerationSettings().getFlowerFeatures()); + logger.debug("Injecting flora into biome {} : {}", tb, flowerFeatures); + ((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures(flowerFeatures); + }, + () -> logger.error( + "No such biome: {}", + tb))), + () -> logger.error("No vanilla biome: {}", vb))); + + } + + public static Map> getTerraBiomeMap() { + return Map.copyOf(TERRA_BIOME_MAP); + } + + public static RegistryKey registerKey(Identifier identifier) { + return RegistryKey.of(Registry.BIOME_KEY, identifier); + } + + public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla) { + GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); + + BiomeEffects.Builder effects = new BiomeEffects.Builder(); + + Biome.Builder builder = new Builder(); + + if(biome.getContext().has(VanillaBiomeProperties.class)) { + VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); + + effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) + .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) + .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) + .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())) + .grassColorModifier( + Objects.requireNonNullElse(vanillaBiomeProperties.getModifier(), vanilla.getEffects().getGrassColorModifier())); + + + if(vanillaBiomeProperties.getGrassColor() == null) { + vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); + } else { + effects.grassColor(vanillaBiomeProperties.getGrassColor()); + } + + if(vanillaBiomeProperties.getFoliageColor() == null) { + vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); + } else { + effects.foliageColor(vanillaBiomeProperties.getFoliageColor()); + } + + builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation())); + + } else { + effects.waterColor(vanilla.getWaterColor()) + .waterFogColor(vanilla.getWaterFogColor()) + .fogColor(vanilla.getFogColor()) + .skyColor(vanilla.getSkyColor()); + vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); + vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); + + builder.precipitation(vanilla.getPrecipitation()); + } + + vanilla.getLoopSound().ifPresent(effects::loopSound); + vanilla.getAdditionsSound().ifPresent(effects::additionsSound); + vanilla.getMoodSound().ifPresent(effects::moodSound); + vanilla.getMusic().ifPresent(effects::music); + vanilla.getParticleConfig().ifPresent(effects::particleConfig); + + return builder + .temperature(vanilla.getTemperature()) + .downfall(vanilla.getDownfall()) + .effects(effects.build()) + .spawnSettings(vanilla.getSpawnSettings()) + .generationSettings(generationSettings.build()) + .build(); + } + + public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) { + return pack.getID() + .toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT); + } } From 3b156586dc8f1bd56d8a37319d093e75e8f47801 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 21 Jun 2022 18:21:54 -0700 Subject: [PATCH 179/220] common-ify LifecycleUtil --- .../terra/api/util/generic/pair/Pair.java | 6 ++ .../dfsek/terra/fabric/FabricEntryPoint.java | 12 +++ .../com/dfsek/terra/fabric/PlatformImpl.java | 12 +++ .../client/MinecraftClientMixin.java | 6 +- .../lifecycle/server/ServerMainMixin.java | 6 +- .../com/dfsek/terra/fabric/util/TagUtil.java | 4 +- .../dfsek/terra/forge/ForgeEntryPoint.java | 16 ++- .../com/dfsek/terra/forge/PlatformImpl.java | 6 ++ .../dfsek/terra/forge/util/LifecycleUtil.java | 102 ------------------ .../com/dfsek/terra/forge/util/TagUtil.java | 4 +- .../java/com/dfsek/terra/mod/ModPlatform.java | 10 ++ .../com/dfsek/terra/mod/util/PresetUtil.java} | 71 ++++++------ 12 files changed, 97 insertions(+), 158 deletions(-) delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric/util/LifecycleUtil.java => mod-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java} (65%) diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java index ad4c2c879..4727b57e2 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.util.Objects; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -145,6 +146,11 @@ public final class Pair { } } + public Pair apply(BiConsumer consumer) { + consumer.accept(this.left, this.right); + return this; + } + @Override public String toString() { return String.format("{%s,%s}", left, right); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java index d85b330e0..ca110eccf 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -24,9 +24,14 @@ import cloud.commandframework.fabric.FabricServerCommandManager; import com.dfsek.terra.api.command.CommandSender; import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.fabric.util.BiomeUtil; +import com.dfsek.terra.mod.CommonPlatform; + import net.fabricmc.api.ModInitializer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,6 +54,13 @@ public class FabricEntryPoint implements ModInitializer { Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); } + public static void initialize() { + getPlatform().getEventManager().callEvent( + new PlatformInitializationEvent()); + BiomeUtil.registerBiomes(); + CommonPlatform.get().registerWorldTypes((id, preset) -> BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, id, preset)); + } + @Override public void onInitialize() { logger.info("Initializing Terra Fabric mod..."); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java index efa3bfe17..66ddb8c67 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java @@ -25,9 +25,18 @@ import com.dfsek.terra.fabric.util.BiomeUtil; import com.dfsek.terra.mod.CommonPlatform; import com.dfsek.terra.mod.ModPlatform; +import com.dfsek.terra.mod.generation.TerraBiomeSource; + +import com.dfsek.terra.mod.util.PresetUtil; + import net.fabricmc.loader.api.FabricLoader; import net.minecraft.MinecraftVersion; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.world.dimension.DimensionOptions; +import net.minecraft.world.gen.WorldPreset; +import net.minecraft.world.gen.chunk.ChunkGenerator; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +44,9 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.BiConsumer; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java index 620ebf100..b605d8cdb 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java @@ -17,8 +17,6 @@ package com.dfsek.terra.fabric.mixin.lifecycle.client; -import com.dfsek.terra.fabric.util.LifecycleUtil; - import net.minecraft.client.MinecraftClient; import net.minecraft.client.RunArgs; import org.spongepowered.asm.mixin.Mixin; @@ -26,9 +24,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.fabric.FabricEntryPoint; -import com.dfsek.terra.fabric.util.BiomeUtil; @Mixin(MinecraftClient.class) @@ -40,6 +36,6 @@ public class MinecraftClientMixin { // sorta arbitrary position, after mod init, before window opens shift = At.Shift.BEFORE)) public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { - LifecycleUtil.initialize(); + FabricEntryPoint.initialize(); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java index ecf5e933b..16e107631 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java @@ -17,16 +17,12 @@ package com.dfsek.terra.fabric.mixin.lifecycle.server; -import com.dfsek.terra.fabric.util.BiomeUtil; -import com.dfsek.terra.fabric.util.LifecycleUtil; - import net.minecraft.server.Main; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.fabric.FabricEntryPoint; @@ -39,6 +35,6 @@ public class ServerMainMixin { // after registry manager creation ) private static void injectConstructor(String[] args, CallbackInfo ci) { - LifecycleUtil.initialize(); + FabricEntryPoint.initialize(); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java index 78c180283..f921cba34 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java @@ -2,6 +2,8 @@ package com.dfsek.terra.fabric.util; import com.dfsek.terra.mod.util.MinecraftUtil; +import com.dfsek.terra.mod.util.PresetUtil; + import com.google.common.collect.ImmutableMap; import net.minecraft.tag.TagKey; import net.minecraft.tag.WorldPresetTags; @@ -38,7 +40,7 @@ public final class TagUtil { logger.info("Doing preset tag garbage...."); Map, List>> collect = tagsToMutableMap(registry); - LifecycleUtil + PresetUtil .getPresets() .forEach(id -> MinecraftUtil .getEntry(registry, id) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 5208f01ec..dbc919781 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -17,8 +17,12 @@ package com.dfsek.terra.forge; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.forge.util.BiomeUtil; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.Biome; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -28,12 +32,12 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.ForgeRegistries.Keys; import net.minecraftforge.registries.RegisterEvent; +import net.minecraftforge.registries.RegisterEvent.RegisterHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.dfsek.terra.forge.AwfulForgeHacks.RegistrySanityCheck; import com.dfsek.terra.forge.AwfulForgeHacks.RegistryStep; -import com.dfsek.terra.forge.util.LifecycleUtil; import com.dfsek.terra.mod.data.Codecs; @@ -62,11 +66,17 @@ public class ForgeEntryPoint { modEventBus.register(this); } + public static void initialize(RegisterHelper helper) { + getPlatform().getEventManager().callEvent( + new PlatformInitializationEvent()); + BiomeUtil.registerBiomes(helper); + } + @SubscribeEvent(priority = EventPriority.LOWEST) public void registerBiomes(RegisterEvent event) { event.register(Keys.BLOCKS, helper -> sanityCheck.progress(RegistryStep.BLOCK, () -> logger.debug("Block registration detected."))); - event.register(Keys.BIOMES, helper -> sanityCheck.progress(RegistryStep.BIOME, () -> LifecycleUtil.initialize(helper))); - event.register(Registry.WORLD_PRESET_KEY, helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> LifecycleUtil.registerWorldTypes(helper))); + event.register(Keys.BIOMES, helper -> sanityCheck.progress(RegistryStep.BIOME, () -> initialize(helper))); + event.register(Registry.WORLD_PRESET_KEY, helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> TERRA_PLUGIN.registerWorldTypes(helper::register))); event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER)); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index 294fa01d9..b3996a9d8 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -20,8 +20,13 @@ package com.dfsek.terra.forge; import ca.solostudios.strata.Versions; import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.version.Version; + +import com.dfsek.terra.mod.util.PresetUtil; + import net.minecraft.MinecraftVersion; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.Identifier; +import net.minecraft.world.gen.WorldPreset; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.server.ServerLifecycleHooks; import org.jetbrains.annotations.NotNull; @@ -31,6 +36,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.function.BiConsumer; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java deleted file mode 100644 index abaabaa0e..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/LifecycleUtil.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.dfsek.terra.forge.util; - -import net.minecraft.structure.StructureSet; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryEntry; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.MultiNoiseBiomeSource; -import net.minecraft.world.biome.source.TheEndBiomeSource; -import net.minecraft.world.dimension.DimensionOptions; -import net.minecraft.world.dimension.DimensionType; -import net.minecraft.world.dimension.DimensionTypes; -import net.minecraft.world.gen.WorldPreset; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; -import net.minecraft.world.gen.chunk.NoiseChunkGenerator; -import net.minecraftforge.registries.RegisterEvent.RegisterHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; -import com.dfsek.terra.forge.ForgeEntryPoint; -import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; -import com.dfsek.terra.mod.generation.TerraBiomeSource; - - -public class LifecycleUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleUtil.class); - - private static final List PRESETS = new ArrayList<>(); - public static void initialize(RegisterHelper helper) { - ForgeEntryPoint.getPlatform().getEventManager().callEvent( - new PlatformInitializationEvent()); - BiomeUtil.registerBiomes(helper); - } - - public static void registerWorldTypes(RegisterHelper helper) { - LOGGER.info("Registering Terra world types..."); - - Registry dimensionTypeRegistry = BuiltinRegistries.DIMENSION_TYPE; - Registry chunkGeneratorSettingsRegistry = BuiltinRegistries.CHUNK_GENERATOR_SETTINGS; - Registry structureSetRegistry = BuiltinRegistries.STRUCTURE_SET; - Registry noiseParametersRegistry = BuiltinRegistries.NOISE_PARAMETERS; - Registry biomeRegistry = BuiltinRegistries.BIOME; - - RegistryEntry theNetherDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_NETHER); - RegistryEntry - netherChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.NETHER); - DimensionOptions netherDimensionOptions = new DimensionOptions(theNetherDimensionType, - new NoiseChunkGenerator(structureSetRegistry, - noiseParametersRegistry, - MultiNoiseBiomeSource.Preset.NETHER.getBiomeSource( - biomeRegistry), - netherChunkGeneratorSettings)); - RegistryEntry theEndDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_END); - RegistryEntry endChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry( - ChunkGeneratorSettings.END); - DimensionOptions endDimensionOptions = new DimensionOptions(theEndDimensionType, - new NoiseChunkGenerator(structureSetRegistry, noiseParametersRegistry, - new TheEndBiomeSource(biomeRegistry), - endChunkGeneratorSettings)); - - RegistryEntry overworldDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.OVERWORLD); - - RegistryEntry overworld = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.OVERWORLD); - ForgeEntryPoint - .getPlatform() - .getRawConfigRegistry() - .forEach((id, pack) -> { - Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( - Locale.ROOT)); - - PRESETS.add(generatorID); - - TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); - ChunkGenerator generator = new MinecraftChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); - - DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); - WorldPreset preset = new WorldPreset( - Map.of( - DimensionOptions.OVERWORLD, dimensionOptions, - DimensionOptions.NETHER, netherDimensionOptions, - DimensionOptions.END, endDimensionOptions - ) - ); - helper.register(generatorID, preset); - LOGGER.info("Registered world type \"{}\"", generatorID); - } - ); - } - - public static List getPresets() { - return PRESETS; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java index 38a1e2237..462a6719e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java @@ -2,6 +2,8 @@ package com.dfsek.terra.forge.util; import com.dfsek.terra.mod.util.MinecraftUtil; +import com.dfsek.terra.mod.util.PresetUtil; + import com.google.common.collect.ImmutableMap; import net.minecraft.tag.TagKey; import net.minecraft.tag.WorldPresetTags; @@ -38,7 +40,7 @@ public final class TagUtil { logger.info("Doing preset tag garbage...."); Map, List>> collect = tagsToMutableMap(registry); - LifecycleUtil + PresetUtil .getPresets() .forEach(id -> MinecraftUtil .getEntry(registry, id) diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java index 48fa219c2..5a75d0cc2 100644 --- a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java @@ -12,6 +12,8 @@ import com.dfsek.terra.api.world.biome.PlatformBiome; import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.util.PresetUtil; + import net.minecraft.command.CommandSource; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Identifier; @@ -19,14 +21,22 @@ import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; +import net.minecraft.world.gen.WorldPreset; import java.util.List; import java.util.Locale; +import java.util.function.BiConsumer; +import java.util.function.Consumer; public abstract class ModPlatform extends AbstractPlatform { public abstract MinecraftServer getServer(); + public void registerWorldTypes(BiConsumer registerFunction) { + getRawConfigRegistry() + .forEach(pack -> PresetUtil.createDefault(pack).apply(registerFunction)); + } + @Override public void register(TypeRegistry registry) { super.register(registry); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/LifecycleUtil.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java similarity index 65% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/LifecycleUtil.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java index d91d4e263..7b3e57ca5 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/LifecycleUtil.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java @@ -1,7 +1,8 @@ -package com.dfsek.terra.fabric.util; +package com.dfsek.terra.mod.util; -import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; -import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.api.config.ConfigPack; + +import com.dfsek.terra.api.util.generic.pair.Pair; import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; import com.dfsek.terra.mod.generation.TerraBiomeSource; @@ -30,24 +31,17 @@ import java.util.Locale; import java.util.Map; -public class LifecycleUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleUtil.class); - +public class PresetUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(PresetUtil.class); private static final List PRESETS = new ArrayList<>(); - public static void initialize() { - FabricEntryPoint.getPlatform().getEventManager().callEvent( - new PlatformInitializationEvent()); - BiomeUtil.registerBiomes(); - - - LOGGER.info("Registering Terra world types..."); - + + public static Pair createDefault(ConfigPack pack) { Registry dimensionTypeRegistry = BuiltinRegistries.DIMENSION_TYPE; Registry chunkGeneratorSettingsRegistry = BuiltinRegistries.CHUNK_GENERATOR_SETTINGS; Registry structureSetRegistry = BuiltinRegistries.STRUCTURE_SET; Registry noiseParametersRegistry = BuiltinRegistries.NOISE_PARAMETERS; Registry biomeRegistry = BuiltinRegistries.BIOME; - + RegistryEntry theNetherDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_NETHER); RegistryEntry netherChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.NETHER); @@ -64,34 +58,29 @@ public class LifecycleUtil { new NoiseChunkGenerator(structureSetRegistry, noiseParametersRegistry, new TheEndBiomeSource(biomeRegistry), endChunkGeneratorSettings)); - + RegistryEntry overworldDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.OVERWORLD); - + RegistryEntry overworld = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.OVERWORLD); - FabricEntryPoint - .getPlatform() - .getRawConfigRegistry() - .forEach((id, pack) -> { - Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( - Locale.ROOT)); - - PRESETS.add(generatorID); - - TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); - ChunkGenerator generator = new MinecraftChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); - - DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); - WorldPreset preset = new WorldPreset( - Map.of( - DimensionOptions.OVERWORLD, dimensionOptions, - DimensionOptions.NETHER, netherDimensionOptions, - DimensionOptions.END, endDimensionOptions - ) - ); - BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, generatorID, preset); - LOGGER.info("Registered world type \"{}\"", generatorID); - } - ); + + Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( + Locale.ROOT)); + + PRESETS.add(generatorID); + + TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); + ChunkGenerator generator = new MinecraftChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); + + DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); + WorldPreset preset = new WorldPreset( + Map.of( + DimensionOptions.OVERWORLD, dimensionOptions, + DimensionOptions.NETHER, netherDimensionOptions, + DimensionOptions.END, endDimensionOptions + ) + ); + LOGGER.info("Created world type \"{}\"", generatorID); + return Pair.of(generatorID, preset); } public static List getPresets() { From 2ae4f8035101cb09149a81481decab05a430c84c Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 22 Jun 2022 06:10:41 -0700 Subject: [PATCH 180/220] move tagutil into common --- .../lifecycle/DataPackContentsMixin.java | 2 +- .../com/dfsek/terra/fabric/util/TagUtil.java | 107 ------------------ .../lifecycle/DataPackContentsMixin.java | 3 +- .../com/dfsek/terra/mod}/util/TagUtil.java | 6 +- 4 files changed, 4 insertions(+), 114 deletions(-) delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java rename platforms/{forge/src/main/java/com/dfsek/terra/forge => mod-common/src/main/java/com/dfsek/terra/mod}/util/TagUtil.java (97%) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java index e355e4f2d..5dcb1de72 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java @@ -1,6 +1,6 @@ package com.dfsek.terra.fabric.mixin.lifecycle; -import com.dfsek.terra.fabric.util.TagUtil; +import com.dfsek.terra.mod.util.TagUtil; import com.dfsek.terra.mod.util.MinecraftUtil; import net.minecraft.server.DataPackContents; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java deleted file mode 100644 index f921cba34..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.dfsek.terra.fabric.util; - -import com.dfsek.terra.mod.util.MinecraftUtil; - -import com.dfsek.terra.mod.util.PresetUtil; - -import com.google.common.collect.ImmutableMap; -import net.minecraft.tag.TagKey; -import net.minecraft.tag.WorldPresetTags; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryEntry; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.WorldPreset; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -public final class TagUtil { - private static final Logger logger = LoggerFactory.getLogger(TagUtil.class); - - private TagUtil() { - - } - - private static Map, List>> tagsToMutableMap(Registry registry) { - return registry - .streamTagsAndEntries() - .collect(HashMap::new, - (map, pair) -> - map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), - HashMap::putAll); - } - - public static void registerWorldPresetTags(Registry registry) { - logger.info("Doing preset tag garbage...."); - Map, List>> collect = tagsToMutableMap(registry); - - PresetUtil - .getPresets() - .forEach(id -> MinecraftUtil - .getEntry(registry, id) - .ifPresentOrElse( - preset -> collect - .computeIfAbsent(WorldPresetTags.NORMAL, tag -> new ArrayList<>()) - .add(preset), - () -> logger.error("Preset {} does not exist!", id))); - - registry.clearTags(); - registry.populateTags(ImmutableMap.copyOf(collect)); - } - - public static void registerBiomeTags(Registry registry) { - logger.info("Doing biome tag garbage...."); - Map, List>> collect = tagsToMutableMap(registry); - - MinecraftUtil - .getTerraBiomeMap() - .forEach((vb, terraBiomes) -> - MinecraftUtil - .getEntry(registry, vb) - .ifPresentOrElse( - vanilla -> terraBiomes - .forEach(tb -> MinecraftUtil - .getEntry(registry, tb) - .ifPresentOrElse( - terra -> { - logger.debug( - vanilla.getKey() - .orElseThrow() - .getValue() + - " (vanilla for " + - terra.getKey() - .orElseThrow() - .getValue() + - ": " + - vanilla.streamTags() - .toList()); - - vanilla.streamTags() - .forEach( - tag -> collect - .computeIfAbsent( - tag, - t -> new ArrayList<>()) - .add(terra)); - }, - () -> logger.error( - "No such biome: {}", - tb))), - () -> logger.error("No vanilla biome: {}", vb))); - - registry.clearTags(); - registry.populateTags(ImmutableMap.copyOf(collect)); - - if(logger.isDebugEnabled()) { - registry.streamEntries() - .map(e -> e.registryKey().getValue() + ": " + - e.streamTags().reduce("", (s, t) -> t.id() + ", " + s, String::concat)) - .forEach(logger::debug); - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java index b7db9106a..99e886389 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java @@ -1,9 +1,10 @@ package com.dfsek.terra.forge.mixin.lifecycle; import com.dfsek.terra.forge.util.BiomeUtil; -import com.dfsek.terra.forge.util.TagUtil; import com.dfsek.terra.mod.util.MinecraftUtil; +import com.dfsek.terra.mod.util.TagUtil; + import net.minecraft.server.DataPackContents; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java similarity index 97% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java index 462a6719e..8edf50afc 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/TagUtil.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java @@ -1,8 +1,4 @@ -package com.dfsek.terra.forge.util; - -import com.dfsek.terra.mod.util.MinecraftUtil; - -import com.dfsek.terra.mod.util.PresetUtil; +package com.dfsek.terra.mod.util; import com.google.common.collect.ImmutableMap; import net.minecraft.tag.TagKey; From 42cf7b95437c38b4d510b0d9df5f7aecc9ce74c2 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 22 Jun 2022 06:31:38 -0700 Subject: [PATCH 181/220] move DataPackContentsMixin to common --- .../main/resources/terra.fabric.mixins.json | 1 - .../lifecycle/DataPackContentsMixin.java | 31 ------- .../main/resources/terra.forge.mixins.json | 1 - .../lifecycle/DataPackContentsMixin.java | 2 +- .../main/resources/terra.common.mixins.json | 89 ++++++++++--------- 5 files changed, 46 insertions(+), 78 deletions(-) delete mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mod-common/src/main/java/com/dfsek/terra/mod}/mixin/lifecycle/DataPackContentsMixin.java (95%) diff --git a/platforms/fabric/src/main/resources/terra.fabric.mixins.json b/platforms/fabric/src/main/resources/terra.fabric.mixins.json index d28c0541c..52882ee43 100644 --- a/platforms/fabric/src/main/resources/terra.fabric.mixins.json +++ b/platforms/fabric/src/main/resources/terra.fabric.mixins.json @@ -4,7 +4,6 @@ "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "lifecycle.DataPackContentsMixin", "lifecycle.MinecraftServerMixin", "lifecycle.NoiseConfigMixin", "lifecycle.RegistryMixin" diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java deleted file mode 100644 index 99e886389..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/DataPackContentsMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.forge.mixin.lifecycle; - -import com.dfsek.terra.forge.util.BiomeUtil; -import com.dfsek.terra.mod.util.MinecraftUtil; - -import com.dfsek.terra.mod.util.TagUtil; - -import net.minecraft.server.DataPackContents; -import net.minecraft.util.registry.DynamicRegistryManager; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.biome.Biome; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - - -@Mixin(DataPackContents.class) -public class DataPackContentsMixin { - /* - * #refresh populates all tags in the registries - */ - @Inject(method = "refresh(Lnet/minecraft/util/registry/DynamicRegistryManager;)V", at = @At("RETURN")) - private void injectReload(DynamicRegistryManager dynamicRegistryManager, CallbackInfo ci) { - TagUtil.registerWorldPresetTags(dynamicRegistryManager.get(Registry.WORLD_PRESET_KEY)); - - Registry biomeRegistry = dynamicRegistryManager.get(Registry.BIOME_KEY); - TagUtil.registerBiomeTags(biomeRegistry); - MinecraftUtil.registerFlora(biomeRegistry); - } -} diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index a1316f288..355d77483 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -4,7 +4,6 @@ "package": "com.dfsek.terra.forge.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "lifecycle.DataPackContentsMixin", "lifecycle.NoiseConfigMixin" ], "client": [ diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java similarity index 95% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java rename to platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java index 5dcb1de72..d18fbf8d2 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java +++ b/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric.mixin.lifecycle; +package com.dfsek.terra.mod.mixin.lifecycle; import com.dfsek.terra.mod.util.TagUtil; import com.dfsek.terra.mod.util.MinecraftUtil; diff --git a/platforms/mod-common/src/main/resources/terra.common.mixins.json b/platforms/mod-common/src/main/resources/terra.common.mixins.json index c8142c28a..b084bee6f 100644 --- a/platforms/mod-common/src/main/resources/terra.common.mixins.json +++ b/platforms/mod-common/src/main/resources/terra.common.mixins.json @@ -1,46 +1,47 @@ { - "required": true, - "minVersion": "0.8", - "package": "com.dfsek.terra.mod.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - "access.MobSpawnerLogicAccessor", - "access.StateAccessor", - "access.StructureAccessorAccessor", - "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", - "fix.NetherFossilOptimization", - "implementations.compat.GenerationSettingsFloraFeaturesMixin", - "implementations.terra.BiomeMixin", - "implementations.terra.HandleImplementationMixin", - "implementations.terra.block.BlockMixin", - "implementations.terra.block.entity.BlockEntityMixin", - "implementations.terra.block.entity.LootableContainerBlockEntityMixin", - "implementations.terra.block.entity.MobSpawnerBlockEntityMixin", - "implementations.terra.block.entity.SignBlockEntityMixin", - "implementations.terra.block.state.BlockStateMixin", - "implementations.terra.block.state.PropertyMixin", - "implementations.terra.chunk.ChunkRegionMixin", - "implementations.terra.chunk.WorldChunkMixin", - "implementations.terra.chunk.data.ProtoChunkMixin", - "implementations.terra.entity.EntityMixin", - "implementations.terra.entity.EntityTypeMixin", - "implementations.terra.entity.PlayerEntityMixin", - "implementations.terra.entity.ServerCommandSourceMixin", - "implementations.terra.inventory.LockableContainerBlockEntityMixin", - "implementations.terra.inventory.item.ItemMixin", - "implementations.terra.inventory.item.ItemStackMixin", - "implementations.terra.inventory.meta.EnchantmentMixin", - "implementations.terra.inventory.meta.ItemStackDamageableMixin", - "implementations.terra.inventory.meta.ItemStackMetaMixin", - "implementations.terra.world.ChunkRegionMixin", - "implementations.terra.world.ServerWorldMixin" - ], - "client": [ - ], - "server": [ - ], - "injectors": { - "defaultRequire": 1 - }, - "refmap": "terra-common-refmap.json" + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.mod.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "access.MobSpawnerLogicAccessor", + "access.StateAccessor", + "access.StructureAccessorAccessor", + "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", + "fix.NetherFossilOptimization", + "implementations.compat.GenerationSettingsFloraFeaturesMixin", + "implementations.terra.BiomeMixin", + "implementations.terra.HandleImplementationMixin", + "implementations.terra.block.BlockMixin", + "implementations.terra.block.entity.BlockEntityMixin", + "implementations.terra.block.entity.LootableContainerBlockEntityMixin", + "implementations.terra.block.entity.MobSpawnerBlockEntityMixin", + "implementations.terra.block.entity.SignBlockEntityMixin", + "implementations.terra.block.state.BlockStateMixin", + "implementations.terra.block.state.PropertyMixin", + "implementations.terra.chunk.ChunkRegionMixin", + "implementations.terra.chunk.WorldChunkMixin", + "implementations.terra.chunk.data.ProtoChunkMixin", + "implementations.terra.entity.EntityMixin", + "implementations.terra.entity.EntityTypeMixin", + "implementations.terra.entity.PlayerEntityMixin", + "implementations.terra.entity.ServerCommandSourceMixin", + "implementations.terra.inventory.LockableContainerBlockEntityMixin", + "implementations.terra.inventory.item.ItemMixin", + "implementations.terra.inventory.item.ItemStackMixin", + "implementations.terra.inventory.meta.EnchantmentMixin", + "implementations.terra.inventory.meta.ItemStackDamageableMixin", + "implementations.terra.inventory.meta.ItemStackMetaMixin", + "implementations.terra.world.ChunkRegionMixin", + "implementations.terra.world.ServerWorldMixin", + "lifecycle.DataPackContentsMixin" + ], + "client": [ + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "terra-common-refmap.json" } \ No newline at end of file From 3139416b358cae01c20c9bebd99f8be77a65a392 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 22 Jun 2022 07:23:39 -0700 Subject: [PATCH 182/220] rename mod-common to mixin-common --- platforms/fabric/build.gradle.kts | 4 ++-- platforms/forge/build.gradle.kts | 6 +++--- platforms/{mod-common => mixin-common}/README.md | 0 platforms/{mod-common => mixin-common}/build.gradle.kts | 0 .../src/main/java/com/dfsek/terra/mod/CommonPlatform.java | 0 .../src/main/java/com/dfsek/terra/mod/MinecraftAddon.java | 0 .../src/main/java/com/dfsek/terra/mod/ModPlatform.java | 0 .../terra/mod/config/PostLoadCompatibilityOptions.java | 0 .../dfsek/terra/mod/config/PreLoadCompatibilityOptions.java | 0 .../java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java | 0 .../com/dfsek/terra/mod/config/VanillaBiomeProperties.java | 0 .../src/main/java/com/dfsek/terra/mod/data/Codecs.java | 0 .../mod/generation/MinecraftChunkGeneratorWrapper.java | 0 .../com/dfsek/terra/mod/generation/TerraBiomeSource.java | 0 .../com/dfsek/terra/mod/handle/MinecraftItemHandle.java | 0 .../com/dfsek/terra/mod/handle/MinecraftWorldHandle.java | 0 .../terra/mod/mixin/access/MobSpawnerLogicAccessor.java | 0 .../com/dfsek/terra/mod/mixin/access/StateAccessor.java | 0 .../terra/mod/mixin/access/StructureAccessorAccessor.java | 0 .../fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java | 0 .../dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java | 0 .../compat/GenerationSettingsFloraFeaturesMixin.java | 0 .../terra/mod/mixin/implementations/terra/BiomeMixin.java | 0 .../implementations/terra/HandleImplementationMixin.java | 0 .../mod/mixin/implementations/terra/block/BlockMixin.java | 0 .../terra/block/entity/BlockEntityMixin.java | 0 .../block/entity/LootableContainerBlockEntityMixin.java | 0 .../terra/block/entity/MobSpawnerBlockEntityMixin.java | 0 .../terra/block/entity/SignBlockEntityMixin.java | 0 .../implementations/terra/block/state/BlockStateMixin.java | 0 .../implementations/terra/block/state/PropertyMixin.java | 0 .../mixin/implementations/terra/chunk/ChunkRegionMixin.java | 0 .../mixin/implementations/terra/chunk/WorldChunkMixin.java | 0 .../implementations/terra/chunk/data/ProtoChunkMixin.java | 0 .../mod/mixin/implementations/terra/entity/EntityMixin.java | 0 .../mixin/implementations/terra/entity/EntityTypeMixin.java | 0 .../implementations/terra/entity/PlayerEntityMixin.java | 0 .../terra/entity/ServerCommandSourceMixin.java | 0 .../terra/inventory/LockableContainerBlockEntityMixin.java | 0 .../implementations/terra/inventory/item/ItemMixin.java | 0 .../terra/inventory/item/ItemStackMixin.java | 0 .../terra/inventory/meta/EnchantmentMixin.java | 0 .../terra/inventory/meta/ItemStackDamageableMixin.java | 0 .../terra/inventory/meta/ItemStackMetaMixin.java | 0 .../terra/mod/mixin/implementations/terra/package-info.java | 0 .../mixin/implementations/terra/world/ChunkRegionMixin.java | 0 .../mixin/implementations/terra/world/ServerWorldMixin.java | 0 .../terra/mod/mixin/lifecycle/DataPackContentsMixin.java | 0 .../dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java | 0 .../java/com/dfsek/terra/mod/util/MinecraftAdapter.java | 0 .../main/java/com/dfsek/terra/mod/util/MinecraftUtil.java | 0 .../src/main/java/com/dfsek/terra/mod/util/PresetUtil.java | 0 .../src/main/java/com/dfsek/terra/mod/util/SeedHack.java | 0 .../src/main/java/com/dfsek/terra/mod/util/TagUtil.java | 0 .../src/main/resources/fabric.mod.json | 0 .../src/main/resources/terra.common.mixins.json | 0 56 files changed, 5 insertions(+), 5 deletions(-) rename platforms/{mod-common => mixin-common}/README.md (100%) rename platforms/{mod-common => mixin-common}/build.gradle.kts (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/CommonPlatform.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/ModPlatform.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/config/PostLoadCompatibilityOptions.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/config/PreLoadCompatibilityOptions.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/data/Codecs.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/access/MobSpawnerLogicAccessor.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/access/StateAccessor.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/access/StructureAccessorAccessor.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/BiomeMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/HandleImplementationMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/BlockMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/BlockEntityMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/PropertyMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/ChunkRegionMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/WorldChunkMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityTypeMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/PlayerEntityMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/ServerCommandSourceMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/package-info.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/util/SeedHack.java (100%) rename platforms/{mod-common => mixin-common}/src/main/java/com/dfsek/terra/mod/util/TagUtil.java (100%) rename platforms/{mod-common => mixin-common}/src/main/resources/fabric.mod.json (100%) rename platforms/{mod-common => mixin-common}/src/main/resources/terra.common.mixins.json (100%) diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 2af355a9a..4b7d3c70e 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -22,8 +22,8 @@ dependencies { "annotationProcessor"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") "annotationProcessor"("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") - "common"(project(path = ":platforms:mod-common", configuration = "namedElements")) { isTransitive = false } - shaded(project(path = ":platforms:mod-common", configuration = "transformProductionFabric")) { isTransitive = false } + "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionFabric")) { isTransitive = false } minecraft("com.mojang:minecraft:${Versions.Fabric.minecraft}") mappings("net.fabricmc:yarn:${Versions.Fabric.yarn}:v2") diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 9fcf26433..b09a9a1b1 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -18,9 +18,9 @@ configurations { dependencies { shadedApi(project(":common:implementation:base")) - "common"(project(path = ":platforms:mod-common", configuration = "namedElements")) { isTransitive = false } - shaded(project(path = ":platforms:mod-common", configuration = "transformProductionForge")) { isTransitive = false } - "developmentForge"(project(":platforms:mod-common", configuration = "namedElements")) { + "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionForge")) { isTransitive = false } + "developmentForge"(project(":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } diff --git a/platforms/mod-common/README.md b/platforms/mixin-common/README.md similarity index 100% rename from platforms/mod-common/README.md rename to platforms/mixin-common/README.md diff --git a/platforms/mod-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts similarity index 100% rename from platforms/mod-common/build.gradle.kts rename to platforms/mixin-common/build.gradle.kts diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/CommonPlatform.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/CommonPlatform.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/CommonPlatform.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/CommonPlatform.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PostLoadCompatibilityOptions.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/PostLoadCompatibilityOptions.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PostLoadCompatibilityOptions.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/PostLoadCompatibilityOptions.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PreLoadCompatibilityOptions.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/PreLoadCompatibilityOptions.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/PreLoadCompatibilityOptions.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/PreLoadCompatibilityOptions.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/MobSpawnerLogicAccessor.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/MobSpawnerLogicAccessor.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/MobSpawnerLogicAccessor.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/MobSpawnerLogicAccessor.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StateAccessor.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/StateAccessor.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StateAccessor.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/StateAccessor.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StructureAccessorAccessor.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/StructureAccessorAccessor.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/access/StructureAccessorAccessor.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/StructureAccessorAccessor.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/BiomeMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/BiomeMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/BiomeMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/BiomeMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/HandleImplementationMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/HandleImplementationMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/HandleImplementationMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/HandleImplementationMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/BlockMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/BlockMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/BlockMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/BlockMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/BlockEntityMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/BlockEntityMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/BlockEntityMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/BlockEntityMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/LootableContainerBlockEntityMixin.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/SignBlockEntityMixin.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/PropertyMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/PropertyMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/PropertyMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/PropertyMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/ChunkRegionMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/ChunkRegionMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/ChunkRegionMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/ChunkRegionMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/WorldChunkMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/WorldChunkMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/WorldChunkMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/WorldChunkMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityTypeMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityTypeMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityTypeMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityTypeMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/PlayerEntityMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/PlayerEntityMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/PlayerEntityMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/PlayerEntityMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/ServerCommandSourceMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/ServerCommandSourceMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/ServerCommandSourceMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/ServerCommandSourceMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/LockableContainerBlockEntityMixin.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackDamageableMixin.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/package-info.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/package-info.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/package-info.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/package-info.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin_ifaces/FloraFeatureHolder.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftAdapter.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java diff --git a/platforms/mod-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 similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/SeedHack.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/SeedHack.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/SeedHack.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/SeedHack.java diff --git a/platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java similarity index 100% rename from platforms/mod-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java rename to platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java diff --git a/platforms/mod-common/src/main/resources/fabric.mod.json b/platforms/mixin-common/src/main/resources/fabric.mod.json similarity index 100% rename from platforms/mod-common/src/main/resources/fabric.mod.json rename to platforms/mixin-common/src/main/resources/fabric.mod.json diff --git a/platforms/mod-common/src/main/resources/terra.common.mixins.json b/platforms/mixin-common/src/main/resources/terra.common.mixins.json similarity index 100% rename from platforms/mod-common/src/main/resources/terra.common.mixins.json rename to platforms/mixin-common/src/main/resources/terra.common.mixins.json From 0997326aefbfc75b1054cee729fb551ee031c40a Mon Sep 17 00:00:00 2001 From: Astrashh Date: Fri, 24 Jun 2022 17:53:54 +1000 Subject: [PATCH 183/220] Use correct dimensions in TS sampler function --- .../addons/terrascript/sampler/SamplerFunctionBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java index 98ac7fca3..07ce640fd 100644 --- a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java @@ -61,7 +61,7 @@ public class SamplerFunctionBuilder implements FunctionBuilder) argumentList.get(1), (Returnable) argumentList.get(2), @@ -73,7 +73,7 @@ public class SamplerFunctionBuilder implements FunctionBuilder) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), - s -> Objects.requireNonNull(samplers2d.get(s.get()), "No such 2D noise function " + s.get()) + s -> Objects.requireNonNull(samplers3d.get(s.get()), "No such 3D noise function " + s.get()) .getSampler(), true, position); From e4d05312aac1f30ad71c61b6e07a87e2b36edef9 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 24 Jun 2022 16:00:35 -0700 Subject: [PATCH 184/220] ignore mixins from common package in AwfulForgeHacks --- .../src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java index 5565fd1ba..0ddb92caa 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java @@ -61,7 +61,8 @@ public final class AwfulForgeHacks { try(JarFile jar = getTerraJar()) { jar.stream() .forEach(jarEntry -> { - if(jarEntry.getName().startsWith("com/dfsek/terra/forge/mixin")) { + if(jarEntry.getName().startsWith("com/dfsek/terra/forge/mixin") + || jarEntry.getName().startsWith("com/dfsek/terra/mod/mixin")) { return; } if(jarEntry.getName().endsWith(".class")) { From cffdf7aeeb836e6f708955bbcc421b173cf335b4 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 24 Jun 2022 16:00:47 -0700 Subject: [PATCH 185/220] use Fabric Loom --- platforms/fabric/build.gradle.kts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 4b7d3c70e..4020713db 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -1,13 +1,8 @@ plugins { - id("dev.architectury.loom") version Versions.Mod.architecuryLoom - id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("fabric-loom") version Versions.Fabric.loom id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower } -architectury { - fabric() -} - configurations { val common by creating From b05852e0746c9a2664f10b0c10c8accba46285d4 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 24 Jun 2022 17:50:40 -0700 Subject: [PATCH 186/220] make slf4j testImplementation --- common/api/build.gradle.kts | 1 + common/implementation/base/build.gradle.kts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/common/api/build.gradle.kts b/common/api/build.gradle.kts index fe36f682e..2fce99b17 100644 --- a/common/api/build.gradle.kts +++ b/common/api/build.gradle.kts @@ -1,6 +1,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("com.dfsek.tectonic", "common", Versions.Libraries.tectonic) diff --git a/common/implementation/base/build.gradle.kts b/common/implementation/base/build.gradle.kts index 64c176c77..1910484f0 100644 --- a/common/implementation/base/build.gradle.kts +++ b/common/implementation/base/build.gradle.kts @@ -2,6 +2,8 @@ dependencies { api(project(":common:api")) api(project(":common:implementation:bootstrap-addon-loader")) + testImplementation("org.slf4j", "slf4j-api", Versions.Libraries.slf4j) + implementation("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO) implementation("org.apache.commons", "commons-text", Versions.Libraries.Internal.apacheText) From dbd5edabae9da3fd7c22da68b159a02207caaaba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Sun, 26 Jun 2022 21:48:38 -0700 Subject: [PATCH 187/220] Imports --- .../src/main/kotlin/DistributionConfig.kt | 3 -- .../biome/extrusion/BiomeExtrusionAddon.java | 5 +-- .../extrusion/BiomeExtrusionProvider.java | 2 - .../addons/biome/extrusion/api/Extrusion.java | 4 +- .../biome/extrusion/api/ReplaceableBiome.java | 4 +- .../addons/biome/extrusion/api/SelfBiome.java | 4 +- .../config/BiomeExtrusionTemplate.java | 4 +- .../extrusions/ReplaceExtrusionTemplate.java | 1 - .../extrusions/ReplaceExtrusion.java | 8 ++-- .../extrusion/extrusions/SetExtrusion.java | 8 ++-- .../biome/pipeline/BiomePipelineColumn.java | 4 +- .../biome/pipeline/BiomePipelineProvider.java | 5 +-- .../biome/query/BiomeQueryAPIAddon.java | 4 +- .../addons/biome/query/api/BiomeQueries.java | 4 +- .../biome/query/impl/SingleTagQuery.java | 4 +- .../noise/BiomeNoiseConfigTemplate.java | 1 - .../config/noise/BiomeNoiseProperties.java | 1 - .../generation/NoiseChunkGenerator3D.java | 6 +-- .../math/interpolation/ChunkInterpolator.java | 4 +- .../LazilyEvaluatedInterpolator.java | 3 +- .../locators/AdjacentPatternLocator.java | 1 - .../locator/locators/PatternLocator.java | 4 +- .../locator/locators/SurfaceLocator.java | 4 +- .../locator/patterns/MatchPattern.java | 5 +-- .../feature/locator/patterns/Pattern.java | 3 -- .../feature/FeatureGenerationStage.java | 6 +-- .../addons/terrascript/parser/lang/Scope.java | 7 ++-- .../lang/keywords/looplike/IfKeyword.java | 3 +- .../lang/operations/BinaryOperation.java | 4 -- .../lang/operations/BooleanAndOperation.java | 2 - .../lang/operations/BooleanOrOperation.java | 2 - .../lang/operations/DivisionOperation.java | 2 - .../lang/operations/ModuloOperation.java | 2 - .../operations/MultiplicationOperation.java | 2 - .../operations/NumberAdditionOperation.java | 2 - .../lang/operations/SubtractionOperation.java | 2 - .../lang/operations/UnaryOperation.java | 2 - .../statements/EqualsStatement.java | 7 +--- .../GreaterOrEqualsThanStatement.java | 2 - .../statements/GreaterThanStatement.java | 2 - .../statements/LessThanOrEqualsStatement.java | 2 - .../statements/LessThanStatement.java | 2 - .../statements/NotEqualsStatement.java | 7 +--- .../variables/assign/NumAssignmentNode.java | 1 - .../terrascript/script/StructureScript.java | 4 +- .../src/test/java/structure/ParserTest.java | 4 +- .../java/com/dfsek/terra/api/util/Column.java | 6 +-- .../terra/api/util/generic/pair/Pair.java | 1 - .../world/biome/generation/BiomeProvider.java | 13 +++---- .../generation/CachingBiomeProvider.java | 6 +-- common/api/src/test/java/util/ColumnTest.java | 9 ++--- .../com/dfsek/terra/AbstractPlatform.java | 39 ++++++++++++------- platforms/bukkit/build.gradle.kts | 2 - .../com/dfsek/terra/bukkit/BukkitAddon.java | 4 -- .../com/dfsek/terra/bukkit/PlatformImpl.java | 4 +- .../BukkitChunkGeneratorWrapper.java | 8 ++-- .../dfsek/terra/bukkit/nms/Initializer.java | 5 +-- .../dfsek/terra/bukkit/util/VersionUtil.java | 2 - .../bukkit/nms/v1_18_R2/NMSBiomeProvider.java | 6 +-- .../v1_18_R2/NMSChunkGeneratorDelegate.java | 19 +++++---- .../bukkit/nms/v1_19_R1/NMSBiomeInjector.java | 18 ++++++--- .../v1_19_R1/NMSChunkGeneratorDelegate.java | 3 -- .../dfsek/terra/fabric/FabricEntryPoint.java | 14 +++---- .../com/dfsek/terra/fabric/PlatformImpl.java | 24 ++---------- .../mixin/lifecycle/MinecraftServerMixin.java | 3 -- .../mixin/lifecycle/NoiseConfigMixin.java | 4 +- .../dfsek/terra/fabric/util/BiomeUtil.java | 1 + .../dfsek/terra/forge/AwfulForgeHacks.java | 1 - .../dfsek/terra/forge/ForgeEntryPoint.java | 5 +-- .../com/dfsek/terra/forge/PlatformImpl.java | 6 --- .../java/com/dfsek/terra/mod/ModPlatform.java | 20 +++------- .../terra/mod/config/ProtoPlatformBiome.java | 3 +- .../mod/config/VanillaBiomeProperties.java | 3 +- .../java/com/dfsek/terra/mod/data/Codecs.java | 5 +-- .../MinecraftChunkGeneratorWrapper.java | 3 +- .../mod/generation/TerraBiomeSource.java | 13 +++---- .../mixin/fix/NetherFossilOptimization.java | 4 +- .../GenerationSettingsFloraFeaturesMixin.java | 4 +- .../terra/block/state/BlockStateMixin.java | 3 +- .../terra/chunk/data/ProtoChunkMixin.java | 6 +-- .../terra/world/ChunkRegionMixin.java | 2 +- .../terra/world/ServerWorldMixin.java | 2 +- .../lifecycle/DataPackContentsMixin.java | 6 +-- .../dfsek/terra/mod/util/MinecraftUtil.java | 17 ++++---- .../com/dfsek/terra/mod/util/PresetUtil.java | 11 +++--- 85 files changed, 179 insertions(+), 289 deletions(-) diff --git a/buildSrc/src/main/kotlin/DistributionConfig.kt b/buildSrc/src/main/kotlin/DistributionConfig.kt index df8d88d0f..253869ae6 100644 --- a/buildSrc/src/main/kotlin/DistributionConfig.kt +++ b/buildSrc/src/main/kotlin/DistributionConfig.kt @@ -7,12 +7,9 @@ import java.nio.file.Files import java.nio.file.StandardCopyOption import org.gradle.api.DefaultTask import org.gradle.api.Project -import org.gradle.api.Task import org.gradle.api.plugins.BasePluginExtension -import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.creating import org.gradle.kotlin.dsl.extra import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.named diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java index 5d8b1275b..cd4b1c9a4 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java @@ -2,13 +2,14 @@ package com.dfsek.terra.addons.biome.extrusion; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import java.util.function.Supplier; + import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; import com.dfsek.terra.addons.biome.extrusion.config.BiomeExtrusionTemplate; import com.dfsek.terra.addons.biome.extrusion.config.ReplaceableBiomeLoader; import com.dfsek.terra.addons.biome.extrusion.config.extrusions.ReplaceExtrusionTemplate; import com.dfsek.terra.addons.biome.extrusion.config.extrusions.SetExtrusionTemplate; -import com.dfsek.terra.addons.biome.extrusion.extrusions.SetExtrusion; import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; @@ -22,8 +23,6 @@ import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import java.util.function.Supplier; - public class BiomeExtrusionAddon implements AddonInitializer { public static final TypeKey>> EXTRUSION_REGISTRY_KEY = new TypeKey<>() { diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index 605063428..a7331fc8a 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -10,8 +10,6 @@ import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.github.benmanes.caffeine.cache.LoadingCache; - public class BiomeExtrusionProvider implements BiomeProvider { private final BiomeProvider delegate; 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 3f3474428..8a7154fa9 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 com.dfsek.terra.api.world.biome.Biome; - import java.util.Collection; +import com.dfsek.terra.api.world.biome.Biome; + public interface Extrusion { Biome extrude(Biome original, int x, int y, int z, long seed); diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java index 31e742afa..e76eec1f3 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java @@ -1,10 +1,10 @@ package com.dfsek.terra.addons.biome.extrusion.api; -import com.dfsek.terra.api.world.biome.Biome; - import java.util.Optional; +import com.dfsek.terra.api.world.biome.Biome; + /** * Basically just a specialised implementation of {@link Optional} for biomes where a biome may be a "self" reference. diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java index 4e37192af..42e775ccc 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java @@ -1,10 +1,10 @@ package com.dfsek.terra.addons.biome.extrusion.api; -import com.dfsek.terra.api.world.biome.Biome; - import java.util.Objects; +import com.dfsek.terra.api.world.biome.Biome; + final class SelfBiome implements ReplaceableBiome { public static final SelfBiome INSTANCE = new SelfBiome(); diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java index 527e7d981..810246d65 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/BiomeExtrusionTemplate.java @@ -4,13 +4,13 @@ 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 java.util.List; + import com.dfsek.terra.addons.biome.extrusion.BiomeExtrusionProvider; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import java.util.List; - public class BiomeExtrusionTemplate implements ObjectTemplate { @Value("provider") diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/ReplaceExtrusionTemplate.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/ReplaceExtrusionTemplate.java index de5127b81..1b4743dc4 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/ReplaceExtrusionTemplate.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/extrusions/ReplaceExtrusionTemplate.java @@ -5,7 +5,6 @@ import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; import com.dfsek.terra.addons.biome.extrusion.extrusions.ReplaceExtrusion; -import com.dfsek.terra.addons.biome.extrusion.extrusions.SetExtrusion; import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.util.collection.ProbabilityCollection; diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java index bc45ac40c..7458c475c 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java @@ -1,5 +1,9 @@ package com.dfsek.terra.addons.biome.extrusion.extrusions; +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Collectors; + import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; import com.dfsek.terra.addons.biome.query.api.BiomeQueries; @@ -8,10 +12,6 @@ import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.util.collection.ProbabilityCollection; import com.dfsek.terra.api.world.biome.Biome; -import java.util.Collection; -import java.util.function.Predicate; -import java.util.stream.Collectors; - /** * Sets biomes at locations based on a sampler. diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java index a272d42be..79209c28a 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java @@ -1,5 +1,9 @@ package com.dfsek.terra.addons.biome.extrusion.extrusions; +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Collectors; + import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; import com.dfsek.terra.api.noise.NoiseSampler; @@ -7,10 +11,6 @@ import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.util.collection.ProbabilityCollection; import com.dfsek.terra.api.world.biome.Biome; -import java.util.Collection; -import java.util.function.Predicate; -import java.util.stream.Collectors; - /** * Sets biomes at locations based on a sampler. diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java index 2bae69d45..609d22ee1 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineColumn.java @@ -1,13 +1,13 @@ package com.dfsek.terra.addons.biome.pipeline; +import java.util.function.Consumer; + import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.util.function.IntIntObjConsumer; import com.dfsek.terra.api.util.function.IntObjConsumer; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import java.util.function.Consumer; - class BiomePipelineColumn implements Column { private final int min; diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java index 395e8d24e..063395ae4 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -7,16 +7,12 @@ package com.dfsek.terra.addons.biome.pipeline; -import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.world.info.WorldProperties; - import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import net.jafama.FastMath; import java.util.Comparator; import java.util.HashSet; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.StreamSupport; @@ -26,6 +22,7 @@ import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.registry.key.StringIdentifiable; +import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/BiomeQueryAPIAddon.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/BiomeQueryAPIAddon.java index 3004cb0e1..5f767998f 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/BiomeQueryAPIAddon.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/BiomeQueryAPIAddon.java @@ -1,5 +1,7 @@ package com.dfsek.terra.addons.biome.query; +import java.util.Collection; + import com.dfsek.terra.addons.biome.query.impl.BiomeTagFlattener; import com.dfsek.terra.addons.biome.query.impl.BiomeTagHolder; import com.dfsek.terra.addons.manifest.api.AddonInitializer; @@ -12,8 +14,6 @@ import com.dfsek.terra.api.properties.Context; import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.biome.Biome; -import java.util.Collection; - public class BiomeQueryAPIAddon implements AddonInitializer { @Inject diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java index 83b1ebf18..6e36b7a45 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java @@ -1,10 +1,10 @@ package com.dfsek.terra.addons.biome.query.api; +import java.util.function.Predicate; + import com.dfsek.terra.addons.biome.query.impl.SingleTagQuery; import com.dfsek.terra.api.world.biome.Biome; -import java.util.function.Predicate; - public final class BiomeQueries { private BiomeQueries() { diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java index d2dfc4b23..af2bfa8c7 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java @@ -1,10 +1,10 @@ package com.dfsek.terra.addons.biome.query.impl; +import java.util.function.Predicate; + import com.dfsek.terra.addons.biome.query.BiomeQueryAPIAddon; import com.dfsek.terra.api.world.biome.Biome; -import java.util.function.Predicate; - public class SingleTagQuery implements Predicate { private int tagIndex = -1; diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java index 0e091b44b..cd034f012 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java @@ -6,7 +6,6 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.util.mutable.MutableInteger; public class BiomeNoiseConfigTemplate implements ObjectTemplate { diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseProperties.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseProperties.java index b058e4c2f..7f4b20a88 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseProperties.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseProperties.java @@ -2,7 +2,6 @@ package com.dfsek.terra.addons.chunkgenerator.config.noise; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.properties.Properties; -import com.dfsek.terra.api.util.mutable.MutableInteger; public record BiomeNoiseProperties(NoiseSampler base, 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 24be708af..fcb8d3fe2 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 @@ -8,6 +8,9 @@ package com.dfsek.terra.addons.chunkgenerator.generation; +import net.jafama.FastMath; +import org.jetbrains.annotations.NotNull; + import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.addons.chunkgenerator.config.palette.PaletteInfo; import com.dfsek.terra.addons.chunkgenerator.generation.math.PaletteUtil; @@ -26,9 +29,6 @@ import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; import com.dfsek.terra.api.world.chunk.generation.util.Palette; import com.dfsek.terra.api.world.info.WorldProperties; -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - public class NoiseChunkGenerator3D implements ChunkGenerator { private final Platform platform; diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 89fe55afe..4ef7072c7 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -7,14 +7,14 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; +import net.jafama.FastMath; + import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import net.jafama.FastMath; - /** * Class to abstract away the Interpolators needed to generate a chunk.
diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java index 97a6a147c..6e46ba774 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java @@ -1,10 +1,9 @@ package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; -import com.dfsek.terra.api.properties.PropertyKey; - import net.jafama.FastMath; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import static com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.Interpolator.lerp; diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java index ab1de182f..439c85ad1 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java @@ -11,7 +11,6 @@ import com.dfsek.terra.addons.feature.locator.patterns.Pattern; import com.dfsek.terra.api.structure.feature.BinaryColumn; import com.dfsek.terra.api.structure.feature.Locator; import com.dfsek.terra.api.util.Range; -import com.dfsek.terra.api.world.World; import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.chunk.generation.util.Column; diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java index 575b2328e..b4ea6b1d8 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java @@ -7,14 +7,14 @@ package com.dfsek.terra.addons.feature.locator.locators; +import net.jafama.FastMath; + import com.dfsek.terra.addons.feature.locator.patterns.Pattern; import com.dfsek.terra.api.structure.feature.BinaryColumn; import com.dfsek.terra.api.structure.feature.Locator; import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.world.chunk.generation.util.Column; -import net.jafama.FastMath; - public class PatternLocator implements Locator { private final Pattern pattern; diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java index e0194167b..9e9b7ef2e 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java @@ -7,14 +7,14 @@ package com.dfsek.terra.addons.feature.locator.locators; +import net.jafama.FastMath; + import com.dfsek.terra.api.structure.feature.BinaryColumn; import com.dfsek.terra.api.structure.feature.Locator; import com.dfsek.terra.api.util.Range; import com.dfsek.terra.api.world.chunk.generation.util.Column; import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder; -import net.jafama.FastMath; - public class SurfaceLocator implements Locator { private final Range search; diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java index 111744cd9..e2ca64f69 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java @@ -7,16 +7,13 @@ package com.dfsek.terra.addons.feature.locator.patterns; -import com.dfsek.terra.api.world.ServerWorld; - -import com.dfsek.terra.api.world.WritableWorld; - import net.jafama.FastMath; import java.util.function.Predicate; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.chunk.generation.util.Column; diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java index 86850378e..4c2d0de67 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java @@ -7,9 +7,6 @@ package com.dfsek.terra.addons.feature.locator.patterns; -import com.dfsek.terra.api.world.ReadableWorld; -import com.dfsek.terra.api.world.ServerWorld; -import com.dfsek.terra.api.world.World; import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.chunk.generation.util.Column; 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 0a7a0c9b4..5408b26e4 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,6 +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.properties.PropertyKey; @@ -18,9 +21,6 @@ import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.api.world.chunk.generation.util.Column; -import java.util.Collections; -import java.util.Random; - public class FeatureGenerationStage implements GenerationStage, StringIdentifiable { private final Platform platform; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java index 946abbfea..f9532c8cf 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java @@ -1,15 +1,14 @@ package com.dfsek.terra.addons.terrascript.parser.lang; -import com.dfsek.terra.addons.terrascript.parser.lang.Returnable.ReturnType; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.reference.VariableReferenceNode; -import com.dfsek.terra.api.util.generic.pair.Pair; - import net.jafama.FastMath; import java.util.HashMap; import java.util.Map; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable.ReturnType; +import com.dfsek.terra.api.util.generic.pair.Pair; + public class Scope { private final double[] num; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java index 7d36d114d..f49cab112 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike; -import com.dfsek.terra.api.util.generic.pair.Pair; - import org.jetbrains.annotations.Nullable; import java.util.List; @@ -19,6 +17,7 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.util.generic.pair.Pair; public class IfKeyword implements Keyword> { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java index f336b3055..fdacebe4c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java @@ -7,11 +7,7 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java index b10407a79..94a08bbe6 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java index 177297972..e5ca10337 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java index e2153559e..793012549 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java index 41cc48662..3731d0807 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java index aeaf9bd90..62e58a92c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java index bb216047a..33439b742 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java index e31b2b5de..dca6c66c5 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java index 5071e95ea..d83ab0ad2 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java @@ -7,9 +7,7 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.tokenizer.Position; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java index 82a045742..97648aa1f 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java @@ -7,14 +7,11 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; - import net.jafama.FastMath; -import java.util.function.Supplier; - +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.tokenizer.Position; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java index 10c60a305..d25f6bd0d 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java index 0bb3e5500..8e5cc4aee 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java index ef2aa8346..207d09632 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java index f06e395b1..aed7189f6 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; -import java.util.function.Supplier; - import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java index aaecd56bc..3241c8657 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java @@ -7,14 +7,11 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; - import net.jafama.FastMath; -import java.util.function.Supplier; - +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.tokenizer.Position; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java index 55ebb8aa8..1b67e7150 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java @@ -3,7 +3,6 @@ package com.dfsek.terra.addons.terrascript.parser.lang.variables.assign; import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable; import com.dfsek.terra.addons.terrascript.tokenizer.Position; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java index 87636fd9e..e865d0d6d 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java @@ -7,8 +7,6 @@ package com.dfsek.terra.addons.terrascript.script; -import com.dfsek.terra.addons.terrascript.parser.lang.Executable; - import net.jafama.FastMath; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; @@ -20,7 +18,7 @@ import java.nio.charset.Charset; import java.util.Random; import com.dfsek.terra.addons.terrascript.parser.Parser; -import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.Executable; 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.builders.BinaryNumberFunctionBuilder; diff --git a/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java b/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java index e50589dfb..2f07954d2 100644 --- a/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java +++ b/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java @@ -8,8 +8,6 @@ package structure; -import com.dfsek.terra.addons.terrascript.parser.lang.Executable; - import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; @@ -20,7 +18,7 @@ import java.util.Objects; import com.dfsek.terra.addons.terrascript.parser.Parser; import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.Executable; import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Scope; diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java index 4610bbf8d..2b6264228 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Column.java @@ -1,12 +1,12 @@ package com.dfsek.terra.api.util; -import com.dfsek.terra.api.util.function.IntIntObjConsumer; -import com.dfsek.terra.api.util.function.IntObjConsumer; - import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; +import com.dfsek.terra.api.util.function.IntIntObjConsumer; +import com.dfsek.terra.api.util.function.IntObjConsumer; + public interface Column { int getMinY(); diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java index 4727b57e2..d47cfdc05 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java @@ -15,7 +15,6 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; -import java.util.function.UnaryOperator; public final class Pair { diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 09c6f3dbd..cfa5a78c0 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -7,19 +7,18 @@ package com.dfsek.terra.api.world.biome.generation; -import com.dfsek.terra.api.util.Column; -import com.dfsek.terra.api.util.vector.Vector3; -import com.dfsek.terra.api.util.vector.Vector3Int; -import com.dfsek.terra.api.world.biome.Biome; - -import com.dfsek.terra.api.world.info.WorldProperties; - import org.jetbrains.annotations.Contract; import java.util.Optional; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.info.WorldProperties; + /** * Provides locations of biomes in a world. diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index e503dd54c..fa3847a23 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -1,14 +1,14 @@ package com.dfsek.terra.api.world.biome.generation; -import com.dfsek.terra.api.Handle; -import com.dfsek.terra.api.world.biome.Biome; - import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.Scheduler; import java.util.Optional; +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.world.biome.Biome; + /** * A biome provider implementation that lazily evaluates biomes, and caches them. diff --git a/common/api/src/test/java/util/ColumnTest.java b/common/api/src/test/java/util/ColumnTest.java index bcb3f6064..7ba140683 100644 --- a/common/api/src/test/java/util/ColumnTest.java +++ b/common/api/src/test/java/util/ColumnTest.java @@ -1,10 +1,5 @@ package util; -import com.dfsek.terra.api.util.Column; - -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.api.util.mutable.MutableInteger; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -14,6 +9,10 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; +import com.dfsek.terra.api.util.Column; +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.api.util.mutable.MutableInteger; + import static org.junit.jupiter.api.Assertions.*; diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java index 81933014f..4ea9466ec 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java @@ -18,6 +18,30 @@ package com.dfsek.terra; import com.dfsek.tectonic.api.TypeRegistry; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import com.dfsek.terra.addon.BootstrapAddonLoader; import com.dfsek.terra.addon.DependencySorter; @@ -49,21 +73,6 @@ import com.dfsek.terra.registry.LockedRegistryImpl; import com.dfsek.terra.registry.OpenRegistryImpl; import com.dfsek.terra.registry.master.ConfigRegistry; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.yaml.snakeyaml.Yaml; - -import java.io.*; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.stream.Collectors; - /** * Skeleton implementation of {@link Platform} diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index 7221c9f90..ee85af57a 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -1,5 +1,3 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - plugins { id("xyz.jpenilla.run-paper") version "1.0.6" } diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitAddon.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitAddon.java index 38d3ff2dc..ac215b83e 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitAddon.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitAddon.java @@ -7,12 +7,8 @@ import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.world.biome.Biome; - import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class BukkitAddon implements BaseAddon { private static final Version VERSION = Versions.getVersion(1, 0, 0); diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java index a58cc1a3d..bba0e1bc1 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java @@ -20,9 +20,6 @@ package com.dfsek.terra.bukkit; import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.exception.LoadException; - -import com.dfsek.terra.api.addon.BaseAddon; - import org.bukkit.Bukkit; import org.bukkit.entity.EntityType; import org.jetbrains.annotations.NotNull; @@ -34,6 +31,7 @@ import java.util.List; import java.util.Locale; import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.handle.WorldHandle; diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java index a1c7a6ef1..bf847ff86 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java @@ -17,8 +17,6 @@ package com.dfsek.terra.bukkit.generator; -import com.dfsek.terra.api.world.info.WorldProperties; - import org.bukkit.World; import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BlockPopulator; @@ -26,6 +24,8 @@ import org.bukkit.generator.LimitedRegion; import org.bukkit.generator.WorldInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; import java.util.Random; @@ -35,12 +35,10 @@ import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; +import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.bukkit.world.BukkitProtoWorld; import com.dfsek.terra.bukkit.world.BukkitWorldProperties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGenerator implements GeneratorWrapper { private static final Logger LOGGER = LoggerFactory.getLogger(BukkitChunkGeneratorWrapper.class); 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 b86a37f89..675b84b00 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,13 +1,10 @@ package com.dfsek.terra.bukkit.nms; -import com.dfsek.terra.bukkit.PlatformImpl; -import com.dfsek.terra.bukkit.TerraBukkitPlugin; - import org.bukkit.Bukkit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.lang.reflect.InvocationTargetException; +import com.dfsek.terra.bukkit.PlatformImpl; public interface Initializer { 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 08e9b4864..469582bf2 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 @@ -1,7 +1,5 @@ package com.dfsek.terra.bukkit.util; -import ca.solostudios.strata.Versions; -import ca.solostudios.strata.version.Version; import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.slf4j.Logger; diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeProvider.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeProvider.java index 6d44d19d5..111b2802b 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeProvider.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeProvider.java @@ -1,8 +1,5 @@ package com.dfsek.terra.bukkit.nms.v1_18_R2; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; - import com.mojang.serialization.Codec; import net.minecraft.core.Holder; import net.minecraft.core.Registry; @@ -11,6 +8,9 @@ import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.Climate.Sampler; import org.jetbrains.annotations.NotNull; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; + public class NMSBiomeProvider extends BiomeSource { private final BiomeProvider delegate; diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java index 4bc41052c..ff4e1597c 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java @@ -1,10 +1,5 @@ package com.dfsek.terra.bukkit.nms.v1_18_R2; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.util.generic.Lazy; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.api.world.info.WorldProperties; - import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; @@ -21,7 +16,6 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeManager; import net.minecraft.world.level.biome.Climate; import net.minecraft.world.level.biome.Climate.Sampler; -import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.GenerationStep; @@ -36,11 +30,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Random; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.stream.Collectors; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.info.WorldProperties; + public class NMSChunkGeneratorDelegate extends ChunkGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class); diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java index 4ed328fff..fdf380e97 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java @@ -1,10 +1,5 @@ package com.dfsek.terra.bukkit.nms.v1_19_R1; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; -import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; -import com.dfsek.terra.registry.master.ConfigRegistry; - import com.google.common.collect.ImmutableMap; import com.mojang.serialization.Lifecycle; import net.minecraft.core.Holder; @@ -21,7 +16,18 @@ import org.bukkit.NamespacedKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; +import com.dfsek.terra.registry.master.ConfigRegistry; public class NMSBiomeInjector { diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java index 860bfa5a0..e20a5da0b 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java @@ -16,8 +16,6 @@ import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeManager; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.GenerationStep.Carving; @@ -34,7 +32,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java index ca110eccf..6fcc2b792 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -18,16 +18,7 @@ package com.dfsek.terra.fabric; 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 com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; -import com.dfsek.terra.fabric.util.BiomeUtil; -import com.dfsek.terra.mod.CommonPlatform; - import net.fabricmc.api.ModInitializer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.util.Identifier; @@ -36,6 +27,11 @@ import net.minecraft.util.registry.Registry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.fabric.util.BiomeUtil; +import com.dfsek.terra.mod.CommonPlatform; import com.dfsek.terra.mod.data.Codecs; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java index 14f298947..c21f755cd 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java @@ -20,27 +20,9 @@ package com.dfsek.terra.fabric; import ca.solostudios.strata.Versions; import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.version.Version; - -import com.dfsek.terra.fabric.util.BiomeUtil; -import com.dfsek.terra.mod.CommonPlatform; -import com.dfsek.terra.mod.ModPlatform; - -import com.dfsek.terra.mod.generation.TerraBiomeSource; - -import com.dfsek.terra.mod.util.PresetUtil; - import net.fabricmc.loader.api.FabricLoader; import net.minecraft.MinecraftVersion; import net.minecraft.server.MinecraftServer; -import net.minecraft.sound.BiomeAdditionsSound; -import net.minecraft.sound.BiomeMoodSound; -import net.minecraft.sound.MusicSound; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.world.dimension.DimensionOptions; -import net.minecraft.world.gen.WorldPreset; -import net.minecraft.world.gen.chunk.ChunkGenerator; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,15 +30,15 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.function.BiConsumer; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.fabric.util.BiomeUtil; +import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.ModPlatform; import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; import com.dfsek.terra.mod.handle.MinecraftItemHandle; import com.dfsek.terra.mod.handle.MinecraftWorldHandle; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java index 2a545ebf0..0620de7f2 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java @@ -1,14 +1,11 @@ package com.dfsek.terra.fabric.mixin.lifecycle; -import com.mojang.authlib.GameProfileRepository; -import com.mojang.authlib.minecraft.MinecraftSessionService; import com.mojang.datafixers.DataFixer; import net.minecraft.resource.ResourcePackManager; import net.minecraft.server.MinecraftServer; import net.minecraft.server.SaveLoader; import net.minecraft.server.WorldGenerationProgressListenerFactory; import net.minecraft.util.ApiServices; -import net.minecraft.util.UserCache; import net.minecraft.world.level.storage.LevelStorage; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java index b24bfd489..15957b31c 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java @@ -1,7 +1,5 @@ package com.dfsek.terra.fabric.mixin.lifecycle; -import com.dfsek.terra.mod.util.SeedHack; - import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; @@ -14,6 +12,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.dfsek.terra.mod.util.SeedHack; + /** * Hack to map noise sampler to seeds diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java index a092166e6..fdaee4a21 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -70,4 +70,5 @@ public final class BiomeUtil { MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); } } + } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java index 0ddb92caa..12c67e838 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java @@ -7,7 +7,6 @@ import java.io.IOException; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import java.util.jar.JarFile; import java.util.stream.Stream; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index dbc919781..9691dde88 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -17,9 +17,6 @@ package com.dfsek.terra.forge; -import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; -import com.dfsek.terra.forge.util.BiomeUtil; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.Biome; @@ -36,8 +33,10 @@ import net.minecraftforge.registries.RegisterEvent.RegisterHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.forge.AwfulForgeHacks.RegistrySanityCheck; import com.dfsek.terra.forge.AwfulForgeHacks.RegistryStep; +import com.dfsek.terra.forge.util.BiomeUtil; import com.dfsek.terra.mod.data.Codecs; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index b3996a9d8..294fa01d9 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -20,13 +20,8 @@ package com.dfsek.terra.forge; import ca.solostudios.strata.Versions; import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.version.Version; - -import com.dfsek.terra.mod.util.PresetUtil; - import net.minecraft.MinecraftVersion; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Identifier; -import net.minecraft.world.gen.WorldPreset; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.server.ServerLifecycleHooks; import org.jetbrains.annotations.NotNull; @@ -36,7 +31,6 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.function.BiConsumer; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; 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 5a75d0cc2..7d140eb79 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 @@ -1,24 +1,11 @@ package com.dfsek.terra.mod; import com.dfsek.tectonic.api.TypeRegistry; - import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.exception.LoadException; - -import com.dfsek.terra.AbstractPlatform; - -import com.dfsek.terra.api.addon.BaseAddon; -import com.dfsek.terra.api.world.biome.PlatformBiome; - -import com.dfsek.terra.mod.config.ProtoPlatformBiome; - -import com.dfsek.terra.mod.util.PresetUtil; - -import net.minecraft.command.CommandSource; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; import net.minecraft.world.gen.WorldPreset; @@ -26,7 +13,12 @@ import net.minecraft.world.gen.WorldPreset; import java.util.List; import java.util.Locale; import java.util.function.BiConsumer; -import java.util.function.Consumer; + +import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.world.biome.PlatformBiome; +import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.util.PresetUtil; public abstract class ModPlatform extends AbstractPlatform { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java index 78542fabe..f9524ef58 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/ProtoPlatformBiome.java @@ -17,8 +17,6 @@ package com.dfsek.terra.mod.config; -import com.dfsek.terra.mod.util.MinecraftUtil; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; @@ -27,6 +25,7 @@ import net.minecraft.world.biome.Biome; import java.util.Objects; import com.dfsek.terra.api.world.biome.PlatformBiome; +import com.dfsek.terra.mod.util.MinecraftUtil; public class ProtoPlatformBiome implements PlatformBiome { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java index 72095c53b..0bec88566 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java @@ -10,11 +10,10 @@ import net.minecraft.sound.SoundEvent; import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.Biome.TemperatureModifier; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; +import net.minecraft.world.biome.BiomeParticleConfig; import com.dfsek.terra.api.properties.Properties; -import net.minecraft.world.biome.BiomeParticleConfig; - public class VanillaBiomeProperties implements ConfigTemplate, Properties { @Value("colors.grass") 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 643ced594..36f774297 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,8 +1,5 @@ package com.dfsek.terra.mod.data; -import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; -import com.dfsek.terra.mod.generation.TerraBiomeSource; - import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.util.dynamic.RegistryOps; @@ -12,6 +9,8 @@ import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.registry.key.RegistryKey; import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.generation.TerraBiomeSource; public final class Codecs { 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 1b8af7852..5742120d6 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,8 +17,6 @@ package com.dfsek.terra.mod.generation; -import com.dfsek.terra.mod.mixin.access.StructureAccessorAccessor; - import com.mojang.serialization.Codec; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -65,6 +63,7 @@ import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; import com.dfsek.terra.mod.data.Codecs; +import com.dfsek.terra.mod.mixin.access.StructureAccessorAccessor; import com.dfsek.terra.mod.util.MinecraftAdapter; 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 7f1f1d6dd..5730cee80 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,13 +17,6 @@ package com.dfsek.terra.mod.generation; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.world.biome.generation.BiomeProvider; -import com.dfsek.terra.mod.data.Codecs; -import com.dfsek.terra.mod.config.ProtoPlatformBiome; - -import com.dfsek.terra.mod.util.SeedHack; - import com.mojang.serialization.Codec; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryEntry; @@ -34,6 +27,12 @@ import org.slf4j.LoggerFactory; import java.util.stream.StreamSupport; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.data.Codecs; +import com.dfsek.terra.mod.util.SeedHack; + public class TerraBiomeSource extends BiomeSource { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java index f0eb245b8..12d6a0732 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java @@ -1,7 +1,5 @@ package com.dfsek.terra.mod.mixin.fix; -import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; - import net.minecraft.world.gen.structure.NetherFossilStructure; import net.minecraft.world.gen.structure.Structure.Context; import net.minecraft.world.gen.structure.Structure.StructurePosition; @@ -12,6 +10,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Optional; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; + /** * Disable fossil generation in Terra worlds, as they are very expensive due to consistently triggering cache misses. diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java index df71e733f..c254445d1 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/compat/GenerationSettingsFloraFeaturesMixin.java @@ -1,7 +1,5 @@ package com.dfsek.terra.mod.mixin.implementations.compat; -import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; - import net.minecraft.world.biome.GenerationSettings; import net.minecraft.world.gen.feature.ConfiguredFeature; import org.spongepowered.asm.mixin.Implements; @@ -13,6 +11,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; +import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; + @Mixin(GenerationSettings.class) @Implements(@Interface(iface = FloraFeatureHolder.class, prefix = "terra$")) 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 86272efd9..636a3f721 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,6 @@ package com.dfsek.terra.mod.mixin.implementations.terra.block.state; -import com.dfsek.terra.mod.mixin.access.StateAccessor; - import com.google.common.collect.ImmutableMap; import com.mojang.serialization.MapCodec; import net.minecraft.block.AbstractBlock.AbstractBlockState; @@ -20,6 +18,7 @@ import java.util.stream.Collectors; import com.dfsek.terra.api.block.BlockType; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.properties.Property; +import com.dfsek.terra.mod.mixin.access.StateAccessor; @Mixin(AbstractBlockState.class) diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java index f90e5a3b3..25c8f196f 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/chunk/data/ProtoChunkMixin.java @@ -17,9 +17,6 @@ package com.dfsek.terra.mod.mixin.implementations.terra.chunk.data; -import com.dfsek.terra.api.block.state.BlockState; -import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; - import net.minecraft.util.math.BlockPos; import net.minecraft.world.HeightLimitView; import org.jetbrains.annotations.NotNull; @@ -28,6 +25,9 @@ import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; + @Mixin(net.minecraft.world.chunk.ProtoChunk.class) @Implements(@Interface(iface = ProtoChunk.class, prefix = "terra$")) 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 c17a8c1ee..64ed28314 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 @@ -17,7 +17,6 @@ package com.dfsek.terra.mod.mixin.implementations.terra.world; -import com.dfsek.terra.mod.util.MinecraftUtil; import net.minecraft.block.FluidBlock; import net.minecraft.fluid.Fluid; import net.minecraft.util.math.BlockPos; @@ -49,6 +48,7 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.util.MinecraftUtil; @Mixin(ChunkRegion.class) diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java index f219db0a1..74af91dbc 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java @@ -17,7 +17,6 @@ package com.dfsek.terra.mod.mixin.implementations.terra.world; -import com.dfsek.terra.mod.util.MinecraftUtil; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldAccess; import org.spongepowered.asm.mixin.Implements; @@ -36,6 +35,7 @@ import com.dfsek.terra.api.world.chunk.Chunk; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; import com.dfsek.terra.mod.generation.TerraBiomeSource; +import com.dfsek.terra.mod.util.MinecraftUtil; @Mixin(net.minecraft.server.world.ServerWorld.class) 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 d18fbf8d2..a9ecb9354 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 @@ -1,8 +1,5 @@ package com.dfsek.terra.mod.mixin.lifecycle; -import com.dfsek.terra.mod.util.TagUtil; -import com.dfsek.terra.mod.util.MinecraftUtil; - import net.minecraft.server.DataPackContents; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; @@ -12,6 +9,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.dfsek.terra.mod.util.MinecraftUtil; +import com.dfsek.terra.mod.util.TagUtil; + @Mixin(DataPackContents.class) public class DataPackContentsMixin { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java index 276aefaa9..fc2eb9def 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java @@ -1,14 +1,5 @@ package com.dfsek.terra.mod.util; -import com.dfsek.terra.api.block.entity.BlockEntity; -import com.dfsek.terra.api.block.entity.Container; -import com.dfsek.terra.api.block.entity.MobSpawner; -import com.dfsek.terra.api.block.entity.Sign; - -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.mod.config.VanillaBiomeProperties; -import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; - import net.minecraft.block.entity.LootableContainerBlockEntity; import net.minecraft.block.entity.MobSpawnerBlockEntity; import net.minecraft.block.entity.SignBlockEntity; @@ -33,6 +24,14 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.block.entity.MobSpawner; +import com.dfsek.terra.api.block.entity.Sign; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; + public final class MinecraftUtil { public static final Logger logger = LoggerFactory.getLogger(MinecraftUtil.class); 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 7b3e57ca5..df1641f39 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 @@ -1,11 +1,5 @@ package com.dfsek.terra.mod.util; -import com.dfsek.terra.api.config.ConfigPack; - -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; -import com.dfsek.terra.mod.generation.TerraBiomeSource; - import net.minecraft.structure.StructureSet; import net.minecraft.util.Identifier; import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters; @@ -30,6 +24,11 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.generation.TerraBiomeSource; + public class PresetUtil { private static final Logger LOGGER = LoggerFactory.getLogger(PresetUtil.class); From b0bf9d042e64dce7394d1029e6490a426a17dc98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Sun, 26 Jun 2022 22:02:18 -0700 Subject: [PATCH 188/220] oops --- .../java/com/dfsek/terra/mod/ModPlatform.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) 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 7d140eb79..49cc681c1 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,11 +3,25 @@ package com.dfsek.terra.mod; import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.exception.LoadException; + +import com.dfsek.terra.mod.config.BiomeAdditionsSoundTemplate; +import com.dfsek.terra.mod.config.BiomeMoodSoundTemplate; +import com.dfsek.terra.mod.config.BiomeParticleConfigTemplate; + +import com.dfsek.terra.mod.config.MusicSoundTemplate; +import com.dfsek.terra.mod.config.SoundEventTemplate; + import net.minecraft.server.MinecraftServer; +import net.minecraft.sound.BiomeAdditionsSound; +import net.minecraft.sound.BiomeMoodSound; +import net.minecraft.sound.MusicSound; +import net.minecraft.sound.SoundEvent; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.world.biome.Biome.Precipitation; +import net.minecraft.world.biome.Biome.TemperatureModifier; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; +import net.minecraft.world.biome.BiomeParticleConfig; import net.minecraft.world.gen.WorldPreset; import java.util.List; @@ -42,7 +56,14 @@ public abstract class ModPlatform extends AbstractPlatform { .registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase( Locale.ROOT))) .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase( - Locale.ROOT))); + Locale.ROOT))) + .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase( + Locale.ROOT))) + .registerLoader(BiomeParticleConfig.class, BiomeParticleConfigTemplate::new) + .registerLoader(SoundEvent.class, SoundEventTemplate::new) + .registerLoader(BiomeMoodSound.class, BiomeMoodSoundTemplate::new) + .registerLoader(BiomeAdditionsSound.class, BiomeAdditionsSoundTemplate::new) + .registerLoader(MusicSound.class, MusicSoundTemplate::new); } private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException { From 71aa42011f75d53ac028ea0c0a54f9e5230ec358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Sun, 26 Jun 2022 23:43:15 -0700 Subject: [PATCH 189/220] Spawning! --- gradle.properties | 2 +- platforms/fabric/build.gradle.kts | 2 +- .../dfsek/terra/fabric/util/BiomeUtil.java | 19 ++++----- .../src/main/resources/terra.accesswidener | 1 - platforms/forge/build.gradle.kts | 2 + platforms/mixin-common/build.gradle.kts | 1 + .../java/com/dfsek/terra/mod/ModPlatform.java | 29 ++++++++++---- .../config/BiomeAdditionsSoundTemplate.java | 2 +- .../config/BiomeParticleConfigTemplate.java | 6 +-- .../terra/mod/config/EntityTypeTemplate.java | 20 ++++++++++ .../terra/mod/config/MusicSoundTemplate.java | 2 +- .../terra/mod/config/SoundEventTemplate.java | 2 +- .../terra/mod/config/SpawnCostConfig.java | 38 ++++++++++++++++++ .../terra/mod/config/SpawnEntryTemplate.java | 31 +++++++++++++++ .../terra/mod/config/SpawnGroupTemplate.java | 18 +++++++++ .../mod/config/SpawnSettingsTemplate.java | 39 +++++++++++++++++++ .../terra/mod/config/SpawnTypeConfig.java | 31 +++++++++++++++ .../mod/config/VanillaBiomeProperties.java | 13 ++++++- .../terra/mod/mixin/access/BiomeAccessor.java | 12 ++++++ .../dfsek/terra/mod/util/MinecraftUtil.java | 12 +++--- .../src/main/resources/terra.accesswidener | 2 + 21 files changed, 249 insertions(+), 35 deletions(-) delete mode 100644 platforms/fabric/src/main/resources/terra.accesswidener create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/EntityTypeTemplate.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnCostConfig.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnEntryTemplate.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnGroupTemplate.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnSettingsTemplate.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnTypeConfig.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/BiomeAccessor.java create mode 100644 platforms/mixin-common/src/main/resources/terra.accesswidener diff --git a/gradle.properties b/gradle.properties index baf5d0e6a..067f03e0c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Magic options for more perf -org.gradle.jvmargs=-Xmx2048M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC +org.gradle.jvmargs=-Xmx3048M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC org.gradle.vfs.watch=true kapt.use.worker.api=true kapt.include.compile.classpath=false diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 4020713db..1155a480e 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -36,7 +36,7 @@ dependencies { } loom { - accessWidenerPath.set(file("src/main/resources/terra.accesswidener")) + accessWidenerPath.set(project(":platforms:mixin-common").file("src/main/resources/terra.accesswidener")) mixin { defaultRefmapName.set("terra-fabric-refmap.json") } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java index fdaee4a21..7afb25668 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -1,23 +1,20 @@ package com.dfsek.terra.fabric.util; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.fabric.FabricEntryPoint; -import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; - -import com.dfsek.terra.mod.config.ProtoPlatformBiome; -import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; -import com.dfsek.terra.mod.util.MinecraftUtil; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.gen.feature.ConfiguredFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; +import java.util.ArrayList; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.util.MinecraftUtil; public final class BiomeUtil { diff --git a/platforms/fabric/src/main/resources/terra.accesswidener b/platforms/fabric/src/main/resources/terra.accesswidener deleted file mode 100644 index 3fde5170f..000000000 --- a/platforms/fabric/src/main/resources/terra.accesswidener +++ /dev/null @@ -1 +0,0 @@ -accessWidener v1 named diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index b09a9a1b1..95cd6d82d 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -32,11 +32,13 @@ dependencies { } loom { + accessWidenerPath.set(project(":platforms:mixin-common").file("src/main/resources/terra.accesswidener")) mixin { defaultRefmapName.set("terra-forge-refmap.json") } forge { + convertAccessWideners.set(true) mixinConfig("terra.common.mixins.json") mixinConfig("terra.forge.mixins.json") } diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts index 33a503818..439419b70 100644 --- a/platforms/mixin-common/build.gradle.kts +++ b/platforms/mixin-common/build.gradle.kts @@ -7,6 +7,7 @@ loom { mixin { defaultRefmapName.set("terra-common-refmap.json") } + accessWidenerPath.set(file("src/main/resources/terra.accesswidener")) } dependencies { 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 49cc681c1..7d70b727e 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 @@ -4,13 +4,10 @@ import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.exception.LoadException; -import com.dfsek.terra.mod.config.BiomeAdditionsSoundTemplate; -import com.dfsek.terra.mod.config.BiomeMoodSoundTemplate; -import com.dfsek.terra.mod.config.BiomeParticleConfigTemplate; - -import com.dfsek.terra.mod.config.MusicSoundTemplate; -import com.dfsek.terra.mod.config.SoundEventTemplate; +import com.dfsek.terra.mod.config.SpawnSettingsTemplate; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; import net.minecraft.server.MinecraftServer; import net.minecraft.sound.BiomeAdditionsSound; import net.minecraft.sound.BiomeMoodSound; @@ -22,6 +19,8 @@ import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.Biome.TemperatureModifier; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; import net.minecraft.world.biome.BiomeParticleConfig; +import net.minecraft.world.biome.SpawnSettings; +import net.minecraft.world.biome.SpawnSettings.SpawnEntry; import net.minecraft.world.gen.WorldPreset; import java.util.List; @@ -31,7 +30,17 @@ import java.util.function.BiConsumer; import com.dfsek.terra.AbstractPlatform; import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.world.biome.PlatformBiome; +import com.dfsek.terra.mod.config.BiomeAdditionsSoundTemplate; +import com.dfsek.terra.mod.config.BiomeMoodSoundTemplate; +import com.dfsek.terra.mod.config.BiomeParticleConfigTemplate; +import com.dfsek.terra.mod.config.EntityTypeTemplate; +import com.dfsek.terra.mod.config.MusicSoundTemplate; import com.dfsek.terra.mod.config.ProtoPlatformBiome; +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.SpawnTypeConfig; import com.dfsek.terra.mod.util.PresetUtil; @@ -63,7 +72,13 @@ public abstract class ModPlatform extends AbstractPlatform { .registerLoader(SoundEvent.class, SoundEventTemplate::new) .registerLoader(BiomeMoodSound.class, BiomeMoodSoundTemplate::new) .registerLoader(BiomeAdditionsSound.class, BiomeAdditionsSoundTemplate::new) - .registerLoader(MusicSound.class, MusicSoundTemplate::new); + .registerLoader(MusicSound.class, MusicSoundTemplate::new) + .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); } private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeAdditionsSoundTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeAdditionsSoundTemplate.java index f6bc69a5a..92e6dc7a7 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeAdditionsSoundTemplate.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeAdditionsSoundTemplate.java @@ -12,7 +12,7 @@ public class BiomeAdditionsSoundTemplate implements ObjectTemplate> { + @Value("id") + @Default + private Identifier id = null; + + @Override + public EntityType get() { + return Registry.ENTITY_TYPE.get(id); + } +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/MusicSoundTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/MusicSoundTemplate.java index 4896a0cc5..674d47548 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/MusicSoundTemplate.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/MusicSoundTemplate.java @@ -20,7 +20,7 @@ public class MusicSoundTemplate implements ObjectTemplate { @Default private Integer maxDelay = null; - @Value("-current-music") + @Value("replace-current-music") @Default private Boolean replaceCurrentMusic = null; diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SoundEventTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SoundEventTemplate.java index 7a69b1546..f2ae58993 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SoundEventTemplate.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SoundEventTemplate.java @@ -12,7 +12,7 @@ public class SoundEventTemplate implements ObjectTemplate { @Default private Identifier id = null; - @Value("distanceToTravel") + @Value("distance-to-travel") @Default private Float distanceToTravel = null; diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnCostConfig.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnCostConfig.java new file mode 100644 index 000000000..3af1ff1b1 --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnCostConfig.java @@ -0,0 +1,38 @@ +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.EntityType; + + +public class SpawnCostConfig implements ObjectTemplate { + @Value("type") + @Default + private EntityType type = null; + + @Value("mass") + @Default + private Double mass = null; + + @Value("gravity") + @Default + private Double gravity = null; + + public EntityType getType() { + return type; + } + + public Double getMass() { + return mass; + } + + public Double getGravity() { + return gravity; + } + + @Override + public SpawnCostConfig get() { + return this; + } +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnEntryTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnEntryTemplate.java new file mode 100644 index 000000000..7c203b62e --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnEntryTemplate.java @@ -0,0 +1,31 @@ +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.EntityType; +import net.minecraft.world.biome.SpawnSettings.SpawnEntry; + + +public class SpawnEntryTemplate implements ObjectTemplate { + @Value("type") + @Default + private EntityType type = null; + + @Value("weight") + @Default + private Integer weight = null; + + @Value("min-group-size") + @Default + private Integer minGroupSize = null; + + @Value("max-group-size") + @Default + private Integer maxGroupSize = null; + + @Override + public SpawnEntry get() { + return new SpawnEntry(type, weight, minGroupSize, maxGroupSize); + } +} 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 new file mode 100644 index 000000000..e6a9143d1 --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnGroupTemplate.java @@ -0,0 +1,18 @@ +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 new file mode 100644 index 000000000..25fae1481 --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnSettingsTemplate.java @@ -0,0 +1,39 @@ +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.world.biome.SpawnSettings; + +import java.util.List; + + +public class SpawnSettingsTemplate implements ObjectTemplate { + @Value("spawns") + @Default + private List spawns = null; + + @Value("costs") + @Default + private List costs = null; + + @Value("probability") + @Default + private Float probability = null; + + @Override + public SpawnSettings get() { + SpawnSettings.Builder builder = new SpawnSettings.Builder(); + for (SpawnTypeConfig spawn : spawns) { + builder.spawn(spawn.getGroup(), spawn.getEntry()); + } + for (SpawnCostConfig cost: costs) { + builder.spawnCost(cost.getType(), cost.getMass(), cost.getGravity()); + } + if (probability != null) { + builder.creatureSpawnProbability(probability); + } + + return builder.build(); + } +} 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 new file mode 100644 index 000000000..0f1eff6b5 --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnTypeConfig.java @@ -0,0 +1,31 @@ +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; +import net.minecraft.world.biome.SpawnSettings.SpawnEntry; + + +public class SpawnTypeConfig implements ObjectTemplate { + @Value("group") + @Default + private SpawnGroup group = null; + + @Value("entry") + @Default + private SpawnEntry entry = null; + + public SpawnGroup getGroup() { + return group; + } + + public SpawnEntry getEntry() { + return entry; + } + + @Override + public SpawnTypeConfig get() { + return this; + } +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java index 0bec88566..e44e4b977 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java @@ -11,6 +11,7 @@ import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.Biome.TemperatureModifier; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; import net.minecraft.world.biome.BiomeParticleConfig; +import net.minecraft.world.biome.SpawnSettings; import com.dfsek.terra.api.properties.Properties; @@ -42,7 +43,7 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { @Value("colors.modifier") @Default - private GrassColorModifier modifier = null; + private GrassColorModifier grassColorModifier = null; @Value("particles") @Default @@ -80,6 +81,10 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { @Default private MusicSound music = null; + @Value("spawning") + @Default + private SpawnSettings spawnSettings = null; + public Integer getGrassColor() { return grassColor; } @@ -105,7 +110,7 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { } public GrassColorModifier getGrassColorModifier() { - return modifier; + return grassColorModifier; } public BiomeParticleConfig getParticleConfig() { @@ -143,4 +148,8 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { public MusicSound getMusic() { return music; } + + public SpawnSettings getSpawnSettings() { + return spawnSettings; + } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/BiomeAccessor.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/BiomeAccessor.java new file mode 100644 index 000000000..c51029682 --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/BiomeAccessor.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.mod.mixin.access; + +import net.minecraft.world.biome.Biome; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + + +@Mixin(Biome.class) +public interface BiomeAccessor { + @Accessor("weather") + Biome.Weather getWeather(); +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java index fc2eb9def..1fa62bcae 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java @@ -30,6 +30,7 @@ import com.dfsek.terra.api.block.entity.MobSpawner; import com.dfsek.terra.api.block.entity.Sign; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.mod.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.mixin.access.BiomeAccessor; import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder; @@ -151,14 +152,13 @@ public final class MinecraftUtil { builder.temperature(Objects.requireNonNullElse(vanillaBiomeProperties.getTemperature(), vanilla.getTemperature())); builder.downfall(Objects.requireNonNullElse(vanillaBiomeProperties.getDownfall(), vanilla.getDownfall())); - - if (vanillaBiomeProperties.getTemperatureModifier() != null) { - builder.temperatureModifier(vanillaBiomeProperties.getTemperatureModifier()); - } - + + builder.temperatureModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getTemperatureModifier(), ((BiomeAccessor)((Object)vanilla)).getWeather().temperatureModifier())); + + builder.spawnSettings(Objects.requireNonNullElse(vanillaBiomeProperties.getSpawnSettings(), vanilla.getSpawnSettings())); + return builder .effects(effects.build()) - .spawnSettings(vanilla.getSpawnSettings()) .generationSettings(generationSettings.build()) .build(); } diff --git a/platforms/mixin-common/src/main/resources/terra.accesswidener b/platforms/mixin-common/src/main/resources/terra.accesswidener new file mode 100644 index 000000000..4f59bb962 --- /dev/null +++ b/platforms/mixin-common/src/main/resources/terra.accesswidener @@ -0,0 +1,2 @@ +accessWidener v1 named +accessible class net/minecraft/world/biome/Biome$Weather \ No newline at end of file From e21bb5c26d69795600d00abfb957605e00be21f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Sun, 26 Jun 2022 23:58:48 -0700 Subject: [PATCH 190/220] Refractor --- buildSrc/src/main/kotlin/DistributionConfig.kt | 4 ++-- .../dfsek/terra/bukkit/world/block/data/BukkitBlockState.java | 2 +- .../terra/bukkit/world/inventory/meta/BukkitDamageable.java | 2 +- .../terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java | 2 +- platforms/cli/build.gradle.kts | 2 +- .../src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/buildSrc/src/main/kotlin/DistributionConfig.kt b/buildSrc/src/main/kotlin/DistributionConfig.kt index 253869ae6..60e79867a 100644 --- a/buildSrc/src/main/kotlin/DistributionConfig.kt +++ b/buildSrc/src/main/kotlin/DistributionConfig.kt @@ -52,8 +52,8 @@ fun Project.configureDistribution() { println("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB") val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" - val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}"); - + val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}") + if (!Files.exists(addonPath)) { Files.createDirectories(addonPath.parent) Files.createFile(addonPath) diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java index f670d4f03..4a6716826 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java @@ -24,7 +24,7 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter; public class BukkitBlockState implements BlockState { - private org.bukkit.block.data.BlockData delegate; + private final org.bukkit.block.data.BlockData delegate; protected BukkitBlockState(org.bukkit.block.data.BlockData delegate) { this.delegate = delegate; diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java index 09e2e167b..74287e964 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java @@ -25,7 +25,7 @@ import com.dfsek.terra.bukkit.world.inventory.BukkitItemMeta; public class BukkitDamageable extends BukkitItemMeta implements Damageable { public BukkitDamageable(org.bukkit.inventory.meta.Damageable delegate) { - super((ItemMeta) delegate); + super(delegate); } @Override diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java index ff4e1597c..2b292142f 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java @@ -227,7 +227,7 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { this.climateSampler()); if(pair != null) { - BlockPos blockposition = (BlockPos) pair.getFirst(); + BlockPos blockposition = pair.getFirst(); k1 = SectionPos.blockToSectionCoord(blockposition.getX()); l1 = SectionPos.blockToSectionCoord(blockposition.getZ()); diff --git a/platforms/cli/build.gradle.kts b/platforms/cli/build.gradle.kts index 677d2f585..26d9f3d6c 100644 --- a/platforms/cli/build.gradle.kts +++ b/platforms/cli/build.gradle.kts @@ -20,7 +20,7 @@ dependencies { implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) } -tasks.withType() { +tasks.withType { entryCompression = ZipEntryCompression.STORED manifest { attributes( diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java index 12c67e838..899a97055 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java @@ -83,7 +83,7 @@ public final class AwfulForgeHacks { BLOCK, BIOME, WORLD_TYPE, - DONE; + DONE } From ca791026bd52e93d55954ae628421edb3ece6706 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 27 Jun 2022 20:20:23 -0700 Subject: [PATCH 191/220] bump version --- build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2938b5688..de1b02560 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,8 @@ preRelease(true) -versionProjects(":common:api", version("6.1.2")) -versionProjects(":common:implementation", version("6.1.2")) -versionProjects(":platforms", version("6.1.2")) +versionProjects(":common:api", version("6.2.0")) +versionProjects(":common:implementation", version("6.2.0")) +versionProjects(":platforms", version("6.2.0")) allprojects { From 18de2c3f99ada9f888c85b4c63ca3b639b12ee9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Thu, 30 Jun 2022 18:30:13 -0700 Subject: [PATCH 192/220] Fix dev launch for fabric and forge --- .gitignore | 5 +- buildSrc/src/main/kotlin/Versions.kt | 11 +- .../terra/addon/BootstrapAddonLoader.java | 1 - platforms/fabric/build.gradle.kts | 23 ++-- .../fabric/src/main/resources/fabric.mod.json | 3 +- .../main/resources/terra.fabric.mixins.json | 3 +- platforms/forge/build.gradle.kts | 29 +++-- .../dfsek/terra/forge/AwfulForgeHacks.java | 105 ++++++++++++++---- .../main/resources/terra.forge.mixins.json | 3 +- platforms/mixin-common/build.gradle.kts | 9 +- .../com/dfsek/terra/mod/MinecraftAddon.java | 2 +- .../src/main/resources/fabric.mod.json | 8 -- .../main/resources/terra.common.mixins.json | 4 +- .../main/resources => }/terra.accesswidener | 0 ...d.gradle.kts => build.gradle.kts.disabled} | 0 15 files changed, 140 insertions(+), 66 deletions(-) delete mode 100644 platforms/mixin-common/src/main/resources/fabric.mod.json rename platforms/mixin-common/{src/main/resources => }/terra.accesswidener (100%) rename platforms/sponge/{build.gradle.kts => build.gradle.kts.disabled} (100%) diff --git a/.gitignore b/.gitignore index 7e27208c8..11b505e85 100644 --- a/.gitignore +++ b/.gitignore @@ -246,4 +246,7 @@ nbdist/ /run/ **/testDir/ -platforms/fabric/run/config/Terra/config.yml + +platforms/fabric/run/** + +platforms/forge/run/** diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index f0b5efc0f..451f648a2 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -20,11 +20,8 @@ object Versions { object Fabric { const val fabricLoader = "0.14.2" const val fabricAPI = "0.56.0+1.19" - const val minecraft = "1.19" - const val yarn = "$minecraft+build.1" const val mixin = "0.11.2+mixin.0.8.5" const val loom = "0.12-SNAPSHOT" - const val loomQuiltflower = "1.7.1" const val minotaur = "1.1.0" } @@ -35,13 +32,13 @@ object Versions { const val architecuryLoom = "0.12.0-SNAPSHOT" const val architectutyPlugin = "3.4-SNAPSHOT" + + const val loomQuiltflower = "1.7.1" } object Forge { - const val minecraft = "1.19" - const val forge = "$minecraft-41.0.38" - const val yarn = "$minecraft+build.1" - const val architecuryLoom = "0.12.0-SNAPSHOT" + const val forge = "${Mod.minecraft}-41.0.38" + const val burningwave = "" } object Bukkit { diff --git a/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java index 37eba4762..244bef568 100644 --- a/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java +++ b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java @@ -96,7 +96,6 @@ public class BootstrapAddonLoader implements BootstrapBaseAddon + setOf("fabric-lifecycle-events-v1", "fabric-resource-loader-v0", "fabric-api-base", "fabric-command-api-v2", "fabric-networking-api-v1").forEach { apiModule -> val module = fabricApi.module(apiModule, Versions.Fabric.fabricAPI) modImplementation(module) include(module) @@ -36,16 +37,16 @@ dependencies { } loom { - accessWidenerPath.set(project(":platforms:mixin-common").file("src/main/resources/terra.accesswidener")) + accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) + mixin { - defaultRefmapName.set("terra-fabric-refmap.json") + defaultRefmapName.set("terra.fabric.refmap.json") } + } -addonDir(project.file("./run/config/Terra/addons"), tasks.named("runClient").get()) -addonDir(project.file("./run/config/Terra/addons"), tasks.named("runServer").get()) - +addonDir(project.file("./run/config/Terra/addons"), tasks.named("configureLaunch").get()) tasks { compileJava { @@ -56,4 +57,8 @@ tasks { inputFile.set(shadowJar.get().archiveFile) archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") } + + processResources { + from(project(":platforms:mixin-common").file("terra.accesswidener")) + } } diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index e6e490c1a..2d9a3db6a 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -21,7 +21,8 @@ ] }, "mixins": [ - "terra.fabric.mixins.json" + "terra.fabric.mixins.json", + "terra.common.mixins.json" ], "depends": { "fabricloader": ">=0.14.2", diff --git a/platforms/fabric/src/main/resources/terra.fabric.mixins.json b/platforms/fabric/src/main/resources/terra.fabric.mixins.json index 52882ee43..9b2d4bcec 100644 --- a/platforms/fabric/src/main/resources/terra.fabric.mixins.json +++ b/platforms/fabric/src/main/resources/terra.fabric.mixins.json @@ -16,6 +16,5 @@ ], "injectors": { "defaultRequire": 1 - }, - "refmap": "terra-fabric-refmap.json" + } } \ No newline at end of file diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 95cd6d82d..a667149d7 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -1,7 +1,7 @@ plugins { - id("dev.architectury.loom") version Versions.Forge.architecuryLoom + id("dev.architectury.loom") version Versions.Mod.architecuryLoom id("architectury-plugin") version Versions.Mod.architectutyPlugin - id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower + id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } architectury { @@ -17,34 +17,43 @@ configurations { dependencies { shadedApi(project(":common:implementation:base")) + "forgeRuntimeLibrary"(project(":common:implementation:base")) + "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionForge")) { isTransitive = false } - "developmentForge"(project(":platforms:mixin-common", configuration = "namedElements")) { + "developmentForge"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } forge(group = "net.minecraftforge", name = "forge", version = Versions.Forge.forge) - minecraft("com.mojang:minecraft:${Versions.Forge.minecraft}") - mappings("net.fabricmc:yarn:${Versions.Forge.yarn}:v2") + minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") + mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") + + //forge is not ok. + compileOnly("org.burningwave:core:12.53.0") + "forgeRuntimeLibrary"("org.burningwave:core:12.53.0") } loom { - accessWidenerPath.set(project(":platforms:mixin-common").file("src/main/resources/terra.accesswidener")) + accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) + mixin { - defaultRefmapName.set("terra-forge-refmap.json") + defaultRefmapName.set("terra.forge.refmap.json") } forge { convertAccessWideners.set(true) mixinConfig("terra.common.mixins.json") mixinConfig("terra.forge.mixins.json") + extraAccessWideners.add(loom.accessWidenerPath.get().asFile.name) } } +addonDir(project.file("./run/config/Terra/addons"), tasks.named("configureLaunch").get()) tasks { jar { @@ -66,4 +75,8 @@ tasks { inputFile.set(shadowJar.get().archiveFile) archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") } -} + + processResources { + from(project(":platforms:mixin-common").file("terra.accesswidener")) + } +} \ No newline at end of file diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java index 899a97055..1d0f44bc2 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java @@ -1,16 +1,34 @@ package com.dfsek.terra.forge; +import com.dfsek.terra.AbstractPlatform; + +import cpw.mods.cl.ModuleClassLoader; +import net.minecraftforge.fml.loading.FMLLoader; +import org.burningwave.core.classes.Classes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Stream; +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; + /** * Forge is really wacky and screws with class resolution in the addon loader. Loading every single Terra class *manually* on startup @@ -33,7 +51,7 @@ public final class AwfulForgeHacks { */ public static JarFile getTerraJar() throws IOException { LOGGER.info("Scanning for Terra JAR..."); - return Files.walk(Path.of("./", "mods"), 1, FileVisitOption.FOLLOW_LINKS) + return Files.walk(Path.of(System.getProperty("user.dir"), "mods"), 1, FileVisitOption.FOLLOW_LINKS) .filter(it -> it.getFileName().toString().endsWith(".jar")) .peek(path -> LOGGER.info("Found mod: {}", path)) .map(Path::toFile) @@ -52,30 +70,75 @@ public final class AwfulForgeHacks { .equals(ForgeEntryPoint.class.getName().replace('.', '/') + ".class"))) .findFirst() .orElseThrow(() -> new IllegalStateException("Could not find Terra JAR")); - } public static void loadAllTerraClasses() { - - try(JarFile jar = getTerraJar()) { - jar.stream() - .forEach(jarEntry -> { - if(jarEntry.getName().startsWith("com/dfsek/terra/forge/mixin") - || jarEntry.getName().startsWith("com/dfsek/terra/mod/mixin")) { - return; - } - if(jarEntry.getName().endsWith(".class")) { - String name = jarEntry.getName().replace('/', '.'); - name = name.substring(0, name.length() - 6); - try { - Class.forName(name); - } catch(ClassNotFoundException | NoClassDefFoundError e) { - LOGGER.warn("Failed to load class {}: {}", name, e); + if (FMLLoader.isProduction()) { + try(JarFile jar = getTerraJar()) { + jar.stream() + .forEach(jarEntry -> { + if(jarEntry.getName().startsWith("com/dfsek/terra/forge/mixin") + || jarEntry.getName().startsWith("com/dfsek/terra/mod/mixin")) { + return; } - } - }); - } catch(IOException e) { - throw new IllegalStateException("Could not load all Terra classes", e); + if(jarEntry.getName().endsWith(".class")) { + String name = jarEntry.getName().replace('/', '.'); + name = name.substring(0, name.length() - 6); + try { + Class.forName(name); + } catch(ClassNotFoundException | NoClassDefFoundError e) { + LOGGER.warn("Failed to load class {}: {}", name, e); + } + } + }); + } catch(IOException e) { + throw new IllegalStateException("Could not load all Terra classes", e); + } + } else { + // Forgive me for what I'm about to do... + LOGGER.warn("I felt a great disturbance in the JVM, as if millions of class not found exceptions suddenly cried out in terror and were suddenly silenced."); + ArrayList pathsToLoad = new ArrayList<>(); + + Path terraRoot = Path.of(System.getProperty("user.dir")).getParent().getParent().getParent(); + Path commonRoot = terraRoot.resolve("common"); + Path implementationRoot = commonRoot.resolve("implementation"); + + pathsToLoad.add(commonRoot.resolve("api")); + pathsToLoad.add(implementationRoot.resolve("base")); + pathsToLoad.add(implementationRoot.resolve("bootstrap-addon-loader")); + for (Path path : pathsToLoad) { + try { + Path target = path.resolve("build").resolve("classes").resolve("java").resolve("main"); + + BootstrapAddonClassLoader cl = new BootstrapAddonClassLoader(new URL[] { path.toUri().toURL()}); + + Classes.Loaders omegaCL = Classes.Loaders.create(); + Files.walk(target, Integer.MAX_VALUE, FileVisitOption.FOLLOW_LINKS) + .filter(it -> it.getFileName().toString().endsWith(".class")) + .map(Path::toFile) + .forEach(it -> { + String name = it.getAbsolutePath().replace(target + "/", "").replace('\\', '.').replace('/', '.'); + name = name.substring(0, name.length() - 6); + LOGGER.info("Loading class {}", name); + try { + Class.forName(name); + } catch(ClassNotFoundException e) { + try { + String pathToJar = cl.loadClass(name).getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); + + cl.addURL(new URL("jar:file:" + pathToJar + "!/")); + Class newClassLoad = Class.forName(name, true, cl); + omegaCL.loadOrDefine(newClassLoad, AbstractPlatform.class.getClassLoader()); + } catch(ClassNotFoundException | URISyntaxException | IOException ex) { + throw new RuntimeException(ex); + } + + } + }); + } catch(IOException e) { + throw new IllegalStateException("Could not load all Terra classes", e); + } + } } } diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index 355d77483..9bc9426db 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -12,6 +12,5 @@ ], "injectors": { "defaultRequire": 1 - }, - "refmap": "terra-forge-refmap.json" + } } \ No newline at end of file diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts index 439419b70..8646e8b39 100644 --- a/platforms/mixin-common/build.gradle.kts +++ b/platforms/mixin-common/build.gradle.kts @@ -1,13 +1,15 @@ plugins { id("dev.architectury.loom") version Versions.Mod.architecuryLoom id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } loom { + accessWidenerPath.set(file("terra.accesswidener")) + mixin { - defaultRefmapName.set("terra-common-refmap.json") + defaultRefmapName.set("terra.common.refmap.json") } - accessWidenerPath.set(file("src/main/resources/terra.accesswidener")) } dependencies { @@ -22,4 +24,5 @@ dependencies { architectury { common("fabric", "forge") minecraft = Versions.Mod.minecraft -} \ No newline at end of file +} + diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java index 76b13b137..edc8ea63f 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java @@ -75,6 +75,6 @@ public final class MinecraftAddon implements BaseAddon { @Override public String getID() { - return "terra-fabric"; + return "terra-mod"; } } diff --git a/platforms/mixin-common/src/main/resources/fabric.mod.json b/platforms/mixin-common/src/main/resources/fabric.mod.json deleted file mode 100644 index 2f4b9b0de..000000000 --- a/platforms/mixin-common/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "schemaVersion": 1, - "id": "terra-common", - "version": "1.0.0", - "mixins": [ - "terra.common.mixins.json" - ] -} \ 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 b084bee6f..b2b28d2e0 100644 --- a/platforms/mixin-common/src/main/resources/terra.common.mixins.json +++ b/platforms/mixin-common/src/main/resources/terra.common.mixins.json @@ -4,6 +4,7 @@ "package": "com.dfsek.terra.mod.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "access.BiomeAccessor", "access.MobSpawnerLogicAccessor", "access.StateAccessor", "access.StructureAccessorAccessor", @@ -42,6 +43,5 @@ ], "injectors": { "defaultRequire": 1 - }, - "refmap": "terra-common-refmap.json" + } } \ No newline at end of file diff --git a/platforms/mixin-common/src/main/resources/terra.accesswidener b/platforms/mixin-common/terra.accesswidener similarity index 100% rename from platforms/mixin-common/src/main/resources/terra.accesswidener rename to platforms/mixin-common/terra.accesswidener diff --git a/platforms/sponge/build.gradle.kts b/platforms/sponge/build.gradle.kts.disabled similarity index 100% rename from platforms/sponge/build.gradle.kts rename to platforms/sponge/build.gradle.kts.disabled From 7a4bf38cbcc6ee9c258b1e7ca42d6d00afd603e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Thu, 30 Jun 2022 22:00:21 -0700 Subject: [PATCH 193/220] actually version ify burningwave --- buildSrc/src/main/kotlin/Versions.kt | 2 +- platforms/forge/build.gradle.kts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 451f648a2..78517707c 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -38,7 +38,7 @@ object Versions { object Forge { const val forge = "${Mod.minecraft}-41.0.38" - const val burningwave = "" + const val burningwave = "12.53.0" } object Bukkit { diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index a667149d7..fc967677e 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -33,8 +33,8 @@ dependencies { mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") //forge is not ok. - compileOnly("org.burningwave:core:12.53.0") - "forgeRuntimeLibrary"("org.burningwave:core:12.53.0") + compileOnly("org.burningwave:core:${Versions.Forge.burningwave}") + "forgeRuntimeLibrary"("org.burningwave:core:${Versions.Forge.burningwave}") } loom { From 21d8be47269ef52c5937d3e2cf5540aeb2960e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Sun, 3 Jul 2022 13:44:53 -0700 Subject: [PATCH 194/220] abstract addon id --- .../com/dfsek/terra/fabric/FabricAddon.java | 16 +++++++ .../com/dfsek/terra/fabric/PlatformImpl.java | 5 +++ .../com/dfsek/terra/forge/ForgeAddon.java | 16 +++++++ .../com/dfsek/terra/forge/PlatformImpl.java | 44 +++++++++++-------- .../com/dfsek/terra/mod/MinecraftAddon.java | 7 +-- .../java/com/dfsek/terra/mod/ModPlatform.java | 6 ++- 6 files changed, 67 insertions(+), 27 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java create mode 100644 platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java new file mode 100644 index 000000000..21ed9870c --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.fabric; + +import com.dfsek.terra.mod.MinecraftAddon; +import com.dfsek.terra.mod.ModPlatform; + +public class FabricAddon extends MinecraftAddon { + + public FabricAddon(ModPlatform modPlatform) { + super(modPlatform); + } + + @Override + public String getID() { + return "terra-fabric"; + } +} \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java index c21f755cd..4c5ab038a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java @@ -143,4 +143,9 @@ public class PlatformImpl extends ModPlatform { public @NotNull ItemHandle getItemHandle() { return itemHandle; } + + @Override + public BaseAddon getPlatformAddon() { + return new FabricAddon(this); + } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java new file mode 100644 index 000000000..5b6e82ec1 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.forge; + +import com.dfsek.terra.mod.MinecraftAddon; +import com.dfsek.terra.mod.ModPlatform; + +public class ForgeAddon extends MinecraftAddon { + + public ForgeAddon(ModPlatform modPlatform) { + super(modPlatform); + } + + @Override + public String getID() { + return "terra-forge"; + } +} \ No newline at end of file diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java index 294fa01d9..5281b8ba1 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java @@ -49,33 +49,33 @@ public class PlatformImpl extends ModPlatform { private final ItemHandle itemHandle = new MinecraftItemHandle(); private final WorldHandle worldHandle = new MinecraftWorldHandle(); private final Lazy dataFolder = Lazy.lazy(() -> new File("./config/Terra")); - + public PlatformImpl() { CommonPlatform.initialize(this); load(); } - + @Override public MinecraftServer getServer() { return ServerLifecycleHooks.getCurrentServer(); } - + @Override public boolean reload() { getTerraConfig().load(this); getRawConfigRegistry().clear(); boolean succeed = getRawConfigRegistry().loadAll(this); - + MinecraftServer server = getServer(); - - if(server != null) { + + if (server != null) { server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { LOGGER.warn("Failed to execute reload", throwable); return null; }).join(); //BiomeUtil.registerBiomes(); server.getWorlds().forEach(world -> { - if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { + if (world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { chunkGeneratorWrapper.setPack(pack); LOGGER.info("Replaced pack in chunk generator for world {}", world); @@ -85,51 +85,57 @@ public class PlatformImpl extends ModPlatform { } return succeed; } - + @Override protected Iterable platformAddon() { List addons = new ArrayList<>(); - + super.platformAddon().forEach(addons::add); - + String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); try { addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft")); - } catch(ParseException e) { + } catch (ParseException e) { try { addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft")); - } catch(ParseException ex) { + } catch (ParseException ex) { LOGGER.warn("Failed to parse Minecraft version", e); } } - + FMLLoader.getLoadingModList().getMods().forEach(mod -> { String id = mod.getModId(); - if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; + if (id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; Version version = Versions.getVersion(mod.getVersion().getMajorVersion(), mod.getVersion().getMinorVersion(), mod.getVersion().getIncrementalVersion()); addons.add(new EphemeralAddon(version, "forge:" + id)); }); - + return addons; } - + @Override public @NotNull String platformName() { return "Forge"; } - + @Override public @NotNull WorldHandle getWorldHandle() { return worldHandle; } - + @Override public @NotNull File getDataFolder() { return dataFolder.value(); } - + @Override public @NotNull ItemHandle getItemHandle() { return itemHandle; } + + + @Override + public BaseAddon getPlatformAddon() { + return new ForgeAddon(this); + } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java index edc8ea63f..50fd7a428 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java @@ -33,7 +33,7 @@ import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; import com.dfsek.terra.mod.config.VanillaBiomeProperties; -public final class MinecraftAddon implements BaseAddon { +public abstract class MinecraftAddon implements BaseAddon { private static final Version VERSION = Versions.getVersion(1, 0, 0); private static final Logger logger = LoggerFactory.getLogger(MinecraftAddon.class); private final ModPlatform modPlatform; @@ -72,9 +72,4 @@ public final class MinecraftAddon implements BaseAddon { public Version getVersion() { return VERSION; } - - @Override - public String getID() { - return "terra-mod"; - } } 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 7d70b727e..ed9f2a986 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 @@ -86,9 +86,11 @@ public abstract class ModPlatform extends AbstractPlatform { if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure. return new ProtoPlatformBiome(identifier); } - + @Override protected Iterable platformAddon() { - return List.of(new MinecraftAddon(this)); + return List.of(getPlatformAddon()); } + + protected abstract BaseAddon getPlatformAddon(); } From cdb957403e4090d356f160a1c8099cb9c978ee70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Sun, 3 Jul 2022 13:50:07 -0700 Subject: [PATCH 195/220] Change memory to align to 1024mb --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 067f03e0c..62df22f83 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Magic options for more perf -org.gradle.jvmargs=-Xmx3048M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC +org.gradle.jvmargs=-Xmx3072M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC org.gradle.vfs.watch=true kapt.use.worker.api=true kapt.include.compile.classpath=false From 82920e570f24a407199b064c8f3e4afca09bb02a Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 4 Jul 2022 20:54:07 -0700 Subject: [PATCH 196/220] add quilt platform implementation --- buildSrc/build.gradle.kts | 4 +- buildSrc/src/main/kotlin/DependencyConfig.kt | 20 ++- buildSrc/src/main/kotlin/Versions.kt | 6 + gradle.properties | 17 +- platforms/mixin-common/build.gradle.kts | 2 +- platforms/quilt/build.gradle.kts | 60 +++++++ .../com/dfsek/terra/quilt/PlatformImpl.java | 151 ++++++++++++++++++ .../com/dfsek/terra/quilt/QuiltAddon.java | 16 ++ .../dfsek/terra/quilt/QuiltEntryPoint.java | 76 +++++++++ .../mixin/lifecycle/MinecraftServerMixin.java | 32 ++++ .../mixin/lifecycle/NoiseConfigMixin.java | 31 ++++ .../quilt/mixin/lifecycle/RegistryMixin.java | 19 +++ .../client/MinecraftClientMixin.java | 40 +++++ .../quilt/mixin/lifecycle/package-info.java | 22 +++ .../lifecycle/server/ServerMainMixin.java | 39 +++++ .../com/dfsek/terra/quilt/util/BiomeUtil.java | 71 ++++++++ .../src/main/resources/assets/terra/icon.png | Bin 0 -> 129860 bytes .../resources/assets/terra/lang/en_us.json | 4 + .../quilt/src/main/resources/quilt.mod.json | 52 ++++++ .../main/resources/terra.quilt.mixins.json | 20 +++ settings.gradle.kts | 7 +- 21 files changed, 671 insertions(+), 18 deletions(-) create mode 100644 platforms/quilt/build.gradle.kts create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java create mode 100644 platforms/quilt/src/main/resources/assets/terra/icon.png create mode 100644 platforms/quilt/src/main/resources/assets/terra/lang/en_us.json create mode 100644 platforms/quilt/src/main/resources/quilt.mod.json create mode 100644 platforms/quilt/src/main/resources/terra.quilt.mixins.json diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 21036749f..d6fbe2a8f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -15,7 +15,9 @@ buildscript { repositories { mavenCentral() gradlePluginPortal() - maven { url = uri("https://repo.codemc.org/repository/maven-public") } + maven("https://repo.codemc.org/repository/maven-public") { + name = "CodeMC" + } maven("https://papermc.io/repo/repository/maven-public/") { name = "PaperMC" } diff --git a/buildSrc/src/main/kotlin/DependencyConfig.kt b/buildSrc/src/main/kotlin/DependencyConfig.kt index a507eb96c..55f6f18b6 100644 --- a/buildSrc/src/main/kotlin/DependencyConfig.kt +++ b/buildSrc/src/main/kotlin/DependencyConfig.kt @@ -30,11 +30,21 @@ fun Project.configureDependencies() { repositories { mavenCentral() gradlePluginPortal() - maven("https://maven.fabricmc.net/") - maven("https://repo.codemc.org/repository/maven-public") - maven("https://repo.codemc.io/repository/nms/") - maven("https://papermc.io/repo/repository/maven-public/") - maven ( "https://files.minecraftforge.net/maven/" ) + maven("https://maven.fabricmc.net/") { + name = "FabricMC" + } + maven("https://repo.codemc.org/repository/maven-public") { + name = "CodeMC" + } + maven("https://papermc.io/repo/repository/maven-public/") { + name = "PaperMC" + } + maven ( "https://files.minecraftforge.net/maven/" ) { + name = "Forge" + } + maven ("https://maven.quiltmc.org/repository/release/") { + name = "Quilt" + } } dependencies { diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 78517707c..d5a77a8c4 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -25,6 +25,12 @@ object Versions { const val minotaur = "1.1.0" } + object Quilt { + const val quiltLoader = "0.17.0" + const val loom = "0.12.+" + const val fabricApi = "2.0.0-alpha.2+0.55.3-1.19" + } + object Mod { const val minecraft = "1.19" const val yarn = "$minecraft+build.1" diff --git a/gradle.properties b/gradle.properties index 62df22f83..35e42e00d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,11 @@ -# Magic options for more perf +# Project information +terra.description=A modern voxel world generation modding platform +terra.source=https://github.com/PolyhedralDev/Terra +terra.issues=https://github.com/PolyhedralDev/Terra/issues +terra.wiki=https://github.com/PolyhedralDev/Terra/wiki +terra.license=MIT + +# Gradle options org.gradle.jvmargs=-Xmx3072M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC org.gradle.vfs.watch=true kapt.use.worker.api=true @@ -6,11 +13,3 @@ kapt.include.compile.classpath=false org.gradle.parallel=true org.gradle.caching=true org.gradle.warning.mode=all -#org.gradle.logging.level=info -#org.gradle.configureondemand=true -# Project information -terra.description=A modern voxel world generation modding platform -terra.source=https://github.com/PolyhedralDev/Terra -terra.issues=https://github.com/PolyhedralDev/Terra/issues -terra.wiki=https://github.com/PolyhedralDev/Terra/wiki -terra.license=GNU General Public License, version 3.0 \ No newline at end of file diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts index 8646e8b39..47b720ca2 100644 --- a/platforms/mixin-common/build.gradle.kts +++ b/platforms/mixin-common/build.gradle.kts @@ -22,7 +22,7 @@ dependencies { } architectury { - common("fabric", "forge") + common("fabric", "forge", "quilt") minecraft = Versions.Mod.minecraft } diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts new file mode 100644 index 000000000..5bfcf8099 --- /dev/null +++ b/platforms/quilt/build.gradle.kts @@ -0,0 +1,60 @@ +plugins { + id("org.quiltmc.loom") version Versions.Quilt.loom + id("architectury-plugin") version Versions.Mod.architectutyPlugin +} + + +configurations { + val common by creating + compileClasspath.get().extendsFrom(common) + runtimeClasspath.get().extendsFrom(common) +} + +dependencies { + shadedApi(project(":common:implementation:base")) + + "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionQuilt")) { isTransitive = false } + + minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") + mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") + + modImplementation("org.quiltmc:quilt-loader:${Versions.Quilt.quiltLoader}") + + modApi("org.quiltmc.quilted-fabric-api:quilted-fabric-api:${Versions.Quilt.fabricApi}") + + setOf("fabric-lifecycle-events-v1", "fabric-resource-loader-v0", "fabric-api-base", "fabric-command-api-v2", "fabric-networking-api-v1").forEach { apiModule -> + val module = fabricApi.module(apiModule, Versions.Fabric.fabricAPI) + modImplementation(module) + include(module) + } + + modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) + include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) +} + +loom { + accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) + + mixin { + defaultRefmapName.set("terra.quilt.refmap.json") + } +} + + +addonDir(project.file("./run/config/Terra/addons"), tasks.named("configureLaunch").get()) + +tasks { + compileJava { + options.release.set(17) + } + + remapJar { + inputFile.set(shadowJar.get().archiveFile) + archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") + } + + processResources { + from(project(":platforms:mixin-common").file("terra.accesswidener")) + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java new file mode 100644 index 000000000..958e61080 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java @@ -0,0 +1,151 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.quilt; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.Version; +import net.minecraft.MinecraftVersion; +import net.minecraft.server.MinecraftServer; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.loader.api.QuiltLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import com.dfsek.terra.addon.EphemeralAddon; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.ModPlatform; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.handle.MinecraftItemHandle; +import com.dfsek.terra.mod.handle.MinecraftWorldHandle; +import com.dfsek.terra.quilt.util.BiomeUtil; + + +public class PlatformImpl extends ModPlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); + private final ItemHandle itemHandle = new MinecraftItemHandle(); + private final WorldHandle worldHandle = new MinecraftWorldHandle(); + private final Lazy dataFolder = Lazy.lazy(() -> new File(QuiltLoader.getConfigDir().toFile(), "Terra")); + private MinecraftServer server; + + public PlatformImpl() { + CommonPlatform.initialize(this); + load(); + } + + public void setServer(MinecraftServer server) { + this.server = server; + } + + @Override + public MinecraftServer getServer() { + return server; + } + + @Override + public boolean reload() { + getTerraConfig().load(this); + getRawConfigRegistry().clear(); + boolean succeed = getRawConfigRegistry().loadAll(this); + + + if(server != null) { + server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { + LOGGER.warn("Failed to execute reload", throwable); + return null; + }).join(); + BiomeUtil.registerBiomes(); + server.getWorlds().forEach(world -> { + if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { + getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { + chunkGeneratorWrapper.setPack(pack); + LOGGER.info("Replaced pack in chunk generator for world {}", world); + }); + } + }); + } + return succeed; + } + + @Override + protected Iterable platformAddon() { + List addons = new ArrayList<>(); + + super.platformAddon().forEach(addons::add); + + String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); + try { + addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft")); + } catch(ParseException e) { + try { + addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft")); + } catch(ParseException ex) { + LOGGER.warn("Failed to parse Minecraft version", e); + } + } + + QuiltLoader.getAllMods().forEach(mod -> { + String id = mod.metadata().id(); + if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; + try { + Version version = Versions.parseVersion(mod.metadata().version().raw()); + addons.add(new EphemeralAddon(version, "quilt:" + id)); + } catch(ParseException e) { + LOGGER.warn( + "Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " + + "it.", + id, mod.metadata().version().raw()); + } + }); + + return addons; + } + + @Override + public @NotNull String platformName() { + return "Quilt"; + } + + @Override + public @NotNull WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public @NotNull File getDataFolder() { + return dataFolder.value(); + } + + @Override + public @NotNull ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public BaseAddon getPlatformAddon() { + return new QuiltAddon(this); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java new file mode 100644 index 000000000..6a34eab74 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.quilt; + +import com.dfsek.terra.mod.MinecraftAddon; +import com.dfsek.terra.mod.ModPlatform; + +public class QuiltAddon extends MinecraftAddon { + + public QuiltAddon(ModPlatform modPlatform) { + super(modPlatform); + } + + @Override + public String getID() { + return "terra-quilt"; + } +} \ No newline at end of file diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java new file mode 100644 index 000000000..20adb8e3b --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java @@ -0,0 +1,76 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.quilt; + +import cloud.commandframework.execution.CommandExecutionCoordinator; +import cloud.commandframework.fabric.FabricServerCommandManager; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.quilt.util.BiomeUtil; +import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.data.Codecs; + + +public class QuiltEntryPoint implements ModInitializer { + private static final Logger logger = LoggerFactory.getLogger(QuiltEntryPoint.class); + + private static final PlatformImpl TERRA_PLUGIN = new PlatformImpl(); + + + public static PlatformImpl getPlatform() { + return TERRA_PLUGIN; + } + + public static void register() { // register the things + Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER); + Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); + } + + public static void initialize() { + getPlatform().getEventManager().callEvent( + new PlatformInitializationEvent()); + BiomeUtil.registerBiomes(); + CommonPlatform.get().registerWorldTypes((id, preset) -> BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, id, preset)); + } + + @Override + public void onInitialize(ModContainer container) { + logger.info("Initializing Terra Quilt mod..."); + + FabricServerCommandManager manager = new FabricServerCommandManager<>( + CommandExecutionCoordinator.simpleCoordinator(), + serverCommandSource -> (CommandSender) serverCommandSource, + commandSender -> (ServerCommandSource) commandSender + ); + + + manager.brigadierManager().setNativeNumberSuggestions(false); + + TERRA_PLUGIN.getEventManager().callEvent(new CommandRegistrationEvent(manager)); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java new file mode 100644 index 000000000..53277b18c --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.quilt.mixin.lifecycle; + +import com.mojang.datafixers.DataFixer; +import net.minecraft.resource.ResourcePackManager; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.SaveLoader; +import net.minecraft.server.WorldGenerationProgressListenerFactory; +import net.minecraft.util.ApiServices; +import net.minecraft.world.level.storage.LevelStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.net.Proxy; + +import com.dfsek.terra.quilt.QuiltEntryPoint; + + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + @Inject(method = "(Ljava/lang/Thread;Lnet/minecraft/world/level/storage/LevelStorage$Session;" + + "Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/server/SaveLoader;Ljava/net/Proxy;" + + "Lcom/mojang/datafixers/DataFixer;Lnet/minecraft/util/ApiServices;" + + "Lnet/minecraft/server/WorldGenerationProgressListenerFactory;)V", + at = @At("RETURN")) + private void injectConstructor(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager, + SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices, + WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { + QuiltEntryPoint.getPlatform().setServer((MinecraftServer) (Object) this); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java new file mode 100644 index 000000000..6b863cca0 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.quilt.mixin.lifecycle; + +import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import net.minecraft.world.gen.noise.NoiseConfig; +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; + +import com.dfsek.terra.mod.util.SeedHack; + + +/** + * Hack to map noise sampler to seeds + */ +@Mixin(NoiseConfig.class) +public class NoiseConfigMixin { + @Shadow + @Final + private MultiNoiseSampler multiNoiseSampler; + + @Inject(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At("TAIL")) + private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, Registry noiseRegistry, long seed, CallbackInfo ci) { + SeedHack.register(multiNoiseSampler, seed); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java new file mode 100644 index 000000000..55d649d44 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.quilt.mixin.lifecycle; + + +import com.dfsek.terra.quilt.QuiltEntryPoint; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +// Register Terra things to the builtin registries. +@Mixin(Registry.class) +public class RegistryMixin { + @Inject(method = "", at = @At("RETURN")) + private static void registerTerraGenerators(CallbackInfo ci) { + QuiltEntryPoint.register(); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java new file mode 100644 index 000000000..6556ba806 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java @@ -0,0 +1,40 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.quilt.mixin.lifecycle.client; + +import com.dfsek.terra.quilt.QuiltEntryPoint; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.RunArgs; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin { + @Inject(method = "", at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/util/WindowProvider;createWindow" + + "(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)" + + "Lnet/minecraft/client/util/Window;", + // sorta arbitrary position, after mod init, before window opens + shift = At.Shift.BEFORE)) + public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { + QuiltEntryPoint.initialize(); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java new file mode 100644 index 000000000..23f9f63d2 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java @@ -0,0 +1,22 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +/** + * Mixins that inject behavior into the client/server lifecycle. + */ + +package com.dfsek.terra.quilt.mixin.lifecycle; \ No newline at end of file diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java new file mode 100644 index 000000000..577e2cfe2 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java @@ -0,0 +1,39 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.quilt.mixin.lifecycle.server; + +import com.dfsek.terra.quilt.QuiltEntryPoint; +import net.minecraft.server.Main; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(Main.class) +public class ServerMainMixin { + @Inject(method = "main([Ljava/lang/String;)V", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/resource/ResourcePackManager;(Lnet/minecraft/resource/ResourceType;" + + "[Lnet/minecraft/resource/ResourcePackProvider;)V") + // after registry manager creation + ) + private static void injectConstructor(String[] args, CallbackInfo ci) { + QuiltEntryPoint.initialize(); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java new file mode 100644 index 000000000..e26d08938 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java @@ -0,0 +1,71 @@ +package com.dfsek.terra.quilt.util; + +import com.dfsek.terra.quilt.QuiltEntryPoint; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.util.MinecraftUtil; + + +public final class BiomeUtil { + private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class); + + private BiomeUtil() { + + } + + public static void registerBiomes() { + logger.info("Registering biomes..."); + QuiltEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. + pack.getCheckedRegistry(Biome.class) + .forEach((id, biome) -> registerBiome(biome, pack, id)); + }); + MinecraftUtil.registerFlora(BuiltinRegistries.BIOME); + logger.info("Terra biomes registered."); + } + + /** + * Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate. + * + * @param biome The Terra BiomeBuilder. + * @param pack The ConfigPack this biome belongs to. + */ + private static void registerBiome(Biome biome, ConfigPack pack, + com.dfsek.terra.api.registry.key.RegistryKey id) { + Registry registry = BuiltinRegistries.BIOME; + RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(registry); + + + if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); + } else { + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla)); + + Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); + + if(registry.containsId(identifier)) { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(MinecraftUtil.getEntry(registry, identifier) + .orElseThrow() + .getKey() + .orElseThrow()); + } else { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry, + MinecraftUtil.registerKey(identifier).getValue(), + minecraftBiome).getKey().orElseThrow()); + } + + MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); + } + } + +} diff --git a/platforms/quilt/src/main/resources/assets/terra/icon.png b/platforms/quilt/src/main/resources/assets/terra/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f458866a0d1cd397e5fa592ef1707a97722f1f GIT binary patch literal 129860 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
_vO6)hziR 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%0DMHvKS|?`Q93A21D4 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

C7Im@Ow zfOG_FV~Bf~=X6a4`)fWHE|=$M*CTb<@VD$ zBc`JVS8^UnLdZ%`%>7KV@?coWq#`YkEW~Y)?OD z+L1>B$kF2D$P}FB$#?QV7TCA$zrB^t1R#X-%|PM}k1~ zq+<=>xNB>!tna?rall&WR7Z*d1`=N5Y2;>eT6WR6)-pj!H(XLVdmoJ3J&((d{c;#b zn|BmqQybvZ@!*5S_QM-fhTvrk@o%Nuca$!EcAY(yY9Dr193JQt;+E1bkJPuGhX}VP zO}|QYA_w?>9F>>YX;8hKRJx_R@`PoJh`ryKWoX@aTdZUXtiwhtHRqCjm`>HAUmCG) zTpo?p# z-_a+X)U)_gJ57pwTjgai z+!H&!1>lU5w~f*_+`59H%d%HezVbm6-E;{6wEYgCgl(2 z;u#tS-@A7sgHgYS0)i?$n&@rv4oPe?D?Q@Y9WkHl~2Unh$OP&NAWkJCR~BJOMwl3Ri zjhYETYDJOWSS8@XYSXyS2r?#rfK%%3l($*CrbZPJeNi9bOD5KiqHn*o4HP0We)}rxntJnN?ZkG+ zr+wSu{TP15-{Zzw?;90@OOb^fr2^4ihs>B;;Z#cPcQDKE2_-6JrR=ij;)Im>q`phl zg(q`a-|$9hW}aw`+C>AMN^y9NAiP3mMc60|TlEC9xliv+1vQ1PAsy*TU~^}x?HeAV zow1Pp@EYtdvcAqIL&`ZEi=;V^l1;ic{e9oY0rkol`ZjOzRKBjCoUzNAwJQkKK9+GveTKR z;r0>GXt`z!g1nqCT)NgS$(=++hejonoCm+A5!Ys772w2;SerIASMpfeN9<@mGWuIN62R=2{_BO0JHX3=*i() zoq9v8G@_Os%DYy3H10XP5zxfY_+2Oyv<(?iQXi)3;`!w!wO*q3wxW~N-+vr+jGSCE z0k7hsx#HQZN!WT%L)LfegY4mLcSaH1hi~-WsV}27Cb`kVlYB;3tRx~y<@^$ZLbi0Z zu;ppA9rt&k!yojNZLTLmb5EbWlwF^+$p7kSQ)?|rPa^(b_-a_$(LIuh+uVGFA>T9B zR?ioQUz!i4_I_@8!}_lO9y8t0Wp#o1RNF|xeRW~@M9madyA~B+n!M~+$bzeO4xwgt z>ymPIoa|=$z#rO(A>w?R45E;#nVNXHPK=EaS?T?CZMC&5j7xzTd`INxvGCHV`9Zr4 zsH!VI-i?%m&pSfp`_yr-qv~*u{>V^6B6tV%7qpiaqU?ZyjvI(cA zUsfcE#Z>H67T3u8-zLL&2;P&`G>)q%i&~mahpXi#?`~@kXOoYBj9_`4Air;`&Jltd zxp;Va_SMvxc7`nusS@kbcA|m&qy9u!Kc($h5-&Nxc|j^bkEC)!`8e4>3)F10SxQ`X z)*$+POM-o98=e`*g%IQ+*39oDteGjif&!+E%RqeO#NCPJZcNNMz>zA?kgV4h{KiEZ zJZK%(bD0!ZO9T~vXO``jW3}s@unU3gxUa)Xe`mHpcFjs|Fr`G)_-D%b(L2Z;iz0Lq z|IC(}{3DZcyIVOFQXN9=h|_Ug-;#3SE=-sRlb7Z0wE8d!0q#=^d+uE#)S zUc15laDzVM=3FJ;hS>2@N;)`O-K%zkacSpEG1rhc6ereZHh6Rx?Z;LZf|`YM1wMAX z@NhjRnW==>SMRVTFQkdVDUl@LQ~?t6g3|R!lCgO6;n*wxNzNAxwaJ071SQ87b!c`q zJ8qE!_f%lZp#6Z~g$|cgs5|k`5kJr*%h_>1V@a<#S&Pky2?7311`SBnsk;}gB|0%o z_F?_y*zH*8=y5{H6dw-I311`l>xETJ{YfhI-}BV85wiuhKk@f}Gp7!D*YFPl{(MNY zId>t6;jV@wsCa&)cSX^)fNV6i<;AcTAfcUau!4*Mn4mD4*QbGu&e`FaZS-L1B(Fqw zC9D|ciNaj-q6p}6zrXvwMXdC@mN9s6)RpM|8msB=9|8P!0D9cT2E88Cvn3Nu5A~rV zB?!cI9+vJH9C35yGf${NDbSi~5x{UUO;0+jR|}6)1PplRJx0E_Gs?hNc{FO9 z_N%~vDcB9AT`6k9hLcl1rk&ya>Mz1^~?y0NpwYUNiY2f6^1Q!m&!#O`0rG{+VV zxqgWOE&~#g1;7)&q*If;$^H2kuulq10!{&QTO~gG)-gpB8C$@3**+|XN4M@i_tQ6i zA}lzw7K6Ldzo&nJuFDiBKOOvpi6DICXFUnPC=h*hY$(ZD^MnN;j3$5=xF#IRoSGCx zddbZ$&8Ne#!XdT8z|%^_UIB&-Aw>V%ty-O56HH%r!K4>3j6YT zVLT2*%d#0anxjG<&vAg`dl^|#>>aNZ6g1sr-vs${<3crEf!||xGdd3`*@zrJYOqZU z!rl+qNy9=a!63*qW)N~&=%JDJ=Y$a=_k?BHg!>*aau7J6wI*XL`dav@4rn=-e-8oc z`$3yQ5M1m$fa34{i{d2=NSREeAXJLfecEL2ktJD1bcEZpyU7o0rhy;n?01U3V>OlI zX{XW;`nzvS4X{4|Ry8^jSsa*8=V7$bzp zfz4Xgc^=l>3vmOG%_Z>zgHOF2$a{u?jx&4Q?AO`rL3EE3o#fL=Iqv~_~p?~?fVDXc8Jy*TM=DUIOORjd^YHw!!W*!5?^t?k^bvcCnX2-E2dthbxT7 z?js6sVd9HpUZt}u^54f-d_CcAY&SES($9*7la(k91|w7G&wSDxzIBQ8q*0zwh(-<% zh^z5WJs7)wb}bRN?%ZT4%{QYboubQw!0P$GUPPSrZ=ybAB}bkwo%iOtHkj^SaNR=q z?g_VNJ(A-dyN-(o*N2bR;(334!}A_)xA4yClB(s;U=Zu_Hh8aw<}HVYkgW7s9N@$U zBdMS13*Ck<-tx_1*!R)^%y~S29qX%phbi2(P&e{1sM2=qQ&uIGjS7v&P#uJlv$vY& zj<2@9;8O{+B9%wKQid}EZj;lcZN#pPEdd$s!&W6UEPDkI4;k?q9(S=~)@e5~eor*) z)V-VJP5jK6zA~{AdCloYezW(b2$bVh3k@)SA@_2vO*;rWswe04n?|uv5|sl4SJy?) z=2#NoP7IS4_kaCRed~QG4f#|#)3|vscjie=v*W_V72uCt?);V%iTpdem~ArRvdk8U ztqm45Dl}=mFH}p0Q+IB1v_Kgt`45fp=PiyM-)754z44oByvgsr0-v6fhYnza#NkR2 z0ISzXvKGGFtVwAOKHypiPe(^w4NKgD4{IA1i1^%`7_MXJu5`>8FoTL4S0HiONeU%NrOF?bsl*;RAR z?chPN@J2B+2DlN6$oQvtM{8VCplCnfl2F>0%CIc$+lxn&L^n7KW6u7q;c zp_|qP7w&iYqP0)t`9G%&Byo^um^!{DvADPo3!cjQEh7Af8YkK|x%r+03i5Vcy0bP! z93BwO9k3jeOxg%0O>gYfCNq&pE#V&47llVjB8)%tOqcrT_f;g+eCGKQ zVz2^q`u3zGI+7ZifUWjx$n)yH7k)1$778wvwyx*|HGW^6KcRUtZ+NSszNUC`!yixDYAA_JMZbq6QIY za9X+AwOMf~I0jm``r-qm*M5;Z#b5Pe?#jo`#yFZ~pQ=PUjQN_ra(_HwHn37VV+RwJ z>szrq)++n6H%7H&{Fca-_hp7@Q$M}e8(tBrJ`lWr(hAG^H(LK<9>vx<=0?-3V>U}6 z#{xErz4QcUUKzswruXm@X^ZJt)m25vmtf5;3jU3W0_e^7b(9^#Gv0F2hoL`zpM@937lKOV)E5#yu|x@3 zSNs&T?zh{z>BJ=7-Ygfdi62DORYr67VsMYqo!Db*~ zNUW+;fuNxpG}Nub?OcB0O_=JQEWgDs>yiV;&iTL!J%9HqE6ffZJ3UFrCr)*bNc^Bh zb6ccb*`Yh4AAX!K9Iy7c$o@t7sPX%L=VBlZRRK zoE1dbha&}#{o2Fd)&e}1Q*HaMvA6^c3VseR-k~RvI=Q_#2Id34R3h%};is7v8ZKvjD2Dh#=2ruEzX?{CcNBQ0qg` z{mw6JZNMLKeyh*^`$f}R(~0WzfS+Q={e8Zau1PkFEY+8Z$~P9sYj-?{!CKsjQN9%P zRR&sb_){Da_dYu5*&S>U@8Fl)fNN$YRJNTNnD`g?yx@rd#m28wWBHNq!K-pYRa!w&+n`EGxaX_HI=s;spM0a zcWQ{o`Uc#!m0AOEp;kfL*3pbS@JeUscce3K3$VL4B1I_8`WR z?A699B}v?ZU!I!n9eYJKxEw-#eXI`;>!1Iy#uqakw(*a=IDA;av)?_`4=+Xla_l-flFb!_e$0 zZKh}g!%n*!P|191oocOnjPO`;p7lS>Fp)RTk>r;W+MPv z{Bi7 zHFNV{yJK9xz($Ap=8j3xY@YXy$8mxq=5Z(Qd~rhC0nV&7icqyn=6`CaRnD_;ah%Dg z>faUVl1-RjJ|$yvmf|_nn`)aYX)|`{J+)X8zj~`qP9RRuI!e$cB7_EF zOBk~_72sshz{6LXat+Ko?3N&hKfd;vC#8FAg?OuW0oa8Vt%XbaYF9oySl{}`5cp=< zr5aiw+VR@Nn=zNBs*bGbNp>+H)g()A@_79`tNMSd!l_54=`{Nb(35Qp&N^ydf@ZmW zkK;e&>OOiAGsRzmZVMj+7oILtXr`*AL+9W(Kd>8Hd*q4PJPCn}BV&AXm4MAe0&e_* zr^F~AZ4C1c6v*a zF*j^7@>#RN-3%1~v9d*yPB@yW1~_E4M*&O1anifAVD-hb$?I&Z=?RyLIqhn?}`<+*Igp(G%+8 znd8I?eq2fQW5k1mlq=!OWE%VH;$5egseIIyYi5!O&DX+{i~>wG22yk8vjpzbK`&2X zXTwONO1y@#{S)iJp?Ok;Bf04+L~YupIy#pjV( z>P`!k_clyowHx`r8r3iCceT`1Ys30L!H5|d$2rTlb*SeHeYx5yzIV8>5n|x6_sfYs z5Fz1HFAh)RC;`A~K;~Xa-k9vUm&d0F93>PijDP1=Iu&i)>;rN5{`$gao=m2fevcq6 z!{yc|1G~=#HyKnQu|f}A>#RK};_#J%b5bQ!^4FZW6lJ8f50Uiy);h#88l4Yq zll1(5_zYtXPx%IkYB#oKiShUG0Pvu<`$o0l9wX!W(65K-#~{{;hHU5^R-gZ+?i@?Ggv>&MT6FtnZDztDy!Y=`ot| z_%Ec5Y|@n8dDosB65k8%35fkk%fHnLFO7Cv@g>p z%fEsi?Y-hX{54}uCXOuqvdA~YAnd~?-y*R*8)`G=jhe5=2kd@b{PzYsjH;%*AFFMb zoeQtDWVDkhJ?HEZDyQQW7f zoEwm$6Q~$hO(~u(AcN#SQWB3t^-u!}7rY8%5}zTol7BNClxopIuMFybS3oTUKQ+yM zz(~)zB5i^{^9R%P0=aQiurW=h86J@!uzvfWcPeE8q$uBF!{HUB<(Tm;;ctFn!e>m9kE1@{ly&AEnje0QHTK@yOe1GhdSjFuN zjx)V#H@VU~w=^~RII)e^+NHIlT5T$coUc6d$;~swtqe$Vu6M2lL1K}aSuBMEF1pb7 z?McqH){J6cHu)1J5D{waeDIa1y52$q*$ioTNx&=U$rE)D_(s}SDMZ@$HT_$k#Nm2` zxRd(bfp~M+g9XV#x}YV&wSI?|Q$m1Um{~2o zJ0X&QdRni$j`bV_j@j3$Icb{T0%p&axhtQN`4=Kw660TOFx1shy=0RAJE(BQH)db( z6#q*(#r4)%E3w`z`Uqa1hy2puF3jh%BcPve>q8^K*G1_`6geG+f$wXsiqk1=;LGH} z-$f6F3nQRUJ$T8Ht%{jGpg6IJ%njQCcjLH$_gC8#3PjDFWxzS1zr55fk@dgY{eJ`v zNNz`OXTIS+Is8Smhc@14BpqkqZf44p3wfW7#jmeud&UeI49LW}u0=|~=Q(fU&;LMr z0d@=&V)ACwAXunO#ee9-_e$K;XpsZu_;AdH6$>u`s@C-dlCDqeBnAb7*(4{+B&M8CFgEe2W>zA7nbtKA|2 zSefbF$59GO7f2?KR8i*Ju(<%fj)t>&9bGXhZ__AhA4MYBhq(R}w4J;&L3xY31;`*o zI3R-_IRVk&IOpadC6(8Bwk}WN10ZP57x3LS??GCZCtR&gRuUg^U~^(wgat$pdZBJ0 zfb_k+2guSPuTJ5TiWWA>l5w1v8LC$96?9-)KRW1#t`{W|0yh%->6d9xHjQ3RB|ll1 zg#dm}$*#a>aCN#nnoG)=Jfi+YK*l2XQrjGXOX2v^9wQGq1OpAca|sis)bU(d0l}ah z6i-uO+`TP7#f^)23g9dhX4HFzR74lz*65cRCun8KB{r!HoIJ!KugiMj)Jh=xBt9&- z-3ZGv+pe2y>#$k|<=tt5eAB>IWvqReULGXnVb!~@l!a&VLgDJ^^_&eeZY=-Er{p4+ zUPt(Q$UxXmXI_tG0&yht4|n7cHhxRDPD?R;%r$FRrsIWr*D0x2eP$Q8zdEhm9n_oF zSXRspD-nAt8)S|}7IG^DX*iShg@>-f@NZpIv9|TAl}x!|&VyPVeKc;z$LEK}H}19a zZkEztS;yUspAzXv14?770ip+MgjB+oTM|z#LT1_bY5kcTo-Q-|wt~2Fx%KtgYn5eL z$2}9E2dfjUw%_cD(0{`-W(cG&DEhzx*K6xa{(y@?7&;yPXo zhbrWk8LXYhYJD1fMPdW>$Dm+N?sb{1l&B}ZOV*$zk9iFMdh`{2L}*YUD=rS03(8}m zVaH^P+tD4OTal$=X}>FZ_u{_?mxV9olXA(qXXtVUwRDhgwds`fFUdYgpv-IAoh22c zTv$GkI4v3z>7a5HpL#>LpD2oo`}d#`$&dXD+~oBEm^&fG!OG z6jlqbmK7f{ACOmQ8wm7zlm#6j_25c3I$jW9jz3|T+PG*ZeeQ7`ho~N z>-&_q`Mhy+{(aq)$d_L>bQrC+&f($`K^6Z*PBG#+ghZd_?Z`r1?SFWz3 zc8YeqlP(6i6#dXMDE<#}zlYa-r-W$cpS>{gplW@pEV-Q_{OP$m=MqgOrM&5cHw@}S zg8K;G7->X6n5)B780kWxH-7FcwA;AZ)Mac{DQPAQih4`t23ibXc>*q|u!fA)Nwm!X zL@jXVmY{%W{BVuPTD<1HHRb(tnyzLAbZsaO3Eh3{DEmV?k;41)QIF5=1y}R{H>gi5 z|Cfq?MCs;pOcmbKb_-K6Fs%ojo(tTb-kh#6vbQ4e`$LIaFI01b0=*_)Z}DPNrT9gn)~7ql6Z_zcuaZCmcq?nNq_6qHS4{oAQ@i~y9y za<{SLEc(~ec(2{LU(fo=!bXLxf4`o1SMK+Xy#n$9@Kg>y87J2DN$`&u}`@!3a3+db65e4NB0JEV}*){ouzJ9M>L*HHuG~ikOJg z9f$6u56pI;>k;?U9ZIqX+dL{UARYaav)D8EL5J`ob+A7y}Di@Ls zRqZF}{)4RtskZrdx!YZeq1s+;71nsB@7P(}(%ZaiuF4e5glUXyFiz~)#!3Wl4~&Wr z2lX-ZCrm})g^Rwb34r$$z3_f~MPJm;$oXd&MxWgIupNvp=t1N5Ck2w$@|E)3#)KMT zsE$|SF>G(;xt~{BCilH}Vr!@U?*Xoqt!2n$d+`oJu|aMbG1H1Np^z7-s;pJLec@Y_ zXK%H9)D;S{QI0>J17KnTL6n`8=OnAF^aK{4Ty`m{&>2@$)BP8wIeeK|0Wjd~&k6n6 zR?*kB*3AZWutPrR~_nZ^=Ubl9%kqhL&%J9N?@BGkaUohpnzd0x`oQ*-eL?KE-cUXq-`Qhd&X zoI5&Rz*N>!Ar#z4B#yBOhJUK=funq=N?&s&c!prM@~f88d}tU)1<_ zX+j>J{dT4|n%n&LNXfM+v?Rg1`+`kvqIZ4le%_8*(jB!?Uj^;M`+RKxt}ZP+EjNbo zZ)xY4H1ZGJa7tZflmJlx9ABF!p?GXMLCOj=PcH0IyPJ{D+411X7PidzYdmr1uN#uJJnP2EqC@Q6IUE zSJ(?K(pjUimwMCWnUMkRgpukef{!CefOW ztn`>L8I7uS@6`i3?%;asS{gUd6j%b90==fRJZ1lK0c!qr1E1`?i~pi|;IBch@$B5H zebkB5it@Kj8F3DU027%E*5EOTO5U{(0~RgX!D#MxLI|1D#XDcLUHn^$Rv)UUq|trz zQvuq%UMQ80Plqv^Xghe%F*?YEtbePPsg2~nb<=Yr#vROtco*bR+-$MD@E zG+%!()F)*996hJtpNAM$U}FDV5-cV)>O(eZ0_9|pWf77O3It4atj<5Oe(&yYgCx>@ zHRgHD#5Ln%|1|%QWi3BRuhx(X_+}x*PBd5TbP~AJ4O|HtK;_5a*k`C;Nusl>;YsC3 zTPze+_QdTJK3U$*n9a|YZ3pL^xuv{^J^j1mMuSq={w*^Fccf}2vzVqA;xA-Zrmlv1 zbGq*+aRPM~!1n$+;!uWuHRQ$fD*he4_S{?C{_i!m8|2c{4sdDNlgBWA>lM?u6yNlW zeWy9^p2-m4D((EV4XPpF+kJ9MHlQBmktA>!5!5o0Ppw3MS+##m95fd^IJ6tSfcUjj zxlBi1yS<3Tk3VYTJdg@fnrk15_^b8*I7I+Y5)N3#MlQ5ra@B$+Y+L7hM8_T#L)G4# zx57{9lbU(j&a$Bzl>`{Oc5C=+q=&&5Gj?k2=rJjVn2}hLJr6=sy-oQ)foNxqE&t5feIOH{-d63#n z+q}J6kRr<`Nwv}c1$-TMqwuvMJToSM5C7e@4FjIa{knwo-6&B&S{iJD4uqwMu*YHt z#AmgZ@3N>+yBV8IV#)N-zGiM^#%5azE@X-$cXX?uQwq}yYykCgXGuY80k`wP@wJvl zPYvzdW&nx8X2XGcxYOpiFpK~kCVG2SlzVIb%OUSGx(qQm@eyIk{A}Z5+4R&0T1?x) zZX}=d{~}Idk@r*C=a5rU@JH1@qMX>=d+IOgnFE7ydm^fi$S{bnnB01JFD%OyquR&Z z`2s46O2AEs0i`=Y7b*&%i)LqaTfFqVX2}gP*D9UP?0)>DxAsdv)wJNZwj+csa^9aN zjQSfFUowZ}RaBV$dfKYU@+#pivd61vJW@I!6Mti|6}|QsZbR|EsB;OkQ|S)&y7L1q zr&96m+t!c^8;IC)qhs5SXiL#n$R9}8F>II?Y^%Ba%u%*Pd=JF9BvAcPf-&<5y1+-a zri}N`LN8mFqPAAa4^u4V;l3u@qjMBkZR-F>4?PIO|+ z1OEu@qs$LNsIdU<&S_*)U*Lc1RO2(VJ5s>RS+|5AbZvuHfH6S&_(6Rz$7JX_o3MH? zPA4ManS9ly=2QYO^(FdzGWi)mVHYkfLb@ykW$H~oT>lNM!C*w&e$tb@o1sBZuS$TN zWU&8AE8v1chu>A3cNp?n8(DJgHK&JdP-`DJ&*qOQzrRSk-D3ZSpv1E~p6+*c*ZfOQ zagJQsbv@h#-+d-&AiSr%HxU$lzZ;6f!N)F)q-`DcwULdnH>~g17Rst@Y<(j!@lR3qEfXTr{@lCOL{U-Rpo?lbZ${rU1t^08zJ6TnlQEwiRjncf{>4(3X zZ#Qx661-v@XZ84e(9ra!P!?%5ft_iZ?1TU6vlIvMwuy66%=lH8y1$`TckpS8S`PuP z%naF9W*;UB!DW;XdUc5Q%E{FQU#oAWxOHJ;i^0+@9aVqXe^r94n|6Q^p#qJM}Q5-MslV?X;kG(v$<-#DFouTd36# zs-#fA$?z?eMY`RuF1NFjq7J|?}$U4Oyu<*VSPNm zzDM^5#UUJ&cf^Rs;YY+Dw808KR&?x($sDw-t?b0a0;6~cSdD7P(1RE;Vloat9pU?-2v$IsC|^)(i@(UFhl75(WWPnC80e$n2@ z_xR+lM00Ov=?lTdWF-(;(Wv_6Gnh!Oy%etSByW)DZ;MePSxZ4Xz|7aWB(KRm8E*eP z>)PzfAx{&E8I6gaHvr|f7lgq+q_d& zOGOj5?w#b{#PZ{0JerCWjgy1utxLC)PEeG`uO#(te|dosVD;PzzJgBb!nHc}@kk=V|%7kjn|zi1G3iG7rma4%tz z@q&Z8x(8@qe``Nex}~&ADPYEkp2UCgrTH)9*5)xU11li_8Xv8Yib-$LL!e)&-bt$q z95W7XMtr=E`Bu)awFh zi`(`y3=Ubiges)?slH>nPvAJ1o_1OGaT(t*QMCK+H6j@kcSB_J&E4O$l6Lful3AqH zeN+BHYI!ycg!P4w;jhlMW7wsS$ASI1whviKs7WW_6z?Ac=da-;f1K?G)=|KR>WkYn z4#tTUMI=BatU>d!+J$S7MlJISM0}qebXRHxj;RYOH{1O`ey! zWl}WpCW}Emde`qbwo~s!3)p`Jk90S#_EJ!{)QjfxYXar>@F}?Cc0M?@41^GA+*R!? z!hfnM-7x3pm@j`dav{mL>;ATJ09XhT+Qlsb?|+yg>>I7mzRN;Cf*u z`7p<)0(aVN_28dBGBMbnY1NW1e@SgBd6xD3;|8E*=RcfipbQAR&|^m2Nyeog&6-b- zz4^>{Z_B>&werS_lNn3nP$xs7bvkjYVQ$^%V$WrS({h@ z;d?lxB#qZ4^HqtPuM7w}ORP5@aU9+1YPg5@vcx;p3^{$S;->}S)bqto-JfdlOsE@o znL>2eOZVU9J^vI*Mm`+xeTzv3PxH|3i}~eo9BnSMsPxSbZ8D&}a^E-jyIZ`uPL{=^ zqSgs3k-HV+QdPNO6rb8epQdEv<~+idUnCJdgY+uuZ2kf^M8vC`#io*J0$r@EZi4r^ zj|ZT8R5H@fddYVRGaU?{3;Z*729VdY>#8MJag2ehdUYI_io#qp2cb$K49VADHj2LD zF#XUKbPGm6ACv}=()DHQSxxnAM}0kM3IZUu}~`-45eapBxJ1dyLI zaB;U-Yj_~>k!VqfK@adv@#H~<52Q-!tUW;`%7Ih<%p>)xuJPU@MypnJM-#glXDrn( zeH^!E;%yRz9O?l>-+b%&q5XSGSh5dEBCb+pE~SkPD3@h=Kiu* zyH#(8YN(86Z?o@acB$fSnY9qX^_tKbT45;#G;5uomZaJrf*ZOpMf<3LqZIX0p5NDC zKo1ilP!4&)wIlWdgoIk)L~<=XmCYQu)(SA|-r=o(`D+8nx#_v(i#P^wS6V{#_&KM3d$ zcv1TdR3|xg$DqUs-uLllGzbgLjV;zvCH7$wT~MC(q-$WB*fxh1rH+w=7G2)6?5 z^w@wwTDOeB57Ss}eB#8q$?y{K>zZrupk#u*Aszq6h?U?jUNA1$y1#(sD){&3al>4D zR1kQ0P}77|0qEYbW#Ioxc15+_<8u(eiyw6Qj4>!FLdz56yI3-3A+xcV$bIYfsnCAZr$@BYD$t+eDXfdp&AF-xG#~x17zzG(hDP< zAbj^dpxXc8!7ax&KTC(J?mB`y35tZ8K^wVp6TB1FAPz@*$umP0MCXR-aO&ViPsXqP z<>k1Et^4DLN`Jbv^~SSk zF+_wC9E^v9f-(WbXzBKY-NdQ?lGRzi<9=fW?WeoN&5=eaQ?cI?*>EUeVak)RvAhEB zX9&1>SgRrvcwP6wb?rmj17VV5zPLW(dX6T8l#gbD^PtrbK(}JY<@#&83 zt&6c<1<4umB^Daak|Nm|#?fSNr{}rH$@@v)3XS z!(4X>^9zt@jrrJvli!U z`+zaab;59%yT1t6wMW4%!gt%PS%W|2EV^h#nO~udl*ak>&<*0_Kmai5=>bu2N72)> zB?`iJV(drY*?(b6UOQ-cf%ADy-_B>mSb>`ef0on1PbO9jVCVeG&DR2u!Ef5EPgsG; z1z4paOf|Gn6hQk{AtiXfQ~&fB^BK&4;*l8s9w zDHF{8;|w*R1|J*wY9>R^+N;4c&-^$)Y4b0Gc`5W}w2Xk%_6=mANO(JK#cez<9k4)5 zd25D`<1X<@AMwA&UjgH1*iLl(>`t})YJ6pT_54~aX_D{Spb+9q2sJN&?5ajd2m^)@ z{_=5v$tA#OXqz3&mKiM47+)F3{V{c=rNhSI7>)b^Y6SuU^@`k|TGeQ!x&a=jiAG#3 zhvH?2w}>SJ-k3+gF=sPx2+i{2g|x5_3zA>P))2knxyVf2rC8{+Omzs;aO<;+jQ#re z8^yu=76vdI#u8c5{-RH(9)E-7)7{3d|Ejq9wa*ui3vbIh4k#=o=b_|#EI#PUJz!cAZH_nKf)Hr(Z?{|v>IX?4$1P%+|(cNjMI$0ksSL? ztqZS)6KK3<1(t&~r68`2(F zq4iFy9nysJ99|lGiI)z3=SMq$mv*qrU4bKtpSoZoQMEI6?L+2g6xe>wll>1gq+H@^ zhyH{B(a-H|H`wYOMCXVtj+bCtBrK|_ga+IU$mUpKl;GGfL1U2Y!o zyf!vSHfbLtXgnD6>8lPmZfD^g6z-meTj2GXuT&v3oe_7`J%kyaroqJedc2#6?*XIK zhS6stO}z(`B6g=1GlZ*xzrsoWosu~iHZE%uE)){FsxnXE&a{i}dtn)8*qjxaqWgek zbw0f!+P&~pF?f;UYvjzbAf#a{-uH&=Iu`Mnh5F!@JSeloo$!=@halkxsiMM$$L##I zURf3AbH_*i$Uwn=YuE4Wl(*=qs+q+QPno!R9}JEEp!e2>q{g6jzZpcd$x9J+1DhEd z4|XS#x0>ows=jcWJjEGYXOFg(9yeJbO8>3>-Y48MLH`t8qcpGlOk@n9P{6cX(-6~J z>RXlQ>oV)=!+#XKw!N-Gr5X3jc8bifm8+|NFj+!~*SCUt>ZfO@I{1n!QlrYV)la|) ziRY)2b0Jiut#k#31LX$xTLT(LT#JEOBu?q{=?TBk52v7g81ZT&N!Bv4&X+h2N?M|Y zjeD_e5&l16=03IcJBxFNRx#%}BTt$*Rht@k42y%;3BIKv6%}^$NLj zQ$}Y~*7-=UU5Oe_JDU_`P;FNDM>O!7luRHeRHu~ZIEGh_7wlO#hFQe#d&F(v`ZA%{ zAin_yva~FlNd~-Eip}CSg=)mq7OvrEbj1?MY7PV3*GX!N!!-J*gybQ=?O6?%WxRIG z3Hel+(w{6K(VUzcEZFJ`y4;+63W`c4acS#?+W!ej^OIdRh%?u`W* z6gYW0({OdAZBUngZtDH_R{kkB1HNW2-rcaguE&?LWyeQ7Q({p%Al*in^N0-mPwd%_ z#^n9~OT(37*>v$uQJxFR&xx2(k;R^2&MAS+t@eBj5kWD&zrXR8j4=9t+RT6%dDl){ zS5TfC__Srbiol03e)15BaY5|p284aWm{<~Y$i|f;bc+dF8cw6ZQ2C?Z^@PU=-ZEV# zl#vQ`mgFvMabrlomo?fV+bU)Iu>E)KxK9n$Ev~Ljk+8h_EYpA*!Eag4{R9c9^-Qqg zw_)zt-E2x`l1U%y&wl?i1YGx7EaHBlUvxRF30xH-)CUPo=PdpyhOnxPXrB(^%Y3Q(4AEL(jEq$xnB5RfbiWu z=$I7bIv}&s2I)5m@g@0e2qiWyHLwlX3e!Ay4w05|;uTwqhboE$w%j#e_P6M-<3FAa zUof;mBqNz#bbACaB_z(XNaKO*IK1mgFL>(S=6D8qgHz?add$<;4l<~0sr12POMTe#w@t&2l_rlKCYKTEgHIW?wL$SzEl>Wx2< zw;gV9dg1dqFb=0!az9!(7f`VYQQX}e^To3e^4a=ViSEc;utFbb`mJJNhe^DCz9qTY zE5Uc4OOPqVurIH5%owGps$g8UKH^xpqLuWqxrG7qxY|61G5_M+Yqa26{0QX9L42FC zAY~(L@ZU?{CHOTcpc)q;8YnYDhe25t#+Cxh&3&hSbds%Y(B#aVJm$N1jpw(!+E|?v z;-7BI`4!$6fT3-#(TkUh+LO&ssUB`a6ayd{@wCo?TVLjHYboQ2cs0z4IaT=0Z!_%qTnJ3w zAXRWs{eEX|d?t9pzXdD#t*s4AS>+R7xKt+@ZZslsEMJc5C^kM3mo?8>-qtXae65ix z%cmu#IqS|c|D%C6D$oZKDBl=EJAR0Zv8i9A1!CZ=d$c^n8lez#vSZKF@4SbS$W)=A zAZVF#EMbmpsk*URkW4q0_j&?4y;Wh}(_^O;_9kSoSboMDo1?XkGX-%c$NQb^#uW#&=zoEwW(0X1&()mq330U z0B-DNZFLn&x%-!jG=3uMYp`&+=q1X5ase6B(pB?Nw-NJuHaLN@<1&|mV-v>w8;{*_7#M&&1|(Lx>8+BeUGXMxXQZ)=nh#L>Senb9Y?q&ja|0GPms22FUJeok)X(_=U${CJC-Fw! z&E<*@p6g!3S;7big+_;7qwU6Kip{ex9xN$)>{Ui)7n-yF^wVL+uyj1SQ{4g~=v%R} zg)GS%<{F4XHkX@rP+Z4CxVxypEEKzkwma9+iA+q65#XO2r*BTCr55rYL%(b5ed0rA z@Kfv?G|JRfB+t8yo~q~0JHNjB)~5j)$lCAJwn#W?pD}}}0y&cENL~-_BK`qsX-cez z$4y!QfQW}Pkc_9kfjhoru3<+GzVsAY&zfq4f#>XccE)Yl*rV*`RdlmZ97*lK8`au% zi}q&5KINEHj%LQNu1la%4*^1Xk9jzD#>FfI29!T;KZ;Fn8$;>i?655!^Y52?wNnrB zDB3d6f{QHs#3rvsU$C_f>G4wz`gBk{Kkr=!V}tX@xXtdK(45A-@q$e_6XKqBXoZD@ zl3Dzal|D3O#7y{K!is%qw+9$$g^bF8K^VU$Rkuu{-%OXQ1YAmaZ2kF;36>9LV&5%9 zU(Zb}xaL{yjY#R`4VHaxe$4j^TVoKtm()$*@KO?7l;tlIyOL=hFznb8hWc3DN5T-s zKhl~v;mBa(`p}TIn^*d4;#)#e8MB>M=Y1${*eY?NFLX)7TLZr`fxeygv8_{<)U_um?x9S2z0f9tzRV*@tP6$u;k zPh-Gxpur#{V;oM?A0K^8{I&aX2S2K245WZIu8CDj#s&LnqniF?(4!-Cm~70|Ual=H zTT_;9N%tTFckb5uCtXew(-?lPRY!5|&ypQ9g9(?Ny# zjnjXBkFSVb{b0Igo9I`+kLVsmMpL5>=jk zsfDC4noJxm_Y~QBbzA4mYSH|523tDdpg4q%wlHCB?Vgn>=YqT-pe6~!%oexA>TP8Y zy~V`}w2HDM zPz(Tv@_S`Nv3U&08x;+0Iv@G}HQR-ffM=o34`t1CnLOf#W6JBU2~-RXIEinoz(T~h z%w2CGS_$U_^_`!Q>^PK)4j&&mJnptiHIGz_l$&f35sHGLa$v%=OGAB1?dgRzf5Be2 zRR4VQRWnBGAFfHkSxTy7V_-I7Nu0|}AbufF2MFdR7tDr3d>77`{$@ivYaSm_t;K$_ zYgwjfg#w)<(Yb+=8HtBneQ5QW%&s)j(oz4sR=5{N!6fQ?6@?i4QV(JtZHrV>DbuO3 z9*(^c&UcBOabdJTE_y9y_SX|lC=M^3)qtD9!(!eDn%WG19+1H3VLjEwW4TQ*AMd^+ zcV(`;lkADzwiCk}>t_~+f}nhs{iCGYM`7e(1bCqx>KsJqc7qsQ+#f{_$4RbM20(_$ zG-w;Qh4&4{rxI^%$3AcUq;s07!`RV>vGd7HBeNKkMuxkkqNFAS;espVj9usk)E?m8 zc#d>rtL!PnhCRr+xL(dIuD5w_$3iN<{qsn=kDAiIL}%}WQK?QwCTc5sPi>Q zh(s||n>}Lkpd3+iMc0g8KLvMyb(7qx2T=D?nZ#Zd<(PqJkD~L6g8JO;7j?Cc(@)N2)T&P$tY%kyxT$z|J2sN zS(7yF($VVNHl|S?1&v~gyVz{_;f3L~>S@Q8HV9(lAefiJB~h7_u}J;S;=jrd>voC2 zvrr1vMLMT*!R-rsX=G-lYW}OWd5`?08zj5XLCl*9j^7wDPV!i3IKeCa=kYvgF@I=H z(>E7xr_(b}2w=OnE&}OcuwmI7R6C8xNTOOVW!5|zlPqa}|JpGMsF8$QJnVZnohk{L zBkHhnfB&geb+ebVCQT}d*HtpJR^kDmZTh(~CNpiJ=H?E8SquI5O{q#jiZ{OWBu@;r?WCZTB1} zPlXv=1HyZg&~ZK_7L1N0S?Z1LMU+@fL4l47CXTL*p*u1G*IZ#ecoXK8Da$cJW!sx6 zvN5*#85P*Ov8);XVwjX+X225|(eY3wuoLWj*X_B1v*y#`LiLu{QFubfi0cQ64r6TNVjjMzQ@nu zs0+2alkbNH);k}ai>HR5O>NUQ~GawR^3Y@PDh1ccjJF!3Kb>L6pMg|xhS1ZZ06V~${m(5S?!poci8X9i+Jj@c`;9<=B%)@C+q+kMg6a%;vUDse)vH&DrvW(7CT;H1=jb2G z?dLxBB8z83^y!&p+^t6?6N^Ijv50*mqQT5bH%o}|8=o$&)QfH_zNq{*;OXX0lja-` z@5NsKJ{UB9;mu$>u5#9>JL3vU-19LXr}3O|U?lRoU^J!4f_If%$SwGJ)KHB|z>+n} z6K8&|1~ixZ43a#*miP|u?+wIa5&Sljr#jVT|1*%8^8xG{Mz=ZKk}-e3E+e`Rqv`9_ zt6!*&vE%Sb;$At`_?nF`e#+IbcXz612Ou5ypr~70d2XXA)LAp7v3US`> z=HD6kF~QyB6pg@r*Jiyn{^YxVg^E9=T&;Yxi?mnpG8HIEw3e9}xz6I8MUQ$d4B95V z?H&GX9$X$=`josOkaR2Np)4~{BdNVsw&(F32{?v;^4*7a-H9XvTG>}qYY6Ca^~`hj ziZT$mB{%1US$u)?9saq9=f0yCD&w9$RMVB<{)7C2_ z+J89OJmk1Y2&&ducljHP&i4u1wp-6hU1*1|cFH%gvP;^v-<4ENqt*nB=5|yTVB1d- zlq@Dlj|uxO%ROjyScg>e(#4}Ho+Z2IxMU?-QgWV#zub%^Z_rhoInbxECW@d(o6 z{&q>?msxjDa@|dogv-D5H}2VM-Lm&fO-b7vD)}}jC)ar49gs+XV*5;jCHC%wfDbrm zLG1wp2nT!?(q-9QNXT5LW9dKake{m=0l7Sul8dWAFDh&gfqqa)YCF5bV*L1GI?1NPdLhMR0T zW5=%-S#%UVAy3)_6y5OimhIu5lI*k%u0gcrs{RZzQ(1I-{kB5zf2Wks6*s09)qhz+ zcWt~l;`fgm@gOQ0S)&v6kou;0U*gf8R7%d>6VWON7$(V0e&Tbqb%wT{Y}1U&b)9ww zWeKEO=4eBop1>TxvY5TgDmYUZFLBttX)=2?d2oDaa}E~{!uRje zq3Ay{z3g{4sM`Mh(G8+oq$2!vt8-&k ztimT(gZhUHA^(CZl}`(W4?ejYRGZKTb}E1z!#8+`=RV_PZiugz#)?dX_B^35!*xb6M`?7!S%E?bZ*~!sfOAqh8 z%>PH|YKF02qCY?PLt_Qoe+%t-esyi?dsDlNolIyD6)8e|plIbKTA?dXw@?26fybhJ z0qP^!5L}1^C>~Lb_cq}LOpBH!bvM5TKn2zj)5}k^lMoI;(cyikMUAWfHe~aPmC$Vw z|FeJrhr$VQTv`pO``F94bE`UYF!v3$7()n{0B&+9+*^JCGm?IrrK!LDFHw4%|K0~( z{Ngp8L%-e*fMKw2fh6A_GRb~F$6XVT`y7?CK$@d2Pmko?6vne$wH87lc+8g63~o@3 z*#1Dha|FjAJs9Ox)?D75Q|rZS`=L+K0LdA4DTm8-ONIQ@S(H?RD=vXo5d32Vs9TSZ z@F8>gujZk|7(b_NG(Y25^d~;ijU&=@CRstZZsq&Q z4L-eNu{PoV-sr-@`Qnd`h#}$EJIZfc4(?nAd!3jyy7mku?jm|=a#4L;7aLCPeQ3EGl@i#F`7`nkPbcm7B9M3|(ydvZb`(SsA3myicz zM7I@Gcn68d96EFNWdnsu*Jgxn9)kkn7mE>sWsTKX#EV9I8 zSTNAgiD=GM(9?h8^eeAPq z-KC8sx>ak^>&yQ>J`PY(o@$ZXdHmIJL)@dsVHWL>?X&%D*E76YM5v!yWe97O#dyqJ znHIfMORpKly8(PacC(m|mUs${eT(8VM#Nve{(JI$;uSwU6Q6UmjdR9Fn>N6Z8obe0 z!<47;1^ong4x&L*()hh<{VnPjUvdrqKM~5he(5ETG3K^iEV{RU#s)`46;AQ*@7p^K zEpnlK9(yoM2rZfnWbGaGBbJzk<`tV)Wi6i7i=R%|hZH#StgRXp z*vcfc2am5MHqvPvDR-CG9Nd+V-uGi7d3`tsViFv4G`7*V6E5xdxQ&&2T0>?S765f& zKymwGucg|KB9fAXBdeB})fZ{t*V!MB3U@9wf$0Irlh<)i7Q&4arE5jXKSTHYuOKu^ zy7Su%OpVn>LFnag|2Bnc$kxjaSgP*krYukNSa-y+{Bwmb2zf+9sp;5Gcf~&~ui`R= zOI1WS7!xfeY#UWRA`)}lNWmst;cDr=TWo+x%+Dk1l2U?}7~+4x$i7pbdY=Wiou1N( zp$#2#suy8`s>5pCTRSdYP#T6Dq$ z*!H`NrGw_V0Z|h3VXHO<2t8p(Vt)e-QqA_gD*_{ua{jq-^=nur>*-gk?Nrr%KzBrh zb66x+i}*+`u-mCO>+8Z*4j}(w{C73^b+Q94+D*TUwZG$;NJFQKMT8NsCj@{f!6o$W0oS7eKGTj$V-D{2ZF-``c`a>XgE?5%HG3 zt-=xZ;bjZUvsy|^sZmCqJn>WMXK|j&@u;Rl;!Z4QWnSg1?qh~|mp;h@b6t5M3co#( zGoh_f4|kQv1;lr2ZoQ5dA6modMc3&$r(6St9WZ&5{t1L7sb+%8S5J78a6`aRt?pau*|aj=tC%&<F68KOY#KtDANU3wQDuU435ML`>N zG}#Ad5leBrlh!xyHwC+%+J7=y&Gc7NC#JCdAfS<6dA_4_SNgFw+YXgozeWO5^a2!b zqr*|Ww_1a=gJla+Ch$tQHW6ya*GvgVAuq4*=@{dJH;lJE%jC3jE1W9fW@{WY83A-oPGI{u(cVjbfCD zi}T#$kCwsru9MbV3Agq8znI+M3FW04cE~q?%kKE?*N=)IA(WSR`naFZJ!{~ddnJrD zqDe9=Q?1<_(7m5tDA*)LK|DGiN99zIBu7{+RoJAst2gKF{}TIN`;zk2*T2oC)xj_1 z4G0~jhMqEEj6QDbox@jZayn%c+mHsLlo^s~Zc05e>t0#Vrr0n3noWt+6C)RbZ`VfT zTNFSaD612p(ZVqei)$qv-nODXOl0=sN zc;}&*^CTB4HORIynu5jf{5mZeQ4~dmM)#M$RW3A?J=(3^=J{vwnxi}?d z(!>%B(Tw!kYp2EmdQNOz2$82Utz2&oGO8iyXQeD6Jljk#94&WpT&kcwB3|sEb|U`y z331-gR_jUXuRiC5FTEEFyULDZK{FWb8~dvs24}BKcHB$+1K2UN6~%dCd-iQ5o#IR_ zG3OH7M=DDqrgz&E#4h|ojh}yd?HM#VnX*913^#An6RSdcy8Qc3yw92yp2o=t1)0Gk zwf+3!)tfvsSMDLk8xGwgC*po!i|!B}>Zx&`h7+!xL?S(h^OjfC@Z(e5n}eLoXWOMA zd60NabQ^AuEj6Vr)WV5KUWBXRo!w{)^g;Keh#YU@p{;;W3C8yNcEKdxcyy$gGC5)=k#-Pq(WE7BU=Y zAvmL+=GdOC_F_KFeM8gFMv-&%N80d%1lA?|hu8Bq`==Q9o|~U>LpQ|G&?Q`~+`eAs zn!0`6GbbG3>E#+2#=}*w9$9)5#rc9_b0i$cRn;Qapi(=^Lq86hu9S}#3(7GfoV#n| z!824tvz))ouw97I$yKuhM~60$vC+)h!lp|v)vxdyQlfrtj)cG^YEEp99kG#rh^o z`yCpC4c9JRt(R)GAW^;=04E-nUc)$xb;Afw#-+?bJeOv%cc3J)8f54k7sA8Ja2Zqft!$w7jwKzhi5bImFzdh^G!s{B$KY zLJsRV9{;zh?L?;S5F&) zr>~utG!j2gAg5DB)G(rzph+@?m4DAnsSJP#vXb1P=ar!G|1=?X%B|@P960!&3iCbI zNaggnf=`5X)>QWa^GfA{V&yXruh88Zc)S_>VQAtaN2Eth$Njuvv%P+2jm_5|@y-Mj zeAA7tF~b{X{`|^j$0?viJG^1#&ODQa4DMIQxowTwYiG7^f&s!bNs;Y*#J809DgXX1 z0H_;HCQ=0Q7SzOQ%62PO?%(DG$h{-DuK&PR++z>S#NrVW6MExyW}miGt_>bYZj;uo zLMb|z&JquT3?ZO_n^y`v&fPVvb{&zTiQWS+v>yl^|S>H1*gv6a=?>hUb1nRFg~Ey zBntev(JUB`qC1k+&iMrD8+#u7H$yB|4HJTNZU%FQ;6J~hfc3m2(QUvm+lZmuONjfi z=k($gYbXxj(3Cj5Vp-D<(5ol?>!HF;#X@=3{;aA{lmYGgVV4#QAm;P`5tIDWkdF1V z`-ppoMWH~mQMA5W0_*tjuV zK}@n6BOCrqd-5KoJLBQ~|2Spj=5K7HFd6%4o>Q`*-JJ!WGuYaRKx1Rv@JRxRhSaJ(rnHR@4?qa<84>QI>V_MAr zC(O5FrY=sdm(0EPBRRCx6HOC8yAV>F-DX_$2P5I9dfwGE3bAylX5N!5%RMwlMCB!k zXQr<9Xwi#rn5<>p0H1x#QewBvFlKO#pn_@92HnGY@WCXCJjAV@=D$s!euRG&%fwt! z*g_pcF5)0!$zNlf?~)^jm&H%!krP0Fn9z>1)@_kANR&oXa(C=f0LB6mX8-dge$HIDKTU5k~XYToMhJ$J$MVr5EzIJNu~`Hu@XqXMNZb zW1R!TxFOxWx%)@Rlr!@`Hk6!Qx;GiIl16s$r#g8r{^M~t$H~uP$uE}ak8CP%-g@4| zdXOZ#eWYB8DhYnnvk*4~R^1Z}6z`9`NNinn`&G9-!~D%5rh~vz($sLd0LOm@NWizZ z#&aC~&W%4X$d3C4{@Dd*8UEBP#Wlb8*L zrB@?(`4ELW8+q1H5I<&Ow%myK+AFZ6#E9MuIU?$7=0U5gy7HK0w^sLL2J6C)!8+dM zhCRg~+c)zC+KapU_DUtm|6iKEzM=jpgU$n~anTcv2M>s6Gi@Zmz#50fnBAv#soA8i zyYc^mT^2c1&BkM{kLYYQh-mD@Z<*oO-eq3ToQ&B%SWCHB3R zp*Csz^Nrm~6ioa-j33%7?Yte@3$J7Nn>pBySb?w@VF&;hWfY{pv{Pyl9d-;$?5U>V z_u=VpdOd9$uI-@ZfY)aoXxJW82h>*%rmO z6z?E068Mw%!9nRqH_r+FiBLrc$%P)ECEXDT26xMPQWS+m#2DqP6efqMu8vi4G|=ZZDN?obk$p_8`vtBz?2Np1Spbc@k2&GCyXigG*^_k=M zKX+IN!g9Bs_99+ez)QR0k_HMqNv6-Q?7@=vo5crNB8D9CMPn^bsOfUr6NT`CNmDM20?-xik_;>jk-3tj;O9F%yFWAIQtS09@x zN}f+8bem*dCO>hsCKP4c6N=fC>=O;9CJz#JV$t`(2iB*>(FSbl0R8$63l=YMKa`o*m=ws5eCnPAQx>}c1;S+$5V5(^&+FljvU zT|~{9)({jv_ns|;GQ76)I4z_pS?wSJgU;V(QD_o10@T$hgHOmv_&4yESTP<}RpP8O zl2b#yrB>y7gg;3!G&>0Rs(%~$a2PFramBO^6zj9Zv5b{4HLzpa&V+D81Fi>Y>bm#w z8QJWu7*x88MZ}CGtEkvXV*#d^)OT+SauQu2|3{)kQ_9va6?5c+-Ur!? zVZL;YLWt~H3u-a4#2qiRh}vDt+S_2443Oxy1gH)Io^&W8Jlz4WKKm!aazrEilzk`~5N0iJ`&|=q6VEDBU zV$2H#TAQ}x_NLH+8$LKoka%i%i0q>AHSEnQR6|YfaS}@6$EA5~*2N{c6iRAov_JBq zJ#vB8uLr5DDv!j;*5APSL)Ziul;u1PG+%$@T|%v9DOuQd+jLlx+)0-egSncYItRHk zM5yH$o+Cnu0i3uf$GA5XuD9owMk{$1DX4&b*yc+2N2YXEpA0}- z0bhG&vdJb%-)Yl1$W0(prREb*G#Jh=VX{S%7qgY~F<1sKEMUzVeo-}1F4lj1`5WB} zsf||QUuFUCj%?02YWLEKti85zx)=RY&7_v6Y7jB>GN_G?1MvHJ_DUL=>4|M59e~&a zUQW(Q_SOO|N+FD3Q$nn&@2l2YUC;?8{u>2+BG%T+#0TbYZbUs?4m^_br^3dd6iyNg zgC%i$bq@lr;Tg7#oMnn>(=kvD!5`v}-n_OZd7uqhp@>?FVdRVoKC)ZJ1yzAyK~%tK zf9&Rwvk}Q)4Srat2@A`rgPk86E^H-%P;!up4dMFSJoy>!o@BTLrZLPJbNk?HyWU=- zgAyK&R03wzX3s&G%Usz5zZA4)gSTAjIfHPdbK9ypVPcLopc>*|0JBJRGd2XY61d0T zZ>h8&&2xfpB65awWWKv7RX77@p{sh=x!w%L@&nmr`D4(XmP!|bH~Mfv*P63B z8so-xm_PMk#Rf6zh@Mw%HJP8mn0U|k!`$2pnY7;V)Fr_6=Hw>4e4)-uwk>=Ijb`zh z#8dzMfCz$X_MGN3Yz7M?M1GMh!9$k4vN53R@xJ%~=s#9@NCfs+#A#lsh3*eT)k_#` zrguZpd9SF_-OS@=#8^L)W(2^@~l19Gz z`Xboh2H*ifhGblF0wtzR|U}1lTFV2+bbJc_|Gt5mymQW|p1z@F|Vz z=s49+5G-y*_w6m{i@S*frbKM-+$B+H)i5h%gjkrR1D+u~yW~s;6kEJe&?(+r>~?Be za-(s^Qx@(2LbwRG8x(aL%g@=0OopJ+K*s6!;?4M$L>3x|982}!S$YL>$Uv;qu&Fn< zb5ROnQQTS4$B)k_X7%4NrMsJj1ZgKmP)!da1X$E_-q{hUvtd8HXCsdUmQ1qdxNlUq z*3LLp&Xx{P?(Gu!Js~biDP#u;E|=>$o>7Ly(;RYX3xc3Ch8D@8BD$+q_A?Y+Gjd<} zn(StJ4EZKQ@W4}hLD)xeiXY=Lie|cq&cf&M+~4(*1*U(C`qWViQBaRb)L;Jvz5sb) zYAc)-DmD~#(glbJhFoz+e}3Z^E{TkMqbytETMOv#A;y#N&`4Y1G``FH$}!{{bb9qo z!MWgDGOXzXD_>EihC|05j=ofgHr{H_g6Mb(vPzAXN{qn)^{T)}CJiLB)+yCo{PtM? z2!!}QrO%q-Hoq$Y!y&P*D-buNA+Sh=}B~p5vB!X|yQ-PU`bcK!I_<*Hf_j z&TZQPYSNoB?xFC=&U+@mkO#*If za$VV+@KgOxXxKGEfIMyYnu6HUL=FFjo*T~lTRnj!6mTyoQ*;A%F=W>gHtxEY$w(w^ zhgWewGX(h2W*pot&SGg|_Fx1CIM0k1V8y;I^oSr9;&w=#)zx%*1F(iyU|H^Pxl)*?EkS z>dB(aH+Ur7lJhgi^0rVR63Eg@J`;!%B)+{HpkGDw_w5@RlGsM7e@ryGxvxs-k{9Dq zeV6}Gx0KZ2iuA3kpz(<=oSYO;&ww?qWdG}Uo%F^s%8GEq5v&jszs8aLK3LJ8C+rbA zxDI)Wz1P=pKeGK4Ve($=pbz{gmm>8=yu7BZiwMyK?~Abp4~40gxtK=Hd^cG5mXi?i z2zMgQel5bI<`tEJRAI9_6YEE7t;;bBM>I<+=TW3y093a7{2TNhv;gWrICF!meVxnA z%h1CSJV9U}M>~H0tj#lI_f=ZNA^7Ea(VMrYBo9XP$%Ux>_qTED3bWEgB2T-X8wVp0 zQ;bcHKmIl?W$-7tc(qA3z7o#6rN+(;#7y<_jT|i4a>vIB&(gT-kcm9B_?=Vzd{7 zkf1n4mywks$5=Zwf=_B;mvzPC`Paw)-@P39H-*{56!01^Lw(2D3eX+HTH zk_S+5lH#yNI;UTQO7+2XY%H>gTH_5r0OXG>Oh<2JCr;Y9f;4EN^ zC$KujsGukAt=f1i`=hvTX!tJ@iWHjMw%_;b>BtfMw)k*_7))iBC} z&@#R&ZES!;0fP{?$t4YGL@_6>{qm@RFfeyCG{{UR@+2f}gYUB-U$VAS zt;T!ILRpl5uALqb4U!gsY3y(e5&C%=qkn8*p^*~cunTaYQ@oKNBeVpOGw`gDBhL=x zu)_tdvVajf%+FY~Bc)lUR-ec{k{38f3Y%q#{LuGBH*g;jeCAsq*mkaKomc{+G{~m9XFU43q$XD zO?{?0B0{a}h)V?}{+-7wOdYpkFmGdU;qVODdRYHztlzG|T#%b-R04p<tdjZ7Bdb|^&pAlk zZX+YMI&aryOUyT2hb+>qL8kygMQTbs{g78j3RXOj4={`kR26GS8F*zNpqW!4nyurP$)of;iW8e!` z-$dh#xM4mK1}s0ETet6;F7EZXk<_y;;J%Y}VuvFfCV?b3&;?a_QPvw+UX}``3!E&) zF~~Syj3u~FW&fWxH2)oe^NenMSYMW;g7kVzLAdcjkR96=8$2S3_xzvxD>gLJ2~#Ef zX239ac@asZMnTRF%8ontELjHZT2jIE{LYI;H#;cF2P+5WAAPF3LJZIFsePz3a6)RW z(ZYL-JN6+|Atn`wZiKi+)-eQCS)F>njG7}TqC@gyh&UJ%l)n<8W`901I|8Syi^0zw z!{Iw6Q0|#9ai8zt_KNYrT`L6{JeS!HNgTEFv-JI-z5sOhE)rNl)-=}lDWa&h9)lz> z8$zdow!y$O*f9j(1TxJ>5_dbJf{|&~bMe+eeoMHpDs~3!rLEP5qgn&K#V5C>{%A5Z zYolbKz`t#j^NA1)54G)mfYY~cB{+G$dJB%lh^O`jOrjc$bz`aHf*FXsC;NlxV)hhtIdhHRv+1sg>;5R8-hmGzyk<$kbMi;ooCT9 z*NL=Qe7@Nb?zGjF@%%SZI6q)77Cg~+IzXq6=yh8D) zSyPiH)&R*yq;0e7kH0ZxVica6)YHwezYTS=zY9uh>7@_vO_y?R{AQi-u{^myNfk>}pfOQg9Y%2lpIIWwr;6J)C!a3ZH>^Cg#B z(wi6o6w$BllF1TGT1Vk{qlwV42v&~&r;qX0dxh!o53LJ}7u=! z-b_Z1v@_jUU$vhWy%f?@db^!ums(tLw7u(_&bs>Pvv__DKY7)XgbFVo|MVuwRM+DD z?iJa+=Nb|eLjBto(Zzo3LC*QJzrXVOD`&8#T3=1#HPh~*$x%P^#4-PKRDpc`niy8D zXRBa%J#fh+&zI+s_32}|=m4!G-gjTlFC|S58}%1@fA?trT|*(H`LW@n@uY0)({fc-3?~dM?vG(mNI4oDrv6L-IuSbIz-##dEoL%9H}uj^D{-e~}ACdD^YK ziCZfgNxY8xIoDKAxa5B(S$J71BHy}ibcK>qs6W|kM?odPA$BKB$lT%GJjuJr5Tz^& zgCt(H9$lVeG9`{~PKAqef^5=vUfP5cr!GfNW_$g)#pLt-_S@35h&zsMWcR5|Be~U* z%6LA%j=bM3cjoRhU#BaDF$f{-Od_?p(l~7E3zM^R)um}wDDW;cqyX9U)4FdyNEmv& z{i8|J`~`<~6GG!VU)xEjQgX*rpMxbnkT6+*>jZA@RZ z2@rw~Z~ta1=GX0Ywy(3hBNWw!EwkIT8_Ka+Gmd@k<{cZ)`LM!_#pIp8y?8)+eCUZB z-oM3qT&GlgX4=oWOIa%7yvkyl=9BN2{?gLQnL21SXW>c}gA}m?F;9akEaZD29d}Xj z`5xDoKjiAmBL+!2C^c^;oALk=aX{c@TA zkL$tQvx}J>v&K`))!Oq9y$`i?n+=j^>6I=V>I2i&I8W6Qe6mei&E;RH|5$$D^*3_M z23>%;KDSQo|7(y5L|fWDBD( zZEn(|dB;(Kk)Tgn;VhygXQML&Q|EtTR0B)%(#6A5o5~3`2BUYW@7%JXZ|KU#%7a;> zxdcl{)sD0*lk1TpnecVHn^=lGNvFIr%VOU#ylv_i@2)EHATtD>tA5a}OM2@$pC5Wq z#(YewwK;#+2W8sh+V`7bt5=%bq}ng5{22*6Vq}cS8?Tv%_HobTTYIVRWjJ1bTZ(hO zLdhHA?DryQ`dV#Ws#GslXSY!bBibFpmAhg-4lh&)yJxF=7eZo2C`3k#`i1YH6qpIF`=;acB+>Tx z_Y}LTn!;pzA4*@3k|r;|z-%we(8`E$-wK|NDeez3?ubm3Jy@it^>^yQ`nU-8Yf_6U zF0lHAtnj4U=(a|*KM~Gf-iH-mS6#*54m>~}XFZl7`EvG=Yq{LbFZ1Puh(Qz@xMv(8 zRg85#Sy)i8@XGUnCPBHcUokwb|LP{gM~k!ta&1{E4L}CVKn% zw*$DNzmVtz_9CwyPd-KOQgCi@=9jT_dCd%H_DV<`H3y4TU{0K_*J6M~vL(OPQU~a& z+Al@z;A+pLKXHt5BGXk+72<$0{X27^HmXgTxlqDjTS=ztklcB?P7@L3yVUQ_et3NS zj*W&y!}O5ms(TFu#;2y%_piv-GuFVD@E>JmOH*55!Fj)OLJrIHne4FCX7BsJjSVqu z%KG5AVy~$tegEfyN&Lt2$`r_BmwGPW@5-gCm;dzsjz95*O5>oJ@@F9{qYPVKnJ?HZ zdhSS^3XmncMu1Y}fCUVw&}5u`G;64FirUS%qsKquf}*Syx*%L)Lww;ygA<`};k%`# zYe_cvxqmK$y;ozlV8}R`y0ldO<6t?(Z5r#=J8S$7v0ChPwZ--Kuk1LwQGK{iE(%0@ zqalT)Yf;%;#&JT8=ucQfnJ zDn@uA?UkhYm~3r{6f5TYY_*62OG4q|V*Bm&F5WT9n{zt2T}G>gDrpGyJxp=pNL!un zOP0BXO$u50r8Zw6UpuDX(o%K)igE_g)jeN?$_D0mI@})~YIr!?%WH0M82U|67+9m( zpYte)G*_(?rwOUuac1~p`Bgy>C;4hBtQIfFC@j{T7aOu8r2QQxXZf0cm(7RR^io#t z1SqsjDP=!A1+*6A9J~DBrPt!5;&hkB;H6&ST`6;ZZfyK@T25B``VV~?l#G+ioH^uNRqaouR;JR4x7az(StMUTdh^-td;rls)6b(Kh+@d6ZmFcOAB?2TFhJ z`np)68hC+dgz|Y*rRSaMtZ2?#x~tUpjZJriU?l~tT{I4TZ}%^o2x_{loI7+4?}3dn zMf&XC@pfg`{5%lALsmwh#wmrYIyu~c;R|0E+WHc`=EgVS=}o?+Ss7z4pth+6{~3+a z7m+;GIP0wTm(848D~E4xdd@p-M%FZd`3$oS!k9GF^5o?+{UeXJ>uAoh7{lh0rZpUS ztlw58acW|gHGhX+un>rmh(3pn*QD*gfexHdJ^WsY>IDNnOMipcdZuI;X4VW2iJj4HcgSJdYe z44LsnvkTH}uv@!XQfdx8-dePMK#;gA`Vij!-HIsVbh4$p8EOXQxV%_*NdWV9R;E78 z_tuNHs2k>PIkU1~c?Xpwrn3<_`O2dfrlfni4UyIwraa8``uO zV~`3}qEFoRNQ75=sx|YIo&T&mId0VN?(@^4ezW>Tlb1_0*aUL3xPuDbK0)n_rVj{7 zJgaz>Ga3XsMt&LZPo-Ua|2|guFGA>g@5iN=Tn{ij9V4%m6caaR5LtrzjWteVD_%Vy zX_xi0+W3%Vax&;#$jTmA$mQ&6-&gOFNRmh~MBN9wh^+DvU;oOR?pC>_zqOY|*(X<3ms%Rp9wUW~XNb%u zxiB%)O}}`d-qR{TWUWCPUaTXUckR@ewn@7b@$lwk+WnYP!v$+1gc#0Oj99+TR{bKY ze|V#WFz5TsX+)N)u7)bc8Vm04N-?Z0*1f-#^{ed+A$QLA^@&rW)F zXjVD6J?a@%#^jyc_V%aA{M_{q#c%(%_?~#btai!+D?3*k+ao*ARn-N~db&Aq!Q7=E z9rg7=)zOwWhqWb{vNvhIdy)I_{AK4kvuE!30t)aS4-tThr+|Jj!myK8h>1ncy3nu$*ENHK5rwZjO-MUv0N<-TW6{qk6!)r z4PcICIU-s}bk;s4C0*45@8vZ{6MPpVnUEfBk(0Wvu%b&}$Sg(`>FzLo|j*gbh) z4zpkXI=i#{>&G;I;r^*aW?km|W)k-4{o?G(+WQ}VvtNJ1^6^PkT>iRe z`${I+Dh4pS{Idk7)wx1}3v8!9i^w+Z7ujW5d-sNQ^J`G6RNC@x*kR?LCdc*GRF-SD z0Zmo;%X}$t!D^G!Z(mDWY+XJ7=V~*7_b+0l=0.17.0" + }, + { + "id": "java", + "version": ">=17" + }, + { + "id": "minecraft", + "version": "1.19.x" + }, + { + "id": "quilted_fabric_api", + "versions": ">=2.0.0-" + } + ] + }, + "mixin": [ + "terra.quilt.mixins.json", + "terra.common.mixins.json" + ], + "accessWidener": "terra.accesswidener" +} \ No newline at end of file diff --git a/platforms/quilt/src/main/resources/terra.quilt.mixins.json b/platforms/quilt/src/main/resources/terra.quilt.mixins.json new file mode 100644 index 000000000..ca92e0bf1 --- /dev/null +++ b/platforms/quilt/src/main/resources/terra.quilt.mixins.json @@ -0,0 +1,20 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.quilt.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "lifecycle.MinecraftServerMixin", + "lifecycle.NoiseConfigMixin", + "lifecycle.RegistryMixin" + ], + "client": [ + "lifecycle.client.MinecraftClientMixin" + ], + "server": [ + "lifecycle.server.ServerMainMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index a8a8b3644..7a1cdc8a0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -28,11 +28,14 @@ pluginManagement { maven("https://maven.fabricmc.net") { name = "Fabric Maven" } - maven ( "https://maven.architectury.dev/" ) { + maven("https://maven.architectury.dev/") { name = "Architectury Maven" } - maven ( "https://files.minecraftforge.net/maven/" ) { + maven("https://files.minecraftforge.net/maven/") { name = "Forge Maven" } + maven("https://maven.quiltmc.org/repository/release/") { + name = "Quilt" + } } } From 2edf3657817584e7f029b278eace818a9f9d46df Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 4 Jul 2022 21:13:30 -0700 Subject: [PATCH 197/220] create mixin-lifecycle project --- platforms/fabric/build.gradle.kts | 3 +++ platforms/mixin-common/README.md | 2 +- platforms/mixin-lifecycle/README.md | 3 +++ platforms/mixin-lifecycle/build.gradle.kts | 30 ++++++++++++++++++++++ platforms/quilt/build.gradle.kts | 11 +++++++- 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 platforms/mixin-lifecycle/README.md create mode 100644 platforms/mixin-lifecycle/build.gradle.kts diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 4d83590a2..220c15962 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -20,6 +20,9 @@ dependencies { "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionFabric")) { isTransitive = false } + "common"(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } + shaded(project(path = ":platforms:mixin-lifecycle", configuration = "transformProductionFabric")) { isTransitive = false } + minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") diff --git a/platforms/mixin-common/README.md b/platforms/mixin-common/README.md index f92b8b043..0c411a1bf 100644 --- a/platforms/mixin-common/README.md +++ b/platforms/mixin-common/README.md @@ -1,4 +1,4 @@ # mixin-common -This project contains mixins shared between Forge & Fabric, as +This project contains mixins shared between Forge, Fabric and Quilt, as well as glue code. \ No newline at end of file diff --git a/platforms/mixin-lifecycle/README.md b/platforms/mixin-lifecycle/README.md new file mode 100644 index 000000000..6c2c62cba --- /dev/null +++ b/platforms/mixin-lifecycle/README.md @@ -0,0 +1,3 @@ +# mixin-lifecycle + +This project contains lifecycle mixins shared between Fabric and Quilt. \ No newline at end of file diff --git a/platforms/mixin-lifecycle/build.gradle.kts b/platforms/mixin-lifecycle/build.gradle.kts new file mode 100644 index 000000000..aa3a38fdb --- /dev/null +++ b/platforms/mixin-lifecycle/build.gradle.kts @@ -0,0 +1,30 @@ +plugins { + id("dev.architectury.loom") version Versions.Mod.architecuryLoom + id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower +} + +loom { + accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) + + mixin { + defaultRefmapName.set("terra.lifecycle.refmap.json") + } +} + +dependencies { + shadedApi(project(":common:implementation:base")) + + modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") + + compileOnly(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + + minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") + mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") +} + +architectury { + common("fabric", "quilt") + minecraft = Versions.Mod.minecraft +} + diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index 5bfcf8099..365fec3bd 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -15,6 +15,9 @@ dependencies { "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionQuilt")) { isTransitive = false } + "common"(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } + shaded(project(path = ":platforms:mixin-lifecycle", configuration = "transformProductionQuilt")) { isTransitive = false } + minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") @@ -23,7 +26,13 @@ dependencies { modApi("org.quiltmc.quilted-fabric-api:quilted-fabric-api:${Versions.Quilt.fabricApi}") - setOf("fabric-lifecycle-events-v1", "fabric-resource-loader-v0", "fabric-api-base", "fabric-command-api-v2", "fabric-networking-api-v1").forEach { apiModule -> + setOf( + "fabric-lifecycle-events-v1", + "fabric-resource-loader-v0", + "fabric-api-base", + "fabric-command-api-v2", + "fabric-networking-api-v1" + ).forEach { apiModule -> val module = fabricApi.module(apiModule, Versions.Fabric.fabricAPI) modImplementation(module) include(module) From 5da26e2b532d1f26ead893e820d1745c5ecae6d0 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 5 Jul 2022 01:11:32 -0700 Subject: [PATCH 198/220] split most fabric and quilt code into common project --- platforms/fabric/build.gradle.kts | 6 +- .../dfsek/terra/fabric/FabricEntryPoint.java | 28 +--- .../dfsek/terra/fabric/FabricPlatform.java | 76 +++++++++ .../com/dfsek/terra/fabric/PlatformImpl.java | 151 ------------------ .../mixin/lifecycle/MinecraftServerMixin.java | 32 ---- .../mixin/lifecycle/NoiseConfigMixin.java | 31 ---- .../fabric/mixin/lifecycle/RegistryMixin.java | 20 --- .../fabric/mixin/lifecycle/package-info.java | 22 --- .../dfsek/terra/fabric/util/BiomeUtil.java | 71 -------- .../fabric/src/main/resources/fabric.mod.json | 1 + .../main/resources/terra.fabric.mixins.json | 5 - .../dfsek/terra/forge/ForgeEntryPoint.java | 6 +- .../{PlatformImpl.java => ForgePlatform.java} | 25 +-- platforms/mixin-common/build.gradle.kts | 2 + .../java/com/dfsek/terra/mod/ModPlatform.java | 21 +++ .../terra/lifecycle/LifecyclePlatform.java | 88 ++++++++++ .../lifecycle/mixin}/NoiseConfigMixin.java | 2 +- .../terra/lifecycle/mixin}/RegistryMixin.java | 9 +- .../mixin/lifecycle/MinecraftServerMixin.java | 6 +- .../client/MinecraftClientMixin.java | 6 +- .../lifecycle/server/ServerMainMixin.java | 6 +- .../terra/lifecycle}/util/BiomeUtil.java | 6 +- .../terra/lifecycle/util/LifecycleUtil.java | 19 +++ .../terra/lifecycle/util/RegistryUtil.java | 18 +++ .../resources/terra.lifecycle.mixins.json | 20 +++ .../com/dfsek/terra/quilt/PlatformImpl.java | 151 ------------------ .../dfsek/terra/quilt/QuiltEntryPoint.java | 29 +--- .../com/dfsek/terra/quilt/QuiltPlatform.java | 74 +++++++++ .../client/MinecraftClientMixin.java | 40 ----- .../quilt/mixin/lifecycle/package-info.java | 22 --- .../lifecycle/server/ServerMainMixin.java | 39 ----- .../quilt/src/main/resources/quilt.mod.json | 1 + .../main/resources/terra.quilt.mixins.json | 5 - 33 files changed, 351 insertions(+), 687 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricPlatform.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/RegistryMixin.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java rename platforms/forge/src/main/java/com/dfsek/terra/forge/{PlatformImpl.java => ForgePlatform.java} (87%) create mode 100644 platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java rename platforms/{quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle => mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin}/NoiseConfigMixin.java (96%) rename platforms/{quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle => mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin}/RegistryMixin.java (70%) rename platforms/{quilt/src/main/java/com/dfsek/terra/quilt => mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle}/mixin/lifecycle/MinecraftServerMixin.java (89%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle}/mixin/lifecycle/client/MinecraftClientMixin.java (91%) rename platforms/{fabric/src/main/java/com/dfsek/terra/fabric => mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle}/mixin/lifecycle/server/ServerMainMixin.java (90%) rename platforms/{quilt/src/main/java/com/dfsek/terra/quilt => mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle}/util/BiomeUtil.java (94%) create mode 100644 platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LifecycleUtil.java create mode 100644 platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/RegistryUtil.java create mode 100644 platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json delete mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPlatform.java delete mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java delete mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java delete mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 220c15962..d73796332 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -14,9 +14,9 @@ configurations { dependencies { shadedApi(project(":common:implementation:base")) - "compileOnly"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - "annotationProcessor"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - "annotationProcessor"("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") + compileOnly("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") + annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") + annotationProcessor("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionFabric")) { isTransitive = false } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java index 6fcc2b792..403f8df56 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -21,42 +21,18 @@ import cloud.commandframework.execution.CommandExecutionCoordinator; import cloud.commandframework.fabric.FabricServerCommandManager; import net.fabricmc.api.ModInitializer; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.util.registry.Registry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.dfsek.terra.api.command.CommandSender; import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; -import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; -import com.dfsek.terra.fabric.util.BiomeUtil; -import com.dfsek.terra.mod.CommonPlatform; -import com.dfsek.terra.mod.data.Codecs; public class FabricEntryPoint implements ModInitializer { private static final Logger logger = LoggerFactory.getLogger(FabricEntryPoint.class); - private static final PlatformImpl TERRA_PLUGIN = new PlatformImpl(); - - - public static PlatformImpl getPlatform() { - return TERRA_PLUGIN; - } - - public static void register() { // register the things - Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER); - Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); - } - - public static void initialize() { - getPlatform().getEventManager().callEvent( - new PlatformInitializationEvent()); - BiomeUtil.registerBiomes(); - CommonPlatform.get().registerWorldTypes((id, preset) -> BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, id, preset)); - } - + private static final FabricPlatform TERRA_PLUGIN = new FabricPlatform(); + @Override public void onInitialize() { logger.info("Initializing Terra Fabric mod..."); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricPlatform.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricPlatform.java new file mode 100644 index 000000000..6477407b4 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricPlatform.java @@ -0,0 +1,76 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.Version; + +import com.dfsek.terra.lifecycle.LifecyclePlatform; + +import net.fabricmc.loader.api.FabricLoader; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Collection; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.dfsek.terra.addon.EphemeralAddon; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.mod.CommonPlatform; + + +public class FabricPlatform extends LifecyclePlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(FabricPlatform.class); + + @Override + protected Collection getPlatformMods() { + return FabricLoader.getInstance().getAllMods().stream().flatMap(mod -> { + String id = mod.getMetadata().getId(); + if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return Stream.empty(); + try { + Version version = Versions.parseVersion(mod.getMetadata().getVersion().getFriendlyString()); + return Stream.of(new EphemeralAddon(version, "fabric:" + id)); + } catch(ParseException e) { + LOGGER.warn( + "Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " + + "it.", + id, mod.getMetadata().getVersion().getFriendlyString()); + } + return Stream.empty(); + }).collect(Collectors.toList()); + } + @Override + public @NotNull String platformName() { + return "Fabric"; + } + + @Override + public @NotNull File getDataFolder() { + return new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra"); + } + + @Override + public BaseAddon getPlatformAddon() { + return new FabricAddon(this); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java deleted file mode 100644 index 4c5ab038a..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.fabric; - -import ca.solostudios.strata.Versions; -import ca.solostudios.strata.parser.tokenizer.ParseException; -import ca.solostudios.strata.version.Version; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.MinecraftVersion; -import net.minecraft.server.MinecraftServer; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import com.dfsek.terra.addon.EphemeralAddon; -import com.dfsek.terra.api.addon.BaseAddon; -import com.dfsek.terra.api.handle.ItemHandle; -import com.dfsek.terra.api.handle.WorldHandle; -import com.dfsek.terra.api.util.generic.Lazy; -import com.dfsek.terra.fabric.util.BiomeUtil; -import com.dfsek.terra.mod.CommonPlatform; -import com.dfsek.terra.mod.ModPlatform; -import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; -import com.dfsek.terra.mod.handle.MinecraftItemHandle; -import com.dfsek.terra.mod.handle.MinecraftWorldHandle; - - -public class PlatformImpl extends ModPlatform { - private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); - private final ItemHandle itemHandle = new MinecraftItemHandle(); - private final WorldHandle worldHandle = new MinecraftWorldHandle(); - private final Lazy dataFolder = Lazy.lazy(() -> new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra")); - private MinecraftServer server; - - public PlatformImpl() { - CommonPlatform.initialize(this); - load(); - } - - public void setServer(MinecraftServer server) { - this.server = server; - } - - @Override - public MinecraftServer getServer() { - return server; - } - - @Override - public boolean reload() { - getTerraConfig().load(this); - getRawConfigRegistry().clear(); - boolean succeed = getRawConfigRegistry().loadAll(this); - - - if(server != null) { - server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { - LOGGER.warn("Failed to execute reload", throwable); - return null; - }).join(); - BiomeUtil.registerBiomes(); - server.getWorlds().forEach(world -> { - if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { - getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { - chunkGeneratorWrapper.setPack(pack); - LOGGER.info("Replaced pack in chunk generator for world {}", world); - }); - } - }); - } - return succeed; - } - - @Override - protected Iterable platformAddon() { - List addons = new ArrayList<>(); - - super.platformAddon().forEach(addons::add); - - String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); - try { - addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft")); - } catch(ParseException e) { - try { - addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft")); - } catch(ParseException ex) { - LOGGER.warn("Failed to parse Minecraft version", e); - } - } - - FabricLoader.getInstance().getAllMods().forEach(mod -> { - String id = mod.getMetadata().getId(); - if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; - try { - Version version = Versions.parseVersion(mod.getMetadata().getVersion().getFriendlyString()); - addons.add(new EphemeralAddon(version, "fabric:" + id)); - } catch(ParseException e) { - LOGGER.warn( - "Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " + - "it.", - id, mod.getMetadata().getVersion().getFriendlyString()); - } - }); - - return addons; - } - - @Override - public @NotNull String platformName() { - return "Fabric"; - } - - @Override - public @NotNull WorldHandle getWorldHandle() { - return worldHandle; - } - - @Override - public @NotNull File getDataFolder() { - return dataFolder.value(); - } - - @Override - public @NotNull ItemHandle getItemHandle() { - return itemHandle; - } - - @Override - public BaseAddon getPlatformAddon() { - return new FabricAddon(this); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java deleted file mode 100644 index 0620de7f2..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.fabric.mixin.lifecycle; - -import com.mojang.datafixers.DataFixer; -import net.minecraft.resource.ResourcePackManager; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.SaveLoader; -import net.minecraft.server.WorldGenerationProgressListenerFactory; -import net.minecraft.util.ApiServices; -import net.minecraft.world.level.storage.LevelStorage; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.net.Proxy; - -import com.dfsek.terra.fabric.FabricEntryPoint; - - -@Mixin(MinecraftServer.class) -public class MinecraftServerMixin { - @Inject(method = "(Ljava/lang/Thread;Lnet/minecraft/world/level/storage/LevelStorage$Session;" + - "Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/server/SaveLoader;Ljava/net/Proxy;" + - "Lcom/mojang/datafixers/DataFixer;Lnet/minecraft/util/ApiServices;" + - "Lnet/minecraft/server/WorldGenerationProgressListenerFactory;)V", - at = @At("RETURN")) - private void injectConstructor(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager, - SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices, - WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { - FabricEntryPoint.getPlatform().setServer((MinecraftServer) (Object) this); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java deleted file mode 100644 index 15957b31c..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/NoiseConfigMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.fabric.mixin.lifecycle; - -import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; -import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; -import net.minecraft.world.gen.noise.NoiseConfig; -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; - -import com.dfsek.terra.mod.util.SeedHack; - - -/** - * Hack to map noise sampler to seeds - */ -@Mixin(NoiseConfig.class) -public class NoiseConfigMixin { - @Shadow - @Final - private MultiNoiseSampler multiNoiseSampler; - - @Inject(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At("TAIL")) - private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, Registry noiseRegistry, long seed, CallbackInfo ci) { - SeedHack.register(multiNoiseSampler, seed); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/RegistryMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/RegistryMixin.java deleted file mode 100644 index 0f6ccd532..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/RegistryMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.fabric.mixin.lifecycle; - - -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.dfsek.terra.fabric.FabricEntryPoint; - - -// Register Terra things to the builtin registries. -@Mixin(Registry.class) -public class RegistryMixin { - @Inject(method = "", at = @At("RETURN")) - private static void registerTerraGenerators(CallbackInfo ci) { - FabricEntryPoint.register(); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java deleted file mode 100644 index ad90c31eb..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -/** - * Mixins that inject behavior into the client/server lifecycle. - */ - -package com.dfsek.terra.fabric.mixin.lifecycle; \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java deleted file mode 100644 index 7afb25668..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.dfsek.terra.fabric.util; - -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryKey; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; - -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.fabric.FabricEntryPoint; -import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.mod.config.ProtoPlatformBiome; -import com.dfsek.terra.mod.util.MinecraftUtil; - - -public final class BiomeUtil { - private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class); - - private BiomeUtil() { - - } - - public static void registerBiomes() { - logger.info("Registering biomes..."); - FabricEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. - pack.getCheckedRegistry(Biome.class) - .forEach((id, biome) -> registerBiome(biome, pack, id)); - }); - MinecraftUtil.registerFlora(BuiltinRegistries.BIOME); - logger.info("Terra biomes registered."); - } - - /** - * Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate. - * - * @param biome The Terra BiomeBuilder. - * @param pack The ConfigPack this biome belongs to. - */ - private static void registerBiome(Biome biome, ConfigPack pack, - com.dfsek.terra.api.registry.key.RegistryKey id) { - Registry registry = BuiltinRegistries.BIOME; - RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(registry); - - - if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { - ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); - } else { - net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla)); - - Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); - - if(registry.containsId(identifier)) { - ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(MinecraftUtil.getEntry(registry, identifier) - .orElseThrow() - .getKey() - .orElseThrow()); - } else { - ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry, - MinecraftUtil.registerKey(identifier).getValue(), - minecraftBiome).getKey().orElseThrow()); - } - - MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); - } - } - -} diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index 2d9a3db6a..65289db22 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -22,6 +22,7 @@ }, "mixins": [ "terra.fabric.mixins.json", + "terra.lifecycle.mixins.json", "terra.common.mixins.json" ], "depends": { diff --git a/platforms/fabric/src/main/resources/terra.fabric.mixins.json b/platforms/fabric/src/main/resources/terra.fabric.mixins.json index 9b2d4bcec..f97889f6d 100644 --- a/platforms/fabric/src/main/resources/terra.fabric.mixins.json +++ b/platforms/fabric/src/main/resources/terra.fabric.mixins.json @@ -4,15 +4,10 @@ "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "lifecycle.MinecraftServerMixin", - "lifecycle.NoiseConfigMixin", - "lifecycle.RegistryMixin" ], "client": [ - "lifecycle.client.MinecraftClientMixin" ], "server": [ - "lifecycle.server.ServerMainMixin" ], "injectors": { "defaultRequire": 1 diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index 9691dde88..d9ad54d81 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -47,16 +47,16 @@ public class ForgeEntryPoint { static { AwfulForgeHacks.loadAllTerraClasses(); - TERRA_PLUGIN = new PlatformImpl(); + TERRA_PLUGIN = new ForgePlatform(); } public static final String MODID = "terra"; private static final Logger logger = LoggerFactory.getLogger(ForgeEntryPoint.class); - private static final PlatformImpl TERRA_PLUGIN; + private static final ForgePlatform TERRA_PLUGIN; - public static PlatformImpl getPlatform() { + public static ForgePlatform getPlatform() { return TERRA_PLUGIN; } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java similarity index 87% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java index 5281b8ba1..60cd727f4 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/PlatformImpl.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java @@ -34,23 +34,17 @@ import java.util.List; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; -import com.dfsek.terra.api.handle.ItemHandle; -import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.api.util.generic.Lazy; import com.dfsek.terra.mod.CommonPlatform; import com.dfsek.terra.mod.ModPlatform; import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; -import com.dfsek.terra.mod.handle.MinecraftItemHandle; -import com.dfsek.terra.mod.handle.MinecraftWorldHandle; -public class PlatformImpl extends ModPlatform { - private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); - private final ItemHandle itemHandle = new MinecraftItemHandle(); - private final WorldHandle worldHandle = new MinecraftWorldHandle(); +public class ForgePlatform extends ModPlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(ForgePlatform.class); private final Lazy dataFolder = Lazy.lazy(() -> new File("./config/Terra")); - public PlatformImpl() { + public ForgePlatform() { CommonPlatform.initialize(this); load(); } @@ -117,23 +111,12 @@ public class PlatformImpl extends ModPlatform { public @NotNull String platformName() { return "Forge"; } - - @Override - public @NotNull WorldHandle getWorldHandle() { - return worldHandle; - } - + @Override public @NotNull File getDataFolder() { return dataFolder.value(); } - @Override - public @NotNull ItemHandle getItemHandle() { - return itemHandle; - } - - @Override public BaseAddon getPlatformAddon() { return new ForgeAddon(this); diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts index 47b720ca2..08098d753 100644 --- a/platforms/mixin-common/build.gradle.kts +++ b/platforms/mixin-common/build.gradle.kts @@ -15,6 +15,8 @@ loom { dependencies { shadedApi(project(":common:implementation:base")) + compileOnly("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") + modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") 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 ed9f2a986..680fcf187 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 @@ -4,8 +4,14 @@ import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.mod.config.SpawnSettingsTemplate; +import com.dfsek.terra.mod.handle.MinecraftItemHandle; + +import com.dfsek.terra.mod.handle.MinecraftWorldHandle; + import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnGroup; import net.minecraft.server.MinecraftServer; @@ -43,10 +49,15 @@ import com.dfsek.terra.mod.config.SpawnGroupTemplate; import com.dfsek.terra.mod.config.SpawnTypeConfig; import com.dfsek.terra.mod.util.PresetUtil; +import org.jetbrains.annotations.NotNull; + public abstract class ModPlatform extends AbstractPlatform { public abstract MinecraftServer getServer(); + private final ItemHandle itemHandle = new MinecraftItemHandle(); + private final WorldHandle worldHandle = new MinecraftWorldHandle(); + public void registerWorldTypes(BiConsumer registerFunction) { getRawConfigRegistry() .forEach(pack -> PresetUtil.createDefault(pack).apply(registerFunction)); @@ -93,4 +104,14 @@ public abstract class ModPlatform extends AbstractPlatform { } protected abstract BaseAddon getPlatformAddon(); + + @Override + public @NotNull WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public @NotNull ItemHandle getItemHandle() { + return itemHandle; + } } 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 new file mode 100644 index 000000000..13ae3f692 --- /dev/null +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java @@ -0,0 +1,88 @@ +package com.dfsek.terra.lifecycle; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import net.minecraft.MinecraftVersion; +import net.minecraft.server.MinecraftServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.dfsek.terra.addon.EphemeralAddon; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.lifecycle.util.BiomeUtil; +import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.ModPlatform; +import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; + + +public abstract class LifecyclePlatform extends ModPlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(LifecyclePlatform.class); + private static MinecraftServer server; + + public LifecyclePlatform() { + CommonPlatform.initialize(this); + load(); + } + + public static void setServer(MinecraftServer server) { + LifecyclePlatform.server = server; + } + + @Override + public MinecraftServer getServer() { + return server; + } + + @Override + public boolean reload() { + getTerraConfig().load(this); + getRawConfigRegistry().clear(); + boolean succeed = getRawConfigRegistry().loadAll(this); + + + if(server != null) { + server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { + LOGGER.warn("Failed to execute reload", throwable); + return null; + }).join(); + BiomeUtil.registerBiomes(); + server.getWorlds().forEach(world -> { + if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { + getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { + chunkGeneratorWrapper.setPack(pack); + LOGGER.info("Replaced pack in chunk generator for world {}", world); + }); + } + }); + } + return succeed; + } + + @Override + protected Iterable platformAddon() { + List addons = new ArrayList<>(); + + super.platformAddon().forEach(addons::add); + + String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); + try { + addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft")); + } catch(ParseException e) { + try { + addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft")); + } catch(ParseException ex) { + LOGGER.warn("Failed to parse Minecraft version", e); + } + } + + addons.addAll(getPlatformMods()); + + return addons; + } + + protected abstract Collection getPlatformMods(); +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/NoiseConfigMixin.java similarity index 96% rename from platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java rename to platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/NoiseConfigMixin.java index 6b863cca0..015a22260 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/NoiseConfigMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.quilt.mixin.lifecycle; +package com.dfsek.terra.lifecycle.mixin; import net.minecraft.util.math.noise.DoublePerlinNoiseSampler; import net.minecraft.util.registry.Registry; diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/RegistryMixin.java similarity index 70% rename from platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java rename to platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/RegistryMixin.java index 55d649d44..42b73c1ce 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/RegistryMixin.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.quilt.mixin.lifecycle; +package com.dfsek.terra.lifecycle.mixin; +import com.dfsek.terra.lifecycle.util.RegistryUtil; -import com.dfsek.terra.quilt.QuiltEntryPoint; import net.minecraft.util.registry.Registry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -9,11 +9,10 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -// Register Terra things to the builtin registries. @Mixin(Registry.class) public class RegistryMixin { @Inject(method = "", at = @At("RETURN")) private static void registerTerraGenerators(CallbackInfo ci) { - QuiltEntryPoint.register(); + RegistryUtil.register(); } -} +} \ No newline at end of file diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/MinecraftServerMixin.java similarity index 89% rename from platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java rename to platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/MinecraftServerMixin.java index 53277b18c..25ac340d0 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/MinecraftServerMixin.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.quilt.mixin.lifecycle; +package com.dfsek.terra.lifecycle.mixin.lifecycle; import com.mojang.datafixers.DataFixer; import net.minecraft.resource.ResourcePackManager; @@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.net.Proxy; -import com.dfsek.terra.quilt.QuiltEntryPoint; +import com.dfsek.terra.lifecycle.LifecyclePlatform; @Mixin(MinecraftServer.class) @@ -27,6 +27,6 @@ public class MinecraftServerMixin { private void injectConstructor(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager, SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices, WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { - QuiltEntryPoint.getPlatform().setServer((MinecraftServer) (Object) this); + LifecyclePlatform.setServer((MinecraftServer) (Object) this); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/client/MinecraftClientMixin.java similarity index 91% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java rename to platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/client/MinecraftClientMixin.java index b605d8cdb..30f092786 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/client/MinecraftClientMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.lifecycle.client; +package com.dfsek.terra.lifecycle.mixin.lifecycle.client; import net.minecraft.client.MinecraftClient; import net.minecraft.client.RunArgs; @@ -24,7 +24,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.lifecycle.util.LifecycleUtil; @Mixin(MinecraftClient.class) @@ -36,6 +36,6 @@ public class MinecraftClientMixin { // sorta arbitrary position, after mod init, before window opens shift = At.Shift.BEFORE)) public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { - FabricEntryPoint.initialize(); + LifecycleUtil.initialize(); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/server/ServerMainMixin.java similarity index 90% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java rename to platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/server/ServerMainMixin.java index 16e107631..e2e52bd2a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/server/ServerMainMixin.java @@ -15,7 +15,7 @@ * along with Terra. If not, see . */ -package com.dfsek.terra.fabric.mixin.lifecycle.server; +package com.dfsek.terra.lifecycle.mixin.lifecycle.server; import net.minecraft.server.Main; import org.spongepowered.asm.mixin.Mixin; @@ -23,7 +23,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.lifecycle.util.LifecycleUtil; @Mixin(Main.class) @@ -35,6 +35,6 @@ public class ServerMainMixin { // after registry manager creation ) private static void injectConstructor(String[] args, CallbackInfo ci) { - FabricEntryPoint.initialize(); + LifecycleUtil.initialize(); } } diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/BiomeUtil.java similarity index 94% rename from platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java rename to platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/BiomeUtil.java index e26d08938..b632220f9 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/BiomeUtil.java @@ -1,6 +1,5 @@ -package com.dfsek.terra.quilt.util; +package com.dfsek.terra.lifecycle.util; -import com.dfsek.terra.quilt.QuiltEntryPoint; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; @@ -12,6 +11,7 @@ import java.util.ArrayList; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.mod.CommonPlatform; import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; import com.dfsek.terra.mod.config.ProtoPlatformBiome; import com.dfsek.terra.mod.util.MinecraftUtil; @@ -26,7 +26,7 @@ public final class BiomeUtil { public static void registerBiomes() { logger.info("Registering biomes..."); - QuiltEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. + CommonPlatform.get().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. pack.getCheckedRegistry(Biome.class) .forEach((id, biome) -> registerBiome(biome, pack, id)); }); 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 new file mode 100644 index 000000000..7961a9c9a --- /dev/null +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LifecycleUtil.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.lifecycle.util; + +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.mod.CommonPlatform; + +import net.minecraft.util.registry.BuiltinRegistries; + + +public final class LifecycleUtil { + private LifecycleUtil() { + + } + + public static void initialize() { + CommonPlatform.get().getEventManager().callEvent(new PlatformInitializationEvent()); + BiomeUtil.registerBiomes(); + CommonPlatform.get().registerWorldTypes((id, preset) -> BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, id, preset)); + } +} 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 new file mode 100644 index 000000000..000f7c472 --- /dev/null +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/RegistryUtil.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.lifecycle.util; + +import com.dfsek.terra.mod.data.Codecs; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + + +public final class RegistryUtil { + private RegistryUtil() { + + } + + public static void register() { + Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER); + Registry.register(Registry.BIOME_SOURCE, new Identifier("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 new file mode 100644 index 000000000..ea76eb90e --- /dev/null +++ b/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json @@ -0,0 +1,20 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.lifecycle.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "NoiseConfigMixin", + "RegistryMixin", + "lifecycle.MinecraftServerMixin" + ], + "client": [ + "lifecycle.client.MinecraftClientMixin" + ], + "server": [ + "lifecycle.server.ServerMainMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java deleted file mode 100644 index 958e61080..000000000 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.quilt; - -import ca.solostudios.strata.Versions; -import ca.solostudios.strata.parser.tokenizer.ParseException; -import ca.solostudios.strata.version.Version; -import net.minecraft.MinecraftVersion; -import net.minecraft.server.MinecraftServer; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.loader.api.QuiltLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import com.dfsek.terra.addon.EphemeralAddon; -import com.dfsek.terra.api.addon.BaseAddon; -import com.dfsek.terra.api.handle.ItemHandle; -import com.dfsek.terra.api.handle.WorldHandle; -import com.dfsek.terra.api.util.generic.Lazy; -import com.dfsek.terra.mod.CommonPlatform; -import com.dfsek.terra.mod.ModPlatform; -import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; -import com.dfsek.terra.mod.handle.MinecraftItemHandle; -import com.dfsek.terra.mod.handle.MinecraftWorldHandle; -import com.dfsek.terra.quilt.util.BiomeUtil; - - -public class PlatformImpl extends ModPlatform { - private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); - private final ItemHandle itemHandle = new MinecraftItemHandle(); - private final WorldHandle worldHandle = new MinecraftWorldHandle(); - private final Lazy dataFolder = Lazy.lazy(() -> new File(QuiltLoader.getConfigDir().toFile(), "Terra")); - private MinecraftServer server; - - public PlatformImpl() { - CommonPlatform.initialize(this); - load(); - } - - public void setServer(MinecraftServer server) { - this.server = server; - } - - @Override - public MinecraftServer getServer() { - return server; - } - - @Override - public boolean reload() { - getTerraConfig().load(this); - getRawConfigRegistry().clear(); - boolean succeed = getRawConfigRegistry().loadAll(this); - - - if(server != null) { - server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { - LOGGER.warn("Failed to execute reload", throwable); - return null; - }).join(); - BiomeUtil.registerBiomes(); - server.getWorlds().forEach(world -> { - if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { - getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { - chunkGeneratorWrapper.setPack(pack); - LOGGER.info("Replaced pack in chunk generator for world {}", world); - }); - } - }); - } - return succeed; - } - - @Override - protected Iterable platformAddon() { - List addons = new ArrayList<>(); - - super.platformAddon().forEach(addons::add); - - String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); - try { - addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft")); - } catch(ParseException e) { - try { - addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft")); - } catch(ParseException ex) { - LOGGER.warn("Failed to parse Minecraft version", e); - } - } - - QuiltLoader.getAllMods().forEach(mod -> { - String id = mod.metadata().id(); - if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; - try { - Version version = Versions.parseVersion(mod.metadata().version().raw()); - addons.add(new EphemeralAddon(version, "quilt:" + id)); - } catch(ParseException e) { - LOGGER.warn( - "Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " + - "it.", - id, mod.metadata().version().raw()); - } - }); - - return addons; - } - - @Override - public @NotNull String platformName() { - return "Quilt"; - } - - @Override - public @NotNull WorldHandle getWorldHandle() { - return worldHandle; - } - - @Override - public @NotNull File getDataFolder() { - return dataFolder.value(); - } - - @Override - public @NotNull ItemHandle getItemHandle() { - return itemHandle; - } - - @Override - public BaseAddon getPlatformAddon() { - return new QuiltAddon(this); - } -} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java index 20adb8e3b..f7c939fed 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java @@ -19,45 +19,20 @@ package com.dfsek.terra.quilt; import cloud.commandframework.execution.CommandExecutionCoordinator; import cloud.commandframework.fabric.FabricServerCommandManager; +import net.minecraft.server.command.ServerCommandSource; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.util.registry.Registry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.dfsek.terra.api.command.CommandSender; import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; -import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; -import com.dfsek.terra.quilt.util.BiomeUtil; -import com.dfsek.terra.mod.CommonPlatform; -import com.dfsek.terra.mod.data.Codecs; public class QuiltEntryPoint implements ModInitializer { private static final Logger logger = LoggerFactory.getLogger(QuiltEntryPoint.class); - private static final PlatformImpl TERRA_PLUGIN = new PlatformImpl(); - - - public static PlatformImpl getPlatform() { - return TERRA_PLUGIN; - } - - public static void register() { // register the things - Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER); - Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); - } - - public static void initialize() { - getPlatform().getEventManager().callEvent( - new PlatformInitializationEvent()); - BiomeUtil.registerBiomes(); - CommonPlatform.get().registerWorldTypes((id, preset) -> BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, id, preset)); - } - + private static final QuiltPlatform TERRA_PLUGIN = new QuiltPlatform(); @Override public void onInitialize(ModContainer container) { logger.info("Initializing Terra Quilt mod..."); diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPlatform.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPlatform.java new file mode 100644 index 000000000..406e2ffcf --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPlatform.java @@ -0,0 +1,74 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.quilt; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.Version; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.loader.api.QuiltLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Collection; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.dfsek.terra.addon.EphemeralAddon; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.lifecycle.LifecyclePlatform; + + +public class QuiltPlatform extends LifecyclePlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(QuiltPlatform.class); + + @Override + protected Collection getPlatformMods() { + return QuiltLoader.getAllMods().stream().flatMap(mod -> { + String id = mod.metadata().id(); + if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return Stream.empty(); + try { + Version version = Versions.parseVersion(mod.metadata().version().raw()); + return Stream.of(new EphemeralAddon(version, "quilt:" + id)); + } catch(ParseException e) { + LOGGER.warn( + "Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " + + "it.", + id, mod.metadata().version().raw()); + } + return Stream.empty(); + }).collect(Collectors.toList()); + } + + @Override + public @NotNull String platformName() { + return "Quilt"; + } + + @Override + public @NotNull File getDataFolder() { + return new File(QuiltLoader.getConfigDir().toFile(), "Terra"); + } + + @Override + public BaseAddon getPlatformAddon() { + return new QuiltAddon(this); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java deleted file mode 100644 index 6556ba806..000000000 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.quilt.mixin.lifecycle.client; - -import com.dfsek.terra.quilt.QuiltEntryPoint; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.RunArgs; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - - -@Mixin(MinecraftClient.class) -public class MinecraftClientMixin { - @Inject(method = "", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/util/WindowProvider;createWindow" + - "(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)" + - "Lnet/minecraft/client/util/Window;", - // sorta arbitrary position, after mod init, before window opens - shift = At.Shift.BEFORE)) - public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { - QuiltEntryPoint.initialize(); - } -} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java deleted file mode 100644 index 23f9f63d2..000000000 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -/** - * Mixins that inject behavior into the client/server lifecycle. - */ - -package com.dfsek.terra.quilt.mixin.lifecycle; \ No newline at end of file diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java deleted file mode 100644 index 577e2cfe2..000000000 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.quilt.mixin.lifecycle.server; - -import com.dfsek.terra.quilt.QuiltEntryPoint; -import net.minecraft.server.Main; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - - -@Mixin(Main.class) -public class ServerMainMixin { - @Inject(method = "main([Ljava/lang/String;)V", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/resource/ResourcePackManager;(Lnet/minecraft/resource/ResourceType;" + - "[Lnet/minecraft/resource/ResourcePackProvider;)V") - // after registry manager creation - ) - private static void injectConstructor(String[] args, CallbackInfo ci) { - QuiltEntryPoint.initialize(); - } -} diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json index 6dac98fb9..fdb6735b4 100644 --- a/platforms/quilt/src/main/resources/quilt.mod.json +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -46,6 +46,7 @@ }, "mixin": [ "terra.quilt.mixins.json", + "terra.lifecycle.mixins.json", "terra.common.mixins.json" ], "accessWidener": "terra.accesswidener" diff --git a/platforms/quilt/src/main/resources/terra.quilt.mixins.json b/platforms/quilt/src/main/resources/terra.quilt.mixins.json index ca92e0bf1..91f51b344 100644 --- a/platforms/quilt/src/main/resources/terra.quilt.mixins.json +++ b/platforms/quilt/src/main/resources/terra.quilt.mixins.json @@ -4,15 +4,10 @@ "package": "com.dfsek.terra.quilt.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "lifecycle.MinecraftServerMixin", - "lifecycle.NoiseConfigMixin", - "lifecycle.RegistryMixin" ], "client": [ - "lifecycle.client.MinecraftClientMixin" ], "server": [ - "lifecycle.server.ServerMainMixin" ], "injectors": { "defaultRequire": 1 From 892ba38fec7965e5336ba64f1aa01caffcb61e63 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 5 Jul 2022 01:20:50 -0700 Subject: [PATCH 199/220] specify fabric mixin in fabric-quilt shared code --- platforms/mixin-common/build.gradle.kts | 2 -- platforms/mixin-lifecycle/build.gradle.kts | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts index 08098d753..47b720ca2 100644 --- a/platforms/mixin-common/build.gradle.kts +++ b/platforms/mixin-common/build.gradle.kts @@ -15,8 +15,6 @@ loom { dependencies { shadedApi(project(":common:implementation:base")) - compileOnly("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") diff --git a/platforms/mixin-lifecycle/build.gradle.kts b/platforms/mixin-lifecycle/build.gradle.kts index aa3a38fdb..ded26a47c 100644 --- a/platforms/mixin-lifecycle/build.gradle.kts +++ b/platforms/mixin-lifecycle/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { shadedApi(project(":common:implementation:base")) modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") + compileOnly("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") compileOnly(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } From 7e883ab5ced8bd16e940ff388f2290063c117cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 01:52:24 -0700 Subject: [PATCH 200/220] Villager Types --- .../com/dfsek/terra/forge/util/BiomeUtil.java | 19 +++++++++++++++-- .../java/com/dfsek/terra/mod/ModPlatform.java | 6 +++++- .../mod/config/VanillaBiomeProperties.java | 9 ++++++++ .../mod/config/VillagerTypeTemplate.java | 21 +++++++++++++++++++ .../mixin/access/VillagerTypeAccessor.java | 17 +++++++++++++++ .../dfsek/terra/mod/util/MinecraftUtil.java | 7 ++++--- .../main/resources/terra.common.mixins.json | 1 + 7 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VillagerTypeTemplate.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/VillagerTypeAccessor.java diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java index 28fe88ec2..827143edb 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java @@ -1,14 +1,21 @@ package com.dfsek.terra.forge.util; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; +import net.minecraft.village.VillagerType; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegisterEvent.RegisterHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.Map; +import java.util.Objects; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.Biome; @@ -45,13 +52,17 @@ public final class BiomeUtil { */ private static void registerBiome(Biome biome, ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey id, RegisterHelper helper) { - RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(BuiltinRegistries.BIOME); + RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()) .get(BuiltinRegistries.BIOME); if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); } else { - net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value()); + VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); + + net.minecraft.world.biome.Biome vanillaBiome = ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value(); + + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, vanillaBiome, vanillaBiomeProperties); Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); @@ -62,6 +73,10 @@ public final class BiomeUtil { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow()); } + Map villagerMap = VillagerTypeAccessor.getBiomeTypeToIdMap(); + + villagerMap.put(RegistryKey.of(Registry.BIOME_KEY, identifier), Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(), villagerMap.getOrDefault(vanilla, VillagerType.PLAINS))); + MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); } } 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 ed9f2a986..0bea26d0c 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 @@ -6,6 +6,8 @@ import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.terra.mod.config.SpawnSettingsTemplate; +import com.dfsek.terra.mod.config.VillagerTypeTemplate; + import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnGroup; import net.minecraft.server.MinecraftServer; @@ -15,6 +17,7 @@ import net.minecraft.sound.MusicSound; import net.minecraft.sound.SoundEvent; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.village.VillagerType; import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.Biome.TemperatureModifier; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; @@ -78,7 +81,8 @@ public abstract class ModPlatform extends AbstractPlatform { .registerLoader(SpawnEntry.class, SpawnEntryTemplate::new) .registerLoader(SpawnGroup.class, SpawnGroupTemplate::new) .registerLoader(SpawnTypeConfig.class, SpawnTypeConfig::new) - .registerLoader(SpawnSettings.class, SpawnSettingsTemplate::new); + .registerLoader(SpawnSettings.class, SpawnSettingsTemplate::new) + .registerLoader(VillagerType.class, VillagerTypeTemplate::new); } private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java index e44e4b977..429829267 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java @@ -7,6 +7,7 @@ import net.minecraft.sound.BiomeAdditionsSound; import net.minecraft.sound.BiomeMoodSound; import net.minecraft.sound.MusicSound; import net.minecraft.sound.SoundEvent; +import net.minecraft.village.VillagerType; import net.minecraft.world.biome.Biome.Precipitation; import net.minecraft.world.biome.Biome.TemperatureModifier; import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; @@ -85,6 +86,10 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { @Default private SpawnSettings spawnSettings = null; + @Value("villager-type") + @Default + private VillagerType villagerType = null; + public Integer getGrassColor() { return grassColor; } @@ -152,4 +157,8 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { public SpawnSettings getSpawnSettings() { return spawnSettings; } + + public VillagerType getVillagerType() { + return villagerType; + } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VillagerTypeTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VillagerTypeTemplate.java new file mode 100644 index 000000000..235102dac --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VillagerTypeTemplate.java @@ -0,0 +1,21 @@ +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.EntityType; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.village.VillagerType; + + +public class VillagerTypeTemplate implements ObjectTemplate { + @Value("id") + @Default + private Identifier id = null; + + @Override + public VillagerType get() { + return Registry.VILLAGER_TYPE.get(id); + } +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/VillagerTypeAccessor.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/VillagerTypeAccessor.java new file mode 100644 index 000000000..acf269a11 --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/VillagerTypeAccessor.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.mod.mixin.access; + +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.village.VillagerType; +import net.minecraft.world.biome.Biome; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(VillagerType.class) +public interface VillagerTypeAccessor { + @Accessor("BIOME_TO_TYPE") + static Map, VillagerType> getBiomeTypeToIdMap() { + throw new AssertionError("Untransformed Accessor!"); + } +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java index 1fa62bcae..152e743da 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java @@ -1,5 +1,7 @@ package com.dfsek.terra.mod.util; +import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; + import net.minecraft.block.entity.LootableContainerBlockEntity; import net.minecraft.block.entity.MobSpawnerBlockEntity; import net.minecraft.block.entity.SignBlockEntity; @@ -8,6 +10,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryEntry; import net.minecraft.util.registry.RegistryKey; +import net.minecraft.village.VillagerType; import net.minecraft.world.WorldAccess; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome.Builder; @@ -89,15 +92,13 @@ public final class MinecraftUtil { return RegistryKey.of(Registry.BIOME_KEY, identifier); } - public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla) { + public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla, VanillaBiomeProperties vanillaBiomeProperties) { GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); BiomeEffects.Builder effects = new BiomeEffects.Builder(); net.minecraft.world.biome.Biome.Builder builder = new Builder(); - VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) 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 b2b28d2e0..a6b6987a3 100644 --- a/platforms/mixin-common/src/main/resources/terra.common.mixins.json +++ b/platforms/mixin-common/src/main/resources/terra.common.mixins.json @@ -8,6 +8,7 @@ "access.MobSpawnerLogicAccessor", "access.StateAccessor", "access.StructureAccessorAccessor", + "access.VillagerTypeAccessor", "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", "fix.NetherFossilOptimization", "implementations.compat.GenerationSettingsFloraFeaturesMixin", From d280e113e66c54003d5c6f2108e858f285087523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 01:58:32 -0700 Subject: [PATCH 201/220] Villagers on lifecycle --- .../com/dfsek/terra/forge/util/BiomeUtil.java | 4 +--- .../dfsek/terra/lifecycle/util/BiomeUtil.java | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java index 827143edb..1678fd4a8 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java @@ -59,10 +59,8 @@ public final class BiomeUtil { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); } else { VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - - net.minecraft.world.biome.Biome vanillaBiome = ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value(); - net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, vanillaBiome, vanillaBiomeProperties); + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value(), vanillaBiomeProperties); Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); 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 b632220f9..8e6732a58 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 @@ -1,13 +1,20 @@ package com.dfsek.terra.lifecycle.util; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; + +import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; +import net.minecraft.village.VillagerType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.Map; +import java.util.Objects; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.Biome; @@ -49,7 +56,9 @@ public final class BiomeUtil { if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); } else { - net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla)); + VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); + + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla), vanillaBiomeProperties); Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); @@ -63,7 +72,11 @@ public final class BiomeUtil { MinecraftUtil.registerKey(identifier).getValue(), minecraftBiome).getKey().orElseThrow()); } - + + Map villagerMap = VillagerTypeAccessor.getBiomeTypeToIdMap(); + + villagerMap.put(RegistryKey.of(Registry.BIOME_KEY, identifier), Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(), villagerMap.getOrDefault(vanilla, VillagerType.PLAINS))); + MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); } } From 19e46fbe4c246d3ba4328c5551c0bf135c7317cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 02:24:25 -0700 Subject: [PATCH 202/220] remove dep because we shade --- platforms/quilt/src/main/resources/quilt.mod.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json index fdb6735b4..53afd8ecf 100644 --- a/platforms/quilt/src/main/resources/quilt.mod.json +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -37,10 +37,6 @@ { "id": "minecraft", "version": "1.19.x" - }, - { - "id": "quilted_fabric_api", - "versions": ">=2.0.0-" } ] }, From 8d19368999867c268213fa5cdeba49bc4fa19ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 11:24:18 -0700 Subject: [PATCH 203/220] quilt progress --- platforms/quilt/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index 365fec3bd..75484c22f 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -65,5 +65,7 @@ tasks { processResources { from(project(":platforms:mixin-common").file("terra.accesswidener")) + from(project(":platforms:mixin-common").file("src/main/resources/terra.common.mixins.json")) + from(project(":platforms:mixin-lifecycle").file("src/main/resources/terra.lifecycle.mixins.json")) } } From 639fc71f7af1c7ea057dd837f84c6d52275b5c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 12:54:27 -0700 Subject: [PATCH 204/220] Quilt progress 2 --- .gitignore | 3 +-- .../dfsek/terra/fabric/FabricEntryPoint.java | 4 +++- .../terra/fabric/mixin/RegistryMixin.java | 18 ++++++++++++++++++ .../main/resources/terra.fabric.mixins.json | 1 + .../terra/mod/handle/MinecraftWorldHandle.java | 3 ++- .../main/resources/terra.lifecycle.mixins.json | 1 - .../com/dfsek/terra/quilt/QuiltEntryPoint.java | 6 +++++- 7 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/RegistryMixin.java diff --git a/.gitignore b/.gitignore index 11b505e85..63dda4360 100644 --- a/.gitignore +++ b/.gitignore @@ -247,6 +247,5 @@ nbdist/ **/testDir/ -platforms/fabric/run/** +platforms/**/run/** -platforms/forge/run/** diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java index 403f8df56..c97f348e2 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -19,6 +19,9 @@ package com.dfsek.terra.fabric; import cloud.commandframework.execution.CommandExecutionCoordinator; import cloud.commandframework.fabric.FabricServerCommandManager; + +import com.dfsek.terra.lifecycle.util.RegistryUtil; + import net.fabricmc.api.ModInitializer; import net.minecraft.server.command.ServerCommandSource; import org.slf4j.Logger; @@ -43,7 +46,6 @@ public class FabricEntryPoint implements ModInitializer { commandSender -> (ServerCommandSource) commandSender ); - manager.brigadierManager().setNativeNumberSuggestions(false); TERRA_PLUGIN.getEventManager().callEvent(new CommandRegistrationEvent(manager)); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/RegistryMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/RegistryMixin.java new file mode 100644 index 000000000..1d32a1a38 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/RegistryMixin.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.fabric.mixin; + +import com.dfsek.terra.lifecycle.util.RegistryUtil; + +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(Registry.class) +public class RegistryMixin { + @Inject(method = "", at = @At("RETURN")) + private static void registerTerraGenerators(CallbackInfo ci) { + RegistryUtil.register(); + } +} \ 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 f97889f6d..50c976016 100644 --- a/platforms/fabric/src/main/resources/terra.fabric.mixins.json +++ b/platforms/fabric/src/main/resources/terra.fabric.mixins.json @@ -4,6 +4,7 @@ "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "RegistryMixin" ], "client": [ ], 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 13eef4b2d..fae4336ba 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 @@ -31,7 +31,7 @@ import com.dfsek.terra.api.handle.WorldHandle; public class MinecraftWorldHandle implements WorldHandle { - private static final BlockState AIR = (BlockState) Blocks.AIR.getDefaultState(); + private static BlockState AIR = null; @Override public @NotNull BlockState createBlockState(@NotNull String data) { @@ -46,6 +46,7 @@ public class MinecraftWorldHandle implements WorldHandle { @Override public @NotNull BlockState air() { + if (AIR == null) AIR = (BlockState) Blocks.AIR.getDefaultState(); return AIR; } 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 ea76eb90e..58c338929 100644 --- a/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json +++ b/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json @@ -5,7 +5,6 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "NoiseConfigMixin", - "RegistryMixin", "lifecycle.MinecraftServerMixin" ], "client": [ diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java index f7c939fed..3faf845c6 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java @@ -19,6 +19,9 @@ package com.dfsek.terra.quilt; import cloud.commandframework.execution.CommandExecutionCoordinator; import cloud.commandframework.fabric.FabricServerCommandManager; + +import com.dfsek.terra.lifecycle.util.RegistryUtil; + import net.minecraft.server.command.ServerCommandSource; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; @@ -42,7 +45,8 @@ public class QuiltEntryPoint implements ModInitializer { serverCommandSource -> (CommandSender) serverCommandSource, commandSender -> (ServerCommandSource) commandSender ); - + + RegistryUtil.register(); manager.brigadierManager().setNativeNumberSuggestions(false); From b31f917acf072275c646b2bab9680c775714ac0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 14:17:44 -0700 Subject: [PATCH 205/220] Fix cloud in dev env --- .../com/dfsek/terra/quilt/PreLaunchHacks.java | 43 +++++++++++++++++++ .../terra/quilt/QuiltPreLaunchEntryPoint.java | 22 ++++++++++ .../quilt/src/main/resources/quilt.mod.json | 3 ++ 3 files changed, 68 insertions(+) create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/PreLaunchHacks.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PreLaunchHacks.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PreLaunchHacks.java new file mode 100644 index 000000000..c9d42de36 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PreLaunchHacks.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.quilt; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; + +/** + * So you want to Mixin into Authlib/Brigadier/DataFixerUpper, on Fabric you'll need this guy. + * + *

YOU SHOULD ONLY USE THIS CLASS DURING "preLaunch" and ONLY TARGET A CLASS WHICH IS NOT ANY CLASS YOU MIXIN TO. + * + * This will likely not work on Gson because FabricLoader has some special logic related to Gson. + */ +public final class PreLaunchHacks { + private PreLaunchHacks() {} + + private static final ClassLoader KNOT_CLASSLOADER = Thread.currentThread().getContextClassLoader(); + private static final Method ADD_URL_METHOD; + + static { + Method tempAddUrlMethod = null; + try { + tempAddUrlMethod = KNOT_CLASSLOADER.getClass().getMethod("addURL", URL.class); + tempAddUrlMethod.setAccessible(true); + } catch (ReflectiveOperationException e) { + throw new RuntimeException("Failed to load Classloader fields", e); + } + + ADD_URL_METHOD = tempAddUrlMethod; + } + + /** + * Hackily load the package which a mixin may exist within. + * + * YOU SHOULD NOT TARGET A CLASS WHICH YOU MIXIN TO. + * + * @param pathOfAClass The path of any class within the package. + */ + public static void hackilyLoadForMixin(String pathOfAClass) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException { + URL url = Class.forName(pathOfAClass).getProtectionDomain().getCodeSource().getLocation(); + ADD_URL_METHOD.invoke(KNOT_CLASSLOADER, url); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java new file mode 100644 index 000000000..1afb1ee4e --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.quilt; + +import cloud.commandframework.brigadier.BrigadierMappingBuilder; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.loader.api.QuiltLoader; +import org.quiltmc.loader.api.entrypoint.PreLaunchEntrypoint; + +import java.lang.reflect.InvocationTargetException; + + +public class QuiltPreLaunchEntryPoint implements PreLaunchEntrypoint { + @Override + public void onPreLaunch(ModContainer mod) { + if (QuiltLoader.isDevelopmentEnvironment()) { + try { + PreLaunchHacks.hackilyLoadForMixin(BrigadierMappingBuilder.class.getName()); + } catch(ClassNotFoundException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json index 53afd8ecf..fbf0b5470 100644 --- a/platforms/quilt/src/main/resources/quilt.mod.json +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -23,6 +23,9 @@ "entrypoints": { "init": [ "com.dfsek.terra.quilt.QuiltEntryPoint" + ], + "pre_launch": [ + "com.dfsek.terra.quilt.QuiltPreLaunchEntryPoint" ] }, "depends": [ From 60046c466480b7db988a9910dc9e3d2272515b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 12:54:27 -0700 Subject: [PATCH 206/220] Revert "Quilt progress 2" This reverts commit 639fc71f7af1c7ea057dd837f84c6d52275b5c68. --- .gitignore | 3 ++- .../dfsek/terra/fabric/FabricEntryPoint.java | 4 +--- .../terra/fabric/mixin/RegistryMixin.java | 18 ------------------ .../main/resources/terra.fabric.mixins.json | 1 - .../terra/mod/handle/MinecraftWorldHandle.java | 3 +-- .../main/resources/terra.lifecycle.mixins.json | 1 + .../com/dfsek/terra/quilt/QuiltEntryPoint.java | 6 +----- 7 files changed, 6 insertions(+), 30 deletions(-) delete mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/RegistryMixin.java diff --git a/.gitignore b/.gitignore index 63dda4360..11b505e85 100644 --- a/.gitignore +++ b/.gitignore @@ -247,5 +247,6 @@ nbdist/ **/testDir/ -platforms/**/run/** +platforms/fabric/run/** +platforms/forge/run/** diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java index c97f348e2..403f8df56 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -19,9 +19,6 @@ package com.dfsek.terra.fabric; import cloud.commandframework.execution.CommandExecutionCoordinator; import cloud.commandframework.fabric.FabricServerCommandManager; - -import com.dfsek.terra.lifecycle.util.RegistryUtil; - import net.fabricmc.api.ModInitializer; import net.minecraft.server.command.ServerCommandSource; import org.slf4j.Logger; @@ -46,6 +43,7 @@ public class FabricEntryPoint implements ModInitializer { commandSender -> (ServerCommandSource) commandSender ); + manager.brigadierManager().setNativeNumberSuggestions(false); TERRA_PLUGIN.getEventManager().callEvent(new CommandRegistrationEvent(manager)); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/RegistryMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/RegistryMixin.java deleted file mode 100644 index 1d32a1a38..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/RegistryMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.fabric.mixin; - -import com.dfsek.terra.lifecycle.util.RegistryUtil; - -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - - -@Mixin(Registry.class) -public class RegistryMixin { - @Inject(method = "", at = @At("RETURN")) - private static void registerTerraGenerators(CallbackInfo ci) { - RegistryUtil.register(); - } -} \ 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 50c976016..f97889f6d 100644 --- a/platforms/fabric/src/main/resources/terra.fabric.mixins.json +++ b/platforms/fabric/src/main/resources/terra.fabric.mixins.json @@ -4,7 +4,6 @@ "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "RegistryMixin" ], "client": [ ], 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 fae4336ba..13eef4b2d 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 @@ -31,7 +31,7 @@ import com.dfsek.terra.api.handle.WorldHandle; public class MinecraftWorldHandle implements WorldHandle { - private static BlockState AIR = null; + private static final BlockState AIR = (BlockState) Blocks.AIR.getDefaultState(); @Override public @NotNull BlockState createBlockState(@NotNull String data) { @@ -46,7 +46,6 @@ public class MinecraftWorldHandle implements WorldHandle { @Override public @NotNull BlockState air() { - if (AIR == null) AIR = (BlockState) Blocks.AIR.getDefaultState(); return AIR; } 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 58c338929..ea76eb90e 100644 --- a/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json +++ b/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "NoiseConfigMixin", + "RegistryMixin", "lifecycle.MinecraftServerMixin" ], "client": [ diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java index 3faf845c6..f7c939fed 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java @@ -19,9 +19,6 @@ package com.dfsek.terra.quilt; import cloud.commandframework.execution.CommandExecutionCoordinator; import cloud.commandframework.fabric.FabricServerCommandManager; - -import com.dfsek.terra.lifecycle.util.RegistryUtil; - import net.minecraft.server.command.ServerCommandSource; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; @@ -45,8 +42,7 @@ public class QuiltEntryPoint implements ModInitializer { serverCommandSource -> (CommandSender) serverCommandSource, commandSender -> (ServerCommandSource) commandSender ); - - RegistryUtil.register(); + manager.brigadierManager().setNativeNumberSuggestions(false); From 0ee359b0a3091f12f7b46de1867bc8092fe8963a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 14:18:26 -0700 Subject: [PATCH 207/220] Git ignore --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 11b505e85..63dda4360 100644 --- a/.gitignore +++ b/.gitignore @@ -247,6 +247,5 @@ nbdist/ **/testDir/ -platforms/fabric/run/** +platforms/**/run/** -platforms/forge/run/** From b6d8453042757a6bb85c9732b93a57f61d09d231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 16:36:30 -0700 Subject: [PATCH 208/220] update QSL --- buildSrc/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index d5a77a8c4..481247b17 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -28,7 +28,7 @@ object Versions { object Quilt { const val quiltLoader = "0.17.0" const val loom = "0.12.+" - const val fabricApi = "2.0.0-alpha.2+0.55.3-1.19" + const val fabricApi = "2.0.0-beta.4+0.57.0-1.19" } object Mod { From b7343ca3271b2250f255a97cd95558fbeda09c31 Mon Sep 17 00:00:00 2001 From: dfsek Date: Tue, 5 Jul 2022 18:04:39 -0700 Subject: [PATCH 209/220] fix typo --- buildSrc/src/main/kotlin/Versions.kt | 2 +- platforms/fabric/build.gradle.kts | 2 +- platforms/forge/build.gradle.kts | 2 +- platforms/mixin-common/build.gradle.kts | 2 +- platforms/mixin-lifecycle/build.gradle.kts | 2 +- platforms/quilt/build.gradle.kts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index d5a77a8c4..703873929 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -37,7 +37,7 @@ object Versions { const val fabricLoader = "0.14.2" const val architecuryLoom = "0.12.0-SNAPSHOT" - const val architectutyPlugin = "3.4-SNAPSHOT" + const val architecturyPlugin = "3.4-SNAPSHOT" const val loomQuiltflower = "1.7.1" } diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index d73796332..1c79fbf62 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("fabric-loom") version Versions.Fabric.loom - id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("architectury-plugin") version Versions.Mod.architecturyPlugin id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index fc967677e..602f85976 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("dev.architectury.loom") version Versions.Mod.architecuryLoom - id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("architectury-plugin") version Versions.Mod.architecturyPlugin id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts index 47b720ca2..f9d382c58 100644 --- a/platforms/mixin-common/build.gradle.kts +++ b/platforms/mixin-common/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("dev.architectury.loom") version Versions.Mod.architecuryLoom - id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("architectury-plugin") version Versions.Mod.architecturyPlugin id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } diff --git a/platforms/mixin-lifecycle/build.gradle.kts b/platforms/mixin-lifecycle/build.gradle.kts index ded26a47c..7ccf286d7 100644 --- a/platforms/mixin-lifecycle/build.gradle.kts +++ b/platforms/mixin-lifecycle/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("dev.architectury.loom") version Versions.Mod.architecuryLoom - id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("architectury-plugin") version Versions.Mod.architecturyPlugin id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index 75484c22f..68a48fd41 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("org.quiltmc.loom") version Versions.Quilt.loom - id("architectury-plugin") version Versions.Mod.architectutyPlugin + id("architectury-plugin") version Versions.Mod.architecturyPlugin } From 29e1d05c710910e655b4a89474d092daa0801dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 22:57:03 -0700 Subject: [PATCH 210/220] quilt works! --- platforms/mixin-lifecycle/build.gradle.kts | 45 +++++++++++++++++----- platforms/quilt/build.gradle.kts | 42 ++++++++------------ platforms/quilt/gradle.properties | 1 + 3 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 platforms/quilt/gradle.properties diff --git a/platforms/mixin-lifecycle/build.gradle.kts b/platforms/mixin-lifecycle/build.gradle.kts index 7ccf286d7..a9fcf8b17 100644 --- a/platforms/mixin-lifecycle/build.gradle.kts +++ b/platforms/mixin-lifecycle/build.gradle.kts @@ -4,6 +4,30 @@ plugins { id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } +architectury { + platformSetupLoomIde() + fabric() +} + +configurations { + val common by creating + compileClasspath.get().extendsFrom(common) + runtimeClasspath.get().extendsFrom(common) +} + +dependencies { + shadedApi(project(":common:implementation:base")) + + compileOnly("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") + annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") + annotationProcessor("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") + + "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + + minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") + mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") +} + loom { accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) @@ -12,20 +36,21 @@ loom { } } -dependencies { - shadedApi(project(":common:implementation:base")) +tasks { + compileJava { + options.release.set(17) + } - modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") - compileOnly("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") + remapJar { + inputFile.set(shadowJar.get().archiveFile) + } - compileOnly(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } - - minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") - mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") + processResources { + from(project(":platforms:mixin-common").file("terra.accesswidener")) + } } architectury { common("fabric", "quilt") minecraft = Versions.Mod.minecraft -} - +} \ No newline at end of file diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index 68a48fd41..70d593ccc 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -1,21 +1,21 @@ plugins { - id("org.quiltmc.loom") version Versions.Quilt.loom + id("dev.architectury.loom") version Versions.Mod.architecuryLoom id("architectury-plugin") version Versions.Mod.architecturyPlugin } - -configurations { - val common by creating - compileClasspath.get().extendsFrom(common) - runtimeClasspath.get().extendsFrom(common) +architectury { + platformSetupLoomIde() + loader("quilt") } dependencies { shadedApi(project(":common:implementation:base")) - "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + "developmentQuilt"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionQuilt")) { isTransitive = false } - "common"(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } + implementation(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } + "developmentQuilt"(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-lifecycle", configuration = "transformProductionQuilt")) { isTransitive = false } @@ -24,22 +24,16 @@ dependencies { modImplementation("org.quiltmc:quilt-loader:${Versions.Quilt.quiltLoader}") - modApi("org.quiltmc.quilted-fabric-api:quilted-fabric-api:${Versions.Quilt.fabricApi}") - - setOf( - "fabric-lifecycle-events-v1", - "fabric-resource-loader-v0", - "fabric-api-base", - "fabric-command-api-v2", - "fabric-networking-api-v1" - ).forEach { apiModule -> - val module = fabricApi.module(apiModule, Versions.Fabric.fabricAPI) - modImplementation(module) - include(module) + modImplementation("org.quiltmc.quilted-fabric-api:quilted-fabric-api:${Versions.Quilt.fabricApi}") + + modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) { + exclude("net.fabricmc") + exclude("net.fabricmc.fabric-api") + } + include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) { + exclude("net.fabricmc") + exclude("net.fabricmc.fabric-api") } - - modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) - include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) } loom { @@ -65,7 +59,5 @@ tasks { processResources { from(project(":platforms:mixin-common").file("terra.accesswidener")) - from(project(":platforms:mixin-common").file("src/main/resources/terra.common.mixins.json")) - from(project(":platforms:mixin-lifecycle").file("src/main/resources/terra.lifecycle.mixins.json")) } } diff --git a/platforms/quilt/gradle.properties b/platforms/quilt/gradle.properties new file mode 100644 index 000000000..96758ce85 --- /dev/null +++ b/platforms/quilt/gradle.properties @@ -0,0 +1 @@ +loom.platform=quilt \ No newline at end of file From 36ceabd749eb41d0b14bccd3c1e51f7f8587ba9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Wed, 6 Jul 2022 00:26:42 -0700 Subject: [PATCH 211/220] Refactor Mixin build setup --- buildSrc/src/main/kotlin/DependencyConfig.kt | 3 ++ buildSrc/src/main/kotlin/Versions.kt | 15 ++++---- .../structure-sponge-loader/build.gradle.kts | 4 -- platforms/cli/build.gradle.kts | 11 ++---- platforms/fabric/build.gradle.kts | 37 ++++++++++--------- platforms/fabric/gradle.properties | 1 + .../fabric/src/main/resources/fabric.mod.json | 3 +- platforms/forge/build.gradle.kts | 35 +++++++----------- platforms/mixin-common/build.gradle.kts | 5 ++- .../main/resources}/terra.accesswidener | 0 platforms/mixin-lifecycle/build.gradle.kts | 24 ++---------- platforms/quilt/build.gradle.kts | 23 +++++++++--- .../quilt/src/main/resources/quilt.mod.json | 3 +- 13 files changed, 75 insertions(+), 89 deletions(-) create mode 100644 platforms/fabric/gradle.properties rename platforms/mixin-common/{ => src/main/resources}/terra.accesswidener (100%) diff --git a/buildSrc/src/main/kotlin/DependencyConfig.kt b/buildSrc/src/main/kotlin/DependencyConfig.kt index 55f6f18b6..d31736022 100644 --- a/buildSrc/src/main/kotlin/DependencyConfig.kt +++ b/buildSrc/src/main/kotlin/DependencyConfig.kt @@ -45,6 +45,9 @@ fun Project.configureDependencies() { maven ("https://maven.quiltmc.org/repository/release/") { name = "Quilt" } + maven("https://jitpack.io") { + name = "JitPack" + } } dependencies { diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index c7d2193e5..ef3ce2946 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -18,20 +18,18 @@ object Versions { } object Fabric { - const val fabricLoader = "0.14.2" - const val fabricAPI = "0.56.0+1.19" - const val mixin = "0.11.2+mixin.0.8.5" - const val loom = "0.12-SNAPSHOT" - const val minotaur = "1.1.0" + const val fabricLoader = "0.14.8" + const val fabricAPI = "0.57.0+1.19" } object Quilt { const val quiltLoader = "0.17.0" - const val loom = "0.12.+" const val fabricApi = "2.0.0-beta.4+0.57.0-1.19" } object Mod { + const val mixin = "0.11.2+mixin.0.8.5" + const val minecraft = "1.19" const val yarn = "$minecraft+build.1" const val fabricLoader = "0.14.2" @@ -40,10 +38,12 @@ object Versions { const val architecturyPlugin = "3.4-SNAPSHOT" const val loomQuiltflower = "1.7.1" + + const val lazyDfu = "0.1.2" } object Forge { - const val forge = "${Mod.minecraft}-41.0.38" + const val forge = "${Mod.minecraft}-41.0.63" const val burningwave = "12.53.0" } @@ -64,5 +64,6 @@ object Versions { const val nbt = "6.1" const val logback = "1.2.9" const val commonsIO = "2.7" + const val guava = "31.0.1-jre" } } \ No newline at end of file diff --git a/common/addons/structure-sponge-loader/build.gradle.kts b/common/addons/structure-sponge-loader/build.gradle.kts index d064e4fd5..dba93405f 100644 --- a/common/addons/structure-sponge-loader/build.gradle.kts +++ b/common/addons/structure-sponge-loader/build.gradle.kts @@ -2,10 +2,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar version = version("1.0.0") -repositories { - maven { url = uri("https://jitpack.io/") } -} - dependencies { api("commons-io:commons-io:2.7") api("com.github.Querz:NBT:6.1") diff --git a/platforms/cli/build.gradle.kts b/platforms/cli/build.gradle.kts index 26d9f3d6c..e273422af 100644 --- a/platforms/cli/build.gradle.kts +++ b/platforms/cli/build.gradle.kts @@ -2,18 +2,15 @@ plugins { application } -repositories { - maven { url = uri("https://jitpack.io/") } -} - val javaMainClass = "com.dfsek.terra.cli.TerraCLI" dependencies { - shadedApi("commons-io:commons-io:${Versions.CLI.commonsIO}") - shadedApi("com.github.Querz:NBT:${Versions.CLI.nbt}") shadedApi(project(":common:implementation:base")) - shadedImplementation("com.google.guava:guava:31.0.1-jre") + shadedApi("commons-io:commons-io:${Versions.CLI.commonsIO}") + shadedApi("com.github.Querz:NBT:${Versions.CLI.nbt}") + + shadedImplementation("com.google.guava:guava:${Versions.CLI.guava}") shadedImplementation("ch.qos.logback:logback-classic:${Versions.CLI.logback}") diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 1c79fbf62..85a829444 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -1,26 +1,22 @@ plugins { - id("fabric-loom") version Versions.Fabric.loom + id("dev.architectury.loom") version Versions.Mod.architecuryLoom id("architectury-plugin") version Versions.Mod.architecturyPlugin id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } - -configurations { - val common by creating - compileClasspath.get().extendsFrom(common) - runtimeClasspath.get().extendsFrom(common) +architectury { + platformSetupLoomIde() + loader("fabric") } dependencies { shadedApi(project(":common:implementation:base")) - compileOnly("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - annotationProcessor("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") - - "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + "developmentFabric"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionFabric")) { isTransitive = false } - "common"(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } + implementation(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } + "developmentFabric"(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-lifecycle", configuration = "transformProductionFabric")) { isTransitive = false } @@ -37,15 +33,25 @@ dependencies { modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) + + modLocalRuntime("com.github.astei:lazydfu:${Versions.Mod.lazyDfu}") } loom { - accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) + accessWidenerPath.set(project(":platforms:mixin-common").file("src/main/resources/terra.accesswidener")) mixin { defaultRefmapName.set("terra.fabric.refmap.json") } + launches { + named("client") { + property("fabric.log.level", "debug") + } + named("server") { + property("fabric.log.level", "debug") + } + } } @@ -57,11 +63,8 @@ tasks { } remapJar { + injectAccessWidener.set(true) inputFile.set(shadowJar.get().archiveFile) archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") } - - processResources { - from(project(":platforms:mixin-common").file("terra.accesswidener")) - } } diff --git a/platforms/fabric/gradle.properties b/platforms/fabric/gradle.properties new file mode 100644 index 000000000..90ee7a259 --- /dev/null +++ b/platforms/fabric/gradle.properties @@ -0,0 +1 @@ +loom.platform=fabric \ No newline at end of file diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index 65289db22..e71bcfeac 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -29,6 +29,5 @@ "fabricloader": ">=0.14.2", "java": ">=17", "minecraft": "1.19.x" - }, - "accessWidener": "terra.accesswidener" + } } \ No newline at end of file diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 602f85976..6b545f2ba 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -6,26 +6,16 @@ plugins { architectury { platformSetupLoomIde() - forge() -} - -configurations { - val common by creating - compileClasspath.get().extendsFrom(common) - runtimeClasspath.get().extendsFrom(common) + loader("forge") } dependencies { shadedApi(project(":common:implementation:base")) "forgeRuntimeLibrary"(project(":common:implementation:base")) - - "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + "developmentForge"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionForge")) { isTransitive = false } - "developmentForge"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { - isTransitive = false - } - forge(group = "net.minecraftforge", name = "forge", version = Versions.Forge.forge) @@ -38,12 +28,21 @@ dependencies { } loom { - accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) + accessWidenerPath.set(project(":platforms:mixin-common").file("src/main/resources/terra.accesswidener")) mixin { defaultRefmapName.set("terra.forge.refmap.json") } + launches { + named("client") { + property("fabric.log.level", "debug") + } + named("server") { + property("fabric.log.level", "debug") + } + } + forge { convertAccessWideners.set(true) mixinConfig("terra.common.mixins.json") @@ -66,17 +65,9 @@ tasks { ) } } - - shadowJar { - exclude("fabric.mod.json") - } remapJar { inputFile.set(shadowJar.get().archiveFile) archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") } - - processResources { - from(project(":platforms:mixin-common").file("terra.accesswidener")) - } } \ No newline at end of file diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts index f9d382c58..c270dbf53 100644 --- a/platforms/mixin-common/build.gradle.kts +++ b/platforms/mixin-common/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } loom { - accessWidenerPath.set(file("terra.accesswidener")) + accessWidenerPath.set(file("src/main/resources/terra.accesswidener")) mixin { defaultRefmapName.set("terra.common.refmap.json") @@ -15,7 +15,8 @@ loom { dependencies { shadedApi(project(":common:implementation:base")) - modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") + compileOnly("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") + annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") diff --git a/platforms/mixin-common/terra.accesswidener b/platforms/mixin-common/src/main/resources/terra.accesswidener similarity index 100% rename from platforms/mixin-common/terra.accesswidener rename to platforms/mixin-common/src/main/resources/terra.accesswidener diff --git a/platforms/mixin-lifecycle/build.gradle.kts b/platforms/mixin-lifecycle/build.gradle.kts index a9fcf8b17..eb8459b4e 100644 --- a/platforms/mixin-lifecycle/build.gradle.kts +++ b/platforms/mixin-lifecycle/build.gradle.kts @@ -4,32 +4,20 @@ plugins { id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } -architectury { - platformSetupLoomIde() - fabric() -} - -configurations { - val common by creating - compileClasspath.get().extendsFrom(common) - runtimeClasspath.get().extendsFrom(common) -} - dependencies { shadedApi(project(":common:implementation:base")) - compileOnly("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}") - annotationProcessor("net.fabricmc:fabric-loom:${Versions.Fabric.loom}") + compileOnly("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") + annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") - "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } + implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") } loom { - accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) + accessWidenerPath.set(project(":platforms:mixin-common").file("src/main/resources/terra.accesswidener")) mixin { defaultRefmapName.set("terra.lifecycle.refmap.json") @@ -44,10 +32,6 @@ tasks { remapJar { inputFile.set(shadowJar.get().archiveFile) } - - processResources { - from(project(":platforms:mixin-common").file("terra.accesswidener")) - } } architectury { diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index 70d593ccc..ead32bd01 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("dev.architectury.loom") version Versions.Mod.architecuryLoom id("architectury-plugin") version Versions.Mod.architecturyPlugin + id("io.github.juuxel.loom-quiltflower") version Versions.Mod.loomQuiltflower } architectury { @@ -18,7 +19,6 @@ dependencies { "developmentQuilt"(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-lifecycle", configuration = "transformProductionQuilt")) { isTransitive = false } - minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") @@ -34,14 +34,28 @@ dependencies { exclude("net.fabricmc") exclude("net.fabricmc.fabric-api") } + + modLocalRuntime("com.github.astei:lazydfu:${Versions.Mod.lazyDfu}") { + exclude("net.fabricmc") + exclude("net.fabricmc.fabric-api") + } } loom { - accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener")) + accessWidenerPath.set(project(":platforms:mixin-common").file("src/main/resources/terra.accesswidener")) mixin { defaultRefmapName.set("terra.quilt.refmap.json") } + + launches { + named("client") { + property("fabric.log.level", "debug") + } + named("server") { + property("fabric.log.level", "debug") + } + } } @@ -53,11 +67,8 @@ tasks { } remapJar { + injectAccessWidener.set(true) inputFile.set(shadowJar.get().archiveFile) archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") } - - processResources { - from(project(":platforms:mixin-common").file("terra.accesswidener")) - } } diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json index fbf0b5470..6ea8b960f 100644 --- a/platforms/quilt/src/main/resources/quilt.mod.json +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -47,6 +47,5 @@ "terra.quilt.mixins.json", "terra.lifecycle.mixins.json", "terra.common.mixins.json" - ], - "accessWidener": "terra.accesswidener" + ] } \ No newline at end of file From 10d44ce2178f99c0d357c58c48211c42221bbe10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Wed, 6 Jul 2022 00:51:47 -0700 Subject: [PATCH 212/220] Expand the AwfulHacks series --- .../bukkit/nms/v1_18_R2/AwfulBukkitHacks.java | 106 ++++++++++++++++++ .../bukkit/nms/v1_18_R2/NMSBiomeInjector.java | 80 +------------ .../bukkit/nms/v1_18_R2/NMSInitializer.java | 2 +- .../bukkit/nms/v1_19_R1/AwfulBukkitHacks.java | 102 +++++++++++++++++ .../bukkit/nms/v1_19_R1/NMSBiomeInjector.java | 83 +------------- .../bukkit/nms/v1_19_R1/NMSInitializer.java | 2 +- ...eLaunchHacks.java => AwfulQuiltHacks.java} | 4 +- .../terra/quilt/QuiltPreLaunchEntryPoint.java | 2 +- 8 files changed, 216 insertions(+), 165 deletions(-) create mode 100644 platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/AwfulBukkitHacks.java create mode 100644 platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/AwfulBukkitHacks.java rename platforms/quilt/src/main/java/com/dfsek/terra/quilt/{PreLaunchHacks.java => AwfulQuiltHacks.java} (95%) diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/AwfulBukkitHacks.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/AwfulBukkitHacks.java new file mode 100644 index 000000000..e530ec04a --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/AwfulBukkitHacks.java @@ -0,0 +1,106 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; +import com.dfsek.terra.registry.master.ConfigRegistry; + +import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.Lifecycle; +import net.minecraft.core.Holder; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.core.WritableRegistry; +import net.minecraft.data.BuiltinRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.biome.Biome; +import org.bukkit.NamespacedKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class AwfulBukkitHacks { + private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class); + private static final Map> terraBiomeMap = new HashMap<>(); + + + public static void registerBiomes(ConfigRegistry configRegistry) { + try { + LOGGER.info("Hacking biome registry..."); + WritableRegistry biomeRegistry = (WritableRegistry) Registries.biomeRegistry(); + + Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry) biomeRegistry, false); + + configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> { + try { + BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); + NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey(); + ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey()); + Biome platform = NMSBiomeInjector.createBiome( + biome, + biomeRegistry.get(vanillaMinecraftKey) // get + ); + + ResourceKey delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))); + + BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform); + biomeRegistry.register(delegateKey, platform, Lifecycle.stable()); + platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); + + terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location()); + + LOGGER.debug("Registered biome: " + delegateKey); + } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + })); + + Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry) biomeRegistry, true); // freeze registry again :) + + LOGGER.info("Doing tag garbage...."); + Map, List>> collect = biomeRegistry + .getTags() // streamKeysAndEntries + .collect(HashMap::new, + (map, pair) -> + map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), + HashMap::putAll); + + terraBiomeMap + .forEach((vb, terraBiomes) -> + NMSBiomeInjector.getEntry(biomeRegistry, vb) + .ifPresentOrElse( + vanilla -> terraBiomes + .forEach(tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb) + .ifPresentOrElse( + terra -> { + LOGGER.debug(vanilla.unwrapKey().orElseThrow().location() + + " (vanilla for " + + terra.unwrapKey().orElseThrow().location() + + ": " + + vanilla.tags().toList()); + + vanilla.tags() + .forEach( + tag -> collect + .computeIfAbsent(tag, + t -> new ArrayList<>()) + .add(terra)); + }, + () -> LOGGER.error( + "No such biome: {}", + tb))), + () -> LOGGER.error("No vanilla biome: {}", vb))); + + biomeRegistry.resetTags(); // clearTags + biomeRegistry.bindTags(ImmutableMap.copyOf(collect)); // populateTags + + } catch(SecurityException | IllegalArgumentException exception) { + throw new RuntimeException(exception); + } + } +} diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java index 3c69226d8..bf42448b2 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java @@ -31,84 +31,6 @@ import com.dfsek.terra.registry.master.ConfigRegistry; public class NMSBiomeInjector { - private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class); - private static final Map> terraBiomeMap = new HashMap<>(); - - - public static void registerBiomes(ConfigRegistry configRegistry) { - try { - LOGGER.info("Hacking biome registry..."); - WritableRegistry biomeRegistry = (WritableRegistry) Registries.biomeRegistry(); - - Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry) biomeRegistry, false); - - configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> { - try { - BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); - NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey(); - ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey()); - Biome platform = createBiome( - biome, - biomeRegistry.get(vanillaMinecraftKey) // get - ); - - ResourceKey delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("terra", createBiomeID(pack, key))); - - BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform); - biomeRegistry.register(delegateKey, platform, Lifecycle.stable()); - platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); - - terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location()); - - LOGGER.debug("Registered biome: " + delegateKey); - } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - throw new RuntimeException(e); - } - })); - - Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry) biomeRegistry, true); // freeze registry again :) - - LOGGER.info("Doing tag garbage...."); - Map, List>> collect = biomeRegistry - .getTags() // streamKeysAndEntries - .collect(HashMap::new, - (map, pair) -> - map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), - HashMap::putAll); - - terraBiomeMap - .forEach((vb, terraBiomes) -> - getEntry(biomeRegistry, vb) - .ifPresentOrElse( - vanilla -> terraBiomes - .forEach(tb -> getEntry(biomeRegistry, tb) - .ifPresentOrElse( - terra -> { - LOGGER.debug(vanilla.unwrapKey().orElseThrow().location() + - " (vanilla for " + - terra.unwrapKey().orElseThrow().location() + - ": " + - vanilla.tags().toList()); - - vanilla.tags() - .forEach( - tag -> collect - .computeIfAbsent(tag, - t -> new ArrayList<>()) - .add(terra)); - }, - () -> LOGGER.error( - "No such biome: {}", - tb))), - () -> LOGGER.error("No vanilla biome: {}", vb))); - - biomeRegistry.resetTags(); // clearTags - biomeRegistry.bindTags(ImmutableMap.copyOf(collect)); // populateTags - - } catch(SecurityException | IllegalArgumentException exception) { - throw new RuntimeException(exception); - } - } public static Optional> getEntry(Registry registry, ResourceLocation identifier) { return registry.getOptional(identifier) @@ -116,7 +38,7 @@ public class NMSBiomeInjector { .map(registry::getOrCreateHolder); } - private static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla) + public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Biome.BiomeBuilder builder = new Biome.BiomeBuilder(); // Builder diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInitializer.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInitializer.java index 60c7e1c1d..f724b89f0 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInitializer.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInitializer.java @@ -9,7 +9,7 @@ import com.dfsek.terra.bukkit.nms.Initializer; public class NMSInitializer implements Initializer { @Override public void initialize(PlatformImpl platform) { - NMSBiomeInjector.registerBiomes(platform.getRawConfigRegistry()); + AwfulBukkitHacks.registerBiomes(platform.getRawConfigRegistry()); Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin()); } } diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/AwfulBukkitHacks.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/AwfulBukkitHacks.java new file mode 100644 index 000000000..bfda736e2 --- /dev/null +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/AwfulBukkitHacks.java @@ -0,0 +1,102 @@ +package com.dfsek.terra.bukkit.nms.v1_19_R1; + +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; +import com.dfsek.terra.registry.master.ConfigRegistry; +import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.Lifecycle; +import net.minecraft.core.Holder; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.core.WritableRegistry; +import net.minecraft.data.BuiltinRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.biome.Biome; +import org.bukkit.NamespacedKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class AwfulBukkitHacks { + private static final Logger LOGGER = LoggerFactory.getLogger(AwfulBukkitHacks.class); + + private static final Map> terraBiomeMap = new HashMap<>(); + + public static void registerBiomes(ConfigRegistry configRegistry) { + try { + LOGGER.info("Hacking biome registry..."); + WritableRegistry biomeRegistry = (WritableRegistry) Registries.biomeRegistry(); + + Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry) biomeRegistry, false); + + configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> { + try { + BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); + NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey(); + ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey()); + Biome platform = NMSBiomeInjector.createBiome( + biome, + Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)) // get + ); + + ResourceKey delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, + new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))); + + BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform); + biomeRegistry.register(delegateKey, platform, Lifecycle.stable()); + platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); + + terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location()); + + LOGGER.debug("Registered biome: " + delegateKey); + } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + })); + + Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry) biomeRegistry, true); // freeze registry again :) + + LOGGER.info("Doing tag garbage...."); + Map, List>> collect = biomeRegistry + .getTags() // streamKeysAndEntries + .collect(HashMap::new, + (map, pair) -> + map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), + HashMap::putAll); + + terraBiomeMap + .forEach((vb, terraBiomes) -> + NMSBiomeInjector.getEntry(biomeRegistry, vb) + .ifPresentOrElse( + vanilla -> terraBiomes + .forEach(tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb) + .ifPresentOrElse( + terra -> { + LOGGER.debug(vanilla.unwrapKey().orElseThrow().location() + + " (vanilla for " + + terra.unwrapKey().orElseThrow().location() + + ": " + + vanilla.tags().toList()); + + vanilla.tags() + .forEach( + tag -> collect + .computeIfAbsent(tag, + t -> new ArrayList<>()) + .add(terra)); + }, + () -> LOGGER.error( + "No such biome: {}", + tb))), + () -> LOGGER.error("No vanilla biome: {}", vb))); + + biomeRegistry.resetTags(); + biomeRegistry.bindTags(ImmutableMap.copyOf(collect)); + + } catch(SecurityException | IllegalArgumentException exception) { + throw new RuntimeException(exception); + } + } +} diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java index fdf380e97..88f224f4b 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java @@ -31,93 +31,14 @@ import com.dfsek.terra.registry.master.ConfigRegistry; public class NMSBiomeInjector { - private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class); - private static final Map> terraBiomeMap = new HashMap<>(); - - - public static void registerBiomes(ConfigRegistry configRegistry) { - try { - LOGGER.info("Hacking biome registry..."); - WritableRegistry biomeRegistry = (WritableRegistry) Registries.biomeRegistry(); - - Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry) biomeRegistry, false); - - configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> { - try { - BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); - NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey(); - ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey()); - Biome platform = createBiome( - biome, - Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)) // get - ); - - ResourceKey delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, - new ResourceLocation("terra", createBiomeID(pack, key))); - - BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform); - biomeRegistry.register(delegateKey, platform, Lifecycle.stable()); - platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); - - terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location()); - - LOGGER.debug("Registered biome: " + delegateKey); - } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - throw new RuntimeException(e); - } - })); - - Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry) biomeRegistry, true); // freeze registry again :) - - LOGGER.info("Doing tag garbage...."); - Map, List>> collect = biomeRegistry - .getTags() // streamKeysAndEntries - .collect(HashMap::new, - (map, pair) -> - map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), - HashMap::putAll); - - terraBiomeMap - .forEach((vb, terraBiomes) -> - getEntry(biomeRegistry, vb) - .ifPresentOrElse( - vanilla -> terraBiomes - .forEach(tb -> getEntry(biomeRegistry, tb) - .ifPresentOrElse( - terra -> { - LOGGER.debug(vanilla.unwrapKey().orElseThrow().location() + - " (vanilla for " + - terra.unwrapKey().orElseThrow().location() + - ": " + - vanilla.tags().toList()); - - vanilla.tags() - .forEach( - tag -> collect - .computeIfAbsent(tag, - t -> new ArrayList<>()) - .add(terra)); - }, - () -> LOGGER.error( - "No such biome: {}", - tb))), - () -> LOGGER.error("No vanilla biome: {}", vb))); - - biomeRegistry.resetTags(); - biomeRegistry.bindTags(ImmutableMap.copyOf(collect)); - - } catch(SecurityException | IllegalArgumentException exception) { - throw new RuntimeException(exception); - } - } - + public static Optional> getEntry(Registry registry, ResourceLocation identifier) { return registry.getOptional(identifier) .flatMap(registry::getResourceKey) .map(registry::getOrCreateHolderOrThrow); } - private static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla) + public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Biome.BiomeBuilder builder = new Biome.BiomeBuilder(); diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSInitializer.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSInitializer.java index 61efc587d..82a293cd1 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSInitializer.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSInitializer.java @@ -9,7 +9,7 @@ import com.dfsek.terra.bukkit.nms.Initializer; public class NMSInitializer implements Initializer { @Override public void initialize(PlatformImpl platform) { - NMSBiomeInjector.registerBiomes(platform.getRawConfigRegistry()); + AwfulBukkitHacks.registerBiomes(platform.getRawConfigRegistry()); Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin()); } } diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PreLaunchHacks.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/AwfulQuiltHacks.java similarity index 95% rename from platforms/quilt/src/main/java/com/dfsek/terra/quilt/PreLaunchHacks.java rename to platforms/quilt/src/main/java/com/dfsek/terra/quilt/AwfulQuiltHacks.java index c9d42de36..7e3b7afcc 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PreLaunchHacks.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/AwfulQuiltHacks.java @@ -11,8 +11,8 @@ import java.net.URL; * * This will likely not work on Gson because FabricLoader has some special logic related to Gson. */ -public final class PreLaunchHacks { - private PreLaunchHacks() {} +public final class AwfulQuiltHacks { + private AwfulQuiltHacks() {} private static final ClassLoader KNOT_CLASSLOADER = Thread.currentThread().getContextClassLoader(); private static final Method ADD_URL_METHOD; diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java index 1afb1ee4e..1e4fb70a9 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java @@ -13,7 +13,7 @@ public class QuiltPreLaunchEntryPoint implements PreLaunchEntrypoint { public void onPreLaunch(ModContainer mod) { if (QuiltLoader.isDevelopmentEnvironment()) { try { - PreLaunchHacks.hackilyLoadForMixin(BrigadierMappingBuilder.class.getName()); + AwfulQuiltHacks.hackilyLoadForMixin(BrigadierMappingBuilder.class.getName()); } catch(ClassNotFoundException | InvocationTargetException | IllegalAccessException e) { throw new RuntimeException(e); } From ef4a28fd23e5d0ceba0cbef4be25e0c5edd55d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Tue, 5 Jul 2022 02:24:25 -0700 Subject: [PATCH 213/220] Revert "remove dep because we shade" This reverts commit 19e46fbe4c246d3ba4328c5551c0bf135c7317cb. --- platforms/quilt/src/main/resources/quilt.mod.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json index 6ea8b960f..0f53988ec 100644 --- a/platforms/quilt/src/main/resources/quilt.mod.json +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -40,6 +40,10 @@ { "id": "minecraft", "version": "1.19.x" + }, + { + "id": "quilted_fabric_api", + "versions": ">=2.0.0-" } ] }, From 7bef49012528a801637175f94eac97cce42338fd Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 6 Jul 2022 16:10:29 -0700 Subject: [PATCH 214/220] increase Gradle memory --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 35e42e00d..2193336e8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ terra.wiki=https://github.com/PolyhedralDev/Terra/wiki terra.license=MIT # Gradle options -org.gradle.jvmargs=-Xmx3072M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC +org.gradle.jvmargs=-Xmx4096M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC org.gradle.vfs.watch=true kapt.use.worker.api=true kapt.include.compile.classpath=false From a1acfef7210767b6bf62750db1c9509b38f4c083 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 6 Jul 2022 16:42:32 -0700 Subject: [PATCH 215/220] fix remapping --- platforms/forge/build.gradle.kts | 3 +++ platforms/mixin-common/build.gradle.kts | 1 + platforms/mixin-lifecycle/build.gradle.kts | 1 + platforms/quilt/build.gradle.kts | 5 +++++ 4 files changed, 10 insertions(+) diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 6b545f2ba..343b965b0 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -10,6 +10,9 @@ architectury { } dependencies { + annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") + annotationProcessor("dev.architectury:architectury-loom:${Versions.Mod.architecuryLoom}") + shadedApi(project(":common:implementation:base")) "forgeRuntimeLibrary"(project(":common:implementation:base")) diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts index c270dbf53..b293f3cfa 100644 --- a/platforms/mixin-common/build.gradle.kts +++ b/platforms/mixin-common/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { compileOnly("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") + annotationProcessor("dev.architectury:architectury-loom:${Versions.Mod.architecuryLoom}") minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") diff --git a/platforms/mixin-lifecycle/build.gradle.kts b/platforms/mixin-lifecycle/build.gradle.kts index eb8459b4e..0a9e71d7c 100644 --- a/platforms/mixin-lifecycle/build.gradle.kts +++ b/platforms/mixin-lifecycle/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { compileOnly("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") + annotationProcessor("dev.architectury:architectury-loom:${Versions.Mod.architecuryLoom}") implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index ead32bd01..8fc889b2f 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -12,9 +12,14 @@ architectury { dependencies { shadedApi(project(":common:implementation:base")) + annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") + annotationProcessor("dev.architectury:architectury-loom:${Versions.Mod.architecuryLoom}") + + implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } "developmentQuilt"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionQuilt")) { isTransitive = false } + implementation(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } "developmentQuilt"(project(path = ":platforms:mixin-lifecycle", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-lifecycle", configuration = "transformProductionQuilt")) { isTransitive = false } From 1d5abbcb6bdc0e8c7cf9bcdff7d34356878e0241 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 6 Jul 2022 17:15:08 -0700 Subject: [PATCH 216/220] specify mixin refmaps --- .../mixin-common/src/main/resources/terra.common.mixins.json | 3 ++- .../src/main/resources/terra.lifecycle.mixins.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) 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 a6b6987a3..d36a29a4e 100644 --- a/platforms/mixin-common/src/main/resources/terra.common.mixins.json +++ b/platforms/mixin-common/src/main/resources/terra.common.mixins.json @@ -44,5 +44,6 @@ ], "injectors": { "defaultRequire": 1 - } + }, + "refmap": "terra.common.refmap.json" } \ No newline at end of file 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 ea76eb90e..4df69c7fb 100644 --- a/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json +++ b/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json @@ -16,5 +16,6 @@ ], "injectors": { "defaultRequire": 1 - } + }, + "refmap": "terra.lifecycle.refmap.json" } \ No newline at end of file From dc5e71e3deec972cdc6b06a828a07edd9998ee11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Wed, 6 Jul 2022 17:32:43 -0700 Subject: [PATCH 217/220] fix tooling hell --- platforms/forge/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 343b965b0..5a8c1c837 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -40,9 +40,11 @@ loom { launches { named("client") { property("fabric.log.level", "debug") + property("mixin.env.disableRefMap", "true") } named("server") { property("fabric.log.level", "debug") + property("mixin.env.disableRefMap", "true") } } From b3a8f375bcfd21ebeac5575dc75a738a3967984b Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 6 Jul 2022 19:28:07 -0700 Subject: [PATCH 218/220] reformat all code --- .github/PULL_REQUEST_TEMPLATE.md | 12 +- CONTRIBUTING.md | 7 +- buildSrc/src/main/kotlin/AddonConfig.kt | 44 +++---- buildSrc/src/main/kotlin/DependencyConfig.kt | 4 +- .../src/main/kotlin/DistributionConfig.kt | 2 +- buildSrc/src/main/kotlin/Versions.kt | 4 +- .../extrusion/BiomeExtrusionProvider.java | 6 +- .../biome/extrusion/api/ReplaceableBiome.java | 16 +-- .../biome/pipeline/BiomePipelineProvider.java | 8 +- .../config/BiomeProviderTemplate.java | 2 +- .../biome/query/BiomeQueryAPIAddon.java | 4 +- .../addons/biome/query/api/BiomeQueries.java | 2 +- .../biome/query/impl/SingleTagQuery.java | 2 +- .../NoiseChunkGenerator3DAddon.java | 12 +- .../config/noise/ThreadLocalNoiseHolder.java | 2 +- .../config/palette/BiomePaletteTemplate.java | 3 +- .../math/interpolation/ChunkInterpolator.java | 4 +- .../LazilyEvaluatedInterpolator.java | 1 + .../math/samplers/SamplerProvider.java | 2 +- .../locator/locators/SamplerLocator.java | 26 ++--- .../defined/UserDefinedFunction.java | 11 +- .../addons/terrascript/parser/Parser.java | 4 +- .../addons/terrascript/parser/lang/Scope.java | 8 +- .../lang/constants/BooleanConstant.java | 1 + .../lang/constants/NumericConstant.java | 1 + .../parser/lang/functions/Function.java | 34 +++--- .../lang/operations/BooleanOrOperation.java | 1 + .../operations/ConcatenationOperation.java | 20 ++-- .../lang/operations/ModuloOperation.java | 1 + .../operations/MultiplicationOperation.java | 1 + .../operations/NumberAdditionOperation.java | 1 + .../lang/operations/SubtractionOperation.java | 1 + .../statements/EqualsStatement.java | 2 +- .../statements/LessThanOrEqualsStatement.java | 1 + .../statements/LessThanStatement.java | 1 + .../assign/VariableAssignmentNode.java | 3 +- .../reference/VariableReferenceNode.java | 2 +- .../src/test/java/structure/ParserTest.java | 3 +- .../dfsek/terra/api/properties/Context.java | 14 +-- .../dfsek/terra/api/util/GeometryUtil.java | 2 +- .../terra/api/util/generic/pair/Pair.java | 109 +++++++++--------- .../world/biome/generation/BiomeProvider.java | 2 +- .../generation/CachingBiomeProvider.java | 6 +- .../world/chunk/generation/util/Column.java | 2 +- .../terra/api/world/util/Interceptors.java | 4 +- common/api/src/test/java/util/ColumnTest.java | 6 +- .../terra/config/pack/ConfigPackImpl.java | 3 +- .../src/test/java/registry/RegistryTest.java | 6 +- .../terra/addon/BootstrapAddonLoader.java | 3 +- gradle.properties | 1 - .../dfsek/terra/bukkit/TerraBukkitPlugin.java | 2 +- .../BukkitChunkGeneratorWrapper.java | 39 ++++--- .../dfsek/terra/bukkit/nms/Initializer.java | 4 +- .../inventory/meta/BukkitDamageable.java | 2 - .../bukkit/nms/v1_18_R2/AwfulBukkitHacks.java | 63 +++++----- .../bukkit/nms/v1_18_R2/NMSBiomeInjector.java | 45 +++----- .../v1_18_R2/NMSChunkGeneratorDelegate.java | 18 ++- .../nms/v1_18_R2/NMSInjectListener.java | 7 +- .../terra/bukkit/nms/v1_18_R2/Reflection.java | 5 +- .../bukkit/nms/v1_19_R1/AwfulBukkitHacks.java | 76 +++++++----- .../bukkit/nms/v1_19_R1/NMSBiomeInjector.java | 16 --- .../bukkit/nms/v1_19_R1/NMSBiomeProvider.java | 11 +- .../v1_19_R1/NMSChunkGeneratorDelegate.java | 22 ++-- .../nms/v1_19_R1/NMSInjectListener.java | 7 +- .../terra/bukkit/nms/v1_19_R1/Reflection.java | 4 +- .../terra/bukkit/nms/v1_19_R1/Registries.java | 4 +- .../dfsek/terra/cli/block/CLIBlockState.java | 4 +- platforms/fabric/build.gradle.kts | 8 +- .../com/dfsek/terra/fabric/FabricAddon.java | 5 +- .../dfsek/terra/fabric/FabricEntryPoint.java | 2 +- .../dfsek/terra/fabric/FabricPlatform.java | 9 +- platforms/forge/build.gradle.kts | 2 +- .../dfsek/terra/forge/AwfulForgeHacks.java | 75 ++++++------ .../com/dfsek/terra/forge/ForgeAddon.java | 5 +- .../dfsek/terra/forge/ForgeEntryPoint.java | 26 ++--- .../com/dfsek/terra/forge/ForgePlatform.java | 37 +++--- .../mixin/lifecycle/NoiseConfigMixin.java | 10 +- .../com/dfsek/terra/forge/util/BiomeUtil.java | 33 ++++-- .../src/main/resources/META-INF/mods.toml | 2 +- .../forge/src/main/resources/pack.mcmeta | 8 +- .../main/resources/terra.forge.mixins.json | 2 +- .../com/dfsek/terra/mod/MinecraftAddon.java | 8 +- .../java/com/dfsek/terra/mod/ModPlatform.java | 38 +++--- .../config/BiomeAdditionsSoundTemplate.java | 2 +- .../mod/config/BiomeMoodSoundTemplate.java | 2 +- .../config/BiomeParticleConfigTemplate.java | 4 +- .../terra/mod/config/MusicSoundTemplate.java | 2 +- .../terra/mod/config/SoundEventTemplate.java | 4 +- .../mod/config/SpawnSettingsTemplate.java | 6 +- .../mod/config/VanillaBiomeProperties.java | 2 +- .../mod/config/VillagerTypeTemplate.java | 1 - .../java/com/dfsek/terra/mod/data/Codecs.java | 4 +- .../mixin/access/VillagerTypeAccessor.java | 1 + ...oveGoalsUnsynchronizedRandomAccessFix.java | 3 +- .../mixin/fix/NetherFossilOptimization.java | 5 +- .../dfsek/terra/mod/util/MinecraftUtil.java | 83 ++++++------- .../com/dfsek/terra/mod/util/PresetUtil.java | 14 +-- .../main/resources/terra.common.mixins.json | 92 +++++++-------- .../terra/lifecycle/LifecyclePlatform.java | 8 +- .../lifecycle/mixin/NoiseConfigMixin.java | 6 +- .../terra/lifecycle/mixin/RegistryMixin.java | 4 +- .../dfsek/terra/lifecycle/util/BiomeUtil.java | 24 ++-- .../terra/lifecycle/util/LifecycleUtil.java | 6 +- .../terra/lifecycle/util/RegistryUtil.java | 6 +- .../resources/terra.lifecycle.mixins.json | 2 +- platforms/quilt/build.gradle.kts | 2 +- .../dfsek/terra/quilt/AwfulQuiltHacks.java | 53 ++++----- .../com/dfsek/terra/quilt/QuiltAddon.java | 1 + .../dfsek/terra/quilt/QuiltEntryPoint.java | 1 + .../com/dfsek/terra/quilt/QuiltPlatform.java | 3 +- .../terra/quilt/QuiltPreLaunchEntryPoint.java | 2 +- 111 files changed, 706 insertions(+), 653 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 35418fc93..62b32c8d9 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -72,15 +72,19 @@ - [ ] Bug Fix - [ ] Build system -- [ ] Documentation +- [ ] + Documentation - [ ] New Feature - [ ] Performance -- [ ] Refactoring -- [ ] Repository +- [ ] + Refactoring +- [ ] + Repository - [ ] Revert - [ ] Style - [ ] Tests -- [ ] Translation +- [ ] + Translation #### Compatiblity diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bbb72ecad..b876ff487 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,7 +63,8 @@ to [Terra global moderation team](CODE_OF_CONDUCT.md#Reporting). ## I don't want to read this whole thing I just have a question!!! -> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below. +> **Note:** Please don't file an issue to ask a question. You'll get faster +> results by using the resources below. We have an official discord server where you can request help from various users @@ -103,7 +104,9 @@ you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report) . -> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. +> **Note:** If you find a **Closed** issue that seems like it is the same thing +> that you're experiencing, open a new issue and include a link to the original +> issue in the body of your new one. #### Before Submitting A Bug Report diff --git a/buildSrc/src/main/kotlin/AddonConfig.kt b/buildSrc/src/main/kotlin/AddonConfig.kt index ec585ba8e..b4dda3bca 100644 --- a/buildSrc/src/main/kotlin/AddonConfig.kt +++ b/buildSrc/src/main/kotlin/AddonConfig.kt @@ -12,30 +12,30 @@ import kotlin.streams.asStream */ fun Project.addonDir(dir: File, task: Task) { val moveAddons = tasks.register("moveAddons" + task.name) { - dependsOn("compileAddons") - doLast { - dir.parentFile.mkdirs() - matchingAddons(dir) { - it.name.startsWith("Terra-") // Assume everything that starts with Terra- is a core addon. - }.forEach { - println("Deleting old addon: " + it.absolutePath) - it.delete() - } - forSubProjects(":common:addons") { - val jar = tasks.named("shadowJar").get() as ShadowJar - - val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" - val target = File(dir, boot + jar.archiveFileName.get()) - - val base = "${jar.archiveBaseName.get()}-${version}" - - println("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base") - - jar.archiveFile.orNull?.asFile?.copyTo(target) - } + dependsOn("compileAddons") + doLast { + dir.parentFile.mkdirs() + matchingAddons(dir) { + it.name.startsWith("Terra-") // Assume everything that starts with Terra- is a core addon. + }.forEach { + println("Deleting old addon: " + it.absolutePath) + it.delete() + } + forSubProjects(":common:addons") { + val jar = tasks.named("shadowJar").get() as ShadowJar + + val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" + val target = File(dir, boot + jar.archiveFileName.get()) + + val base = "${jar.archiveBaseName.get()}-${version}" + + println("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base") + + jar.archiveFile.orNull?.asFile?.copyTo(target) } - } + + } task.dependsOn(moveAddons) } diff --git a/buildSrc/src/main/kotlin/DependencyConfig.kt b/buildSrc/src/main/kotlin/DependencyConfig.kt index d31736022..b0e7d32c4 100644 --- a/buildSrc/src/main/kotlin/DependencyConfig.kt +++ b/buildSrc/src/main/kotlin/DependencyConfig.kt @@ -39,10 +39,10 @@ fun Project.configureDependencies() { maven("https://papermc.io/repo/repository/maven-public/") { name = "PaperMC" } - maven ( "https://files.minecraftforge.net/maven/" ) { + maven("https://files.minecraftforge.net/maven/") { name = "Forge" } - maven ("https://maven.quiltmc.org/repository/release/") { + maven("https://maven.quiltmc.org/repository/release/") { name = "Quilt" } maven("https://jitpack.io") { diff --git a/buildSrc/src/main/kotlin/DistributionConfig.kt b/buildSrc/src/main/kotlin/DistributionConfig.kt index 60e79867a..56fe68ad7 100644 --- a/buildSrc/src/main/kotlin/DistributionConfig.kt +++ b/buildSrc/src/main/kotlin/DistributionConfig.kt @@ -53,7 +53,7 @@ fun Project.configureDistribution() { val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}") - + if (!Files.exists(addonPath)) { Files.createDirectories(addonPath.parent) Files.createFile(addonPath) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index ef3ce2946..28ca98ca0 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -33,10 +33,10 @@ object Versions { const val minecraft = "1.19" const val yarn = "$minecraft+build.1" const val fabricLoader = "0.14.2" - + const val architecuryLoom = "0.12.0-SNAPSHOT" const val architecturyPlugin = "3.4-SNAPSHOT" - + const val loomQuiltflower = "1.7.1" const val lazyDfu = "0.1.2" diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java index a7331fc8a..c9f1f8129 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionProvider.java @@ -28,7 +28,7 @@ public class BiomeExtrusionProvider implements BiomeProvider { @Override public Biome getBiome(int x, int y, int z, long seed) { Biome delegated = delegate.getBiome(x, y, z, seed); - + return extrude(delegated, x, y, z, seed); } @@ -42,8 +42,8 @@ public class BiomeExtrusionProvider implements BiomeProvider { @Override public Column getColumn(int x, int z, long seed, int min, int max) { return delegate.getBaseBiome(x, z, seed) - .map(base -> (Column) new BaseBiomeColumn(this, base, min, max, x, z, seed)) - .orElseGet(() -> BiomeProvider.super.getColumn(x, z, seed, min, max)); + .map(base -> (Column) new BaseBiomeColumn(this, base, min, max, x, z, seed)) + .orElseGet(() -> BiomeProvider.super.getColumn(x, z, seed, min, max)); } @Override diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java index e76eec1f3..d79ec409a 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java @@ -10,6 +10,14 @@ import com.dfsek.terra.api.world.biome.Biome; * Basically just a specialised implementation of {@link Optional} for biomes where a biome may be a "self" reference. */ public sealed interface ReplaceableBiome permits PresentBiome, SelfBiome { + static ReplaceableBiome of(Biome biome) { + return new PresentBiome(biome); + } + + static ReplaceableBiome self() { + return SelfBiome.INSTANCE; + } + Biome get(Biome existing); default Biome get() { @@ -20,12 +28,4 @@ public sealed interface ReplaceableBiome permits PresentBiome, SelfBiome { } boolean isSelf(); - - static ReplaceableBiome of(Biome biome) { - return new PresentBiome(biome); - } - - static ReplaceableBiome self() { - return SelfBiome.INSTANCE; - } } diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java index 063395ae4..f3f4c3aa9 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -81,11 +81,11 @@ public class BiomePipelineProvider implements BiomeProvider { public Biome getBiome(int x, int z, long seed) { x += mutator.noise(seed + 1, x, z) * noiseAmp; z += mutator.noise(seed + 2, x, z) * noiseAmp; - - + + x /= resolution; z /= resolution; - + int fdX = FastMath.floorDiv(x, pipeline.getSize()); int fdZ = FastMath.floorDiv(z, pipeline.getSize()); return holderCache.get(new SeededVector(fdX, fdZ, seed)).getBiome(x - fdX * pipeline.getSize(), @@ -120,7 +120,7 @@ public class BiomePipelineProvider implements BiomeProvider { } return false; } - + @Override public int hashCode() { int code = x; 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 a6df1f200..1412485fe 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 BIOME_TAG_KEY = Context.create(BiomeTagHolder.class); @Inject private Platform platform; - @Inject private BaseAddon addon; - public static PropertyKey BIOME_TAG_KEY = Context.create(BiomeTagHolder.class); - @Override public void initialize() { diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java index 6e36b7a45..dbee2752b 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/api/BiomeQueries.java @@ -8,7 +8,7 @@ import com.dfsek.terra.api.world.biome.Biome; public final class BiomeQueries { private BiomeQueries() { - + } public static Predicate has(String tag) { diff --git a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java index af2bfa8c7..eef1a0a56 100644 --- a/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java +++ b/common/addons/biome-query-api/src/main/java/com/dfsek/terra/addons/biome/query/impl/SingleTagQuery.java @@ -7,8 +7,8 @@ import com.dfsek.terra.api.world.biome.Biome; public class SingleTagQuery implements Predicate { - private int tagIndex = -1; private final String tag; + private int tagIndex = -1; public SingleTagQuery(String tag) { this.tag = tag; diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java index cd81f9555..06450b613 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java @@ -49,9 +49,9 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { .getOrCreateRegistry(ChunkGeneratorProvider.class) .register(addon.key("NOISE_3D"), pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(), - config.getHorizontalRes(), - config.getVerticalRes(), noisePropertiesPropertyKey, - paletteInfoPropertyKey)); + config.getHorizontalRes(), + config.getVerticalRes(), noisePropertiesPropertyKey, + paletteInfoPropertyKey)); event.getPack() .applyLoader(SlantLayer.class, SlantLayer::new); }) @@ -62,8 +62,10 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer { .register(addon, ConfigurationLoadEvent.class) .then(event -> { if(event.is(Biome.class)) { - event.getLoadedObject(Biome.class).getContext().put(paletteInfoPropertyKey, event.load(new BiomePaletteTemplate(platform)).get()); - event.getLoadedObject(Biome.class).getContext().put(noisePropertiesPropertyKey, event.load(new BiomeNoiseConfigTemplate()).get()); + event.getLoadedObject(Biome.class).getContext().put(paletteInfoPropertyKey, + event.load(new BiomePaletteTemplate(platform)).get()); + event.getLoadedObject(Biome.class).getContext().put(noisePropertiesPropertyKey, + event.load(new BiomeNoiseConfigTemplate()).get()); } }) .failThrough(); diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/ThreadLocalNoiseHolder.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/ThreadLocalNoiseHolder.java index c8fc0c7ac..454f9492f 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/ThreadLocalNoiseHolder.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/ThreadLocalNoiseHolder.java @@ -12,7 +12,7 @@ public class ThreadLocalNoiseHolder { if(holder.init && holder.y == y && holder.z == z && holder.x == x && holder.seed == seed) { return holder.noise; } - + double noise = sampler.noise(seed, x, y, z); holder.noise = noise; holder.x = x; 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 f95d9dffa..f1f0f804a 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 @@ -83,6 +83,7 @@ public class BiomePaletteTemplate implements ObjectTemplate { slantLayers.put(threshold, layer.getPalette()); } - return new PaletteInfo(builder.build(), SlantHolder.of(slantLayers, minThreshold), oceanPalette, seaLevel, slantDepth, updatePalette); + return new PaletteInfo(builder.build(), SlantHolder.of(slantLayers, minThreshold), oceanPalette, seaLevel, slantDepth, + updatePalette); } } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java index 4ef7072c7..d712bfc60 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -87,10 +87,10 @@ public class ChunkInterpolator { for(int zi = -blend; zi <= blend; zi++) { int blendX = (xi * step); int blendZ = (zi * step); - + int localIndex = (scaledX + maxBlend + blendX) + maxBlendAndChunk * (scaledZ + maxBlend + blendZ); Column column = columns[localIndex]; - + if(column == null) { column = provider.getColumn(absoluteX + blendX, absoluteZ + blendZ, seed, min, max); columns[localIndex] = column; diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java index 6e46ba774..f2a48c50a 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java @@ -25,6 +25,7 @@ public class LazilyEvaluatedInterpolator { private final int min, max; private final int zMul, yMul; + public LazilyEvaluatedInterpolator(BiomeProvider biomeProvider, int cx, int cz, int max, PropertyKey noisePropertiesKey, int min, int horizontalRes, int verticalRes, long seed) { diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java index 11ce0167f..ab20614b5 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java @@ -53,7 +53,7 @@ public class SamplerProvider { public Sampler3D getChunk(int cx, int cz, WorldProperties world, BiomeProvider provider) { WorldContext context = new WorldContext(cx, cz, world.getSeed(), world.getMinHeight(), world.getMaxHeight()); return cache.get(context, c -> new Sampler3D(c.cx, c.cz, c.seed, c.minHeight, c.maxHeight, provider, - elevationSmooth, noisePropertiesKey, maxBlend)); + elevationSmooth, noisePropertiesKey, maxBlend)); } private record WorldContext(int cx, int cz, long seed, int minHeight, int maxHeight) { diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SamplerLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SamplerLocator.java index 3a2ff8330..e5c43a122 100644 --- a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SamplerLocator.java +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SamplerLocator.java @@ -23,6 +23,19 @@ public class SamplerLocator implements Locator { this.samplers = samplers; } + private static int floorToInt(double value) { + int valueInt = (int) value; + if(value < 0.0) { + if(value == (double) valueInt) { + return valueInt; + } else { + return valueInt == Integer.MIN_VALUE ? valueInt : valueInt - 1; + } + } else { + return valueInt; + } + } + @Override public BinaryColumn getSuitableCoordinates(Column column) { BinaryColumnBuilder results = column.newBinaryColumn(); @@ -36,17 +49,4 @@ public class SamplerLocator implements Locator { return results.build(); } - - private static int floorToInt(double value) { - int valueInt = (int)value; - if (value < 0.0) { - if (value == (double)valueInt) { - return valueInt; - } else { - return valueInt == Integer.MIN_VALUE ? valueInt : valueInt - 1; - } - } else { - return valueInt; - } - } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java index fe72ed070..a087012ca 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java @@ -23,11 +23,10 @@ import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; public class UserDefinedFunction implements DynamicFunction { + private static final Map CACHE = new HashMap<>(); private final Expression expression; private final int args; - private static final Map CACHE = new HashMap<>(); - protected UserDefinedFunction(Expression expression, int args) { this.expression = expression; this.args = args; @@ -38,17 +37,17 @@ public class UserDefinedFunction implements DynamicFunction { if(function == null) { Parser parser = new Parser(); Scope parent = new Scope(); - + Scope functionScope = new Scope().withParent(parent); - + template.getArgs().forEach(functionScope::addInvocationVariable); - + for(Entry entry : template.getFunctions().entrySet()) { String id = entry.getKey(); FunctionTemplate nest = entry.getValue(); parser.registerFunction(id, newInstance(nest)); } - + function = new UserDefinedFunction(parser.parse(template.getFunction(), functionScope), template.getArgs().size()); CACHE.put(template, function); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java index fae348713..2b344343a 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java @@ -338,9 +338,9 @@ public class Parser { Returnable value = parseExpression(tokens, true, scopeBuilder); ParserUtil.checkReturnType(value, returnType); - + String id = identifier.getContent(); - + return switch(value.returnType()) { case NUMBER -> new NumAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.num(id)); case STRING -> new StrAssignmentNode((Returnable) value, identifier.getPosition(), scopeBuilder.str(id)); diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java index f9532c8cf..511c486bd 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java @@ -46,9 +46,8 @@ public class Scope { } public static final class ScopeBuilder { - private int numSize, boolSize, strSize = 0; private final Map> indices; - + private int numSize, boolSize, strSize = 0; private ScopeBuilder parent; public ScopeBuilder() { @@ -77,6 +76,7 @@ public class Scope { } return id; } + public int num(String id) { int num = numSize; indices.put(check(id), Pair.of(num, ReturnType.NUMBER)); @@ -107,14 +107,14 @@ public class Scope { parent.updateBoolSize(size); } } - + private void updateNumSize(int size) { this.numSize = FastMath.max(numSize, size); if(parent != null) { parent.updateNumSize(size); } } - + private void updateStrSize(int size) { this.strSize = FastMath.max(strSize, size); if(parent != null) { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java index 25cf9cdc2..3782344d1 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java @@ -14,6 +14,7 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public class BooleanConstant extends ConstantExpression { private final boolean constant; + public BooleanConstant(Boolean constant, Position position) { super(constant, position); this.constant = constant; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java index 78164fdc8..296b0c3e4 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java @@ -15,6 +15,7 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public class NumericConstant extends ConstantExpression { private final double constant; + public NumericConstant(Number constant, Position position) { super(constant, position); this.constant = constant.doubleValue(); diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java index 86780eb55..9c1da1155 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java @@ -14,6 +14,23 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public interface Function extends Returnable { + Function NULL = new Function<>() { + @Override + public ReturnType returnType() { + return null; + } + + @Override + public Object apply(ImplementationArguments implementationArguments, Scope scope) { + return null; + } + + @Override + public Position getPosition() { + return null; + } + }; + @Override default double applyDouble(ImplementationArguments implementationArguments, Scope scope) { return ((Number) apply(implementationArguments, scope)).doubleValue(); @@ -23,21 +40,4 @@ public interface Function extends Returnable { default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { return (Boolean) apply(implementationArguments, scope); } - - Function NULL = new Function<>() { - @Override - public ReturnType returnType() { - return null; - } - - @Override - public Object apply(ImplementationArguments implementationArguments, Scope scope) { - return null; - } - - @Override - public Position getPosition() { - return null; - } - }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java index e5ca10337..4722e175c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java @@ -27,6 +27,7 @@ public class BooleanOrOperation extends BinaryOperation { public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { return left.applyBoolean(implementationArguments, scope) || right.applyBoolean(implementationArguments, scope); } + @Override public ReturnType returnType() { return ReturnType.BOOLEAN; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java index 17e233b84..1ff9d11b1 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java @@ -18,16 +18,6 @@ public class ConcatenationOperation extends BinaryOperation { super(left, right, position); } - @Override - public Returnable.ReturnType returnType() { - return Returnable.ReturnType.STRING; - } - - @Override - public Object apply(ImplementationArguments implementationArguments, Scope scope) { - return toString(left.apply(implementationArguments, scope)) + toString(right.apply(implementationArguments, scope)); - } - private static String toString(Object object) { String s = object.toString(); if(object instanceof Double) { @@ -38,4 +28,14 @@ public class ConcatenationOperation extends BinaryOperation { } return s; } + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.STRING; + } + + @Override + public Object apply(ImplementationArguments implementationArguments, Scope scope) { + return toString(left.apply(implementationArguments, scope)) + toString(right.apply(implementationArguments, scope)); + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java index 3731d0807..b305f4c90 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java @@ -27,6 +27,7 @@ public class ModuloOperation extends BinaryOperation { public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { return left.applyDouble(implementationArguments, scope) % right.applyDouble(implementationArguments, scope); } + @Override public ReturnType returnType() { return ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java index 62e58a92c..2a2cdbfe6 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java @@ -27,6 +27,7 @@ public class MultiplicationOperation extends BinaryOperation { public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { return left.applyDouble(implementationArguments, scope) * right.applyDouble(implementationArguments, scope); } + @Override public ReturnType returnType() { return ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java index 33439b742..075a27619 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java @@ -27,6 +27,7 @@ public class NumberAdditionOperation extends BinaryOperation { public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { return left.applyDouble(implementationArguments, scope) + right.applyDouble(implementationArguments, scope); } + @Override public ReturnType returnType() { return ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java index dca6c66c5..9a11c430f 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java @@ -27,6 +27,7 @@ public class SubtractionOperation extends BinaryOperation { public double applyDouble(ImplementationArguments implementationArguments, Scope scope) { return left.applyDouble(implementationArguments, scope) - right.applyDouble(implementationArguments, scope); } + @Override public ReturnType returnType() { return ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java index 97648aa1f..f402e4862 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java @@ -42,7 +42,7 @@ public class EqualsStatement extends BinaryOperation { if(leftValue instanceof Number l && rightValue instanceof Number r) { return FastMath.abs(l.doubleValue() - r.doubleValue()) <= EPSILON; } - + return leftValue.equals(rightValue); } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java index 207d09632..891210395 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java @@ -29,6 +29,7 @@ public class LessThanOrEqualsStatement extends BinaryOperation public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { return left.applyDouble(implementationArguments, scope) <= right.applyDouble(implementationArguments, scope); } + @Override public Returnable.ReturnType returnType() { return Returnable.ReturnType.BOOLEAN; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java index aed7189f6..969f0e27e 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java @@ -29,6 +29,7 @@ public class LessThanStatement extends BinaryOperation { public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) { return left.applyDouble(implementationArguments, scope) < right.applyDouble(implementationArguments, scope); } + @Override public Returnable.ReturnType returnType() { return Returnable.ReturnType.BOOLEAN; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java index edfb15ef7..ebca757b5 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java @@ -14,9 +14,8 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public abstract class VariableAssignmentNode implements Item { protected final Returnable value; - private final Position position; protected final int index; - + private final Position position; public VariableAssignmentNode(Returnable value, Position position, int index) { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java index a115f8b94..ecfebedca 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java @@ -12,9 +12,9 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public abstract class VariableReferenceNode implements Returnable { + protected final int index; private final Position position; private final ReturnType type; - protected final int index; public VariableReferenceNode(Position position, ReturnType type, int index) { this.position = position; diff --git a/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java b/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java index 2f07954d2..fc0fcf532 100644 --- a/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java +++ b/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java @@ -30,7 +30,8 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position; public class ParserTest { @Test public void parse() throws IOException, ParseException { - Parser parser = new Parser(IOUtils.toString(Objects.requireNonNull(getClass().getResourceAsStream("/test.tesf")), Charset.defaultCharset())); + Parser parser = new Parser( + IOUtils.toString(Objects.requireNonNull(getClass().getResourceAsStream("/test.tesf")), Charset.defaultCharset())); parser.registerFunction("test", new FunctionBuilder() { @Override diff --git a/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java b/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java index b5a1f408f..175ec60af 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java +++ b/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java @@ -14,10 +14,15 @@ import java.util.concurrent.atomic.AtomicReference; public class Context { - private final Map, Properties> map = new HashMap<>(); - private final AtomicReference list = new AtomicReference<>(new Properties[size.get()]); private static final AtomicInteger size = new AtomicInteger(0); private static final Map, PropertyKey> properties = new HashMap<>(); + private final Map, Properties> map = new HashMap<>(); + private final AtomicReference list = new AtomicReference<>(new Properties[size.get()]); + + @SuppressWarnings("unchecked") + public static PropertyKey create(Class clazz) { + return (PropertyKey) properties.computeIfAbsent(clazz, c -> new PropertyKey<>(size.getAndIncrement(), clazz)); + } @SuppressWarnings("unchecked") public T get(Class clazz) { @@ -33,11 +38,6 @@ public class Context { return this; } - @SuppressWarnings("unchecked") - public static PropertyKey create(Class clazz) { - return (PropertyKey) properties.computeIfAbsent(clazz, c -> new PropertyKey<>(size.getAndIncrement(), clazz)); - } - public Context put(PropertyKey key, T properties) { list.updateAndGet(p -> { if(p.length == size.get()) return p; diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/GeometryUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/GeometryUtil.java index 6bb21b3df..25984257f 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/GeometryUtil.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/GeometryUtil.java @@ -7,7 +7,7 @@ import com.dfsek.terra.api.util.vector.Vector3Int; public final class GeometryUtil { private GeometryUtil() { - + } public static void sphere(Vector3Int origin, int radius, Consumer action) { diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java index d47cfdc05..c1ddf92d6 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java @@ -22,6 +22,11 @@ public final class Pair { private final L left; private final R right; + private Pair(L left, R right) { + this.left = left; + this.right = right; + } + public static Function, Pair> mapLeft(Function function) { return pair -> of(function.apply(pair.left), pair.right); } @@ -54,11 +59,6 @@ public final class Pair { return pair -> pair.left; } - private Pair(L left, R right) { - this.left = left; - this.right = right; - } - @Contract("_, _ -> new") public static Pair of(L1 left, R1 right) { return new Pair<>(left, right); @@ -96,55 +96,6 @@ public final class Pair { return Objects.equals(this.left, that.left) && Objects.equals(this.right, that.right); } - public static class Mutable { - private L left; - private R right; - - private Mutable(L left, R right) { - this.left = left; - this.right = right; - } - - @NotNull - @Contract("_, _ -> new") - public static Pair.Mutable of(L1 left, R1 right) { - return new Mutable<>(left, right); - } - - @Contract("-> new") - public Pair immutable() { - return Pair.of(left, right); - } - - public L getLeft() { - return left; - } - - public void setLeft(L left) { - this.left = left; - } - - public R getRight() { - return right; - } - - public void setRight(R right) { - this.right = right; - } - - @Override - public int hashCode() { - return Objects.hash(left, right); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof Mutable that)) return false; - - return Objects.equals(this.left, that.left) && Objects.equals(this.right, that.right); - } - } - public Pair apply(BiConsumer consumer) { consumer.accept(this.left, this.right); return this; @@ -154,4 +105,54 @@ public final class Pair { public String toString() { return String.format("{%s,%s}", left, right); } + + + public static class Mutable { + private L left; + private R right; + + private Mutable(L left, R right) { + this.left = left; + this.right = right; + } + + @NotNull + @Contract("_, _ -> new") + public static Pair.Mutable of(L1 left, R1 right) { + return new Mutable<>(left, right); + } + + @Contract("-> new") + public Pair immutable() { + return Pair.of(left, right); + } + + public L getLeft() { + return left; + } + + public void setLeft(L left) { + this.left = left; + } + + public R getRight() { + return right; + } + + public void setRight(R right) { + this.right = right; + } + + @Override + public int hashCode() { + return Objects.hash(left, right); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Mutable that)) return false; + + return Objects.equals(this.left, that.left) && Objects.equals(this.right, that.right); + } + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index cfa5a78c0..01ffbda70 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -97,7 +97,7 @@ public interface BiomeProvider { } return new CachingBiomeProvider(this); } - + default int resolution() { return 1; diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index fa3847a23..fff67f75a 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -30,12 +30,12 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { .initialCapacity(98304) .maximumSize(98304) // 1 full chunk (high res) .build(vec -> delegate.getBiome(vec.x * res, vec.y * res, vec.z * res, vec.seed)); - + this.baseCache = Caffeine .newBuilder() .maximumSize(256) // 1 full chunk (high res) .build(vec -> delegate.getBaseBiome(vec.x * res, vec.z * res, vec.seed)); - + } @Override @@ -80,6 +80,8 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { return 31 * code + ((int) (seed ^ (seed >>> 32))); } } + + private record SeededVector2(int x, int z, long seed) { @Override public boolean equals(Object obj) { diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java index 2f5cf9d19..c92ca2311 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -38,7 +38,7 @@ public class Column { this.max = max; this.min = min; } - + public int getX() { return x; diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/util/Interceptors.java b/common/api/src/main/java/com/dfsek/terra/api/world/util/Interceptors.java index c608ea4d9..4b98c8b34 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/util/Interceptors.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/util/Interceptors.java @@ -4,9 +4,9 @@ public final class Interceptors { private static final ReadInterceptor READ_THROUGH = ((x, y, z, world) -> world.getBlockState(x, y, z)); private static final WriteInterceptor WRITE_THROUGH = ((x, y, z, block, world, physics) -> world.setBlockState(x, y, z, block, physics)); - + private Interceptors() { - + } public static ReadInterceptor readThrough() { diff --git a/common/api/src/test/java/util/ColumnTest.java b/common/api/src/test/java/util/ColumnTest.java index 7ba140683..06f4a03e4 100644 --- a/common/api/src/test/java/util/ColumnTest.java +++ b/common/api/src/test/java/util/ColumnTest.java @@ -86,17 +86,17 @@ public class ColumnTest { public int getMaxY() { return max; } - + @Override public int getX() { return 0; } - + @Override public int getZ() { return 0; } - + @Override public T get(int y) { return p.apply(y); diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java index 9061b8d0c..84f2fb382 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java @@ -231,7 +231,8 @@ public class ConfigPackImpl implements ConfigPack { ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate(); selfLoader.load(packPostTemplate, packManifest); - seededBiomeProvider = template.getBiomeCache() ? packPostTemplate.getProviderBuilder().caching() : packPostTemplate.getProviderBuilder(); + seededBiomeProvider = + template.getBiomeCache() ? packPostTemplate.getProviderBuilder().caching() : packPostTemplate.getProviderBuilder(); checkDeadEntries(); } diff --git a/common/implementation/base/src/test/java/registry/RegistryTest.java b/common/implementation/base/src/test/java/registry/RegistryTest.java index b11e123b6..3f17a1776 100644 --- a/common/implementation/base/src/test/java/registry/RegistryTest.java +++ b/common/implementation/base/src/test/java/registry/RegistryTest.java @@ -50,7 +50,7 @@ public class RegistryTest { test.registerChecked(RegistryKey.parse("test:test"), "bazinga2"); fail("Shouldn't be able to re-register with #registerChecked!"); } catch(DuplicateEntryException ignore) { - + } } @@ -66,7 +66,7 @@ public class RegistryTest { test.register(RegistryKey.parse("test:test"), "bazinga2"); fail("Shouldn't be able to re-register in CheckedRegistry!"); } catch(DuplicateEntryException ignore) { - + } } @@ -90,7 +90,7 @@ public class RegistryTest { test.getByID("test"); fail("Shouldn't be able to get with ambiguous ID!"); } catch(IllegalArgumentException ignore) { - + } } } diff --git a/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java index 244bef568..301f276fa 100644 --- a/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java +++ b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java @@ -84,7 +84,7 @@ public class BootstrapAddonLoader implements BootstrapBaseAddon bootstrapAddons = Files.walk(bootstrapFolder, 1, FileVisitOption.FOLLOW_LINKS)) { return bootstrapAddons.filter(path -> path.toFile().isFile()) .filter(path -> path.toFile().canRead()) @@ -96,6 +96,7 @@ public class BootstrapAddonLoader implements BootstrapBaseAddon delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))); + ResourceKey delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("terra", + NMSBiomeInjector.createBiomeID( + pack, key))); BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform); biomeRegistry.register(delegateKey, platform, Lifecycle.stable()); @@ -73,28 +75,35 @@ public class AwfulBukkitHacks { terraBiomeMap .forEach((vb, terraBiomes) -> NMSBiomeInjector.getEntry(biomeRegistry, vb) - .ifPresentOrElse( - vanilla -> terraBiomes - .forEach(tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb) - .ifPresentOrElse( - terra -> { - LOGGER.debug(vanilla.unwrapKey().orElseThrow().location() + - " (vanilla for " + - terra.unwrapKey().orElseThrow().location() + - ": " + - vanilla.tags().toList()); - - vanilla.tags() - .forEach( - tag -> collect - .computeIfAbsent(tag, - t -> new ArrayList<>()) - .add(terra)); - }, - () -> LOGGER.error( - "No such biome: {}", - tb))), - () -> LOGGER.error("No vanilla biome: {}", vb))); + .ifPresentOrElse( + vanilla -> terraBiomes + .forEach(tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb) + .ifPresentOrElse( + terra -> { + LOGGER.debug( + vanilla.unwrapKey() + .orElseThrow() + .location() + + " (vanilla for " + + terra.unwrapKey() + .orElseThrow() + .location() + + ": " + + vanilla.tags() + .toList()); + + vanilla.tags() + .forEach( + tag -> collect + .computeIfAbsent( + tag, + t -> new ArrayList<>()) + .add(terra)); + }, + () -> LOGGER.error( + "No such biome: {}", + tb))), + () -> LOGGER.error("No vanilla biome: {}", vb))); biomeRegistry.resetTags(); // clearTags biomeRegistry.bindTags(ImmutableMap.copyOf(collect)); // populateTags diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java index bf42448b2..6271e4632 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java @@ -1,33 +1,17 @@ package com.dfsek.terra.bukkit.nms.v1_18_R2; -import com.google.common.collect.ImmutableMap; -import com.mojang.serialization.Lifecycle; import net.minecraft.core.Holder; -import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; -import net.minecraft.core.WritableRegistry; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSpecialEffects; -import org.bukkit.NamespacedKey; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Objects; import java.util.Optional; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; -import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; -import com.dfsek.terra.registry.master.ConfigRegistry; public class NMSBiomeInjector { @@ -45,33 +29,32 @@ public class NMSBiomeInjector { builder.biomeCategory(Reflection.BIOME.getBiomeCategory(vanilla)) .precipitation(vanilla.getPrecipitation()) // getPrecipitation - .mobSpawnSettings(vanilla.getMobSettings()) - .generationSettings(vanilla.getGenerationSettings()) - .temperature(vanilla.getBaseTemperature()) - .downfall(vanilla.getDownfall()); - - + .mobSpawnSettings(vanilla.getMobSettings()) + .generationSettings(vanilla.getGenerationSettings()) + .temperature(vanilla.getBaseTemperature()) + .downfall(vanilla.getDownfall()); + BiomeSpecialEffects.Builder effects = new BiomeSpecialEffects.Builder(); - + effects.grassColorModifier(vanilla.getSpecialEffects().getGrassColorModifier()); - + VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - + effects.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) - + .waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) - + .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) - + .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())); - + if(vanillaBiomeProperties.getFoliageColor() == null) { vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride); } else { effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor()); } - + if(vanillaBiomeProperties.getGrassColor() == null) { vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride); } else { @@ -83,7 +66,7 @@ public class NMSBiomeInjector { vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound); vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic); vanilla.getAmbientParticle().ifPresent(effects::ambientParticle); - + builder.specialEffects(effects.build()); return builder.build(); // build() diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java index 2b292142f..395ea949c 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java @@ -49,17 +49,14 @@ import com.dfsek.terra.api.world.info.WorldProperties; public class NMSChunkGeneratorDelegate extends ChunkGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class); + private static final Lazy> EMPTY = Lazy.lazy(List::of); private final NMSBiomeProvider biomeSource; private final com.dfsek.terra.api.world.chunk.generation.ChunkGenerator delegate; - private final ChunkGenerator vanilla; private final ConfigPack pack; - private final long seed; - private final Map>> ringPositions = new Object2ObjectArrayMap<>(); - private static final Lazy> EMPTY = Lazy.lazy(List::of); - + private volatile boolean rings = false; public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) { super(Registries.structureSet(), Optional.empty(), biomeProvider, biomeProvider, seed); @@ -71,13 +68,15 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { } @Override - public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull BiomeManager biomeAccess, @NotNull StructureFeatureManager structureAccessor, + public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull BiomeManager biomeAccess, + @NotNull StructureFeatureManager structureAccessor, @NotNull ChunkAccess chunk, GenerationStep.@NotNull Carving generationStep) { // no-op } @Override - public void applyBiomeDecoration(@NotNull WorldGenLevel world, @NotNull ChunkAccess chunk, @NotNull StructureFeatureManager structureAccessor) { + public void applyBiomeDecoration(@NotNull WorldGenLevel world, @NotNull ChunkAccess chunk, + @NotNull StructureFeatureManager structureAccessor) { vanilla.applyBiomeDecoration(world, chunk, structureAccessor); } @@ -87,7 +86,8 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { } @Override - public @NotNull CompletableFuture fillFromNoise(@NotNull Executor executor, @NotNull Blender blender, @NotNull StructureFeatureManager structureAccessor, + public @NotNull CompletableFuture fillFromNoise(@NotNull Executor executor, @NotNull Blender blender, + @NotNull StructureFeatureManager structureAccessor, @NotNull ChunkAccess chunk) { return vanilla.fillFromNoise(executor, blender, structureAccessor, chunk); } @@ -161,8 +161,6 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { return ringPositions.getOrDefault(concentricringsstructureplacement, EMPTY).value(); } - private volatile boolean rings = false; - @Override public synchronized void ensureStructuresGenerated() { if(!this.rings) { diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInjectListener.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInjectListener.java index 46f4a64c0..55408a136 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInjectListener.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInjectListener.java @@ -25,15 +25,16 @@ public class NMSInjectListener implements Listener { @EventHandler public void onWorldInit(WorldInitEvent event) { - if (!INJECTED.contains(event.getWorld()) && event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) { + if(!INJECTED.contains(event.getWorld()) && + event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) { INJECT_LOCK.lock(); INJECTED.add(event.getWorld()); LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName()); CraftWorld craftWorld = (CraftWorld) event.getWorld(); ServerLevel serverWorld = craftWorld.getHandle(); - + ConfigPack pack = bukkitChunkGeneratorWrapper.getPack(); - + ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator(); NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), vanilla.getBiomeSource(), craftWorld.getSeed()); NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()); diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/Reflection.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/Reflection.java index 53e9e80f9..9e226cb8d 100644 --- a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/Reflection.java +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/Reflection.java @@ -15,18 +15,21 @@ public class Reflection { static { ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar(); - ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper, Reflection.class.getClassLoader()); + ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper, + Reflection.class.getClassLoader()); MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class); BIOME = reflectionProxyFactory.reflectionProxy(BiomeProxy.class); } + @Proxies(MappedRegistry.class) public interface MappedRegistryProxy { @FieldSetter("frozen") void setFrozen(MappedRegistry instance, boolean frozen); } + @Proxies(Biome.class) public interface BiomeProxy { @FieldGetter("biomeCategory") diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/AwfulBukkitHacks.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/AwfulBukkitHacks.java index bfda736e2..3bce51cdd 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/AwfulBukkitHacks.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/AwfulBukkitHacks.java @@ -1,7 +1,5 @@ package com.dfsek.terra.bukkit.nms.v1_19_R1; -import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; -import com.dfsek.terra.registry.master.ConfigRegistry; import com.google.common.collect.ImmutableMap; import com.mojang.serialization.Lifecycle; import net.minecraft.core.Holder; @@ -17,7 +15,15 @@ import org.bukkit.NamespacedKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; +import com.dfsek.terra.registry.master.ConfigRegistry; + public class AwfulBukkitHacks { private static final Logger LOGGER = LoggerFactory.getLogger(AwfulBukkitHacks.class); @@ -39,10 +45,11 @@ public class AwfulBukkitHacks { Biome platform = NMSBiomeInjector.createBiome( biome, Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)) // get - ); + ); ResourceKey delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, - new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))); + new ResourceLocation("terra", + NMSBiomeInjector.createBiomeID(pack, key))); BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform); biomeRegistry.register(delegateKey, platform, Lifecycle.stable()); @@ -62,35 +69,42 @@ public class AwfulBukkitHacks { Map, List>> collect = biomeRegistry .getTags() // streamKeysAndEntries .collect(HashMap::new, - (map, pair) -> - map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), - HashMap::putAll); + (map, pair) -> + map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), + HashMap::putAll); terraBiomeMap .forEach((vb, terraBiomes) -> - NMSBiomeInjector.getEntry(biomeRegistry, vb) - .ifPresentOrElse( - vanilla -> terraBiomes - .forEach(tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb) - .ifPresentOrElse( - terra -> { - LOGGER.debug(vanilla.unwrapKey().orElseThrow().location() + - " (vanilla for " + - terra.unwrapKey().orElseThrow().location() + - ": " + - vanilla.tags().toList()); - - vanilla.tags() - .forEach( - tag -> collect - .computeIfAbsent(tag, - t -> new ArrayList<>()) - .add(terra)); - }, - () -> LOGGER.error( - "No such biome: {}", - tb))), - () -> LOGGER.error("No vanilla biome: {}", vb))); + NMSBiomeInjector.getEntry(biomeRegistry, vb) + .ifPresentOrElse( + vanilla -> terraBiomes + .forEach(tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb) + .ifPresentOrElse( + terra -> { + LOGGER.debug( + vanilla.unwrapKey() + .orElseThrow() + .location() + + " (vanilla for " + + terra.unwrapKey() + .orElseThrow() + .location() + + ": " + + vanilla.tags() + .toList()); + + vanilla.tags() + .forEach( + tag -> collect + .computeIfAbsent( + tag, + t -> new ArrayList<>()) + .add(terra)); + }, + () -> LOGGER.error( + "No such biome: {}", + tb))), + () -> LOGGER.error("No vanilla biome: {}", vb))); biomeRegistry.resetTags(); biomeRegistry.bindTags(ImmutableMap.copyOf(collect)); diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java index 88f224f4b..8a5d56c35 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeInjector.java @@ -1,33 +1,17 @@ package com.dfsek.terra.bukkit.nms.v1_19_R1; -import com.google.common.collect.ImmutableMap; -import com.mojang.serialization.Lifecycle; import net.minecraft.core.Holder; -import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; -import net.minecraft.core.WritableRegistry; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSpecialEffects; -import org.bukkit.NamespacedKey; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Objects; import java.util.Optional; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; -import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; -import com.dfsek.terra.registry.master.ConfigRegistry; public class NMSBiomeInjector { diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeProvider.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeProvider.java index 36433165b..0c5a8ef06 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeProvider.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSBiomeProvider.java @@ -18,7 +18,11 @@ public class NMSBiomeProvider extends BiomeSource { private final Registry biomeRegistry = Registries.biomeRegistry(); public NMSBiomeProvider(BiomeProvider delegate, long seed) { - super(delegate.stream().map(biome -> Registries.biomeRegistry().getHolderOrThrow(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext().get(NMSBiomeInfo.class).biomeKey()))); + super(delegate.stream() + .map(biome -> Registries.biomeRegistry() + .getHolderOrThrow(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext() + .get(NMSBiomeInfo.class) + .biomeKey()))); this.delegate = delegate; this.seed = seed; } @@ -30,6 +34,9 @@ public class NMSBiomeProvider extends BiomeSource { @Override public @NotNull Holder getNoiseBiome(int x, int y, int z, @NotNull Sampler sampler) { - return biomeRegistry.getHolderOrThrow(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome()).getContext().get(NMSBiomeInfo.class).biomeKey()); + return biomeRegistry.getHolderOrThrow(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed) + .getPlatformBiome()).getContext() + .get(NMSBiomeInfo.class) + .biomeKey()); } } diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java index e20a5da0b..81933be0f 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSChunkGeneratorDelegate.java @@ -55,6 +55,8 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { private final ConfigPack pack; private final long seed; + private final Map>> ringPositions = new Object2ObjectArrayMap<>(); + private volatile boolean rings = false; public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) { super(Registries.structureSet(), Optional.empty(), biomeProvider); @@ -137,19 +139,16 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { .getHandle()).getState(); } return new NoiseColumn(getMinY(), array); - + */ return vanilla.getBaseColumn(x, z, world, noiseConfig); } - + @Override public void addDebugScreenInfo(@NotNull List text, @NotNull RandomState noiseConfig, @NotNull BlockPos pos) { - + } - private volatile boolean rings = false; - private final Map>> ringPositions = new Object2ObjectArrayMap<>(); - @Override public void ensureStructuresGenerated(@NotNull RandomState noiseConfig) { if(!this.rings) { @@ -161,7 +160,8 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { } @Override - public List getRingPositionsFor(@NotNull ConcentricRingsStructurePlacement structurePlacement, @NotNull RandomState noiseConfig) { + public List getRingPositionsFor(@NotNull ConcentricRingsStructurePlacement structurePlacement, + @NotNull RandomState noiseConfig) { ensureStructuresGenerated(noiseConfig); return ringPositions.get(structurePlacement).value(); } @@ -179,13 +179,15 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator { } } - if (match) { - if (holder.placement() instanceof ConcentricRingsStructurePlacement concentricringsstructureplacement) { - this.ringPositions.put(concentricringsstructureplacement, Lazy.lazy(() -> this.generateRingPositions(holder, noiseConfig, concentricringsstructureplacement))); + if(match) { + if(holder.placement() instanceof ConcentricRingsStructurePlacement concentricringsstructureplacement) { + this.ringPositions.put(concentricringsstructureplacement, Lazy.lazy( + () -> this.generateRingPositions(holder, noiseConfig, concentricringsstructureplacement))); } } }); } + private List generateRingPositions(StructureSet holder, RandomState randomstate, ConcentricRingsStructurePlacement concentricringsstructureplacement) { // Spigot if(concentricringsstructureplacement.count() == 0) { diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSInjectListener.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSInjectListener.java index c647afbd5..d57689a9b 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSInjectListener.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/NMSInjectListener.java @@ -25,15 +25,16 @@ public class NMSInjectListener implements Listener { @EventHandler public void onWorldInit(WorldInitEvent event) { - if (!INJECTED.contains(event.getWorld()) && event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) { + if(!INJECTED.contains(event.getWorld()) && + event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) { INJECT_LOCK.lock(); INJECTED.add(event.getWorld()); LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName()); CraftWorld craftWorld = (CraftWorld) event.getWorld(); ServerLevel serverWorld = craftWorld.getHandle(); - + ConfigPack pack = bukkitChunkGeneratorWrapper.getPack(); - + ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator(); NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed()); NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()); diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/Reflection.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/Reflection.java index 157157005..8fa9a0b01 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/Reflection.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/Reflection.java @@ -12,11 +12,13 @@ public class Reflection { static { ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar(); - ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper, Reflection.class.getClassLoader()); + ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper, + Reflection.class.getClassLoader()); MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class); } + @Proxies(MappedRegistry.class) public interface MappedRegistryProxy { @FieldSetter("frozen") diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/Registries.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/Registries.java index 622589a77..f1cdc645e 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/Registries.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/Registries.java @@ -16,8 +16,8 @@ public class Registries { return dedicatedserver .registryAccess() .registryOrThrow( // getRegistry - key - ); + key + ); } public static Registry biomeRegistry() { diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockState.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockState.java index 53cbc5e90..026f3dfc5 100644 --- a/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockState.java +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockState.java @@ -16,9 +16,9 @@ public class CLIBlockState implements BlockState { public CLIBlockState(String value) { this.value = value; if(value.contains("[")) { - + } else { - + } this.isAir = value.startsWith("minecraft:air"); this.nbt = new CompoundTag(); diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 85a829444..e07a43a58 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -25,7 +25,13 @@ dependencies { modImplementation("net.fabricmc:fabric-loader:${Versions.Fabric.fabricLoader}") - setOf("fabric-lifecycle-events-v1", "fabric-resource-loader-v0", "fabric-api-base", "fabric-command-api-v2", "fabric-networking-api-v1").forEach { apiModule -> + setOf( + "fabric-lifecycle-events-v1", + "fabric-resource-loader-v0", + "fabric-api-base", + "fabric-command-api-v2", + "fabric-networking-api-v1" + ).forEach { apiModule -> val module = fabricApi.module(apiModule, Versions.Fabric.fabricAPI) modImplementation(module) include(module) diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java index 21ed9870c..db98b73df 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java @@ -3,12 +3,13 @@ package com.dfsek.terra.fabric; import com.dfsek.terra.mod.MinecraftAddon; import com.dfsek.terra.mod.ModPlatform; -public class FabricAddon extends MinecraftAddon { +public class FabricAddon extends MinecraftAddon { + public FabricAddon(ModPlatform modPlatform) { super(modPlatform); } - + @Override public String getID() { return "terra-fabric"; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java index 403f8df56..54d03961e 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -32,7 +32,7 @@ public class FabricEntryPoint implements ModInitializer { private static final Logger logger = LoggerFactory.getLogger(FabricEntryPoint.class); private static final FabricPlatform TERRA_PLUGIN = new FabricPlatform(); - + @Override public void onInitialize() { logger.info("Initializing Terra Fabric mod..."); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricPlatform.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricPlatform.java index 6477407b4..2c85b86ee 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricPlatform.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricPlatform.java @@ -20,9 +20,6 @@ package com.dfsek.terra.fabric; import ca.solostudios.strata.Versions; import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.version.Version; - -import com.dfsek.terra.lifecycle.LifecyclePlatform; - import net.fabricmc.loader.api.FabricLoader; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -35,8 +32,7 @@ import java.util.stream.Stream; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; -import com.dfsek.terra.api.util.generic.Lazy; -import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.lifecycle.LifecyclePlatform; public class FabricPlatform extends LifecyclePlatform { @@ -59,6 +55,7 @@ public class FabricPlatform extends LifecyclePlatform { return Stream.empty(); }).collect(Collectors.toList()); } + @Override public @NotNull String platformName() { return "Fabric"; @@ -68,7 +65,7 @@ public class FabricPlatform extends LifecyclePlatform { public @NotNull File getDataFolder() { return new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra"); } - + @Override public BaseAddon getPlatformAddon() { return new FabricAddon(this); diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 5a8c1c837..1eee6098a 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -70,7 +70,7 @@ tasks { ) } } - + remapJar { inputFile.set(shadowJar.get().archiveFile) archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java index 1d0f44bc2..07f4dafc9 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/AwfulForgeHacks.java @@ -1,32 +1,22 @@ package com.dfsek.terra.forge; -import com.dfsek.terra.AbstractPlatform; - -import cpw.mods.cl.ModuleClassLoader; import net.minecraftforge.fml.loading.FMLLoader; import org.burningwave.core.classes.Classes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.lang.reflect.Field; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; import java.util.concurrent.atomic.AtomicReference; -import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Stream; +import com.dfsek.terra.AbstractPlatform; import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; @@ -73,7 +63,7 @@ public final class AwfulForgeHacks { } public static void loadAllTerraClasses() { - if (FMLLoader.isProduction()) { + if(FMLLoader.isProduction()) { try(JarFile jar = getTerraJar()) { jar.stream() .forEach(jarEntry -> { @@ -96,45 +86,52 @@ public final class AwfulForgeHacks { } } else { // Forgive me for what I'm about to do... - LOGGER.warn("I felt a great disturbance in the JVM, as if millions of class not found exceptions suddenly cried out in terror and were suddenly silenced."); + LOGGER.warn( + "I felt a great disturbance in the JVM, as if millions of class not found exceptions suddenly cried out in terror and" + + " were suddenly silenced."); ArrayList pathsToLoad = new ArrayList<>(); Path terraRoot = Path.of(System.getProperty("user.dir")).getParent().getParent().getParent(); Path commonRoot = terraRoot.resolve("common"); Path implementationRoot = commonRoot.resolve("implementation"); - + pathsToLoad.add(commonRoot.resolve("api")); pathsToLoad.add(implementationRoot.resolve("base")); pathsToLoad.add(implementationRoot.resolve("bootstrap-addon-loader")); - for (Path path : pathsToLoad) { + for(Path path : pathsToLoad) { try { Path target = path.resolve("build").resolve("classes").resolve("java").resolve("main"); - BootstrapAddonClassLoader cl = new BootstrapAddonClassLoader(new URL[] { path.toUri().toURL()}); - - Classes.Loaders omegaCL = Classes.Loaders.create(); + BootstrapAddonClassLoader cl = new BootstrapAddonClassLoader(new URL[]{ path.toUri().toURL() }); + + Classes.Loaders omegaCL = Classes.Loaders.create(); Files.walk(target, Integer.MAX_VALUE, FileVisitOption.FOLLOW_LINKS) - .filter(it -> it.getFileName().toString().endsWith(".class")) - .map(Path::toFile) - .forEach(it -> { - String name = it.getAbsolutePath().replace(target + "/", "").replace('\\', '.').replace('/', '.'); - name = name.substring(0, name.length() - 6); - LOGGER.info("Loading class {}", name); - try { - Class.forName(name); - } catch(ClassNotFoundException e) { - try { - String pathToJar = cl.loadClass(name).getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); - - cl.addURL(new URL("jar:file:" + pathToJar + "!/")); - Class newClassLoad = Class.forName(name, true, cl); - omegaCL.loadOrDefine(newClassLoad, AbstractPlatform.class.getClassLoader()); - } catch(ClassNotFoundException | URISyntaxException | IOException ex) { - throw new RuntimeException(ex); - } - - } - }); + .filter(it -> it.getFileName().toString().endsWith(".class")) + .map(Path::toFile) + .forEach(it -> { + String name = it.getAbsolutePath().replace(target + "/", "").replace('\\', '.').replace('/', '.'); + name = name.substring(0, name.length() - 6); + LOGGER.info("Loading class {}", name); + try { + Class.forName(name); + } catch(ClassNotFoundException e) { + try { + String pathToJar = cl.loadClass(name) + .getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI() + .getPath(); + + cl.addURL(new URL("jar:file:" + pathToJar + "!/")); + Class newClassLoad = Class.forName(name, true, cl); + omegaCL.loadOrDefine(newClassLoad, AbstractPlatform.class.getClassLoader()); + } catch(ClassNotFoundException | URISyntaxException | IOException ex) { + throw new RuntimeException(ex); + } + + } + }); } catch(IOException e) { throw new IllegalStateException("Could not load all Terra classes", e); } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java index 5b6e82ec1..e742610cf 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAddon.java @@ -3,12 +3,13 @@ package com.dfsek.terra.forge; import com.dfsek.terra.mod.MinecraftAddon; import com.dfsek.terra.mod.ModPlatform; -public class ForgeAddon extends MinecraftAddon { +public class ForgeAddon extends MinecraftAddon { + public ForgeAddon(ModPlatform modPlatform) { super(modPlatform); } - + @Override public String getID() { return "terra-forge"; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java index d9ad54d81..b342e5a11 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeEntryPoint.java @@ -43,28 +43,24 @@ import com.dfsek.terra.mod.data.Codecs; @Mod("terra") @EventBusSubscriber(bus = Bus.MOD) public class ForgeEntryPoint { - private final RegistrySanityCheck sanityCheck = new RegistrySanityCheck(); - + public static final String MODID = "terra"; + private static final Logger logger = LoggerFactory.getLogger(ForgeEntryPoint.class); + private static final ForgePlatform TERRA_PLUGIN; static { AwfulForgeHacks.loadAllTerraClasses(); TERRA_PLUGIN = new ForgePlatform(); } - - public static final String MODID = "terra"; - - private static final Logger logger = LoggerFactory.getLogger(ForgeEntryPoint.class); - - private static final ForgePlatform TERRA_PLUGIN; - - public static ForgePlatform getPlatform() { - return TERRA_PLUGIN; - } + private final RegistrySanityCheck sanityCheck = new RegistrySanityCheck(); public ForgeEntryPoint() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); modEventBus.register(this); } + public static ForgePlatform getPlatform() { + return TERRA_PLUGIN; + } + public static void initialize(RegisterHelper helper) { getPlatform().getEventManager().callEvent( new PlatformInitializationEvent()); @@ -75,10 +71,12 @@ public class ForgeEntryPoint { public void registerBiomes(RegisterEvent event) { event.register(Keys.BLOCKS, helper -> sanityCheck.progress(RegistryStep.BLOCK, () -> logger.debug("Block registration detected."))); event.register(Keys.BIOMES, helper -> sanityCheck.progress(RegistryStep.BIOME, () -> initialize(helper))); - event.register(Registry.WORLD_PRESET_KEY, helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> TERRA_PLUGIN.registerWorldTypes(helper::register))); + event.register(Registry.WORLD_PRESET_KEY, + helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> TERRA_PLUGIN.registerWorldTypes(helper::register))); - event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER)); + event.register(Registry.CHUNK_GENERATOR_KEY, + helper -> helper.register(new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER)); event.register(Registry.BIOME_SOURCE_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE)); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java index 60cd727f4..2d8b51c9a 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java @@ -43,33 +43,33 @@ import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; public class ForgePlatform extends ModPlatform { private static final Logger LOGGER = LoggerFactory.getLogger(ForgePlatform.class); private final Lazy dataFolder = Lazy.lazy(() -> new File("./config/Terra")); - + public ForgePlatform() { CommonPlatform.initialize(this); load(); } - + @Override public MinecraftServer getServer() { return ServerLifecycleHooks.getCurrentServer(); } - + @Override public boolean reload() { getTerraConfig().load(this); getRawConfigRegistry().clear(); boolean succeed = getRawConfigRegistry().loadAll(this); - + MinecraftServer server = getServer(); - - if (server != null) { + + if(server != null) { server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { LOGGER.warn("Failed to execute reload", throwable); return null; }).join(); //BiomeUtil.registerBiomes(); server.getWorlds().forEach(world -> { - if (world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { + if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) { getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { chunkGeneratorWrapper.setPack(pack); LOGGER.info("Replaced pack in chunk generator for world {}", world); @@ -79,34 +79,35 @@ public class ForgePlatform extends ModPlatform { } return succeed; } - + @Override protected Iterable platformAddon() { List addons = new ArrayList<>(); - + super.platformAddon().forEach(addons::add); - + String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); try { addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft")); - } catch (ParseException e) { + } catch(ParseException e) { try { addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft")); - } catch (ParseException ex) { + } catch(ParseException ex) { LOGGER.warn("Failed to parse Minecraft version", e); } } - + FMLLoader.getLoadingModList().getMods().forEach(mod -> { String id = mod.getModId(); - if (id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; - Version version = Versions.getVersion(mod.getVersion().getMajorVersion(), mod.getVersion().getMinorVersion(), mod.getVersion().getIncrementalVersion()); + if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; + Version version = Versions.getVersion(mod.getVersion().getMajorVersion(), mod.getVersion().getMinorVersion(), + mod.getVersion().getIncrementalVersion()); addons.add(new EphemeralAddon(version, "forge:" + id)); }); - + return addons; } - + @Override public @NotNull String platformName() { return "Forge"; @@ -116,7 +117,7 @@ public class ForgePlatform extends ModPlatform { public @NotNull File getDataFolder() { return dataFolder.value(); } - + @Override public BaseAddon getPlatformAddon() { return new ForgeAddon(this); diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java index 41a113f9e..1bdffca2e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/lifecycle/NoiseConfigMixin.java @@ -24,7 +24,15 @@ public class NoiseConfigMixin { @Final private long legacyWorldSeed; - @Redirect(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At(value = "NEW", target = "(Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Ljava/util/List;)Lnet/minecraft/world/biome/source/util/MultiNoiseUtil$MultiNoiseSampler;")) + @Redirect(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", + at = @At(value = "NEW", + target = "(Lnet/minecraft/world/gen/densityfunction/DensityFunction;" + + "Lnet/minecraft/world/gen/densityfunction/DensityFunction;" + + "Lnet/minecraft/world/gen/densityfunction/DensityFunction;" + + "Lnet/minecraft/world/gen/densityfunction/DensityFunction;" + + "Lnet/minecraft/world/gen/densityfunction/DensityFunction;" + + "Lnet/minecraft/world/gen/densityfunction/DensityFunction;Ljava/util/List;)" + + "Lnet/minecraft/world/biome/source/util/MultiNoiseUtil$MultiNoiseSampler;")) private MultiNoiseSampler t(DensityFunction densityFunction, DensityFunction densityFunction2, DensityFunction densityFunction3, DensityFunction densityFunction4, DensityFunction densityFunction5, DensityFunction densityFunction6, List list) { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java index 1678fd4a8..177a63f8e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/util/BiomeUtil.java @@ -1,8 +1,5 @@ package com.dfsek.terra.forge.util; -import com.dfsek.terra.mod.config.VanillaBiomeProperties; -import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; @@ -22,6 +19,8 @@ import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.forge.ForgeEntryPoint; import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; import com.dfsek.terra.mod.util.MinecraftUtil; @@ -32,7 +31,7 @@ public final class BiomeUtil { private BiomeUtil() { } - + public static void registerBiomes(RegisterHelper helper) { logger.info("Registering biomes..."); @@ -51,29 +50,41 @@ public final class BiomeUtil { * @param pack The ConfigPack this biome belongs to. */ private static void registerBiome(Biome biome, ConfigPack pack, - com.dfsek.terra.api.registry.key.RegistryKey id, RegisterHelper helper) { - RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()) .get(BuiltinRegistries.BIOME); + com.dfsek.terra.api.registry.key.RegistryKey id, + RegisterHelper helper) { + RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(BuiltinRegistries.BIOME); if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); } else { VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - - net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value(), vanillaBiomeProperties); + + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, + ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla) + .value(), + vanillaBiomeProperties); Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); if(ForgeRegistries.BIOMES.containsKey(identifier)) { - ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow()); + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier) + .orElseThrow() + .getKey() + .orElseThrow()); } else { helper.register(MinecraftUtil.registerKey(identifier).getValue(), minecraftBiome); - ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow()); + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier) + .orElseThrow() + .getKey() + .orElseThrow()); } Map villagerMap = VillagerTypeAccessor.getBiomeTypeToIdMap(); - villagerMap.put(RegistryKey.of(Registry.BIOME_KEY, identifier), Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(), villagerMap.getOrDefault(vanilla, VillagerType.PLAINS))); + villagerMap.put(RegistryKey.of(Registry.BIOME_KEY, identifier), + Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(), + villagerMap.getOrDefault(vanilla, VillagerType.PLAINS))); MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); } diff --git a/platforms/forge/src/main/resources/META-INF/mods.toml b/platforms/forge/src/main/resources/META-INF/mods.toml index ae314f8d3..ff9e92ada 100644 --- a/platforms/forge/src/main/resources/META-INF/mods.toml +++ b/platforms/forge/src/main/resources/META-INF/mods.toml @@ -1,7 +1,7 @@ modLoader = "javafml" loaderVersion = "[41,)" license = "GNU General Public License, v3.0" -issueTrackerURL="https://github.com/PolyhedralDev/Terra/issues" +issueTrackerURL = "https://github.com/PolyhedralDev/Terra/issues" [[mods]] modId = "terra" diff --git a/platforms/forge/src/main/resources/pack.mcmeta b/platforms/forge/src/main/resources/pack.mcmeta index 3dc15cc76..5e44f2fa1 100644 --- a/platforms/forge/src/main/resources/pack.mcmeta +++ b/platforms/forge/src/main/resources/pack.mcmeta @@ -1,6 +1,6 @@ { - "pack": { - "description": "Terra Resources", - "pack_format": 9 - } + "pack": { + "description": "Terra Resources", + "pack_format": 9 + } } diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index 9bc9426db..25c1c470e 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -4,7 +4,7 @@ "package": "com.dfsek.terra.forge.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "lifecycle.NoiseConfigMixin" + "lifecycle.NoiseConfigMixin" ], "client": [ ], diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java index 50fd7a428..fa1214389 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/MinecraftAddon.java @@ -61,10 +61,10 @@ public abstract class MinecraftAddon implements BaseAddon { .getHandler(FunctionalEventHandler.class) .register(this, ConfigurationLoadEvent.class) .then(event -> { - if(event.is(Biome.class)) { - event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties())); - } - }) + if(event.is(Biome.class)) { + event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties())); + } + }) .global(); } 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 e6a7d9054..4a6efa188 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,17 +3,6 @@ package com.dfsek.terra.mod; import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.exception.LoadException; - -import com.dfsek.terra.api.handle.ItemHandle; -import com.dfsek.terra.api.handle.WorldHandle; -import com.dfsek.terra.mod.config.SpawnSettingsTemplate; - -import com.dfsek.terra.mod.handle.MinecraftItemHandle; - -import com.dfsek.terra.mod.handle.MinecraftWorldHandle; - -import com.dfsek.terra.mod.config.VillagerTypeTemplate; - import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnGroup; import net.minecraft.server.MinecraftServer; @@ -31,6 +20,7 @@ import net.minecraft.world.biome.BiomeParticleConfig; import net.minecraft.world.biome.SpawnSettings; import net.minecraft.world.biome.SpawnSettings.SpawnEntry; import net.minecraft.world.gen.WorldPreset; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Locale; @@ -38,6 +28,8 @@ import java.util.function.BiConsumer; import com.dfsek.terra.AbstractPlatform; import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.api.world.biome.PlatformBiome; import com.dfsek.terra.mod.config.BiomeAdditionsSoundTemplate; import com.dfsek.terra.mod.config.BiomeMoodSoundTemplate; @@ -49,17 +41,19 @@ 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; +import com.dfsek.terra.mod.handle.MinecraftItemHandle; +import com.dfsek.terra.mod.handle.MinecraftWorldHandle; import com.dfsek.terra.mod.util.PresetUtil; -import org.jetbrains.annotations.NotNull; - public abstract class ModPlatform extends AbstractPlatform { - public abstract MinecraftServer getServer(); - private final ItemHandle itemHandle = new MinecraftItemHandle(); private final WorldHandle worldHandle = new MinecraftWorldHandle(); + + public abstract MinecraftServer getServer(); public void registerWorldTypes(BiConsumer registerFunction) { getRawConfigRegistry() @@ -78,10 +72,12 @@ public abstract class ModPlatform extends AbstractPlatform { }) .registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase( Locale.ROOT))) - .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase( - Locale.ROOT))) - .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase( - Locale.ROOT))) + .registerLoader(GrassColorModifier.class, + (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase( + Locale.ROOT))) + .registerLoader(GrassColorModifier.class, + (type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase( + Locale.ROOT))) .registerLoader(BiomeParticleConfig.class, BiomeParticleConfigTemplate::new) .registerLoader(SoundEvent.class, SoundEventTemplate::new) .registerLoader(BiomeMoodSound.class, BiomeMoodSoundTemplate::new) @@ -101,12 +97,12 @@ public abstract class ModPlatform extends AbstractPlatform { if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure. return new ProtoPlatformBiome(identifier); } - + @Override protected Iterable platformAddon() { return List.of(getPlatformAddon()); } - + protected abstract BaseAddon getPlatformAddon(); @Override diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeAdditionsSoundTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeAdditionsSoundTemplate.java index 92e6dc7a7..e9d4a2038 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeAdditionsSoundTemplate.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeAdditionsSoundTemplate.java @@ -18,7 +18,7 @@ public class BiomeAdditionsSoundTemplate implements ObjectTemplate { @Override public BiomeMoodSound get() { - if (sound == null || soundCultivationTicks == null || soundSpawnRange == null || soundExtraDistance == null) { + if(sound == null || soundCultivationTicks == null || soundSpawnRange == null || soundExtraDistance == null) { return null; } else { return new BiomeMoodSound(sound, soundCultivationTicks, soundSpawnRange, soundExtraDistance); 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 5e2558412..538a80870 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 @@ -17,10 +17,10 @@ public class BiomeParticleConfigTemplate implements ObjectTemplate { @Override public MusicSound get() { - if (sound == null || minDelay == null || maxDelay == null || replaceCurrentMusic == null) { + if(sound == null || minDelay == null || maxDelay == null || replaceCurrentMusic == null) { return null; } else { return new MusicSound(sound, minDelay, maxDelay, replaceCurrentMusic); diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SoundEventTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SoundEventTemplate.java index f2ae58993..5e87dc21a 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SoundEventTemplate.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SoundEventTemplate.java @@ -18,9 +18,9 @@ public class SoundEventTemplate implements ObjectTemplate { @Override public SoundEvent get() { - if (id == null) { + if(id == null) { return null; - } else if (distanceToTravel == null) { + } else if(distanceToTravel == null) { return new SoundEvent(id); } else { return new SoundEvent(id, distanceToTravel); 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 25fae1481..9b72e579c 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 @@ -24,13 +24,13 @@ public class SpawnSettingsTemplate implements ObjectTemplate { @Override public SpawnSettings get() { SpawnSettings.Builder builder = new SpawnSettings.Builder(); - for (SpawnTypeConfig spawn : spawns) { + for(SpawnTypeConfig spawn : spawns) { builder.spawn(spawn.getGroup(), spawn.getEntry()); } - for (SpawnCostConfig cost: costs) { + for(SpawnCostConfig cost : costs) { builder.spawnCost(cost.getType(), cost.getMass(), cost.getGravity()); } - if (probability != null) { + if(probability != null) { builder.creatureSpawnProbability(probability); } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java index 429829267..b5b88a6b9 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java @@ -93,7 +93,7 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { public Integer getGrassColor() { return grassColor; } - + public Integer getFogColor() { return fogColor; } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VillagerTypeTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VillagerTypeTemplate.java index 235102dac..f8cce4832 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VillagerTypeTemplate.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VillagerTypeTemplate.java @@ -3,7 +3,6 @@ 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.EntityType; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.village.VillagerType; 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 36f774297..5f5dd615a 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 @@ -31,8 +31,8 @@ public final class Codecs { .getConfigRegistry() .get(id) .orElseThrow(() -> new IllegalArgumentException( - "No such config pack " + - id))))); + "No such config pack " + + id))))); public static final Codec TERRA_BIOME_SOURCE = RecordCodecBuilder .create(instance -> instance.group(RegistryOps.createRegistryCodec(Registry.BIOME_KEY) diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/VillagerTypeAccessor.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/VillagerTypeAccessor.java index acf269a11..477c0647b 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/VillagerTypeAccessor.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/access/VillagerTypeAccessor.java @@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.gen.Accessor; import java.util.Map; + @Mixin(VillagerType.class) public interface VillagerTypeAccessor { @Accessor("BIOME_TO_TYPE") diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java index ba73ff960..f29e6d259 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/BeeMoveGoalsUnsynchronizedRandomAccessFix.java @@ -20,7 +20,8 @@ import com.dfsek.terra.mod.CommonPlatform; MoveToFlowerGoal.class }) public class BeeMoveGoalsUnsynchronizedRandomAccessFix { - @Redirect(method = "", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;random:Lnet/minecraft/util/math/random/Random;")) + @Redirect(method = "", + at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;random:Lnet/minecraft/util/math/random/Random;")) public Random redirectRandomAccess(World instance) { return new CheckedRandom(CommonPlatform.get().getServer().getTicks()); // replace with new random seeded by tick time. } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java index 12d6a0732..f2ab4956a 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/fix/NetherFossilOptimization.java @@ -15,8 +15,9 @@ import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; /** * Disable fossil generation in Terra worlds, as they are very expensive due to consistently triggering cache misses. - * - * Currently, on Fabric, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in nether. + *

+ * Currently, on Fabric, Terra cannot be specified as a Nether generator. TODO: logic to turn fossils back on if chunk generator is in + * nether. */ @Mixin(NetherFossilStructure.class) public class NetherFossilOptimization { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java index 152e743da..69f91e6f6 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java @@ -1,7 +1,5 @@ package com.dfsek.terra.mod.util; -import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; - import net.minecraft.block.entity.LootableContainerBlockEntity; import net.minecraft.block.entity.MobSpawnerBlockEntity; import net.minecraft.block.entity.SignBlockEntity; @@ -10,7 +8,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryEntry; import net.minecraft.util.registry.RegistryKey; -import net.minecraft.village.VillagerType; import net.minecraft.world.WorldAccess; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome.Builder; @@ -69,18 +66,23 @@ public final class MinecraftUtil { TERRA_BIOME_MAP .forEach((vb, terraBiomes) -> biomes.getOrEmpty(vb) - .ifPresentOrElse(vanilla -> terraBiomes - .forEach(tb -> biomes.getOrEmpty(tb) - .ifPresentOrElse( - terra -> { - List> flowerFeatures = List.copyOf(vanilla.getGenerationSettings().getFlowerFeatures()); - logger.debug("Injecting flora into biome {} : {}", tb, flowerFeatures); - ((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures(flowerFeatures); - }, - () -> logger.error( - "No such biome: {}", - tb))), - () -> logger.error("No vanilla biome: {}", vb))); + .ifPresentOrElse(vanilla -> terraBiomes + .forEach(tb -> biomes.getOrEmpty(tb) + .ifPresentOrElse( + terra -> { + List> flowerFeatures = List.copyOf( + vanilla.getGenerationSettings() + .getFlowerFeatures()); + logger.debug("Injecting flora into biome" + + " {} : {}", tb, + flowerFeatures); + ((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures( + flowerFeatures); + }, + () -> logger.error( + "No such biome: {}", + tb))), + () -> logger.error("No vanilla biome: {}", vb))); } @@ -92,70 +94,73 @@ public final class MinecraftUtil { return RegistryKey.of(Registry.BIOME_KEY, identifier); } - public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla, VanillaBiomeProperties vanillaBiomeProperties) { + public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla, + VanillaBiomeProperties vanillaBiomeProperties) { GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); - + BiomeEffects.Builder effects = new BiomeEffects.Builder(); - + net.minecraft.world.biome.Biome.Builder builder = new Builder(); - + effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())) .grassColorModifier( - Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(), vanilla.getEffects().getGrassColorModifier())); - - if (vanillaBiomeProperties.getFoliageColor() == null) { + Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(), + vanilla.getEffects().getGrassColorModifier())); + + if(vanillaBiomeProperties.getFoliageColor() == null) { vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); } else { effects.foliageColor(vanillaBiomeProperties.getFoliageColor()); } - - if (vanillaBiomeProperties.getGrassColor() == null) { + + if(vanillaBiomeProperties.getGrassColor() == null) { vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); } else { effects.grassColor(vanillaBiomeProperties.getGrassColor()); } - - if (vanillaBiomeProperties.getParticleConfig() == null) { + + if(vanillaBiomeProperties.getParticleConfig() == null) { vanilla.getEffects().getParticleConfig().ifPresent(effects::particleConfig); } else { effects.particleConfig(vanillaBiomeProperties.getParticleConfig()); } - - if (vanillaBiomeProperties.getLoopSound() == null) { + + if(vanillaBiomeProperties.getLoopSound() == null) { vanilla.getEffects().getLoopSound().ifPresent(effects::loopSound); } else { effects.loopSound(vanillaBiomeProperties.getLoopSound()); } - - if (vanillaBiomeProperties.getMoodSound() == null) { + + if(vanillaBiomeProperties.getMoodSound() == null) { vanilla.getEffects().getMoodSound().ifPresent(effects::moodSound); } else { effects.moodSound(vanillaBiomeProperties.getMoodSound()); } - - if (vanillaBiomeProperties.getAdditionsSound() == null) { + + if(vanillaBiomeProperties.getAdditionsSound() == null) { vanilla.getEffects().getAdditionsSound().ifPresent(effects::additionsSound); } else { effects.additionsSound(vanillaBiomeProperties.getAdditionsSound()); } - - if (vanillaBiomeProperties.getMusic() == null) { + + if(vanillaBiomeProperties.getMusic() == null) { vanilla.getEffects().getMusic().ifPresent(effects::music); } else { effects.music(vanillaBiomeProperties.getMusic()); } - + builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation())); - + builder.temperature(Objects.requireNonNullElse(vanillaBiomeProperties.getTemperature(), vanilla.getTemperature())); - + builder.downfall(Objects.requireNonNullElse(vanillaBiomeProperties.getDownfall(), vanilla.getDownfall())); - builder.temperatureModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getTemperatureModifier(), ((BiomeAccessor)((Object)vanilla)).getWeather().temperatureModifier())); - + builder.temperatureModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getTemperatureModifier(), + ((BiomeAccessor) ((Object) vanilla)).getWeather().temperatureModifier())); + builder.spawnSettings(Objects.requireNonNullElse(vanillaBiomeProperties.getSpawnSettings(), vanilla.getSpawnSettings())); return builder 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 df1641f39..f4fd942c8 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 @@ -40,7 +40,7 @@ public class PresetUtil { Registry structureSetRegistry = BuiltinRegistries.STRUCTURE_SET; Registry noiseParametersRegistry = BuiltinRegistries.NOISE_PARAMETERS; Registry biomeRegistry = BuiltinRegistries.BIOME; - + RegistryEntry theNetherDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_NETHER); RegistryEntry netherChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.NETHER); @@ -57,19 +57,19 @@ public class PresetUtil { new NoiseChunkGenerator(structureSetRegistry, noiseParametersRegistry, new TheEndBiomeSource(biomeRegistry), endChunkGeneratorSettings)); - + RegistryEntry overworldDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.OVERWORLD); - + RegistryEntry overworld = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.OVERWORLD); - + Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( Locale.ROOT)); - + PRESETS.add(generatorID); - + TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack); ChunkGenerator generator = new MinecraftChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld); - + DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator); WorldPreset preset = new WorldPreset( Map.of( 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 d36a29a4e..d4402241c 100644 --- a/platforms/mixin-common/src/main/resources/terra.common.mixins.json +++ b/platforms/mixin-common/src/main/resources/terra.common.mixins.json @@ -1,49 +1,49 @@ { - "required": true, - "minVersion": "0.8", - "package": "com.dfsek.terra.mod.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - "access.BiomeAccessor", - "access.MobSpawnerLogicAccessor", - "access.StateAccessor", - "access.StructureAccessorAccessor", - "access.VillagerTypeAccessor", - "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", - "fix.NetherFossilOptimization", - "implementations.compat.GenerationSettingsFloraFeaturesMixin", - "implementations.terra.BiomeMixin", - "implementations.terra.HandleImplementationMixin", - "implementations.terra.block.BlockMixin", - "implementations.terra.block.entity.BlockEntityMixin", - "implementations.terra.block.entity.LootableContainerBlockEntityMixin", - "implementations.terra.block.entity.MobSpawnerBlockEntityMixin", - "implementations.terra.block.entity.SignBlockEntityMixin", - "implementations.terra.block.state.BlockStateMixin", - "implementations.terra.block.state.PropertyMixin", - "implementations.terra.chunk.ChunkRegionMixin", - "implementations.terra.chunk.WorldChunkMixin", - "implementations.terra.chunk.data.ProtoChunkMixin", - "implementations.terra.entity.EntityMixin", - "implementations.terra.entity.EntityTypeMixin", - "implementations.terra.entity.PlayerEntityMixin", - "implementations.terra.entity.ServerCommandSourceMixin", - "implementations.terra.inventory.LockableContainerBlockEntityMixin", - "implementations.terra.inventory.item.ItemMixin", - "implementations.terra.inventory.item.ItemStackMixin", - "implementations.terra.inventory.meta.EnchantmentMixin", - "implementations.terra.inventory.meta.ItemStackDamageableMixin", - "implementations.terra.inventory.meta.ItemStackMetaMixin", - "implementations.terra.world.ChunkRegionMixin", - "implementations.terra.world.ServerWorldMixin", - "lifecycle.DataPackContentsMixin" - ], - "client": [ - ], - "server": [ - ], - "injectors": { - "defaultRequire": 1 - }, + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.mod.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "access.BiomeAccessor", + "access.MobSpawnerLogicAccessor", + "access.StateAccessor", + "access.StructureAccessorAccessor", + "access.VillagerTypeAccessor", + "fix.BeeMoveGoalsUnsynchronizedRandomAccessFix", + "fix.NetherFossilOptimization", + "implementations.compat.GenerationSettingsFloraFeaturesMixin", + "implementations.terra.BiomeMixin", + "implementations.terra.HandleImplementationMixin", + "implementations.terra.block.BlockMixin", + "implementations.terra.block.entity.BlockEntityMixin", + "implementations.terra.block.entity.LootableContainerBlockEntityMixin", + "implementations.terra.block.entity.MobSpawnerBlockEntityMixin", + "implementations.terra.block.entity.SignBlockEntityMixin", + "implementations.terra.block.state.BlockStateMixin", + "implementations.terra.block.state.PropertyMixin", + "implementations.terra.chunk.ChunkRegionMixin", + "implementations.terra.chunk.WorldChunkMixin", + "implementations.terra.chunk.data.ProtoChunkMixin", + "implementations.terra.entity.EntityMixin", + "implementations.terra.entity.EntityTypeMixin", + "implementations.terra.entity.PlayerEntityMixin", + "implementations.terra.entity.ServerCommandSourceMixin", + "implementations.terra.inventory.LockableContainerBlockEntityMixin", + "implementations.terra.inventory.item.ItemMixin", + "implementations.terra.inventory.item.ItemStackMixin", + "implementations.terra.inventory.meta.EnchantmentMixin", + "implementations.terra.inventory.meta.ItemStackDamageableMixin", + "implementations.terra.inventory.meta.ItemStackMetaMixin", + "implementations.terra.world.ChunkRegionMixin", + "implementations.terra.world.ServerWorldMixin", + "lifecycle.DataPackContentsMixin" + ], + "client": [ + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + }, "refmap": "terra.common.refmap.json" } \ No newline at end of file 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 13ae3f692..f218380d7 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 @@ -28,15 +28,15 @@ public abstract class LifecyclePlatform extends ModPlatform { load(); } - public static void setServer(MinecraftServer server) { - LifecyclePlatform.server = server; - } - @Override public MinecraftServer getServer() { return server; } + public static void setServer(MinecraftServer server) { + LifecyclePlatform.server = server; + } + @Override public boolean reload() { getTerraConfig().load(this); diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/NoiseConfigMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/NoiseConfigMixin.java index 015a22260..2793aa500 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/NoiseConfigMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/NoiseConfigMixin.java @@ -24,8 +24,10 @@ public class NoiseConfigMixin { @Final private MultiNoiseSampler multiNoiseSampler; - @Inject(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At("TAIL")) - private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, Registry noiseRegistry, long seed, CallbackInfo ci) { + @Inject(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", + at = @At("TAIL")) + private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, + Registry noiseRegistry, long seed, CallbackInfo ci) { SeedHack.register(multiNoiseSampler, seed); } } diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/RegistryMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/RegistryMixin.java index 42b73c1ce..8e2c12c70 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/RegistryMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/RegistryMixin.java @@ -1,13 +1,13 @@ package com.dfsek.terra.lifecycle.mixin; -import com.dfsek.terra.lifecycle.util.RegistryUtil; - import net.minecraft.util.registry.Registry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.dfsek.terra.lifecycle.util.RegistryUtil; + @Mixin(Registry.class) public class RegistryMixin { 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 8e6732a58..f0d3e06e6 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 @@ -1,9 +1,5 @@ package com.dfsek.terra.lifecycle.util; -import com.dfsek.terra.mod.config.VanillaBiomeProperties; - -import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; @@ -21,6 +17,8 @@ import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.mod.CommonPlatform; import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions; import com.dfsek.terra.mod.config.ProtoPlatformBiome; +import com.dfsek.terra.mod.config.VanillaBiomeProperties; +import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; import com.dfsek.terra.mod.util.MinecraftUtil; @@ -48,7 +46,7 @@ public final class BiomeUtil { * @param pack The ConfigPack this biome belongs to. */ private static void registerBiome(Biome biome, ConfigPack pack, - com.dfsek.terra.api.registry.key.RegistryKey id) { + com.dfsek.terra.api.registry.key.RegistryKey id) { Registry registry = BuiltinRegistries.BIOME; RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(registry); @@ -58,7 +56,8 @@ public final class BiomeUtil { } else { VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla), vanillaBiomeProperties); + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla), + vanillaBiomeProperties); Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); @@ -69,14 +68,17 @@ public final class BiomeUtil { .orElseThrow()); } else { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry, - MinecraftUtil.registerKey(identifier).getValue(), + MinecraftUtil.registerKey(identifier) + .getValue(), minecraftBiome).getKey().orElseThrow()); } - + Map villagerMap = VillagerTypeAccessor.getBiomeTypeToIdMap(); - - villagerMap.put(RegistryKey.of(Registry.BIOME_KEY, identifier), Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(), villagerMap.getOrDefault(vanilla, VillagerType.PLAINS))); - + + villagerMap.put(RegistryKey.of(Registry.BIOME_KEY, identifier), + Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(), + villagerMap.getOrDefault(vanilla, VillagerType.PLAINS))); + MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(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 7961a9c9a..498de58aa 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 @@ -1,14 +1,14 @@ package com.dfsek.terra.lifecycle.util; +import net.minecraft.util.registry.BuiltinRegistries; + import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.mod.CommonPlatform; -import net.minecraft.util.registry.BuiltinRegistries; - public final class LifecycleUtil { private LifecycleUtil() { - + } public static void initialize() { 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 000f7c472..9f17b89e3 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 @@ -1,14 +1,14 @@ package com.dfsek.terra.lifecycle.util; -import com.dfsek.terra.mod.data.Codecs; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; +import com.dfsek.terra.mod.data.Codecs; + public final class RegistryUtil { private RegistryUtil() { - + } public static void register() { 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 4df69c7fb..7ec5e4d95 100644 --- a/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json +++ b/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json @@ -16,6 +16,6 @@ ], "injectors": { "defaultRequire": 1 - }, + }, "refmap": "terra.lifecycle.refmap.json" } \ No newline at end of file diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index 8fc889b2f..c1f443dd1 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -30,7 +30,7 @@ dependencies { modImplementation("org.quiltmc:quilt-loader:${Versions.Quilt.quiltLoader}") modImplementation("org.quiltmc.quilted-fabric-api:quilted-fabric-api:${Versions.Quilt.fabricApi}") - + modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) { exclude("net.fabricmc") exclude("net.fabricmc.fabric-api") diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/AwfulQuiltHacks.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/AwfulQuiltHacks.java index 7e3b7afcc..6dbcbaff4 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/AwfulQuiltHacks.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/AwfulQuiltHacks.java @@ -4,40 +4,41 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; + /** * So you want to Mixin into Authlib/Brigadier/DataFixerUpper, on Fabric you'll need this guy. * *

YOU SHOULD ONLY USE THIS CLASS DURING "preLaunch" and ONLY TARGET A CLASS WHICH IS NOT ANY CLASS YOU MIXIN TO. - * + *

* This will likely not work on Gson because FabricLoader has some special logic related to Gson. */ public final class AwfulQuiltHacks { - private AwfulQuiltHacks() {} + private static final ClassLoader KNOT_CLASSLOADER = Thread.currentThread().getContextClassLoader(); + private static final Method ADD_URL_METHOD; + static { + Method tempAddUrlMethod = null; + try { + tempAddUrlMethod = KNOT_CLASSLOADER.getClass().getMethod("addURL", URL.class); + tempAddUrlMethod.setAccessible(true); + } catch(ReflectiveOperationException e) { + throw new RuntimeException("Failed to load Classloader fields", e); + } - private static final ClassLoader KNOT_CLASSLOADER = Thread.currentThread().getContextClassLoader(); - private static final Method ADD_URL_METHOD; + ADD_URL_METHOD = tempAddUrlMethod; + } - static { - Method tempAddUrlMethod = null; - try { - tempAddUrlMethod = KNOT_CLASSLOADER.getClass().getMethod("addURL", URL.class); - tempAddUrlMethod.setAccessible(true); - } catch (ReflectiveOperationException e) { - throw new RuntimeException("Failed to load Classloader fields", e); - } + private AwfulQuiltHacks() { } - ADD_URL_METHOD = tempAddUrlMethod; - } - - /** - * Hackily load the package which a mixin may exist within. - * - * YOU SHOULD NOT TARGET A CLASS WHICH YOU MIXIN TO. - * - * @param pathOfAClass The path of any class within the package. - */ - public static void hackilyLoadForMixin(String pathOfAClass) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException { - URL url = Class.forName(pathOfAClass).getProtectionDomain().getCodeSource().getLocation(); - ADD_URL_METHOD.invoke(KNOT_CLASSLOADER, url); - } + /** + * Hackily load the package which a mixin may exist within. + *

+ * YOU SHOULD NOT TARGET A CLASS WHICH YOU MIXIN TO. + * + * @param pathOfAClass The path of any class within the package. + */ + public static void hackilyLoadForMixin(String pathOfAClass) + throws ClassNotFoundException, InvocationTargetException, IllegalAccessException { + URL url = Class.forName(pathOfAClass).getProtectionDomain().getCodeSource().getLocation(); + ADD_URL_METHOD.invoke(KNOT_CLASSLOADER, url); + } } diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java index 6a34eab74..f0767fdcf 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java @@ -3,6 +3,7 @@ package com.dfsek.terra.quilt; import com.dfsek.terra.mod.MinecraftAddon; import com.dfsek.terra.mod.ModPlatform; + public class QuiltAddon extends MinecraftAddon { public QuiltAddon(ModPlatform modPlatform) { diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java index f7c939fed..88f676daf 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java @@ -33,6 +33,7 @@ public class QuiltEntryPoint implements ModInitializer { private static final Logger logger = LoggerFactory.getLogger(QuiltEntryPoint.class); private static final QuiltPlatform TERRA_PLUGIN = new QuiltPlatform(); + @Override public void onInitialize(ModContainer container) { logger.info("Initializing Terra Quilt mod..."); diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPlatform.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPlatform.java index 406e2ffcf..dfc1a7a18 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPlatform.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPlatform.java @@ -32,7 +32,6 @@ import java.util.stream.Stream; import com.dfsek.terra.addon.EphemeralAddon; import com.dfsek.terra.api.addon.BaseAddon; -import com.dfsek.terra.api.util.generic.Lazy; import com.dfsek.terra.lifecycle.LifecyclePlatform; @@ -41,7 +40,7 @@ public class QuiltPlatform extends LifecyclePlatform { @Override protected Collection getPlatformMods() { - return QuiltLoader.getAllMods().stream().flatMap(mod -> { + return QuiltLoader.getAllMods().stream().flatMap(mod -> { String id = mod.metadata().id(); if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return Stream.empty(); try { diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java index 1e4fb70a9..e4d8cc0aa 100644 --- a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltPreLaunchEntryPoint.java @@ -11,7 +11,7 @@ import java.lang.reflect.InvocationTargetException; public class QuiltPreLaunchEntryPoint implements PreLaunchEntrypoint { @Override public void onPreLaunch(ModContainer mod) { - if (QuiltLoader.isDevelopmentEnvironment()) { + if(QuiltLoader.isDevelopmentEnvironment()) { try { AwfulQuiltHacks.hackilyLoadForMixin(BrigadierMappingBuilder.class.getName()); } catch(ClassNotFoundException | InvocationTargetException | IllegalAccessException e) { From 3cec404c6be9893d99c69877ca889856c4adc491 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 6 Jul 2022 19:32:23 -0700 Subject: [PATCH 219/220] specify platform in loom builds --- platforms/fabric/build.gradle.kts | 2 +- platforms/forge/build.gradle.kts | 2 +- platforms/quilt/build.gradle.kts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index e07a43a58..7ed3f2e75 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -71,6 +71,6 @@ tasks { remapJar { injectAccessWidener.set(true) inputFile.set(shadowJar.get().archiveFile) - archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") + archiveFileName.set("${rootProject.name.capitalize()}-fabric-${project.version}.jar") } } diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts index 1eee6098a..7cfddab1d 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts @@ -73,6 +73,6 @@ tasks { remapJar { inputFile.set(shadowJar.get().archiveFile) - archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") + archiveFileName.set("${rootProject.name.capitalize()}-forge-${project.version}.jar") } } \ No newline at end of file diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index c1f443dd1..940045d47 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -74,6 +74,6 @@ tasks { remapJar { injectAccessWidener.set(true) inputFile.set(shadowJar.get().archiveFile) - archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar") + archiveFileName.set("${rootProject.name.capitalize()}-quilt-${project.version}.jar") } } From 75a2dd7b6e443140815b05606841543b06be3238 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 6 Jul 2022 19:36:01 -0700 Subject: [PATCH 220/220] revert formatting of PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 62b32c8d9..35418fc93 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -72,19 +72,15 @@ - [ ] Bug Fix - [ ] Build system -- [ ] - Documentation +- [ ] Documentation - [ ] New Feature - [ ] Performance -- [ ] - Refactoring -- [ ] - Repository +- [ ] Refactoring +- [ ] Repository - [ ] Revert - [ ] Style - [ ] Tests -- [ ] - Translation +- [ ] Translation #### Compatiblity