diff --git a/build.gradle b/build.gradle index dd670fe..dc74469 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id 'fabric-loom' version '1.1.+' id 'maven-publish' - id 'io.github.juuxel.loom-quiltflower' version '1.8.0' + id 'io.github.juuxel.loom-quiltflower' version '1.10.0' } archivesBaseName = project.archive_name diff --git a/gradle.properties b/gradle.properties index 667d81f..c8d7496 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,7 +20,7 @@ fabric_version=0.83.0+1.20 terraform_surfaces_api_version=7.0.0-beta.1 # TerraBlender so we can target it with mixins -terrablender_version=1.19.4-2.2.0.156 +terrablender_version=1.20-3.0.0.163 # MixinExtras so we can mixin more kindly mixin_extras_version=0.2.0-beta.5 @@ -41,14 +41,14 @@ default_release_type=alpha # CurseForge Metadata curseforge_slug=biolith curseforge_id=852512 -curseforge_game_versions=1.20, Fabric, Quilt +curseforge_game_versions=1.20, 1.20.1, Fabric, Quilt curseforge_required_dependencies=fabric-api curseforge_optional_dependencies= # Modrinth Metadata modrinth_slug=biolith modrinth_id=iGEl6Crx -modrinth_game_versions=1.20 +modrinth_game_versions=1.20, 1.20.1 modrinth_mod_loaders=fabric, quilt modrinth_required_dependencies=fabric-api diff --git a/src/main/java/com/terraformersmc/biolith/impl/biome/BiomeCoordinator.java b/src/main/java/com/terraformersmc/biolith/impl/biome/BiomeCoordinator.java index c446a10..748903a 100644 --- a/src/main/java/com/terraformersmc/biolith/impl/biome/BiomeCoordinator.java +++ b/src/main/java/com/terraformersmc/biolith/impl/biome/BiomeCoordinator.java @@ -3,7 +3,9 @@ import com.terraformersmc.biolith.impl.Biolith; import com.terraformersmc.biolith.impl.config.BiolithState; import com.terraformersmc.biolith.impl.surface.SurfaceRuleCollector; +import net.minecraft.registry.CombinedDynamicRegistries; import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.ServerDynamicRegistryType; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; @@ -26,8 +28,19 @@ public class BiomeCoordinator { private static boolean serverStarted = false; protected static DynamicRegistryManager.Immutable registryManager; + public static void setRegistryManager(CombinedDynamicRegistries combinedDynamicRegistries) { + // Called by biolith$earlyCaptureRegistries() in MixinMinecraftServer so we can set this really early. + registryManager = combinedDynamicRegistries.getCombinedRegistryManager(); + } + + public static @Nullable DynamicRegistryManager.Immutable getRegistryManager() { + return registryManager; + } + public static void handleServerStarting(MinecraftServer server) { - registryManager = server.getCombinedDynamicRegistries().getCombinedRegistryManager(); + if (registryManager == null) { + registryManager = server.getCombinedDynamicRegistries().getCombinedRegistryManager(); + } if (Biolith.COMPAT_TERRABLENDER) { registerWithTerrablender(); @@ -67,10 +80,6 @@ public static void handleServerStopped(MinecraftServer server) { OVERWORLD_STATE = null; } - public static @Nullable DynamicRegistryManager.Immutable getRegistryManager() { - return registryManager; - } - // When TerraBlender is present, it ignores our surface rules in the Overworld and Nether. // To avoid this, we submit a duplicate registration to TerraBlender (but only once). private static void registerWithTerrablender() { diff --git a/src/main/java/com/terraformersmc/biolith/impl/biome/DimensionBiomePlacement.java b/src/main/java/com/terraformersmc/biolith/impl/biome/DimensionBiomePlacement.java index 4130cd5..d7f0c24 100644 --- a/src/main/java/com/terraformersmc/biolith/impl/biome/DimensionBiomePlacement.java +++ b/src/main/java/com/terraformersmc/biolith/impl/biome/DimensionBiomePlacement.java @@ -5,10 +5,7 @@ import com.terraformersmc.biolith.impl.Biolith; import com.terraformersmc.biolith.impl.config.BiolithState; import com.terraformersmc.terraform.noise.OpenSimplexNoise2; -import net.minecraft.registry.DynamicRegistryManager; -import net.minecraft.registry.Registry; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.*; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; @@ -57,6 +54,19 @@ protected void serverReplaced(BiolithState state, long seed) { seedlets[7] = (int) (seed >> 56 & 0xffL); } + protected RegistryEntryLookup getBiomeLookup() { + if (biomeRegistry != null) { + return biomeRegistry.getReadOnlyWrapper(); + } + + DynamicRegistryManager.Immutable registryManager = BiomeCoordinator.getRegistryManager(); + if (registryManager == null) { + throw new IllegalStateException("BiomeSource created while RegistryManager is null!"); + } + + return registryManager.getWrapperOrThrow(RegistryKeys.BIOME); + } + public void addPlacement(RegistryKey biome, MultiNoiseUtil.NoiseHypercube noisePoint) { if (biomesInjected) { Biolith.LOGGER.error("Biolith's BiomePlacement.addPlacement() called too late for biome: {}", biome.getValue()); @@ -84,6 +94,8 @@ public void addSubBiome(RegistryKey target, RegistryKey biome, Sub public abstract RegistryEntry getReplacement(int x, int y, int z, MultiNoiseUtil.NoiseValuePoint noisePoint, BiolithFittestNodes> fittestNodes); + public abstract void writeBiomeEntries(Consumer>> parameters); + public abstract void writeBiomeParameters(Consumer>> parameters); // Approximation of normalizing K.jpg OpenSimplex2(F) values in [-1,1] to unbiased values in [0,1]. diff --git a/src/main/java/com/terraformersmc/biolith/impl/biome/EndBiomePlacement.java b/src/main/java/com/terraformersmc/biolith/impl/biome/EndBiomePlacement.java index cdd55aa..3d14ed0 100644 --- a/src/main/java/com/terraformersmc/biolith/impl/biome/EndBiomePlacement.java +++ b/src/main/java/com/terraformersmc/biolith/impl/biome/EndBiomePlacement.java @@ -3,6 +3,7 @@ import com.mojang.datafixers.util.Pair; import com.terraformersmc.biolith.impl.config.BiolithState; import com.terraformersmc.terraform.noise.OpenSimplexNoise2; +import net.minecraft.registry.RegistryEntryLookup; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.world.biome.Biome; @@ -107,6 +108,33 @@ private double getLocalNoise(int x, int y, int z) { return localNoise; } + public void writeBiomeEntries(Consumer>> parameters) { + biomesInjected = true; + RegistryEntryLookup biomeEntryGetter = getBiomeLookup(); + + // End biomes are merged during construction of the End Biome stream. + + placementRequests.forEach(pair -> parameters.accept(pair.mapSecond(biomeEntryGetter::getOrThrow))); + + // Replacement biomes are placed out-of-range so they do not generate except as replacements. + // This adds the biome to TheEndBiomeSource and BiomeSource so features and structures will place. + + replacementRequests.values().stream() + .flatMap(requestSet -> requestSet.requests.stream()) + .map(ReplacementRequest::biome).distinct() + .forEach(biome -> { + if (!biome.equals(VANILLA_PLACEHOLDER)) { + parameters.accept(Pair.of(OUT_OF_RANGE, biomeEntryGetter.getOrThrow(biome))); + } + }); + + subBiomeRequests.values().stream() + .flatMap(requestSet -> requestSet.requests.stream()) + .map(SubBiomeRequest::biome).distinct() + .forEach(biome -> parameters.accept(Pair.of(OUT_OF_RANGE, biomeEntryGetter.getOrThrow(biome)))); + } + + // TODO: Deprecated for clean-up in the mixins -- Review and remove from all DimensionBiomePlacements? // NOTE: biomeRegistry IS already available when biomeStream() is called to init BiomeSource.biomes. public void writeBiomeParameters(Consumer>> parameters) { assert biomeRegistry != null; diff --git a/src/main/java/com/terraformersmc/biolith/impl/biome/InterfaceBiomeSource.java b/src/main/java/com/terraformersmc/biolith/impl/biome/InterfaceBiomeSource.java new file mode 100644 index 0000000..517f3b3 --- /dev/null +++ b/src/main/java/com/terraformersmc/biolith/impl/biome/InterfaceBiomeSource.java @@ -0,0 +1,11 @@ +package com.terraformersmc.biolith.impl.biome; + +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.world.dimension.DimensionType; + +@SuppressWarnings("unused") +public interface InterfaceBiomeSource { + RegistryEntry biolith$getDimensionType(); + + void biolith$setDimensionType(RegistryEntry dimensionTypeEntry); +} \ No newline at end of file diff --git a/src/main/java/com/terraformersmc/biolith/impl/biome/NetherBiomePlacement.java b/src/main/java/com/terraformersmc/biolith/impl/biome/NetherBiomePlacement.java index cae8c5c..cbd835e 100644 --- a/src/main/java/com/terraformersmc/biolith/impl/biome/NetherBiomePlacement.java +++ b/src/main/java/com/terraformersmc/biolith/impl/biome/NetherBiomePlacement.java @@ -1,6 +1,7 @@ package com.terraformersmc.biolith.impl.biome; import com.mojang.datafixers.util.Pair; +import net.minecraft.registry.RegistryEntryLookup; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.world.biome.Biome; @@ -75,6 +76,33 @@ private double getLocalNoise(int x, int y, int z) { return localNoise; } + public void writeBiomeEntries(Consumer>> parameters) { + biomesInjected = true; + RegistryEntryLookup biomeEntryGetter = getBiomeLookup(); + + // Nether biomes are merged during construction of the Nether parameters list. + + placementRequests.forEach(pair -> parameters.accept(pair.mapSecond(biomeEntryGetter::getOrThrow))); + + // Replacement biomes are placed out-of-range so they do not generate except as replacements. + // This adds the biome to MultiNoiseBiomeSource and BiomeSource so features and structures will place. + + replacementRequests.values().stream() + .flatMap(requestSet -> requestSet.requests.stream()) + .map(ReplacementRequest::biome).distinct() + .forEach(biome -> { + if (!biome.equals(VANILLA_PLACEHOLDER)) { + parameters.accept(Pair.of(OUT_OF_RANGE, biomeEntryGetter.getOrThrow(biome))); + } + }); + + subBiomeRequests.values().stream() + .flatMap(requestSet -> requestSet.requests.stream()) + .map(SubBiomeRequest::biome).distinct() + .forEach(biome -> parameters.accept(Pair.of(OUT_OF_RANGE, biomeEntryGetter.getOrThrow(biome)))); + } + + // TODO: Unused since 1.0.0-alpha.5 -- Review and remove from all DimensionBiomePlacements? // NOTE: biomeRegistry IS already available when writeBiomeParameters() is called by MultiNoiseBiomeSourceParameterList. public void writeBiomeParameters(Consumer>> parameters) { assert biomeRegistry != null; diff --git a/src/main/java/com/terraformersmc/biolith/impl/biome/OverworldBiomePlacement.java b/src/main/java/com/terraformersmc/biolith/impl/biome/OverworldBiomePlacement.java index e947629..327edbe 100644 --- a/src/main/java/com/terraformersmc/biolith/impl/biome/OverworldBiomePlacement.java +++ b/src/main/java/com/terraformersmc/biolith/impl/biome/OverworldBiomePlacement.java @@ -1,6 +1,7 @@ package com.terraformersmc.biolith.impl.biome; import com.mojang.datafixers.util.Pair; +import net.minecraft.registry.RegistryEntryLookup; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.world.biome.Biome; @@ -82,6 +83,33 @@ private double getLocalNoise(int x, int y, int z) { return localNoise; } + public void writeBiomeEntries(Consumer>> parameters) { + biomesInjected = true; + RegistryEntryLookup biomeEntryGetter = getBiomeLookup(); + + // Overworld biomes are added directly to the Overworld parameters list. + + placementRequests.forEach(pair -> parameters.accept(pair.mapSecond(biomeEntryGetter::getOrThrow))); + + // Replacement biomes are placed out-of-range so they do not generate except as replacements. + // This adds the biome to MultiNoiseBiomeSource and BiomeSource so features and structures will place. + + replacementRequests.values().stream() + .flatMap(requestSet -> requestSet.requests.stream()) + .map(ReplacementRequest::biome).distinct() + .forEach(biome -> { + if (!biome.equals(VANILLA_PLACEHOLDER)) { + parameters.accept(Pair.of(OUT_OF_RANGE, biomeEntryGetter.getOrThrow(biome))); + } + }); + + subBiomeRequests.values().stream() + .flatMap(requestSet -> requestSet.requests.stream()) + .map(SubBiomeRequest::biome).distinct() + .forEach(biome -> parameters.accept(Pair.of(OUT_OF_RANGE, biomeEntryGetter.getOrThrow(biome)))); + } + + // TODO: Unused since 1.0.0-alpha.5 -- Review and remove from all DimensionBiomePlacements? // NOTE: biomeRegistry is NOT yet available when writeBiomeParameters() is called by VanillaBiomeParameters. public void writeBiomeParameters(Consumer>> parameters) { biomesInjected = true; diff --git a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinBiomeSource.java b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinBiomeSource.java new file mode 100644 index 0000000..448b62a --- /dev/null +++ b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinBiomeSource.java @@ -0,0 +1,27 @@ +package com.terraformersmc.biolith.impl.mixin; + +import com.terraformersmc.biolith.impl.biome.InterfaceBiomeSource; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.world.biome.source.BiomeSource; +import net.minecraft.world.dimension.DimensionType; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(BiomeSource.class) +public class MixinBiomeSource implements InterfaceBiomeSource { + private RegistryEntry biolith$dimensionTypeEntry; + + @Override + public @Nullable RegistryEntry biolith$getDimensionType() { + return biolith$dimensionTypeEntry; + } + + @Override + public void biolith$setDimensionType(RegistryEntry dimensionTypeEntry) { + if (biolith$dimensionTypeEntry != null) { + throw new IllegalStateException("Dimension Type already set: " + biolith$dimensionTypeEntry); + } + + biolith$dimensionTypeEntry = dimensionTypeEntry; + } +} diff --git a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinDimensionOptions.java b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinDimensionOptions.java new file mode 100644 index 0000000..035088c --- /dev/null +++ b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinDimensionOptions.java @@ -0,0 +1,18 @@ +package com.terraformersmc.biolith.impl.mixin; + +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.world.dimension.DimensionOptions; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.chunk.ChunkGenerator; +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(DimensionOptions.class) +public class MixinDimensionOptions { + @Inject(method = "", at = @At("RETURN")) + private void biolith$storeDimensionTypeToBiomeSource(RegistryEntry dimensionTypeEntry, ChunkGenerator chunkGenerator, CallbackInfo ci) { + chunkGenerator.getBiomeSource().biolith$setDimensionType(dimensionTypeEntry); + } +} diff --git a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMinecraftServer.java b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMinecraftServer.java index 86a1b50..a1c9981 100644 --- a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMinecraftServer.java +++ b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMinecraftServer.java @@ -1,12 +1,20 @@ package com.terraformersmc.biolith.impl.mixin; import com.google.common.collect.Streams; +import com.mojang.datafixers.DataFixer; +import com.terraformersmc.biolith.impl.biome.BiomeCoordinator; import com.terraformersmc.biolith.impl.surface.SurfaceRuleCollector; +import net.minecraft.registry.CombinedDynamicRegistries; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.ServerDynamicRegistryType; +import net.minecraft.resource.ResourcePackManager; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.SaveLoader; import net.minecraft.server.WorldGenerationProgressListener; +import net.minecraft.server.WorldGenerationProgressListenerFactory; import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.ApiServices; import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionOptions; import net.minecraft.world.dimension.DimensionTypes; @@ -15,6 +23,8 @@ import net.minecraft.world.gen.chunk.NoiseChunkGenerator; import net.minecraft.world.gen.surfacebuilder.MaterialRules; import net.minecraft.world.level.ServerWorldProperties; +import net.minecraft.world.level.storage.LevelStorage; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -23,16 +33,32 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import java.net.Proxy; import java.util.Arrays; import java.util.Map; import java.util.stream.Stream; @Mixin(MinecraftServer.class) public abstract class MixinMinecraftServer { + @Shadow + @Final + private CombinedDynamicRegistries combinedDynamicRegistries; + @Shadow @Final private Map, ServerWorld> worlds; + @Inject(method = "", at = @At( + value = "FIELD", + target = "Lnet/minecraft/server/MinecraftServer;combinedDynamicRegistries:Lnet/minecraft/registry/CombinedDynamicRegistries;", + opcode = Opcodes.PUTFIELD, + ordinal = 0, + shift = At.Shift.AFTER)) + private void biolith$earlyCaptureRegistries(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager, SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices, WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { + // We need the registries really early in case TerraBlender calls us before the Fabric server start event. + BiomeCoordinator.setRegistryManager(combinedDynamicRegistries); + } + @Inject(method = "createWorlds", at = @At(value = "RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) private void biolith$prependSurfaceRules(WorldGenerationProgressListener worldGenerationProgressListener, CallbackInfo ci, ServerWorldProperties serverWorldProperties, boolean isDebug, Registry dimensionOptionsRegistry) { MaterialRules.MaterialRule[] rulesType = new MaterialRules.MaterialRule[0]; diff --git a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMultiNoiseBiomeSource.java b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMultiNoiseBiomeSource.java index 9d6dbbd..308a0da 100644 --- a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMultiNoiseBiomeSource.java +++ b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMultiNoiseBiomeSource.java @@ -1,40 +1,75 @@ package com.terraformersmc.biolith.impl.mixin; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.datafixers.util.Either; +import com.mojang.datafixers.util.Pair; import com.terraformersmc.biolith.impl.biome.BiolithFittestNodes; import com.terraformersmc.biolith.impl.biome.BiomeCoordinator; import com.terraformersmc.biolith.impl.compat.InterfaceEntries; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.source.BiomeSource; import net.minecraft.world.biome.source.MultiNoiseBiomeSource; import net.minecraft.world.biome.source.MultiNoiseBiomeSourceParameterList; import net.minecraft.world.biome.source.util.MultiNoiseUtil; +import net.minecraft.world.dimension.DimensionTypes; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + // Inject before TerraBlender so we can ensure our tree search and placement overrides get used. @Mixin(value = MultiNoiseBiomeSource.class, priority = 900) -public abstract class MixinMultiNoiseBiomeSource { +public abstract class MixinMultiNoiseBiomeSource extends BiomeSource { @Shadow protected abstract MultiNoiseUtil.Entries> getBiomeEntries(); - @Unique - private boolean biolith$isNether = false; - @Unique - private boolean biolith$isOverworld = false; + @Shadow @Final private Either>, RegistryEntry> biomeEntries; + private MultiNoiseUtil.Entries> biolith$biomeEntries; + + // Inject noise points the first time somebody requests them. + @WrapOperation( + method = "getBiomeEntries", + at = @At(value = "INVOKE", target = "Lcom/mojang/datafixers/util/Either;map(Ljava/util/function/Function;Ljava/util/function/Function;)Ljava/lang/Object;") + ) + @SuppressWarnings("unused") + private Object biolith$injectEntries(Either>, RegistryEntry> instance, Function>, MultiNoiseUtil.Entries>> leftMap, Function, MultiNoiseUtil.Entries>> rightMap, Operation original) { + synchronized (this) { + // Only compute this once, since our version is more expensive than Mojang's. + if (biolith$biomeEntries == null) { + // Mojang does the exact same cast in on the return of this operation. + //noinspection unchecked + MultiNoiseUtil.Entries> originalEntries = + (MultiNoiseUtil.Entries>) original.call(instance, leftMap, rightMap); + + if (biolith$getDimensionType().matchesKey(DimensionTypes.OVERWORLD)) { + List>> parameterList = new ArrayList<>(256); + + parameterList.addAll(originalEntries.getEntries()); + BiomeCoordinator.OVERWORLD.writeBiomeEntries(parameterList::add); + + biolith$biomeEntries = new MultiNoiseUtil.Entries<>(parameterList); + } else if (biolith$getDimensionType().matchesKey(DimensionTypes.THE_NETHER)) { + List>> parameterList = new ArrayList<>(64); + + parameterList.addAll(originalEntries.getEntries()); + BiomeCoordinator.NETHER.writeBiomeEntries(parameterList::add); + + biolith$biomeEntries = new MultiNoiseUtil.Entries<>(parameterList); + } else { + biolith$biomeEntries = originalEntries; + } + } + } // synchronized (this) - // We have to evaluate what world we are in a *lot* so we want these answers precomputed as booleans we can check. - @Inject(method = "", at = @At("RETURN")) - private void biolith$MultiNoiseBiomeSource(Either>, RegistryEntry> biomeEntries, CallbackInfo ci) { - biomeEntries.ifRight(parameterList -> { - biolith$isNether = parameterList.matchesId(MultiNoiseBiomeSourceParameterList.Preset.NETHER.id()); - biolith$isOverworld = parameterList.matchesId(MultiNoiseBiomeSourceParameterList.Preset.OVERWORLD.id()); - }); + return biolith$biomeEntries; } // We calculate the vanilla/datapack biome, then we apply any overlays. @@ -59,9 +94,9 @@ public abstract class MixinMultiNoiseBiomeSource { //noinspection unchecked fittestNodes = searchTree.biolith$searchTreeGet(noisePoint, MultiNoiseUtil.SearchTree.TreeNode::getSquaredDistance); - if (biolith$isOverworld) { + if (biolith$getDimensionType().matchesKey(DimensionTypes.OVERWORLD)) { cir.setReturnValue(BiomeCoordinator.OVERWORLD.getReplacement(x, y, z, noisePoint, fittestNodes)); - } else if (biolith$isNether) { + } else if (biolith$getDimensionType().matchesKey(DimensionTypes.THE_NETHER)) { cir.setReturnValue(BiomeCoordinator.NETHER.getReplacement(x, y, z, noisePoint, fittestNodes)); } else { cir.setReturnValue(fittestNodes.ultimate().value); diff --git a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMultiNoiseParameterPresetNether.java b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMultiNoiseParameterPresetNether.java deleted file mode 100644 index 81a5bfe..0000000 --- a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMultiNoiseParameterPresetNether.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.terraformersmc.biolith.impl.mixin; - -import com.google.common.collect.Streams; -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.mojang.datafixers.util.Pair; -import com.terraformersmc.biolith.impl.Biolith; -import com.terraformersmc.biolith.impl.biome.BiomeCoordinator; -import net.minecraft.registry.RegistryKey; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.util.MultiNoiseUtil; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; - -@SuppressWarnings("unused") -@Mixin(targets = "net/minecraft/world/biome/source/MultiNoiseBiomeSourceParameterList$Preset$1") -public class MixinMultiNoiseParameterPresetNether { - @ModifyReturnValue(method = "apply", at = @At("RETURN")) - private MultiNoiseUtil.Entries biolith$applyNetherPreset(MultiNoiseUtil.Entries original, Function, T> biomeEntryGetter) { - if (Biolith.COMPAT_DATAGEN) { - // During datagen we have to avoid adding biome registry keys. - return original; - } - - // Wrapping NETHER.writeBiomeParameters() like this allows us to use the same interface there as we do for OVERWORLD. - // So it looks kind of silly here, but it works fine and makes the code in the main biome placement classes alike. - List>> parameterList = new ArrayList<>(64); - BiomeCoordinator.NETHER.writeBiomeParameters(parameterList::add); - - return new MultiNoiseUtil.Entries<>( - Streams.concat( - original.getEntries().stream(), - parameterList.stream().map(pair -> Pair.of(pair.getFirst(), biomeEntryGetter.apply(pair.getSecond()))) - ).distinct().collect(Collectors.toList()) - ); - } -} diff --git a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinVanillaBiomeParameters.java b/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinVanillaBiomeParameters.java deleted file mode 100644 index 7b9b9ce..0000000 --- a/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinVanillaBiomeParameters.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.terraformersmc.biolith.impl.mixin; - -import com.mojang.datafixers.util.Pair; -import com.terraformersmc.biolith.impl.Biolith; -import com.terraformersmc.biolith.impl.biome.BiomeCoordinator; -import net.minecraft.registry.RegistryKey; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.util.MultiNoiseUtil; -import net.minecraft.world.biome.source.util.VanillaBiomeParameters; -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.function.Consumer; - -@Mixin(VanillaBiomeParameters.class) -public class MixinVanillaBiomeParameters { - @Inject(method = "writeOverworldBiomeParameters", at = @At("TAIL")) - private void biolith$injectOverworldBiomes(Consumer>> parameters, CallbackInfo ci) { - if (Biolith.COMPAT_DATAGEN) { - // During datagen we have to avoid adding registry keys. - return; - } - - BiomeCoordinator.OVERWORLD.writeBiomeParameters(parameters); - } -} diff --git a/src/main/resources/biolith.mixins.json b/src/main/resources/biolith.mixins.json index e5a2484..5334876 100644 --- a/src/main/resources/biolith.mixins.json +++ b/src/main/resources/biolith.mixins.json @@ -5,16 +5,16 @@ "compatibilityLevel": "JAVA_17", "plugin": "com.terraformersmc.biolith.impl.mixin.BiolithMixinPlugin", "mixins": [ + "MixinBiomeSource", "MixinChunkGeneratorSettings", + "MixinDimensionOptions", "MixinEntries", "MixinMinecraftServer", "MixinMultiNoiseBiomeSource", - "MixinMultiNoiseParameterPresetNether", "MixinSearchTree", "MixinServerWorld", "MixinSurfaceBuilder", - "MixinTheEndBiomeSource", - "MixinVanillaBiomeParameters" + "MixinTheEndBiomeSource" ], "injectors": { "defaultRequire": 1, diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index f673013..afbca8a 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -27,6 +27,7 @@ ], "custom": { "loom:injected_interfaces": { + "net/minecraft/class_1966": ["com/terraformersmc/biolith/impl/biome/InterfaceBiomeSource"], "net/minecraft/class_6544\u0024class_6548": ["com/terraformersmc/biolith/impl/biome/InterfaceSearchTree"], "net/minecraft/class_6544\u0024class_6547": ["com/terraformersmc/biolith/impl/compat/InterfaceEntries"] },