Improved SurfaceRule Handling

This commit is contained in:
Frank 2022-05-27 00:42:34 +02:00
parent e08d85b605
commit bdf30109f6
16 changed files with 266 additions and 161 deletions

View file

@ -1,20 +1,16 @@
# Done to increase the memory available to gradle. # Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx2G org.gradle.jvmargs=-Xmx2G
#Loom #Loom
loom_version=0.11-SNAPSHOT loom_version=0.11-SNAPSHOT
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/versions.html # check these on https://fabricmc.net/versions.html
minecraft_version= 1.19-pre1 minecraft_version=1.19-pre3
loader_version= 0.14.5 loader_version=0.14.6
fabric_version = 0.52.4+1.19 fabric_version=0.53.4+1.19
# Mod Properties # Mod Properties
mod_version = 2.0.0 mod_version=2.0.0
maven_group = org.betterx.bclib maven_group=org.betterx.bclib
archives_base_name = bclib archives_base_name=bclib
# Dependencies # Dependencies
patchouli_version = 50-FABRIC patchouli_version=50-FABRIC
modmenu_version=4.0.0-beta.3 modmenu_version=4.0.0-beta.3

View file

@ -8,9 +8,12 @@ import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.CustomSpawner;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.ServerLevelData;
import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.api.dataexchange.DataExchangeAPI;
import org.betterx.bclib.api.datafixer.DataFixerAPI; import org.betterx.bclib.api.datafixer.DataFixerAPI;
import java.util.ArrayList; import java.util.ArrayList;
@ -25,6 +28,25 @@ public class LifeCycleAPI {
private final static List<LevelLoadCall> onLoadLevel = new ArrayList<>(2); private final static List<LevelLoadCall> onLoadLevel = new ArrayList<>(2);
private final static List<BeforeLevelLoadCall> beforeLoadLevel = new ArrayList<>(2); private final static List<BeforeLevelLoadCall> beforeLoadLevel = new ArrayList<>(2);
public static void startingWorld(LevelStorageSource.LevelStorageAccess levelStorageAccess,
WorldGenSettings settings) {
DataExchangeAPI.prepareServerside();
BiomeAPI.prepareNewLevel();
DataFixerAPI.createWorldData(levelStorageAccess, settings);
_runBeforeLevelLoad();
}
public static void startingWorld(String levelID,
WorldGenSettings worldGenSettings,
LevelStorageSource levelSource) {
DataExchangeAPI.prepareServerside();
BiomeAPI.prepareNewLevel();
DataFixerAPI.createWorldData(levelSource, levelID, worldGenSettings);
_runBeforeLevelLoad();
}
/** /**
* A callback function that is used for each new ServerLevel instance * A callback function that is used for each new ServerLevel instance
*/ */
@ -121,18 +143,18 @@ public class LifeCycleAPI {
List<CustomSpawner> list, List<CustomSpawner> list,
boolean bl2) { boolean bl2) {
onLoadLevel.forEach(c -> c.onLoad( onLoadLevel.forEach(c -> c.onLoad(
world, world,
minecraftServer, minecraftServer,
executor, executor,
levelStorageAccess, levelStorageAccess,
serverLevelData, serverLevelData,
resourceKey, resourceKey,
chunkProgressListener, chunkProgressListener,
bl, bl,
l, l,
list, list,
bl2) bl2)
); );
final long seed = world.getSeed(); final long seed = world.getSeed();
final Registry<Biome> biomeRegistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); final Registry<Biome> biomeRegistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);

View file

