diff --git a/src/main/java/mod/bluestaggo/modernerbeta/client/debug/entries/DebugEntryInjectedBiome.java b/src/main/java/mod/bluestaggo/modernerbeta/client/debug/entries/DebugEntryInjectedBiome.java index 6bf913fc..bd5d6b10 100644 --- a/src/main/java/mod/bluestaggo/modernerbeta/client/debug/entries/DebugEntryInjectedBiome.java +++ b/src/main/java/mod/bluestaggo/modernerbeta/client/debug/entries/DebugEntryInjectedBiome.java @@ -1,6 +1,7 @@ //~dotLocation package mod.bluestaggo.modernerbeta.client.debug.entries; +import mod.bluestaggo.modernerbeta.level.biome.ModernBetaBiomeSource; import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionRule; import mod.bluestaggo.modernerbeta.level.biome.injection.InjectionNeeds; import mod.bluestaggo.modernerbeta.level.chunk.ModernBetaChunkGenerator; @@ -13,6 +14,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.level.chunk.LevelChunk; import org.jetbrains.annotations.Nullable; *///?} +import mod.bluestaggo.modernerbeta.mixin.BiomeManagerAccessor; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; import net.minecraft.world.level.chunk.ChunkGenerator; @@ -45,9 +47,17 @@ public class DebugEntryInjectedBiome /*? >=1.21.9 {*/ /*implements DebugScreenEn ChunkGenerator chunkGenerator = serverLevel.getChunkSource().getGenerator(); if (chunkGenerator instanceof ModernBetaChunkGenerator modernBetaChunkGenerator && - modernBetaChunkGenerator.getBiomeInjector() != null) { - String biome = modernBetaChunkGenerator.getBiomeInjector() - .getBiomeAtBlock(level, x, y, z, null, BiomeInjectionRule.Step.ALL, InjectionNeeds.all()) + chunkGenerator.getBiomeSource() instanceof ModernBetaBiomeSource modernBetaBiomeSource) { + String biome = modernBetaBiomeSource.getBiomeInjectionHandler() + .getBiomeAtBlock( + level, + modernBetaBiomeSource.getBiomeProvider(), + ((BiomeManagerAccessor) serverLevel.getBiomeManager()).getBiomeZoomSeed(), + x, y, z, + BiomeInjectionRule.Step.ALL, + InjectionNeeds.all(), + true + ) .unwrapKey() .map(key -> key.location().toString()) .orElse("[unregistered]"); diff --git a/src/main/java/mod/bluestaggo/modernerbeta/imixin/ModernBetaSurfaceSystem.java b/src/main/java/mod/bluestaggo/modernerbeta/imixin/ModernBetaSurfaceSystem.java index fb1bb798..fd49da79 100644 --- a/src/main/java/mod/bluestaggo/modernerbeta/imixin/ModernBetaSurfaceSystem.java +++ b/src/main/java/mod/bluestaggo/modernerbeta/imixin/ModernBetaSurfaceSystem.java @@ -1,10 +1,10 @@ package mod.bluestaggo.modernerbeta.imixin; -import mod.bluestaggo.modernerbeta.api.level.biome.BiomeProvider; import mod.bluestaggo.modernerbeta.api.level.chunk.ChunkProvider; +import mod.bluestaggo.modernerbeta.level.biome.ModernBetaBiomeSource; public interface ModernBetaSurfaceSystem { void modernerBeta$setupChunkContext(ChunkProvider chunkProvider); - void modernerBeta$setupBiomeContext(BiomeProvider biomeProvider); + void modernerBeta$setupBiomeContext(ModernBetaBiomeSource biomeSource); ChunkProvider modernerBeta$getContext(); } diff --git a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/ModernBetaBiomeSource.java b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/ModernBetaBiomeSource.java index 3558f060..50bfea9f 100644 --- a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/ModernBetaBiomeSource.java +++ b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/ModernBetaBiomeSource.java @@ -11,6 +11,8 @@ import mod.bluestaggo.modernerbeta.api.level.biome.BiomeResolverBlock; import mod.bluestaggo.modernerbeta.api.level.biome.BiomeResolverExtendedId; import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionRule; import mod.bluestaggo.modernerbeta.level.biome.injection.InjectionNeeds; +import mod.bluestaggo.modernerbeta.level.biome.injection.handler.BiomeInjectionHandler; +import mod.bluestaggo.modernerbeta.level.biome.injection.handler.SimpleBiomeInjectionHandler; import mod.bluestaggo.modernerbeta.registry.ModernBetaRegistries; import mod.bluestaggo.modernerbeta.api.level.cavebiome.CaveBiomeProvider; import mod.bluestaggo.modernerbeta.registry.IRegistryHandler; @@ -62,6 +64,7 @@ public class ModernBetaBiomeSource extends BiomeSource { private BiomeProvider biomeProvider; private CaveBiomeProvider caveBiomeProvider; + private BiomeInjectionHandler biomeInjectionHandler; private ModernBetaChunkGenerator chunkGenerator; @@ -110,6 +113,8 @@ public class ModernBetaBiomeSource extends BiomeSource { this.caveBiomeProvider = ModernBetaRegistries.CAVE_BIOME .getValue(caveBiomeSettings.getProvider()) .apply(caveBiomeSettings, this.biomeRegistry, seed); + + this.biomeInjectionHandler = new SimpleBiomeInjectionHandler(this.chunkGenerator, this); } @Override @@ -121,30 +126,34 @@ public class ModernBetaBiomeSource extends BiomeSource { public @NotNull Set> getBiomesWithin(int startX, int startY, int startZ, int radius, Sampler noiseSampler) { if (this.chunkGenerator == null) return super.getBiomesWithin(startX, startY, startZ, radius, noiseSampler); - + int minX = QuartPos.fromBlock(startX - radius); int minZ = QuartPos.fromBlock(startZ - radius); - + int maxX = QuartPos.fromBlock(startX + radius); int maxZ = QuartPos.fromBlock(startZ + radius); - + int rangeX = maxX - minX + 1; int rangeZ = maxZ - minZ + 1; - + HashSet> set = Sets.newHashSet(); for (int localZ = 0; localZ < rangeZ; ++localZ) { for (int localX = 0; localX < rangeX; ++localX) { int biomeX = minX + localX; int biomeZ = minZ + localZ; - - int x = biomeX << 2; - int z = biomeZ << 2; - int y = this.chunkGenerator.getHeight(x, z, Heightmap.Types.OCEAN_FLOOR_WG, null); - - set.add(this.chunkGenerator.getBiomeInjector().getBiomeAtBlock(null, x, y, z, noiseSampler, BiomeInjectionRule.Step.ALL, InjectionNeeds.all())); + + int y = this.chunkGenerator.getHeight(biomeX << 2, biomeZ << 2, Heightmap.Types.OCEAN_FLOOR_WG, null); + + set.add(this.biomeInjectionHandler.getBiome( + null, + biomeX, QuartPos.fromBlock(y), biomeZ, + BiomeInjectionRule.Step.ALL, + InjectionNeeds.all(), + true + )); } } - + return set; } @@ -194,9 +203,8 @@ public class ModernBetaBiomeSource extends BiomeSource { for (int y : sections) { int biomeY = QuartPos.fromBlock(y); - Holder biome = this.chunkGenerator - .getBiomeInjector() - .getBiome(level, biomeX, biomeY, biomeZ, noiseSampler, BiomeInjectionRule.Step.ALL, InjectionNeeds.cheapToFulfill()); + Holder biome = this.biomeInjectionHandler + .getBiome(level, biomeX, biomeY, biomeZ, BiomeInjectionRule.Step.ALL, InjectionNeeds.cheapToFulfill(), true); if (!biomeSet.contains(biome)) continue; @@ -242,6 +250,10 @@ public class ModernBetaBiomeSource extends BiomeSource { public void setChunkGenerator(ModernBetaChunkGenerator chunkGenerator) { this.chunkGenerator = chunkGenerator; } + + public HolderGetter getPresetRegistry() { + return this.presetRegistry; + } public BiomeProvider getBiomeProvider() { return this.biomeProvider; @@ -250,6 +262,10 @@ public class ModernBetaBiomeSource extends BiomeSource { public CaveBiomeProvider getCaveBiomeProvider() { return this.caveBiomeProvider; } + + public BiomeInjectionHandler getBiomeInjectionHandler() { + return this.biomeInjectionHandler; + } public ModernBetaSettings getBiomeSettings() { return this.biomeSettings; diff --git a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/BiomeInjectionContext.java b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/BiomeInjectionContext.java index ace59cd5..a4646b04 100644 --- a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/BiomeInjectionContext.java +++ b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/BiomeInjectionContext.java @@ -73,7 +73,7 @@ public final class BiomeInjectionContext { return this; } - void setupContext() { + public void setupContext() { ModernBetaSettings settingsChunk = this.chunkGenerator.getChunkSettings() .mapPreset(this.chunkGenerator.getPresetRegistry(), ModernBetaSettingsPreset::chunkSettings); diff --git a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/BiomeInjectionHandler.java b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/BiomeInjectionHandler.java deleted file mode 100644 index 3e2461a2..00000000 --- a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/BiomeInjectionHandler.java +++ /dev/null @@ -1,248 +0,0 @@ -//~dotLocation -package mod.bluestaggo.modernerbeta.level.biome.injection; - -import mod.bluestaggo.modernerbeta.api.level.biome.climate.ClimateSampler; -import mod.bluestaggo.modernerbeta.api.level.chunk.ChunkProvider; -import mod.bluestaggo.modernerbeta.api.level.chunk.ChunkProviderNoise; -import mod.bluestaggo.modernerbeta.mixin.LevelChunkSectionAccessor; -import mod.bluestaggo.modernerbeta.settings.ModernBetaSettings; -import mod.bluestaggo.modernerbeta.settings.ModernBetaSettingsPreset; -import mod.bluestaggo.modernerbeta.settings.SettingsComponentTypes; -import mod.bluestaggo.modernerbeta.util.chunk.ChunkHeightmap; -import mod.bluestaggo.modernerbeta.level.biome.ModernBetaBiomeSource; -import mod.bluestaggo.modernerbeta.level.chunk.ModernBetaChunkGenerator; -import net.minecraft.core.Holder; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.Climate.Sampler; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.PalettedContainer; -import net.minecraft.world.level.chunk.PalettedContainerRO; -import net.minecraft.world.level.levelgen.Heightmap; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumSet; -import java.util.List; -import java.util.Optional; - -public class BiomeInjectionHandler { - private final ModernBetaChunkGenerator modernBetaChunkGenerator; - private final ModernBetaBiomeSource modernBetaBiomeSource; - - private final List rules; - private final ThreadLocal context; - - public BiomeInjectionHandler(ModernBetaChunkGenerator modernBetaChunkGenerator, ModernBetaBiomeSource modernBetaBiomeSource) { - this.modernBetaChunkGenerator = modernBetaChunkGenerator; - this.modernBetaBiomeSource = modernBetaBiomeSource; - - ModernBetaSettings settingsBiome = this.modernBetaBiomeSource.getBiomeSettings() - .mapPreset(modernBetaChunkGenerator.getPresetRegistry(), ModernBetaSettingsPreset::biomeSettings); - - this.rules = settingsBiome.getOrDefault(SettingsComponentTypes.BIOME_INJECTION_RULES); - - this.context = ThreadLocal.withInitial(() -> { - BiomeInjectionContext instance = new BiomeInjectionContext(this.modernBetaChunkGenerator, this.modernBetaBiomeSource); - instance.setupContext(); - return instance; - }); - } - - public void injectBiomes(ChunkAccess chunk, Sampler noiseSampler, BiomeInjectionRule.Step step) { - if (this.rules.isEmpty()) { - return; - } - - ChunkPos chunkPos = chunk.getPos(); - - int startBiomeX = chunkPos.getMinBlockX() >> 2; - int startBiomeZ = chunkPos.getMinBlockZ() >> 2; - LevelHeightAccessor view = chunk.getHeightAccessorForGeneration(); - - /* - * Collect the following for an x/z coordinate: - * -> Height at local biome coordinate. - * -> Minimum height of area around local biome coordinate. - * -> Blockstate at height of local biome coordinate. - */ - - // Replace biomes from biome container - for (int sectionY = view.getMinSectionY(); sectionY < view.getMaxSectionY() + 1; ++sectionY) { - int sectionYNdx = chunk.getSectionIndexFromSectionY(sectionY); - LevelChunkSection section = chunk.getSection(sectionYNdx); - - PalettedContainerRO> readableContainer = section.getBiomes(); - PalettedContainer> palettedContainer = section.getBiomes().recreate(); - palettedContainer.acquire(); - - try { - for (int localBiomeX = 0; localBiomeX < 4; ++localBiomeX) { - int biomeX = localBiomeX + startBiomeX; - - for (int localBiomeZ = 0; localBiomeZ < 4; ++localBiomeZ) { - int biomeZ = localBiomeZ + startBiomeZ; - - for (int localBiomeY = 0; localBiomeY < 4; ++localBiomeY) { - int biomeY = sectionY << 2 | localBiomeY; - - Holder initialBiome = readableContainer.get(localBiomeX, localBiomeY, localBiomeZ); - Holder replacementBiome = this.getOptionalBiome(view, biomeX, biomeY, biomeZ, - noiseSampler, step, InjectionNeeds.all()).orElse(initialBiome); - - palettedContainer.getAndSetUnchecked(localBiomeX, localBiomeY, localBiomeZ, replacementBiome); - } - } - } - } finally { - palettedContainer.release(); - } - - ((LevelChunkSectionAccessor)section).setBiomes(palettedContainer); - } - } - - public @NotNull Holder getBiomeAtBlock( - LevelHeightAccessor level, - int x, int y, int z, - Sampler noiseSampler, - BiomeInjectionRule.Step step, - EnumSet ableToFulfill - ) { - int biomeX = x >> 2; - int biomeY = y >> 2; - int biomeZ = z >> 2; - - return this.getBiome(level, biomeX, biomeY, biomeZ, noiseSampler, step, ableToFulfill); - } - - public @NotNull Holder getBiome( - LevelHeightAccessor level, - int biomeX, int biomeY, int biomeZ, - Sampler noiseSampler, - BiomeInjectionRule.Step step, - EnumSet ableToFulfill - ) { - if (this.rules.isEmpty()) { - return this.modernBetaBiomeSource.getNoiseBiome(biomeX, biomeY, biomeZ, noiseSampler); - } - - if (ableToFulfill.contains(InjectionNeeds.CLIMATE) && - !(this.modernBetaBiomeSource.getBiomeProvider() instanceof ClimateSampler)) { - ableToFulfill.remove(InjectionNeeds.CLIMATE); - } - - BiomeInjectionContext context = this.setupContext(level, biomeX, biomeY, biomeZ, ableToFulfill); - - return this - .getBiome(context, biomeX, biomeY, biomeZ, noiseSampler, step, ableToFulfill) - .orElseGet(() -> this.modernBetaBiomeSource.getNoiseBiome(biomeX, biomeY, biomeZ, noiseSampler)); - } - - public @NotNull Optional> getOptionalBiome( - @Nullable LevelHeightAccessor level, - int biomeX, int biomeY, int biomeZ, - Sampler noiseSampler, - BiomeInjectionRule.Step step, - EnumSet ableToFulfill - ) { - if (ableToFulfill.contains(InjectionNeeds.HEIGHTS) && level == null) { - ableToFulfill.remove(InjectionNeeds.HEIGHTS); - } - - if (ableToFulfill.contains(InjectionNeeds.CLIMATE) && - !(this.modernBetaBiomeSource.getBiomeProvider() instanceof ClimateSampler)) { - ableToFulfill.remove(InjectionNeeds.CLIMATE); - } - - BiomeInjectionContext context = this.setupContext(level, biomeX, biomeY, biomeZ, ableToFulfill); - - return this.getBiome(context, biomeX, biomeY, biomeZ, noiseSampler, step, ableToFulfill); - } - - private @NotNull Optional> getBiome( - BiomeInjectionContext context, - int biomeX, int biomeY, int biomeZ, - Sampler noiseSampler, - BiomeInjectionRule.Step step, - EnumSet ableToFulfill - ) { - Holder biome = null; - - for (BiomeInjectionRule rule : this.rules) { - if (step != BiomeInjectionRule.Step.ALL && step != rule.stepFor()) - continue; - - if (!rule.canFulfill(ableToFulfill)) - continue; - - if (rule.needs().contains(InjectionNeeds.BIOMES) && context.getBiome() == null) - context.setBiome(this.modernBetaBiomeSource.getNoiseBiome(biomeX, biomeY, biomeZ, noiseSampler)); - - rule.initIfNeeded(); - Holder result = rule.apply(context, biomeX, biomeY, biomeZ); - if (result != null) { - context.setBiome(result); - biome = result; - } - } - - return Optional.ofNullable(biome); - } - - private BiomeInjectionContext setupContext( - LevelHeightAccessor level, - int biomeX, int biomeY, int biomeZ, - EnumSet ableToFulfill - ) { - BiomeInjectionContext context = this.context.get(); - - if (ableToFulfill.contains(InjectionNeeds.HEIGHTS)) { - int worldMinY = this.modernBetaChunkGenerator.getMinY(); - int topHeight = this.sampleTopHeight(level, biomeX, biomeZ); - int minHeight = this.sampleMinHeight(level, biomeX, biomeZ); - - context.setHeights(worldMinY, topHeight, minHeight); - } - - return context - .setBiome(null) - .setFulfillableNeeds(ableToFulfill) - .setPosition((biomeX << 2) + 2, biomeY << 2, (biomeZ << 2) + 2); - } - - private int sampleTopHeight(LevelHeightAccessor level, int biomeX, int biomeZ) { - int x = (biomeX << 2) + 2; - int z = (biomeZ << 2) + 2; - - return this.modernBetaChunkGenerator.getHeight(x, z, Heightmap.Types.OCEAN_FLOOR_WG, level); - } - - private int sampleFloorHeight(LevelHeightAccessor level, int biomeX, int biomeZ) { - int x = (biomeX << 2) + 2; - int z = (biomeZ << 2) + 2; - - ChunkProvider chunkProvider = this.modernBetaChunkGenerator.getChunkProvider(); - - return chunkProvider instanceof ChunkProviderNoise chunkProviderNoise ? - chunkProviderNoise.getHeight(level, x, z, ChunkHeightmap.Type.SURFACE_FLOOR) : - chunkProvider.getHeight(level, x, z, Heightmap.Types.OCEAN_FLOOR_WG); - } - - private int sampleMinHeight(LevelHeightAccessor level, int centerBiomeX, int centerBiomeZ) { - int minHeight = Integer.MAX_VALUE; - - for (int localBiomeX = -1; localBiomeX <= 1; ++localBiomeX) { - for (int localBiomeZ = -1; localBiomeZ <= 1; ++localBiomeZ) { - int biomeX = centerBiomeX + localBiomeX; - int biomeZ = centerBiomeZ + localBiomeZ; - - minHeight = Math.min(minHeight, this.sampleFloorHeight(level, biomeX, biomeZ)); - } - } - - return minHeight; - } -} diff --git a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/BiomeInjectionHandler.java b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/BiomeInjectionHandler.java new file mode 100644 index 00000000..c8cf2c13 --- /dev/null +++ b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/BiomeInjectionHandler.java @@ -0,0 +1,179 @@ +package mod.bluestaggo.modernerbeta.level.biome.injection.handler; + +import mod.bluestaggo.modernerbeta.api.level.biome.BiomeProvider; +import mod.bluestaggo.modernerbeta.api.level.biome.BiomeResolverBlock; +import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionRule; +import mod.bluestaggo.modernerbeta.level.biome.injection.InjectionNeeds; +import mod.bluestaggo.modernerbeta.mixin.LevelChunkSectionAccessor; +import net.minecraft.core.Holder; +import net.minecraft.util.LinearCongruentialGenerator; +import net.minecraft.util.Mth; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.chunk.PalettedContainerRO; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumSet; +import java.util.List; + +public interface BiomeInjectionHandler { + @Nullable Holder getBiome( + LevelHeightAccessor level, + int biomeX, int biomeY, int biomeZ, + BiomeInjectionRule.Step step, + EnumSet ableToFulfill, + boolean shouldDelegate + ); + + @NotNull List getRulesForStep( + BiomeInjectionRule.Step step, + EnumSet ableToFulfill + ); + + default @NotNull Holder getBiomeAtBlock( + LevelHeightAccessor level, + BiomeProvider baseBiomeProvider, + long biomeZoomSeed, + int x, int y, int z, + BiomeInjectionRule.Step step, + EnumSet ableToFulfill, + boolean shouldDelegate + ) { + int absX = x - 2; + int absY = y - 2; + int absZ = z - 2; + + int parentX = absX >> 2; + int parentY = absY >> 2; + int parentZ = absZ >> 2; + + double fractX = (absX & 3) / 4.0; + double fractY = (absY & 3) / 4.0; + double fractZ = (absZ & 3) / 4.0; + + int minI = 0; + double minFiddledDistance = Double.POSITIVE_INFINITY; + + for (int i = 0; i < 8; i++) { + boolean xEven = (i & 4) == 0; + boolean yEven = (i & 2) == 0; + boolean zEven = (i & 1) == 0; + + int cornerX = xEven ? parentX : parentX + 1; + int cornerY = yEven ? parentY : parentY + 1; + int cornerZ = zEven ? parentZ : parentZ + 1; + + double distanceX = xEven ? fractX : fractX - 1.0; + double distanceY = yEven ? fractY : fractY - 1.0; + double distanceZ = zEven ? fractZ : fractZ - 1.0; + + double next = getFiddledDistance(biomeZoomSeed, cornerX, cornerY, cornerZ, distanceX, distanceY, distanceZ); + if (minFiddledDistance > next) { + minI = i; + minFiddledDistance = next; + } + } + + int biomeX = (minI & 4) == 0 ? parentX : parentX + 1; + int biomeY = (minI & 2) == 0 ? parentY : parentY + 1; + int biomeZ = (minI & 1) == 0 ? parentZ : parentZ + 1; + Holder biome = this.getBiome(level, biomeX, biomeY, biomeZ, step, ableToFulfill, shouldDelegate); + + if (biome == null) { + if (baseBiomeProvider instanceof BiomeResolverBlock biomeBlock) { + biome = biomeBlock.getBiomeBlock(x, y, z); + } else { + biome = baseBiomeProvider.getBiome(biomeX, biomeY, biomeZ); + } + } + + return biome; + } + + default PalettedContainer> injectIntoChunkSection( + LevelHeightAccessor view, + ChunkPos chunkPos, + int sectionY, + PalettedContainerRO> biomes, + BiomeInjectionRule.Step step, + EnumSet ableToFulfill + ) { + int startBiomeX = chunkPos.getMinBlockX() >> 2; + int startBiomeZ = chunkPos.getMinBlockZ() >> 2; + + PalettedContainer> palettedContainer = biomes.recreate(); + palettedContainer.acquire(); + + try { + for (int localBiomeX = 0; localBiomeX < 4; ++localBiomeX) { + int biomeX = localBiomeX + startBiomeX; + + for (int localBiomeZ = 0; localBiomeZ < 4; ++localBiomeZ) { + int biomeZ = localBiomeZ + startBiomeZ; + + for (int localBiomeY = 0; localBiomeY < 4; ++localBiomeY) { + int biomeY = sectionY << 2 | localBiomeY; + + Holder replacementBiome = this.getBiome(view, biomeX, biomeY, biomeZ, step, ableToFulfill, true); + if (replacementBiome == null) { + replacementBiome = biomes.get(localBiomeX, localBiomeY, localBiomeZ); + } + + palettedContainer.getAndSetUnchecked(localBiomeX, localBiomeY, localBiomeZ, replacementBiome); + } + } + } + } finally { + palettedContainer.release(); + } + + return palettedContainer; + } + + default void injectIntoChunk(ChunkAccess chunk, BiomeInjectionRule.Step step, EnumSet ableToFulfill) { + LevelHeightAccessor view = chunk.getHeightAccessorForGeneration(); + + for (int sectionY = view.getMinSectionY(); sectionY < view.getMaxSectionY() + 1; sectionY++) { + int sectionIndex = chunk.getSectionIndexFromSectionY(sectionY); + LevelChunkSection section = chunk.getSection(sectionIndex); + + PalettedContainerRO> biomes = section.getBiomes(); + PalettedContainer> injected = + this.injectIntoChunkSection(view, chunk.getPos(), sectionY, biomes, step, ableToFulfill); + + ((LevelChunkSectionAccessor)section).setBiomes(injected); + } + } + + private static double getFiddledDistance( + long seed, + int xRandom, int yRandom, int zRandom, + double distanceX, double distanceY, double distanceZ + ) { + long rval = LinearCongruentialGenerator.next(seed, xRandom); + rval = LinearCongruentialGenerator.next(rval, yRandom); + rval = LinearCongruentialGenerator.next(rval, zRandom); + rval = LinearCongruentialGenerator.next(rval, xRandom); + rval = LinearCongruentialGenerator.next(rval, yRandom); + rval = LinearCongruentialGenerator.next(rval, zRandom); + double fiddleX = getFiddle(rval); + rval = LinearCongruentialGenerator.next(rval, seed); + double fiddleY = getFiddle(rval); + rval = LinearCongruentialGenerator.next(rval, seed); + double fiddleZ = getFiddle(rval); + + return Mth.square(distanceZ + fiddleZ) + + Mth.square(distanceY + fiddleY) + + Mth.square(distanceX + fiddleX); + } + + private static double getFiddle(long rval) { + double uniform = Math.floorMod(rval >> 24, 1024) / 1024.0; + return (uniform - 0.5) * 0.9; + } +} diff --git a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/CachedBiomeInjectionHandler.java b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/CachedBiomeInjectionHandler.java new file mode 100644 index 00000000..9e68fb83 --- /dev/null +++ b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/CachedBiomeInjectionHandler.java @@ -0,0 +1,39 @@ +package mod.bluestaggo.modernerbeta.level.biome.injection.handler; + +import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionRule; +import mod.bluestaggo.modernerbeta.level.biome.injection.InjectionNeeds; +import net.minecraft.core.Holder; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumSet; +import java.util.List; + +public class CachedBiomeInjectionHandler implements BiomeInjectionHandler { + private final BiomeInjectionHandler baseHandler; + + public CachedBiomeInjectionHandler(BiomeInjectionHandler baseHandler) { + this.baseHandler = baseHandler; + } + + @Override + public @Nullable Holder getBiome( + LevelHeightAccessor level, + int biomeX, int biomeY, int biomeZ, + BiomeInjectionRule.Step step, + EnumSet ableToFulfill, + boolean shouldDelegate + ) { + return null; + } + + @Override + public @NotNull List getRulesForStep( + BiomeInjectionRule.Step step, + EnumSet ableToFulfill + ) { + return this.baseHandler.getRulesForStep(step, ableToFulfill); + } +} diff --git a/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/SimpleBiomeInjectionHandler.java b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/SimpleBiomeInjectionHandler.java new file mode 100644 index 00000000..9abde3ad --- /dev/null +++ b/src/main/java/mod/bluestaggo/modernerbeta/level/biome/injection/handler/SimpleBiomeInjectionHandler.java @@ -0,0 +1,186 @@ +package mod.bluestaggo.modernerbeta.level.biome.injection.handler; + +import mod.bluestaggo.modernerbeta.api.level.biome.climate.ClimateSampler; +import mod.bluestaggo.modernerbeta.api.level.chunk.ChunkProvider; +import mod.bluestaggo.modernerbeta.api.level.chunk.ChunkProviderNoise; +import mod.bluestaggo.modernerbeta.level.biome.ModernBetaBiomeSource; +import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionContext; +import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionRule; +import mod.bluestaggo.modernerbeta.level.biome.injection.InjectionNeeds; +import mod.bluestaggo.modernerbeta.level.chunk.ModernBetaChunkGenerator; +import mod.bluestaggo.modernerbeta.settings.ModernBetaSettings; +import mod.bluestaggo.modernerbeta.settings.ModernBetaSettingsPreset; +import mod.bluestaggo.modernerbeta.settings.SettingsComponentTypes; +import mod.bluestaggo.modernerbeta.util.chunk.ChunkHeightmap; +import net.minecraft.core.Holder; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.Heightmap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumSet; +import java.util.List; + +public class SimpleBiomeInjectionHandler implements BiomeInjectionHandler { + private final ModernBetaChunkGenerator modernBetaChunkGenerator; + private final ModernBetaBiomeSource modernBetaBiomeSource; + + private final List allRules; + private final ThreadLocal context; + + public SimpleBiomeInjectionHandler(ModernBetaChunkGenerator modernBetaChunkGenerator, ModernBetaBiomeSource modernBetaBiomeSource) { + this.modernBetaChunkGenerator = modernBetaChunkGenerator; + this.modernBetaBiomeSource = modernBetaBiomeSource; + + ModernBetaSettings settingsBiome = this.modernBetaBiomeSource.getBiomeSettings() + .mapPreset(modernBetaBiomeSource.getPresetRegistry(), ModernBetaSettingsPreset::biomeSettings); + + this.allRules = settingsBiome.getOrDefault(SettingsComponentTypes.BIOME_INJECTION_RULES); + + this.context = ThreadLocal.withInitial(() -> { + BiomeInjectionContext instance = new BiomeInjectionContext(this.modernBetaChunkGenerator, this.modernBetaBiomeSource); + instance.setupContext(); + return instance; + }); + } + + private @Nullable Holder delegateBiome( + LevelHeightAccessor level, + int biomeX, int biomeY, int biomeZ, + BiomeInjectionRule.Step step, + EnumSet ableToFulfill, + boolean base + ) { + BiomeInjectionRule.Step curStep = step; + if (curStep == BiomeInjectionRule.Step.ALL) + return this.modernBetaBiomeSource.getNoiseBiome(biomeX, biomeY, biomeZ, null); + + int prevStepOrdinal = curStep.ordinal() - 1; + + if (prevStepOrdinal >= 0) { + curStep = BiomeInjectionRule.Step.values()[prevStepOrdinal]; + return this.getBiome(level, biomeX, biomeY, biomeZ, curStep, ableToFulfill, true); + } + + if (base) { + return this.modernBetaBiomeSource.getNoiseBiome(biomeX, biomeY, biomeZ, null); + } + + return null; + } + + @Override + public @Nullable Holder getBiome( + LevelHeightAccessor level, + int biomeX, int biomeY, int biomeZ, + BiomeInjectionRule.Step step, + EnumSet ableToFulfill, + boolean shouldDelegate + ) { + List rules = this.getRulesForStep(step, ableToFulfill); + if (rules.isEmpty()) { + return null; + } + + BiomeInjectionContext context = this.setupContext(level, biomeX, biomeY, biomeZ, ableToFulfill); + + Holder biome = null; + + for (BiomeInjectionRule rule : rules) { + if (step != BiomeInjectionRule.Step.ALL && step != rule.stepFor()) + continue; + + if (!rule.canFulfill(ableToFulfill)) + continue; + + if (rule.needs().contains(InjectionNeeds.BIOMES) && context.getBiome() == null) { + if (!shouldDelegate) + throw new IllegalStateException("Injector needs a biome, we do not have one, and are unable to delegate."); + + context.setBiome(this.delegateBiome(level, biomeX, biomeY, biomeZ, step, ableToFulfill, true)); + } + + rule.initIfNeeded(); + Holder result = rule.apply(context, biomeX, biomeY, biomeZ); + if (result != null) { + context.setBiome(result); + biome = result; + } + } + + if (biome == null && shouldDelegate) + return this.delegateBiome(level, biomeX, biomeY, biomeZ, step, ableToFulfill, false); + + return biome; + } + + @Override + public @NotNull List getRulesForStep( + BiomeInjectionRule.Step step, + EnumSet ableToFulfill + ) { + if (ableToFulfill.contains(InjectionNeeds.CLIMATE) && + !(this.modernBetaBiomeSource.getBiomeProvider() instanceof ClimateSampler)) { + ableToFulfill.remove(InjectionNeeds.CLIMATE); + } + + return this.allRules.stream() + .filter(rule -> step == BiomeInjectionRule.Step.ALL || step == rule.stepFor()) + .toList(); + } + + private BiomeInjectionContext setupContext( + LevelHeightAccessor level, + int biomeX, int biomeY, int biomeZ, + EnumSet ableToFulfill + ) { + BiomeInjectionContext context = this.context.get(); + + if (ableToFulfill.contains(InjectionNeeds.HEIGHTS)) { + int worldMinY = this.modernBetaChunkGenerator.getMinY(); + int topHeight = this.sampleTopHeight(level, biomeX, biomeZ); + int minHeight = this.sampleMinHeight(level, biomeX, biomeZ); + + context.setHeights(worldMinY, topHeight, minHeight); + } + + return context + .setBiome(null) + .setFulfillableNeeds(ableToFulfill) + .setPosition((biomeX << 2) + 2, biomeY << 2, (biomeZ << 2) + 2); + } + + private int sampleTopHeight(LevelHeightAccessor level, int biomeX, int biomeZ) { + int x = (biomeX << 2) + 2; + int z = (biomeZ << 2) + 2; + + return this.modernBetaChunkGenerator.getHeight(x, z, Heightmap.Types.OCEAN_FLOOR_WG, level); + } + + private int sampleFloorHeight(LevelHeightAccessor level, int biomeX, int biomeZ) { + int x = (biomeX << 2) + 2; + int z = (biomeZ << 2) + 2; + + ChunkProvider chunkProvider = this.modernBetaChunkGenerator.getChunkProvider(); + + return chunkProvider instanceof ChunkProviderNoise chunkProviderNoise ? + chunkProviderNoise.getHeight(level, x, z, ChunkHeightmap.Type.SURFACE_FLOOR) : + chunkProvider.getHeight(level, x, z, Heightmap.Types.OCEAN_FLOOR_WG); + } + + private int sampleMinHeight(LevelHeightAccessor level, int centerBiomeX, int centerBiomeZ) { + int minHeight = Integer.MAX_VALUE; + + for (int localBiomeX = -1; localBiomeX <= 1; ++localBiomeX) { + for (int localBiomeZ = -1; localBiomeZ <= 1; ++localBiomeZ) { + int biomeX = centerBiomeX + localBiomeX; + int biomeZ = centerBiomeZ + localBiomeZ; + + minHeight = Math.min(minHeight, this.sampleFloorHeight(level, biomeX, biomeZ)); + } + } + + return minHeight; + } +} diff --git a/src/main/java/mod/bluestaggo/modernerbeta/level/chunk/ModernBetaChunkGenerator.java b/src/main/java/mod/bluestaggo/modernerbeta/level/chunk/ModernBetaChunkGenerator.java index 9295eefb..df3faa25 100644 --- a/src/main/java/mod/bluestaggo/modernerbeta/level/chunk/ModernBetaChunkGenerator.java +++ b/src/main/java/mod/bluestaggo/modernerbeta/level/chunk/ModernBetaChunkGenerator.java @@ -6,7 +6,7 @@ import mod.bluestaggo.modernerbeta.ModernerBeta; import mod.bluestaggo.modernerbeta.api.level.chunk.surface.SurfaceConfig; import mod.bluestaggo.modernerbeta.compat.ModCompat; import mod.bluestaggo.modernerbeta.imixin.ModernBetaSurfaceSystem; -import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionHandler; +import mod.bluestaggo.modernerbeta.level.biome.injection.InjectionNeeds; import mod.bluestaggo.modernerbeta.mixin.ChunkGeneratorStructureStateAccessor; import mod.bluestaggo.modernerbeta.mixin.NoiseBasedChunkGeneratorAccessor; import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionRule; @@ -62,7 +62,6 @@ import org.jetbrains.annotations.NotNull; import java.util.*; import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; import java.util.stream.Collectors; //? if <1.21 //import java.util.concurrent.Executor; @@ -80,7 +79,6 @@ public class ModernBetaChunkGenerator extends NoiseBasedChunkGenerator { private final HolderGetter presetRegistry; private final HolderGetter surfaceConfigRegistry; private final ModernBetaSettings chunkSettings; - private final Supplier biomeInjector; private boolean useSurfaceRules; private CaveGeneration caveSettings = CaveGeneration.DEFAULT; @@ -99,9 +97,6 @@ public class ModernBetaChunkGenerator extends NoiseBasedChunkGenerator { this.presetRegistry = presetRegistry; this.surfaceConfigRegistry = surfaceConfigRegistry; this.chunkSettings = fixupPreset(chunkProviderSettings); - this.biomeInjector = Suppliers.memoize(() -> - this.biomeSource instanceof ModernBetaBiomeSource modernBetaBiomeSource - ? new BiomeInjectionHandler(this, modernBetaBiomeSource) : null); NoiseBasedChunkGeneratorAccessor accessor = (NoiseBasedChunkGeneratorAccessor) this; Holder settings = DefferedDirectHolder.of(this::noiseGeneratorSettings); @@ -259,7 +254,7 @@ public class ModernBetaChunkGenerator extends NoiseBasedChunkGenerator { if (ModCompat.skipGeneratingChunk(chunkPos.x, chunkPos.z)) return; - this.injectBiomes(chunk, noiseConfig.sampler(), BiomeInjectionRule.Step.PRE); + this.injectBiomes(chunk, BiomeInjectionRule.Step.PRE); if (!this.chunkProvider.skipChunk(chunkPos.x, chunkPos.z, ModernBetaGenerationStep.SURFACE)) { if (this.biomeSource instanceof ModernBetaBiomeSource modernBetaBiomeSource) { @@ -274,7 +269,7 @@ public class ModernBetaChunkGenerator extends NoiseBasedChunkGenerator { } } - this.injectBiomes(chunk, noiseConfig.sampler(), BiomeInjectionRule.Step.POST); + this.injectBiomes(chunk, BiomeInjectionRule.Step.POST); } @Override @@ -293,7 +288,7 @@ public class ModernBetaChunkGenerator extends NoiseBasedChunkGenerator { modernBetaSurfaceSystem.modernerBeta$setupChunkContext(this.chunkProvider); if (this.biomeSource instanceof ModernBetaBiomeSource modernBetaBiomeSource) { - modernBetaSurfaceSystem.modernerBeta$setupBiomeContext(modernBetaBiomeSource.getBiomeProvider()); + modernBetaSurfaceSystem.modernerBeta$setupBiomeContext(modernBetaBiomeSource); } } @@ -536,10 +531,6 @@ public class ModernBetaChunkGenerator extends NoiseBasedChunkGenerator { public ModernBetaSettings getChunkSettings() { return this.chunkSettings; } - - public BiomeInjectionHandler getBiomeInjector() { - return this.biomeInjector.get(); - } public boolean allowSurfaceRules() { return useSurfaceRules; @@ -550,10 +541,9 @@ public class ModernBetaChunkGenerator extends NoiseBasedChunkGenerator { return CODEC; } - private void injectBiomes(ChunkAccess chunk, Sampler noiseSampler, BiomeInjectionRule.Step step) { - BiomeInjectionHandler biomeInjectionHandler = this.biomeInjector.get(); - if (biomeInjectionHandler != null) { - biomeInjectionHandler.injectBiomes(chunk, noiseSampler, step); + private void injectBiomes(ChunkAccess chunk, BiomeInjectionRule.Step step) { + if (this.biomeSource instanceof ModernBetaBiomeSource modernBetaBiomeSource) { + modernBetaBiomeSource.getBiomeInjectionHandler().injectIntoChunk(chunk, step, InjectionNeeds.all()); } } diff --git a/src/main/java/mod/bluestaggo/modernerbeta/mixin/BiomeManagerAccessor.java b/src/main/java/mod/bluestaggo/modernerbeta/mixin/BiomeManagerAccessor.java new file mode 100644 index 00000000..9b2841e6 --- /dev/null +++ b/src/main/java/mod/bluestaggo/modernerbeta/mixin/BiomeManagerAccessor.java @@ -0,0 +1,11 @@ +package mod.bluestaggo.modernerbeta.mixin; + +import net.minecraft.world.level.biome.BiomeManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(BiomeManager.class) +public interface BiomeManagerAccessor { + @Accessor("biomeZoomSeed") + long getBiomeZoomSeed(); +} diff --git a/src/main/java/mod/bluestaggo/modernerbeta/mixin/StructureMixin.java b/src/main/java/mod/bluestaggo/modernerbeta/mixin/StructureMixin.java index 5536d8cf..53010e2e 100644 --- a/src/main/java/mod/bluestaggo/modernerbeta/mixin/StructureMixin.java +++ b/src/main/java/mod/bluestaggo/modernerbeta/mixin/StructureMixin.java @@ -1,10 +1,11 @@ package mod.bluestaggo.modernerbeta.mixin; +import mod.bluestaggo.modernerbeta.level.biome.ModernBetaBiomeSource; import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionRule; import mod.bluestaggo.modernerbeta.level.biome.injection.InjectionNeeds; -import mod.bluestaggo.modernerbeta.level.chunk.ModernBetaChunkGenerator; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.QuartPos; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.levelgen.structure.Structure.GenerationContext; @@ -20,16 +21,16 @@ public abstract class StructureMixin { private static void injectIsValidBiome(GenerationStub result, GenerationContext context, CallbackInfoReturnable info) { BlockPos blockPos = result.position(); - if (context.chunkGenerator() instanceof ModernBetaChunkGenerator chunkGenerator) { - if (chunkGenerator.getBiomeInjector() != null) { - Holder biome = chunkGenerator.getBiomeInjector().getBiomeAtBlock( + if (context.biomeSource() instanceof ModernBetaBiomeSource biomeSource) { + if (biomeSource.getBiomeInjectionHandler() != null) { + Holder biome = biomeSource.getBiomeInjectionHandler().getBiome( context.heightAccessor(), - blockPos.getX(), - blockPos.getY(), - blockPos.getZ(), - context.randomState().sampler(), + QuartPos.fromBlock(blockPos.getX()), + QuartPos.fromBlock(blockPos.getY()), + QuartPos.fromBlock(blockPos.getZ()), BiomeInjectionRule.Step.ALL, - InjectionNeeds.all() + InjectionNeeds.all(), + true ); boolean isBiomeValid = context.validBiome().test(biome); diff --git a/src/main/java/mod/bluestaggo/modernerbeta/mixin/SurfaceSystemMixin.java b/src/main/java/mod/bluestaggo/modernerbeta/mixin/SurfaceSystemMixin.java index 04f19837..5e9b7595 100644 --- a/src/main/java/mod/bluestaggo/modernerbeta/mixin/SurfaceSystemMixin.java +++ b/src/main/java/mod/bluestaggo/modernerbeta/mixin/SurfaceSystemMixin.java @@ -2,10 +2,12 @@ package mod.bluestaggo.modernerbeta.mixin; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import mod.bluestaggo.modernerbeta.api.level.biome.BiomeProvider; import mod.bluestaggo.modernerbeta.api.level.biome.BiomeResolverBlock; import mod.bluestaggo.modernerbeta.api.level.chunk.ChunkProvider; import mod.bluestaggo.modernerbeta.imixin.ModernBetaSurfaceSystem; +import mod.bluestaggo.modernerbeta.level.biome.ModernBetaBiomeSource; +import mod.bluestaggo.modernerbeta.level.biome.injection.BiomeInjectionRule; +import mod.bluestaggo.modernerbeta.level.biome.injection.InjectionNeeds; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.Registry; @@ -28,7 +30,7 @@ import java.util.function.Function; @Mixin(SurfaceSystem.class) public class SurfaceSystemMixin implements ModernBetaSurfaceSystem { @Unique private ChunkProvider modernerBeta$chunkProvider; - @Unique private BiomeProvider modernerBeta$biomeProvider; + @Unique private ModernBetaBiomeSource modernerBeta$biomeProvider; @Unique private final ThreadLocal modernerBeta$surfaceRandom = new ThreadLocal<>(); @Override @@ -37,8 +39,8 @@ public class SurfaceSystemMixin implements ModernBetaSurfaceSystem { } @Override - public void modernerBeta$setupBiomeContext(BiomeProvider biomeProvider) { - this.modernerBeta$biomeProvider = biomeProvider; + public void modernerBeta$setupBiomeContext(ModernBetaBiomeSource biomeSource) { + this.modernerBeta$biomeProvider = biomeSource; } @Override @@ -100,11 +102,32 @@ public class SurfaceSystemMixin implements ModernBetaSurfaceSystem { target = "Lnet/minecraft/world/level/biome/BiomeManager;getBiome(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/core/Holder;" ) ) - private Holder getProperBiomeForMB(BiomeManager instance, BlockPos pos, Operation> original) { - //TODO: this needs to handle biome injection - if (this.modernerBeta$biomeProvider != null && - this.modernerBeta$biomeProvider instanceof BiomeResolverBlock biomeResolver) { - return biomeResolver.getBiomeBlock(pos.getX(), pos.getY(), pos.getZ()); + private Holder getProperBiomeForMB( + BiomeManager instance, + BlockPos pos, + Operation> original, + RandomState randomState, + BiomeManager biomeManager, + Registry biomes, + boolean useLegacyRandomSource, + WorldGenerationContext context, + ChunkAccess chunk, + NoiseChunk noiseChunk, + SurfaceRules.RuleSource ruleSource + ) { + //TODO: this needs to handle biome injection better (?) + if (this.modernerBeta$biomeProvider != null/* && + this.modernerBeta$biomeProvider instanceof BiomeResolverBlock biomeResolver*/) { +// return biomeResolver.getBiomeBlock(pos.getX(), pos.getY(), pos.getZ()); + return this.modernerBeta$biomeProvider.getBiomeInjectionHandler().getBiomeAtBlock( + chunk, + this.modernerBeta$biomeProvider.getBiomeProvider(), + ((BiomeManagerAccessor) instance).getBiomeZoomSeed(), + pos.getX(), pos.getY(), pos.getZ(), + BiomeInjectionRule.Step.PRE, + InjectionNeeds.all(), + true + ); } return original.call(instance, pos);