diff --git a/src/main/java/ru/bclib/api/biomes/BCLBiomeBuilder.java b/src/main/java/ru/bclib/api/biomes/BCLBiomeBuilder.java index da74bf61..4d6332a5 100644 --- a/src/main/java/ru/bclib/api/biomes/BCLBiomeBuilder.java +++ b/src/main/java/ru/bclib/api/biomes/BCLBiomeBuilder.java @@ -1,7 +1,6 @@ package ru.bclib.api.biomes; import net.fabricmc.fabric.api.biome.v1.BiomeModifications; -import net.minecraft.core.Registry; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.data.BuiltinRegistries; import net.minecraft.data.worldgen.BiomeDefaultFeatures; diff --git a/src/main/java/ru/bclib/api/biomes/BiomeAPI.java b/src/main/java/ru/bclib/api/biomes/BiomeAPI.java index 41a4f745..2fe2f267 100644 --- a/src/main/java/ru/bclib/api/biomes/BiomeAPI.java +++ b/src/main/java/ru/bclib/api/biomes/BiomeAPI.java @@ -14,9 +14,9 @@ import net.fabricmc.fabric.impl.biome.TheEndBiomeData; import net.minecraft.client.Minecraft; import net.minecraft.core.Registry; import net.minecraft.data.BuiltinRegistries; +import net.minecraft.data.worldgen.SurfaceRuleData; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.random.WeightedRandomList; import net.minecraft.world.entity.EntityType; @@ -24,12 +24,18 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biome.BiomeCategory; import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.biome.Climate; import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.levelgen.GenerationStep.Carving; import net.minecraft.world.level.levelgen.GenerationStep.Decoration; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.feature.StructureFeature; @@ -49,16 +55,16 @@ import ru.bclib.world.generator.BiomePicker; import ru.bclib.world.structures.BCLStructureFeature; import java.util.ArrayList; -import java.util.EnumMap; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Random; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; +import java.util.stream.Collectors; public class BiomeAPI { /** @@ -76,6 +82,7 @@ public class BiomeAPI { private static Registry biomeRegistry; private static final Map>> MODIFICATIONS = Maps.newHashMap(); + private static final Map SURFACE_RULES = Maps.newHashMap(); private static final Set MODIFIED_BIOMES = Sets.newHashSet(); public static final BCLBiome NETHER_WASTES_BIOME = registerNetherBiome(getFromRegistry(Biomes.NETHER_WASTES)); @@ -91,12 +98,14 @@ public class BiomeAPI { public static final BCLBiome END_BARRENS = registerEndVoidBiome(getFromRegistry(new ResourceLocation("end_barrens"))); public static final BCLBiome SMALL_END_ISLANDS = registerEndVoidBiome(getFromRegistry(new ResourceLocation("small_end_islands"))); + private static SurfaceRules.RuleSource netherRuleSource; + private static SurfaceRules.RuleSource endRuleSource; + /** * Initialize registry for current server. - * - * @param server - {@link MinecraftServer} + * @param biomeRegistry - {@link Registry} for {@link Biome}. */ - public static void initRegistry( Registry biomeRegistry) { + public static void initRegistry(Registry biomeRegistry) { BiomeAPI.biomeRegistry = biomeRegistry; CLIENT.clear(); } @@ -411,19 +420,46 @@ public class BiomeAPI { registerBiomeModification(Level.END, modification); } + /** + * Returns surface rule source for the Nether. + * @return {@link SurfaceRules.RuleSource}. + */ + public static SurfaceRules.RuleSource getNetherRuleSource() { + return netherRuleSource; + } + + /** + * Returns surface rule source for the End. + * @return {@link SurfaceRules.RuleSource}. + */ + public static SurfaceRules.RuleSource getEndRuleSource() { + return endRuleSource; + } + /** * Will apply biome modifications to world, internal usage only. * @param level */ public static void applyModifications(ServerLevel level) { + BiomeSource source = level.getChunkSource().getGenerator().getBiomeSource(); + Set biomes = source.possibleBiomes(); + + if (level.dimension() == Level.NETHER) { + RuleSource[] rules = getRuleSources(biomes, level.dimension()); + netherRuleSource = rules.length > 0 ? SurfaceRules.sequence(rules) : null; + System.out.println("Adding nether sources! " + rules.length); + } + else if (level.dimension() == Level.END) { + RuleSource[] rules = getRuleSources(biomes, level.dimension()); + endRuleSource = rules.length > 0 ? SurfaceRules.sequence(rules) : null; + System.out.println("Adding end sources! " + rules.length); + } + List> modifications = MODIFICATIONS.get(level.dimension()); if (modifications == null) { return; } - BiomeSource source = level.getChunkSource().getGenerator().getBiomeSource(); - Set biomes = source.possibleBiomes(); - biomes.forEach(biome -> { ResourceLocation biomeID = getBiomeID(biome); boolean modify = isDatapackBiome(biomeID); @@ -442,6 +478,41 @@ public class BiomeAPI { }); } + private static SurfaceRules.RuleSource[] getRuleSources(Set biomes, ResourceKey dimensionType) { + Set biomeIDs = biomes.stream().map(biome -> getBiomeID(biome)).collect(Collectors.toSet()); + List rules = Lists.newArrayList(); + SURFACE_RULES.forEach((biomeID, rule) -> { + if (biomeIDs.contains(biomeID)) { + rules.add(rule); + } + }); + + // Try handle biomes from other dimension, may work not as expected + // Will not work + /*Optional optional = biomes + .stream() + .filter(biome -> biome.getBiomeCategory() != BiomeCategory.THEEND && biome.getBiomeCategory() != BiomeCategory.NETHER) + .findAny(); + if (optional.isPresent()) { + rules.add(SurfaceRuleData.overworld()); + } + + if (dimensionType == Level.NETHER) { + optional = biomes.stream().filter(biome -> biome.getBiomeCategory() != BiomeCategory.THEEND).findAny(); + if (optional.isPresent()) { + rules.add(SurfaceRuleData.end()); + } + } + else if (dimensionType == Level.END) { + optional = biomes.stream().filter(biome -> biome.getBiomeCategory() != BiomeCategory.NETHER).findAny(); + if (optional.isPresent()) { + rules.add(SurfaceRuleData.end()); + } + }*/ + + return rules.toArray(new SurfaceRules.RuleSource[rules.size()]); + } + /** * Adds new features to existing biome. * @param biome {@link Biome} to add features in. @@ -503,21 +574,16 @@ public class BiomeAPI { * @param structure {@link ConfiguredStructureFeature} to add. */ public static void addBiomeStructure(ResourceKey biomeKey, ConfiguredStructureFeature structure) { - //BiomeStructureStartsImpl.addStart(registries, structure, getBiomeID(biome)); changeStructureStarts(structureMap -> { Multimap, ResourceKey> configuredMap = structureMap.computeIfAbsent(structure.feature, k -> HashMultimap.create()); configuredMap.put(structure, biomeKey); }); - - } public static void addBiomeStructure(Biome biome, ConfiguredStructureFeature structure) { - //BiomeStructureStartsImpl.addStart(registries, structure, getBiomeID(biome)); changeStructureStarts(structureMap -> { Multimap, ResourceKey> configuredMap = structureMap.computeIfAbsent(structure.feature, k -> HashMultimap.create()); - var key = getBiomeKey(biome); if (key!=null) { configuredMap.put(structure, key); @@ -525,11 +591,8 @@ public class BiomeAPI { BCLib.LOGGER.error("Unable to find Biome " + getBiomeID(biome)); } }); - - } - private static void changeStructureStarts(Consumer, Multimap, ResourceKey>>> modifier) { Registry chunkGenSettingsRegistry = BuiltinRegistries.NOISE_GENERATOR_SETTINGS; @@ -539,11 +602,8 @@ public class BiomeAPI { modifier.accept(structureMap); setMutableStructureConfig(entry.getValue(), structureMap); } - - } - /** * Adds new structure feature to existing biome. * @param biomeKey {@link ResourceKey} for the {@link Biome} to add structure feature in. @@ -552,7 +612,6 @@ public class BiomeAPI { public static void addBiomeStructure(ResourceKey biomeKey, BCLStructureFeature structure) { addBiomeStructure(biomeKey, structure.getFeatureConfigured()); } - /** * Adds new structure features to existing biome. @@ -565,6 +624,40 @@ public class BiomeAPI { } } + /** + * Adds new carver into existing biome. + * @param biome {@link Biome} to add carver in. + * @param carver {@link ConfiguredWorldCarver} to add. + * @param stage {@link Carving} stage. + */ + public static void addBiomeCarver(Biome biome, ConfiguredWorldCarver carver, Carving stage) { + BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings(); + Map>>> carvers = CollectionsUtil.getMutable(accessor.bclib_getCarvers()); + List>> carverList = CollectionsUtil.getMutable(carvers.getOrDefault(stage, new ArrayList<>())); + carvers.put(stage, carverList); + carverList.add(() -> carver); + accessor.bclib_setCarvers(carvers); + } + + /** + * Adds surface rule to specified biome. + * @param biomeID biome {@link ResourceLocation}. + * @param source {@link SurfaceRules.RuleSource}. + */ + public static void addSurfaceRule(ResourceLocation biomeID, SurfaceRules.RuleSource source) { + SURFACE_RULES.put(biomeID, source); + } + + /** + * Get surface rule for the biome using its {@link ResourceLocation} ID as a key. + * @param biomeID {@link ResourceLocation} biome ID. + * @return {@link SurfaceRules.RuleSource}. + */ + @Nullable + public static SurfaceRules.RuleSource getSurfaceRule(ResourceLocation biomeID) { + return SURFACE_RULES.get(biomeID); + } + /** * Adds mob spawning to specified biome. * @param biome {@link Biome} to add mob spawning. @@ -633,11 +726,12 @@ public class BiomeAPI { //inspired by net.fabricmc.fabric.impl.biome.modification.BiomeStructureStartsImpl private static void setMutableStructureConfig(NoiseGeneratorSettings settings, Map, Multimap, ResourceKey>> structureStarts) { - final StructureSettingsAccessor access = (StructureSettingsAccessor)settings.structureSettings(); - access.bcl_setStructureConfig(structureStarts.entrySet().stream() - .collect(ImmutableMap.toImmutableMap( - Map.Entry::getKey, - e -> ImmutableMultimap.copyOf(e.getValue()) - ))); + final StructureSettingsAccessor access = (StructureSettingsAccessor) settings.structureSettings(); + access.bcl_setStructureConfig( + structureStarts + .entrySet() + .stream() + .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, e -> ImmutableMultimap.copyOf(e.getValue()))) + ); } } diff --git a/src/main/java/ru/bclib/mixin/common/BiomeGenerationSettingsAccessor.java b/src/main/java/ru/bclib/mixin/common/BiomeGenerationSettingsAccessor.java index b31f859e..fcb6ec6f 100644 --- a/src/main/java/ru/bclib/mixin/common/BiomeGenerationSettingsAccessor.java +++ b/src/main/java/ru/bclib/mixin/common/BiomeGenerationSettingsAccessor.java @@ -1,12 +1,16 @@ package ru.bclib.mixin.common; import net.minecraft.world.level.biome.BiomeGenerationSettings; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.GenerationStep.Carving; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; import net.minecraft.world.level.levelgen.placement.PlacedFeature; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Supplier; @@ -24,4 +28,10 @@ public interface BiomeGenerationSettingsAccessor { @Accessor("featureSet") void bclib_setFeatureSet(Set features); + + @Accessor("carvers") + Map>>> bclib_getCarvers(); + + @Accessor("carvers") + void bclib_setCarvers(Map>>> features); } diff --git a/src/main/java/ru/bclib/mixin/common/MainMixin.java b/src/main/java/ru/bclib/mixin/common/MainMixin.java index e672681d..059129e0 100644 --- a/src/main/java/ru/bclib/mixin/common/MainMixin.java +++ b/src/main/java/ru/bclib/mixin/common/MainMixin.java @@ -1,7 +1,6 @@ package ru.bclib.mixin.common; import net.minecraft.server.Main; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java b/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java index 23bf14d9..e337b2c6 100644 --- a/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java +++ b/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java @@ -21,7 +21,6 @@ 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 ru.bclib.api.biomes.BiomeAPI; import ru.bclib.api.dataexchange.DataExchangeAPI; import ru.bclib.recipes.BCLRecipeManager; diff --git a/src/main/java/ru/bclib/mixin/common/ServerLevelMixin.java b/src/main/java/ru/bclib/mixin/common/ServerLevelMixin.java index d0910008..d405536a 100644 --- a/src/main/java/ru/bclib/mixin/common/ServerLevelMixin.java +++ b/src/main/java/ru/bclib/mixin/common/ServerLevelMixin.java @@ -9,13 +9,11 @@ import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.Level; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.WritableLevelData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import ru.bclib.api.LifeCycleAPI; diff --git a/src/main/java/ru/bclib/mixin/common/StructureSettingsAccessor.java b/src/main/java/ru/bclib/mixin/common/StructureSettingsAccessor.java index e48342ef..cb323706 100644 --- a/src/main/java/ru/bclib/mixin/common/StructureSettingsAccessor.java +++ b/src/main/java/ru/bclib/mixin/common/StructureSettingsAccessor.java @@ -3,20 +3,14 @@ package ru.bclib.mixin.common; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import net.minecraft.resources.ResourceKey; -import net.minecraft.util.random.WeightedRandomList; -import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData; import net.minecraft.world.level.levelgen.StructureSettings; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.feature.StructureFeature; -import net.minecraft.world.level.levelgen.feature.configurations.StructureFeatureConfiguration; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.Map; - @Mixin(StructureSettings.class) public interface StructureSettingsAccessor { @Accessor("configuredStructures") diff --git a/src/main/java/ru/bclib/mixin/common/SurfaceRuleDataMixin.java b/src/main/java/ru/bclib/mixin/common/SurfaceRuleDataMixin.java new file mode 100644 index 00000000..4e04d7e0 --- /dev/null +++ b/src/main/java/ru/bclib/mixin/common/SurfaceRuleDataMixin.java @@ -0,0 +1,31 @@ +package ru.bclib.mixin.common; + +import net.minecraft.data.worldgen.SurfaceRuleData; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; +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.api.biomes.BiomeAPI; + +@Mixin(SurfaceRuleData.class) +public class SurfaceRuleDataMixin { + @Inject(method = "nether", at = @At("RETURN"), cancellable = true) + private static void bclib_addNetherRuleSource(CallbackInfoReturnable info) { + if (BiomeAPI.getNetherRuleSource() != null) { + RuleSource source = info.getReturnValue(); + source = SurfaceRules.sequence(source, BiomeAPI.getNetherRuleSource()); + info.setReturnValue(source); + } + } + + @Inject(method = "end", at = @At("RETURN"), cancellable = true) + private static void bclib_addEndRuleSource(CallbackInfoReturnable info) { + if (BiomeAPI.getEndRuleSource() != null) { + RuleSource source = info.getReturnValue(); + source = SurfaceRules.sequence(source, BiomeAPI.getEndRuleSource()); + info.setReturnValue(source); + } + } +} diff --git a/src/main/java/ru/bclib/world/biomes/BCLBiome.java b/src/main/java/ru/bclib/world/biomes/BCLBiome.java index ab00606f..bc0cb223 100644 --- a/src/main/java/ru/bclib/world/biomes/BCLBiome.java +++ b/src/main/java/ru/bclib/world/biomes/BCLBiome.java @@ -8,11 +8,8 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import org.jetbrains.annotations.Nullable; -import ru.bclib.api.biomes.BiomeAPI; import ru.bclib.util.WeightedList; -import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; diff --git a/src/main/java/ru/bclib/world/biomes/BCLBiomeDef.java b/src/main/java/ru/bclib/world/biomes/BCLBiomeDef.java index 9fe6fdd1..f0a59596 100644 --- a/src/main/java/ru/bclib/world/biomes/BCLBiomeDef.java +++ b/src/main/java/ru/bclib/world/biomes/BCLBiomeDef.java @@ -27,7 +27,6 @@ import net.minecraft.world.level.levelgen.carver.CarverConfiguration; import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature; -import ru.bclib.api.biomes.BiomeAPI; import ru.bclib.config.IdConfig; import ru.bclib.config.PathConfig; import ru.bclib.util.ColorUtil; diff --git a/src/main/resources/bclib.mixins.common.json b/src/main/resources/bclib.mixins.common.json index df63f458..da8faabc 100644 --- a/src/main/resources/bclib.mixins.common.json +++ b/src/main/resources/bclib.mixins.common.json @@ -37,7 +37,8 @@ "MainMixin", "BiomeGenerationSettingsAccessor", "MobSpawnSettingsAccessor", - "StructureSettingsAccessor" + "StructureSettingsAccessor", + "SurfaceRuleDataMixin" ], "injectors": { "defaultRequire": 1