@ -26,10 +26,10 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.dimension.BuiltinDimensionTypes;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration; import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; 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.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
@ -56,7 +56,6 @@ import org.betterx.bclib.interfaces.SurfaceRuleProvider;
import org.betterx.bclib.mixin.client.MinecraftMixin; import org.betterx.bclib.mixin.client.MinecraftMixin;
import org.betterx.bclib.mixin.common.BiomeGenerationSettingsAccessor; import org.betterx.bclib.mixin.common.BiomeGenerationSettingsAccessor;
import org.betterx.bclib.mixin.common.MobSpawnSettingsAccessor; import org.betterx.bclib.mixin.common.MobSpawnSettingsAccessor;
import org.betterx.bclib.mixin.common.NoiseGeneratorSettingsMixin;
import org.betterx.bclib.util.CollectionsUtil; import org.betterx.bclib.util.CollectionsUtil;
import org.betterx.bclib.world.biomes.BCLBiome; import org.betterx.bclib.world.biomes.BCLBiome;
import org.betterx.bclib.world.biomes.FabricBiomesData; import org.betterx.bclib.world.biomes.FabricBiomesData;
@ -126,7 +125,7 @@ public class BiomeAPI {
private static final Map<Holder<PlacedFeature>, Integer> FEATURE_ORDER = Maps.newHashMap(); private static final Map<Holder<PlacedFeature>, Integer> FEATURE_ORDER = Maps.newHashMap();
private static final MutableInt FEATURE_ORDER_ID = new MutableInt(0); private static final MutableInt FEATURE_ORDER_ID = new MutableInt(0);
private static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Holder<Biome>>>> MODIFICATIONS = Maps.newHashMap(); private static final Map<ResourceKey<DimensionType>, List<BiConsumer<ResourceLocation, Holder<Biome>>>> MODIFICATIONS = Maps.newHashMap();
private static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Holder<Biome>>>> TAG_ADDERS = Maps.newHashMap(); private static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Holder<Biome>>>> TAG_ADDERS = Maps.newHashMap();
private static final Set<SurfaceRuleProvider> MODIFIED_SURFACE_PROVIDERS = new HashSet<>(8); private static final Set<SurfaceRuleProvider> MODIFIED_SURFACE_PROVIDERS = new HashSet<>(8);
@ -560,7 +559,7 @@ public class BiomeAPI {
* @param dimensionID {@link ResourceLocation} dimension ID, example: Level.OVERWORLD or "minecraft:overworld". * @param dimensionID {@link ResourceLocation} dimension ID, example: Level.OVERWORLD or "minecraft:overworld".
* @param modification {@link BiConsumer} with {@link ResourceKey} biome ID and {@link Biome} parameters. * @param modification {@link BiConsumer} with {@link ResourceKey} biome ID and {@link Biome} parameters.
*/ */
public static void registerBiomeModification(ResourceKey dimensionID, public static void registerBiomeModification(ResourceKey<DimensionType> dimensionID,
BiConsumer<ResourceLocation, Holder<Biome>> modification) { BiConsumer<ResourceLocation, Holder<Biome>> modification) {
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID, List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID,
k -> Lists.newArrayList()); k -> Lists.newArrayList());
@ -573,7 +572,7 @@ public class BiomeAPI {
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters. * @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
*/ */
public static void registerOverworldBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) { public static void registerOverworldBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
registerBiomeModification(Level.OVERWORLD, modification); registerBiomeModification(BuiltinDimensionTypes.OVERWORLD, modification);
} }
/** /**
@ -582,7 +581,7 @@ public class BiomeAPI {
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters. * @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
*/ */
public static void registerNetherBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) { public static void registerNetherBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
registerBiomeModification(Level.NETHER, modification); registerBiomeModification(BuiltinDimensionTypes.NETHER, modification);
} }
/** /**
@ -591,7 +590,7 @@ public class BiomeAPI {
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters. * @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
*/ */
public static void registerEndBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) { public static void registerEndBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
registerBiomeModification(Level.END, modification); registerBiomeModification(BuiltinDimensionTypes.END, modification);
} }
/** /**
@ -656,7 +655,11 @@ public class BiomeAPI {
* *
* @param level * @param level
*/ */
public static void applyModifications(ServerLevel level) { @Deprecated(forRemoval = true)
public static void applyModificationsDeprecated(ServerLevel level) {
//TODO: Now Disabled, because we fix the settings when everything gets loaded
if (level != null) return;
NoiseGeneratorSettings noiseGeneratorSettings = null; NoiseGeneratorSettings noiseGeneratorSettings = null;
final ChunkGenerator chunkGenerator = level.getChunkSource().getGenerator(); final ChunkGenerator chunkGenerator = level.getChunkSource().getGenerator();
final BiomeSource source = chunkGenerator.getBiomeSource(); final BiomeSource source = chunkGenerator.getBiomeSource();
@ -675,7 +678,10 @@ public class BiomeAPI {
} }
} }
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(level.dimension()); List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(level
.dimensionTypeRegistration()
.unwrapKey()
.orElseThrow());
for (Holder<Biome> biomeHolder : biomes) { for (Holder<Biome> biomeHolder : biomes) {
if (biomeHolder.isBound()) { if (biomeHolder.isBound()) {
applyModificationsAndUpdateFeatures(modifications, biomeHolder); applyModificationsAndUpdateFeatures(modifications, biomeHolder);
@ -698,6 +704,18 @@ public class BiomeAPI {
((BiomeSourceAccessor) source).bclRebuildFeatures(); ((BiomeSourceAccessor) source).bclRebuildFeatures();
} }
public static void applyModifications(BiomeSource source, ResourceKey<DimensionType> dimension) {
BCLib.LOGGER.info("Apply Modifications for " + dimension.location() + " BiomeSource " + source);
final Set<Holder<Biome>> biomes = source.possibleBiomes();
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(dimension);
for (Holder<Biome> biomeHolder : biomes) {
if (biomeHolder.isBound()) {
applyModificationsAndUpdateFeatures(modifications, biomeHolder);
}
}
}
private static void applyModificationsAndUpdateFeatures(List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications, private static void applyModificationsAndUpdateFeatures(List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications,
Holder<Biome> biome) { Holder<Biome> biome) {
ResourceLocation biomeID = getBiomeID(biome); ResourceLocation biomeID = getBiomeID(biome);
@ -727,7 +745,7 @@ public class BiomeAPI {
} }
accessor.bclib_setFeatures(featureList); accessor.bclib_setFeatures(featureList);
} }
/** /**
* Adds new features to existing biome. * Adds new features to existing biome.
* *
@ -788,8 +806,8 @@ public class BiomeAPI {
accessor.bclib_setFeatureSet(featureSet); accessor.bclib_setFeatureSet(featureSet);
accessor.bclib_setFlowerFeatures(flowerFeatures); accessor.bclib_setFlowerFeatures(flowerFeatures);
} }
/** /**
* Adds mob spawning to specified biome. * Adds mob spawning to specified biome.
* *

View file

@ -3,16 +3,26 @@ package org.betterx.bclib.api.worldgen;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.resources.RegistryOps; import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.BuiltinDimensionTypes;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.synth.NormalNoise; import net.minecraft.world.level.levelgen.synth.NormalNoise;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider; import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
import org.betterx.bclib.interfaces.SurfaceRuleProvider;
import java.util.Optional;
public class BCLChunkGenerator extends NoiseBasedChunkGenerator { public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
@ -39,6 +49,7 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
.apply(builderInstance, builderInstance.stable(BCLChunkGenerator::new)); .apply(builderInstance, builderInstance.stable(BCLChunkGenerator::new));
}); });
public BCLChunkGenerator(Registry<StructureSet> registry, public BCLChunkGenerator(Registry<StructureSet> registry,
Registry<NormalNoise.NoiseParameters> registry2, Registry<NormalNoise.NoiseParameters> registry2,
BiomeSource biomeSource, BiomeSource biomeSource,
@ -47,6 +58,35 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
System.out.println("Chunk Generator: " + this); System.out.println("Chunk Generator: " + this);
} }
public static void injectNoiseSettings(WorldGenSettings settings) {
injectNoiseSettings(LevelStem.NETHER, BuiltinDimensionTypes.NETHER, settings);
injectNoiseSettings(LevelStem.END, BuiltinDimensionTypes.END, settings);
}
public static void injectNoiseSettings(ResourceKey<LevelStem> dimensionKey,
ResourceKey<DimensionType> dimensionTypeKey,
WorldGenSettings settings) {
Optional<Holder<LevelStem>> loadedStem = settings.dimensions().getHolder(dimensionKey);
final ChunkGenerator loadedChunkGenerator = loadedStem.map(h -> h.value().generator()).orElse(null);
injectNoiseSettings(dimensionTypeKey, loadedChunkGenerator);
}
public static void injectNoiseSettings(ResourceKey<DimensionType> dimensionTypeKey,
ChunkGenerator loadedChunkGenerator) {
BCLib.LOGGER.debug("Correcting Noise Settings for " + dimensionTypeKey.location().toString());
final BiomeSource loadedBiomeSource = loadedChunkGenerator.getBiomeSource();
BiomeAPI.applyModifications(loadedBiomeSource, dimensionTypeKey);
if (loadedChunkGenerator instanceof NoiseBasedChunkGenerator nbc) {
if (((Object) nbc.generatorSettings().value()) instanceof SurfaceRuleProvider srp) {
srp.bclib_overwrite(SurfaceRuleUtil.addRulesForBiomeSource(nbc
.generatorSettings()
.value()
.surfaceRule(), loadedBiomeSource));
}
}
}
@Override @Override
protected Codec<? extends ChunkGenerator> codec() { protected Codec<? extends ChunkGenerator> codec() {
return CODEC; return CODEC;

View file

@ -1,8 +1,5 @@
package org.betterx.bclib.api.worldgen; package org.betterx.bclib.api.worldgen;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@ -10,6 +7,10 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.SurfaceRules; import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.betterx.bclib.api.biomes.BiomeAPI; import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.mixin.common.NoiseGeneratorSettingsMixin; import org.betterx.bclib.mixin.common.NoiseGeneratorSettingsMixin;
@ -20,71 +21,77 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SurfaceRuleUtil { public class SurfaceRuleUtil {
private static final Map<ResourceLocation, RuleSource> SURFACE_RULES = Maps.newHashMap(); private static final Map<ResourceLocation, RuleSource> SURFACE_RULES = Maps.newHashMap();
private static List<RuleSource> getRuleSourcesForBiomes(Set<Holder<Biome>> biomes) {
Set<ResourceLocation> biomeIDs = biomes
.stream()
.map(biome -> BiomeAPI.getBiomeID(biome))
.collect(Collectors.toSet());
return getRuleSourcesFromIDs(biomeIDs);
}
/**
* Creates a list of SurfaceRules for all Biomes that are managed by the passed {@link BiomeSource}.
* If we have Surface rules for any of the Biomes from the given set of {@link BiomeSource}, they
* will be added to the result
* <p>
* Note: This Method is used in the {@link NoiseGeneratorSettingsMixin} which in turn
* is called from {@link BiomeAPI#applyModifications(ServerLevel)}.
*
* @param sources The Set of {@link BiomeSource} we want to consider
* @return A list of {@link RuleSource}-Objects that are needed to create those Biomes
*/
public static List<RuleSource> getRuleSources(Set<BiomeSource> sources) {
final Set<Holder<Biome>> biomes = new HashSet<>();
for (BiomeSource s : sources) {
biomes.addAll(s.possibleBiomes());
}
return getRuleSourcesForBiomes(biomes); private static List<RuleSource> getRuleSourcesForBiomes(Set<Holder<Biome>> biomes) {
} Set<ResourceLocation> biomeIDs = biomes
.stream()
public static List<RuleSource> getRuleSources(BiomeSource biomeSource) { .map(biome -> BiomeAPI.getBiomeID(biome))
return getRuleSourcesForBiomes(Sets.newHashSet(biomeSource.possibleBiomes())); .collect(Collectors.toSet());
} return getRuleSourcesFromIDs(biomeIDs);
}
private static List<RuleSource> getRuleSourcesFromIDs(Set<ResourceLocation> biomeIDs) {
List<RuleSource> rules = Lists.newArrayList(); /**
SURFACE_RULES.forEach((biomeID, rule) -> { * Creates a list of SurfaceRules for all Biomes that are managed by the passed {@link BiomeSource}.
if (biomeIDs.contains(biomeID)) { * If we have Surface rules for any of the Biomes from the given set of {@link BiomeSource}, they
rules.add(rule); * will be added to the result
} * <p>
}); * Note: This Method is used in the {@link NoiseGeneratorSettingsMixin} which in turn
return rules; * is called from {@link BiomeAPI#applyModificationsDeprecated(ServerLevel)}.
} *
* @param sources The Set of {@link BiomeSource} we want to consider
/** * @return A list of {@link RuleSource}-Objects that are needed to create those Biomes
* Adds surface rule to specified biome. */
* public static List<RuleSource> getRuleSources(Set<BiomeSource> sources) {
* @param biomeID biome {@link ResourceLocation}. final Set<Holder<Biome>> biomes = new HashSet<>();
* @param source {@link RuleSource}. for (BiomeSource s : sources) {
*/ biomes.addAll(s.possibleBiomes());
public static void addSurfaceRule(ResourceLocation biomeID, RuleSource source) { }
SURFACE_RULES.put(biomeID, source);
//NOISE_GENERATOR_SETTINGS.forEach(BiomeAPI::changeSurfaceRulesForGenerator); return getRuleSourcesForBiomes(biomes);
} }
public static RuleSource addRulesForBiomeSource(RuleSource org, BiomeSource biomeSource) { public static List<RuleSource> getRuleSources(BiomeSource biomeSource) {
List<RuleSource> additionalRules = getRuleSources(biomeSource); return getRuleSourcesForBiomes(Sets.newHashSet(biomeSource.possibleBiomes()));
if (org instanceof SurfaceRules.SequenceRuleSource sequenceRule) { }
List<RuleSource> existingSequence = sequenceRule.sequence();
additionalRules = additionalRules.stream().filter(r -> existingSequence.indexOf(r) < 0).collect(Collectors.toList()); private static List<RuleSource> getRuleSourcesFromIDs(Set<ResourceLocation> biomeIDs) {
additionalRules.addAll(sequenceRule.sequence()); List<RuleSource> rules = Lists.newArrayList();
} else { SURFACE_RULES.forEach((biomeID, rule) -> {
additionalRules.add(org); if (biomeIDs.contains(biomeID)) {
} rules.add(rule);
}
return SurfaceRules.sequence(additionalRules.toArray(new RuleSource[additionalRules.size()])); });
} return rules;
}
/**
* Adds surface rule to specified biome.
*
* @param biomeID biome {@link ResourceLocation}.
* @param source {@link RuleSource}.
*/
public static void addSurfaceRule(ResourceLocation biomeID, RuleSource source) {
SURFACE_RULES.put(biomeID, source);
//NOISE_GENERATOR_SETTINGS.forEach(BiomeAPI::changeSurfaceRulesForGenerator);
}
public static RuleSource addRulesForBiomeSource(RuleSource org, BiomeSource biomeSource) {
List<RuleSource> additionalRules = getRuleSources(biomeSource);
if (org instanceof SurfaceRules.SequenceRuleSource sequenceRule) {
List<RuleSource> existingSequence = sequenceRule.sequence();
additionalRules = additionalRules
.stream()
.filter(r -> existingSequence.indexOf(r) < 0)
.collect(Collectors.toList());
if (additionalRules.size() == 0) return org;
additionalRules.addAll(sequenceRule.sequence());
} else {
if (additionalRules.size() == 0) return org;
if (!additionalRules.contains(org))
additionalRules.add(org);
}
return SurfaceRules.sequence(additionalRules.toArray(new RuleSource[additionalRules.size()]));
}
} }

View file

@ -1,8 +1,10 @@
package org.betterx.bclib.interfaces; package org.betterx.bclib.interfaces;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.SurfaceRules;
public interface SurfaceRuleProvider { public interface SurfaceRuleProvider {
void bclib_addBiomeSource(BiomeSource source); void bclib_addBiomeSource(BiomeSource source);
void bclib_clearBiomeSources(); void bclib_clearBiomeSources();
void bclib_overwrite(SurfaceRules.RuleSource surfaceRule);
} }

View file

@ -10,21 +10,30 @@ import net.minecraft.server.WorldLoader;
import net.minecraft.world.level.DataPackConfig; import net.minecraft.world.level.DataPackConfig;
import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.presets.WorldPreset; import net.minecraft.world.level.levelgen.presets.WorldPreset;
import net.minecraft.world.level.storage.LevelStorageSource;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import org.betterx.bclib.api.LifeCycleAPI;
import org.betterx.bclib.api.biomes.BiomeAPI; import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.presets.worldgen.BCLWorldPresets;
import org.betterx.bclib.api.worldgen.WorldGenUtil; import org.betterx.bclib.api.worldgen.WorldGenUtil;
import org.betterx.bclib.presets.worldgen.BCLWorldPresets;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Optional; import java.util.Optional;
@Mixin(CreateWorldScreen.class) @Mixin(CreateWorldScreen.class)
public class CreateWorldScreenMixin { public class CreateWorldScreenMixin {
@Shadow
@Final
public WorldGenSettingsComponent worldGenSettingsComponent;
@Inject(method = "<init>", at = @At("TAIL")) @Inject(method = "<init>", at = @At("TAIL"))
private void bcl_init(Screen screen, private void bcl_init(Screen screen,
DataPackConfig dataPackConfig, DataPackConfig dataPackConfig,
@ -47,4 +56,14 @@ public class CreateWorldScreenMixin {
return WorldGenUtil.defaultWorldDataSupplier(res.getSecond()); return WorldGenUtil.defaultWorldDataSupplier(res.getSecond());
}; };
} }
@Inject(method = "createNewWorldDirectory", at = @At("RETURN"))
void bcl_createNewWorld(CallbackInfoReturnable<Optional<LevelStorageSource.LevelStorageAccess>> cir) {
Optional<LevelStorageSource.LevelStorageAccess> levelStorageAccess = cir.getReturnValue();
if (levelStorageAccess.isPresent()) {
LifeCycleAPI.startingWorld(levelStorageAccess.get(),
worldGenSettingsComponent.settings().worldGenSettings());
}
}
} }

