Improved SurfaceRule Handling
This commit is contained in:
parent
e08d85b605
commit
bdf30109f6
16 changed files with 266 additions and 161 deletions
|
@ -8,9 +8,12 @@ import net.minecraft.server.level.progress.ChunkProgressListener;
|
|||
import net.minecraft.world.level.CustomSpawner;
|
||||
import net.minecraft.world.level.Level;
|
||||
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.ServerLevelData;
|
||||
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.datafixer.DataFixerAPI;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -25,6 +28,25 @@ public class LifeCycleAPI {
|
|||
private final static List<LevelLoadCall> onLoadLevel = 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
|
||||
*/
|
||||
|
@ -121,18 +143,18 @@ public class LifeCycleAPI {
|
|||
List<CustomSpawner> list,
|
||||
boolean bl2) {
|
||||
onLoadLevel.forEach(c -> c.onLoad(
|
||||
world,
|
||||
minecraftServer,
|
||||
executor,
|
||||
levelStorageAccess,
|
||||
serverLevelData,
|
||||
resourceKey,
|
||||
chunkProgressListener,
|
||||
bl,
|
||||
l,
|
||||
list,
|
||||
bl2)
|
||||
);
|
||||
world,
|
||||
minecraftServer,
|
||||
executor,
|
||||
levelStorageAccess,
|
||||
serverLevelData,
|
||||
resourceKey,
|
||||
chunkProgressListener,
|
||||
bl,
|
||||
l,
|
||||
list,
|
||||
bl2)
|
||||
);
|
||||
|
||||
final long seed = world.getSeed();
|
||||
final Registry<Biome> biomeRegistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
|
|
|
@ -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.ChunkGenerator;
|
||||
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.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.Feature;
|
||||
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.common.BiomeGenerationSettingsAccessor;
|
||||
import org.betterx.bclib.mixin.common.MobSpawnSettingsAccessor;
|
||||
import org.betterx.bclib.mixin.common.NoiseGeneratorSettingsMixin;
|
||||
import org.betterx.bclib.util.CollectionsUtil;
|
||||
import org.betterx.bclib.world.biomes.BCLBiome;
|
||||
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 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 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 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) {
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID,
|
||||
k -> Lists.newArrayList());
|
||||
|
@ -573,7 +572,7 @@ public class BiomeAPI {
|
|||
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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;
|
||||
final ChunkGenerator chunkGenerator = level.getChunkSource().getGenerator();
|
||||
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) {
|
||||
if (biomeHolder.isBound()) {
|
||||
applyModificationsAndUpdateFeatures(modifications, biomeHolder);
|
||||
|
@ -698,6 +704,18 @@ public class BiomeAPI {
|
|||
((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,
|
||||
Holder<Biome> biome) {
|
||||
ResourceLocation biomeID = getBiomeID(biome);
|
||||
|
@ -727,7 +745,7 @@ public class BiomeAPI {
|
|||
}
|
||||
accessor.bclib_setFeatures(featureList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds new features to existing biome.
|
||||
*
|
||||
|
@ -788,8 +806,8 @@ public class BiomeAPI {
|
|||
accessor.bclib_setFeatureSet(featureSet);
|
||||
accessor.bclib_setFlowerFeatures(flowerFeatures);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds mob spawning to specified biome.
|
||||
*
|
||||
|
|
|
@ -3,16 +3,26 @@ package org.betterx.bclib.api.worldgen;
|
|||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
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.NoiseGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import net.minecraft.world.level.levelgen.synth.NormalNoise;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
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.SurfaceRuleProvider;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
|
||||
|
||||
|
@ -39,6 +49,7 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
|
|||
.apply(builderInstance, builderInstance.stable(BCLChunkGenerator::new));
|
||||
});
|
||||
|
||||
|
||||
public BCLChunkGenerator(Registry<StructureSet> registry,
|
||||
Registry<NormalNoise.NoiseParameters> registry2,
|
||||
BiomeSource biomeSource,
|
||||
|
@ -47,6 +58,35 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
|
|||
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
|
||||
protected Codec<? extends ChunkGenerator> codec() {
|
||||
return CODEC;
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
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.resources.ResourceLocation;
|
||||
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.levelgen.SurfaceRules;
|
||||
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.mixin.common.NoiseGeneratorSettingsMixin;
|
||||
|
||||
|
@ -20,71 +21,77 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class SurfaceRuleUtil {
|
||||
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());
|
||||
}
|
||||
private static final Map<ResourceLocation, RuleSource> SURFACE_RULES = Maps.newHashMap();
|
||||
|
||||
return getRuleSourcesForBiomes(biomes);
|
||||
}
|
||||
|
||||
public static List<RuleSource> getRuleSources(BiomeSource biomeSource) {
|
||||
return getRuleSourcesForBiomes(Sets.newHashSet(biomeSource.possibleBiomes()));
|
||||
}
|
||||
|
||||
private static List<RuleSource> getRuleSourcesFromIDs(Set<ResourceLocation> biomeIDs) {
|
||||
List<RuleSource> rules = Lists.newArrayList();
|
||||
SURFACE_RULES.forEach((biomeID, rule) -> {
|
||||
if (biomeIDs.contains(biomeID)) {
|
||||
rules.add(rule);
|
||||
}
|
||||
});
|
||||
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());
|
||||
additionalRules.addAll(sequenceRule.sequence());
|
||||
} else {
|
||||
additionalRules.add(org);
|
||||
}
|
||||
|
||||
return SurfaceRules.sequence(additionalRules.toArray(new RuleSource[additionalRules.size()]));
|
||||
}
|
||||
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#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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
public static List<RuleSource> getRuleSources(BiomeSource biomeSource) {
|
||||
return getRuleSourcesForBiomes(Sets.newHashSet(biomeSource.possibleBiomes()));
|
||||
}
|
||||
|
||||
private static List<RuleSource> getRuleSourcesFromIDs(Set<ResourceLocation> biomeIDs) {
|
||||
List<RuleSource> rules = Lists.newArrayList();
|
||||
SURFACE_RULES.forEach((biomeID, rule) -> {
|
||||
if (biomeIDs.contains(biomeID)) {
|
||||
rules.add(rule);
|
||||
}
|
||||
});
|
||||
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()]));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue