Add callback that allows us to modify Biome tags

This commit is contained in:
Frank 2022-05-17 02:25:51 +02:00
parent aaa0acdd09
commit b6321cec93
4 changed files with 92 additions and 13 deletions

View file

@ -30,7 +30,6 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
@ -50,6 +49,7 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.Nullable;
import ru.bclib.BCLib;
import ru.bclib.api.tag.CommonBiomeTags;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.entity.BCLEntityWrapper;
import ru.bclib.interfaces.BiomeSourceAccessor;
@ -60,12 +60,10 @@ import ru.bclib.interfaces.SurfaceRuleProvider;
import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor;
import ru.bclib.mixin.common.MobSpawnSettingsAccessor;
import ru.bclib.util.CollectionsUtil;
import ru.bclib.util.MHelper;
import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.biomes.FabricBiomesData;
import ru.bclib.world.biomes.VanillaBiomeSettings;
import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.generator.BiomePicker;
import java.util.HashSet;
import java.util.List;
@ -73,13 +71,14 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.structure.Structure;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class BiomeAPI {
enum Dimension {OVERWORLD, NETHER, END_LAND, END_VOID, UNDEFINED};
@ -98,6 +97,7 @@ public class BiomeAPI {
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, List<BiConsumer<ResourceLocation, Holder<Biome>>>> TAG_ADDERS = Maps.newHashMap();
private static final Map<ResourceLocation, SurfaceRules.RuleSource> SURFACE_RULES = Maps.newHashMap();
private static final Set<SurfaceRuleProvider> MODIFIED_SURFACE_PROVIDERS = new HashSet<>(8);
@ -171,7 +171,17 @@ public class BiomeAPI {
}
ID_MAP.put(bclbiome.getID(), bclbiome);
DIMENSION_MAP.put(bclbiome.getID(), dim);
if (dim==Dimension.NETHER) {
TagAPI.addBiomeTag(BiomeTags.IS_NETHER, bclbiome.getBiome());
TagAPI.addBiomeTag(CommonBiomeTags.IN_NETHER, bclbiome.getBiome());
} else if (dim==Dimension.END_LAND || dim==Dimension.END_VOID) {
TagAPI.addBiomeTag(BiomeTags.IS_END, bclbiome.getBiome());
}
bclbiome.afterRegistration();
return bclbiome;
}
@ -180,11 +190,7 @@ public class BiomeAPI {
registerBiome(subBiome, dim);
parent.addSubBiome(subBiome);
if (dim==Dimension.NETHER) {
TagAPI.addBiomeTag(BiomeTags.IS_NETHER, subBiome.getBiome());
} else if (dim==Dimension.END_LAND || dim==Dimension.END_VOID) {
TagAPI.addBiomeTag(BiomeTags.IS_END, subBiome.getBiome());
}
return subBiome;
}
@ -204,7 +210,6 @@ public class BiomeAPI {
ResourceKey<Biome> key = BiomeAPI.getBiomeKeyOrThrow(bclBiome.getBiomeHolder());
bclBiome.forEachClimateParameter(p -> NetherBiomeData.addNetherBiome(key, p));
TagAPI.addBiomeTag(BiomeTags.IS_NETHER, bclBiome.getBiome());
return bclBiome;
}
@ -217,7 +222,6 @@ public class BiomeAPI {
public static BCLBiome registerNetherBiome(Biome biome) {
BCLBiome bclBiome = new BCLBiome(biome, null);
registerBiome(bclBiome, Dimension.NETHER);
TagAPI.addBiomeTag(BiomeTags.IS_NETHER, bclBiome.getBiome());
return bclBiome;
}
@ -502,6 +506,52 @@ public class BiomeAPI {
public static void registerEndBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
registerBiomeModification(Level.END, modification);
}
/**
* For internal use only
*/
public static void _runTagAdders(){
for (var mod:TAG_ADDERS.entrySet()) {
Stream<ResourceLocation> s = null;
if (mod.getKey()==Level.NETHER) s = DIMENSION_MAP.entrySet().stream().filter(e ->e.getValue() == Dimension.NETHER).map(e -> e.getKey());
else if (mod.getKey()==Level.END) s = DIMENSION_MAP.entrySet().stream().filter(e ->e.getValue() == Dimension.END_VOID || e.getValue()==Dimension.END_LAND).map(e -> e.getKey());
if (s!=null) {
s.forEach(id -> {
BCLBiome b = BiomeAPI.getBiome(id);
Holder<Biome> biomeHolder = b.getBiomeHolder();
if (biomeHolder.isBound()) {
mod.getValue().forEach(c -> c.accept(id, biomeHolder));
}
});
}
}
}
/**
* Registers new biome modification for specified dimension. Will work both for mod and datapack biomes.
* @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 onFinishingBiomeTags(ResourceKey dimensionID, BiConsumer<ResourceLocation, Holder<Biome>> modification) {
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = TAG_ADDERS.computeIfAbsent(dimensionID, k -> Lists.newArrayList());
modifications.add(modification);
}
/**
* Registers new biome modification for the Nether. Will work both for mod and datapack biomes.
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
*/
public static void onFinishingNetherBiomeTags(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
onFinishingBiomeTags(Level.NETHER, modification);
}
/**
* Registers new biome modification for the End. Will work both for mod and datapack biomes.
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
*/
public static void onFinishingEndBiomeTags(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
onFinishingBiomeTags(Level.END, modification);
}
/**
* Will apply biome modifications to world, internal usage only.

View file

@ -0,0 +1,9 @@
package ru.bclib.api.tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
public class CommonBiomeTags {
public static final TagKey<Biome> IN_NETHER = TagAPI.makeCommonBiomeTag("in_nether");
}

View file

@ -139,6 +139,10 @@ public class TagAPI {
public static TagKey<Item> makeCommonItemTag(String name) {
return ITEMS.makeCommonTag(name);
}
public static TagKey<Biome> makeCommonBiomeTag(String name) {
return BIOMES.makeCommonTag(name);
}
/**
* Initializes basic tags. Should be called only in BCLib main class.
@ -265,7 +269,9 @@ public class TagAPI {
public static void addItemTag(TagKey<Item> tagID, Item... items) {
ITEMS.add(tagID, items);
}
/**
* Automatically called in {@link net.minecraft.tags.TagLoader#loadAndBuild(ResourceManager)}.
* <p>
@ -277,9 +283,10 @@ public class TagAPI {
* @return The {@code tagsMap} Parameter.
*/
public static <T> Map<ResourceLocation, Tag.Builder> apply(String directory, Map<ResourceLocation, Tag.Builder> tagsMap) {
TagType<?> type = TYPES.get(directory);
if (type!=null){
type.forEach((id, ids) -> apply(tagsMap.computeIfAbsent(id, key -> Tag.Builder.tag()), ids));
type.apply(tagsMap);
}
// final BiConsumer<ResourceLocation, Set<ResourceLocation>> consumer;

View file

@ -4,12 +4,15 @@ import net.minecraft.core.DefaultedRegistry;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import net.minecraft.tags.TagManager;
import net.minecraft.world.level.biome.Biome;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import ru.bclib.BCLib;
import ru.bclib.api.biomes.BiomeAPI;
import java.util.Map;
import java.util.Set;
@ -17,6 +20,7 @@ import java.util.function.BiConsumer;
import java.util.function.Function;
public class TagType<T> {
boolean isFrozen = false;
public static class RegistryBacked<T> extends Simple<T>{
private final DefaultedRegistry<T> registry;
@ -121,6 +125,7 @@ public class TagType<T> {
}
public void addUntyped(TagKey<T> tagID, ResourceLocation... elements) {
if (isFrozen) BCLib.LOGGER.warning("Adding Tag " + tagID + " after the API was frozen.");
Set<ResourceLocation> set = getSetForTag(tagID);
for (ResourceLocation id : elements) {
if (id != null) {
@ -141,6 +146,7 @@ public class TagType<T> {
* @param elements array of Elements to add into tag.
*/
protected void add(TagKey<T> tagID, T... elements) {
if (isFrozen) BCLib.LOGGER.warning("Adding Tag " + tagID + " after the API was frozen.");
Set<ResourceLocation> set = getSetForTag(tagID);
for (T element : elements) {
ResourceLocation id = locationProvider.apply(element);
@ -158,6 +164,7 @@ public class TagType<T> {
@Deprecated(forRemoval = true)
protected void add(ResourceLocation tagID, T... elements) {
if (isFrozen) BCLib.LOGGER.warning("Adding Tag " + tagID + " after the API was frozen.");
Set<ResourceLocation> set = getSetForTag(tagID);
for (T element : elements) {
ResourceLocation id = locationProvider.apply(element);
@ -177,4 +184,10 @@ public class TagType<T> {
public void forEach(BiConsumer<ResourceLocation, Set<ResourceLocation>> consumer) {
tags.forEach(consumer);
}
public void apply(Map<ResourceLocation, Tag.Builder> tagsMap){
if (Registry.BIOME_REGISTRY.equals(registryKey)) BiomeAPI._runTagAdders();
this.isFrozen = true;
this.forEach((id, ids) -> TagAPI.apply(tagsMap.computeIfAbsent(id, key -> Tag.Builder.tag()), ids));
}
}