Merge pull request #126 from paulevsGitch/1.18.2

1.18.2
This commit is contained in:
paulevsGitch 2022-04-08 20:55:01 +03:00 committed by GitHub
commit ff7eda1287
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
97 changed files with 1287 additions and 1138 deletions

View file

@ -13,6 +13,7 @@ import ru.bclib.api.dataexchange.handler.autosync.RequestFiles;
import ru.bclib.api.dataexchange.handler.autosync.SendFiles;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.config.Configs;
import ru.bclib.recipes.AnvilRecipe;
import ru.bclib.recipes.CraftingRecipes;
import ru.bclib.registry.BaseBlockEntities;
import ru.bclib.registry.BaseRegistry;
@ -38,6 +39,7 @@ public class BCLib implements ModInitializer {
CraftingRecipes.init();
WorldDataAPI.registerModCache(MOD_ID);
DataExchangeAPI.registerMod(MOD_ID);
AnvilRecipe.register();
DataExchangeAPI.registerDescriptors(List.of(
HelloClient.DESCRIPTOR,

View file

@ -1,5 +1,6 @@
package ru.bclib.api;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
@ -49,7 +50,7 @@ public class LifeCycleAPI {
LevelStorageSource.LevelStorageAccess levelStorageAccess,
ServerLevelData serverLevelData,
ResourceKey<Level> resourceKey,
DimensionType dimensionType,
Holder<DimensionType> dimensionType,
ChunkProgressListener chunkProgressListener,
ChunkGenerator chunkGenerator,
boolean bl,
@ -114,7 +115,7 @@ public class LifeCycleAPI {
LevelStorageSource.LevelStorageAccess levelStorageAccess,
ServerLevelData serverLevelData,
ResourceKey<Level> resourceKey,
DimensionType dimensionType,
Holder<DimensionType> dimensionType,
ChunkProgressListener chunkProgressListener,
ChunkGenerator chunkGenerator,
boolean bl,

View file

@ -10,6 +10,7 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import ru.bclib.BCLib;
import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.api.tag.NamedMineableTags;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.api.tag.TagAPI.TagLocation;
import ru.bclib.blocks.BaseBarrelBlock;
@ -23,6 +24,7 @@ import ru.bclib.config.Configs;
import ru.bclib.interfaces.PostInitable;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.interfaces.tools.*;
import ru.bclib.registry.BaseBlockEntities;
import java.util.List;
@ -111,6 +113,29 @@ public class PostInitAPI {
else if (block instanceof BaseFurnaceBlock) {
BaseBlockEntities.FURNACE.registerBlock(block);
}
if (!(block instanceof PreventMineableAdd)) {
if (block instanceof AddMineableShears) {
TagAPI.addBlockTags(block, NamedMineableTags.SHEARS);
}
if (block instanceof AddMineableAxe) {
TagAPI.addBlockTags(block, NamedMineableTags.AXE);
}
if (block instanceof AddMineablePickaxe) {
TagAPI.addBlockTags(block, NamedMineableTags.PICKAXE);
}
if (block instanceof AddMineableShovel) {
TagAPI.addBlockTags(block, NamedMineableTags.SHOVEL);
}
if (block instanceof AddMineableHoe) {
TagAPI.addBlockTags(block, NamedMineableTags.HOE);
}
if (block instanceof AddMineableSword) {
TagAPI.addBlockTags(block, NamedMineableTags.SWORD);
}
if (block instanceof AddMineableHammer) {
TagAPI.addBlockTags(block, NamedMineableTags.HAMMER);
}
}
if (block instanceof TagProvider) {
TagProvider.class.cast(block).addTags(blockTags, itemTags);
blockTags.forEach(tag -> TagAPI.addBlockTag(tag, block));

View file

@ -1,25 +1,24 @@
package ru.bclib.api.biomes;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.data.worldgen.BiomeDefaultFeatures;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.Music;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.tags.TagKey;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
import net.minecraft.world.level.biome.AmbientMoodSettings;
import net.minecraft.world.level.biome.AmbientParticleSettings;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.*;
import net.minecraft.world.level.biome.Biome.BiomeBuilder;
import net.minecraft.world.level.biome.Biome.BiomeCategory;
import net.minecraft.world.level.biome.Biome.Precipitation;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSpecialEffects;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@ -28,12 +27,13 @@ import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.Noises;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import ru.bclib.api.surface.SurfaceRuleBuilder;
import ru.bclib.entity.BCLEntityWrapper;
import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor;
import ru.bclib.util.CollectionsUtil;
import ru.bclib.util.ColorUtil;
import ru.bclib.util.Pair;
import ru.bclib.util.TriFunction;
import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.biomes.BCLBiomeSettings;
@ -41,12 +41,10 @@ import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.structures.BCLStructureFeature;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class BCLBiomeBuilder {
@ -57,7 +55,8 @@ public class BCLBiomeBuilder {
private static final BCLBiomeBuilder INSTANCE = new BCLBiomeBuilder();
private static final SurfaceRules.ConditionSource SURFACE_NOISE = SurfaceRules.noiseCondition(Noises.SOUL_SAND_LAYER, -0.012);
private List<ConfiguredStructureFeature> structures = new ArrayList<>(16);
private List<TagKey<Biome>> structureTags = new ArrayList<>(8);
private List<Pair<GenerationStep.Carving, Holder<? extends ConfiguredWorldCarver<?>>>> carvers = new ArrayList<>(1);
private BiomeGenerationSettings.Builder generationSettings;
private BiomeSpecialEffects.Builder effectsBuilder;
private MobSpawnSettings.Builder spawnSettings;
@ -87,7 +86,7 @@ public class BCLBiomeBuilder {
INSTANCE.generationSettings = null;
INSTANCE.effectsBuilder = null;
INSTANCE.spawnSettings = null;
INSTANCE.structures.clear();
INSTANCE.structureTags.clear();
INSTANCE.temperature = 1.0F;
INSTANCE.fogDensity = 1.0F;
INSTANCE.edgeSize = 0;
@ -96,6 +95,7 @@ public class BCLBiomeBuilder {
INSTANCE.height = 0.1F;
INSTANCE.vertical = false;
INSTANCE.edge = null;
INSTANCE.carvers.clear();
return INSTANCE;
}
@ -500,7 +500,7 @@ public class BCLBiomeBuilder {
* @param feature {@link PlacedFeature}.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder feature(Decoration decoration, PlacedFeature feature) {
public BCLBiomeBuilder feature(Decoration decoration, Holder<PlacedFeature> feature) {
getGeneration().addFeature(decoration, feature);
return this;
}
@ -542,11 +542,11 @@ public class BCLBiomeBuilder {
/**
* Adds new structure feature into the biome.
* @param structure {@link ConfiguredStructureFeature} to add.
* @param structureTag {@link TagKey} to add.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder structure(ConfiguredStructureFeature<?, ?> structure) {
structures.add(structure);
public BCLBiomeBuilder structure(TagKey<Biome> structureTag) {
structureTags.add(structureTag);
return this;
}
@ -557,7 +557,7 @@ public class BCLBiomeBuilder {
*/
public BCLBiomeBuilder structure(BCLStructureFeature structure) {
structure.addInternalBiome(biomeID);
return structure(structure.getFeatureConfigured());
return structure(structure.biomeTag);
}
/**
@ -565,11 +565,13 @@ public class BCLBiomeBuilder {
* @param carver {@link ConfiguredWorldCarver} to add.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder carver(GenerationStep.Carving step, ConfiguredWorldCarver<?> carver) {
public BCLBiomeBuilder carver(GenerationStep.Carving step, Holder<? extends ConfiguredWorldCarver<?>> carver) {
final ResourceLocation immutableID = biomeID;
BuiltinRegistries.CONFIGURED_CARVER
.getResourceKey(carver)
.ifPresent(key -> BiomeModifications.addCarver(ctx -> ctx.getBiomeKey().location().equals(immutableID), step, key));
var oKey = carver.unwrapKey();
if (oKey.isPresent()) {
BiomeModifications.addCarver(ctx -> ctx.getBiomeKey().location().equals(immutableID), step, (ResourceKey<ConfiguredWorldCarver<?>>) oKey.get());
}
//carvers.add(new Pair<>(step, carver));
return this;
}
@ -625,8 +627,8 @@ public class BCLBiomeBuilder {
this.height = height;
return this;
}
/**
* Make this a vertical Biome
@ -645,7 +647,7 @@ public class BCLBiomeBuilder {
public BCLBiome build() {
return build((BiomeSupplier<BCLBiome>)BCLBiome::new);
}
/**
* Finalize biome creation.
* @param biomeConstructor {@link BiFunction} biome constructor.
@ -655,7 +657,22 @@ public class BCLBiomeBuilder {
public <T extends BCLBiome> T build(BiFunction<ResourceLocation, Biome, T> biomeConstructor) {
return build((id, biome, settings)->biomeConstructor.apply(id, biome));
}
private static BiomeGenerationSettings fixGenerationSettings(BiomeGenerationSettings settings){
//Fabric Biome Modification API can not handle an empty carver map, thus we will create one with
//an empty HolderSet for every possible step:
//https://github.com/FabricMC/fabric/issues/2079
//TODO: Remove, once fabric gets fixed
if (settings instanceof BiomeGenerationSettingsAccessor acc){
Map<GenerationStep.Carving, HolderSet<ConfiguredWorldCarver<?>>> carvers = CollectionsUtil.getMutable(acc.bclib_getCarvers());
for (GenerationStep.Carving step : GenerationStep.Carving.values()){
carvers.computeIfAbsent(step, __->HolderSet.direct(Lists.newArrayList()));
}
acc.bclib_setCarvers(carvers);
}
return settings;
}
/**
* Finalize biome creation.
* @param biomeConstructor {@link BiomeSupplier} biome constructor.
@ -670,26 +687,8 @@ public class BCLBiomeBuilder {
builder.mobSpawnSettings(getSpawns().build());
builder.specialEffects(getEffects().build());
Map<Decoration, List<Supplier<PlacedFeature>>> defferedFeatures = new HashMap<>();
BiomeGenerationSettingsAccessor acc = BiomeGenerationSettingsAccessor.class.cast(getGeneration().build());
if (acc != null) {
builder.generationSettings(new BiomeGenerationSettings.Builder().build());
var decorations = acc.bclib_getFeatures();
for (Decoration d : Decoration.values()) {
int i = d.ordinal();
if (i >= 0 && i < decorations.size()) {
var features = decorations.get(i);
defferedFeatures.put(d, features.stream().collect(Collectors.toList()));
}
else {
defferedFeatures.put(d, new ArrayList<>(0));
}
}
}
else {
builder.generationSettings(getGeneration().build());
}
builder.generationSettings(fixGenerationSettings(getGeneration().build()));
BCLBiomeSettings settings = BCLBiomeSettings.createBCL()
.setTerrainHeight(height)
@ -699,11 +698,13 @@ public class BCLBiomeBuilder {
.setEdge(edge)
.setVertical(vertical)
.build();
final T res = biomeConstructor.apply(biomeID, builder.build(), settings);
res.attachStructures(structures);
final Biome biome = builder.build();
final T res = biomeConstructor.apply(biomeID, biome, settings);
res.attachStructures(structureTags);
res.setSurface(surfaceRule);
res.setFeatures(defferedFeatures);
//carvers.forEach(cfg -> BiomeAPI.addBiomeCarver(biome, cfg.second, cfg.first));
return res;
}

View file

@ -1,19 +1,18 @@
package ru.bclib.api.biomes;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.impl.biome.NetherBiomeData;
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
import net.fabricmc.fabric.impl.structure.FabricStructureImpl;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceKey;
@ -26,11 +25,7 @@ import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.WorldGenLevel;
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.*;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
@ -41,27 +36,21 @@ import net.minecraft.world.level.levelgen.GenerationStep.Carving;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.StructureSettings;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.feature.configurations.StructureFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.Nullable;
import ru.bclib.BCLib;
import ru.bclib.entity.BCLEntityWrapper;
import ru.bclib.interfaces.BiomeSourceAccessor;
import ru.bclib.interfaces.NoiseGeneratorSettingsProvider;
import ru.bclib.interfaces.SurfaceMaterialProvider;
import ru.bclib.interfaces.SurfaceProvider;
import ru.bclib.interfaces.SurfaceRuleProvider;
import ru.bclib.interfaces.*;
import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor;
import ru.bclib.mixin.common.MobSpawnSettingsAccessor;
import ru.bclib.mixin.common.StructureSettingsAccessor;
import ru.bclib.util.CollectionsUtil;
import ru.bclib.util.MHelper;
import ru.bclib.world.biomes.BCLBiome;
@ -69,18 +58,9 @@ 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 ru.bclib.world.structures.BCLStructureFeature;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@ -100,27 +80,26 @@ public class BiomeAPI {
private static final Map<Biome, BCLBiome> CLIENT = Maps.newHashMap();
private static Registry<Biome> biomeRegistry;
private static final Map<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 final static Map<StructureID, BiConsumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>, Map<StructureFeature<?>, StructureFeatureConfiguration>>> STRUCTURE_STARTS = new HashMap<>();
private static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Biome>>> MODIFICATIONS = Maps.newHashMap();
private static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Holder<Biome>>>> MODIFICATIONS = Maps.newHashMap();
private static final Map<ResourceLocation, SurfaceRules.RuleSource> SURFACE_RULES = Maps.newHashMap();
private static final Set<SurfaceRuleProvider> MODIFIED_SURFACE_PROVIDERS = new HashSet<>(8);
public static final BCLBiome NETHER_WASTES_BIOME = registerNetherBiome(getFromRegistry(Biomes.NETHER_WASTES));
public static final BCLBiome CRIMSON_FOREST_BIOME = registerNetherBiome(getFromRegistry(Biomes.CRIMSON_FOREST));
public static final BCLBiome WARPED_FOREST_BIOME = registerNetherBiome(getFromRegistry(Biomes.WARPED_FOREST));
public static final BCLBiome SOUL_SAND_VALLEY_BIOME = registerNetherBiome(getFromRegistry(Biomes.SOUL_SAND_VALLEY));
public static final BCLBiome BASALT_DELTAS_BIOME = registerNetherBiome(getFromRegistry(Biomes.BASALT_DELTAS));
public static final BCLBiome NETHER_WASTES_BIOME = registerNetherBiome(getFromRegistry(Biomes.NETHER_WASTES).value());
public static final BCLBiome CRIMSON_FOREST_BIOME = registerNetherBiome(getFromRegistry(Biomes.CRIMSON_FOREST).value());
public static final BCLBiome WARPED_FOREST_BIOME = registerNetherBiome(getFromRegistry(Biomes.WARPED_FOREST).value());
public static final BCLBiome SOUL_SAND_VALLEY_BIOME = registerNetherBiome(getFromRegistry(Biomes.SOUL_SAND_VALLEY).value());
public static final BCLBiome BASALT_DELTAS_BIOME = registerNetherBiome(getFromRegistry(Biomes.BASALT_DELTAS).value());
public static final BCLBiome THE_END = registerEndLandBiome(getFromRegistry(Biomes.THE_END));
public static final BCLBiome END_MIDLANDS = registerSubBiome(THE_END, getFromRegistry(Biomes.END_MIDLANDS), 0.5F);
public static final BCLBiome END_HIGHLANDS = registerSubBiome(THE_END, getFromRegistry(Biomes.END_HIGHLANDS), 0.5F);
public static final BCLBiome END_MIDLANDS = registerSubBiome(THE_END, getFromRegistry(Biomes.END_MIDLANDS).value(), 0.5F);
public static final BCLBiome END_HIGHLANDS = registerSubBiome(THE_END, getFromRegistry(Biomes.END_HIGHLANDS).value(), 0.5F);
public static final BCLBiome END_BARRENS = registerEndVoidBiome(getFromRegistry(new ResourceLocation("end_barrens")));
public static final BCLBiome SMALL_END_ISLANDS = registerEndVoidBiome(getFromRegistry(new ResourceLocation("small_end_islands")));
private static void initFeatureOrder() {
if (!FEATURE_ORDER.isEmpty()) {
return;
@ -137,8 +116,7 @@ public class BiomeAPI {
.map(Entry::getValue)
.map(biome -> (BiomeGenerationSettingsAccessor) biome.getGenerationSettings())
.map(BiomeGenerationSettingsAccessor::bclib_getFeatures)
.forEach(stepFeatureSuppliers -> stepFeatureSuppliers.forEach(step -> step.forEach(featureSupplier -> {
PlacedFeature feature = featureSupplier.get();
.forEach(stepFeatureSuppliers -> stepFeatureSuppliers.forEach(step -> step.forEach(feature -> {
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
})));
}
@ -161,23 +139,23 @@ public class BiomeAPI {
* called from {@link ru.bclib.mixin.client.MinecraftMixin}
*/
public static void prepareNewLevel(){
STRUCTURE_STARTS.clear();
MODIFIED_SURFACE_PROVIDERS.forEach(p->p.bclib_clearBiomeSources());
MODIFIED_SURFACE_PROVIDERS.clear();
}
/**
* Register {@link BCLBiome} instance and its {@link Biome} if necessary.
* @param biome {@link BCLBiome}
* @param bclbiome {@link BCLBiome}
* @return {@link BCLBiome}
*/
public static BCLBiome registerBiome(BCLBiome biome) {
if (BuiltinRegistries.BIOME.get(biome.getID()) == null) {
Registry.register(BuiltinRegistries.BIOME, biome.getID(), biome.getBiome());
public static BCLBiome registerBiome(BCLBiome bclbiome) {
if (BuiltinRegistries.BIOME.get(bclbiome.getID()) == null) {
final Biome biome = bclbiome.getBiome();
ResourceLocation loc = bclbiome.getID();
Registry.register(BuiltinRegistries.BIOME, loc, biome);
}
ID_MAP.put(biome.getID(), biome);
return biome;
ID_MAP.put(bclbiome.getID(), bclbiome);
return bclbiome;
}
public static BCLBiome registerSubBiome(BCLBiome parent, BCLBiome subBiome) {
@ -212,7 +190,7 @@ public class BiomeAPI {
MHelper.randRange(-1.5F, 1.5F, random),
random.nextFloat()
);
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow();
ResourceKey<Biome> key = BiomeAPI.getBiomeKeyOrThrow(biome.getBiomeHolder());
NetherBiomeData.addNetherBiome(key, parameters);
return biome;
}
@ -242,7 +220,7 @@ public class BiomeAPI {
END_LAND_BIOME_PICKER.addBiome(biome);
float weight = biome.getGenChance();
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow();
ResourceKey<Biome> key = BiomeAPI.getBiomeKey(biome.getBiome());
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_HIGHLANDS, key, weight);
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_MIDLANDS, key, weight);
return biome;
@ -254,8 +232,8 @@ public class BiomeAPI {
* @param biome {@link BCLBiome}
* @return {@link BCLBiome}
*/
public static BCLBiome registerEndLandBiome(Biome biome) {
BCLBiome bclBiome = new BCLBiome(biome, null);
public static BCLBiome registerEndLandBiome(Holder<Biome> biome) {
BCLBiome bclBiome = new BCLBiome(biome.value(), null);
END_LAND_BIOME_PICKER.addBiome(bclBiome);
registerBiome(bclBiome);
@ -269,8 +247,8 @@ public class BiomeAPI {
* @param genChance float generation chance.
* @return {@link BCLBiome}
*/
public static BCLBiome registerEndLandBiome(Biome biome, float genChance) {
BCLBiome bclBiome = new BCLBiome(biome, VanillaBiomeSettings.createVanilla().setGenChance(genChance).build());
public static BCLBiome registerEndLandBiome(Holder<Biome> biome, float genChance) {
BCLBiome bclBiome = new BCLBiome(biome.value(), VanillaBiomeSettings.createVanilla().setGenChance(genChance).build());
END_LAND_BIOME_PICKER.addBiome(bclBiome);
registerBiome(bclBiome);
@ -288,7 +266,7 @@ public class BiomeAPI {
END_VOID_BIOME_PICKER.addBiome(biome);
float weight = biome.getGenChance();
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow();
ResourceKey<Biome> key = BiomeAPI.getBiomeKeyOrThrow(biome.getBiomeHolder());
TheEndBiomeData.addEndBiomeReplacement(Biomes.SMALL_END_ISLANDS, key, weight);
return biome;
}
@ -299,8 +277,8 @@ public class BiomeAPI {
* @param biome {@link BCLBiome}
* @return {@link BCLBiome}
*/
public static BCLBiome registerEndVoidBiome(Biome biome) {
BCLBiome bclBiome = new BCLBiome(biome, null);
public static BCLBiome registerEndVoidBiome(Holder<Biome> biome) {
BCLBiome bclBiome = new BCLBiome(biome.value(), null);
END_VOID_BIOME_PICKER.addBiome(bclBiome);
registerBiome(bclBiome);
@ -314,8 +292,8 @@ public class BiomeAPI {
* @param genChance float generation chance.
* @return {@link BCLBiome}
*/
public static BCLBiome registerEndVoidBiome(Biome biome, float genChance) {
BCLBiome bclBiome = new BCLBiome(biome, VanillaBiomeSettings.createVanilla().setGenChance(genChance).build());
public static BCLBiome registerEndVoidBiome(Holder<Biome> biome, float genChance) {
BCLBiome bclBiome = new BCLBiome(biome.value(), VanillaBiomeSettings.createVanilla().setGenChance(genChance).build());
END_VOID_BIOME_PICKER.addBiome(bclBiome);
registerBiome(bclBiome);
@ -324,14 +302,14 @@ public class BiomeAPI {
/**
* Get {@link BCLBiome} from {@link Biome} instance on server. Used to convert world biomes to BCLBiomes.
* @param biome - {@link Biome} from world.
* @param biome - {@link Holder<Biome>} from world.
* @return {@link BCLBiome} or {@code BiomeAPI.EMPTY_BIOME}.
*/
public static BCLBiome getFromBiome(Biome biome) {
public static BCLBiome getFromBiome(Holder<Biome> biome) {
if (biomeRegistry == null) {
return EMPTY_BIOME;
}
return ID_MAP.getOrDefault(biomeRegistry.getKey(biome), EMPTY_BIOME);
return ID_MAP.getOrDefault(biome.unwrapKey().orElseThrow().location(), EMPTY_BIOME);
}
/**
@ -375,6 +353,27 @@ public class BiomeAPI {
}
return id == null ? EMPTY_BIOME.getID() : id;
}
/**
* Get biome {@link ResourceLocation} from given {@link Biome}.
* @param biome - {@link Holder<Biome>} from server world.
* @return biome {@link ResourceLocation}.
*/
public static ResourceLocation getBiomeID(Holder<Biome> biome) {
var oKey = biome.unwrapKey();
if (oKey.isPresent()){
return oKey.get().location();
}
return null;
}
public static ResourceKey getBiomeKey(Holder<Biome> biome) {
return biome.unwrapKey().orElse(null);
}
public static ResourceKey getBiomeKeyOrThrow(Holder<Biome> biome) {
return biome.unwrapKey().orElseThrow();
}
/**
* Get {@link BCLBiome} from given {@link ResourceLocation}.
@ -393,6 +392,15 @@ public class BiomeAPI {
public static BCLBiome getBiome(Biome biome) {
return getBiome(BiomeAPI.getBiomeID(biome));
}
/**
* Get {@link BCLBiome} from given {@link Biome}.
* @param biome - biome {@link Biome}.
* @return {@link BCLBiome} or {@code BiomeAPI.EMPTY_BIOME}.
*/
public static BCLBiome getBiome(Holder<Biome> biome) {
return getBiome(BiomeAPI.getBiomeID(biome));
}
/**
* Check if biome with {@link ResourceLocation} exists in API registry.
@ -409,31 +417,31 @@ public class BiomeAPI {
public static void loadFabricAPIBiomes() {
FabricBiomesData.NETHER_BIOMES.forEach((key) -> {
if (!hasBiome(key.location())) {
registerNetherBiome(BuiltinRegistries.BIOME.get(key.location()));
registerNetherBiome(BuiltinRegistries.BIOME.get(key));
}
});
FabricBiomesData.END_LAND_BIOMES.forEach((key, weight) -> {
if (!hasBiome(key.location())) {
registerEndLandBiome(BuiltinRegistries.BIOME.get(key.location()), weight);
registerEndLandBiome(BuiltinRegistries.BIOME.getHolder(key).orElseThrow(), weight);
}
});
FabricBiomesData.END_VOID_BIOMES.forEach((key, weight) -> {
if (!hasBiome(key.location())) {
registerEndVoidBiome(BuiltinRegistries.BIOME.get(key.location()), weight);
registerEndVoidBiome(BuiltinRegistries.BIOME.getOrCreateHolder(key), weight);
}
});
}
@Nullable
public static Biome getFromRegistry(ResourceLocation key) {
return BuiltinRegistries.BIOME.get(key);
public static Holder<Biome> getFromRegistry(ResourceLocation key) {
return BuiltinRegistries.BIOME.getHolder(ResourceKey.create(Registry.BIOME_REGISTRY, key)).orElseThrow();
}
@Nullable
public static Biome getFromRegistry(ResourceKey<Biome> key) {
return BuiltinRegistries.BIOME.get(key);
public static Holder<Biome> getFromRegistry(ResourceKey<Biome> key) {
return BuiltinRegistries.BIOME.getOrCreateHolder(key);
}
public static boolean isDatapackBiome(ResourceLocation biomeID) {
@ -457,8 +465,8 @@ 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, BiConsumer<ResourceLocation, Biome> modification) {
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID, k -> Lists.newArrayList());
public static void registerBiomeModification(ResourceKey dimensionID, BiConsumer<ResourceLocation, Holder<Biome>> modification) {
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID, k -> Lists.newArrayList());
modifications.add(modification);
}
@ -466,7 +474,7 @@ public class BiomeAPI {
* Registers new biome modification for the Overworld. Will work both for mod and datapack biomes.
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
*/
public static void registerOverworldBiomeModification(BiConsumer<ResourceLocation, Biome> modification) {
public static void registerOverworldBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
registerBiomeModification(Level.OVERWORLD, modification);
}
@ -474,7 +482,7 @@ public class BiomeAPI {
* 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 registerNetherBiomeModification(BiConsumer<ResourceLocation, Biome> modification) {
public static void registerNetherBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
registerBiomeModification(Level.NETHER, modification);
}
@ -482,7 +490,7 @@ public class BiomeAPI {
* 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 registerEndBiomeModification(BiConsumer<ResourceLocation, Biome> modification) {
public static void registerEndBiomeModification(BiConsumer<ResourceLocation, Holder<Biome>> modification) {
registerBiomeModification(Level.END, modification);
}
@ -491,40 +499,54 @@ public class BiomeAPI {
* @param level
*/
public static void applyModifications(ServerLevel level) {
final BiomeSource source = level.getChunkSource().getGenerator().getBiomeSource();
final StructureSettings settings = level.getChunkSource().getGenerator().getSettings();
final Set<Biome> biomes = source.possibleBiomes();
NoiseGeneratorSettings noiseGeneratorSettings = null;
final ChunkGenerator chunkGenerator = level.getChunkSource().getGenerator();
final BiomeSource source = chunkGenerator.getBiomeSource();
final Set<Holder<Biome>> biomes = source.possibleBiomes();
NoiseGeneratorSettings generator = level
if (chunkGenerator instanceof NoiseGeneratorSettingsProvider gen)
noiseGeneratorSettings = gen.bclib_getNoiseGeneratorSettings();
/*final Registry<StructureSet> structureSetRegistry;
if (chunkGenerator instanceof ChunkGeneratorAccessor acc) {
structureSetRegistry = acc.bclib_getStructureSetsRegistry();
} else {
structureSetRegistry = null;
}
noiseGeneratorSettings = level
.getServer()
.getWorldData()
.worldGenSettings()
.dimensions()
.stream()
.map(dim->dim.generator())
.filter(gen->(gen instanceof NoiseGeneratorSettingsProvider) && gen.getSettings()==settings)
.filter(gen-> structureSetRegistry!=null && (gen instanceof NoiseGeneratorSettingsProvider) && (gen instanceof ChunkGeneratorAccessor) && ((ChunkGeneratorAccessor)gen).bclib_getStructureSetsRegistry()==structureSetRegistry)
.map(gen->((NoiseGeneratorSettingsProvider)gen).bclib_getNoiseGeneratorSettings())
.findFirst()
.orElse(null);
.orElse(null);*/
// Datapacks (like Amplified Nether)will change the GeneratorSettings upon load, so we will
// only use the default Setting for Nether/End if we were unable to find a settings object
if (generator==null){
if (noiseGeneratorSettings==null){
if (level.dimension() == Level.NETHER) {
generator = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.NETHER);
noiseGeneratorSettings = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.NETHER);
} else if (level.dimension() == Level.END) {
generator = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.END);
noiseGeneratorSettings = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.END);
}
}
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.get(level.dimension());
for (Biome biome : biomes) {
applyModificationsAndUpdateFeatures(modifications, biome);
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(level.dimension());
for (Holder<Biome> biomeHolder : biomes) {
if (biomeHolder.isBound()) {
applyModificationsAndUpdateFeatures(modifications, biomeHolder);
}
}
if (generator != null) {
final SurfaceRuleProvider provider = SurfaceRuleProvider.class.cast(generator);
if (noiseGeneratorSettings != null) {
final SurfaceRuleProvider provider = SurfaceRuleProvider.class.cast(noiseGeneratorSettings);
// Multiple Biomes can use the same generator. So we need to keep track of all Biomes that are
// Provided by all the BiomeSources that use the same generator.
// This happens for example when using the MiningDimensions, which reuses the generator for the
@ -535,20 +557,10 @@ public class BiomeAPI {
BCLib.LOGGER.warning("No generator for " + source);
}
if (settings!=null){
final StructureSettingsAccessor settingsAccessor = (StructureSettingsAccessor)settings;
final Set<ResourceLocation> biomeIDs = biomes.stream().map(BiomeAPI::getBiomeID).collect(Collectors.toSet());
for (Entry<StructureID, BiConsumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>, Map<StructureFeature<?>, StructureFeatureConfiguration>>> e : STRUCTURE_STARTS.entrySet()) {
if (biomeIDs.contains(e.getKey().biomeID)) {
applyStructureStarts(settingsAccessor, e.getValue());
}
}
}
((BiomeSourceAccessor) source).bclRebuildFeatures();
}
private static void applyModificationsAndUpdateFeatures(List<BiConsumer<ResourceLocation, Biome>> modifications, Biome biome) {
private static void applyModificationsAndUpdateFeatures(List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications, Holder<Biome> biome) {
ResourceLocation biomeID = getBiomeID(biome);
if (modifications!=null) {
modifications.forEach(consumer -> {
@ -556,11 +568,6 @@ public class BiomeAPI {
});
}
final BCLBiome bclBiome = BiomeAPI.getBiome(biome);
if (bclBiome != null) {
addStepFeaturesToBiome(biome, bclBiome.getFeatures());
}
sortBiomeFeatures(biome);
}
@ -568,20 +575,20 @@ public class BiomeAPI {
* Create a unique sort order for all Features of the Biome
* @param biome The {@link Biome} to sort the features for
*/
public static void sortBiomeFeatures(Biome biome) {
BiomeGenerationSettings settings = biome.getGenerationSettings();
public static void sortBiomeFeatures(Holder<Biome> biome) {
BiomeGenerationSettings settings = biome.value().getGenerationSettings();
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) settings;
List<List<Supplier<PlacedFeature>>> featureList = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
List<HolderSet<PlacedFeature>> featureList = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
final int size = featureList.size();
for (int i = 0; i < size; i++) {
List<Supplier<PlacedFeature>> features = CollectionsUtil.getMutable(featureList.get(i));
List<Holder<PlacedFeature>> features = getFeaturesListCopy(featureList, i);
sortFeatures(features);
featureList.set(i, features);
featureList.set(i, HolderSet.direct(features));
}
accessor.bclib_setFeatures(featureList);
}
private static List<SurfaceRules.RuleSource> getRuleSourcesForBiomes(Set<Biome> biomes) {
private static List<SurfaceRules.RuleSource> getRuleSourcesForBiomes(Set<Holder<Biome>> biomes) {
Set<ResourceLocation> biomeIDs = biomes
.stream()
.map(biome -> getBiomeID(biome))
@ -600,7 +607,7 @@ public class BiomeAPI {
* @return A list of {@link RuleSource}-Objects that are needed to create those Biomes
*/
public static List<SurfaceRules.RuleSource> getRuleSources(Set<BiomeSource> sources) {
final Set<Biome> biomes = new HashSet<>();
final Set<Holder<Biome>> biomes = new HashSet<>();
for (BiomeSource s : sources) {
biomes.addAll(s.possibleBiomes());
}
@ -624,7 +631,7 @@ public class BiomeAPI {
* @param feature {@link ConfiguredFeature} to add.
*
*/
public static void addBiomeFeature(Biome biome, BCLFeature feature) {
public static void addBiomeFeature(Holder<Biome> biome, BCLFeature feature) {
addBiomeFeature(biome, feature.getDecoration(), feature.getPlacedFeature());
}
@ -634,7 +641,7 @@ public class BiomeAPI {
* @param step a {@link Decoration} step for the feature.
* @param featureList {@link ConfiguredFeature} to add.
*/
public static void addBiomeFeature(Biome biome, Decoration step, PlacedFeature... featureList) {
public static void addBiomeFeature(Holder<Biome> biome, Decoration step, Holder<PlacedFeature>... featureList) {
addBiomeFeature(biome, step, List.of(featureList));
}
@ -642,107 +649,25 @@ public class BiomeAPI {
* Adds new features to existing biome.
* @param biome {@link Biome} to add features in.
* @param step a {@link Decoration} step for the feature.
* @param featureList List of {@link ConfiguredFeature} to add.
* @param additionalFeatures List of {@link ConfiguredFeature} to add.
*/
private static void addBiomeFeature(Biome biome, Decoration step, List<PlacedFeature> featureList) {
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
List<List<Supplier<PlacedFeature>>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
Set<PlacedFeature> set = CollectionsUtil.getMutable(accessor.bclib_getFeatureSet());
List<Supplier<PlacedFeature>> features = getFeaturesList(allFeatures, step);
for (var feature : featureList) {
features.add(() -> feature);
set.add(feature);
}
accessor.bclib_setFeatures(allFeatures);
accessor.bclib_setFeatureSet(set);
}
/**
* For internal use only!
*
* Adds new features to existing biome. Called from {@link #applyModificationsAndUpdateFeatures(List, Biome)} when the Biome is
* present in any {@link BiomeSource}
* @param biome {@link Biome} to add features in.
* @param featureMap Map of {@link ConfiguredFeature} to add.
*/
private static void addStepFeaturesToBiome(Biome biome, Map<Decoration, List<Supplier<PlacedFeature>>> featureMap) {
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
List<List<Supplier<PlacedFeature>>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
Set<PlacedFeature> set = CollectionsUtil.getMutable(accessor.bclib_getFeatureSet());
for (Decoration step: featureMap.keySet()) {
List<Supplier<PlacedFeature>> features = getFeaturesList(allFeatures, step);
List<Supplier<PlacedFeature>> featureList = featureMap.get(step);
for (Supplier<PlacedFeature> feature : featureList) {
private static void addBiomeFeature(Holder<Biome> biome, Decoration step, List<Holder<PlacedFeature>> additionalFeatures) {
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.value().getGenerationSettings();
List<HolderSet<PlacedFeature>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
List<Holder<PlacedFeature>> features = getFeaturesListCopy(allFeatures, step);
for (var feature : additionalFeatures) {
if (!features.contains(feature))
features.add(feature);
set.add(feature.get());
}
}
allFeatures.set(step.ordinal(), HolderSet.direct(features));
final Supplier<List<ConfiguredFeature<?, ?>>> flowerFeatures = Suppliers.memoize(() -> allFeatures.stream().flatMap(HolderSet::stream).map(Holder::value).flatMap(PlacedFeature::getFeatures).filter(configuredFeature -> configuredFeature.feature() == Feature.FLOWER).collect(ImmutableList.toImmutableList()));
final Supplier<Set<PlacedFeature>> featureSet = Suppliers.memoize(() -> allFeatures.stream().flatMap(HolderSet::stream).map(Holder::value).collect(Collectors.toSet()));
accessor.bclib_setFeatures(allFeatures);
accessor.bclib_setFeatureSet(set);
}
/**
* Adds new structure feature to existing biome.
* @param biomeKey {@link ResourceKey} for the {@link Biome} to add structure feature in.
* @param structure {@link ConfiguredStructureFeature} to add.
*/
public static void addBiomeStructure(ResourceKey biomeKey, ConfiguredStructureFeature structure) {
if (biomeKey == null){
BCLib.LOGGER.error("null is not a valid biomeKey for " + structure);
return;
}
changeStructureStarts(biomeKey.location(), structure, (structureMap, configMap) -> {
Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>> configuredMap = structureMap.computeIfAbsent(structure.feature, k -> HashMultimap.create());
configuredMap.put(structure, biomeKey);
StructureFeatureConfiguration config = FabricStructureImpl.STRUCTURE_TO_CONFIG_MAP.get(structure.feature);
if (config != null){
configMap.put(structure.feature, config);
}
});
}
/**
* Add an existing StructureFeature to a Biome
* @param biome The {@link Biome} you want to add teh feature to
* @param structure The {@link ConfiguredStructureFeature} to add
*/
public static void addBiomeStructure(Biome biome, ConfiguredStructureFeature structure) {
changeStructureStarts(BiomeAPI.getBiomeID(biome), structure, (structureMap, configMap) -> {
Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>> configuredMap = structureMap.computeIfAbsent(structure.feature, k -> HashMultimap.create());
var key = getBiomeKey(biome);
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);
} else {
BCLib.LOGGER.warning("Unable to find Biome " + getBiomeID(biome));
}
});
}
/**
* Adds new structure feature to existing biome.
* @param biomeKey {@link ResourceKey} for the {@link Biome} to add structure feature in.
* @param structure {@link BCLStructureFeature} to add.
*/
public static void addBiomeStructure(ResourceKey biomeKey, BCLStructureFeature structure) {
addBiomeStructure(biomeKey, structure.getFeatureConfigured());
}
/**
* Adds new structure features to existing biome.
* @param biomeKey {@link ResourceKey} for the {@link Biome} to add structure features in.
* @param structures array of {@link BCLStructureFeature} to add.
*/
public static void addBiomeStructures(ResourceKey biomeKey, BCLStructureFeature... structures) {
for (BCLStructureFeature structure: structures) {
addBiomeStructure(biomeKey, structure.getFeatureConfigured());
}
accessor.bclib_setFeatureSet(featureSet);
accessor.bclib_setFlowerFeatures(flowerFeatures);
}
/**
@ -751,13 +676,20 @@ public class BiomeAPI {
* @param carver {@link ConfiguredWorldCarver} to add.
* @param stage {@link Carving} stage.
*/
public static void addBiomeCarver(Biome biome, ConfiguredWorldCarver carver, Carving stage) {
public static void addBiomeCarver(Biome biome, Holder<? extends ConfiguredWorldCarver<?>> carver, Carving stage) {
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
Map<Carving, List<Supplier<ConfiguredWorldCarver<?>>>> carvers = CollectionsUtil.getMutable(accessor.bclib_getCarvers());
List<Supplier<ConfiguredWorldCarver<?>>> carverList = CollectionsUtil.getMutable(carvers.getOrDefault(stage, new ArrayList<>()));
carvers.put(stage, carverList);
carverList.add(() -> carver);
accessor.bclib_setCarvers(carvers);
Map<Carving, HolderSet<ConfiguredWorldCarver<?>>> carverMap = CollectionsUtil.getMutable(accessor.bclib_getCarvers());
HolderSet<ConfiguredWorldCarver<?>> carvers = carverMap.get(stage);
List<Holder<ConfiguredWorldCarver<?>>> carverList;
if (carvers==null) {
carverList = Lists.newArrayList();
} else {
carverList = carvers.stream().toList();
}
carverList.add((Holder<ConfiguredWorldCarver<?>>)carver);
carverMap.put(stage, HolderSet.direct(carverList));
accessor.bclib_setCarvers(carverMap);
}
/**
@ -788,7 +720,7 @@ public class BiomeAPI {
* @param minGroupCount minimum mobs in group.
* @param maxGroupCount maximum mobs in group.
*/
public static <M extends Mob> void addBiomeMobSpawn(Biome biome, BCLEntityWrapper<M> entityType, int weight, int minGroupCount, int maxGroupCount) {
public static <M extends Mob> void addBiomeMobSpawn(Holder<Biome> biome, BCLEntityWrapper<M> entityType, int weight, int minGroupCount, int maxGroupCount) {
if (entityType.canSpawn()){
addBiomeMobSpawn(biome, entityType.type(), weight, minGroupCount, maxGroupCount);
}
@ -802,9 +734,9 @@ public class BiomeAPI {
* @param minGroupCount minimum mobs in group.
* @param maxGroupCount maximum mobs in group.
*/
public static <M extends Mob> void addBiomeMobSpawn(Biome biome, EntityType<M> entityType, int weight, int minGroupCount, int maxGroupCount) {
public static <M extends Mob> void addBiomeMobSpawn(Holder<Biome> biome, EntityType<M> entityType, int weight, int minGroupCount, int maxGroupCount) {
final MobCategory category = entityType.getCategory();
MobSpawnSettingsAccessor accessor = (MobSpawnSettingsAccessor) biome.getMobSettings();
MobSpawnSettingsAccessor accessor = (MobSpawnSettingsAccessor) biome.value().getMobSettings();
Map<MobCategory, WeightedRandomList<SpawnerData>> spawners = CollectionsUtil.getMutable(accessor.bcl_getSpawners());
List<SpawnerData> mobs = spawners.containsKey(category) ? CollectionsUtil.getMutable(spawners.get(category).unwrap()) : Lists.newArrayList();
mobs.add(new SpawnerData(entityType, weight, minGroupCount, maxGroupCount));
@ -815,11 +747,11 @@ public class BiomeAPI {
/**
* Get biome surface block. Can be used to get terrain material for features or other things.
* @param pos {@link BlockPos} position to get block.
* @param biome {@link Biome} to get block from.
* @param biome {@link Holder<Biome>} to get block from.
* @param level {@link ServerLevel} current server level.
* @return {@link BlockState} with the biome surface or AIR if it fails.
*/
public static BlockState getBiomeSurfaceBlock(BlockPos pos, Biome biome, ServerLevel level) {
public static BlockState getBiomeSurfaceBlock(BlockPos pos, Holder<Biome> biome, ServerLevel level) {
ChunkGenerator generator = level.getChunkSource().getGenerator();
if (generator instanceof NoiseBasedChunkGenerator) {
SurfaceProvider provider = SurfaceProvider.class.cast(generator);
@ -832,6 +764,10 @@ public class BiomeAPI {
return findTopMaterial(getBiome(world.getBiome(pos)));
}
public static Optional<BlockState> findTopMaterial(Holder<Biome> biome){
return findTopMaterial(getBiome(biome.value()));
}
public static Optional<BlockState> findTopMaterial(Biome biome){
return findTopMaterial(getBiome(biome));
}
@ -847,6 +783,10 @@ public class BiomeAPI {
return findUnderMaterial(getBiome(world.getBiome(pos)));
}
public static Optional<BlockState> findUnderMaterial(Holder<Biome> biome){
return findUnderMaterial(getBiome(biome.value()));
}
public static Optional<BlockState> findUnderMaterial(Biome biome){
return findUnderMaterial(getBiome(biome));
}
@ -862,11 +802,11 @@ public class BiomeAPI {
* Set biome in chunk at specified position.
* @param chunk {@link ChunkAccess} chunk to set biome in.
* @param pos {@link BlockPos} biome position.
* @param biome {@link Biome} instance. Should be biome from world.
* @param biome {@link Holder<Biome>} instance. Should be biome from world.
*/
public static void setBiome(ChunkAccess chunk, BlockPos pos, Biome biome) {
public static void setBiome(ChunkAccess chunk, BlockPos pos, Holder<Biome> biome) {
int sectionY = (pos.getY() - chunk.getMinBuildHeight()) >> 4;
PalettedContainer<Biome> biomes = chunk.getSection(sectionY).getBiomes();
PalettedContainer<Holder<Biome>> biomes = chunk.getSection(sectionY).getBiomes();
biomes.set((pos.getX() & 15) >> 2, (pos.getY() & 15) >> 2, (pos.getZ() & 15) >> 2, biome);
}
@ -874,9 +814,9 @@ public class BiomeAPI {
* Set biome in world at specified position.
* @param level {@link LevelAccessor} world to set biome in.
* @param pos {@link BlockPos} biome position.
* @param biome {@link Biome} instance. Should be biome from world.
* @param biome {@link Holder<Biome>} instance. Should be biome from world.
*/
public static void setBiome(LevelAccessor level, BlockPos pos, Biome biome) {
public static void setBiome(LevelAccessor level, BlockPos pos, Holder<Biome> biome) {
ChunkAccess chunk = level.getChunk(pos);
setBiome(chunk, pos, biome);
}
@ -909,42 +849,24 @@ public class BiomeAPI {
}
}
private static void changeStructureStarts(ResourceLocation biomeID, ConfiguredStructureFeature structure, BiConsumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>, Map<StructureFeature<?>, StructureFeatureConfiguration>> modifier) {
STRUCTURE_STARTS.put(new StructureID(biomeID, structure), modifier);
}
private static void applyStructureStarts(StructureSettingsAccessor access, BiConsumer<Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>>, Map<StructureFeature<?>, StructureFeatureConfiguration>> modifier) {
Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> structureMap;
Map<StructureFeature<?>, StructureFeatureConfiguration> configMap;
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<Holder<PlacedFeature>> features) {
initFeatureOrder();
Set<PlacedFeature> featuresWithoutDuplicates = Sets.newHashSet();
features.forEach(provider -> featuresWithoutDuplicates.add(provider.get()));
Set<Holder<PlacedFeature>> featuresWithoutDuplicates = Sets.newHashSet();
features.forEach(holder -> featuresWithoutDuplicates.add(holder));
if (featuresWithoutDuplicates.size() != features.size()) {
features.clear();
featuresWithoutDuplicates.forEach(feature -> features.add(() -> feature));
featuresWithoutDuplicates.forEach(feature -> features.add(feature));
}
features.forEach(provider -> {
PlacedFeature feature = provider.get();
features.forEach(feature -> {
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
});
features.sort((f1, f2) -> {
int v1 = FEATURE_ORDER.getOrDefault(f1.get(), 70000);
int v2 = FEATURE_ORDER.getOrDefault(f2.get(), 70000);
int v1 = FEATURE_ORDER.getOrDefault(f1, 70000);
int v2 = FEATURE_ORDER.getOrDefault(f2, 70000);
return Integer.compare(v1, v2);
});
}
@ -966,44 +888,15 @@ public class BiomeAPI {
lists.set(index, list);
return list;
}
private static List<Holder<PlacedFeature>> getFeaturesListCopy(List<HolderSet<PlacedFeature>> features, Decoration step) {
return getFeaturesListCopy(features, step.ordinal());
}
private static List<Supplier<PlacedFeature>> getFeaturesList(List<List<Supplier<PlacedFeature>>> features, Decoration step) {
int index = step.ordinal();
private static List<Holder<PlacedFeature>> getFeaturesListCopy(List<HolderSet<PlacedFeature>> features, int index) {
while (features.size() <= index) {
features.add(Lists.newArrayList());
features.add(HolderSet.direct(Lists.newArrayList()));
}
List<Supplier<PlacedFeature>> mutable = CollectionsUtil.getMutable(features.get(index));
features.set(index, mutable);
return mutable;
}
//inspired by net.fabricmc.fabric.impl.biome.modification.BiomeStructureStartsImpl
private static Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> getMutableConfiguredStructures(StructureSettingsAccessor access) {
ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> configuredStructures = access.bcl_getConfiguredStructures();
Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> result = new HashMap<>(configuredStructures.size());
for (Map.Entry<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> entry : configuredStructures.entrySet()) {
result.put(entry.getKey(), HashMultimap.create(entry.getValue()));
}
return result;
}
//inspired by net.fabricmc.fabric.impl.biome.modification.BiomeStructureStartsImpl
private static void setMutableConfiguredStructures(StructureSettingsAccessor access, Map<StructureFeature<?>, Multimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> structureStarts) {
access.bcl_setConfiguredStructures(
structureStarts
.entrySet()
.stream()
.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);
return features.get(index).stream().collect(Collectors.toList());
}
}

View file

@ -147,24 +147,8 @@ public abstract class DataHandler extends BaseDataHandler {
@Environment(EnvType.CLIENT)
abstract protected void serializeDataOnClient(FriendlyByteBuf buf);
@Deprecated(forRemoval = true)
protected void deserializeIncomingDataOnServer(FriendlyByteBuf buf, PacketSender responseSender){ }
//TODO: should be abstract once deserializeIncomingDataOnServer(FriendlyByteBuf buf, PacketSender responseSender) was removed
protected void deserializeIncomingDataOnServer(FriendlyByteBuf buf, Player player, PacketSender responseSender) {
deserializeIncomingDataOnServer(buf, responseSender);
}
@Deprecated(forRemoval = true)
protected void runOnServerGameThread(MinecraftServer server){ }
//TODO: should be abstract once runOnServerGameThread(MinecraftServer server) was removed
protected void runOnServerGameThread(MinecraftServer server, Player player){
runOnServerGameThread(server);
}
protected abstract void deserializeIncomingDataOnServer(FriendlyByteBuf buf, Player player, PacketSender responseSender);
protected abstract void runOnServerGameThread(MinecraftServer server, Player player);
@Environment(EnvType.CLIENT)
@Override

View file

@ -127,7 +127,6 @@ public class SendFiles extends DataHandler.FromServer {
if ( Configs.CLIENT_CONFIG.isAcceptingConfigs() || Configs.CLIENT_CONFIG.isAcceptingFiles() || Configs.CLIENT_CONFIG.isAcceptingMods()) {
BCLib.LOGGER.info("Writing Files:");
//TODO: Reject files that were not in the last RequestFiles.
for (Pair<AutoFileSyncEntry, byte[]> entry : receivedFiles) {
final AutoFileSyncEntry e = entry.first;
final byte[] data = entry.second;

View file

@ -4,6 +4,7 @@ import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.BiomeFilter;
@ -18,12 +19,12 @@ import ru.bclib.world.features.BCLFeature;
import java.util.ArrayList;
import java.util.List;
public class BCLFeatureBuilder {
public class BCLFeatureBuilder <FC extends FeatureConfiguration, F extends Feature<FC>>{
private static final BCLFeatureBuilder INSTANCE = new BCLFeatureBuilder();
private List<PlacementModifier> modifications = new ArrayList<>(16);
private ResourceLocation featureID;
private Decoration decoration;
private Feature<?> feature;
private F feature;
private BCLFeatureBuilder() {}
@ -60,6 +61,11 @@ public class BCLFeatureBuilder {
modifications.add(modifier);
return this;
}
public BCLFeatureBuilder modifier(List<PlacementModifier> modifiers) {
modifications.addAll(modifiers);
return this;
}
/**
* Generate feature in certain iterations (per chunk).
@ -134,10 +140,9 @@ public class BCLFeatureBuilder {
* @param configuration any {@link FeatureConfiguration} for provided {@link Feature}.
* @return created {@link BCLFeature} instance.
*/
public <FC extends FeatureConfiguration> BCLFeature build(FC configuration) {
public BCLFeature build(FC configuration) {
PlacementModifier [] modifiers = modifications.toArray(new PlacementModifier [modifications.size()]);
PlacedFeature configured = ((Feature<FC>) feature).configured(configuration).placed(modifiers);
return new BCLFeature(featureID, feature, decoration, configured);
return new BCLFeature(featureID, feature, decoration, configuration, modifiers);
}
/**
@ -146,6 +151,6 @@ public class BCLFeatureBuilder {
* @return created {@link BCLFeature} instance.
*/
public BCLFeature build() {
return build(FeatureConfiguration.NONE);
return build((FC)FeatureConfiguration.NONE);
}
}

View file

@ -75,7 +75,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder subsurface(BlockState state, int depth) {
entryInstance = getFromCache("subsurface_" + depth + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(depth, false, false, CaveSurface.FLOOR), rule);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(depth, false, CaveSurface.FLOOR), rule);
return new SurfaceRuleEntry(3, rule);
});
rules.add(entryInstance);
@ -117,7 +117,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder belowFloor(BlockState state, int height, NoiseCondition noise) {
entryInstance = getFromCache("below_floor_" + height + "_" + state.toString() + "_" + noise.getClass().getSimpleName(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height, false, false, CaveSurface.FLOOR), SurfaceRules.ifTrue(noise, rule));
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height, false, CaveSurface.FLOOR), SurfaceRules.ifTrue(noise, rule));
return new SurfaceRuleEntry(3, rule);
});
rules.add(entryInstance);
@ -133,7 +133,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder belowFloor(BlockState state, int height) {
entryInstance = getFromCache("below_floor_" + height + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height, false, false, CaveSurface.FLOOR), rule);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height, false, CaveSurface.FLOOR), rule);
return new SurfaceRuleEntry(3, rule);
});
rules.add(entryInstance);
@ -163,7 +163,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder aboveCeil(BlockState state, int height) {
entryInstance = getFromCache("above_ceil_" + height + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height, false, false, CaveSurface.CEILING), rule);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height, false, CaveSurface.CEILING), rule);
return new SurfaceRuleEntry(3, rule);
});
rules.add(entryInstance);
@ -179,7 +179,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder steep(BlockState state, int depth) {
entryInstance = getFromCache("steep_" + depth + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(depth, false, false, CaveSurface.FLOOR), rule);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(depth, false, CaveSurface.FLOOR), rule);
rule = SurfaceRules.ifTrue(SurfaceRules.steep(), rule);
int priority = depth < 1 ? 0 : 1;
return new SurfaceRuleEntry(priority, rule);

View file

@ -1,23 +1,26 @@
package ru.bclib.api.tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import ru.bclib.api.tag.TagAPI.TagNamed;
public class CommonBlockTags {
public static final TagNamed<Block> BARREL = TagAPI.makeCommonBlockTag("barrel");
public static final TagNamed<Block> BOOKSHELVES = TagAPI.makeCommonBlockTag("bookshelves");
public static final TagNamed<Block> CHEST = TagAPI.makeCommonBlockTag("chest");
public static final TagNamed<Block> END_STONES = TagAPI.makeCommonBlockTag("end_stones");
public static final TagNamed<Block> GEN_END_STONES = END_STONES;
public static final TagNamed<Block> IMMOBILE = TagAPI.makeCommonBlockTag("immobile");
public static final TagNamed<Block> LEAVES = TagAPI.makeCommonBlockTag("leaves");
public static final TagNamed<Block> NETHERRACK = TagAPI.makeCommonBlockTag("netherrack");
public static final TagNamed<Block> NETHER_MYCELIUM = TagAPI.makeCommonBlockTag("nether_mycelium");
public static final TagNamed<Block> NETHER_PORTAL_FRAME = TagAPI.makeCommonBlockTag("nether_pframe");
public static final TagNamed<Block> NETHER_STONES = TagAPI.makeCommonBlockTag("nether_stones");
public static final TagNamed<Block> SAPLINGS = TagAPI.makeCommonBlockTag("saplings");
public static final TagNamed<Block> SOUL_GROUND = TagAPI.makeCommonBlockTag("soul_ground");
public static final TagNamed<Block> WOODEN_BARREL = TagAPI.makeCommonBlockTag("wooden_barrels");
public static final TagNamed<Block> WOODEN_CHEST = TagAPI.makeCommonBlockTag("wooden_chests");
public static final TagNamed<Block> WORKBENCHES = TagAPI.makeCommonBlockTag("workbench");
public static final TagKey<Block> BARREL = TagAPI.makeCommonBlockTag("barrel");
public static final TagKey<Block> BOOKSHELVES = TagAPI.makeCommonBlockTag("bookshelves");
public static final TagKey<Block> CHEST = TagAPI.makeCommonBlockTag("chest");
public static final TagKey<Block> END_STONES = TagAPI.makeCommonBlockTag("end_stones");
public static final TagKey<Block> GEN_END_STONES = END_STONES;
public static final TagKey<Block> IMMOBILE = TagAPI.makeCommonBlockTag("immobile");
public static final TagKey<Block> LEAVES = TagAPI.makeCommonBlockTag("leaves");
public static final TagKey<Block> NETHERRACK = TagAPI.makeCommonBlockTag("netherrack");
public static final TagKey<Block> NETHER_MYCELIUM = TagAPI.makeCommonBlockTag("nether_mycelium");
public static final TagKey<Block> NETHER_PORTAL_FRAME = TagAPI.makeCommonBlockTag("nether_pframe");
public static final TagKey<Block> NETHER_STONES = TagAPI.makeCommonBlockTag("nether_stones");
public static final TagKey<Block> SAPLINGS = TagAPI.makeCommonBlockTag("saplings");
public static final TagKey<Block> SOUL_GROUND = TagAPI.makeCommonBlockTag("soul_ground");
public static final TagKey<Block> WOODEN_BARREL = TagAPI.makeCommonBlockTag("wooden_barrels");
public static final TagKey<Block> WOODEN_CHEST = TagAPI.makeCommonBlockTag("wooden_chests");
public static final TagKey<Block> WORKBENCHES = TagAPI.makeCommonBlockTag("workbench");
public static final TagKey<Block> MINABLE_WITH_HAMMER = TagAPI.makeCommonBlockTag("mineable/hammer");
}

View file

@ -1,19 +1,19 @@
package ru.bclib.api.tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import ru.bclib.api.tag.TagAPI.TagNamed;
public class CommonItemTags {
public final static TagNamed<Item> HAMMERS = TagAPI.makeCommonItemTag("hammers");
public static final TagNamed<Item> BARREL = TagAPI.makeCommonItemTag("barrel");
public static final TagNamed<Item> CHEST = TagAPI.makeCommonItemTag("chest");
public static final TagNamed<Item> SHEARS = TagAPI.makeCommonItemTag("shears");
public static final TagNamed<Item> FURNACES = TagAPI.makeCommonItemTag("furnaces");
public static final TagNamed<Item> IRON_INGOTS = TagAPI.makeCommonItemTag("iron_ingots");
public static final TagNamed<Item> LEAVES = TagAPI.makeCommonItemTag("leaves");
public static final TagNamed<Item> SAPLINGS = TagAPI.makeCommonItemTag("saplings");
public static final TagNamed<Item> SOUL_GROUND = TagAPI.makeCommonItemTag("soul_ground");
public static final TagNamed<Item> WOODEN_BARREL = TagAPI.makeCommonItemTag("wooden_barrels");
public static final TagNamed<Item> WOODEN_CHEST = TagAPI.makeCommonItemTag("wooden_chests");
public static final TagNamed<Item> WORKBENCHES = TagAPI.makeCommonItemTag("workbench");
public final static TagKey<Item> HAMMERS = TagAPI.makeCommonItemTag("hammers");
public static final TagKey<Item> BARREL = TagAPI.makeCommonItemTag("barrel");
public static final TagKey<Item> CHEST = TagAPI.makeCommonItemTag("chest");
public static final TagKey<Item> SHEARS = TagAPI.makeCommonItemTag("shears");
public static final TagKey<Item> FURNACES = TagAPI.makeCommonItemTag("furnaces");
public static final TagKey<Item> IRON_INGOTS = TagAPI.makeCommonItemTag("iron_ingots");
public static final TagKey<Item> LEAVES = TagAPI.makeCommonItemTag("leaves");
public static final TagKey<Item> SAPLINGS = TagAPI.makeCommonItemTag("saplings");
public static final TagKey<Item> SOUL_GROUND = TagAPI.makeCommonItemTag("soul_ground");
public static final TagKey<Item> WOODEN_BARREL = TagAPI.makeCommonItemTag("wooden_barrels");
public static final TagKey<Item> WOODEN_CHEST = TagAPI.makeCommonItemTag("wooden_chests");
public static final TagKey<Item> WORKBENCHES = TagAPI.makeCommonItemTag("workbench");
}

View file

@ -10,4 +10,5 @@ public class NamedMineableTags {
public static final TagLocation<Block> SHEARS = new TagLocation<>("fabric", "mineable/shears");
public static final TagLocation<Block> SHOVEL = new TagLocation<>("mineable/shovel");
public static final TagLocation<Block> SWORD = new TagLocation<>("fabric", "mineable/sword");
public static final TagLocation<Block> HAMMER = new TagLocation<>("c", "mineable/hammer");
}

View file

@ -2,112 +2,178 @@ package ru.bclib.api.tag;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.fabricmc.fabric.api.tag.TagFactory;
import net.fabricmc.fabric.impl.tag.extension.TagDelegate;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.Tag;
import net.minecraft.tags.Tag.Named;
import net.minecraft.tags.TagCollection;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.mixin.common.DiggerItemAccessor;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.function.Supplier;
import java.util.function.BiConsumer;
public class TagAPI {
private static final Map<ResourceLocation, Set<ResourceLocation>> TAGS_BLOCK = Maps.newConcurrentMap();
private static final Map<ResourceLocation, Set<ResourceLocation>> TAGS_ITEM = Maps.newConcurrentMap();
private static final Map<ResourceLocation, Set<ResourceLocation>> TAGS_BIOME = Maps.newConcurrentMap();
/**
* Get or create {@link Tag.Named}.
* Get or create {@link TagKey}.
*
* @param containerSupplier - {@link TagCollection} {@link Supplier} tag collection;
* @param registry - {@link Registry<T>} tag collection;
* @param id - {@link ResourceLocation} tag id.
* @return {@link Tag.Named}.
* @return {@link TagKey}.
*/
public static <T> TagNamed<T> makeTag(Supplier<TagCollection<T>> containerSupplier, TagLocation<T> id) {
Tag<T> tag = containerSupplier.get().getTag(id);
return tag == null ? new Delegate<>(id, containerSupplier) : CommonDelegate.proxy((Named<T>) tag);
public static <T> TagKey<T> makeTag(Registry<T> registry, TagLocation<T> id) {
return registry
.getTagNames()
.filter(tagKey -> tagKey.location().equals(id))
.findAny()
.orElse(TagKey.create(registry.key(), id));
}
/**
* Get or create {@link Block} {@link Tag.Named} with mod namespace.
* Get or create {@link Block} {@link TagKey} with mod namespace.
*
* @param modID - {@link String} mod namespace (mod id);
* @param name - {@link String} tag name.
* @return {@link Block} {@link Tag.Named}.
* @return {@link Block} {@link TagKey}.
*/
public static TagNamed<Block> makeBlockTag(String modID, String name) {
return makeTag(BlockTags::getAllTags, new TagLocation<>(modID, name));
public static TagKey<Biome> makeBiomeTag(String modID, String name) {
return TagKey.create(Registry.BIOME_REGISTRY, new ResourceLocation(modID, name));
}
/**
* Get or create {@link Item} {@link Tag.Named} with mod namespace.
* Get or create {@link Block} {@link TagKey} with mod namespace.
*
* @param modID - {@link String} mod namespace (mod id);
* @param name - {@link String} tag name.
* @return {@link Item} {@link Tag.Named}.
* @return {@link Block} {@link TagKey}.
*/
public static TagNamed<Item> makeItemTag(String modID, String name) {
return makeTag(ItemTags::getAllTags, new TagLocation<>(modID, name));
public static TagKey<Block> makeBlockTag(String modID, String name) {
return makeTag(Registry.BLOCK, new TagLocation<>(modID, name));
}
/**
* Get or create {@link Block} {@link TagKey} with mod namespace.
*
* @param id - {@link String} id for the tag;
* @return {@link Block} {@link TagKey}.
*/
public static TagKey<Block> makeBlockTag(ResourceLocation id) {
return makeTag(Registry.BLOCK, new TagLocation<>(id));
}
/**
* Get or create {@link Block} {@link Tag.Named}.
* Get or create {@link Item} {@link TagKey} with mod namespace.
*
* @param modID - {@link String} mod namespace (mod id);
* @param name - {@link String} tag name.
* @return {@link Item} {@link TagKey}.
*/
public static TagKey<Item> makeItemTag(String modID, String name) {
return makeTag(Registry.ITEM, new TagLocation<>(modID, name));
}
/**
* Get or create {@link Item} {@link TagKey} with mod namespace.
*
* @param id - {@link String} id for the tag;
* @return {@link Item} {@link TagKey}.
*/
public static TagKey<Item> makeItemTag(ResourceLocation id) {
return makeTag(Registry.ITEM, new TagLocation<>(id));
}
/**
* Get or create {@link Block} {@link TagKey}.
*
* @param name - {@link String} tag name.
* @return {@link Block} {@link Tag.Named}.
* @return {@link Block} {@link TagKey}.
* @see <a href="https://fabricmc.net/wiki/tutorial:tags">Fabric Wiki (Tags)</a>
*/
public static TagNamed<Block> makeCommonBlockTag(String name) {
return makeTag(BlockTags::getAllTags, new TagLocation<>("c", name));
public static TagKey<Block> makeCommonBlockTag(String name) {
return makeTag(Registry.BLOCK, new TagLocation<>("c", name));
}
/**
* Get or create {@link Item} {@link Tag.Named}.
* Get or create {@link Item} {@link TagKey}.
*
* @param name - {@link String} tag name.
* @return {@link Item} {@link Tag.Named}.
* @return {@link Item} {@link TagKey}.
* @see <a href="https://fabricmc.net/wiki/tutorial:tags">Fabric Wiki (Tags)</a>
*/
public static TagNamed<Item> makeCommonItemTag(String name) {
return makeTag(ItemTags::getAllTags, new TagLocation<>("c", name));
}
/**
* Get or create Minecraft {@link Block} {@link Tag.Named}.
*
* @param name - {@link String} tag name.
* @return {@link Block} {@link Tag.Named}.
*/
@Deprecated(forRemoval = true)
public static TagNamed<Block> getMCBlockTag(String name) {
ResourceLocation id = new ResourceLocation(name);
Tag<Block> tag = BlockTags.getAllTags().getTag(id);
return CommonDelegate.proxy(tag == null ? (Named<Block>) TagFactory.BLOCK.create(id): (Named<Block>) tag);
public static TagKey<Item> makeCommonItemTag(String name) {
return makeTag(Registry.ITEM, new TagLocation<>("c", name));
}
/**
* Initializes basic tags. Should be called only in BCLib main class.
*/
public static void init() {
addBlockTag(CommonBlockTags.BOOKSHELVES.getName(), Blocks.BOOKSHELF);
addBlockTag(CommonBlockTags.CHEST.getName(), Blocks.CHEST);
addItemTag(CommonItemTags.CHEST.getName(), Items.CHEST);
addItemTag(CommonItemTags.IRON_INGOTS.getName(), Items.IRON_INGOT);
addItemTag(CommonItemTags.FURNACES.getName(), Blocks.FURNACE);
addBlockTag(CommonBlockTags.BOOKSHELVES, Blocks.BOOKSHELF);
addBlockTag(CommonBlockTags.CHEST, Blocks.CHEST);
addItemTag(CommonItemTags.CHEST, Items.CHEST);
addItemTag(CommonItemTags.IRON_INGOTS, Items.IRON_INGOT);
addItemTag(CommonItemTags.FURNACES, Blocks.FURNACE);
}
/**
* Adds multiple Tags to one Biome.
* @param tagIDs array of {@link TagLocation<Biome>} tag IDs.
* @param biome The {@link Biome} to add tag.
*/
@SafeVarargs
public static void addBiomeTags(Biome biome, TagLocation<Biome>... tagIDs) {
for (TagLocation<Biome> tagID : tagIDs) {
addBiomeTagUntyped(tagID, biome);
}
}
/**
* Adds one Tag to multiple Biomes.
* @param tagID {@link TagLocation<Biome>} tag ID.
* @param biomes array of {@link Biome} to add into tag.
*/
public static void addBiomeTag(TagLocation<Biome> tagID, Biome... biomes) {
addBiomeTagUntyped(tagID, biomes);
}
/**
* Adds one Tag to multiple Biomes.
* @param tagID {@link TagKey<Biome>} tag ID.
* @param biomes array of {@link Biome} to add into tag.
*/
public static void addBiomeTag(TagKey<Biome> tagID, Biome... biomes) {
addBiomeTagUntyped(tagID.location(), biomes);
}
/**
* Adds one Tag to multiple Biomes.
* @param tagID {@link ResourceLocation} tag ID.
* @param biomes array of {@link Biome} to add into tag.
*/
protected static void addBiomeTagUntyped(ResourceLocation tagID, Biome... biomes) {
Set<ResourceLocation> set = TAGS_BIOME.computeIfAbsent(tagID, k -> Sets.newHashSet());
for (Biome biome : biomes) {
ResourceLocation id = BiomeAPI.getBiomeID(biome);
if (id != null) {
set.add(id);
}
}
}
/**
* Adds multiple Tags to one Block.
* @param tagIDs array of {@link TagLocation<Block>} tag IDs.
@ -128,6 +194,15 @@ public class TagAPI {
public static void addBlockTag(TagLocation<Block> tagID, Block... blocks) {
addBlockTagUntyped(tagID, blocks);
}
/**
* Adds one Tag to multiple Blocks.
* @param tagID {@link TagKey<Block>} tag ID.
* @param blocks array of {@link Block} to add into tag.
*/
public static void addBlockTag(TagKey<Block> tagID, Block... blocks) {
addBlockTagUntyped(tagID.location(), blocks);
}
/**
* Adds one Tag to multiple Blocks.
@ -164,6 +239,15 @@ public class TagAPI {
public static void addItemTag(TagLocation<Item> tagID, ItemLike... items) {
addItemTagUntyped(tagID, items);
}
/**
* Adds one Tag to multiple Items.
* @param tagID {@link TagKey<Item>} tag ID.
* @param items array of {@link ItemLike} to add into tag.
*/
public static void addItemTag(TagKey<Item> tagID, ItemLike... items) {
addItemTagUntyped(tagID.location(), items);
}
/**
* Adds one Tag to multiple Items.
@ -190,16 +274,17 @@ public class TagAPI {
* @param tagsMap The map that will hold the registered Tags
* @return The {@code tagsMap} Parameter.
*/
public static Map<ResourceLocation, Tag.Builder> apply(String directory, Map<ResourceLocation, Tag.Builder> tagsMap) {
Map<ResourceLocation, Set<ResourceLocation>> tagMap = null;
public static <T> Map<ResourceLocation, Tag.Builder> apply(String directory, Map<ResourceLocation, Tag.Builder> tagsMap) {
final BiConsumer<ResourceLocation, Set<ResourceLocation>> consumer;
consumer = (id, ids) -> apply(tagsMap.computeIfAbsent(id, key -> Tag.Builder.tag()), ids);
if ("tags/blocks".equals(directory)) {
tagMap = TAGS_BLOCK;
TAGS_BLOCK.forEach(consumer);
}
else if ("tags/items".equals(directory)) {
tagMap = TAGS_ITEM;
TAGS_ITEM.forEach(consumer);
}
if (tagMap != null) {
tagMap.forEach((id, ids) -> apply(tagsMap.computeIfAbsent(id, key -> Tag.Builder.tag()), ids));
else if ("tags/worldgen/biome".equals(directory)) {
TAGS_BIOME.forEach(consumer);
}
return tagsMap;
}
@ -215,16 +300,8 @@ public class TagAPI {
ids.forEach(value -> builder.addElement(value, "BCLib Code"));
return builder;
}
/**
* Extends {@link Tag.Named} to return a type safe {@link TagLocation}. This Type was introduced to
* allow type-safe definition of Tags using their ResourceLocation.
* @param <T> The Type of the underlying {@link Tag}
*/
public interface TagNamed<T> extends Tag.Named<T>{
TagLocation<T> getName();
}
/**
* Extends (without changing) {@link ResourceLocation}. This Type was introduced to allow type-safe definition af
* Tags using their ResourceLocation.
@ -234,68 +311,32 @@ public class TagAPI {
public TagLocation(String string) {
super(string);
}
public TagLocation(String string, String string2) {
super(string, string2);
}
public TagLocation(ResourceLocation location) {
super(location.getNamespace(), location.getPath());
}
public static<R> TagLocation<R> of(Tag.Named<R> tag){
return new TagLocation<R>(tag.getName());
public static<R> TagLocation<R> of(TagKey<R> tag){
return new TagLocation<R>(tag.location());
}
}
private abstract static class CommonDelegate<T> implements TagNamed<T> {
protected final Tag.Named<T> delegate;
protected CommonDelegate(Tag.Named<T> source){
this.delegate = source;
}
public static<T> TagNamed<T> proxy(Tag.Named<T> source){
if (source instanceof TagNamed typed) return typed;
return new ProxyDelegate<>(source);
}
@Override
public boolean contains(T object) {
return delegate.contains(object);
}
@Override
public List<T> getValues() {
return delegate.getValues();
}
@Override
public T getRandomElement(Random random) {
return delegate.getRandomElement(random);
}
public static boolean isToolWithMineableTag(ItemStack stack, TagKey<Block> tag){
return isToolWithUntypedMineableTag(stack, tag.location());
}
private static final class ProxyDelegate<T> extends CommonDelegate<T>{
private final TagLocation<T> id;
private ProxyDelegate(Tag.Named<T> source) {
super( source);
id = new TagLocation<>(source.getName()
.getNamespace(), source.getName()
.getPath());
}
@Override
public TagLocation<T> getName(){
return id;
}
public static boolean isToolWithMineableTag(ItemStack stack, TagLocation<Block> tag){
return isToolWithUntypedMineableTag(stack, tag);
}
private static final class Delegate<T> extends CommonDelegate<T>{
public Delegate(TagLocation<T> id, Supplier<TagCollection<T>> containerSupplier) {
super( new TagDelegate<>(id, containerSupplier));
}
@Override
public TagLocation<T> getName(){
return (TagLocation<T>)delegate.getName();
private static boolean isToolWithUntypedMineableTag(ItemStack stack, ResourceLocation tag){
if (stack.getItem() instanceof DiggerItemAccessor dig){
return dig.bclib_getBlockTag().location().equals(tag);
}
return false;
}
}

View file

@ -39,7 +39,6 @@ public class BaseCropBlock extends BasePlantBlock {
public BaseCropBlock(Item drop, Block... terrain) {
this(
FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS)
.randomTicks()
.noCollission(),

View file

@ -2,7 +2,6 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
@ -32,6 +31,7 @@ import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.items.tool.BaseShearsItem;
import ru.bclib.util.BlocksHelper;
import java.util.List;
@ -45,7 +45,6 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
public BaseDoublePlantBlock() {
this(
FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS)
.noCollission()
);
@ -54,7 +53,6 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
public BaseDoublePlantBlock(int light) {
this(
FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS)
.lightLevel((state) -> state.getValue(TOP) ? light : 0)
.noCollission()
@ -117,7 +115,8 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
}
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && FabricToolTags.SHEARS.contains(tool.getItem()) || EnchantmentHelper.getItemEnchantmentLevel(
//TODO: 1.18.2 Test if shearing still works
if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel(
Enchantments.SILK_TOUCH,
tool
) > 0) {

View file

@ -0,0 +1,63 @@
package ru.bclib.blocks;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.tools.AddMineablePickaxe;
import java.util.Collections;
import java.util.List;
public class BaseGlassBlock extends BaseBlockNotFull implements AddMineablePickaxe, RenderLayerProvider {
public BaseGlassBlock(Block block) {
this(block, 0.3f);
}
public BaseGlassBlock(Block block, float resistance) {
super(FabricBlockSettings.copyOf(block)
.resistance(resistance)
.nonOpaque()
.isSuffocating((arg1, arg2, arg3) -> false)
.isViewBlocking((arg1, arg2, arg3) -> false));
}
@Environment(EnvType.CLIENT)
public float getShadeBrightness(BlockState state, BlockGetter view, BlockPos pos) {
return 1.0F;
}
@Override
public boolean propagatesSkylightDown(BlockState state, BlockGetter view, BlockPos pos) {
return true;
}
@Environment(EnvType.CLIENT)
public boolean skipRendering(BlockState state, BlockState neighbor, Direction facing) {
return neighbor.getBlock() == this ? true : super.skipRendering(state, neighbor, facing);
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
return Collections.singletonList(new ItemStack(this));
}
return Collections.emptyList();
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.TRANSLUCENT;
}
}

View file

@ -24,6 +24,8 @@ import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.BlockModelProvider;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.interfaces.tools.AddMineableHoe;
import ru.bclib.interfaces.tools.AddMineableShears;
import ru.bclib.items.tool.BaseShearsItem;
import ru.bclib.util.MHelper;
@ -31,7 +33,7 @@ import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider, RenderLayerProvider, TagProvider {
public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider, RenderLayerProvider, TagProvider, AddMineableShears, AddMineableHoe {
protected final Block sapling;
private static FabricBlockSettings makeLeaves(MaterialColor color) {
@ -100,8 +102,6 @@ public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider,
@Override
public void addTags(List<TagLocation<Block>> blockTags, List<TagLocation<Item>> itemTags) {
blockTags.add(NamedMineableTags.SHEARS);
blockTags.add(NamedMineableTags.HOE);
blockTags.add(NamedBlockTags.LEAVES);
itemTags.add(NamedItemTags.LEAVES);
}

View file

@ -1,17 +1,17 @@
package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.fabricmc.fabric.impl.object.builder.FabricBlockInternals;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TieredItem;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.OreBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
@ -19,7 +19,11 @@ import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import ru.bclib.api.tag.NamedCommonBlockTags;
import ru.bclib.api.tag.NamedMineableTags;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.interfaces.BlockModelProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.util.LootUtil;
import ru.bclib.util.MHelper;
@ -31,6 +35,7 @@ public class BaseOreBlock extends OreBlock implements BlockModelProvider {
private final Supplier<Item> dropItem;
private final int minCount;
private final int maxCount;
private final int miningLevel;
public BaseOreBlock(Supplier<Item> drop, int minCount, int maxCount, int experience) {
this(drop, minCount, maxCount, experience, 0);
@ -53,15 +58,11 @@ public class BaseOreBlock extends OreBlock implements BlockModelProvider {
}
public BaseOreBlock(Properties properties, Supplier<Item> drop, int minCount, int maxCount, int experience, int miningLevel) {
super(makeProps(properties, miningLevel), UniformInt.of(experience>0?1:0, experience));
super(properties, UniformInt.of(experience>0?1:0, experience));
this.dropItem = drop;
this.minCount = minCount;
this.maxCount = maxCount;
}
private static Properties makeProps(Properties properties, int level){
FabricBlockInternals.computeExtraData(properties).addMiningLevel(FabricToolTags.PICKAXES, level);
return properties;
this.miningLevel = miningLevel;
}
@Override
@ -70,30 +71,35 @@ public class BaseOreBlock extends OreBlock implements BlockModelProvider {
return LootUtil
.getDrops(this, state, builder)
.orElseGet(
()->BaseOreBlock.getDroppedItems(this, dropItem.get(), maxCount, minCount, state, builder)
()->BaseOreBlock.getDroppedItems(this, dropItem.get(), maxCount, minCount, miningLevel, state, builder)
);
}
public static List<ItemStack> getDroppedItems(ItemLike block, Item dropItem, int maxCount, int minCount, BlockState state, LootContext.Builder builder) {
public static List<ItemStack> getDroppedItems(ItemLike block, Item dropItem, int maxCount, int minCount, int miningLevel, BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && tool.isCorrectToolForDrops(state)) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
return Collections.singletonList(new ItemStack(block));
boolean canMine = miningLevel==0;
if (tool.getItem() instanceof TieredItem tired) {
canMine = tired.getTier().getLevel()>=miningLevel;
}
int count;
int enchantment = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool);
if (enchantment > 0) {
int min = Mth.clamp(minCount + enchantment, minCount, maxCount);
int max = maxCount + (enchantment / Enchantments.BLOCK_FORTUNE.getMaxLevel());
if (min == max) {
return Collections.singletonList(new ItemStack(dropItem, max));
if (canMine) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
return Collections.singletonList(new ItemStack(block));
}
count = MHelper.randRange(min, max, MHelper.RANDOM);
int count;
int enchantment = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool);
if (enchantment > 0) {
int min = Mth.clamp(minCount + enchantment, minCount, maxCount);
int max = maxCount + (enchantment / Enchantments.BLOCK_FORTUNE.getMaxLevel());
if (min == max) {
return Collections.singletonList(new ItemStack(dropItem, max));
}
count = MHelper.randRange(min, max, MHelper.RANDOM);
} else {
count = MHelper.randRange(minCount, maxCount, MHelper.RANDOM);
}
return Collections.singletonList(new ItemStack(dropItem, count));
}
else {
count = MHelper.randRange(minCount, maxCount, MHelper.RANDOM);
}
return Collections.singletonList(new ItemStack(dropItem, count));
}
return Collections.emptyList();
}

View file

@ -4,7 +4,6 @@ import com.google.common.collect.Lists;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@ -40,12 +39,15 @@ import ru.bclib.client.models.PatternsHelper;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.interfaces.tools.AddMineableHoe;
import ru.bclib.interfaces.tools.AddMineableShears;
import ru.bclib.items.tool.BaseShearsItem;
import java.util.List;
import java.util.Optional;
import java.util.Random;
public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock, TagProvider {
public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock{
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
public BasePlantBlock() {
@ -60,7 +62,6 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
this(
FabricBlockSettings
.of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS)
.noCollission()
);
@ -70,7 +71,6 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
this(
FabricBlockSettings
.of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT)
.breakByHand(true)
.luminance(light)
.sound(SoundType.GRASS)
.noCollission()
@ -116,7 +116,8 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && FabricToolTags.SHEARS.contains(tool.getItem()) || EnchantmentHelper.getItemEnchantmentLevel(
//TODO: 1.18.2 Test if shearing still works
if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel(
Enchantments.SILK_TOUCH,
tool
) > 0) {
@ -167,10 +168,4 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation);
return ModelsHelper.fromPattern(pattern);
}
@Override
public void addTags(List<TagLocation<Block>> blockTags, List<TagLocation<Item>> itemTags) {
blockTags.add(NamedMineableTags.SHEARS);
blockTags.add(NamedMineableTags.HOE);
}
}

View file

@ -20,7 +20,6 @@ public abstract class BasePlantWithAgeBlock extends BasePlantBlock {
public BasePlantWithAgeBlock() {
this(
FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS)
.randomTicks()
.noCollission()

View file

@ -1,7 +1,6 @@
package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
@ -15,6 +14,8 @@ import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.BlockHitResult;
import ru.bclib.api.tag.NamedMineableTags;
import ru.bclib.api.tag.TagAPI;
public class BaseStripableLogBlock extends BaseRotatedPillarBlock {
private final Block striped;
@ -27,7 +28,7 @@ public class BaseStripableLogBlock extends BaseRotatedPillarBlock {
@Override
@SuppressWarnings("deprecation")
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (FabricToolTags.AXES.contains(player.getMainHandItem().getItem())) {
if (TagAPI.isToolWithMineableTag(player.getMainHandItem(), NamedMineableTags.AXE)){
world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F);
if (!world.isClientSide) {
world.setBlock(pos,

View file

@ -3,8 +3,8 @@ package ru.bclib.blocks;
import com.google.common.collect.Maps;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos;
@ -33,6 +33,8 @@ import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.Nullable;
import ru.bclib.api.tag.NamedMineableTags;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.client.models.BasePatterns;
import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper;
@ -69,7 +71,9 @@ public class BaseTerrainBlock extends BaseBlock {
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (pathBlock != null && FabricToolTags.SHOVELS.contains(player.getMainHandItem().getItem())) {
//TODO: 1.18.2 check
if (pathBlock != null && TagAPI.isToolWithMineableTag(player.getMainHandItem(), NamedMineableTags.SHOVEL)){
//if (pathBlock != null && FabricTagProvider.SHOVELS.contains(player.getMainHandItem().getItem())) {
world.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);
if (!world.isClientSide) {
world.setBlockAndUpdate(pos, pathBlock.defaultBlockState());

View file

@ -18,7 +18,6 @@ public abstract class BaseUnderwaterWallPlantBlock extends BaseWallPlantBlock im
this(
FabricBlockSettings
.of(Material.WATER_PLANT)
.breakByHand(true)
.sound(SoundType.WET_GRASS)
.noCollission()
);
@ -28,7 +27,6 @@ public abstract class BaseUnderwaterWallPlantBlock extends BaseWallPlantBlock im
this(
FabricBlockSettings
.of(Material.WATER_PLANT)
.breakByHand(true)
.luminance(light)
.sound(SoundType.WET_GRASS)
.noCollission()

View file

@ -2,7 +2,6 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
@ -31,6 +30,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
import ru.bclib.blocks.BlockProperties.TripleShape;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.items.tool.BaseShearsItem;
import ru.bclib.util.BlocksHelper;
import java.util.List;
@ -53,7 +53,6 @@ public class BaseVineBlock extends BaseBlockNotFull implements RenderLayerProvid
this(
FabricBlockSettings
.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS)
.lightLevel((state) -> bottomOnly ? state.getValue(SHAPE) == TripleShape.BOTTOM ? light : 0 : light)
.noCollission()
@ -110,7 +109,7 @@ public class BaseVineBlock extends BaseBlockNotFull implements RenderLayerProvid
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && FabricToolTags.SHEARS.contains(tool.getItem()) || EnchantmentHelper.getItemEnchantmentLevel(
if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel(
Enchantments.SILK_TOUCH,
tool
) > 0) {

View file

@ -39,7 +39,6 @@ public abstract class BaseWallPlantBlock extends BasePlantBlock {
this(
FabricBlockSettings
.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS)
.noCollission()
);
@ -49,7 +48,6 @@ public abstract class BaseWallPlantBlock extends BasePlantBlock {
this(
FabricBlockSettings
.of(Material.PLANT)
.breakByHand(true)
.luminance(light)
.sound(SoundType.GRASS)
.noCollission()

View file

@ -44,7 +44,6 @@ public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProv
public FeatureSaplingBlock(Function<BlockState, Feature<?>> featureSupplier) {
this(FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.collidable(false)
.instabreak()
.sound(SoundType.GRASS)
@ -55,7 +54,6 @@ public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProv
public FeatureSaplingBlock(int light, Function<BlockState, Feature<?>> featureSupplier) {
this(FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.collidable(false)
.luminance(light)
.instabreak()

View file

@ -14,10 +14,12 @@ import ru.bclib.api.tag.TagAPI.TagLocation;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.interfaces.tools.AddMineableHoe;
import ru.bclib.interfaces.tools.AddMineableShears;
import java.util.List;
public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerProvider, TagProvider {
public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerProvider, TagProvider, AddMineableShears, AddMineableHoe {
public SimpleLeavesBlock(MaterialColor color) {
this(
FabricBlockSettings
@ -58,8 +60,6 @@ public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerPr
@Override
public void addTags(List<TagLocation<Block>> blockTags, List<TagLocation<Item>> itemTags) {
blockTags.add(NamedMineableTags.SHEARS);
blockTags.add(NamedMineableTags.HOE);
blockTags.add(NamedBlockTags.LEAVES);
itemTags.add(NamedItemTags.LEAVES);
}

View file

@ -1,7 +1,6 @@
package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
@ -15,6 +14,8 @@ import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.BlockHitResult;
import ru.bclib.api.tag.NamedMineableTags;
import ru.bclib.api.tag.TagAPI;
public class StripableBarkBlock extends BaseBarkBlock {
private final Block striped;
@ -27,7 +28,7 @@ public class StripableBarkBlock extends BaseBarkBlock {
@Override
@SuppressWarnings("deprecation")
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (FabricToolTags.AXES.contains(player.getMainHandItem().getItem())) {
if (TagAPI.isToolWithMineableTag(player.getMainHandItem(), NamedMineableTags.AXE)){
world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F);
if (!world.isClientSide) {
world.setBlock(pos,

View file

@ -2,7 +2,6 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
@ -36,18 +35,20 @@ import ru.bclib.api.tag.TagAPI.TagLocation;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.interfaces.tools.AddMineableHoe;
import ru.bclib.interfaces.tools.AddMineableShears;
import ru.bclib.items.tool.BaseShearsItem;
import java.util.List;
import java.util.Random;
public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock, LiquidBlockContainer, TagProvider {
public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock, LiquidBlockContainer {
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
public UnderwaterPlantBlock() {
this(
FabricBlockSettings
.of(Material.WATER_PLANT)
.breakByHand(true)
.sound(SoundType.WET_GRASS)
.noCollission()
);
@ -57,7 +58,6 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
this(
FabricBlockSettings
.of(Material.WATER_PLANT)
.breakByHand(true)
.luminance(light)
.sound(SoundType.WET_GRASS)
.noCollission()
@ -105,7 +105,7 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && FabricToolTags.SHEARS.contains(tool.getItem()) || EnchantmentHelper.getItemEnchantmentLevel(
if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel(
Enchantments.SILK_TOUCH,
tool
) > 0) {
@ -158,10 +158,5 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
public FluidState getFluidState(BlockState state) {
return Fluids.WATER.getSource(false);
}
@Override
public void addTags(List<TagLocation<Block>> blockTags, List<TagLocation<Item>> itemTags) {
blockTags.add(NamedMineableTags.SHEARS);
blockTags.add(NamedMineableTags.HOE);
}
}

View file

@ -20,7 +20,6 @@ public abstract class UnderwaterPlantWithAgeBlock extends UnderwaterPlantBlock {
super(
FabricBlockSettings
.of(Material.WATER_PLANT)
.breakByHand(true)
.sound(SoundType.WET_GRASS)
.randomTicks()
.noCollission()

View file

@ -2,7 +2,6 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.player.Player;
@ -30,16 +29,18 @@ import ru.bclib.api.tag.TagAPI.TagLocation;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.interfaces.tools.AddMineableHoe;
import ru.bclib.interfaces.tools.AddMineableShears;
import ru.bclib.items.tool.BaseShearsItem;
import java.util.List;
public abstract class UpDownPlantBlock extends BaseBlockNotFull implements RenderLayerProvider, TagProvider {
public abstract class UpDownPlantBlock extends BaseBlockNotFull implements RenderLayerProvider, AddMineableShears, AddMineableHoe {
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 16, 12);
public UpDownPlantBlock() {
this(FabricBlockSettings
.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS)
.noCollission()
);
@ -83,7 +84,7 @@ public abstract class UpDownPlantBlock extends BaseBlockNotFull implements Rende
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && FabricToolTags.SHEARS.contains(tool.getItem()) || EnchantmentHelper.getItemEnchantmentLevel(
if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel(
Enchantments.SILK_TOUCH,
tool
) > 0) {
@ -104,10 +105,4 @@ public abstract class UpDownPlantBlock extends BaseBlockNotFull implements Rende
super.playerDestroy(world, player, pos, state, blockEntity, stack);
world.neighborChanged(pos, Blocks.AIR, pos.below());
}
@Override
public void addTags(List<TagLocation<Block>> blockTags, List<TagLocation<Item>> itemTags) {
blockTags.add(NamedMineableTags.SHEARS);
blockTags.add(NamedMineableTags.HOE);
}
}

View file

@ -19,7 +19,6 @@ public abstract class WallMushroomBlock extends BaseWallPlantBlock {
this(
FabricBlockSettings
.of(Material.PLANT)
.breakByHand(true)
.luminance(light)
.destroyTime(0.2F)
.sound(SoundType.GRASS)

View file

@ -108,12 +108,12 @@ public class CustomFogRenderer {
}
private static boolean shouldIgnore(Level level, int x, int y, int z) {
Biome biome = level.getBiome(MUT_POS.set(x, y, z));
Biome biome = level.getBiome(MUT_POS.set(x, y, z)).value();
return BiomeAPI.getRenderBiome(biome) == BiomeAPI.EMPTY_BIOME;
}
private static float getFogDensityI(Level level, int x, int y, int z) {
Biome biome = level.getBiome(MUT_POS.set(x, y, z));
Biome biome = level.getBiome(MUT_POS.set(x, y, z)).value();
BCLBiome renderBiome = BiomeAPI.getRenderBiome(biome);
return renderBiome.getFogDensity();
}

View file

@ -6,7 +6,7 @@ import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.Nullable;
@ -32,8 +32,8 @@ public abstract class ComplexMaterial {
private final List<BlockEntry> defaultBlockEntries = Lists.newArrayList();
private final List<ItemEntry> defaultItemEntries = Lists.newArrayList();
private final Map<String, Tag.Named<Block>> blockTags = Maps.newHashMap();
private final Map<String, Tag.Named<Item>> itemTags = Maps.newHashMap();
private final Map<String, TagKey<Block>> blockTags = Maps.newHashMap();
private final Map<String, TagKey<Item>> itemTags = Maps.newHashMap();
private final Map<String, Block> blocks = Maps.newHashMap();
private final Map<String, Item> items = Maps.newHashMap();
@ -105,39 +105,39 @@ public abstract class ComplexMaterial {
/**
* Adds custom block tag for this {@link ComplexMaterial}, tag can be created with {@link TagAPI} or you can use one of already created tags.
* @param tag {@link Tag.Named} for {@link Block}
* @param tag {@link TagKey} for {@link Block}
*/
protected void addBlockTag(Tag.Named<Block> tag) {
String key = tag.getName().getPath().replace(getBaseName() + "_", "");
protected void addBlockTag(TagKey<Block> tag) {
String key = tag.location().getPath().replace(getBaseName() + "_", "");
blockTags.put(key, tag);
}
/**
* Adds custom iten tag for this {@link ComplexMaterial}, tag can be created with {@link TagAPI} or you can use one of already created tags.
* @param tag {@link Tag.Named} for {@link Item}
* Adds custom item tag for this {@link ComplexMaterial}, tag can be created with {@link TagAPI} or you can use one of already created tags.
* @param tag {@link TagKey} for {@link Item}
*/
protected void addItemTag(Tag.Named<Item> tag) {
String key = tag.getName().getPath().replace(getBaseName() + "_", "");
protected void addItemTag(TagKey<Item> tag) {
String key = tag.location().getPath().replace(getBaseName() + "_", "");
itemTags.put(key, tag);
}
/**
* Get custom {@link Block} {@link Tag.Named} from this {@link ComplexMaterial}.
* Get custom {@link Block} {@link TagKey} from this {@link ComplexMaterial}.
* @param key {@link String} tag name (path of its {@link ResourceLocation}), for inner tags created inside material its tag suffix.
* @return {@link Tag.Named} for {@link Block} or {@code null} if nothing is stored.
* @return {@link TagKey} for {@link Block} or {@code null} if nothing is stored.
*/
@Nullable
public Tag.Named<Block> getBlockTag(String key) {
public TagKey<Block> getBlockTag(String key) {
return blockTags.get(key);
}
/**
* Get custom {@link Item} {@link Tag.Named} from this {@link ComplexMaterial}.
* Get custom {@link Item} {@link TagKey} from this {@link ComplexMaterial}.
* @param key {@link String} tag name (path of its {@link ResourceLocation}), for inner tags created inside material its tag suffix.
* @return {@link Tag.Named} for {@link Item} or {@code null} if nothing is stored.
* @return {@link TagKey} for {@link Item} or {@code null} if nothing is stored.
*/
@Nullable
public Tag.Named<Item> getItemTag(String key) {
public TagKey<Item> getItemTag(String key) {
return itemTags.get(key);
}

View file

@ -100,8 +100,8 @@ public class WoodenComplexMaterial extends ComplexMaterial {
}
final protected void initBase(FabricBlockSettings blockSettings, FabricItemSettings itemSettings) {
TagLocation<Block> tagBlockLog = new TagLocation<>(getBlockTag(TAG_LOGS).getName());
TagLocation<Item> tagItemLog = new TagLocation<>(getItemTag(TAG_LOGS).getName());
TagLocation<Block> tagBlockLog = TagLocation.of(getBlockTag(TAG_LOGS));
TagLocation<Item> tagItemLog = TagLocation.of(getItemTag(TAG_LOGS));
addBlockEntry(
new BlockEntry(BLOCK_STRIPPED_LOG, (complexMaterial, settings) -> new BaseRotatedPillarBlock(settings))

View file

@ -1,7 +1,7 @@
package ru.bclib.integration;
import net.fabricmc.fabric.api.tag.TagFactory;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceKey;
@ -9,7 +9,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.Tag;
import net.minecraft.tags.Tag.Named;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
@ -19,6 +19,7 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import ru.bclib.BCLib;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.world.features.BCLFeature;
import java.lang.reflect.Constructor;
@ -38,6 +39,10 @@ public abstract class ModIntegration {
public ResourceLocation getID(String name) {
return new ResourceLocation(modID, name);
}
public ResourceKey<PlacedFeature> getFeatureKey(String name) {
return ResourceKey.create(Registry.PLACED_FEATURE_REGISTRY, getID(name));
}
public Block getBlock(String name) {
return Registry.BLOCK.get(getID(name));
@ -62,8 +67,8 @@ public abstract class ModIntegration {
public BCLFeature getFeature(String featureID, String placedFeatureID, GenerationStep.Decoration featureStep) {
ResourceLocation id = getID(featureID);
Feature<?> feature = Registry.FEATURE.get(id);
PlacedFeature featureConfigured = BuiltinRegistries.PLACED_FEATURE.get(getID(placedFeatureID));
return new BCLFeature(id, feature, featureStep, featureConfigured);
Holder<PlacedFeature> featurePlaced = BuiltinRegistries.PLACED_FEATURE.getHolder(getFeatureKey(placedFeatureID)).orElse(null);
return new BCLFeature(id, feature, featureStep, featurePlaced);
}
public BCLFeature getFeature(String name, GenerationStep.Decoration featureStep) {
@ -74,8 +79,8 @@ public abstract class ModIntegration {
return BuiltinRegistries.CONFIGURED_FEATURE.get(getID(name));
}
public Biome getBiome(String name) {
return BuiltinRegistries.BIOME.get(getID(name));
public Holder<Biome> getBiome(String name) {
return BuiltinRegistries.BIOME.getHolder(getKey(name)).orElseThrow();
}
public Class<?> getClass(String path) {
@ -197,18 +202,13 @@ public abstract class ModIntegration {
return null;
}
public Tag.Named<Item> getItemTag(String name) {
public TagKey<Item> getItemTag(String name) {
ResourceLocation id = getID(name);
Tag<Item> tag = ItemTags.getAllTags().getTag(id);
//return tag == null ? (Named<Item>) TagRegistry.item(id) : (Named<Item>) tag;
return tag == null ? (Named<Item>) TagFactory.ITEM.create(id) : (Named<Item>) tag;
return TagAPI.makeItemTag(id);
}
public Tag.Named<Block> getBlockTag(String name) {
public TagKey<Block> getBlockTag(String name) {
ResourceLocation id = getID(name);
Tag<Block> tag = BlockTags.getAllTags().getTag(id);
//return tag == null ? (Named<Block>) TagRegistry.block(id) : (Named<Block>) tag;
return tag == null ? (Named<Block>) TagFactory.BLOCK.create(id) : (Named<Block>) tag;
return TagAPI.makeBlockTag(id);
}
}

View file

@ -0,0 +1,8 @@
package ru.bclib.interfaces;
import net.minecraft.core.Registry;
import net.minecraft.world.level.levelgen.structure.StructureSet;
public interface ChunkGeneratorAccessor {
Registry<StructureSet> bclib_getStructureSetsRegistry();
}

View file

@ -12,7 +12,7 @@ import java.util.function.Function;
public interface NumericProvider {
ResourceKey<Registry<Codec<? extends NumericProvider>>> NUMERIC_PROVIDER_REGISTRY = ResourceKey.createRegistryKey(BCLib.makeID("worldgen/numeric_provider"));
Registry<Codec<? extends NumericProvider>> NUMERIC_PROVIDER = new MappedRegistry<>(NUMERIC_PROVIDER_REGISTRY, Lifecycle.experimental());
Registry<Codec<? extends NumericProvider>> NUMERIC_PROVIDER = new MappedRegistry<>(NUMERIC_PROVIDER_REGISTRY, Lifecycle.experimental(), null);
Codec<NumericProvider> CODEC = NUMERIC_PROVIDER.byNameCodec().dispatch(NumericProvider::pcodec, Function.identity());
int getNumber(SurfaceRulesContextAccessor context);

View file

@ -1,10 +1,11 @@
package ru.bclib.interfaces;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.state.BlockState;
public interface SurfaceProvider {
public BlockState bclib_getSurface(BlockPos pos, Biome biome, ServerLevel level);
public BlockState bclib_getSurface(BlockPos pos, Holder<Biome> biome, ServerLevel level);
}

View file

@ -0,0 +1,33 @@
package ru.bclib.interfaces;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public interface SurvivesOnBlocks extends SurvivesOnSpecialGround{
List<Block> getSurvivableBlocks();
@Override
default String getSurvivableBlocksString(){
return getSurvivableBlocks()
.stream()
.filter(block -> block!= Blocks.AIR && block!=null)
.map(block -> {
ItemStack stack = new ItemStack(block);
if (stack.hasCustomHoverName()) return stack.getHoverName().getString();
else return block.getName().getString();
})
.sorted(Comparator.naturalOrder())
.collect(Collectors.joining(", "));
}
@Override
default boolean isSurvivable(BlockState state){
return getSurvivableBlocks().contains(state.getBlock());
}
}

View file

@ -0,0 +1,63 @@
package ru.bclib.interfaces;
import com.google.common.collect.Lists;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
import java.util.List;
public interface SurvivesOnSpecialGround {
String getSurvivableBlocksString();
@Environment(EnvType.CLIENT)
static List<String> splitLines(String input) {
final int MAX_LEN = 45;
List<String> lines = Lists.newArrayList();
while (input.length()>MAX_LEN){
int idx = input.lastIndexOf(",", MAX_LEN);
if (idx>=0) {
lines.add( input.substring(0, idx+1).trim());
input = input.substring(idx+1).trim();
} else {
break;
}
}
lines.add(input.trim());
return lines;
}
@Environment(EnvType.CLIENT)
static void appendHoverText(List<Component> list, String description) {
final int MAX_LINES = 7;
List<String> lines = splitLines(description);
if (lines.size()==1) {
list.add(new TranslatableComponent("tooltip.bclib.place_on", lines.get(0)).withStyle(ChatFormatting.GREEN));
} else if (lines.size()>1) {
list.add(new TranslatableComponent("tooltip.bclib.place_on", "").withStyle(ChatFormatting.GREEN));
for (int i = 0; i < Math.min(lines.size(), MAX_LINES); i++) {
String line = lines.get(i);
if (i == MAX_LINES - 1 && i < lines.size() - 1) line += " ...";
list.add(new TextComponent(" " + line).withStyle(ChatFormatting.GREEN));
}
}
}
boolean isSurvivable(BlockState state);
default boolean canSurviveOnTop(BlockState state, LevelReader world, BlockPos pos) {
return isSurvivable(world.getBlockState(pos.below()));
}
default boolean canSurviveOnBottom(BlockState state, LevelReader world, BlockPos pos) {
return isSurvivable(world.getBlockState(pos.above()));
}
}

View file

@ -0,0 +1,40 @@
package ru.bclib.interfaces;
import net.minecraft.core.Registry;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.NetherrackBlock;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public interface SurvivesOnTags extends SurvivesOnSpecialGround{
List<TagKey<Block>> getSurvivableTags();
@Override
default String getSurvivableBlocksString(){
return getSurvivableTags()
.stream()
.map(tag -> Registry.BLOCK.getTag(tag))
.filter(named->named.isPresent())
.map(named->named.get())
.flatMap(named->named.stream())
.filter(block -> block != Blocks.AIR && block != null)
.map(block -> {
ItemStack stack = new ItemStack(block.value());
if (stack.hasCustomHoverName()) return stack.getHoverName().getString();
else return block.value().getName().getString();
})
.sorted(Comparator.naturalOrder())
.collect(Collectors.joining(", "));
}
@Override
default boolean isSurvivable(BlockState state){
return getSurvivableTags().stream().anyMatch(tag->state.is(tag));
}
}

View file

@ -0,0 +1,4 @@
package ru.bclib.interfaces.tools;
public interface AddMineableAxe {
}

View file

@ -0,0 +1,4 @@
package ru.bclib.interfaces.tools;
public interface AddMineableHammer {
}

View file

@ -0,0 +1,4 @@
package ru.bclib.interfaces.tools;
public interface AddMineableHoe {
}

View file

@ -0,0 +1,4 @@
package ru.bclib.interfaces.tools;
public interface AddMineablePickaxe {
}

View file

@ -0,0 +1,4 @@
package ru.bclib.interfaces.tools;
public interface AddMineableShears {
}

View file

@ -0,0 +1,4 @@
package ru.bclib.interfaces.tools;
public interface AddMineableShovel {
}

View file

@ -0,0 +1,4 @@
package ru.bclib.interfaces.tools;
public interface AddMineableSword {
}

View file

@ -0,0 +1,4 @@
package ru.bclib.interfaces.tools;
public interface PreventMineableAdd {
}

View file

@ -2,33 +2,18 @@ package ru.bclib.items.tool;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.AxeItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Tier;
import net.minecraft.world.level.block.state.BlockState;
import ru.bclib.client.models.ModelsHelper;
import ru.bclib.interfaces.ItemModelProvider;
public class BaseAxeItem extends AxeItem implements DynamicAttributeTool, ItemModelProvider {
public class BaseAxeItem extends AxeItem implements ItemModelProvider {
public BaseAxeItem(Tier material, float attackDamage, float attackSpeed, Properties settings) {
super(material, attackDamage, attackSpeed, settings);
}
@Override
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
if (tag.equals(FabricToolTags.AXES)) {
return this.getTier().getLevel();
}
return 0;
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {

View file

@ -2,44 +2,18 @@ package ru.bclib.items.tool;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.fabricmc.fabric.impl.tool.attribute.ToolManagerImpl;
import net.fabricmc.fabric.impl.tool.attribute.ToolManagerImpl.Entry;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.PickaxeItem;
import net.minecraft.world.item.Tier;
import net.minecraft.world.level.block.state.BlockState;
import ru.bclib.client.models.ModelsHelper;
import ru.bclib.interfaces.ItemModelProvider;
public class BasePickaxeItem extends PickaxeItem implements DynamicAttributeTool, ItemModelProvider {
public class BasePickaxeItem extends PickaxeItem implements ItemModelProvider {
public BasePickaxeItem(Tier material, int attackDamage, float attackSpeed, Properties settings) {
super(material, attackDamage, attackSpeed, settings);
}
@Override
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
if (tag.equals(FabricToolTags.PICKAXES)) {
return getTier().getLevel();
}
return 0;
}
@Override
public float getDestroySpeed(ItemStack stack, BlockState state) {
Entry entry = ToolManagerImpl.entryNullable(state.getBlock());
return (entry != null && entry.getMiningLevel(FabricToolTags.PICKAXES) >= 0) ? speed : super.getDestroySpeed(
stack,
state
);
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {

View file

@ -1,11 +1,13 @@
package ru.bclib.items.tool;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.fabricmc.fabric.api.mininglevel.v1.FabricMineableTags;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ShearsItem;
import ru.bclib.api.tag.CommonItemTags;
import ru.bclib.api.tag.TagAPI;
public class BaseShearsItem extends ShearsItem {
public BaseShearsItem(Properties properties) {
@ -13,12 +15,12 @@ public class BaseShearsItem extends ShearsItem {
}
public static boolean isShear(ItemStack tool){
return tool.is(Items.SHEARS) | tool.is(CommonItemTags.SHEARS) || tool.is(FabricToolTags.SHEARS);
return tool.is(Items.SHEARS) | tool.is(CommonItemTags.SHEARS) || TagAPI.isToolWithMineableTag(tool, FabricMineableTags.SHEARS_MINEABLE);
}
public static boolean isShear(ItemStack itemStack, Item item){
if (item == Items.SHEARS){
return itemStack.is(item) | itemStack.is(CommonItemTags.SHEARS) || itemStack.is(FabricToolTags.SHEARS);
return itemStack.is(item) | itemStack.is(CommonItemTags.SHEARS);
} else {
return itemStack.is(item);
}

View file

@ -2,44 +2,18 @@ package ru.bclib.items.tool;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.fabricmc.fabric.impl.tool.attribute.ToolManagerImpl;
import net.fabricmc.fabric.impl.tool.attribute.ToolManagerImpl.Entry;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ShovelItem;
import net.minecraft.world.item.Tier;
import net.minecraft.world.level.block.state.BlockState;
import ru.bclib.client.models.ModelsHelper;
import ru.bclib.interfaces.ItemModelProvider;
public class BaseShovelItem extends ShovelItem implements DynamicAttributeTool, ItemModelProvider {
public class BaseShovelItem extends ShovelItem implements ItemModelProvider {
public BaseShovelItem(Tier material, float attackDamage, float attackSpeed, Properties settings) {
super(material, attackDamage, attackSpeed, settings);
}
@Override
public int getMiningLevel(Tag<Item> tag, BlockState state, ItemStack stack, LivingEntity user) {
if (tag.equals(FabricToolTags.SHOVELS)) {
return this.getTier().getLevel();
}
return 0;
}
@Override
public float getDestroySpeed(ItemStack stack, BlockState state) {
Entry entry = ToolManagerImpl.entryNullable(state.getBlock());
return (entry != null && entry.getMiningLevel(FabricToolTags.SHOVELS) >= 0) ? speed : super.getDestroySpeed(
stack,
state
);
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {

View file

@ -2,7 +2,6 @@ package ru.bclib.items.tool;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.SwordItem;
@ -10,7 +9,7 @@ import net.minecraft.world.item.Tier;
import ru.bclib.client.models.ModelsHelper;
import ru.bclib.interfaces.ItemModelProvider;
public class BaseSwordItem extends SwordItem implements DynamicAttributeTool, ItemModelProvider {
public class BaseSwordItem extends SwordItem implements ItemModelProvider {
public BaseSwordItem(Tier material, int attackDamage, float attackSpeed, Properties settings) {
super(material, attackDamage, attackSpeed, settings);
}

View file

@ -0,0 +1,25 @@
package ru.bclib.mixin.client;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.bclib.interfaces.SurvivesOnSpecialGround;
import java.util.List;
@Mixin(Block.class)
public class BlockMixin {
@Inject(method="appendHoverText", at=@At("HEAD"))
void bclib_appendSurvivalBlock(ItemStack itemStack, @Nullable BlockGetter blockGetter, List<Component> list, TooltipFlag tooltipFlag, CallbackInfo ci){
if (this instanceof SurvivesOnSpecialGround surv){
SurvivesOnSpecialGround.appendHoverText(list, surv.getSurvivableBlocksString());
}
}
}

View file

@ -15,13 +15,13 @@ public abstract class EnchantingTableBlockMixin extends Block {
super(settings);
}
@Redirect(method = "animateTick", at = @At(
@Redirect(method = "isValidBookShelf", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/state/BlockState;is(Lnet/minecraft/world/level/block/Block;)Z"),
require = -1,
expect = -1
)
private boolean bclib_isBookshelf(BlockState state, Block block) {
private static boolean bclib_isBookshelf(BlockState state, Block block) {
return block == Blocks.BOOKSHELF ? state.is(CommonBlockTags.BOOKSHELVES) : state.is(block);
}
}

View file

@ -1,6 +1,5 @@
package ru.bclib.mixin.client;
import com.mojang.datafixers.util.Function4;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Minecraft.ExperimentalDialogType;
import net.minecraft.client.color.block.BlockColors;
@ -8,14 +7,11 @@ import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.main.GameConfig;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.RegistryAccess.RegistryHolder;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.level.DataPackConfig;
import net.minecraft.server.WorldStem;
import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
import net.minecraft.world.level.storage.WorldData;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -44,17 +40,15 @@ public abstract class MinecraftMixin {
@Inject(method = "<init>*", at = @At("TAIL"))
private void bclib_onMCInit(GameConfig args, CallbackInfo info) {
Registry.BLOCK.forEach(block -> {
if (block instanceof CustomColorProvider) {
CustomColorProvider provider = (CustomColorProvider) block;
if (block instanceof CustomColorProvider provider) {
blockColors.register(provider.getProvider(), block);
itemColors.register(provider.getItemProvider(), block.asItem());
}
});
}
@Shadow
protected abstract void doLoadLevel(String string, RegistryHolder registryHolder, Function<LevelStorageAccess, DataPackConfig> function, Function4<LevelStorageAccess, RegistryHolder, ResourceManager, DataPackConfig, WorldData> function4, boolean bl, ExperimentalDialogType experimentalDialogType);
@Shadow protected abstract void doLoadLevel(String string, Function<LevelStorageAccess, WorldStem.DataPackConfigSupplier> function, Function<LevelStorageAccess, WorldStem.WorldDataSupplier> function2, boolean bl, ExperimentalDialogType experimentalDialogType);
@Shadow
@Final
private LevelStorageSource levelSource;
@ -66,7 +60,7 @@ public abstract class MinecraftMixin {
if (DataFixerAPI.fixData(this.levelSource, levelID, true, (appliedFixes) -> {
LifeCycleAPI._runBeforeLevelLoad();
this.doLoadLevel(levelID, RegistryAccess.builtin(), Minecraft::loadDataPacks, Minecraft::loadWorldData, false, appliedFixes ? ExperimentalDialogType.NONE : ExperimentalDialogType.BACKUP);
this.doLoadLevel(levelID, WorldStem.DataPackConfigSupplier::loadFromWorld, WorldStem.WorldDataSupplier::loadFromWorld, false, appliedFixes ? ExperimentalDialogType.NONE : ExperimentalDialogType.BACKUP);
})) {
//cancle call when fix-screen is presented
ci.cancel();
@ -74,7 +68,7 @@ public abstract class MinecraftMixin {
else {
LifeCycleAPI._runBeforeLevelLoad();
if (Configs.CLIENT_CONFIG.suppressExperimentalDialog()) {
this.doLoadLevel(levelID, RegistryAccess.builtin(), Minecraft::loadDataPacks, Minecraft::loadWorldData, false, ExperimentalDialogType.NONE);
this.doLoadLevel(levelID, WorldStem.DataPackConfigSupplier::loadFromWorld, WorldStem.WorldDataSupplier::loadFromWorld, false, ExperimentalDialogType.NONE);
//cancle call as we manually start the level load here
ci.cancel();
}
@ -82,7 +76,7 @@ public abstract class MinecraftMixin {
}
@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, RegistryAccess registryAccess, WorldGenSettings worldGenSettings, CallbackInfo ci) {
DataExchangeAPI.prepareServerside();
BiomeAPI.prepareNewLevel();

View file

@ -2,9 +2,9 @@ package ru.bclib.mixin.client;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.FallbackResourceManager;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.SimpleReloadableResourceManager;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -18,14 +18,14 @@ import ru.bclib.client.render.EmissiveTextureInfo;
import java.io.IOException;
import java.util.Map;
@Mixin(SimpleReloadableResourceManager.class)
public class SimpleReloadableResourceManagerMixin {
@Mixin(MultiPackResourceManager.class)
public class MultiPackResourceManagerMixin {
@Final
@Shadow
private Map<String, FallbackResourceManager> namespacedPacks;
private Map<String, FallbackResourceManager> namespacedManagers;
private ResourceLocation bclib_alphaEmissionMaterial = BCLib.makeID("materialmaps/block/alpha_emission.json");
@Inject(method = "getResource", at = @At("HEAD"), cancellable = true)
private void bclib_getResource(ResourceLocation resourceLocation, CallbackInfoReturnable<Resource> info) throws IOException {
if (!ModIntegrationAPI.hasCanvas()) {
@ -37,15 +37,15 @@ public class SimpleReloadableResourceManagerMixin {
if (!resourceLocation.getPath().contains("/block/")) {
return;
}
String name = resourceLocation.getPath().replace("materialmaps/block/", "").replace(".json", "");
ResourceLocation blockID = new ResourceLocation(resourceLocation.getNamespace(), name);
if (!EmissiveTextureInfo.isEmissiveBlock(blockID)) {
return;
}
ResourceManager resourceManager = this.namespacedPacks.get(resourceLocation.getNamespace());
ResourceManager resourceManager = this.namespacedManagers.get(resourceLocation.getNamespace());
if (resourceManager != null && !resourceManager.hasResource(resourceLocation)) {
info.setReturnValue(resourceManager.getResource(bclib_alphaEmissionMaterial));
}

View file

@ -13,7 +13,7 @@ import ru.bclib.api.biomes.BiomeAPI;
@Mixin(WorldPreset.class)
public class WorldPresetMixin {
@Inject(method = "create", at = @At("HEAD"))
private void bclib_create(RegistryAccess.RegistryHolder registryHolder, long l, boolean bl, boolean bl2, CallbackInfoReturnable<WorldGenSettings> info) {
BiomeAPI.initRegistry(registryHolder.registryOrThrow(Registry.BIOME_REGISTRY));
private void bclib_create(RegistryAccess registryAccess, long l, boolean bl, boolean bl2, CallbackInfoReturnable<WorldGenSettings> info) {
BiomeAPI.initRegistry(registryAccess.registryOrThrow(Registry.BIOME_REGISTRY));
}
}

View file

@ -0,0 +1,13 @@
package ru.bclib.mixin.common;
import net.minecraft.world.level.biome.Biome;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(Biome.class)
public interface BiomeAccessor {
@Accessor("biomeCategory")
@Mutable
Biome.BiomeCategory bclib_getBiomeCategory();
}

View file

@ -1,9 +1,11 @@
package ru.bclib.mixin.common;
import net.minecraft.core.HolderSet;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
@ -17,21 +19,21 @@ import java.util.function.Supplier;
@Mixin(BiomeGenerationSettings.class)
public interface BiomeGenerationSettingsAccessor {
@Accessor("features")
List<List<Supplier<PlacedFeature>>> bclib_getFeatures();
List<HolderSet<PlacedFeature>> bclib_getFeatures();
@Accessor("features")
@Mutable
void bclib_setFeatures(List<List<Supplier<PlacedFeature>>> value);
void bclib_setFeatures(List<HolderSet<PlacedFeature>> value);
@Accessor("featureSet")
Set<PlacedFeature> bclib_getFeatureSet();
@Accessor("featureSet")
void bclib_setFeatureSet(Set<PlacedFeature> features);
void bclib_setFeatureSet(Supplier<Set<PlacedFeature>> featureSet);
@Accessor("flowerFeatures")
void bclib_setFlowerFeatures(Supplier<List<ConfiguredFeature<?, ?>>> flowerFeatures);
@Accessor("carvers")
Map<Carving, List<Supplier<ConfiguredWorldCarver<?>>>> bclib_getCarvers();
Map<GenerationStep.Carving, HolderSet<ConfiguredWorldCarver<?>>> bclib_getCarvers();
@Accessor("carvers")
void bclib_setCarvers(Map<GenerationStep.Carving, List<Supplier<ConfiguredWorldCarver<?>>>> features);
void bclib_setCarvers(Map<GenerationStep.Carving, HolderSet<ConfiguredWorldCarver<?>>> features);
}

View file

@ -1,5 +1,6 @@
package ru.bclib.mixin.common;
import com.google.common.base.Suppliers;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.BiomeSource.StepFeatureData;
@ -12,6 +13,7 @@ import ru.bclib.interfaces.BiomeSourceAccessor;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
@Mixin(BiomeSource.class)
public abstract class BiomeSourceMixin implements BiomeSourceAccessor {
@ -19,10 +21,10 @@ public abstract class BiomeSourceMixin implements BiomeSourceAccessor {
@Shadow public abstract Set<Biome> possibleBiomes();
@Mutable @Shadow @Final private List<StepFeatureData> featuresPerStep;
@Mutable @Shadow @Final private Supplier<List<StepFeatureData>> featuresPerStep;
public void bclRebuildFeatures(){
BCLib.LOGGER.info("Rebuilding features in BiomeSource " + this);
featuresPerStep = buildFeaturesPerStep(this.possibleBiomes().stream().toList(), true);
featuresPerStep = Suppliers.memoize(() -> buildFeaturesPerStep(this.possibleBiomes().stream().toList(), true));
}
}

View file

@ -1,17 +1,23 @@
package ru.bclib.mixin.common;
import net.minecraft.core.Registry;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import org.spongepowered.asm.mixin.Final;
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.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.bclib.interfaces.ChunkGeneratorAccessor;
@Mixin(ChunkGenerator.class)
public class ChunkGeneratorMixin {
public class ChunkGeneratorMixin implements ChunkGeneratorAccessor {
@Shadow @Final protected Registry<StructureSet> structureSets;
private int bclib_featureIteratorSeed;
@ModifyArg(method = "applyBiomeDecoration", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldgenRandom;setFeatureSeed(JII)V"))
@ -23,4 +29,8 @@ public class ChunkGeneratorMixin {
private void bclib_obBiomeGenerate(WorldGenLevel worldGenLevel, ChunkAccess chunkAccess, StructureFeatureManager structureFeatureManager, CallbackInfo ci) {
bclib_featureIteratorSeed = 0;
}
public Registry<StructureSet> bclib_getStructureSetsRegistry(){
return structureSets;
}
}

View file

@ -0,0 +1,21 @@
package ru.bclib.mixin.common;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.DiggerItem;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
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.gen.Accessor;
import java.util.List;
import java.util.function.Supplier;
@Mixin(DiggerItem.class)
public interface DiggerItemAccessor {
@Accessor("blocks")
@Mutable
TagKey<Block> bclib_getBlockTag();
}

View file

@ -4,12 +4,17 @@ import com.mojang.serialization.Lifecycle;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.WritableRegistry;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MultiNoiseBiomeSource;
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.structure.StructureSet;
import net.minecraft.world.level.levelgen.synth.NormalNoise;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -23,41 +28,42 @@ import java.util.OptionalInt;
@Mixin(DimensionType.class)
public class DimensionTypeMixin {
@Inject(
method = "defaultDimensions(Lnet/minecraft/core/RegistryAccess;JZ)Lnet/minecraft/core/MappedRegistry;",
method = "defaultDimensions(Lnet/minecraft/core/RegistryAccess;JZ)Lnet/minecraft/core/Registry;",
locals = LocalCapture.CAPTURE_FAILHARD,
at = @At("TAIL")
)
private static void bclib_updateDimensions(RegistryAccess registryAccess, long seed, boolean bl, CallbackInfoReturnable<MappedRegistry<LevelStem>> info, MappedRegistry<LevelStem> mappedRegistry, Registry<DimensionType> registry, Registry<Biome> biomeRegistry, Registry<NoiseGeneratorSettings> noiseSettingsRegistry, Registry<NormalNoise.NoiseParameters> noiseParamRegistry) {
int id = mappedRegistry.getId(mappedRegistry.get(LevelStem.NETHER));
mappedRegistry.registerOrOverride(
OptionalInt.of(id),
LevelStem.NETHER,
new LevelStem(
() -> registry.getOrThrow(DimensionType.NETHER_LOCATION),
new NoiseBasedChunkGenerator(
noiseParamRegistry,
new BCLibNetherBiomeSource(biomeRegistry, seed),
seed,
() -> noiseSettingsRegistry.getOrThrow(NoiseGeneratorSettings.NETHER)
)
),
Lifecycle.stable()
private static void bclib_updateDimensions(RegistryAccess registryAccess, long seed, boolean bl, CallbackInfoReturnable<Registry> info, WritableRegistry writableRegistry, Registry registry, Registry biomeRegistry, Registry structureRegistry, Registry noiseSettingsRegistry, Registry noiseParamRegistry) {
int id = writableRegistry.getId(writableRegistry.get(LevelStem.NETHER));
writableRegistry.registerOrOverride(
OptionalInt.of(id),
LevelStem.NETHER,
new LevelStem(
registry.getOrCreateHolder(DimensionType.NETHER_LOCATION),
new NoiseBasedChunkGenerator(
structureRegistry,
noiseParamRegistry,
new BCLibNetherBiomeSource(biomeRegistry, seed),
seed,
noiseSettingsRegistry.getOrCreateHolder(NoiseGeneratorSettings.NETHER))
),
Lifecycle.stable()
);
id = mappedRegistry.getId(mappedRegistry.get(LevelStem.END));
mappedRegistry.registerOrOverride(
OptionalInt.of(id),
LevelStem.END,
new LevelStem(
() -> registry.getOrThrow(DimensionType.END_LOCATION),
new NoiseBasedChunkGenerator(
noiseParamRegistry,
new BCLibEndBiomeSource(biomeRegistry, seed),
seed,
() -> noiseSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END)
)
),
Lifecycle.stable()
id = writableRegistry.getId(writableRegistry.get(LevelStem.END));
writableRegistry.registerOrOverride(
OptionalInt.of(id),
LevelStem.END,
new LevelStem(
registry.getOrCreateHolder(DimensionType.END_LOCATION),
new NoiseBasedChunkGenerator(
structureRegistry,
noiseParamRegistry,
new BCLibEndBiomeSource(biomeRegistry, seed),
seed,
noiseSettingsRegistry.getOrCreateHolder(NoiseGeneratorSettings.END))
),
Lifecycle.stable()
);
}
}

View file

@ -1,29 +0,0 @@
package ru.bclib.mixin.common;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.EnchantmentMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import ru.bclib.api.tag.CommonBlockTags;
@Mixin(EnchantmentMenu.class)
public abstract class EnchantmentMenuMixin extends AbstractContainerMenu {
protected EnchantmentMenuMixin(MenuType<?> type, int syncId) {
super(type, syncId);
}
@Redirect(method = "lambda$slotsChanged$0(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/state/BlockState;is(Lnet/minecraft/world/level/block/Block;)Z"),
require = -1,
expect = -1
)
private boolean bclib_isBookshelf(BlockState state, Block block) {
return block == Blocks.BOOKSHELF ? state.is(CommonBlockTags.BOOKSHELVES) : state.is(block);
}
}

View file

@ -3,10 +3,9 @@ package ru.bclib.mixin.common;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.datafixers.DataFixer;
import net.minecraft.core.RegistryAccess.RegistryHolder;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerResources;
import net.minecraft.server.WorldStem;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.server.packs.repository.PackRepository;
@ -32,7 +31,7 @@ import java.util.concurrent.CompletableFuture;
@Mixin(MinecraftServer.class)
public class MinecraftServerMixin {
@Shadow
private ServerResources resources;
private MinecraftServer.ReloadableResources resources;
@Final
@Shadow
@ -43,7 +42,7 @@ public class MinecraftServerMixin {
protected WorldData worldData;
@Inject(method = "<init>*", at = @At("TAIL"))
private void bclib_onServerInit(Thread thread, RegistryHolder registryHolder, LevelStorageAccess levelStorageAccess, WorldData worldData, PackRepository packRepository, Proxy proxy, DataFixer dataFixer, ServerResources serverResources, MinecraftSessionService minecraftSessionService, GameProfileRepository gameProfileRepository, GameProfileCache gameProfileCache, ChunkProgressListenerFactory chunkProgressListenerFactory, CallbackInfo ci) {
private void bclib_onServerInit(Thread thread, LevelStorageAccess levelStorageAccess, PackRepository packRepository, WorldStem worldStem, Proxy proxy, DataFixer dataFixer, MinecraftSessionService minecraftSessionService, GameProfileRepository gameProfileRepository, GameProfileCache gameProfileCache, ChunkProgressListenerFactory chunkProgressListenerFactory, CallbackInfo ci) {
DataExchangeAPI.prepareServerside();
}
@ -58,7 +57,7 @@ public class MinecraftServerMixin {
}
private void bclib_injectRecipes() {
RecipeManagerAccessor accessor = (RecipeManagerAccessor) resources.getRecipeManager();
RecipeManagerAccessor accessor = (RecipeManagerAccessor) resources.managers().getRecipeManager();
accessor.bclib_setRecipesByName(BCLRecipeManager.getMapByName(accessor.bclib_getRecipesByName()));
accessor.bclib_setRecipes(BCLRecipeManager.getMap(accessor.bclib_getRecipes()));
}

View file

@ -1,30 +1,21 @@
package ru.bclib.mixin.common;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.FallbackResourceManager;
import net.minecraft.server.packs.resources.SimpleReloadableResourceManager;
import org.spongepowered.asm.mixin.Final;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
@Mixin(SimpleReloadableResourceManager.class)
public class SimpleReloadableResourceManagerMixin {
@Final
@Shadow
private Map<String, FallbackResourceManager> namespacedPacks;
@Mixin(MultiPackResourceManager.class)
public class MultiPackResourceManagerMixin {
private static final String[] BCLIB_MISSING_RESOURCES = new String[] {
"dimension/the_end.json",
"dimension/the_nether.json",
"dimension_type/the_end.json",
"dimension_type/the_nether.json"
};
@Inject(method = "hasResource", at = @At("HEAD"), cancellable = true)
private void bclib_hasResource(ResourceLocation resourceLocation, CallbackInfoReturnable<Boolean> info) {
if (resourceLocation.getNamespace().equals("minecraft")) {

View file

@ -1,18 +1,15 @@
package ru.bclib.mixin.common;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.levelgen.Aquifer;
import net.minecraft.world.level.levelgen.Beardifier;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseChunk;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.NoiseSampler;
import net.minecraft.world.level.levelgen.*;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.carver.CarvingContext;
import org.spongepowered.asm.mixin.Final;
@ -30,11 +27,13 @@ import java.util.function.Supplier;
public abstract class NoiseBasedChunkGeneratorMixin implements SurfaceProvider, NoiseGeneratorSettingsProvider {
@Final
@Shadow
private NoiseSampler sampler;
private Climate.Sampler sampler;
@Shadow @Final private NoiseRouter router;
@Final
@Shadow
protected Supplier<NoiseGeneratorSettings> settings;
protected Holder<NoiseGeneratorSettings> settings;
@Final
@Shadow
@ -45,12 +44,12 @@ public abstract class NoiseBasedChunkGeneratorMixin implements SurfaceProvider,
@Override
public NoiseGeneratorSettings bclib_getNoiseGeneratorSettings(){
return settings.get();
return settings.value();
}
@Override
@SuppressWarnings("deprecation")
public BlockState bclib_getSurface(BlockPos pos, Biome biome, ServerLevel level) {
public BlockState bclib_getSurface(BlockPos pos, Holder<Biome> biome, ServerLevel level) {
ChunkAccess chunkAccess = level.getChunk(pos.getX() >> 4, pos.getZ() >> 4);
StructureFeatureManager structureFeatureManager = level.structureFeatureManager();
NoiseBasedChunkGenerator generator = NoiseBasedChunkGenerator.class.cast(this);
@ -72,7 +71,7 @@ public abstract class NoiseBasedChunkGeneratorMixin implements SurfaceProvider,
}
Beardifier finalBeardifier = beardifier;
NoiseChunk noiseChunk = chunkAccess.getOrCreateNoiseChunk(this.sampler, () -> finalBeardifier, this.settings.get(), this.globalFluidPicker, Blender.empty());
NoiseChunk noiseChunk = chunkAccess.getOrCreateNoiseChunk(router, () -> finalBeardifier, this.settings.value(), this.globalFluidPicker, Blender.empty());
CarvingContext carvingContext = new CarvingContext(generator, level.registryAccess(), chunkAccess.getHeightAccessorForGeneration(), noiseChunk);
Optional<BlockState> optional = carvingContext.topMaterial(bpos -> biome, chunkAccess, pos, false);
return optional.isPresent() ? optional.get() : bclib_air;

View file

@ -26,14 +26,14 @@ public class NoiseGeneratorSettingsMixin implements SurfaceRuleProvider {
private SurfaceRules.RuleSource bclib_originalSurfaceRule;
private Set<BiomeSource> bclib_biomeSources = new HashSet<>();
private void bclib_updateCutomRules(){
private void bclib_updateCustomRules(){
bclib_setCustomRules(BiomeAPI.getRuleSources(bclib_biomeSources));
}
@Override
public void bclib_addBiomeSource(BiomeSource source) {
bclib_biomeSources.add(source);
bclib_updateCutomRules();
bclib_updateCustomRules();
}
@Override

View file

@ -27,7 +27,7 @@ public abstract class RecipeManagerMixin {
}
@Inject(method = "getRecipeFor", at = @At(value = "HEAD"), cancellable = true)
private <C extends Container, T extends Recipe<C>> void bclib_getRecipeFor(RecipeType<T> type, C inventory, Level world, CallbackInfoReturnable<Optional<T>> info) {
private <C extends Container, T extends Recipe<C>> void bclib_getRecipeFor(RecipeType<T> type, C inventory, Level level, CallbackInfoReturnable<Optional<T>> info) {
Collection<Recipe<C>> values = byType(type).values();
List<Recipe<C>> list = new ArrayList<>(values);
list.sort((v1, v2) -> {
@ -35,6 +35,6 @@ public abstract class RecipeManagerMixin {
boolean b2 = v2.getId().getNamespace().equals("minecraft");
return b1 ^ b2 ? (b1 ? 1 : -1) : 0;
});
info.setReturnValue(list.stream().flatMap((recipe) -> Util.toStream(type.tryMatch(recipe, world, inventory))).findFirst());
info.setReturnValue(list.stream().flatMap(recipe -> type.tryMatch(recipe, level, inventory).stream()).findFirst());
}
}

View file

@ -1,5 +1,6 @@
package ru.bclib.mixin.common;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
@ -9,6 +10,7 @@ import net.minecraft.world.level.CustomSpawner;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData;
@ -28,12 +30,12 @@ import java.util.function.Supplier;
public abstract class ServerLevelMixin extends Level {
private static String bclib_lastWorld = null;
protected ServerLevelMixin(WritableLevelData writableLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, Supplier<ProfilerFiller> supplier, boolean bl, boolean bl2, long l) {
protected ServerLevelMixin(WritableLevelData writableLevelData, ResourceKey<Level> resourceKey, Holder<DimensionType> dimensionType, Supplier<ProfilerFiller> supplier, boolean bl, boolean bl2, long l) {
super(writableLevelData, resourceKey, dimensionType, supplier, bl, bl2, l);
}
@Inject(method = "<init>*", at = @At("TAIL"))
private void bclib_onServerWorldInit(MinecraftServer server, Executor executor, LevelStorageAccess levelStorageAccess, ServerLevelData serverLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, ChunkProgressListener chunkProgressListener, ChunkGenerator chunkGenerator, boolean bl, long l, List<CustomSpawner> list, boolean bl2, CallbackInfo info) {
private void bclib_onServerWorldInit(MinecraftServer server, Executor executor, LevelStorageAccess levelStorageAccess, ServerLevelData serverLevelData, ResourceKey resourceKey, Holder<DimensionType> dimensionType, ChunkProgressListener chunkProgressListener, ChunkGenerator chunkGenerator, boolean bl, long l, List list, boolean bl2, CallbackInfo ci) {
ServerLevel level = ServerLevel.class.cast(this);
LifeCycleAPI._runLevelLoad(level, server, executor, levelStorageAccess, serverLevelData, resourceKey, dimensionType, chunkProgressListener, chunkGenerator, bl, l, list, bl2);

View file

@ -0,0 +1,14 @@
package ru.bclib.mixin.common;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(StructureFeature.class)
public interface StructureFeatureAccessor {
@Invoker
static <F extends StructureFeature<?>> F callRegister(String name, F structureFeature, GenerationStep.Decoration step) {
throw new RuntimeException("Unexpected call");
}
}

View file

@ -0,0 +1,19 @@
package ru.bclib.mixin.common;
import net.minecraft.core.Holder;
import net.minecraft.data.worldgen.StructureFeatures;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(StructureFeatures.class)
public interface StructureFeaturesAccessor {
@Invoker
static <FC extends FeatureConfiguration, F extends StructureFeature<FC>> Holder<ConfiguredStructureFeature<?, ?>> callRegister(ResourceKey<ConfiguredStructureFeature<?, ?>> resourceKey, ConfiguredStructureFeature<FC, F> configuredStructureFeature) {
throw new RuntimeException("Unexpected call");
}
}

View file

@ -1,32 +0,0 @@
package ru.bclib.mixin.common;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.StructureSettings;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.feature.configurations.StructureFeatureConfiguration;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Map;
@Mixin(StructureSettings.class)
public interface StructureSettingsAccessor {
@Accessor("configuredStructures")
ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> bcl_getConfiguredStructures();
@Accessor("structureConfig")
Map<StructureFeature<?>, StructureFeatureConfiguration> bcl_getStructureConfig();
@Accessor("configuredStructures")
@Mutable
void bcl_setConfiguredStructures(ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> configuredStructures);
@Accessor("structureConfig")
@Mutable
void bcl_setStructureConfig(Map<StructureFeature<?>, StructureFeatureConfiguration> structureConfig);
}

View file

@ -1,5 +1,6 @@
package ru.bclib.mixin.common;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkAccess;
@ -25,10 +26,7 @@ public interface SurfaceRulesContextAccessor {
int getSurfaceDepth();
@Accessor("biome")
Supplier<Biome> getBiome();
@Accessor("biomeKey")
Supplier<ResourceKey<Biome>> getBiomeKey();
Supplier<Holder<Biome>> getBiome();
@Accessor("chunk")
ChunkAccess getChunk();

View file

@ -3,6 +3,7 @@ package ru.bclib.mixin.common;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagLoader;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -13,10 +14,11 @@ import java.util.Map;
@Mixin(TagLoader.class)
public class TagLoaderMixin {
@Final
@Shadow
private String directory;
@ModifyArg(method = "loadAndBuild", at = @At(value = "INVOKE", target = "Lnet/minecraft/tags/TagLoader;build(Ljava/util/Map;)Lnet/minecraft/tags/TagCollection;"))
@ModifyArg(method = "loadAndBuild", at = @At(value = "INVOKE", target = "Lnet/minecraft/tags/TagLoader;build(Ljava/util/Map;)Ljava/util/Map;"))
public Map<ResourceLocation, Tag.Builder> be_modifyTags(Map<ResourceLocation, Tag.Builder> tagsMap) {
return TagAPI.apply(directory, tagsMap);
}

View file

@ -1,6 +1,5 @@
package ru.bclib.mixin.common.shears;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.advancements.critereon.ItemPredicate;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@ -24,7 +23,7 @@ public abstract class ItemPredicateBuilderMixin {
@Inject(method = "matches", at = @At("HEAD"), cancellable = true)
void bclib_of(ItemStack itemStack, CallbackInfoReturnable<Boolean> cir) {
if (this.items != null && this.items.size() == 1 && this.items.contains(Items.SHEARS)) {
if (itemStack.is(CommonItemTags.SHEARS) || itemStack.is(FabricToolTags.SHEARS)){
if (itemStack.is(CommonItemTags.SHEARS) ){
cir.setReturnValue(true);
}
}

View file

@ -4,12 +4,16 @@ import com.google.gson.JsonObject;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.minecraft.core.NonNullList;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.TagParser;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.Container;
import net.minecraft.world.InteractionHand;
@ -42,6 +46,10 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
);
public final static ResourceLocation ID = BCLib.makeID(GROUP);
public static void register(){
}
private final ResourceLocation id;
private final Ingredient input;
private final ItemStack output;
@ -116,7 +124,8 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
public boolean matches(Container craftingInventory) {
ItemStack hammer = craftingInventory.getItem(1);
if (hammer.isEmpty() || !CommonItemTags.HAMMERS.contains(hammer.getItem())) {
//TODO: 1.18.2 Test if hammer still works
if (hammer.isEmpty() || !hammer.is(CommonItemTags.HAMMERS)) {
return false;
}
ItemStack material = craftingInventory.getItem(0);
@ -139,12 +148,13 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
@Override
public NonNullList<Ingredient> getIngredients() {
;
NonNullList<Ingredient> defaultedList = NonNullList.create();
defaultedList.add(Ingredient.of(CommonItemTags.HAMMERS
.getValues()
.stream()
.filter(hammer -> ((TieredItem) hammer).getTier().getLevel() >= toolLevel)
.map(ItemStack::new)));
defaultedList.add(Ingredient.of(Registry.ITEM.stream()
.filter(item->item.builtInRegistryHolder().is(CommonItemTags.HAMMERS))
.filter(hammer -> ((TieredItem) hammer).getTier().getLevel() >= toolLevel)
.map(ItemStack::new))
);
defaultedList.add(input);
return defaultedList;
}
@ -209,7 +219,7 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
return this;
}
public Builder setInput(Tag<Item> inputTag) {
public Builder setInput(TagKey<Item> inputTag) {
this.setInput(Ingredient.of(inputTag));
return this;
}

View file

@ -4,6 +4,7 @@ import com.google.common.collect.Maps;
import net.minecraft.core.NonNullList;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.CraftingRecipe;
@ -74,7 +75,7 @@ public class GridRecipe {
return this;
}
public GridRecipe addMaterial(char key, Tag<Item> value) {
public GridRecipe addMaterial(char key, TagKey<Item> value) {
return addMaterial(key, Ingredient.of(value));
}

View file

@ -2,6 +2,7 @@ package ru.bclib.recipes;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
@ -59,7 +60,7 @@ public class SmithingTableRecipe {
return this;
}
public SmithingTableRecipe setBase(Tag<Item> tag) {
public SmithingTableRecipe setBase(TagKey<Item> tag) {
this.base = (Ingredient.of(tag));
return this;
}
@ -70,7 +71,7 @@ public class SmithingTableRecipe {
return this;
}
public SmithingTableRecipe setAddition(Tag<Item> tag) {
public SmithingTableRecipe setAddition(TagKey<Item> tag) {
this.addition = (Ingredient.of(tag));
return this;
}

View file

@ -44,8 +44,8 @@ public class ItemRegistry extends BaseRegistry<Item> {
if (!config.getBoolean("musicDiscs", itemId.getPath(), true)) {
return item;
}
return register(itemId, new BaseDiscItem(power, sound, makeItemSettings().stacksTo(1)));
register(itemId, item);
return item;
}
public Item register(ResourceLocation itemId) {

View file

@ -2,10 +2,13 @@ package ru.bclib.world.biomes;
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.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.SurfaceRules;
@ -15,25 +18,25 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.jetbrains.annotations.Nullable;
import ru.bclib.BCLib;
import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.util.WeightedList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class BCLBiome extends BCLBiomeSettings {
private final List<ConfiguredStructureFeature> structures = Lists.newArrayList();
private final Set<TagKey<Biome>> structureTags = Sets.newHashSet();
private final WeightedList<BCLBiome> subbiomes = new WeightedList<>();
private final Map<String, Object> customData = Maps.newHashMap();
private final ResourceLocation biomeID;
private final Biome biome;
private Consumer<Biome> surfaceInit;
private Consumer<Holder<Biome>> surfaceInit;
private BCLBiome biomeParent;
private Biome actualBiome;
private Holder<Biome> actualBiome;
/**
* Create wrapper for existing biome using its {@link ResourceLocation} identifier.
@ -65,7 +68,7 @@ public class BCLBiome extends BCLBiomeSettings {
* @param settings The Settings for this Biome or {@code null} if you want to apply default settings
*/
public BCLBiome(Biome biome, VanillaBiomeSettings settings) {
this(BuiltinRegistries.BIOME.getKey(biome), biome, settings);
this(BiomeAPI.getBiomeID(biome), biome, settings);
}
public BCLBiome(ResourceLocation biomeID, Biome biome) {
@ -164,7 +167,10 @@ public class BCLBiome extends BCLBiomeSettings {
return biomeID;
}
public Holder<Biome> getBiomeHolder() {
return BuiltinRegistries.BIOME.getOrCreateHolder(BiomeAPI.getBiomeKey(biome));
}
/**
* Getter for biome from buil-in registry. For datapack biomes will be same as actual biome.
* @return {@link Biome}.
@ -177,7 +183,7 @@ public class BCLBiome extends BCLBiomeSettings {
* Getter for actual biome (biome from current world registry with same {@link ResourceLocation} id).
* @return {@link Biome}.
*/
public Biome getActualBiome() {
public Holder<Biome> getActualBiome() {
return this.actualBiome;
}
@ -196,19 +202,23 @@ public class BCLBiome extends BCLBiomeSettings {
if (edge != null && edge != this) {
edge.updateActualBiomes(biomeRegistry);
}
this.actualBiome = biomeRegistry.get(biomeID);
final ResourceKey<Biome> key = biomeRegistry.getResourceKey(biomeRegistry.get(biomeID)).orElseThrow();
this.actualBiome = biomeRegistry.getOrCreateHolder(key);
if (actualBiome==null) {
BCLib.LOGGER.error("Unable to find actual Biome for " + biomeID);
}
if (!this.structures.isEmpty()) {
structures.forEach(s -> BiomeAPI.addBiomeStructure(BiomeAPI.getBiomeKey(actualBiome), s));
if (!this.structureTags.isEmpty()) {
structureTags.forEach(tagKey -> TagAPI.addBiomeTag(tagKey, actualBiome.value()));
}
if (this.surfaceInit != null) {
surfaceInit.accept(actualBiome);
}
}
/**
* Getter for custom data. Will get custom data object or null if object doesn't exists.
@ -276,8 +286,8 @@ public class BCLBiome extends BCLBiomeSettings {
* Adds structures to this biome. For internal use only.
* Used inside {@link ru.bclib.api.biomes.BCLBiomeBuilder}.
*/
public void attachStructures(List<ConfiguredStructureFeature> structures) {
this.structures.addAll(structures);
public void attachStructures(List<TagKey<Biome>> structures) {
this.structureTags.addAll(structures);
}
/**
@ -295,25 +305,7 @@ public class BCLBiome extends BCLBiomeSettings {
}
};
}
private Map<Decoration, List<Supplier<PlacedFeature>>> features = new HashMap<>(0);
/**
* Sets the biome features.
* @param features the feature list.
*/
public void setFeatures(Map<Decoration, List<Supplier<PlacedFeature>>> features) {
this.features = features;
}
/**
* Returns the built-in set of Features for this biome (as they were set with {@link #setFeatures(Map)})
* @return List of all features
*/
public Map<Decoration, List<Supplier<PlacedFeature>>> getFeatures(){
return features;
}
/**
* Returns the group used in the config Files for this biome
*

View file

@ -1,40 +1,59 @@
package ru.bclib.world.features;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.data.worldgen.features.FeatureUtils;
import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.VerticalAnchor;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.HeightRangePlacement;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import ru.bclib.api.features.BCLCommonFeatures;
import java.util.Map.Entry;
import java.util.Optional;
public class BCLFeature {
private PlacedFeature placedFeature;
private Decoration featureStep;
private Feature<?> feature;
public BCLFeature(ResourceLocation id, Feature<?> feature, Decoration featureStep, PlacedFeature placedFeature) {
private final Holder<PlacedFeature> placedFeature;
private final Decoration featureStep;
private final Feature<?> feature;
public<FC extends FeatureConfiguration, F extends Feature<FC>> BCLFeature(ResourceLocation id, F feature, Decoration featureStep, FC configuration, PlacementModifier[] modifiers) {
this(id, feature, featureStep, buildPlacedFeature(id, feature, configuration, modifiers));
}
public BCLFeature(ResourceLocation id, Feature<?> feature, Decoration featureStep, Holder<PlacedFeature> placedFeature) {
this.placedFeature = placedFeature;
this.featureStep = featureStep;
this.feature = feature;
if (!BuiltinRegistries.PLACED_FEATURE.containsKey(id)) {
Registry.register(BuiltinRegistries.PLACED_FEATURE, id, placedFeature);
Registry.register(BuiltinRegistries.PLACED_FEATURE, id, placedFeature.value());
}
if (!Registry.FEATURE.containsKey(id) && !containsObj(Registry.FEATURE, feature)) {
Registry.register(Registry.FEATURE, id, feature);
}
}
private static <FC extends FeatureConfiguration, F extends Feature<FC>> Holder<PlacedFeature> buildPlacedFeature(ResourceLocation id, F feature, FC configuration, PlacementModifier[] modifiers) {
Holder<ConfiguredFeature<?, ?>> configuredFeature;
if (!BuiltinRegistries.CONFIGURED_FEATURE.containsKey(id)) {
configuredFeature = (Holder<ConfiguredFeature<?, ?>>)(Object)FeatureUtils.register(id.toString(), feature, configuration);
} else {
configuredFeature = BuiltinRegistries.CONFIGURED_FEATURE.getHolder(ResourceKey.create(BuiltinRegistries.CONFIGURED_FEATURE.key(), id)).orElseThrow();
}
if (!BuiltinRegistries.PLACED_FEATURE.containsKey(id)) {
return PlacementUtils.register(id.toString(), configuredFeature, modifiers);
} else {
return BuiltinRegistries.PLACED_FEATURE.getHolder(ResourceKey.create(BuiltinRegistries.PLACED_FEATURE.key(), id)).orElseThrow();
}
}
private static <E> boolean containsObj(Registry<E> registry, E obj) {
Optional<Entry<ResourceKey<E>, E>> optional = registry
@ -57,7 +76,7 @@ public class BCLFeature {
* Get configured feature.
* @return {@link PlacedFeature}.
*/
public PlacedFeature getPlacedFeature() {
public Holder<PlacedFeature> getPlacedFeature() {
return placedFeature;
}
@ -68,92 +87,4 @@ public class BCLFeature {
public Decoration getDecoration() {
return featureStep;
}
/**
* Deprecated, use function from {@link BCLCommonFeatures} instead.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeVegetationFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int density) {
return BCLCommonFeatures.makeVegetationFeature(id, feature, density);
}
/**
* Deprecated, use function from {@link BCLCommonFeatures} instead.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeVegetationFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int density, boolean allHeight) {
return BCLCommonFeatures.makeVegetationFeature(id, feature, density, allHeight);
}
/**
* Deprecated, moved to {@link BCLCommonFeatures}. Will be completely removed.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, float airDiscardChance, VerticalAnchor minY, VerticalAnchor maxY, boolean rare) {
return BCLCommonFeatures.makeOreFeature(id, blockOre, hostBlock, veins, veinSize, airDiscardChance, HeightRangePlacement.uniform(minY, maxY), rare);
}
/**
* Deprecated, moved to {@link BCLCommonFeatures}. Will be completely removed.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, VerticalAnchor minY, VerticalAnchor maxY, boolean rare) {
return BCLCommonFeatures.makeOreFeature(id, blockOre, hostBlock, veins, veinSize, 0.0f, HeightRangePlacement.uniform(minY, maxY), rare);
}
/**
* Deprecated, use function from {@link BCLCommonFeatures} instead.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, float airDiscardChance, PlacementModifier placement, boolean rare) {
return BCLCommonFeatures.makeOreFeature(id, blockOre, hostBlock, veins, veinSize, airDiscardChance, placement, rare);
}
/**
* Deprecated, use function from {@link BCLCommonFeatures} instead.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, PlacementModifier placement, boolean rare) {
return BCLCommonFeatures.makeOreFeature(id, blockOre, hostBlock, veins, veinSize, 0.0f, placement, rare);
}
/**
* Deprecated, use function from {@link BCLCommonFeatures} instead.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeChunkFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature) {
return BCLCommonFeatures.makeChunkFeature(id, step, feature);
}
/**
* Deprecated, use function from {@link BCLCommonFeatures} instead.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeChancedFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature, int chance) {
return BCLCommonFeatures.makeChancedFeature(id, step, feature, chance);
}
/**
* Deprecated, use function from {@link BCLCommonFeatures} instead.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeCountFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature, int count) {
return BCLCommonFeatures.makeCountFeature(id, step, feature, count);
}
/**
* Deprecated, use {@link ru.bclib.api.features.BCLFeatureBuilder} instead.
*
* Creates and configures new BCLib feature.
* @param id {@link ResourceLocation} feature ID.
* @param step {@link Decoration} feature step.
* @param feature {@link Feature} with {@link NoneFeatureConfiguration} config.
* @param placementModifiers array of {@link PlacementModifier}
* @return new BCLFeature instance.
*/
@Deprecated(forRemoval = true)
public static BCLFeature makeFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature, PlacementModifier... placementModifiers) {
PlacedFeature configured = feature.configured(FeatureConfiguration.NONE).placed(placementModifiers);
return new BCLFeature(id, feature, step, configured);
}
}

View file

@ -3,6 +3,7 @@ package ru.bclib.world.features;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
@ -50,7 +51,7 @@ public abstract class NBTStructureFeature extends DefaultFeature {
protected abstract void addStructureData(StructurePlaceSettings data);
protected BlockPos getGround(WorldGenLevel world, BlockPos center) {
Biome biome = world.getBiome(center);
Holder<Biome> biome = world.getBiome(center);
ResourceLocation id = BiomeAPI.getBiomeID(biome);
if (id.getNamespace().contains("moutain") || id.getNamespace().contains("lake")) {
int y = getAverageY(world, center);
@ -148,7 +149,7 @@ public abstract class NBTStructureFeature extends DefaultFeature {
if (!isTerrain(stateSt)) {
if (merge == TerrainMerge.SURFACE) {
boolean isTop = mut.getY() == surfMax && state.getMaterial().isSolidBlocking();
Biome b = world.getBiome(mut);
Holder<Biome> b = world.getBiome(mut);
BlockState top = (isTop ? BiomeAPI.findTopMaterial(b) : BiomeAPI.findUnderMaterial(b)).orElse(defaultBlock);
BlocksHelper.setWithoutUpdate(world, mut, top);
}
@ -159,7 +160,7 @@ public abstract class NBTStructureFeature extends DefaultFeature {
else {
if (isTerrain(state) && state.getMaterial().isSolidBlocking()) {
if (merge == TerrainMerge.SURFACE) {
Biome b = world.getBiome(mut);
Holder<Biome> b = world.getBiome(mut);
BlockState bottom = BiomeAPI.findUnderMaterial(b).orElse(defaultBlock);
BlocksHelper.setWithoutUpdate(world, mut, bottom);
}

View file

@ -1,5 +1,6 @@
package ru.bclib.world.generator;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
@ -11,12 +12,12 @@ public abstract class BCLBiomeSource extends BiomeSource {
protected final Registry<Biome> biomeRegistry;
protected final long seed;
private static List<Biome> preInit(Registry<Biome> biomeRegistry, List<Biome> biomes){
private static List<Holder<Biome>> preInit(Registry<Biome> biomeRegistry, List<Holder<Biome>> biomes){
biomes.forEach(biome -> BiomeAPI.sortBiomeFeatures(biome));
return biomes;
}
protected BCLBiomeSource(Registry<Biome> biomeRegistry, long seed, List<Biome> list) {
protected BCLBiomeSource(Registry<Biome> biomeRegistry, long seed, List<Holder<Biome>> list) {
super(preInit(biomeRegistry, list));
this.seed = seed;

View file

@ -1,9 +1,13 @@
package ru.bclib.world.generator;
import com.mojang.datafixers.kinds.Applicative;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.RegistryLookupCodec;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biome.BiomeCategory;
@ -19,6 +23,7 @@ import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.config.ConfigKeeper.StringArrayEntry;
import ru.bclib.config.Configs;
import ru.bclib.interfaces.BiomeMap;
import ru.bclib.mixin.common.BiomeAccessor;
import ru.bclib.noise.OpenSimplexNoise;
import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.generator.map.hex.HexBiomeMap;
@ -29,19 +34,13 @@ import java.util.List;
import java.util.function.Function;
public class BCLibEndBiomeSource extends BCLBiomeSource {
public static final Codec<BCLibEndBiomeSource> CODEC = RecordCodecBuilder.create((instance) -> {
return instance.group(RegistryLookupCodec.create(Registry.BIOME_REGISTRY).forGetter((theEndBiomeSource) -> {
return theEndBiomeSource.biomeRegistry;
}), Codec.LONG.fieldOf("seed").stable().forGetter((theEndBiomeSource) -> {
return theEndBiomeSource.seed;
})).apply(instance, instance.stable(BCLibEndBiomeSource::new));
});
public static Codec<BCLibEndBiomeSource> CODEC = RecordCodecBuilder.create((instance) -> instance.group(RegistryOps.retrieveRegistry(Registry.BIOME_REGISTRY).forGetter((theEndBiomeSource) -> null), Codec.LONG.fieldOf("seed").stable().forGetter((theEndBiomeSource) -> theEndBiomeSource.seed)).apply(instance, instance.stable(BCLibEndBiomeSource::new)));
private static final OpenSimplexNoise SMALL_NOISE = new OpenSimplexNoise(8324);
private Function<Point, Boolean> endLandFunction;
private final SimplexNoise noise;
private final Biome centerBiome;
private final Biome barrens;
private final Holder<Biome> centerBiome;
private final Holder<Biome> barrens;
private BiomeMap mapLand;
private BiomeMap mapVoid;
private final Point pos;
@ -54,11 +53,11 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include", "end_void_biomes", StringArrayEntry.class).getValue();
this.possibleBiomes().forEach(biome -> {
ResourceLocation key = biomeRegistry.getKey(biome);
ResourceLocation key = biome.unwrapKey().orElseThrow().location();
String group = key.getNamespace() + "." + key.getPath();
if (!BiomeAPI.hasBiome(key)) {
BCLBiome bclBiome = new BCLBiome(key, biome);
BCLBiome bclBiome = new BCLBiome(key, biome.value());
if (includeVoid.contains(key.toString())) {
BiomeAPI.END_VOID_BIOME_PICKER.addBiomeMutable(bclBiome);
@ -99,8 +98,8 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
this.mapVoid = new HexBiomeMap(seed, GeneratorOptions.getBiomeSizeEndVoid(), BiomeAPI.END_VOID_BIOME_PICKER);
}
this.centerBiome = biomeRegistry.getOrThrow(Biomes.THE_END);
this.barrens = biomeRegistry.getOrThrow(Biomes.END_BARRENS);
this.centerBiome = biomeRegistry.getOrCreateHolder(Biomes.THE_END);
this.barrens = biomeRegistry.getOrCreateHolder(Biomes.END_BARRENS);
WorldgenRandom chunkRandom = new WorldgenRandom(new LegacyRandomSource(seed));
chunkRandom.consumeCount(17292);
@ -110,34 +109,44 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
this.pos = new Point();
}
private static List<Biome> getBiomes(Registry<Biome> biomeRegistry) {
private static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry) {
List<String> includeLand = Configs.BIOMES_CONFIG.getEntry("force_include", "end_land_biomes", StringArrayEntry.class).getValue();
List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include", "end_void_biomes", StringArrayEntry.class).getValue();
return biomeRegistry.stream().filter(biome -> {
ResourceLocation key = biomeRegistry.getKey(biome);
if (includeLand.contains(key.toString()) || includeVoid.contains(key.toString())) {
return true;
}
if (GeneratorOptions.addEndBiomesByCategory() && biome.getBiomeCategory() == BiomeCategory.THEEND) {
return true;
}
BCLBiome bclBiome = BiomeAPI.getBiome(key);
if (bclBiome != BiomeAPI.EMPTY_BIOME) {
if (bclBiome.getParentBiome() != null) {
bclBiome = bclBiome.getParentBiome();
}
key = bclBiome.getID();
}
return BiomeAPI.END_LAND_BIOME_PICKER.containsImmutable(key) || BiomeAPI.END_VOID_BIOME_PICKER.containsImmutable(key) || (biome.getBiomeCategory() == BiomeCategory.THEEND && BiomeAPI.isDatapackBiome(key));
return biomeRegistry.stream()
.filter(biome -> biomeRegistry.getResourceKey(biome).isPresent())
.map(biome -> biomeRegistry.getOrCreateHolder(biomeRegistry.getResourceKey(biome).get()))
.filter(biome -> {
ResourceLocation key = biome.unwrapKey().orElseThrow().location();
if (includeLand.contains(key.toString()) || includeVoid.contains(key.toString())) {
return true;
}
final boolean isEndBiome;
if ((Object)biome instanceof BiomeAccessor bacc) {
isEndBiome = bacc.bclib_getBiomeCategory() == BiomeCategory.THEEND;
if (GeneratorOptions.addEndBiomesByCategory() && isEndBiome) {
return true;
}
} else {
isEndBiome = false;
}
BCLBiome bclBiome = BiomeAPI.getBiome(key);
if (bclBiome != BiomeAPI.EMPTY_BIOME) {
if (bclBiome.getParentBiome() != null) {
bclBiome = bclBiome.getParentBiome();
}
key = bclBiome.getID();
}
return BiomeAPI.END_LAND_BIOME_PICKER.containsImmutable(key) || BiomeAPI.END_VOID_BIOME_PICKER.containsImmutable(key) || (isEndBiome && BiomeAPI.isDatapackBiome(key));
}).toList();
}
@Override
public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) {
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) {
long posX = biomeX << 2;
long posZ = biomeZ << 2;
long farEndBiomes = GeneratorOptions.getFarEndBiomes();

View file

@ -2,8 +2,10 @@ package ru.bclib.world.generator;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.RegistryLookupCodec;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biome.BiomeCategory;
@ -15,6 +17,7 @@ import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.config.ConfigKeeper.StringArrayEntry;
import ru.bclib.config.Configs;
import ru.bclib.interfaces.BiomeMap;
import ru.bclib.mixin.common.BiomeAccessor;
import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.generator.map.MapStack;
import ru.bclib.world.generator.map.hex.HexBiomeMap;
@ -23,13 +26,22 @@ import ru.bclib.world.generator.map.square.SquareBiomeMap;
import java.util.List;
public class BCLibNetherBiomeSource extends BCLBiomeSource {
public static final Codec<BCLibNetherBiomeSource> CODEC = RecordCodecBuilder.create((instance) -> {
return instance.group(RegistryLookupCodec.create(Registry.BIOME_REGISTRY).forGetter((theEndBiomeSource) -> {
return theEndBiomeSource.biomeRegistry;
}), Codec.LONG.fieldOf("seed").stable().forGetter((theEndBiomeSource) -> {
return theEndBiomeSource.seed;
})).apply(instance, instance.stable(BCLibNetherBiomeSource::new));
});
public static final Codec<BCLibNetherBiomeSource> CODEC = RecordCodecBuilder
.create(instance -> instance
.group(RegistryOps
.retrieveRegistry(Registry.BIOME_REGISTRY)
.forGetter(source -> source.biomeRegistry)
,
Codec
.LONG
.fieldOf("seed")
.stable()
.forGetter(source -> source.seed)
)
.apply(instance, instance.stable(BCLibNetherBiomeSource::new))
);
private BiomeMap biomeMap;
private static boolean forceLegacyGenerator = false;
@ -61,10 +73,10 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
BiomeAPI.NETHER_BIOME_PICKER.clearMutables();
this.possibleBiomes().forEach(biome -> {
ResourceLocation key = biomeRegistry.getKey(biome);
ResourceLocation key = biome.unwrapKey().orElseThrow().location();
if (!BiomeAPI.hasBiome(key)) {
BCLBiome bclBiome = new BCLBiome(key, biome);
BCLBiome bclBiome = new BCLBiome(key, biome.value());
BiomeAPI.NETHER_BIOME_PICKER.addBiomeMutable(bclBiome);
}
else {
@ -85,33 +97,42 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
initMap();
}
private static List<Biome> getBiomes(Registry<Biome> biomeRegistry) {
private static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry) {
List<String> include = Configs.BIOMES_CONFIG.getEntry("force_include", "nether_biomes", StringArrayEntry.class).getValue();
return biomeRegistry.stream().filter(biome -> {
ResourceLocation key = biomeRegistry.getKey(biome);
if (include.contains(key.toString())) {
return true;
}
if (GeneratorOptions.addNetherBiomesByCategory() && biome.getBiomeCategory() == BiomeCategory.NETHER) {
return true;
}
BCLBiome bclBiome = BiomeAPI.getBiome(key);
if (bclBiome != BiomeAPI.EMPTY_BIOME) {
if (bclBiome.getParentBiome() != null) {
bclBiome = bclBiome.getParentBiome();
}
key = bclBiome.getID();
}
return BiomeAPI.NETHER_BIOME_PICKER.containsImmutable(key) || (biome.getBiomeCategory() == BiomeCategory.NETHER && BiomeAPI.isDatapackBiome(key));
return biomeRegistry.stream()
.filter(biome -> biomeRegistry.getResourceKey(biome).isPresent())
.map(biome -> biomeRegistry.getOrCreateHolder(biomeRegistry.getResourceKey(biome).get()))
.filter(biome -> {
ResourceLocation key = biome.unwrapKey().orElseThrow().location();
if (include.contains(key.toString())) {
return true;
}
if (GeneratorOptions.addNetherBiomesByCategory() && (biome instanceof BiomeAccessor) && ((BiomeAccessor)(Object)biome).bclib_getBiomeCategory()== BiomeCategory.NETHER) {
return true;
}
BCLBiome bclBiome = BiomeAPI.getBiome(key);
if (bclBiome != BiomeAPI.EMPTY_BIOME) {
if (bclBiome.getParentBiome() != null) {
bclBiome = bclBiome.getParentBiome();
}
key = bclBiome.getID();
}
final boolean isNetherBiome;
if ((Object)biome instanceof BiomeAccessor bacc) {
isNetherBiome = bacc.bclib_getBiomeCategory() == BiomeCategory.NETHER;
} else {
isNetherBiome = false;
}
return BiomeAPI.NETHER_BIOME_PICKER.containsImmutable(key) || (isNetherBiome && BiomeAPI.isDatapackBiome(key));
}).toList();
}
@Override
public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler var4) {
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler var4) {
if (lastWorldHeight != worldHeight) {
lastWorldHeight = worldHeight;
initMap();

View file

@ -1,17 +1,27 @@
package ru.bclib.world.structures;
import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.structure.v1.FabricStructureBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.QuartPos;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.core.Registry;
import net.minecraft.data.worldgen.StructureSets;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier;
import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement;
import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadType;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.mixin.common.StructureFeatureAccessor;
import ru.bclib.mixin.common.StructureFeaturesAccessor;
import java.util.List;
import java.util.Random;
@ -19,23 +29,40 @@ import java.util.Random;
public class BCLStructureFeature {
private static final Random RANDOM = new Random(354);
private final StructureFeature<NoneFeatureConfiguration> structure;
private final ConfiguredStructureFeature<?, ?> featureConfigured;
private final Holder<ConfiguredStructureFeature<?, ?>> featureConfigured;
private final GenerationStep.Decoration featureStep;
private final List<ResourceLocation> biomes = Lists.newArrayList();
private final ResourceLocation id;
public final TagKey<Biome> biomeTag;
public final ResourceKey<ConfiguredStructureFeature<?, ?>> structureKey;
public final ResourceKey<StructureSet> structureSetKey;
public final RandomSpreadStructurePlacement spreadConfig;
public BCLStructureFeature(ResourceLocation id, StructureFeature<NoneFeatureConfiguration> structure, GenerationStep.Decoration step, int spacing, int separation) {
this(id, structure, step, spacing, separation, false);
}
public BCLStructureFeature(ResourceLocation id, StructureFeature<NoneFeatureConfiguration> structure, GenerationStep.Decoration step, int spacing, int separation, boolean adaptNoise) {
this.id = id;
this.featureStep = step;
this.structure = FabricStructureBuilder
.create(id, structure)
.step(step)
.defaultConfig(spacing, separation, RANDOM.nextInt(8192))
.register();
this.featureConfigured = this.structure.configured(NoneFeatureConfiguration.NONE);
BuiltinRegistries.register(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE, id, this.featureConfigured);
//TODO: 1.18 check if structures are added correctly
//FlatChunkGeneratorConfigAccessor.getStructureToFeatures().put(this.structure, this.featureConfigured);
//parts from vanilla for Structure generation
//public static final ResourceKey<ConfiguredStructureFeature<?, ?>> JUNGLE_TEMPLE =
// BuiltinStructures.createKey("jungle_pyramid");
//public static final Holder<ConfiguredStructureFeature<?, ?>> JUNGLE_TEMPLE =
// StructureFeatures.register(BuiltinStructures.JUNGLE_TEMPLE, StructureFeature.JUNGLE_TEMPLE.configured(NoneFeatureConfiguration.INSTANCE, BiomeTags.HAS_JUNGLE_TEMPLE));
//public static final Holder<StructureSet> JUNGLE_TEMPLES =
// StructureSets.register(BuiltinStructureSets.JUNGLE_TEMPLES, StructureFeatures.JUNGLE_TEMPLE, new RandomSpreadStructurePlacement(32, 8, RandomSpreadType.LINEAR, 14357619));
//public static final StructureFeature<NoneFeatureConfiguration> JUNGLE_TEMPLE =
// StructureFeature.register("jungle_pyramid", new JunglePyramidFeature(NoneFeatureConfiguration.CODEC), GenerationStep.Decoration.SURFACE_STRUCTURES);
//
this.spreadConfig = new RandomSpreadStructurePlacement(spacing, separation, RandomSpreadType.LINEAR, RANDOM.nextInt(8192));
this.structureKey = ResourceKey.create(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY, id);
this.structureSetKey = ResourceKey.create(Registry.STRUCTURE_SET_REGISTRY, id);
this.biomeTag = TagAPI.makeBiomeTag(id.getNamespace(), "has_structure/"+id.getPath());
this.structure = StructureFeatureAccessor.callRegister(id.toString(), structure, step);
this.featureConfigured = StructureFeaturesAccessor.callRegister(structureKey, this.structure.configured(NoneFeatureConfiguration.NONE, biomeTag, adaptNoise));
StructureSets.register(structureSetKey, featureConfigured, spreadConfig);
}
/**
@ -69,7 +96,7 @@ public class BCLStructureFeature {
return structure;
}
public ConfiguredStructureFeature<?, ?> getFeatureConfigured() {
public Holder<ConfiguredStructureFeature<?, ?>> getFeatureConfigured() {
return featureConfigured;
}