View file

@ -40,7 +40,7 @@ public abstract class SignEditScreenMixin extends Screen {
super(component); super(component);
} }
@Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", locals = LocalCapture.CAPTURE_FAILSOFT, at = @At( @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", locals = LocalCapture.CAPTURE_FAILSOFT, at = @At(ordinal = 1,
value = "INVOKE", value = "INVOKE",
target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V",
shift = Shift.BEFORE shift = Shift.BEFORE

View file

@ -2,12 +2,8 @@ package org.betterx.bclib.mixin.common;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.levelgen.*;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.synth.NormalNoise; import net.minecraft.world.level.levelgen.synth.NormalNoise;
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider; import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
@ -16,8 +12,6 @@ import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import java.lang.reflect.Constructor;
@Mixin(NoiseBasedChunkGenerator.class) @Mixin(NoiseBasedChunkGenerator.class)
public abstract class NoiseBasedChunkGeneratorMixin implements SurfaceProvider, NoiseGeneratorSettingsProvider { public abstract class NoiseBasedChunkGeneratorMixin implements SurfaceProvider, NoiseGeneratorSettingsProvider {
@Final @Final
@ -27,12 +21,6 @@ public abstract class NoiseBasedChunkGeneratorMixin implements SurfaceProvider,
@Shadow @Shadow
@Final @Final
private Registry<NormalNoise.NoiseParameters> noises; private Registry<NormalNoise.NoiseParameters> noises;
@Final
@Shadow
private Aquifer.FluidPicker globalFluidPicker;
private static final BlockState bclib_air = Blocks.AIR.defaultBlockState();
private static Constructor<?> bclib_constructor;
@Override @Override
public NoiseGeneratorSettings bclib_getNoiseGeneratorSettings() { public NoiseGeneratorSettings bclib_getNoiseGeneratorSettings() {
@ -48,11 +36,4 @@ public abstract class NoiseBasedChunkGeneratorMixin implements SurfaceProvider,
public Registry<NormalNoise.NoiseParameters> bclib_getNoises() { public Registry<NormalNoise.NoiseParameters> bclib_getNoises() {
return noises; return noises;
} }
@Shadow
protected abstract NoiseChunk createNoiseChunk(ChunkAccess chunkAccess,
StructureManager structureManager,
Blender blender,
RandomState randomState);
} }

View file

@ -68,6 +68,15 @@ public class NoiseGeneratorSettingsMixin implements SurfaceRuleProvider {
bclib_setSurfaceRule(SurfaceRules.sequence(rules.toArray(new RuleSource[rules.size()]))); bclib_setSurfaceRule(SurfaceRules.sequence(rules.toArray(new RuleSource[rules.size()])));
} }
public void bclib_overwrite(SurfaceRules.RuleSource surfaceRule) {
if (surfaceRule == this.surfaceRule) return;
if (this.bcl_containsOverride) {
System.out.println("Adding another override");
}
this.bcl_containsOverride = true;
this.surfaceRule = surfaceRule;
}
void bclib_setSurfaceRule(SurfaceRules.RuleSource surfaceRule) { void bclib_setSurfaceRule(SurfaceRules.RuleSource surfaceRule) {
if (bclib_originalSurfaceRule == null) { if (bclib_originalSurfaceRule == null) {
bclib_originalSurfaceRule = this.surfaceRule; bclib_originalSurfaceRule = this.surfaceRule;
@ -75,6 +84,8 @@ public class NoiseGeneratorSettingsMixin implements SurfaceRuleProvider {
this.surfaceRule = surfaceRule; this.surfaceRule = surfaceRule;
} }
private boolean bcl_containsOverride = false;
RuleSource bclib_getOriginalSurfaceRule() { RuleSource bclib_getOriginalSurfaceRule() {
if (bclib_originalSurfaceRule == null) { if (bclib_originalSurfaceRule == null) {
return surfaceRule; return surfaceRule;

View file

@ -11,8 +11,11 @@ import net.minecraft.world.level.storage.PrimaryLevelData;
import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixer;
import com.mojang.serialization.Dynamic; import com.mojang.serialization.Dynamic;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import org.betterx.bclib.api.worldgen.BCLChunkGenerator;
import org.betterx.bclib.api.worldgen.WorldGenUtil; import org.betterx.bclib.api.worldgen.WorldGenUtil;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
@ -23,9 +26,18 @@ import org.jetbrains.annotations.Nullable;
@Mixin(PrimaryLevelData.class) @Mixin(PrimaryLevelData.class)
public class PrimaryLevelDataMixin { public class PrimaryLevelDataMixin {
@Shadow
@Final
private WorldGenSettings worldGenSettings;
private static final ThreadLocal<Optional<RegistryOps<Tag>>> bcl_lastRegistryAccess = ThreadLocal.withInitial( private static final ThreadLocal<Optional<RegistryOps<Tag>>> bcl_lastRegistryAccess = ThreadLocal.withInitial(
() -> Optional.empty()); () -> Optional.empty());
@ModifyArg(method = "<init>(Lnet/minecraft/world/level/LevelSettings;Lnet/minecraft/world/level/levelgen/WorldGenSettings;Lcom/mojang/serialization/Lifecycle;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PrimaryLevelData;<init>(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/CompoundTag;ZIIIFJJIIIZIZZZLnet/minecraft/world/level/border/WorldBorder$Settings;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/level/timers/TimerQueue;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/level/LevelSettings;Lnet/minecraft/world/level/levelgen/WorldGenSettings;Lcom/mojang/serialization/Lifecycle;)V"))
private static WorldGenSettings bcl_fixOtherSettings(WorldGenSettings worldGenSettings) {
BCLChunkGenerator.injectNoiseSettings(worldGenSettings);
return worldGenSettings;
}
@Inject(method = "parse", at = @At("HEAD")) @Inject(method = "parse", at = @At("HEAD"))
private static void bcl_parse(Dynamic<Tag> dynamic, private static void bcl_parse(Dynamic<Tag> dynamic,
DataFixer dataFixer, DataFixer dataFixer,

View file

@ -57,18 +57,18 @@ public abstract class ServerLevelMixin extends Level {
CallbackInfo ci) { CallbackInfo ci) {
ServerLevel level = ServerLevel.class.cast(this); ServerLevel level = ServerLevel.class.cast(this);
LifeCycleAPI._runLevelLoad(level, LifeCycleAPI._runLevelLoad(level,
server, server,
executor, executor,
levelStorageAccess, levelStorageAccess,
serverLevelData, serverLevelData,
resourceKey, resourceKey,
chunkProgressListener, chunkProgressListener,
bl, bl,
l, l,
list, list,
bl2); bl2);
BiomeAPI.applyModifications(ServerLevel.class.cast(this)); BiomeAPI.applyModificationsDeprecated(ServerLevel.class.cast(this));
if (level.dimension() == Level.NETHER) { if (level.dimension() == Level.NETHER) {
BCLibNetherBiomeSource.setWorldHeight(level.getChunkSource().getGenerator().getGenDepth()); BCLibNetherBiomeSource.setWorldHeight(level.getChunkSource().getGenerator().getGenDepth());

View file

@ -58,11 +58,7 @@ public abstract class WorldOpenFlowsMixin {
RegistryAccess registryAccess, RegistryAccess registryAccess,
WorldGenSettings worldGenSettings, WorldGenSettings worldGenSettings,
CallbackInfo ci) { CallbackInfo ci) {
DataExchangeAPI.prepareServerside(); LifeCycleAPI.startingWorld(levelID, worldGenSettings, this.levelSource);
BiomeAPI.prepareNewLevel();
DataFixerAPI.createWorldData(this.levelSource, levelID, worldGenSettings);
LifeCycleAPI._runBeforeLevelLoad();
} }
@Inject(method = "createLevelFromExistingSettings", at = @At("HEAD")) @Inject(method = "createLevelFromExistingSettings", at = @At("HEAD"))
@ -71,10 +67,6 @@ public abstract class WorldOpenFlowsMixin {
RegistryAccess.Frozen frozen, RegistryAccess.Frozen frozen,
WorldData worldData, WorldData worldData,
CallbackInfo ci) { CallbackInfo ci) {
DataExchangeAPI.prepareServerside(); //LifeCycleAPI.startWorld(levelStorageAccess, worldData.worldGenSettings());
BiomeAPI.prepareNewLevel();
DataFixerAPI.createWorldData(levelStorageAccess, worldData.worldGenSettings());
LifeCycleAPI._runBeforeLevelLoad();
} }
} }

View file

@ -15,6 +15,7 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.api.worldgen.BCLChunkGenerator; import org.betterx.bclib.api.worldgen.BCLChunkGenerator;
import org.betterx.bclib.api.worldgen.SurfaceRuleUtil; import org.betterx.bclib.api.worldgen.SurfaceRuleUtil;
import org.betterx.bclib.api.worldgen.WorldGenUtil; import org.betterx.bclib.api.worldgen.WorldGenUtil;
@ -140,15 +141,16 @@ public class BCLWorldPresetSettings extends WorldPresetSettings {
public WorldGenSettings fixSettingsInCurrentWorld(RegistryAccess access, ResourceKey<LevelStem> dimensionKey, public WorldGenSettings fixSettingsInCurrentWorld(RegistryAccess access, ResourceKey<LevelStem> dimensionKey,
ResourceKey<DimensionType> dimensionTypeKey, ResourceKey<DimensionType> dimensionTypeKey,
WorldGenSettings settings) { WorldGenSettings settings) {
var oldNether = settings.dimensions().getHolder(dimensionKey); Optional<Holder<LevelStem>> loadedStem = settings.dimensions().getHolder(dimensionKey);
int loaderVersion = WorldGenUtil.getBiomeVersionForGenerator(oldNether final ChunkGenerator loadedChunkGenerator = loadedStem.map(h -> h.value().generator()).orElse(null);
final int loaderVersion = WorldGenUtil.getBiomeVersionForGenerator(loadedStem
.map(h -> h.value().generator()) .map(h -> h.value().generator())
.orElse(null)); .orElse(null));
int targetVersion = getVersion(dimensionKey); final int targetVersion = getVersion(dimensionKey);
if (loaderVersion != targetVersion) { if (loaderVersion != targetVersion) {
BCLib.LOGGER.info("Enforcing Correct Generator for " + dimensionKey.location().toString() + "."); BCLib.LOGGER.info("Enforcing Correct Generator for " + dimensionKey.location().toString() + ".");
var chunkGenerator = oldNether.map(h -> h.value().generator()).orElse(null);
Optional<Holder<LevelStem>> refLevelStem = WorldGenUtil.referenceStemForVersion( Optional<Holder<LevelStem>> refLevelStem = WorldGenUtil.referenceStemForVersion(
dimensionKey, dimensionKey,
targetVersion, targetVersion,
@ -164,10 +166,11 @@ public class BCLWorldPresetSettings extends WorldPresetSettings {
return settings; return settings;
} }
if (chunkGenerator instanceof ChunkGeneratorAccessor generator) { if (loadedChunkGenerator instanceof ChunkGeneratorAccessor generator) {
if (chunkGenerator instanceof NoiseGeneratorSettingsProvider noiseProvider) { if (loadedChunkGenerator instanceof NoiseGeneratorSettingsProvider noiseProvider) {
final Set<Holder<Biome>> biomes = chunkGenerator.getBiomeSource().possibleBiomes(); final Set<Holder<Biome>> biomes = loadedChunkGenerator.getBiomeSource().possibleBiomes();
final BiomeSource bs = fixBiomeSource(referenceGenerator.getBiomeSource(), biomes); final BiomeSource bs = fixBiomeSource(referenceGenerator.getBiomeSource(), biomes);
BiomeAPI.applyModifications(bs, dimensionTypeKey);
referenceGenerator = new BCLChunkGenerator(generator.bclib_getStructureSetsRegistry(), referenceGenerator = new BCLChunkGenerator(generator.bclib_getStructureSetsRegistry(),
noiseProvider.bclib_getNoises(), noiseProvider.bclib_getNoises(),
bs, bs,
@ -181,6 +184,8 @@ public class BCLWorldPresetSettings extends WorldPresetSettings {
access, access,
settings, settings,
referenceGenerator); referenceGenerator);
} else {
BCLChunkGenerator.injectNoiseSettings(dimensionTypeKey, loadedChunkGenerator);
} }
return settings; return settings;
} }

View file

@ -57,8 +57,8 @@ public class ModUtil {
private static ModMetadata readJSON(InputStream is, String sourceFile) throws IOException { private static ModMetadata readJSON(InputStream is, String sourceFile) throws IOException {
try (com.google.gson.stream.JsonReader reader = new JsonReader(new InputStreamReader(is, try (com.google.gson.stream.JsonReader reader = new JsonReader(new InputStreamReader(is,
StandardCharsets.UTF_8))) { StandardCharsets.UTF_8))) {
JsonObject data = new JsonParser().parse(reader) JsonObject data = JsonParser.parseReader(reader)
.getAsJsonObject(); .getAsJsonObject();
Version ver; Version ver;
try { try {
ver = new SemanticVersionImpl(data.get("version") ver = new SemanticVersionImpl(data.get("version")

View file

@ -37,9 +37,9 @@
"bclib.mixins.client.json" "bclib.mixins.client.json"
], ],
"depends": { "depends": {
"fabricloader": ">=0.14.5", "fabricloader": ">=0.14.6",
"fabric": ">=0.52.4", "fabric": ">=0.53.4",
"minecraft": "1.19-beta.1" "minecraft": "1.19-beta.3"
}, },
"custom": { "custom": {
"modmenu": { "modmenu": {