Fix for crash when biomeSource is not initialized twice (paulevsGitch/BetterNether#468)
This commit is contained in:
parent
1bb15de385
commit
b60df41c6c
8 changed files with 179 additions and 86 deletions
|
@ -7,12 +7,14 @@ import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
|
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
|
||||||
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
|
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
|
||||||
import net.fabricmc.fabric.impl.biome.NetherBiomeData;
|
import net.fabricmc.fabric.impl.biome.NetherBiomeData;
|
||||||
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
|
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
|
||||||
|
import net.fabricmc.fabric.impl.structure.FabricStructureImpl;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
|
@ -45,16 +47,19 @@ import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
|
||||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||||
|
import net.minecraft.world.level.levelgen.feature.configurations.StructureFeatureConfiguration;
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||||
import org.apache.commons.lang3.mutable.MutableInt;
|
import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import ru.bclib.BCLib;
|
import ru.bclib.BCLib;
|
||||||
import ru.bclib.config.Configs;
|
import ru.bclib.config.Configs;
|
||||||
import ru.bclib.entity.BCLEntityWrapper;
|
import ru.bclib.entity.BCLEntityWrapper;
|
||||||
|
import ru.bclib.interfaces.BiomeSourceAccessor;
|
||||||
import ru.bclib.interfaces.SurfaceMaterialProvider;
|
import ru.bclib.interfaces.SurfaceMaterialProvider;
|
||||||
import ru.bclib.interfaces.SurfaceProvider;
|
import ru.bclib.interfaces.SurfaceProvider;
|
||||||
import ru.bclib.interfaces.SurfaceRuleProvider;
|
import ru.bclib.interfaces.SurfaceRuleProvider;
|
||||||
import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor;
|
import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor;
|
||||||
|
import ru.bclib.mixin.common.BiomeSourceMixin;
|
||||||
import ru.bclib.mixin.common.MobSpawnSettingsAccessor;
|
import ru.bclib.mixin.common.MobSpawnSettingsAccessor;
|
||||||
import ru.bclib.mixin.common.StructureSettingsAccessor;
|
import ru.bclib.mixin.common.StructureSettingsAccessor;
|
||||||
import ru.bclib.util.CollectionsUtil;
|
import ru.bclib.util.CollectionsUtil;
|
||||||
|
@ -67,14 +72,15 @@ import ru.bclib.world.structures.BCLStructureFeature;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -118,21 +124,19 @@ public class BiomeAPI {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinRegistries.BIOME
|
BuiltinRegistries.BIOME.entrySet()
|
||||||
.entrySet()
|
|
||||||
.stream()
|
.stream()
|
||||||
.filter(entry -> entry.getKey().location().getNamespace().equals("minecraft"))
|
.filter(entry -> entry.getKey()
|
||||||
.map(entry -> entry.getValue())
|
.location()
|
||||||
.forEach(biome -> {
|
.getNamespace()
|
||||||
BiomeGenerationSettingsAccessor accessor = BiomeGenerationSettingsAccessor.class.cast(biome.getGenerationSettings());
|
.equals("minecraft"))
|
||||||
List<List<Supplier<PlacedFeature>>> features = accessor.bclib_getFeatures();
|
.map(Entry::getValue)
|
||||||
features.forEach(step -> {
|
.map(biome -> (BiomeGenerationSettingsAccessor) biome.getGenerationSettings())
|
||||||
step.forEach(provider -> {
|
.map(BiomeGenerationSettingsAccessor::bclib_getFeatures)
|
||||||
PlacedFeature feature = provider.get();
|
.forEach(stepFeatureSuppliers -> stepFeatureSuppliers.forEach(step -> step.forEach(featureSupplier -> {
|
||||||
|
PlacedFeature feature = featureSupplier.get();
|
||||||
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
|
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
|
||||||
});
|
})));
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,17 +160,56 @@ public class BiomeAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Set<BiomeSource> worldSources = new HashSet<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For internal use only.
|
||||||
|
*
|
||||||
|
* Used by {@link BiomeSourceMixin} to add new BiomeSources to the BiomeAPI. We need to know all
|
||||||
|
* created Sources in order to rebuild their feature set whenever biomes get recreated
|
||||||
|
* through a datapack.
|
||||||
|
* @param source The new {@link BiomeSource}
|
||||||
|
*/
|
||||||
|
public static void registerBiomeSource(BiomeSource source){
|
||||||
|
worldSources.add(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For internal use only.
|
||||||
|
*
|
||||||
|
* This method gets called before a world is loaded/created to flush cashes we build. The Method is
|
||||||
|
* called from {@link ru.bclib.mixin.client.MinecraftMixin}
|
||||||
|
*/
|
||||||
|
public static void prepareWorldData(){
|
||||||
|
structureStarts.clear();
|
||||||
|
worldSources.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registered by {@link #initRegistry(Registry)} as a callback for whenever a new Biome was
|
||||||
|
* added to our registry
|
||||||
|
* @param biome The {@link Biome} that got added
|
||||||
|
*/
|
||||||
private static void onAddedBiome(Biome biome) {
|
private static void onAddedBiome(Biome biome) {
|
||||||
|
boolean didChange = false;
|
||||||
//BCLib.LOGGER.info(" ++++ " + getBiomeID(biome) + ", " + getBiomeKey(biome) + ", " + biome);
|
//BCLib.LOGGER.info(" ++++ " + getBiomeID(biome) + ", " + getBiomeKey(biome) + ", " + biome);
|
||||||
for (var dim : MODIFICATIONS.keySet()) {
|
for (var dim : MODIFICATIONS.keySet()) {
|
||||||
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.get(dim);
|
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.get(dim);
|
||||||
if (modifications == null) {
|
if (modifications == null) {
|
||||||
sortBiomeFeatures(biome);
|
sortBiomeFeatures(biome);
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyModifications(modifications, biome);
|
didChange=true;
|
||||||
|
applyModificationsToBiome(modifications, biome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (didChange) {
|
||||||
|
// worldSources.stream()
|
||||||
|
// .filter(s -> s.possibleBiomes()
|
||||||
|
// .contains(biome))
|
||||||
|
// .forEach(s -> ((BiomeSourceAccessor) s).bclRebuildFeatures());
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -214,7 +257,7 @@ public class BiomeAPI {
|
||||||
MHelper.randRange(-1.5F, 1.5F, random),
|
MHelper.randRange(-1.5F, 1.5F, random),
|
||||||
random.nextFloat()
|
random.nextFloat()
|
||||||
);
|
);
|
||||||
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).get();
|
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow();
|
||||||
NetherBiomeData.addNetherBiome(key, parameters);
|
NetherBiomeData.addNetherBiome(key, parameters);
|
||||||
return biome;
|
return biome;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +287,7 @@ public class BiomeAPI {
|
||||||
configureBiome(biome);
|
configureBiome(biome);
|
||||||
END_LAND_BIOME_PICKER.addBiome(biome);
|
END_LAND_BIOME_PICKER.addBiome(biome);
|
||||||
float weight = biome.getGenChance();
|
float weight = biome.getGenChance();
|
||||||
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).get();
|
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow();
|
||||||
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_HIGHLANDS, key, weight);
|
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_HIGHLANDS, key, weight);
|
||||||
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_MIDLANDS, key, weight);
|
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_MIDLANDS, key, weight);
|
||||||
return biome;
|
return biome;
|
||||||
|
@ -290,7 +333,7 @@ public class BiomeAPI {
|
||||||
configureBiome(biome);
|
configureBiome(biome);
|
||||||
END_VOID_BIOME_PICKER.addBiome(biome);
|
END_VOID_BIOME_PICKER.addBiome(biome);
|
||||||
float weight = biome.getGenChance();
|
float weight = biome.getGenChance();
|
||||||
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).get();
|
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow();
|
||||||
TheEndBiomeData.addEndBiomeReplacement(Biomes.SMALL_END_ISLANDS, key, weight);
|
TheEndBiomeData.addEndBiomeReplacement(Biomes.SMALL_END_ISLANDS, key, weight);
|
||||||
return biome;
|
return biome;
|
||||||
}
|
}
|
||||||
|
@ -317,7 +360,6 @@ public class BiomeAPI {
|
||||||
* @return {@link BCLBiome}
|
* @return {@link BCLBiome}
|
||||||
*/
|
*/
|
||||||
public static BCLBiome registerEndVoidBiome(Biome biome, float genChance) {
|
public static BCLBiome registerEndVoidBiome(Biome biome, float genChance) {
|
||||||
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome).get();
|
|
||||||
BCLBiome bclBiome = new BCLBiome(biome).setGenChance(genChance);
|
BCLBiome bclBiome = new BCLBiome(biome).setGenChance(genChance);
|
||||||
configureBiome(bclBiome);
|
configureBiome(bclBiome);
|
||||||
END_VOID_BIOME_PICKER.addBiome(bclBiome);
|
END_VOID_BIOME_PICKER.addBiome(bclBiome);
|
||||||
|
@ -361,8 +403,9 @@ public class BiomeAPI {
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static ResourceKey getBiomeKey(Biome biome) {
|
public static ResourceKey getBiomeKey(Biome biome) {
|
||||||
ResourceKey key = BuiltinRegistries.BIOME.getResourceKey(biome).orElse(null);
|
return BuiltinRegistries.BIOME.getResourceKey(biome)
|
||||||
return key != null ? key : biomeRegistry != null ? biomeRegistry.getResourceKey(biome).orElse(null) : null;
|
.orElseGet(() -> biomeRegistry != null ? biomeRegistry.getResourceKey(biome)
|
||||||
|
.orElse(null) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -460,11 +503,7 @@ public class BiomeAPI {
|
||||||
* @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, BiConsumer<ResourceLocation, Biome> modification) {
|
public static void registerBiomeModification(ResourceKey dimensionID, BiConsumer<ResourceLocation, Biome> modification) {
|
||||||
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.get(dimensionID);
|
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID, k -> Lists.newArrayList());
|
||||||
if (modifications == null) {
|
|
||||||
modifications = Lists.newArrayList();
|
|
||||||
MODIFICATIONS.put(dimensionID, modifications);
|
|
||||||
}
|
|
||||||
modifications.add(modification);
|
modifications.add(modification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,11 +560,13 @@ public class BiomeAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
biomes.forEach(biome -> {
|
biomes.forEach(biome -> {
|
||||||
applyModifications(modifications, biome);
|
applyModificationsToBiome(modifications, biome);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
((BiomeSourceAccessor) source).bclRebuildFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyModifications(List<BiConsumer<ResourceLocation, Biome>> modifications, Biome biome) {
|
private static void applyModificationsToBiome(List<BiConsumer<ResourceLocation, Biome>> modifications, Biome biome) {
|
||||||
ResourceLocation biomeID = getBiomeID(biome);
|
ResourceLocation biomeID = getBiomeID(biome);
|
||||||
boolean modify = isDatapackBiome(biomeID);
|
boolean modify = isDatapackBiome(biomeID);
|
||||||
if (biome != BuiltinRegistries.BIOME.get(biomeID)) {
|
if (biome != BuiltinRegistries.BIOME.get(biomeID)) {
|
||||||
|
@ -543,7 +584,7 @@ public class BiomeAPI {
|
||||||
|
|
||||||
final BCLBiome bclBiome = BiomeAPI.getBiome(biome);
|
final BCLBiome bclBiome = BiomeAPI.getBiome(biome);
|
||||||
if (bclBiome!=null) {
|
if (bclBiome!=null) {
|
||||||
addBiomeFeature(biome, bclBiome.getFeatures());
|
addStepFeaturesToBiome(biome, bclBiome.getFeatures());
|
||||||
}
|
}
|
||||||
|
|
||||||
sortBiomeFeatures(biome);
|
sortBiomeFeatures(biome);
|
||||||
|
@ -551,7 +592,7 @@ public class BiomeAPI {
|
||||||
|
|
||||||
public static void sortBiomeFeatures(Biome biome) {
|
public static void sortBiomeFeatures(Biome biome) {
|
||||||
BiomeGenerationSettings settings = biome.getGenerationSettings();
|
BiomeGenerationSettings settings = biome.getGenerationSettings();
|
||||||
BiomeGenerationSettingsAccessor accessor = BiomeGenerationSettingsAccessor.class.cast(settings);
|
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) settings;
|
||||||
List<List<Supplier<PlacedFeature>>> featureList = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
|
List<List<Supplier<PlacedFeature>>> featureList = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
|
||||||
final int size = featureList.size();
|
final int size = featureList.size();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
|
@ -629,7 +670,7 @@ public class BiomeAPI {
|
||||||
* @param step a {@link Decoration} step for the feature.
|
* @param step a {@link Decoration} step for the feature.
|
||||||
* @param featureList List of {@link ConfiguredFeature} to add.
|
* @param featureList List of {@link ConfiguredFeature} to add.
|
||||||
*/
|
*/
|
||||||
public static void addBiomeFeature(Biome biome, Decoration step, List<PlacedFeature> featureList) {
|
private static void addBiomeFeature(Biome biome, Decoration step, List<PlacedFeature> featureList) {
|
||||||
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
|
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
|
||||||
List<List<Supplier<PlacedFeature>>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
|
List<List<Supplier<PlacedFeature>>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
|
||||||
Set<PlacedFeature> set = CollectionsUtil.getMutable(accessor.bclib_getFeatureSet());
|
Set<PlacedFeature> set = CollectionsUtil.getMutable(accessor.bclib_getFeatureSet());
|
||||||
|
@ -643,11 +684,14 @@ public class BiomeAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds new features to existing biome.
|
* For internal use only!
|
||||||
|
*
|
||||||
|
* Adds new features to existing biome. Called from {@link BCLBiome#setFeatures(Map)} when the Biome is
|
||||||
|
* first built, and from {@link #onAddedBiome(Biome)} whenever a Biome is readded through a Datapack
|
||||||
* @param biome {@link Biome} to add features in.
|
* @param biome {@link Biome} to add features in.
|
||||||
* @param featureMap Map of {@link ConfiguredFeature} to add.
|
* @param featureMap Map of {@link ConfiguredFeature} to add.
|
||||||
*/
|
*/
|
||||||
public static void addBiomeFeature(Biome biome, Map<Decoration, List<Supplier<PlacedFeature>>> featureMap) {
|
public static void addStepFeaturesToBiome(Biome biome, Map<Decoration, List<Supplier<PlacedFeature>>> featureMap) {
|
||||||
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
|
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
|
||||||
List<List<Supplier<PlacedFeature>>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
|
List<List<Supplier<PlacedFeature>>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
|
||||||
Set<PlacedFeature> set = CollectionsUtil.getMutable(accessor.bclib_getFeatureSet());
|
Set<PlacedFeature> set = CollectionsUtil.getMutable(accessor.bclib_getFeatureSet());
|
||||||
|
@ -665,34 +709,6 @@ public class BiomeAPI {
|
||||||
accessor.bclib_setFeatureSet(set);
|
accessor.bclib_setFeatureSet(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds new features to existing biome.
|
|
||||||
* @param biomeID {@link ResourceLocation} of the {@link Biome} to add features in.
|
|
||||||
* @param feature {@link ConfiguredFeature} to add.
|
|
||||||
* @param step a {@link Decoration} step for the feature.
|
|
||||||
*/
|
|
||||||
private static void addBiomeFeature(ResourceLocation biomeID, PlacedFeature feature, Decoration step) {
|
|
||||||
addBiomeFeature(BuiltinRegistries.BIOME.get(biomeID), step, feature);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds new features to existing biome.
|
|
||||||
* @param biome {@link Biome} to add features in.
|
|
||||||
* @param features array of {@link BCLFeature} to add.
|
|
||||||
*/
|
|
||||||
public static void addBiomeFeatures(Biome biome, BCLFeature... features) {
|
|
||||||
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
|
|
||||||
List<List<Supplier<PlacedFeature>>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
|
|
||||||
Set<PlacedFeature> set = CollectionsUtil.getMutable(accessor.bclib_getFeatureSet());
|
|
||||||
for (BCLFeature feature: features) {
|
|
||||||
List<Supplier<PlacedFeature>> featureList = getFeaturesList(allFeatures, feature.getDecoration());
|
|
||||||
featureList.add(() -> feature.getPlacedFeature());
|
|
||||||
set.add(feature.getPlacedFeature());
|
|
||||||
}
|
|
||||||
accessor.bclib_setFeatures(allFeatures);
|
|
||||||
accessor.bclib_setFeatureSet(set);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds new structure feature to existing biome.
|
* Adds new structure feature to existing biome.
|
||||||
* @param biomeKey {@link ResourceKey} for the {@link Biome} to add structure feature in.
|
* @param biomeKey {@link ResourceKey} for the {@link Biome} to add structure feature in.
|
||||||
|
@ -703,17 +719,26 @@ public class BiomeAPI {
|
||||||
BCLib.LOGGER.error("null is not a valid biomeKey for " + structure);
|
BCLib.LOGGER.error("null is not a valid biomeKey for " + structure);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
changeStructureStarts(biomeKey.location(), structure, structureMap -> {
|
changeStructureStarts(biomeKey.location(), structure, (structureMap, configMap) -> {
|
||||||
Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>> configuredMap = structureMap.computeIfAbsent(structure.feature, k -> HashMultimap.create());
|
Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>> configuredMap = structureMap.computeIfAbsent(structure.feature, k -> HashMultimap.create());
|
||||||
configuredMap.put(structure, biomeKey);
|
configuredMap.put(structure, biomeKey);
|
||||||
|
|
||||||
|
StructureFeatureConfiguration config = FabricStructureImpl.STRUCTURE_TO_CONFIG_MAP.get(structure.feature);
|
||||||
|
if (config!=null){
|
||||||
|
configMap.put(structure.feature, config);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addBiomeStructure(Biome biome, ConfiguredStructureFeature structure) {
|
public static void addBiomeStructure(Biome biome, ConfiguredStructureFeature structure) {
|
||||||
changeStructureStarts(BiomeAPI.getBiomeID(biome), structure, structureMap -> {
|
changeStructureStarts(BiomeAPI.getBiomeID(biome), structure, (structureMap, configMap) -> {
|
||||||
Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>> configuredMap = structureMap.computeIfAbsent(structure.feature, k -> HashMultimap.create());
|
Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>> configuredMap = structureMap.computeIfAbsent(structure.feature, k -> HashMultimap.create());
|
||||||
var key = getBiomeKey(biome);
|
var key = getBiomeKey(biome);
|
||||||
if (key!=null) {
|
if (key!=null) {
|
||||||
|
StructureFeatureConfiguration config = FabricStructureImpl.STRUCTURE_TO_CONFIG_MAP.get(structure.feature);
|
||||||
|
if (config!=null){
|
||||||
|
configMap.put(structure.feature, config);
|
||||||
|
}
|
||||||
configuredMap.put(structure, key);
|
configuredMap.put(structure, key);
|
||||||
} else {
|
} else {
|
||||||
BCLib.LOGGER.warning("Unable to find Biome " + getBiomeID(biome));
|
BCLib.LOGGER.warning("Unable to find Biome " + getBiomeID(biome));
|
||||||
|
@ -881,11 +906,13 @@ public class BiomeAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static Map<StructureID, Consumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>>> structureStarts = new HashMap<>();
|
private final static Map<StructureID, BiConsumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>, Map<StructureFeature<?>, StructureFeatureConfiguration>>> structureStarts = new HashMap<>();
|
||||||
|
|
||||||
public static void registerStructureEvents(){
|
public static void registerStructureEvents(){
|
||||||
DynamicRegistrySetupCallback.EVENT.register(registryManager -> {
|
DynamicRegistrySetupCallback.EVENT.register(registryManager -> {
|
||||||
Optional<? extends Registry<NoiseGeneratorSettings>> oGeneratorRegistry = registryManager.registry(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY);
|
Optional<? extends Registry<NoiseGeneratorSettings>> oGeneratorRegistry = registryManager.registry(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY);
|
||||||
|
Optional<? extends Registry<Codec<? extends BiomeSource>>> oBiomeSourceRegistry = registryManager.registry(Registry.BIOME_SOURCE_REGISTRY);
|
||||||
|
|
||||||
|
|
||||||
if (oGeneratorRegistry.isPresent()) {
|
if (oGeneratorRegistry.isPresent()) {
|
||||||
RegistryEntryAddedCallback
|
RegistryEntryAddedCallback
|
||||||
|
@ -895,7 +922,7 @@ public class BiomeAPI {
|
||||||
|
|
||||||
//add back modded structures
|
//add back modded structures
|
||||||
StructureSettingsAccessor a = (StructureSettingsAccessor)settings.structureSettings();
|
StructureSettingsAccessor a = (StructureSettingsAccessor)settings.structureSettings();
|
||||||
structureStarts.values().forEach(modifier -> changeStructureStarts(a, modifier));
|
structureStarts.entrySet().forEach(entry -> changeStructureStarts(a, entry.getValue()));
|
||||||
|
|
||||||
//add surface rules
|
//add surface rules
|
||||||
if (biomeRegistry!=null) {
|
if (biomeRegistry!=null) {
|
||||||
|
@ -919,11 +946,7 @@ public class BiomeAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearStructureStarts(){
|
private static void changeStructureStarts(ResourceLocation id, ConfiguredStructureFeature structure, BiConsumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>, Map<StructureFeature<?>, StructureFeatureConfiguration>> modifier) {
|
||||||
structureStarts.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void changeStructureStarts(ResourceLocation id, ConfiguredStructureFeature structure, Consumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>> modifier) {
|
|
||||||
structureStarts.put(new StructureID(id, structure), modifier);
|
structureStarts.put(new StructureID(id, structure), modifier);
|
||||||
Registry<NoiseGeneratorSettings> chunkGenSettingsRegistry = BuiltinRegistries.NOISE_GENERATOR_SETTINGS;
|
Registry<NoiseGeneratorSettings> chunkGenSettingsRegistry = BuiltinRegistries.NOISE_GENERATOR_SETTINGS;
|
||||||
|
|
||||||
|
@ -934,11 +957,17 @@ public class BiomeAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void changeStructureStarts(StructureSettingsAccessor access, Consumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>> modifier) {
|
private static void changeStructureStarts(StructureSettingsAccessor access, BiConsumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>, Map<StructureFeature<?>, StructureFeatureConfiguration>> modifier) {
|
||||||
Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> structureMap;
|
Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> structureMap;
|
||||||
structureMap = getMutableStructureConfig(access);
|
Map<StructureFeature<?>, StructureFeatureConfiguration> configMap;
|
||||||
modifier.accept(structureMap);
|
|
||||||
setMutableStructureConfig(access, structureMap);
|
structureMap = getMutableConfiguredStructures(access);
|
||||||
|
configMap = getMutableStructureConfig(access);
|
||||||
|
|
||||||
|
modifier.accept(structureMap, configMap);
|
||||||
|
|
||||||
|
setMutableConfiguredStructures(access, structureMap);
|
||||||
|
setMutableStructureConfig(access, configMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sortFeatures(List<Supplier<PlacedFeature>> features) {
|
private static void sortFeatures(List<Supplier<PlacedFeature>> features) {
|
||||||
|
@ -1000,7 +1029,7 @@ public class BiomeAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
//inspired by net.fabricmc.fabric.impl.biome.modification.BiomeStructureStartsImpl
|
//inspired by net.fabricmc.fabric.impl.biome.modification.BiomeStructureStartsImpl
|
||||||
private static Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> getMutableStructureConfig(StructureSettingsAccessor access) {
|
private static Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> getMutableConfiguredStructures(StructureSettingsAccessor access) {
|
||||||
ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> configuredStructures = access.bcl_getConfiguredStructures();
|
ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> configuredStructures = access.bcl_getConfiguredStructures();
|
||||||
Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> result = new HashMap<>(configuredStructures.size());
|
Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> result = new HashMap<>(configuredStructures.size());
|
||||||
|
|
||||||
|
@ -1012,7 +1041,7 @@ public class BiomeAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
//inspired by net.fabricmc.fabric.impl.biome.modification.BiomeStructureStartsImpl
|
//inspired by net.fabricmc.fabric.impl.biome.modification.BiomeStructureStartsImpl
|
||||||
private static void setMutableStructureConfig(StructureSettingsAccessor access, Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> structureStarts) {
|
private static void setMutableConfiguredStructures(StructureSettingsAccessor access, Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> structureStarts) {
|
||||||
access.bcl_setConfiguredStructures(
|
access.bcl_setConfiguredStructures(
|
||||||
structureStarts
|
structureStarts
|
||||||
.entrySet()
|
.entrySet()
|
||||||
|
@ -1020,4 +1049,12 @@ public class BiomeAPI {
|
||||||
.collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, e -> ImmutableMultimap.copyOf(e.getValue())))
|
.collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, e -> ImmutableMultimap.copyOf(e.getValue())))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<StructureFeature<?>, StructureFeatureConfiguration> getMutableStructureConfig(StructureSettingsAccessor access) {
|
||||||
|
return CollectionsUtil.getMutable(access.bcl_getStructureConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setMutableStructureConfig(StructureSettingsAccessor access, Map<StructureFeature<?>, StructureFeatureConfiguration> structureConfig) {
|
||||||
|
access.bcl_setStructureConfig(structureConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package ru.bclib.interfaces;
|
||||||
|
|
||||||
|
public interface BiomeSourceAccessor {
|
||||||
|
void bclRebuildFeatures();
|
||||||
|
}
|
|
@ -61,7 +61,7 @@ public abstract class MinecraftMixin {
|
||||||
@Inject(method = "loadLevel", cancellable = true, at = @At("HEAD"))
|
@Inject(method = "loadLevel", cancellable = true, at = @At("HEAD"))
|
||||||
private void bclib_callFixerOnLoad(String levelID, CallbackInfo ci) {
|
private void bclib_callFixerOnLoad(String levelID, CallbackInfo ci) {
|
||||||
DataExchangeAPI.prepareServerside();
|
DataExchangeAPI.prepareServerside();
|
||||||
BiomeAPI.clearStructureStarts();
|
BiomeAPI.prepareWorldData();
|
||||||
|
|
||||||
if (DataFixerAPI.fixData(this.levelSource, levelID, true, (appliedFixes) -> {
|
if (DataFixerAPI.fixData(this.levelSource, levelID, true, (appliedFixes) -> {
|
||||||
LifeCycleAPI._runBeforeLevelLoad();
|
LifeCycleAPI._runBeforeLevelLoad();
|
||||||
|
@ -76,6 +76,9 @@ public abstract class MinecraftMixin {
|
||||||
|
|
||||||
@Inject(method = "createLevel", at = @At("HEAD"))
|
@Inject(method = "createLevel", at = @At("HEAD"))
|
||||||
private void bclib_initPatchData(String levelID, LevelSettings levelSettings, RegistryHolder registryHolder, WorldGenSettings worldGenSettings, CallbackInfo ci) {
|
private void bclib_initPatchData(String levelID, LevelSettings levelSettings, RegistryHolder registryHolder, WorldGenSettings worldGenSettings, CallbackInfo ci) {
|
||||||
|
DataExchangeAPI.prepareServerside();
|
||||||
|
BiomeAPI.prepareWorldData();
|
||||||
|
|
||||||
DataFixerAPI.initializeWorldData(this.levelSource, levelID, true);
|
DataFixerAPI.initializeWorldData(this.levelSource, levelID, true);
|
||||||
LifeCycleAPI._runBeforeLevelLoad();
|
LifeCycleAPI._runBeforeLevelLoad();
|
||||||
}
|
}
|
||||||
|
|
38
src/main/java/ru/bclib/mixin/common/BiomeSourceMixin.java
Normal file
38
src/main/java/ru/bclib/mixin/common/BiomeSourceMixin.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package ru.bclib.mixin.common;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.biome.BiomeSource;
|
||||||
|
import net.minecraft.world.level.biome.BiomeSource.StepFeatureData;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
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.BCLib;
|
||||||
|
import ru.bclib.api.biomes.BiomeAPI;
|
||||||
|
import ru.bclib.interfaces.BiomeSourceAccessor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Mixin(BiomeSource.class)
|
||||||
|
public abstract class BiomeSourceMixin implements BiomeSourceAccessor {
|
||||||
|
@Shadow protected abstract List<StepFeatureData> buildFeaturesPerStep(List<Biome> list, boolean bl);
|
||||||
|
|
||||||
|
@Shadow public abstract Set<Biome> possibleBiomes();
|
||||||
|
|
||||||
|
@Mutable @Shadow @Final private List<StepFeatureData> featuresPerStep;
|
||||||
|
|
||||||
|
public void bclRebuildFeatures(){
|
||||||
|
BCLib.LOGGER.info("Rebuilding features in BiomeSource " + this.getClass());
|
||||||
|
featuresPerStep = buildFeaturesPerStep(this.possibleBiomes().stream().toList(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method="<init>(Ljava/util/List;)V", at=@At(value="INVOKE", shift = Shift.AFTER, target="Lnet/minecraft/world/level/biome/BiomeSource;buildFeaturesPerStep(Ljava/util/List;Z)Ljava/util/List;"))
|
||||||
|
private void bcl_Init(List list, CallbackInfo ci){
|
||||||
|
BiomeAPI.registerBiomeSource((BiomeSource)(Object)this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,16 +7,26 @@ import net.minecraft.world.level.biome.Biome;
|
||||||
import net.minecraft.world.level.levelgen.StructureSettings;
|
import net.minecraft.world.level.levelgen.StructureSettings;
|
||||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
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.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Mutable;
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Mixin(StructureSettings.class)
|
@Mixin(StructureSettings.class)
|
||||||
public interface StructureSettingsAccessor {
|
public interface StructureSettingsAccessor {
|
||||||
@Accessor("configuredStructures")
|
@Accessor("configuredStructures")
|
||||||
ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> bcl_getConfiguredStructures();
|
ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> bcl_getConfiguredStructures();
|
||||||
|
|
||||||
|
@Accessor("structureConfig")
|
||||||
|
Map<StructureFeature<?>, StructureFeatureConfiguration> bcl_getStructureConfig();
|
||||||
|
|
||||||
@Accessor("configuredStructures")
|
@Accessor("configuredStructures")
|
||||||
@Mutable
|
@Mutable
|
||||||
void bcl_setConfiguredStructures(ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> structureConfig);
|
void bcl_setConfiguredStructures(ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> configuredStructures);
|
||||||
|
|
||||||
|
@Accessor("structureConfig")
|
||||||
|
@Mutable
|
||||||
|
void bcl_setStructureConfig(Map<StructureFeature<?>, StructureFeatureConfiguration> structureConfig);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,8 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import ru.bclib.BCLib;
|
import ru.bclib.BCLib;
|
||||||
import ru.bclib.api.biomes.BiomeAPI;
|
import ru.bclib.api.biomes.BiomeAPI;
|
||||||
import ru.bclib.util.Pair;
|
|
||||||
import ru.bclib.util.WeightedList;
|
import ru.bclib.util.WeightedList;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -370,6 +368,7 @@ public class BCLBiome {
|
||||||
*/
|
*/
|
||||||
public void setFeatures(Map<Decoration, List<Supplier<PlacedFeature>>> features) {
|
public void setFeatures(Map<Decoration, List<Supplier<PlacedFeature>>> features) {
|
||||||
this.features = features;
|
this.features = features;
|
||||||
|
BiomeAPI.addStepFeaturesToBiome(getBiome(), features);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -39,7 +39,8 @@
|
||||||
"AnvilMenuMixin",
|
"AnvilMenuMixin",
|
||||||
"TagLoaderMixin",
|
"TagLoaderMixin",
|
||||||
"MainMixin",
|
"MainMixin",
|
||||||
"SurfaceRulesContextAccessor"
|
"SurfaceRulesContextAccessor",
|
||||||
|
"BiomeSourceMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue