From 683427c31202c773d7f4c84446b82ea9a3484372 Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Fri, 13 Aug 2021 21:55:40 +0300 Subject: [PATCH] Nether biome source (WIP) --- src/main/java/ru/bclib/BCLib.java | 2 + src/main/java/ru/bclib/api/BiomeAPI.java | 50 +++++++++-- .../mixin/common/DimensionTypeMixin.java | 35 ++++++++ ...sor.java => WeightedBiomePickerMixin.java} | 2 +- .../mixin/common/WorldGenRegionMixin.java | 26 ++++++ .../world/generator/BCLibEndBiomeSource.java | 14 +-- .../generator/BCLibNetherBiomeSource.java | 86 +++++++++++++++++++ .../world/generator/GeneratorOptions.java | 9 ++ src/main/resources/bclib.mixins.common.json | 3 + 9 files changed, 215 insertions(+), 12 deletions(-) create mode 100644 src/main/java/ru/bclib/mixin/common/DimensionTypeMixin.java rename src/main/java/ru/bclib/mixin/common/{WeightedBiomePickerAccessor.java => WeightedBiomePickerMixin.java} (94%) create mode 100644 src/main/java/ru/bclib/mixin/common/WorldGenRegionMixin.java create mode 100644 src/main/java/ru/bclib/world/generator/BCLibNetherBiomeSource.java diff --git a/src/main/java/ru/bclib/BCLib.java b/src/main/java/ru/bclib/BCLib.java index 061ac50f..8f724bc1 100644 --- a/src/main/java/ru/bclib/BCLib.java +++ b/src/main/java/ru/bclib/BCLib.java @@ -17,6 +17,7 @@ import ru.bclib.registry.BaseBlockEntities; import ru.bclib.registry.BaseRegistry; import ru.bclib.util.Logger; import ru.bclib.world.generator.BCLibEndBiomeSource; +import ru.bclib.world.generator.BCLibNetherBiomeSource; import ru.bclib.world.surface.BCLSurfaceBuilders; import java.util.List; @@ -31,6 +32,7 @@ public class BCLib implements ModInitializer { BaseBlockEntities.register(); BCLSurfaceBuilders.register(); BCLibEndBiomeSource.register(); + BCLibNetherBiomeSource.register(); TagAPI.init(); CraftingRecipes.init(); WorldDataAPI.registerModCache(MOD_ID); diff --git a/src/main/java/ru/bclib/api/BiomeAPI.java b/src/main/java/ru/bclib/api/BiomeAPI.java index 27e80151..e7faf667 100644 --- a/src/main/java/ru/bclib/api/BiomeAPI.java +++ b/src/main/java/ru/bclib/api/BiomeAPI.java @@ -32,6 +32,19 @@ public class BiomeAPI { */ public static final BCLBiome EMPTY_BIOME = new BCLBiome(Biomes.THE_VOID.location(), BuiltinRegistries.BIOME.get(Biomes.THE_VOID), 1, 0); + public static final BCLBiome NETHER_WASTES_BIOME = registerNetherBiome(BuiltinRegistries.BIOME.get(new ResourceLocation("nether_wastes"))); + public static final BCLBiome CRIMSON_FOREST_BIOME = registerNetherBiome(BuiltinRegistries.BIOME.get(new ResourceLocation("crimson_forest"))); + public static final BCLBiome WARPED_FOREST_BIOME = registerNetherBiome(BuiltinRegistries.BIOME.get(new ResourceLocation("warped_forest"))); + public static final BCLBiome SOUL_SAND_VALLEY_BIOME = registerNetherBiome(BuiltinRegistries.BIOME.get(new ResourceLocation("soul_sand_valley"))); + public static final BCLBiome BASALT_DELTAS_BIOME = registerNetherBiome(BuiltinRegistries.BIOME.get(new ResourceLocation("basalt_deltas"))); + + public static final BCLBiome THE_END = registerEndLandBiome(BuiltinRegistries.BIOME.get(new ResourceLocation("the_end"))); + public static final BCLBiome END_MIDLANDS = registerSubBiome(THE_END, BuiltinRegistries.BIOME.get(new ResourceLocation("end_midlands")), 0.5F); + public static final BCLBiome END_HIGHLANDS = registerSubBiome(THE_END, BuiltinRegistries.BIOME.get(new ResourceLocation("end_highlands")), 0.5F); + + public static final BCLBiome END_BARRENS = registerEndVoidBiome(BuiltinRegistries.BIOME.get(new ResourceLocation("end_barrens"))); + public static final BCLBiome SMALL_END_ISLANDS = registerEndVoidBiome(BuiltinRegistries.BIOME.get(new ResourceLocation("small_end_islands"))); + private static final Map NETHER_BIOMES = Maps.newHashMap(); private static final Map END_LAND_BIOMES = Maps.newHashMap(); private static final Map END_VOID_BIOMES = Maps.newHashMap(); @@ -57,18 +70,33 @@ public class BiomeAPI { /** * Register {@link BCLBiome} instance and its {@link Biome} if necessary. * @param biome {@link BCLBiome} + * @return {@link BCLBiome} */ - public static void registerBiome(BCLBiome biome) { + public static BCLBiome registerBiome(BCLBiome biome) { if (BuiltinRegistries.BIOME.get(biome.getID()) == null) { Registry.register(BuiltinRegistries.BIOME, biome.getID(), biome.getBiome()); } ID_MAP.put(biome.getID(), biome); + return biome; + } + + public static BCLBiome registerSubBiome(BCLBiome parent, BCLBiome subBiome) { + registerBiome(subBiome); + parent.addSubBiome(subBiome); + return subBiome; + } + + public static BCLBiome registerSubBiome(BCLBiome parent, Biome biome, float chance) { + ResourceKey key = BuiltinRegistries.BIOME.getResourceKey(biome).get(); + BCLBiome subBiome = new BCLBiome(key.location(), biome, 1, chance); + return registerSubBiome(parent, subBiome); } /** * Register {@link BCLBiome} instance and its {@link Biome} if necessary. * After that biome will be added to BCLib Nether Biome Generator and into Fabric Biome API. * @param biome {@link BCLBiome} + * @return {@link BCLBiome} */ public static void registerNetherBiome(BCLBiome biome) { registerBiome(biome); @@ -89,63 +117,73 @@ public class BiomeAPI { * Register {@link BCLBiome} instance and its {@link Biome} if necessary. * After that biome will be added to BCLib Nether Biome Generator and into Fabric Biome API. * @param biome {@link BCLBiome} + * @return {@link BCLBiome} */ - public static void registerNetherBiome(Biome biome) { + public static BCLBiome registerNetherBiome(Biome biome) { ResourceKey key = BuiltinRegistries.BIOME.getResourceKey(biome).get(); BCLBiome bclBiome = new BCLBiome(key.location(), biome, 1, 1); NETHER_BIOME_PICKER.addBiome(bclBiome); registerBiome(bclBiome); + return bclBiome; } /** * Register {@link BCLBiome} instance and its {@link Biome} if necessary. * After that biome will be added to BCLib End Biome Generator and into Fabric Biome API as a land biome (will generate only on islands). * @param biome {@link BCLBiome} + * @return {@link BCLBiome} */ - public static void registerEndLandBiome(BCLBiome biome) { + public static BCLBiome registerEndLandBiome(BCLBiome biome) { registerBiome(biome); END_LAND_BIOME_PICKER.addBiome(biome); float weight = biome.getGenChance(); ResourceKey key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).get(); InternalBiomeData.addEndBiomeReplacement(Biomes.END_HIGHLANDS, key, weight); InternalBiomeData.addEndBiomeReplacement(Biomes.END_MIDLANDS, key, weight); + return biome; } /** * Register {@link BCLBiome} wrapper for {@link Biome}. * After that biome will be added to BCLib End Biome Generator and into Fabric Biome API as a land biome (will generate only on islands). * @param biome {@link BCLBiome} + * @return {@link BCLBiome} */ - public static void registerEndLandBiome(Biome biome) { + public static BCLBiome registerEndLandBiome(Biome biome) { ResourceKey key = BuiltinRegistries.BIOME.getResourceKey(biome).get(); BCLBiome bclBiome = new BCLBiome(key.location(), biome, 1, 1); END_LAND_BIOME_PICKER.addBiome(bclBiome); registerBiome(bclBiome); + return bclBiome; } /** * Register {@link BCLBiome} instance and its {@link Biome} if necessary. * After that biome will be added to BCLib End Biome Generator and into Fabric Biome API as a void biome (will generate only in the End void - between islands). * @param biome {@link BCLBiome} + * @return {@link BCLBiome} */ - public static void registerEndVoidBiome(BCLBiome biome) { + public static BCLBiome registerEndVoidBiome(BCLBiome biome) { registerBiome(biome); END_VOID_BIOME_PICKER.addBiome(biome); float weight = biome.getGenChance(); ResourceKey key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).get(); InternalBiomeData.addEndBiomeReplacement(Biomes.SMALL_END_ISLANDS, key, weight); + return biome; } /** * Register {@link BCLBiome} instance and its {@link Biome} if necessary. * After that biome will be added to BCLib End Biome Generator and into Fabric Biome API as a void biome (will generate only in the End void - between islands). * @param biome {@link BCLBiome} + * @return {@link BCLBiome} */ - public static void registerEndVoidBiome(Biome biome) { + public static BCLBiome registerEndVoidBiome(Biome biome) { ResourceKey key = BuiltinRegistries.BIOME.getResourceKey(biome).get(); BCLBiome bclBiome = new BCLBiome(key.location(), biome, 1, 1); END_VOID_BIOME_PICKER.addBiome(bclBiome); registerBiome(bclBiome); + return bclBiome; } /** diff --git a/src/main/java/ru/bclib/mixin/common/DimensionTypeMixin.java b/src/main/java/ru/bclib/mixin/common/DimensionTypeMixin.java new file mode 100644 index 00000000..8ff798d3 --- /dev/null +++ b/src/main/java/ru/bclib/mixin/common/DimensionTypeMixin.java @@ -0,0 +1,35 @@ +package ru.bclib.mixin.common; + +import net.minecraft.core.Registry; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +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 ru.bclib.world.generator.BCLibEndBiomeSource; +import ru.bclib.world.generator.BCLibNetherBiomeSource; + +@Mixin(value = DimensionType.class, priority = 100) +public class DimensionTypeMixin { + @Inject(method = "defaultNetherGenerator", at = @At("HEAD"), cancellable = true) + private static void be_replaceNetherBiomeSource(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed, CallbackInfoReturnable info) { + info.setReturnValue(new NoiseBasedChunkGenerator( + new BCLibNetherBiomeSource(biomeRegistry, seed), + seed, + () -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END) + )); + } + + @Inject(method = "defaultEndGenerator", at = @At("HEAD"), cancellable = true) + private static void be_replaceEndBiomeSource(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed, CallbackInfoReturnable info) { + info.setReturnValue(new NoiseBasedChunkGenerator( + new BCLibEndBiomeSource(biomeRegistry, seed), + seed, + () -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END) + )); + } +} \ No newline at end of file diff --git a/src/main/java/ru/bclib/mixin/common/WeightedBiomePickerAccessor.java b/src/main/java/ru/bclib/mixin/common/WeightedBiomePickerMixin.java similarity index 94% rename from src/main/java/ru/bclib/mixin/common/WeightedBiomePickerAccessor.java rename to src/main/java/ru/bclib/mixin/common/WeightedBiomePickerMixin.java index 97f82dcd..602eefcc 100644 --- a/src/main/java/ru/bclib/mixin/common/WeightedBiomePickerAccessor.java +++ b/src/main/java/ru/bclib/mixin/common/WeightedBiomePickerMixin.java @@ -15,7 +15,7 @@ import ru.bclib.interfaces.BiomeListProvider; import java.util.List; @Mixin(value = WeightedBiomePicker.class, remap = false) -public class WeightedBiomePickerAccessor implements BiomeListProvider { +public class WeightedBiomePickerMixin implements BiomeListProvider { private final List> biomes = Lists.newArrayList(); @Inject(method = "addBiome", at = @At("TAIL")) diff --git a/src/main/java/ru/bclib/mixin/common/WorldGenRegionMixin.java b/src/main/java/ru/bclib/mixin/common/WorldGenRegionMixin.java new file mode 100644 index 00000000..a8866f3e --- /dev/null +++ b/src/main/java/ru/bclib/mixin/common/WorldGenRegionMixin.java @@ -0,0 +1,26 @@ +package ru.bclib.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.WorldGenRegion; +import net.minecraft.world.level.ChunkPos; +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; + +@Mixin(WorldGenRegion.class) +public class WorldGenRegionMixin { + @Final + @Shadow + private ChunkPos center; + + @Inject(method = "ensureCanWrite", at = @At("HEAD"), cancellable = true) + private void be_alterBlockCheck(BlockPos blockPos, CallbackInfoReturnable info) { + int x = blockPos.getX() >> 4; + int z = blockPos.getZ() >> 4; + WorldGenRegion region = (WorldGenRegion) (Object) this; + info.setReturnValue(Math.abs(x - center.x) < 2 && Math.abs(z - center.z) < 2); + } +} diff --git a/src/main/java/ru/bclib/world/generator/BCLibEndBiomeSource.java b/src/main/java/ru/bclib/world/generator/BCLibEndBiomeSource.java index 0f96c365..4fa936ae 100644 --- a/src/main/java/ru/bclib/world/generator/BCLibEndBiomeSource.java +++ b/src/main/java/ru/bclib/world/generator/BCLibEndBiomeSource.java @@ -42,6 +42,8 @@ public class BCLibEndBiomeSource extends BiomeSource { public BCLibEndBiomeSource(Registry biomeRegistry, long seed) { super(getBiomes(biomeRegistry)); + BiomeAPI.END_LAND_BIOME_PICKER.clearMutables(); + BiomeAPI.END_VOID_BIOME_PICKER.clearMutables(); biomeRegistry.forEach(biome -> { ResourceLocation key = biomeRegistry.getKey(biome); BCLBiome bclBiome = BiomeAPI.getBiome(key); @@ -50,6 +52,8 @@ public class BCLibEndBiomeSource extends BiomeSource { BiomeAPI.END_LAND_BIOME_PICKER.addBiomeMutable(bclBiome); } }); + BiomeAPI.END_LAND_BIOME_PICKER.rebuild(); + BiomeAPI.END_VOID_BIOME_PICKER.rebuild(); this.mapLand = new BiomeMap(seed, GeneratorOptions.getBiomeSizeEndLand(), BiomeAPI.END_LAND_BIOME_PICKER); this.mapVoid = new BiomeMap(seed, GeneratorOptions.getBiomeSizeEndVoid(), BiomeAPI.END_VOID_BIOME_PICKER); @@ -74,6 +78,7 @@ public class BCLibEndBiomeSource extends BiomeSource { public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) { long i = (long) biomeX * (long) biomeX; long j = (long) biomeZ * (long) biomeZ; + long check = GeneratorOptions.isFarEndBiomes() ? 65536L : 625L; long dist = i + j; if ((biomeX & 31) == 0 && (biomeZ & 31) == 0) { @@ -81,9 +86,8 @@ public class BCLibEndBiomeSource extends BiomeSource { mapVoid.clearCache(); } - BCLBiome endBiome = null; if (endLandFunction == null) { - if (dist <= 65536L) return centerBiome; + if (dist <= check) return centerBiome; float height = TheEndBiomeSource.getHeightValue( noise, (biomeX >> 1) + 1, @@ -104,10 +108,10 @@ public class BCLibEndBiomeSource extends BiomeSource { else { pos.setLocation(biomeX, biomeZ); if (endLandFunction.apply(pos)) { - return dist <= 65536L ? centerBiome : mapLand.getBiome(biomeX << 2, biomeZ << 2).getActualBiome(); + return dist <= check ? centerBiome : mapLand.getBiome(biomeX << 2, biomeZ << 2).getActualBiome(); } else { - return dist <= 65536L ? barrens : mapVoid.getBiome(biomeX << 2, biomeZ << 2).getActualBiome(); + return dist <= check ? barrens : mapVoid.getBiome(biomeX << 2, biomeZ << 2).getActualBiome(); } } } @@ -123,6 +127,6 @@ public class BCLibEndBiomeSource extends BiomeSource { } public static void register() { - Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("better_end_biome_source"), CODEC); + Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("end_biome_source"), CODEC); } } diff --git a/src/main/java/ru/bclib/world/generator/BCLibNetherBiomeSource.java b/src/main/java/ru/bclib/world/generator/BCLibNetherBiomeSource.java new file mode 100644 index 00000000..e9472f4f --- /dev/null +++ b/src/main/java/ru/bclib/world/generator/BCLibNetherBiomeSource.java @@ -0,0 +1,86 @@ +package ru.bclib.world.generator; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.Registry; +import net.minecraft.resources.RegistryLookupCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSource; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.biome.TheEndBiomeSource; +import net.minecraft.world.level.levelgen.WorldgenRandom; +import net.minecraft.world.level.levelgen.synth.SimplexNoise; +import ru.bclib.BCLib; +import ru.bclib.api.BiomeAPI; +import ru.bclib.noise.OpenSimplexNoise; +import ru.bclib.world.biomes.BCLBiome; + +import java.awt.Point; +import java.util.List; +import java.util.function.Function; + +public class BCLibNetherBiomeSource extends BiomeSource { + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group(RegistryLookupCodec.create(Registry.BIOME_REGISTRY).forGetter((theEndBiomeSource) -> { + return theEndBiomeSource.biomeRegistry; + }), Codec.LONG.fieldOf("seed").stable().forGetter((theEndBiomeSource) -> { + return theEndBiomeSource.seed; + })).apply(instance, instance.stable(BCLibNetherBiomeSource::new)); + }); + private final Registry biomeRegistry; + private BiomeMap biomeMap; + private final long seed; + + public BCLibNetherBiomeSource(Registry biomeRegistry, long seed) { + super(getBiomes(biomeRegistry)); + + BiomeAPI.NETHER_BIOME_PICKER.clearMutables(); + biomeRegistry.forEach(biome -> { + ResourceLocation key = biomeRegistry.getKey(biome); + BCLBiome bclBiome = BiomeAPI.getBiome(key); + bclBiome.updateActualBiomes(biomeRegistry); + if (!BiomeAPI.NETHER_BIOME_PICKER.containsImmutable(key)) { + BiomeAPI.NETHER_BIOME_PICKER.addBiomeMutable(bclBiome); + } + }); + BiomeAPI.NETHER_BIOME_PICKER.rebuild(); + + this.biomeMap = new BiomeMap(seed, GeneratorOptions.getBiomeSizeEndLand(), BiomeAPI.NETHER_BIOME_PICKER); + this.biomeRegistry = biomeRegistry; + this.seed = seed; + + WorldgenRandom chunkRandom = new WorldgenRandom(seed); + chunkRandom.consumeCount(17292); + } + + private static List getBiomes(Registry biomeRegistry) { + return biomeRegistry.stream().filter(biome -> BiomeAPI.isEndBiome(biomeRegistry.getKey(biome))).toList(); + } + + @Override + public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) { + long i = (long) biomeX * (long) biomeX; + long j = (long) biomeZ * (long) biomeZ; + + if ((biomeX & 31) == 0 && (biomeZ & 31) == 0) { + biomeMap.clearCache(); + } + + return biomeMap.getBiome(biomeX << 2, biomeZ << 2).getActualBiome(); + } + + @Override + public BiomeSource withSeed(long seed) { + return new BCLibNetherBiomeSource(biomeRegistry, seed); + } + + @Override + protected Codec codec() { + return CODEC; + } + + public static void register() { + Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("nether_biome_source"), CODEC); + } +} diff --git a/src/main/java/ru/bclib/world/generator/GeneratorOptions.java b/src/main/java/ru/bclib/world/generator/GeneratorOptions.java index 4eca70cc..d7bbc22a 100644 --- a/src/main/java/ru/bclib/world/generator/GeneratorOptions.java +++ b/src/main/java/ru/bclib/world/generator/GeneratorOptions.java @@ -11,6 +11,7 @@ public class GeneratorOptions { private static int biomeSizeEndLand; private static int biomeSizeEndVoid; private static Function endLandFunction; + private static boolean farEndBiomes; public static void init() { biomeSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap", "biomeSize", 256); @@ -37,4 +38,12 @@ public class GeneratorOptions { public static Function getEndLandFunction() { return endLandFunction; } + + public static boolean isFarEndBiomes() { + return farEndBiomes; + } + + public static void setFarEndBiomes(boolean farEndBiomes) { + GeneratorOptions.farEndBiomes = farEndBiomes; + } } diff --git a/src/main/resources/bclib.mixins.common.json b/src/main/resources/bclib.mixins.common.json index ecf7c440..bb0e135e 100644 --- a/src/main/resources/bclib.mixins.common.json +++ b/src/main/resources/bclib.mixins.common.json @@ -4,11 +4,14 @@ "package": "ru.bclib.mixin.common", "compatibilityLevel": "JAVA_16", "mixins": [ + "WeightedBiomePickerMixin", "ComposterBlockAccessor", "PotionBrewingAccessor", "RecipeManagerAccessor", "EnchantmentMenuMixin", "MinecraftServerMixin", + "WorldGenRegionMixin", + "DimensionTypeMixin", "RecipeManagerMixin", "BoneMealItemMixin", "ServerLevelMixin",