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

@ -6,15 +6,15 @@ loom_version=0.10-SNAPSHOT
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/versions.html # check these on https://fabricmc.net/versions.html
minecraft_version= 1.18.1 minecraft_version= 1.18.2
loader_version= 0.12.12 loader_version= 0.13.3
fabric_version = 0.46.2+1.18 fabric_version = 0.48.0+1.18.2
# Mod Properties # Mod Properties
mod_version = 1.3.5 mod_version = 1.4.2
maven_group = ru.bclib maven_group = ru.bclib
archives_base_name = bclib archives_base_name = bclib
# Dependencies # Dependencies
patchouli_version = 50-FABRIC patchouli_version = 50-FABRIC
modmenu_version=3.0.1 modmenu_version=3.1.0

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

View file

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

View file

@ -10,6 +10,7 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import ru.bclib.BCLib; import ru.bclib.BCLib;
import ru.bclib.api.biomes.BiomeAPI; import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.api.tag.NamedMineableTags;
import ru.bclib.api.tag.TagAPI; import ru.bclib.api.tag.TagAPI;
import ru.bclib.api.tag.TagAPI.TagLocation; import ru.bclib.api.tag.TagAPI.TagLocation;
import ru.bclib.blocks.BaseBarrelBlock; import ru.bclib.blocks.BaseBarrelBlock;
@ -23,6 +24,7 @@ import ru.bclib.config.Configs;
import ru.bclib.interfaces.PostInitable; import ru.bclib.interfaces.PostInitable;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider; import ru.bclib.interfaces.TagProvider;
import ru.bclib.interfaces.tools.*;
import ru.bclib.registry.BaseBlockEntities; import ru.bclib.registry.BaseBlockEntities;
import java.util.List; import java.util.List;
@ -111,6 +113,29 @@ public class PostInitAPI {
else if (block instanceof BaseFurnaceBlock) { else if (block instanceof BaseFurnaceBlock) {
BaseBlockEntities.FURNACE.registerBlock(block); 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) { if (block instanceof TagProvider) {
TagProvider.class.cast(block).addTags(blockTags, itemTags); TagProvider.class.cast(block).addTags(blockTags, itemTags);
blockTags.forEach(tag -> TagAPI.addBlockTag(tag, block)); blockTags.forEach(tag -> TagAPI.addBlockTag(tag, block));

View file

@ -1,25 +1,24 @@
package ru.bclib.api.biomes; 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.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.core.particles.ParticleOptions;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.data.worldgen.BiomeDefaultFeatures; import net.minecraft.data.worldgen.BiomeDefaultFeatures;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.Music; import net.minecraft.sounds.Music;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.tags.TagKey;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.biome.AmbientAdditionsSettings; import net.minecraft.world.level.biome.*;
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.Biome.BiomeBuilder; import net.minecraft.world.level.biome.Biome.BiomeBuilder;
import net.minecraft.world.level.biome.Biome.BiomeCategory; import net.minecraft.world.level.biome.Biome.BiomeCategory;
import net.minecraft.world.level.biome.Biome.Precipitation; 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.biome.MobSpawnSettings.SpawnerData;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState; 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.Noises;
import net.minecraft.world.level.levelgen.SurfaceRules; import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; 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 net.minecraft.world.level.levelgen.placement.PlacedFeature;
import ru.bclib.api.surface.SurfaceRuleBuilder; import ru.bclib.api.surface.SurfaceRuleBuilder;
import ru.bclib.entity.BCLEntityWrapper; import ru.bclib.entity.BCLEntityWrapper;
import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor; import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor;
import ru.bclib.util.CollectionsUtil;
import ru.bclib.util.ColorUtil; import ru.bclib.util.ColorUtil;
import ru.bclib.util.Pair;
import ru.bclib.util.TriFunction; import ru.bclib.util.TriFunction;
import ru.bclib.world.biomes.BCLBiome; import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.biomes.BCLBiomeSettings; import ru.bclib.world.biomes.BCLBiomeSettings;
@ -41,12 +41,10 @@ import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.structures.BCLStructureFeature; import ru.bclib.world.structures.BCLStructureFeature;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class BCLBiomeBuilder { public class BCLBiomeBuilder {
@ -57,7 +55,8 @@ public class BCLBiomeBuilder {
private static final BCLBiomeBuilder INSTANCE = new BCLBiomeBuilder(); private static final BCLBiomeBuilder INSTANCE = new BCLBiomeBuilder();
private static final SurfaceRules.ConditionSource SURFACE_NOISE = SurfaceRules.noiseCondition(Noises.SOUL_SAND_LAYER, -0.012); 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 BiomeGenerationSettings.Builder generationSettings;
private BiomeSpecialEffects.Builder effectsBuilder; private BiomeSpecialEffects.Builder effectsBuilder;
private MobSpawnSettings.Builder spawnSettings; private MobSpawnSettings.Builder spawnSettings;
@ -87,7 +86,7 @@ public class BCLBiomeBuilder {
INSTANCE.generationSettings = null; INSTANCE.generationSettings = null;
INSTANCE.effectsBuilder = null; INSTANCE.effectsBuilder = null;
INSTANCE.spawnSettings = null; INSTANCE.spawnSettings = null;
INSTANCE.structures.clear(); INSTANCE.structureTags.clear();
INSTANCE.temperature = 1.0F; INSTANCE.temperature = 1.0F;
INSTANCE.fogDensity = 1.0F; INSTANCE.fogDensity = 1.0F;
INSTANCE.edgeSize = 0; INSTANCE.edgeSize = 0;
@ -96,6 +95,7 @@ public class BCLBiomeBuilder {
INSTANCE.height = 0.1F; INSTANCE.height = 0.1F;
INSTANCE.vertical = false; INSTANCE.vertical = false;
INSTANCE.edge = null; INSTANCE.edge = null;
INSTANCE.carvers.clear();
return INSTANCE; return INSTANCE;
} }
@ -500,7 +500,7 @@ public class BCLBiomeBuilder {
* @param feature {@link PlacedFeature}. * @param feature {@link PlacedFeature}.
* @return same {@link BCLBiomeBuilder} instance. * @return same {@link BCLBiomeBuilder} instance.
*/ */
public BCLBiomeBuilder feature(Decoration decoration, PlacedFeature feature) { public BCLBiomeBuilder feature(Decoration decoration, Holder<PlacedFeature> feature) {
getGeneration().addFeature(decoration, feature); getGeneration().addFeature(decoration, feature);
return this; return this;
} }
@ -542,11 +542,11 @@ public class BCLBiomeBuilder {
/** /**
* Adds new structure feature into the biome. * Adds new structure feature into the biome.
* @param structure {@link ConfiguredStructureFeature} to add. * @param structureTag {@link TagKey} to add.
* @return same {@link BCLBiomeBuilder} instance. * @return same {@link BCLBiomeBuilder} instance.
*/ */
public BCLBiomeBuilder structure(ConfiguredStructureFeature<?, ?> structure) { public BCLBiomeBuilder structure(TagKey<Biome> structureTag) {
structures.add(structure); structureTags.add(structureTag);
return this; return this;
} }
@ -557,7 +557,7 @@ public class BCLBiomeBuilder {
*/ */
public BCLBiomeBuilder structure(BCLStructureFeature structure) { public BCLBiomeBuilder structure(BCLStructureFeature structure) {
structure.addInternalBiome(biomeID); structure.addInternalBiome(biomeID);
return structure(structure.getFeatureConfigured()); return structure(structure.biomeTag);
} }
/** /**
@ -565,11 +565,13 @@ public class BCLBiomeBuilder {
* @param carver {@link ConfiguredWorldCarver} to add. * @param carver {@link ConfiguredWorldCarver} to add.
* @return same {@link BCLBiomeBuilder} instance. * @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; final ResourceLocation immutableID = biomeID;
BuiltinRegistries.CONFIGURED_CARVER var oKey = carver.unwrapKey();
.getResourceKey(carver) if (oKey.isPresent()) {
.ifPresent(key -> BiomeModifications.addCarver(ctx -> ctx.getBiomeKey().location().equals(immutableID), step, key)); BiomeModifications.addCarver(ctx -> ctx.getBiomeKey().location().equals(immutableID), step, (ResourceKey<ConfiguredWorldCarver<?>>) oKey.get());
}
//carvers.add(new Pair<>(step, carver));
return this; return this;
} }
@ -625,8 +627,8 @@ public class BCLBiomeBuilder {
this.height = height; this.height = height;
return this; return this;
} }
/** /**
* Make this a vertical Biome * Make this a vertical Biome
@ -645,7 +647,7 @@ public class BCLBiomeBuilder {
public BCLBiome build() { public BCLBiome build() {
return build((BiomeSupplier<BCLBiome>)BCLBiome::new); return build((BiomeSupplier<BCLBiome>)BCLBiome::new);
} }
/** /**
* Finalize biome creation. * Finalize biome creation.
* @param biomeConstructor {@link BiFunction} biome constructor. * @param biomeConstructor {@link BiFunction} biome constructor.
@ -655,7 +657,22 @@ public class BCLBiomeBuilder {
public <T extends BCLBiome> T build(BiFunction<ResourceLocation, Biome, T> biomeConstructor) { public <T extends BCLBiome> T build(BiFunction<ResourceLocation, Biome, T> biomeConstructor) {
return build((id, biome, settings)->biomeConstructor.apply(id, biome)); 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. * Finalize biome creation.
* @param biomeConstructor {@link BiomeSupplier} biome constructor. * @param biomeConstructor {@link BiomeSupplier} biome constructor.
@ -670,26 +687,8 @@ public class BCLBiomeBuilder {
builder.mobSpawnSettings(getSpawns().build()); builder.mobSpawnSettings(getSpawns().build());
builder.specialEffects(getEffects().build()); builder.specialEffects(getEffects().build());
Map<Decoration, List<Supplier<PlacedFeature>>> defferedFeatures = new HashMap<>(); builder.generationSettings(fixGenerationSettings(getGeneration().build()));
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());
}
BCLBiomeSettings settings = BCLBiomeSettings.createBCL() BCLBiomeSettings settings = BCLBiomeSettings.createBCL()
.setTerrainHeight(height) .setTerrainHeight(height)
@ -699,11 +698,13 @@ public class BCLBiomeBuilder {
.setEdge(edge) .setEdge(edge)
.setVertical(vertical) .setVertical(vertical)
.build(); .build();
final T res = biomeConstructor.apply(biomeID, builder.build(), settings); final Biome biome = builder.build();
res.attachStructures(structures); final T res = biomeConstructor.apply(biomeID, biome, settings);
res.attachStructures(structureTags);
res.setSurface(surfaceRule); res.setSurface(surfaceRule);
res.setFeatures(defferedFeatures);
//carvers.forEach(cfg -> BiomeAPI.addBiomeCarver(biome, cfg.second, cfg.first));
return res; return res;
} }

View file

@ -1,19 +1,18 @@
package ru.bclib.api.biomes; package ru.bclib.api.biomes;
import com.google.common.collect.HashMultimap; import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.impl.biome.NetherBiomeData; import net.fabricmc.fabric.impl.biome.NetherBiomeData;
import net.fabricmc.fabric.impl.biome.TheEndBiomeData; import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
import net.fabricmc.fabric.impl.structure.FabricStructureImpl;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries; import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceKey; 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.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.*;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData; import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState; 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.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.StructureSettings;
import net.minecraft.world.level.levelgen.SurfaceRules; import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.StructureFeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import ru.bclib.BCLib; import ru.bclib.BCLib;
import ru.bclib.entity.BCLEntityWrapper; import ru.bclib.entity.BCLEntityWrapper;
import ru.bclib.interfaces.BiomeSourceAccessor; import ru.bclib.interfaces.*;
import ru.bclib.interfaces.NoiseGeneratorSettingsProvider;
import ru.bclib.interfaces.SurfaceMaterialProvider;
import ru.bclib.interfaces.SurfaceProvider;
import ru.bclib.interfaces.SurfaceRuleProvider;
import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor; import ru.bclib.mixin.common.BiomeGenerationSettingsAccessor;
import ru.bclib.mixin.common.MobSpawnSettingsAccessor; import ru.bclib.mixin.common.MobSpawnSettingsAccessor;
import ru.bclib.mixin.common.StructureSettingsAccessor;
import ru.bclib.util.CollectionsUtil; import ru.bclib.util.CollectionsUtil;
import ru.bclib.util.MHelper; import ru.bclib.util.MHelper;
import ru.bclib.world.biomes.BCLBiome; 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.biomes.VanillaBiomeSettings;
import ru.bclib.world.features.BCLFeature; import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.generator.BiomePicker; import ru.bclib.world.generator.BiomePicker;
import ru.bclib.world.structures.BCLStructureFeature;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; 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.BiConsumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -100,27 +80,26 @@ public class BiomeAPI {
private static final Map<Biome, BCLBiome> CLIENT = Maps.newHashMap(); private static final Map<Biome, BCLBiome> CLIENT = Maps.newHashMap();
private static Registry<Biome> biomeRegistry; 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 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, Holder<Biome>>>> MODIFICATIONS = Maps.newHashMap();
private static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Biome>>> MODIFICATIONS = Maps.newHashMap();
private static final Map<ResourceLocation, SurfaceRules.RuleSource> SURFACE_RULES = Maps.newHashMap(); private static final Map<ResourceLocation, SurfaceRules.RuleSource> SURFACE_RULES = Maps.newHashMap();
private static final Set<SurfaceRuleProvider> MODIFIED_SURFACE_PROVIDERS = new HashSet<>(8); 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 NETHER_WASTES_BIOME = registerNetherBiome(getFromRegistry(Biomes.NETHER_WASTES).value());
public static final BCLBiome CRIMSON_FOREST_BIOME = registerNetherBiome(getFromRegistry(Biomes.CRIMSON_FOREST)); 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)); 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)); 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)); 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 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_MIDLANDS = registerSubBiome(THE_END, getFromRegistry(Biomes.END_MIDLANDS).value(), 0.5F);
public static final BCLBiome END_HIGHLANDS = registerSubBiome(THE_END, getFromRegistry(Biomes.END_HIGHLANDS), 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 END_BARRENS = registerEndVoidBiome(getFromRegistry(new ResourceLocation("end_barrens")));
public static final BCLBiome SMALL_END_ISLANDS = registerEndVoidBiome(getFromRegistry(new ResourceLocation("small_end_islands"))); public static final BCLBiome SMALL_END_ISLANDS = registerEndVoidBiome(getFromRegistry(new ResourceLocation("small_end_islands")));
private static void initFeatureOrder() { private static void initFeatureOrder() {
if (!FEATURE_ORDER.isEmpty()) { if (!FEATURE_ORDER.isEmpty()) {
return; return;
@ -137,8 +116,7 @@ public class BiomeAPI {
.map(Entry::getValue) .map(Entry::getValue)
.map(biome -> (BiomeGenerationSettingsAccessor) biome.getGenerationSettings()) .map(biome -> (BiomeGenerationSettingsAccessor) biome.getGenerationSettings())
.map(BiomeGenerationSettingsAccessor::bclib_getFeatures) .map(BiomeGenerationSettingsAccessor::bclib_getFeatures)
.forEach(stepFeatureSuppliers -> stepFeatureSuppliers.forEach(step -> step.forEach(featureSupplier -> { .forEach(stepFeatureSuppliers -> stepFeatureSuppliers.forEach(step -> step.forEach(feature -> {
PlacedFeature feature = featureSupplier.get();
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement()); FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
}))); })));
} }
@ -161,23 +139,23 @@ public class BiomeAPI {
* called from {@link ru.bclib.mixin.client.MinecraftMixin} * called from {@link ru.bclib.mixin.client.MinecraftMixin}
*/ */
public static void prepareNewLevel(){ public static void prepareNewLevel(){
STRUCTURE_STARTS.clear();
MODIFIED_SURFACE_PROVIDERS.forEach(p->p.bclib_clearBiomeSources()); MODIFIED_SURFACE_PROVIDERS.forEach(p->p.bclib_clearBiomeSources());
MODIFIED_SURFACE_PROVIDERS.clear(); MODIFIED_SURFACE_PROVIDERS.clear();
} }
/** /**
* Register {@link BCLBiome} instance and its {@link Biome} if necessary. * Register {@link BCLBiome} instance and its {@link Biome} if necessary.
* @param biome {@link BCLBiome} * @param bclbiome {@link BCLBiome}
* @return {@link BCLBiome} * @return {@link BCLBiome}
*/ */
public static BCLBiome registerBiome(BCLBiome biome) { public static BCLBiome registerBiome(BCLBiome bclbiome) {
if (BuiltinRegistries.BIOME.get(biome.getID()) == null) { if (BuiltinRegistries.BIOME.get(bclbiome.getID()) == null) {
Registry.register(BuiltinRegistries.BIOME, biome.getID(), biome.getBiome()); final Biome biome = bclbiome.getBiome();
ResourceLocation loc = bclbiome.getID();
Registry.register(BuiltinRegistries.BIOME, loc, biome);
} }
ID_MAP.put(biome.getID(), biome); ID_MAP.put(bclbiome.getID(), bclbiome);
return biome; return bclbiome;
} }
public static BCLBiome registerSubBiome(BCLBiome parent, BCLBiome subBiome) { public static BCLBiome registerSubBiome(BCLBiome parent, BCLBiome subBiome) {
@ -212,7 +190,7 @@ public class BiomeAPI {
MHelper.randRange(-1.5F, 1.5F, random), MHelper.randRange(-1.5F, 1.5F, random),
random.nextFloat() random.nextFloat()
); );
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow(); ResourceKey<Biome> key = BiomeAPI.getBiomeKeyOrThrow(biome.getBiomeHolder());
NetherBiomeData.addNetherBiome(key, parameters); NetherBiomeData.addNetherBiome(key, parameters);
return biome; return biome;
} }
@ -242,7 +220,7 @@ public class BiomeAPI {
END_LAND_BIOME_PICKER.addBiome(biome); END_LAND_BIOME_PICKER.addBiome(biome);
float weight = biome.getGenChance(); float weight = biome.getGenChance();
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow(); ResourceKey<Biome> key = BiomeAPI.getBiomeKey(biome.getBiome());
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_HIGHLANDS, key, weight); TheEndBiomeData.addEndBiomeReplacement(Biomes.END_HIGHLANDS, key, weight);
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_MIDLANDS, key, weight); TheEndBiomeData.addEndBiomeReplacement(Biomes.END_MIDLANDS, key, weight);
return biome; return biome;
@ -254,8 +232,8 @@ public class BiomeAPI {
* @param biome {@link BCLBiome} * @param biome {@link BCLBiome}
* @return {@link BCLBiome} * @return {@link BCLBiome}
*/ */
public static BCLBiome registerEndLandBiome(Biome biome) { public static BCLBiome registerEndLandBiome(Holder<Biome> biome) {
BCLBiome bclBiome = new BCLBiome(biome, null); BCLBiome bclBiome = new BCLBiome(biome.value(), null);
END_LAND_BIOME_PICKER.addBiome(bclBiome); END_LAND_BIOME_PICKER.addBiome(bclBiome);
registerBiome(bclBiome); registerBiome(bclBiome);
@ -269,8 +247,8 @@ public class BiomeAPI {
* @param genChance float generation chance. * @param genChance float generation chance.
* @return {@link BCLBiome} * @return {@link BCLBiome}
*/ */
public static BCLBiome registerEndLandBiome(Biome biome, float genChance) { public static BCLBiome registerEndLandBiome(Holder<Biome> biome, float genChance) {
BCLBiome bclBiome = new BCLBiome(biome, VanillaBiomeSettings.createVanilla().setGenChance(genChance).build()); BCLBiome bclBiome = new BCLBiome(biome.value(), VanillaBiomeSettings.createVanilla().setGenChance(genChance).build());
END_LAND_BIOME_PICKER.addBiome(bclBiome); END_LAND_BIOME_PICKER.addBiome(bclBiome);
registerBiome(bclBiome); registerBiome(bclBiome);
@ -288,7 +266,7 @@ public class BiomeAPI {
END_VOID_BIOME_PICKER.addBiome(biome); END_VOID_BIOME_PICKER.addBiome(biome);
float weight = biome.getGenChance(); float weight = biome.getGenChance();
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome.getBiome()).orElseThrow(); ResourceKey<Biome> key = BiomeAPI.getBiomeKeyOrThrow(biome.getBiomeHolder());
TheEndBiomeData.addEndBiomeReplacement(Biomes.SMALL_END_ISLANDS, key, weight); TheEndBiomeData.addEndBiomeReplacement(Biomes.SMALL_END_ISLANDS, key, weight);
return biome; return biome;
} }
@ -299,8 +277,8 @@ public class BiomeAPI {
* @param biome {@link BCLBiome} * @param biome {@link BCLBiome}
* @return {@link BCLBiome} * @return {@link BCLBiome}
*/ */
public static BCLBiome registerEndVoidBiome(Biome biome) { public static BCLBiome registerEndVoidBiome(Holder<Biome> biome) {
BCLBiome bclBiome = new BCLBiome(biome, null); BCLBiome bclBiome = new BCLBiome(biome.value(), null);
END_VOID_BIOME_PICKER.addBiome(bclBiome); END_VOID_BIOME_PICKER.addBiome(bclBiome);
registerBiome(bclBiome); registerBiome(bclBiome);
@ -314,8 +292,8 @@ public class BiomeAPI {
* @param genChance float generation chance. * @param genChance float generation chance.
* @return {@link BCLBiome} * @return {@link BCLBiome}
*/ */
public static BCLBiome registerEndVoidBiome(Biome biome, float genChance) { public static BCLBiome registerEndVoidBiome(Holder<Biome> biome, float genChance) {
BCLBiome bclBiome = new BCLBiome(biome, VanillaBiomeSettings.createVanilla().setGenChance(genChance).build()); BCLBiome bclBiome = new BCLBiome(biome.value(), VanillaBiomeSettings.createVanilla().setGenChance(genChance).build());
END_VOID_BIOME_PICKER.addBiome(bclBiome); END_VOID_BIOME_PICKER.addBiome(bclBiome);
registerBiome(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. * 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}. * @return {@link BCLBiome} or {@code BiomeAPI.EMPTY_BIOME}.
*/ */
public static BCLBiome getFromBiome(Biome biome) { public static BCLBiome getFromBiome(Holder<Biome> biome) {
if (biomeRegistry == null) { if (biomeRegistry == null) {
return EMPTY_BIOME; 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; 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}. * Get {@link BCLBiome} from given {@link ResourceLocation}.
@ -393,6 +392,15 @@ public class BiomeAPI {
public static BCLBiome getBiome(Biome biome) { public static BCLBiome getBiome(Biome biome) {
return getBiome(BiomeAPI.getBiomeID(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. * Check if biome with {@link ResourceLocation} exists in API registry.
@ -409,31 +417,31 @@ public class BiomeAPI {
public static void loadFabricAPIBiomes() { public static void loadFabricAPIBiomes() {
FabricBiomesData.NETHER_BIOMES.forEach((key) -> { FabricBiomesData.NETHER_BIOMES.forEach((key) -> {
if (!hasBiome(key.location())) { if (!hasBiome(key.location())) {
registerNetherBiome(BuiltinRegistries.BIOME.get(key.location())); registerNetherBiome(BuiltinRegistries.BIOME.get(key));
} }
}); });
FabricBiomesData.END_LAND_BIOMES.forEach((key, weight) -> { FabricBiomesData.END_LAND_BIOMES.forEach((key, weight) -> {
if (!hasBiome(key.location())) { 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) -> { FabricBiomesData.END_VOID_BIOMES.forEach((key, weight) -> {
if (!hasBiome(key.location())) { if (!hasBiome(key.location())) {
registerEndVoidBiome(BuiltinRegistries.BIOME.get(key.location()), weight); registerEndVoidBiome(BuiltinRegistries.BIOME.getOrCreateHolder(key), weight);
} }
}); });
} }
@Nullable @Nullable
public static Biome getFromRegistry(ResourceLocation key) { public static Holder<Biome> getFromRegistry(ResourceLocation key) {
return BuiltinRegistries.BIOME.get(key); return BuiltinRegistries.BIOME.getHolder(ResourceKey.create(Registry.BIOME_REGISTRY, key)).orElseThrow();
} }
@Nullable @Nullable
public static Biome getFromRegistry(ResourceKey<Biome> key) { public static Holder<Biome> getFromRegistry(ResourceKey<Biome> key) {
return BuiltinRegistries.BIOME.get(key); return BuiltinRegistries.BIOME.getOrCreateHolder(key);
} }
public static boolean isDatapackBiome(ResourceLocation biomeID) { 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 dimensionID {@link ResourceLocation} dimension ID, example: Level.OVERWORLD or "minecraft:overworld".
* @param modification {@link BiConsumer} with {@link ResourceKey} biome ID and {@link Biome} parameters. * @param modification {@link BiConsumer} with {@link ResourceKey} biome ID and {@link Biome} parameters.
*/ */
public static void registerBiomeModification(ResourceKey dimensionID, BiConsumer<ResourceLocation, Biome> modification) { public static void registerBiomeModification(ResourceKey dimensionID, BiConsumer<ResourceLocation, Holder<Biome>> modification) {
List<BiConsumer<ResourceLocation, Biome>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID, k -> Lists.newArrayList()); List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID, k -> Lists.newArrayList());
modifications.add(modification); 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. * 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. * @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); 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. * 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. * @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); 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. * 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. * @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); registerBiomeModification(Level.END, modification);
} }
@ -491,40 +499,54 @@ public class BiomeAPI {
* @param level * @param level
*/ */
public static void applyModifications(ServerLevel level) { public static void applyModifications(ServerLevel level) {
final BiomeSource source = level.getChunkSource().getGenerator().getBiomeSource(); NoiseGeneratorSettings noiseGeneratorSettings = null;
final StructureSettings settings = level.getChunkSource().getGenerator().getSettings(); final ChunkGenerator chunkGenerator = level.getChunkSource().getGenerator();
final Set<Biome> biomes = source.possibleBiomes(); 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() .getServer()
.getWorldData() .getWorldData()
.worldGenSettings() .worldGenSettings()
.dimensions() .dimensions()
.stream() .stream()
.map(dim->dim.generator()) .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()) .map(gen->((NoiseGeneratorSettingsProvider)gen).bclib_getNoiseGeneratorSettings())
.findFirst() .findFirst()
.orElse(null); .orElse(null);*/
// Datapacks (like Amplified Nether)will change the GeneratorSettings upon load, so we will // 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 // 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) { 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) { } 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()); List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(level.dimension());
for (Biome biome : biomes) { for (Holder<Biome> biomeHolder : biomes) {
applyModificationsAndUpdateFeatures(modifications, biome); if (biomeHolder.isBound()) {
applyModificationsAndUpdateFeatures(modifications, biomeHolder);
}
} }
if (generator != null) { if (noiseGeneratorSettings != null) {
final SurfaceRuleProvider provider = SurfaceRuleProvider.class.cast(generator); 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 // 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. // Provided by all the BiomeSources that use the same generator.
// This happens for example when using the MiningDimensions, which reuses the generator for the // 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); 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(); ((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); ResourceLocation biomeID = getBiomeID(biome);
if (modifications!=null) { if (modifications!=null) {
modifications.forEach(consumer -> { 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); sortBiomeFeatures(biome);
} }
@ -568,20 +575,20 @@ public class BiomeAPI {
* Create a unique sort order for all Features of the Biome * Create a unique sort order for all Features of the Biome
* @param biome The {@link Biome} to sort the features for * @param biome The {@link Biome} to sort the features for
*/ */
public static void sortBiomeFeatures(Biome biome) { public static void sortBiomeFeatures(Holder<Biome> biome) {
BiomeGenerationSettings settings = biome.getGenerationSettings(); BiomeGenerationSettings settings = biome.value().getGenerationSettings();
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) settings; 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(); final int size = featureList.size();
for (int i = 0; i < size; i++) { 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); sortFeatures(features);
featureList.set(i, features); featureList.set(i, HolderSet.direct(features));
} }
accessor.bclib_setFeatures(featureList); 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 Set<ResourceLocation> biomeIDs = biomes
.stream() .stream()
.map(biome -> getBiomeID(biome)) .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 * @return A list of {@link RuleSource}-Objects that are needed to create those Biomes
*/ */
public static List<SurfaceRules.RuleSource> getRuleSources(Set<BiomeSource> sources) { 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) { for (BiomeSource s : sources) {
biomes.addAll(s.possibleBiomes()); biomes.addAll(s.possibleBiomes());
} }
@ -624,7 +631,7 @@ public class BiomeAPI {
* @param feature {@link ConfiguredFeature} to add. * @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()); addBiomeFeature(biome, feature.getDecoration(), feature.getPlacedFeature());
} }
@ -634,7 +641,7 @@ public class BiomeAPI {
* @param step a {@link Decoration} step for the feature. * @param step a {@link Decoration} step for the feature.
* @param featureList {@link ConfiguredFeature} to add. * @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)); addBiomeFeature(biome, step, List.of(featureList));
} }
@ -642,107 +649,25 @@ public class BiomeAPI {
* Adds new features to existing biome. * Adds new features to existing biome.
* @param biome {@link Biome} to add features in. * @param biome {@link Biome} to add features in.
* @param step a {@link Decoration} step for the feature. * @param step a {@link Decoration} step for the feature.
* @param featureList List of {@link ConfiguredFeature} to add. * @param additionalFeatures List of {@link ConfiguredFeature} to add.
*/ */
private static void addBiomeFeature(Biome biome, Decoration step, List<PlacedFeature> featureList) { private static void addBiomeFeature(Holder<Biome> biome, Decoration step, List<Holder<PlacedFeature>> additionalFeatures) {
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings(); BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.value().getGenerationSettings();
List<List<Supplier<PlacedFeature>>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures()); List<HolderSet<PlacedFeature>> allFeatures = CollectionsUtil.getMutable(accessor.bclib_getFeatures());
Set<PlacedFeature> set = CollectionsUtil.getMutable(accessor.bclib_getFeatureSet()); List<Holder<PlacedFeature>> features = getFeaturesListCopy(allFeatures, step);
List<Supplier<PlacedFeature>> features = getFeaturesList(allFeatures, step);
for (var feature : featureList) { for (var feature : additionalFeatures) {
features.add(() -> feature); if (!features.contains(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) {
features.add(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_setFeatures(allFeatures);
accessor.bclib_setFeatureSet(set); accessor.bclib_setFeatureSet(featureSet);
} accessor.bclib_setFlowerFeatures(flowerFeatures);
/**
* 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());
}
} }
/** /**
@ -751,13 +676,20 @@ public class BiomeAPI {
* @param carver {@link ConfiguredWorldCarver} to add. * @param carver {@link ConfiguredWorldCarver} to add.
* @param stage {@link Carving} stage. * @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(); BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) biome.getGenerationSettings();
Map<Carving, List<Supplier<ConfiguredWorldCarver<?>>>> carvers = CollectionsUtil.getMutable(accessor.bclib_getCarvers()); Map<Carving, HolderSet<ConfiguredWorldCarver<?>>> carverMap = CollectionsUtil.getMutable(accessor.bclib_getCarvers());
List<Supplier<ConfiguredWorldCarver<?>>> carverList = CollectionsUtil.getMutable(carvers.getOrDefault(stage, new ArrayList<>())); HolderSet<ConfiguredWorldCarver<?>> carvers = carverMap.get(stage);
carvers.put(stage, carverList);
carverList.add(() -> carver); List<Holder<ConfiguredWorldCarver<?>>> carverList;
accessor.bclib_setCarvers(carvers); 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 minGroupCount minimum mobs in group.
* @param maxGroupCount maximum 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()){ if (entityType.canSpawn()){
addBiomeMobSpawn(biome, entityType.type(), weight, minGroupCount, maxGroupCount); addBiomeMobSpawn(biome, entityType.type(), weight, minGroupCount, maxGroupCount);
} }
@ -802,9 +734,9 @@ public class BiomeAPI {
* @param minGroupCount minimum mobs in group. * @param minGroupCount minimum mobs in group.
* @param maxGroupCount maximum 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(); 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()); Map<MobCategory, WeightedRandomList<SpawnerData>> spawners = CollectionsUtil.getMutable(accessor.bcl_getSpawners());
List<SpawnerData> mobs = spawners.containsKey(category) ? CollectionsUtil.getMutable(spawners.get(category).unwrap()) : Lists.newArrayList(); List<SpawnerData> mobs = spawners.containsKey(category) ? CollectionsUtil.getMutable(spawners.get(category).unwrap()) : Lists.newArrayList();
mobs.add(new SpawnerData(entityType, weight, minGroupCount, maxGroupCount)); 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. * 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 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. * @param level {@link ServerLevel} current server level.
* @return {@link BlockState} with the biome surface or AIR if it fails. * @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(); ChunkGenerator generator = level.getChunkSource().getGenerator();
if (generator instanceof NoiseBasedChunkGenerator) { if (generator instanceof NoiseBasedChunkGenerator) {
SurfaceProvider provider = SurfaceProvider.class.cast(generator); SurfaceProvider provider = SurfaceProvider.class.cast(generator);
@ -832,6 +764,10 @@ public class BiomeAPI {
return findTopMaterial(getBiome(world.getBiome(pos))); 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){ public static Optional<BlockState> findTopMaterial(Biome biome){
return findTopMaterial(getBiome(biome)); return findTopMaterial(getBiome(biome));
} }
@ -847,6 +783,10 @@ public class BiomeAPI {
return findUnderMaterial(getBiome(world.getBiome(pos))); 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){ public static Optional<BlockState> findUnderMaterial(Biome biome){
return findUnderMaterial(getBiome(biome)); return findUnderMaterial(getBiome(biome));
} }
@ -862,11 +802,11 @@ public class BiomeAPI {
* Set biome in chunk at specified position. * Set biome in chunk at specified position.
* @param chunk {@link ChunkAccess} chunk to set biome in. * @param chunk {@link ChunkAccess} chunk to set biome in.
* @param pos {@link BlockPos} biome position. * @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; 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); 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. * Set biome in world at specified position.
* @param level {@link LevelAccessor} world to set biome in. * @param level {@link LevelAccessor} world to set biome in.
* @param pos {@link BlockPos} biome position. * @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); ChunkAccess chunk = level.getChunk(pos);
setBiome(chunk, pos, biome); 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) { private static void sortFeatures(List<Holder<PlacedFeature>> features) {
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) {
initFeatureOrder(); initFeatureOrder();
Set<PlacedFeature> featuresWithoutDuplicates = Sets.newHashSet(); Set<Holder<PlacedFeature>> featuresWithoutDuplicates = Sets.newHashSet();
features.forEach(provider -> featuresWithoutDuplicates.add(provider.get())); features.forEach(holder -> featuresWithoutDuplicates.add(holder));
if (featuresWithoutDuplicates.size() != features.size()) { if (featuresWithoutDuplicates.size() != features.size()) {
features.clear(); features.clear();
featuresWithoutDuplicates.forEach(feature -> features.add(() -> feature)); featuresWithoutDuplicates.forEach(feature -> features.add(feature));
} }
features.forEach(provider -> { features.forEach(feature -> {
PlacedFeature feature = provider.get();
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement()); FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
}); });
features.sort((f1, f2) -> { features.sort((f1, f2) -> {
int v1 = FEATURE_ORDER.getOrDefault(f1.get(), 70000); int v1 = FEATURE_ORDER.getOrDefault(f1, 70000);
int v2 = FEATURE_ORDER.getOrDefault(f2.get(), 70000); int v2 = FEATURE_ORDER.getOrDefault(f2, 70000);
return Integer.compare(v1, v2); return Integer.compare(v1, v2);
}); });
} }
@ -966,44 +888,15 @@ public class BiomeAPI {
lists.set(index, list); lists.set(index, list);
return 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) { private static List<Holder<PlacedFeature>> getFeaturesListCopy(List<HolderSet<PlacedFeature>> features, int index) {
int index = step.ordinal();
while (features.size() <= index) { while (features.size() <= index) {
features.add(Lists.newArrayList()); features.add(HolderSet.direct(Lists.newArrayList()));
} }
List<Supplier<PlacedFeature>> mutable = CollectionsUtil.getMutable(features.get(index)); return features.get(index).stream().collect(Collectors.toList());
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);
} }
} }

View file

@ -147,24 +147,8 @@ public abstract class DataHandler extends BaseDataHandler {
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
abstract protected void serializeDataOnClient(FriendlyByteBuf buf); abstract protected void serializeDataOnClient(FriendlyByteBuf buf);
@Deprecated(forRemoval = true) protected abstract void deserializeIncomingDataOnServer(FriendlyByteBuf buf, Player player, PacketSender responseSender);
protected void deserializeIncomingDataOnServer(FriendlyByteBuf buf, PacketSender responseSender){ } protected abstract void runOnServerGameThread(MinecraftServer server, Player player);
//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);
}
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
@Override @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()) { if ( Configs.CLIENT_CONFIG.isAcceptingConfigs() || Configs.CLIENT_CONFIG.isAcceptingFiles() || Configs.CLIENT_CONFIG.isAcceptingMods()) {
BCLib.LOGGER.info("Writing Files:"); BCLib.LOGGER.info("Writing Files:");
//TODO: Reject files that were not in the last RequestFiles.
for (Pair<AutoFileSyncEntry, byte[]> entry : receivedFiles) { for (Pair<AutoFileSyncEntry, byte[]> entry : receivedFiles) {
final AutoFileSyncEntry e = entry.first; final AutoFileSyncEntry e = entry.first;
final byte[] data = entry.second; 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.resources.ResourceLocation;
import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration; 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.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.BiomeFilter; 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.ArrayList;
import java.util.List; 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 static final BCLFeatureBuilder INSTANCE = new BCLFeatureBuilder();
private List<PlacementModifier> modifications = new ArrayList<>(16); private List<PlacementModifier> modifications = new ArrayList<>(16);
private ResourceLocation featureID; private ResourceLocation featureID;
private Decoration decoration; private Decoration decoration;
private Feature<?> feature; private F feature;
private BCLFeatureBuilder() {} private BCLFeatureBuilder() {}
@ -60,6 +61,11 @@ public class BCLFeatureBuilder {
modifications.add(modifier); modifications.add(modifier);
return this; return this;
} }
public BCLFeatureBuilder modifier(List<PlacementModifier> modifiers) {
modifications.addAll(modifiers);
return this;
}
/** /**
* Generate feature in certain iterations (per chunk). * Generate feature in certain iterations (per chunk).
@ -134,10 +140,9 @@ public class BCLFeatureBuilder {
* @param configuration any {@link FeatureConfiguration} for provided {@link Feature}. * @param configuration any {@link FeatureConfiguration} for provided {@link Feature}.
* @return created {@link BCLFeature} instance. * @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()]); PlacementModifier [] modifiers = modifications.toArray(new PlacementModifier [modifications.size()]);
PlacedFeature configured = ((Feature<FC>) feature).configured(configuration).placed(modifiers); return new BCLFeature(featureID, feature, decoration, configuration, modifiers);
return new BCLFeature(featureID, feature, decoration, configured);
} }
/** /**
@ -146,6 +151,6 @@ public class BCLFeatureBuilder {
* @return created {@link BCLFeature} instance. * @return created {@link BCLFeature} instance.
*/ */
public BCLFeature build() { 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) { public SurfaceRuleBuilder subsurface(BlockState state, int depth) {
entryInstance = getFromCache("subsurface_" + depth + "_" + state.toString(), () -> { entryInstance = getFromCache("subsurface_" + depth + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state); 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); return new SurfaceRuleEntry(3, rule);
}); });
rules.add(entryInstance); rules.add(entryInstance);
@ -117,7 +117,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder belowFloor(BlockState state, int height, NoiseCondition noise) { public SurfaceRuleBuilder belowFloor(BlockState state, int height, NoiseCondition noise) {
entryInstance = getFromCache("below_floor_" + height + "_" + state.toString() + "_" + noise.getClass().getSimpleName(), () -> { entryInstance = getFromCache("below_floor_" + height + "_" + state.toString() + "_" + noise.getClass().getSimpleName(), () -> {
RuleSource rule = SurfaceRules.state(state); 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); return new SurfaceRuleEntry(3, rule);
}); });
rules.add(entryInstance); rules.add(entryInstance);
@ -133,7 +133,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder belowFloor(BlockState state, int height) { public SurfaceRuleBuilder belowFloor(BlockState state, int height) {
entryInstance = getFromCache("below_floor_" + height + "_" + state.toString(), () -> { entryInstance = getFromCache("below_floor_" + height + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state); 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); return new SurfaceRuleEntry(3, rule);
}); });
rules.add(entryInstance); rules.add(entryInstance);
@ -163,7 +163,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder aboveCeil(BlockState state, int height) { public SurfaceRuleBuilder aboveCeil(BlockState state, int height) {
entryInstance = getFromCache("above_ceil_" + height + "_" + state.toString(), () -> { entryInstance = getFromCache("above_ceil_" + height + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state); 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); return new SurfaceRuleEntry(3, rule);
}); });
rules.add(entryInstance); rules.add(entryInstance);
@ -179,7 +179,7 @@ public class SurfaceRuleBuilder {
public SurfaceRuleBuilder steep(BlockState state, int depth) { public SurfaceRuleBuilder steep(BlockState state, int depth) {
entryInstance = getFromCache("steep_" + depth + "_" + state.toString(), () -> { entryInstance = getFromCache("steep_" + depth + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state); 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); rule = SurfaceRules.ifTrue(SurfaceRules.steep(), rule);
int priority = depth < 1 ? 0 : 1; int priority = depth < 1 ? 0 : 1;
return new SurfaceRuleEntry(priority, rule); return new SurfaceRuleEntry(priority, rule);

View file

@ -1,23 +1,26 @@
package ru.bclib.api.tag; package ru.bclib.api.tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import ru.bclib.api.tag.TagAPI.TagNamed;
public class CommonBlockTags { public class CommonBlockTags {
public static final TagNamed<Block> BARREL = TagAPI.makeCommonBlockTag("barrel"); public static final TagKey<Block> BARREL = TagAPI.makeCommonBlockTag("barrel");
public static final TagNamed<Block> BOOKSHELVES = TagAPI.makeCommonBlockTag("bookshelves"); public static final TagKey<Block> BOOKSHELVES = TagAPI.makeCommonBlockTag("bookshelves");
public static final TagNamed<Block> CHEST = TagAPI.makeCommonBlockTag("chest"); public static final TagKey<Block> CHEST = TagAPI.makeCommonBlockTag("chest");
public static final TagNamed<Block> END_STONES = TagAPI.makeCommonBlockTag("end_stones"); public static final TagKey<Block> END_STONES = TagAPI.makeCommonBlockTag("end_stones");
public static final TagNamed<Block> GEN_END_STONES = END_STONES; public static final TagKey<Block> GEN_END_STONES = END_STONES;
public static final TagNamed<Block> IMMOBILE = TagAPI.makeCommonBlockTag("immobile"); public static final TagKey<Block> IMMOBILE = TagAPI.makeCommonBlockTag("immobile");
public static final TagNamed<Block> LEAVES = TagAPI.makeCommonBlockTag("leaves"); public static final TagKey<Block> LEAVES = TagAPI.makeCommonBlockTag("leaves");
public static final TagNamed<Block> NETHERRACK = TagAPI.makeCommonBlockTag("netherrack"); public static final TagKey<Block> NETHERRACK = TagAPI.makeCommonBlockTag("netherrack");
public static final TagNamed<Block> NETHER_MYCELIUM = TagAPI.makeCommonBlockTag("nether_mycelium"); public static final TagKey<Block> NETHER_MYCELIUM = TagAPI.makeCommonBlockTag("nether_mycelium");
public static final TagNamed<Block> NETHER_PORTAL_FRAME = TagAPI.makeCommonBlockTag("nether_pframe"); public static final TagKey<Block> NETHER_PORTAL_FRAME = TagAPI.makeCommonBlockTag("nether_pframe");
public static final TagNamed<Block> NETHER_STONES = TagAPI.makeCommonBlockTag("nether_stones"); public static final TagKey<Block> NETHER_STONES = TagAPI.makeCommonBlockTag("nether_stones");
public static final TagNamed<Block> SAPLINGS = TagAPI.makeCommonBlockTag("saplings"); public static final TagKey<Block> SAPLINGS = TagAPI.makeCommonBlockTag("saplings");
public static final TagNamed<Block> SOUL_GROUND = TagAPI.makeCommonBlockTag("soul_ground"); public static final TagKey<Block> SOUL_GROUND = TagAPI.makeCommonBlockTag("soul_ground");
public static final TagNamed<Block> WOODEN_BARREL = TagAPI.makeCommonBlockTag("wooden_barrels"); public static final TagKey<Block> WOODEN_BARREL = TagAPI.makeCommonBlockTag("wooden_barrels");
public static final TagNamed<Block> WOODEN_CHEST = TagAPI.makeCommonBlockTag("wooden_chests"); public static final TagKey<Block> WOODEN_CHEST = TagAPI.makeCommonBlockTag("wooden_chests");
public static final TagNamed<Block> WORKBENCHES = TagAPI.makeCommonBlockTag("workbench"); 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; package ru.bclib.api.tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import ru.bclib.api.tag.TagAPI.TagNamed;
public class CommonItemTags { public class CommonItemTags {
public final static TagNamed<Item> HAMMERS = TagAPI.makeCommonItemTag("hammers"); public final static TagKey<Item> HAMMERS = TagAPI.makeCommonItemTag("hammers");
public static final TagNamed<Item> BARREL = TagAPI.makeCommonItemTag("barrel"); public static final TagKey<Item> BARREL = TagAPI.makeCommonItemTag("barrel");
public static final TagNamed<Item> CHEST = TagAPI.makeCommonItemTag("chest"); public static final TagKey<Item> CHEST = TagAPI.makeCommonItemTag("chest");
public static final TagNamed<Item> SHEARS = TagAPI.makeCommonItemTag("shears"); public static final TagKey<Item> SHEARS = TagAPI.makeCommonItemTag("shears");
public static final TagNamed<Item> FURNACES = TagAPI.makeCommonItemTag("furnaces"); public static final TagKey<Item> FURNACES = TagAPI.makeCommonItemTag("furnaces");
public static final TagNamed<Item> IRON_INGOTS = TagAPI.makeCommonItemTag("iron_ingots"); public static final TagKey<Item> IRON_INGOTS = TagAPI.makeCommonItemTag("iron_ingots");
public static final TagNamed<Item> LEAVES = TagAPI.makeCommonItemTag("leaves"); public static final TagKey<Item> LEAVES = TagAPI.makeCommonItemTag("leaves");
public static final TagNamed<Item> SAPLINGS = TagAPI.makeCommonItemTag("saplings"); public static final TagKey<Item> SAPLINGS = TagAPI.makeCommonItemTag("saplings");
public static final TagNamed<Item> SOUL_GROUND = TagAPI.makeCommonItemTag("soul_ground"); public static final TagKey<Item> SOUL_GROUND = TagAPI.makeCommonItemTag("soul_ground");
public static final TagNamed<Item> WOODEN_BARREL = TagAPI.makeCommonItemTag("wooden_barrels"); public static final TagKey<Item> WOODEN_BARREL = TagAPI.makeCommonItemTag("wooden_barrels");
public static final TagNamed<Item> WOODEN_CHEST = TagAPI.makeCommonItemTag("wooden_chests"); public static final TagKey<Item> WOODEN_CHEST = TagAPI.makeCommonItemTag("wooden_chests");
public static final TagNamed<Item> WORKBENCHES = TagAPI.makeCommonItemTag("workbench"); 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> SHEARS = new TagLocation<>("fabric", "mineable/shears");
public static final TagLocation<Block> SHOVEL = new TagLocation<>("mineable/shovel"); 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> 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.Maps;
import com.google.common.collect.Sets; 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.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager; 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;
import net.minecraft.tags.Tag.Named; import net.minecraft.tags.TagKey;
import net.minecraft.tags.TagCollection;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.level.ItemLike; 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.Block;
import net.minecraft.world.level.block.Blocks; 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.Map;
import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.BiConsumer;
public class TagAPI { public class TagAPI {
private static final Map<ResourceLocation, Set<ResourceLocation>> TAGS_BLOCK = Maps.newConcurrentMap(); 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_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. * @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) { public static <T> TagKey<T> makeTag(Registry<T> registry, TagLocation<T> id) {
Tag<T> tag = containerSupplier.get().getTag(id); return registry
return tag == null ? new Delegate<>(id, containerSupplier) : CommonDelegate.proxy((Named<T>) tag); .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 modID - {@link String} mod namespace (mod id);
* @param name - {@link String} tag name. * @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) { public static TagKey<Biome> makeBiomeTag(String modID, String name) {
return makeTag(BlockTags::getAllTags, new TagLocation<>(modID, 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 modID - {@link String} mod namespace (mod id);
* @param name - {@link String} tag name. * @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) { public static TagKey<Block> makeBlockTag(String modID, String name) {
return makeTag(ItemTags::getAllTags, new TagLocation<>(modID, 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. * @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> * @see <a href="https://fabricmc.net/wiki/tutorial:tags">Fabric Wiki (Tags)</a>
*/ */
public static TagNamed<Block> makeCommonBlockTag(String name) { public static TagKey<Block> makeCommonBlockTag(String name) {
return makeTag(BlockTags::getAllTags, new TagLocation<>("c", 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. * @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> * @see <a href="https://fabricmc.net/wiki/tutorial:tags">Fabric Wiki (Tags)</a>
*/ */
public static TagNamed<Item> makeCommonItemTag(String name) { public static TagKey<Item> makeCommonItemTag(String name) {
return makeTag(ItemTags::getAllTags, new TagLocation<>("c", name)); return makeTag(Registry.ITEM, 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);
} }
/** /**
* Initializes basic tags. Should be called only in BCLib main class. * Initializes basic tags. Should be called only in BCLib main class.
*/ */
public static void init() { public static void init() {
addBlockTag(CommonBlockTags.BOOKSHELVES.getName(), Blocks.BOOKSHELF); addBlockTag(CommonBlockTags.BOOKSHELVES, Blocks.BOOKSHELF);
addBlockTag(CommonBlockTags.CHEST.getName(), Blocks.CHEST); addBlockTag(CommonBlockTags.CHEST, Blocks.CHEST);
addItemTag(CommonItemTags.CHEST.getName(), Items.CHEST); addItemTag(CommonItemTags.CHEST, Items.CHEST);
addItemTag(CommonItemTags.IRON_INGOTS.getName(), Items.IRON_INGOT); addItemTag(CommonItemTags.IRON_INGOTS, Items.IRON_INGOT);
addItemTag(CommonItemTags.FURNACES.getName(), Blocks.FURNACE); 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. * Adds multiple Tags to one Block.
* @param tagIDs array of {@link TagLocation<Block>} tag IDs. * @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) { public static void addBlockTag(TagLocation<Block> tagID, Block... blocks) {
addBlockTagUntyped(tagID, 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. * Adds one Tag to multiple Blocks.
@ -164,6 +239,15 @@ public class TagAPI {
public static void addItemTag(TagLocation<Item> tagID, ItemLike... items) { public static void addItemTag(TagLocation<Item> tagID, ItemLike... items) {
addItemTagUntyped(tagID, 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. * Adds one Tag to multiple Items.
@ -190,16 +274,17 @@ public class TagAPI {
* @param tagsMap The map that will hold the registered Tags * @param tagsMap The map that will hold the registered Tags
* @return The {@code tagsMap} Parameter. * @return The {@code tagsMap} Parameter.
*/ */
public static Map<ResourceLocation, Tag.Builder> apply(String directory, Map<ResourceLocation, Tag.Builder> tagsMap) { public static <T> Map<ResourceLocation, Tag.Builder> apply(String directory, Map<ResourceLocation, Tag.Builder> tagsMap) {
Map<ResourceLocation, Set<ResourceLocation>> tagMap = null; final BiConsumer<ResourceLocation, Set<ResourceLocation>> consumer;
consumer = (id, ids) -> apply(tagsMap.computeIfAbsent(id, key -> Tag.Builder.tag()), ids);
if ("tags/blocks".equals(directory)) { if ("tags/blocks".equals(directory)) {
tagMap = TAGS_BLOCK; TAGS_BLOCK.forEach(consumer);
} }
else if ("tags/items".equals(directory)) { else if ("tags/items".equals(directory)) {
tagMap = TAGS_ITEM; TAGS_ITEM.forEach(consumer);
} }
if (tagMap != null) { else if ("tags/worldgen/biome".equals(directory)) {
tagMap.forEach((id, ids) -> apply(tagsMap.computeIfAbsent(id, key -> Tag.Builder.tag()), ids)); TAGS_BIOME.forEach(consumer);
} }
return tagsMap; return tagsMap;
} }
@ -215,16 +300,8 @@ public class TagAPI {
ids.forEach(value -> builder.addElement(value, "BCLib Code")); ids.forEach(value -> builder.addElement(value, "BCLib Code"));
return builder; 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 * Extends (without changing) {@link ResourceLocation}. This Type was introduced to allow type-safe definition af
* Tags using their ResourceLocation. * Tags using their ResourceLocation.
@ -234,68 +311,32 @@ public class TagAPI {
public TagLocation(String string) { public TagLocation(String string) {
super(string); super(string);
} }
public TagLocation(String string, String string2) { public TagLocation(String string, String string2) {
super(string, string2); super(string, string2);
} }
public TagLocation(ResourceLocation location) { public TagLocation(ResourceLocation location) {
super(location.getNamespace(), location.getPath()); super(location.getNamespace(), location.getPath());
} }
public static<R> TagLocation<R> of(Tag.Named<R> tag){ public static<R> TagLocation<R> of(TagKey<R> tag){
return new TagLocation<R>(tag.getName()); return new TagLocation<R>(tag.location());
} }
} }
private abstract static class CommonDelegate<T> implements TagNamed<T> { public static boolean isToolWithMineableTag(ItemStack stack, TagKey<Block> tag){
protected final Tag.Named<T> delegate; return isToolWithUntypedMineableTag(stack, tag.location());
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);
}
} }
private static final class ProxyDelegate<T> extends CommonDelegate<T>{ public static boolean isToolWithMineableTag(ItemStack stack, TagLocation<Block> tag){
private final TagLocation<T> id; return isToolWithUntypedMineableTag(stack, tag);
private ProxyDelegate(Tag.Named<T> source) {
super( source);
id = new TagLocation<>(source.getName()
.getNamespace(), source.getName()
.getPath());
}
@Override
public TagLocation<T> getName(){
return id;
}
} }
private static final class Delegate<T> extends CommonDelegate<T>{ private static boolean isToolWithUntypedMineableTag(ItemStack stack, ResourceLocation tag){
public Delegate(TagLocation<T> id, Supplier<TagCollection<T>> containerSupplier) { if (stack.getItem() instanceof DiggerItemAccessor dig){
super( new TagDelegate<>(id, containerSupplier)); return dig.bclib_getBlockTag().location().equals(tag);
}
@Override
public TagLocation<T> getName(){
return (TagLocation<T>)delegate.getName();
} }
return false;
} }
} }

View file

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

View file

@ -2,7 +2,6 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; 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.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel; 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 net.minecraft.world.phys.shapes.VoxelShape;
import ru.bclib.client.render.BCLRenderLayer; import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.items.tool.BaseShearsItem;
import ru.bclib.util.BlocksHelper; import ru.bclib.util.BlocksHelper;
import java.util.List; import java.util.List;
@ -45,7 +45,6 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
public BaseDoublePlantBlock() { public BaseDoublePlantBlock() {
this( this(
FabricBlockSettings.of(Material.PLANT) FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.noCollission() .noCollission()
); );
@ -54,7 +53,6 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
public BaseDoublePlantBlock(int light) { public BaseDoublePlantBlock(int light) {
this( this(
FabricBlockSettings.of(Material.PLANT) FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.lightLevel((state) -> state.getValue(TOP) ? light : 0) .lightLevel((state) -> state.getValue(TOP) ? light : 0)
.noCollission() .noCollission()
@ -117,7 +115,8 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
} }
ItemStack tool = builder.getParameter(LootContextParams.TOOL); 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, Enchantments.SILK_TOUCH,
tool tool
) > 0) { ) > 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.BlockModelProvider;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider; 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.items.tool.BaseShearsItem;
import ru.bclib.util.MHelper; import ru.bclib.util.MHelper;
@ -31,7 +33,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; 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; protected final Block sapling;
private static FabricBlockSettings makeLeaves(MaterialColor color) { private static FabricBlockSettings makeLeaves(MaterialColor color) {
@ -100,8 +102,6 @@ public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider,
@Override @Override
public void addTags(List<TagLocation<Block>> blockTags, List<TagLocation<Item>> itemTags) { public void addTags(List<TagLocation<Block>> blockTags, List<TagLocation<Item>> itemTags) {
blockTags.add(NamedMineableTags.SHEARS);
blockTags.add(NamedMineableTags.HOE);
blockTags.add(NamedBlockTags.LEAVES); blockTags.add(NamedBlockTags.LEAVES);
itemTags.add(NamedItemTags.LEAVES); itemTags.add(NamedItemTags.LEAVES);
} }

View file

@ -1,17 +1,17 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; 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.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; 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.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.ItemLike; 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.OreBlock;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState; 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.material.MaterialColor;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; 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.BlockModelProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.util.LootUtil; import ru.bclib.util.LootUtil;
import ru.bclib.util.MHelper; import ru.bclib.util.MHelper;
@ -31,6 +35,7 @@ public class BaseOreBlock extends OreBlock implements BlockModelProvider {
private final Supplier<Item> dropItem; private final Supplier<Item> dropItem;
private final int minCount; private final int minCount;
private final int maxCount; private final int maxCount;
private final int miningLevel;
public BaseOreBlock(Supplier<Item> drop, int minCount, int maxCount, int experience) { public BaseOreBlock(Supplier<Item> drop, int minCount, int maxCount, int experience) {
this(drop, minCount, maxCount, experience, 0); 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) { 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.dropItem = drop;
this.minCount = minCount; this.minCount = minCount;
this.maxCount = maxCount; this.maxCount = maxCount;
} this.miningLevel = miningLevel;
private static Properties makeProps(Properties properties, int level){
FabricBlockInternals.computeExtraData(properties).addMiningLevel(FabricToolTags.PICKAXES, level);
return properties;
} }
@Override @Override
@ -70,30 +71,35 @@ public class BaseOreBlock extends OreBlock implements BlockModelProvider {
return LootUtil return LootUtil
.getDrops(this, state, builder) .getDrops(this, state, builder)
.orElseGet( .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); ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && tool.isCorrectToolForDrops(state)) { if (tool != null && tool.isCorrectToolForDrops(state)) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { boolean canMine = miningLevel==0;
return Collections.singletonList(new ItemStack(block)); if (tool.getItem() instanceof TieredItem tired) {
canMine = tired.getTier().getLevel()>=miningLevel;
} }
int count; if (canMine) {
int enchantment = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool); if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
if (enchantment > 0) { return Collections.singletonList(new ItemStack(block));
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); 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(); return Collections.emptyList();
} }

View file

@ -4,7 +4,6 @@ import com.google.common.collect.Lists;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; 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.renderer.block.model.BlockModel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -40,12 +39,15 @@ import ru.bclib.client.models.PatternsHelper;
import ru.bclib.client.render.BCLRenderLayer; import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider; 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.List;
import java.util.Optional; import java.util.Optional;
import java.util.Random; 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); private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
public BasePlantBlock() { public BasePlantBlock() {
@ -60,7 +62,6 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
this( this(
FabricBlockSettings FabricBlockSettings
.of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT) .of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.noCollission() .noCollission()
); );
@ -70,7 +71,6 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
this( this(
FabricBlockSettings FabricBlockSettings
.of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT) .of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT)
.breakByHand(true)
.luminance(light) .luminance(light)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.noCollission() .noCollission()
@ -116,7 +116,8 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
@Override @Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL); 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, Enchantments.SILK_TOUCH,
tool tool
) > 0) { ) > 0) {
@ -167,10 +168,4 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation); Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation);
return ModelsHelper.fromPattern(pattern); 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() { public BasePlantWithAgeBlock() {
this( this(
FabricBlockSettings.of(Material.PLANT) FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.randomTicks() .randomTicks()
.noCollission() .noCollission()

View file

@ -1,7 +1,6 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; 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.BlockPos;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents; 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.block.state.BlockState;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import ru.bclib.api.tag.NamedMineableTags;
import ru.bclib.api.tag.TagAPI;
public class BaseStripableLogBlock extends BaseRotatedPillarBlock { public class BaseStripableLogBlock extends BaseRotatedPillarBlock {
private final Block striped; private final Block striped;
@ -27,7 +28,7 @@ public class BaseStripableLogBlock extends BaseRotatedPillarBlock {
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { 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); world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F);
if (!world.isClientSide) { if (!world.isClientSide) {
world.setBlock(pos, world.setBlock(pos,

View file

@ -3,8 +3,8 @@ package ru.bclib.blocks;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; 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.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos; 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.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.Nullable; 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.BasePatterns;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper; import ru.bclib.client.models.PatternsHelper;
@ -69,7 +71,9 @@ public class BaseTerrainBlock extends BaseBlock {
@Override @Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { 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); world.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);
if (!world.isClientSide) { if (!world.isClientSide) {
world.setBlockAndUpdate(pos, pathBlock.defaultBlockState()); world.setBlockAndUpdate(pos, pathBlock.defaultBlockState());

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,6 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; 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.BlockPos;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents; 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.block.state.BlockState;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import ru.bclib.api.tag.NamedMineableTags;
import ru.bclib.api.tag.TagAPI;
public class StripableBarkBlock extends BaseBarkBlock { public class StripableBarkBlock extends BaseBarkBlock {
private final Block striped; private final Block striped;
@ -27,7 +28,7 @@ public class StripableBarkBlock extends BaseBarkBlock {
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { 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); world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F);
if (!world.isClientSide) { if (!world.isClientSide) {
world.setBlock(pos, world.setBlock(pos,

View file

@ -2,7 +2,6 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; 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.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel; 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.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider; 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.List;
import java.util.Random; 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); private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
public UnderwaterPlantBlock() { public UnderwaterPlantBlock() {
this( this(
FabricBlockSettings FabricBlockSettings
.of(Material.WATER_PLANT) .of(Material.WATER_PLANT)
.breakByHand(true)
.sound(SoundType.WET_GRASS) .sound(SoundType.WET_GRASS)
.noCollission() .noCollission()
); );
@ -57,7 +58,6 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
this( this(
FabricBlockSettings FabricBlockSettings
.of(Material.WATER_PLANT) .of(Material.WATER_PLANT)
.breakByHand(true)
.luminance(light) .luminance(light)
.sound(SoundType.WET_GRASS) .sound(SoundType.WET_GRASS)
.noCollission() .noCollission()
@ -105,7 +105,7 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
@Override @Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL); 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, Enchantments.SILK_TOUCH,
tool tool
) > 0) { ) > 0) {
@ -158,10 +158,5 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
public FluidState getFluidState(BlockState state) { public FluidState getFluidState(BlockState state) {
return Fluids.WATER.getSource(false); 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( super(
FabricBlockSettings FabricBlockSettings
.of(Material.WATER_PLANT) .of(Material.WATER_PLANT)
.breakByHand(true)
.sound(SoundType.WET_GRASS) .sound(SoundType.WET_GRASS)
.randomTicks() .randomTicks()
.noCollission() .noCollission()

View file

@ -2,7 +2,6 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; 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.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.entity.player.Player; 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.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider; 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.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); private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 16, 12);
public UpDownPlantBlock() { public UpDownPlantBlock() {
this(FabricBlockSettings this(FabricBlockSettings
.of(Material.PLANT) .of(Material.PLANT)
.breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.noCollission() .noCollission()
); );
@ -83,7 +84,7 @@ public abstract class UpDownPlantBlock extends BaseBlockNotFull implements Rende
@Override @Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL); 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, Enchantments.SILK_TOUCH,
tool tool
) > 0) { ) > 0) {
@ -104,10 +105,4 @@ public abstract class UpDownPlantBlock extends BaseBlockNotFull implements Rende
super.playerDestroy(world, player, pos, state, blockEntity, stack); super.playerDestroy(world, player, pos, state, blockEntity, stack);
world.neighborChanged(pos, Blocks.AIR, pos.below()); 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( this(
FabricBlockSettings FabricBlockSettings
.of(Material.PLANT) .of(Material.PLANT)
.breakByHand(true)
.luminance(light) .luminance(light)
.destroyTime(0.2F) .destroyTime(0.2F)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)

View file

@ -108,12 +108,12 @@ public class CustomFogRenderer {
} }
private static boolean shouldIgnore(Level level, int x, int y, int z) { 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; return BiomeAPI.getRenderBiome(biome) == BiomeAPI.EMPTY_BIOME;
} }
private static float getFogDensityI(Level level, int x, int y, int z) { 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); BCLBiome renderBiome = BiomeAPI.getRenderBiome(biome);
return renderBiome.getFogDensity(); 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.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.resources.ResourceLocation; 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.Item;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -32,8 +32,8 @@ public abstract class ComplexMaterial {
private final List<BlockEntry> defaultBlockEntries = Lists.newArrayList(); private final List<BlockEntry> defaultBlockEntries = Lists.newArrayList();
private final List<ItemEntry> defaultItemEntries = Lists.newArrayList(); private final List<ItemEntry> defaultItemEntries = Lists.newArrayList();
private final Map<String, Tag.Named<Block>> blockTags = Maps.newHashMap(); private final Map<String, TagKey<Block>> blockTags = Maps.newHashMap();
private final Map<String, Tag.Named<Item>> itemTags = Maps.newHashMap(); private final Map<String, TagKey<Item>> itemTags = Maps.newHashMap();
private final Map<String, Block> blocks = Maps.newHashMap(); private final Map<String, Block> blocks = Maps.newHashMap();
private final Map<String, Item> items = 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. * 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) { protected void addBlockTag(TagKey<Block> tag) {
String key = tag.getName().getPath().replace(getBaseName() + "_", ""); String key = tag.location().getPath().replace(getBaseName() + "_", "");
blockTags.put(key, tag); 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. * 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 Tag.Named} for {@link Item} * @param tag {@link TagKey} for {@link Item}
*/ */
protected void addItemTag(Tag.Named<Item> tag) { protected void addItemTag(TagKey<Item> tag) {
String key = tag.getName().getPath().replace(getBaseName() + "_", ""); String key = tag.location().getPath().replace(getBaseName() + "_", "");
itemTags.put(key, tag); 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. * @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 @Nullable
public Tag.Named<Block> getBlockTag(String key) { public TagKey<Block> getBlockTag(String key) {
return blockTags.get(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. * @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 @Nullable
public Tag.Named<Item> getItemTag(String key) { public TagKey<Item> getItemTag(String key) {
return itemTags.get(key); return itemTags.get(key);
} }

View file

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

View file

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

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 { public interface NumericProvider {
ResourceKey<Registry<Codec<? extends NumericProvider>>> NUMERIC_PROVIDER_REGISTRY = ResourceKey.createRegistryKey(BCLib.makeID("worldgen/numeric_provider")); 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()); Codec<NumericProvider> CODEC = NUMERIC_PROVIDER.byNameCodec().dispatch(NumericProvider::pcodec, Function.identity());
int getNumber(SurfaceRulesContextAccessor context); int getNumber(SurfaceRulesContextAccessor context);

View file

@ -1,10 +1,11 @@
package ru.bclib.interfaces; package ru.bclib.interfaces;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
public interface SurfaceProvider { 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.EnvType;
import net.fabricmc.api.Environment; 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.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation; 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.AxeItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Tier; import net.minecraft.world.item.Tier;
import net.minecraft.world.level.block.state.BlockState;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.interfaces.ItemModelProvider; 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) { public BaseAxeItem(Tier material, float attackDamage, float attackSpeed, Properties settings) {
super(material, attackDamage, attackSpeed, 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 @Override
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) { 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.EnvType;
import net.fabricmc.api.Environment; 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.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation; 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.PickaxeItem;
import net.minecraft.world.item.Tier; import net.minecraft.world.item.Tier;
import net.minecraft.world.level.block.state.BlockState;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.interfaces.ItemModelProvider; 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) { public BasePickaxeItem(Tier material, int attackDamage, float attackSpeed, Properties settings) {
super(material, attackDamage, attackSpeed, 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 @Override
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) { public BlockModel getItemModel(ResourceLocation resourceLocation) {

View file

@ -1,11 +1,13 @@
package ru.bclib.items.tool; 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.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.item.ShearsItem; import net.minecraft.world.item.ShearsItem;
import ru.bclib.api.tag.CommonItemTags; import ru.bclib.api.tag.CommonItemTags;
import ru.bclib.api.tag.TagAPI;
public class BaseShearsItem extends ShearsItem { public class BaseShearsItem extends ShearsItem {
public BaseShearsItem(Properties properties) { public BaseShearsItem(Properties properties) {
@ -13,12 +15,12 @@ public class BaseShearsItem extends ShearsItem {
} }
public static boolean isShear(ItemStack tool){ 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){ public static boolean isShear(ItemStack itemStack, Item item){
if (item == Items.SHEARS){ 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 { } else {
return itemStack.is(item); return itemStack.is(item);
} }

View file

@ -2,44 +2,18 @@ package ru.bclib.items.tool;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.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.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation; 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.ShovelItem;
import net.minecraft.world.item.Tier; import net.minecraft.world.item.Tier;
import net.minecraft.world.level.block.state.BlockState;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.interfaces.ItemModelProvider; 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) { public BaseShovelItem(Tier material, float attackDamage, float attackSpeed, Properties settings) {
super(material, attackDamage, attackSpeed, 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 @Override
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) { 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.EnvType;
import net.fabricmc.api.Environment; 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.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.SwordItem; 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.client.models.ModelsHelper;
import ru.bclib.interfaces.ItemModelProvider; 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) { public BaseSwordItem(Tier material, int attackDamage, float attackSpeed, Properties settings) {
super(material, attackDamage, attackSpeed, 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); super(settings);
} }
@Redirect(method = "animateTick", at = @At( @Redirect(method = "isValidBookShelf", at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/world/level/block/state/BlockState;is(Lnet/minecraft/world/level/block/Block;)Z"), target = "Lnet/minecraft/world/level/block/state/BlockState;is(Lnet/minecraft/world/level/block/Block;)Z"),
require = -1, require = -1,
expect = -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); return block == Blocks.BOOKSHELF ? state.is(CommonBlockTags.BOOKSHELVES) : state.is(block);
} }
} }

View file

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

View file

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

View file

@ -13,7 +13,7 @@ import ru.bclib.api.biomes.BiomeAPI;
@Mixin(WorldPreset.class) @Mixin(WorldPreset.class)
public class WorldPresetMixin { public class WorldPresetMixin {
@Inject(method = "create", at = @At("HEAD")) @Inject(method = "create", at = @At("HEAD"))
private void bclib_create(RegistryAccess.RegistryHolder registryHolder, long l, boolean bl, boolean bl2, CallbackInfoReturnable<WorldGenSettings> info) { private void bclib_create(RegistryAccess registryAccess, long l, boolean bl, boolean bl2, CallbackInfoReturnable<WorldGenSettings> info) {
BiomeAPI.initRegistry(registryHolder.registryOrThrow(Registry.BIOME_REGISTRY)); 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; package ru.bclib.mixin.common;
import net.minecraft.core.HolderSet;
import net.minecraft.world.level.biome.BiomeGenerationSettings; import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.levelgen.GenerationStep; import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.GenerationStep.Carving; import net.minecraft.world.level.levelgen.GenerationStep.Carving;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; 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 net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Mutable;
@ -17,21 +19,21 @@ import java.util.function.Supplier;
@Mixin(BiomeGenerationSettings.class) @Mixin(BiomeGenerationSettings.class)
public interface BiomeGenerationSettingsAccessor { public interface BiomeGenerationSettingsAccessor {
@Accessor("features") @Accessor("features")
List<List<Supplier<PlacedFeature>>> bclib_getFeatures(); List<HolderSet<PlacedFeature>> bclib_getFeatures();
@Accessor("features") @Accessor("features")
@Mutable @Mutable
void bclib_setFeatures(List<List<Supplier<PlacedFeature>>> value); void bclib_setFeatures(List<HolderSet<PlacedFeature>> value);
@Accessor("featureSet") @Accessor("featureSet")
Set<PlacedFeature> bclib_getFeatureSet(); void bclib_setFeatureSet(Supplier<Set<PlacedFeature>> featureSet);
@Accessor("featureSet") @Accessor("flowerFeatures")
void bclib_setFeatureSet(Set<PlacedFeature> features); void bclib_setFlowerFeatures(Supplier<List<ConfiguredFeature<?, ?>>> flowerFeatures);
@Accessor("carvers") @Accessor("carvers")
Map<Carving, List<Supplier<ConfiguredWorldCarver<?>>>> bclib_getCarvers(); Map<GenerationStep.Carving, HolderSet<ConfiguredWorldCarver<?>>> bclib_getCarvers();
@Accessor("carvers") @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; package ru.bclib.mixin.common;
import com.google.common.base.Suppliers;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.BiomeSource.StepFeatureData; import net.minecraft.world.level.biome.BiomeSource.StepFeatureData;
@ -12,6 +13,7 @@ import ru.bclib.interfaces.BiomeSourceAccessor;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
@Mixin(BiomeSource.class) @Mixin(BiomeSource.class)
public abstract class BiomeSourceMixin implements BiomeSourceAccessor { public abstract class BiomeSourceMixin implements BiomeSourceAccessor {
@ -19,10 +21,10 @@ public abstract class BiomeSourceMixin implements BiomeSourceAccessor {
@Shadow public abstract Set<Biome> possibleBiomes(); @Shadow public abstract Set<Biome> possibleBiomes();
@Mutable @Shadow @Final private List<StepFeatureData> featuresPerStep; @Mutable @Shadow @Final private Supplier<List<StepFeatureData>> featuresPerStep;
public void bclRebuildFeatures(){ public void bclRebuildFeatures(){
BCLib.LOGGER.info("Rebuilding features in BiomeSource " + this); 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; package ru.bclib.mixin.common;
import net.minecraft.core.Registry;
import net.minecraft.world.level.StructureFeatureManager; import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.bclib.interfaces.ChunkGeneratorAccessor;
@Mixin(ChunkGenerator.class) @Mixin(ChunkGenerator.class)
public class ChunkGeneratorMixin { public class ChunkGeneratorMixin implements ChunkGeneratorAccessor {
@Shadow @Final protected Registry<StructureSet> structureSets;
private int bclib_featureIteratorSeed; private int bclib_featureIteratorSeed;
@ModifyArg(method = "applyBiomeDecoration", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldgenRandom;setFeatureSeed(JII)V")) @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) { private void bclib_obBiomeGenerate(WorldGenLevel worldGenLevel, ChunkAccess chunkAccess, StructureFeatureManager structureFeatureManager, CallbackInfo ci) {
bclib_featureIteratorSeed = 0; 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.MappedRegistry;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.core.WritableRegistry;
import net.minecraft.world.level.biome.Biome; 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.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.synth.NormalNoise; import net.minecraft.world.level.levelgen.synth.NormalNoise;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@ -23,41 +28,42 @@ import java.util.OptionalInt;
@Mixin(DimensionType.class) @Mixin(DimensionType.class)
public class DimensionTypeMixin { public class DimensionTypeMixin {
@Inject( @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, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At("TAIL") 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) { 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 = mappedRegistry.getId(mappedRegistry.get(LevelStem.NETHER)); int id = writableRegistry.getId(writableRegistry.get(LevelStem.NETHER));
mappedRegistry.registerOrOverride( writableRegistry.registerOrOverride(
OptionalInt.of(id), OptionalInt.of(id),
LevelStem.NETHER, LevelStem.NETHER,
new LevelStem( new LevelStem(
() -> registry.getOrThrow(DimensionType.NETHER_LOCATION), registry.getOrCreateHolder(DimensionType.NETHER_LOCATION),
new NoiseBasedChunkGenerator( new NoiseBasedChunkGenerator(
noiseParamRegistry, structureRegistry,
new BCLibNetherBiomeSource(biomeRegistry, seed), noiseParamRegistry,
seed, new BCLibNetherBiomeSource(biomeRegistry, seed),
() -> noiseSettingsRegistry.getOrThrow(NoiseGeneratorSettings.NETHER) seed,
) noiseSettingsRegistry.getOrCreateHolder(NoiseGeneratorSettings.NETHER))
), ),
Lifecycle.stable() Lifecycle.stable()
); );
id = mappedRegistry.getId(mappedRegistry.get(LevelStem.END));
mappedRegistry.registerOrOverride( id = writableRegistry.getId(writableRegistry.get(LevelStem.END));
OptionalInt.of(id), writableRegistry.registerOrOverride(
LevelStem.END, OptionalInt.of(id),
new LevelStem( LevelStem.END,
() -> registry.getOrThrow(DimensionType.END_LOCATION), new LevelStem(
new NoiseBasedChunkGenerator( registry.getOrCreateHolder(DimensionType.END_LOCATION),
noiseParamRegistry, new NoiseBasedChunkGenerator(
new BCLibEndBiomeSource(biomeRegistry, seed), structureRegistry,
seed, noiseParamRegistry,
() -> noiseSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END) new BCLibEndBiomeSource(biomeRegistry, seed),
) seed,
), noiseSettingsRegistry.getOrCreateHolder(NoiseGeneratorSettings.END))
Lifecycle.stable() ),
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.GameProfileRepository;
import com.mojang.authlib.minecraft.MinecraftSessionService; import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixer;
import net.minecraft.core.RegistryAccess.RegistryHolder;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; 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.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListenerFactory; import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.repository.PackRepository;
@ -32,7 +31,7 @@ import java.util.concurrent.CompletableFuture;
@Mixin(MinecraftServer.class) @Mixin(MinecraftServer.class)
public class MinecraftServerMixin { public class MinecraftServerMixin {
@Shadow @Shadow
private ServerResources resources; private MinecraftServer.ReloadableResources resources;
@Final @Final
@Shadow @Shadow
@ -43,7 +42,7 @@ public class MinecraftServerMixin {
protected WorldData worldData; protected WorldData worldData;
@Inject(method = "<init>*", at = @At("TAIL")) @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(); DataExchangeAPI.prepareServerside();
} }
@ -58,7 +57,7 @@ public class MinecraftServerMixin {
} }
private void bclib_injectRecipes() { 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_setRecipesByName(BCLRecipeManager.getMapByName(accessor.bclib_getRecipesByName()));
accessor.bclib_setRecipes(BCLRecipeManager.getMap(accessor.bclib_getRecipes())); accessor.bclib_setRecipes(BCLRecipeManager.getMap(accessor.bclib_getRecipes()));
} }

View file

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

View file

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

View file

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

View file

@ -27,7 +27,7 @@ public abstract class RecipeManagerMixin {
} }
@Inject(method = "getRecipeFor", at = @At(value = "HEAD"), cancellable = true) @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(); Collection<Recipe<C>> values = byType(type).values();
List<Recipe<C>> list = new ArrayList<>(values); List<Recipe<C>> list = new ArrayList<>(values);
list.sort((v1, v2) -> { list.sort((v1, v2) -> {
@ -35,6 +35,6 @@ public abstract class RecipeManagerMixin {
boolean b2 = v2.getId().getNamespace().equals("minecraft"); boolean b2 = v2.getId().getNamespace().equals("minecraft");
return b1 ^ b2 ? (b1 ? 1 : -1) : 0; 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; package ru.bclib.mixin.common;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; 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.Level;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType; 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.LevelStorageSource.LevelStorageAccess;
import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData; import net.minecraft.world.level.storage.WritableLevelData;
@ -28,12 +30,12 @@ import java.util.function.Supplier;
public abstract class ServerLevelMixin extends Level { public abstract class ServerLevelMixin extends Level {
private static String bclib_lastWorld = null; 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); super(writableLevelData, resourceKey, dimensionType, supplier, bl, bl2, l);
} }
@Inject(method = "<init>*", at = @At("TAIL")) @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); ServerLevel level = ServerLevel.class.cast(this);
LifeCycleAPI._runLevelLoad(level, server, executor, levelStorageAccess, serverLevelData, resourceKey, dimensionType, chunkProgressListener, chunkGenerator, bl, l, list, bl2); 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; package ru.bclib.mixin.common;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
@ -25,10 +26,7 @@ public interface SurfaceRulesContextAccessor {
int getSurfaceDepth(); int getSurfaceDepth();
@Accessor("biome") @Accessor("biome")
Supplier<Biome> getBiome(); Supplier<Holder<Biome>> getBiome();
@Accessor("biomeKey")
Supplier<ResourceKey<Biome>> getBiomeKey();
@Accessor("chunk") @Accessor("chunk")
ChunkAccess getChunk(); ChunkAccess getChunk();

View file

@ -3,6 +3,7 @@ package ru.bclib.mixin.common;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag; import net.minecraft.tags.Tag;
import net.minecraft.tags.TagLoader; import net.minecraft.tags.TagLoader;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@ -13,10 +14,11 @@ import java.util.Map;
@Mixin(TagLoader.class) @Mixin(TagLoader.class)
public class TagLoaderMixin { public class TagLoaderMixin {
@Final
@Shadow @Shadow
private String directory; 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) { public Map<ResourceLocation, Tag.Builder> be_modifyTags(Map<ResourceLocation, Tag.Builder> tagsMap) {
return TagAPI.apply(directory, tagsMap); return TagAPI.apply(directory, tagsMap);
} }

View file

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

View file

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

View file

@ -4,6 +4,7 @@ import com.google.common.collect.Maps;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag; import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.CraftingRecipe;
@ -74,7 +75,7 @@ public class GridRecipe {
return this; return this;
} }
public GridRecipe addMaterial(char key, Tag<Item> value) { public GridRecipe addMaterial(char key, TagKey<Item> value) {
return addMaterial(key, Ingredient.of(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.resources.ResourceLocation;
import net.minecraft.tags.Tag; import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Ingredient;
@ -59,7 +60,7 @@ public class SmithingTableRecipe {
return this; return this;
} }
public SmithingTableRecipe setBase(Tag<Item> tag) { public SmithingTableRecipe setBase(TagKey<Item> tag) {
this.base = (Ingredient.of(tag)); this.base = (Ingredient.of(tag));
return this; return this;
} }
@ -70,7 +71,7 @@ public class SmithingTableRecipe {
return this; return this;
} }
public SmithingTableRecipe setAddition(Tag<Item> tag) { public SmithingTableRecipe setAddition(TagKey<Item> tag) {
this.addition = (Ingredient.of(tag)); this.addition = (Ingredient.of(tag));
return this; return this;
} }

View file

@ -44,8 +44,8 @@ public class ItemRegistry extends BaseRegistry<Item> {
if (!config.getBoolean("musicDiscs", itemId.getPath(), true)) { if (!config.getBoolean("musicDiscs", itemId.getPath(), true)) {
return item; return item;
} }
register(itemId, item);
return register(itemId, new BaseDiscItem(power, sound, makeItemSettings().stacksTo(1))); return item;
} }
public Item register(ResourceLocation itemId) { 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.Lists;
import com.google.common.collect.Maps; 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.core.Registry;
import net.minecraft.data.BuiltinRegistries; import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration; import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.SurfaceRules; 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 org.jetbrains.annotations.Nullable;
import ru.bclib.BCLib; import ru.bclib.BCLib;
import ru.bclib.api.biomes.BiomeAPI; import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.api.tag.TagAPI;
import ru.bclib.util.WeightedList; import ru.bclib.util.WeightedList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
public class BCLBiome extends BCLBiomeSettings { 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 WeightedList<BCLBiome> subbiomes = new WeightedList<>();
private final Map<String, Object> customData = Maps.newHashMap(); private final Map<String, Object> customData = Maps.newHashMap();
private final ResourceLocation biomeID; private final ResourceLocation biomeID;
private final Biome biome; private final Biome biome;
private Consumer<Biome> surfaceInit; private Consumer<Holder<Biome>> surfaceInit;
private BCLBiome biomeParent; private BCLBiome biomeParent;
private Biome actualBiome; private Holder<Biome> actualBiome;
/** /**
* Create wrapper for existing biome using its {@link ResourceLocation} identifier. * 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 * @param settings The Settings for this Biome or {@code null} if you want to apply default settings
*/ */
public BCLBiome(Biome biome, VanillaBiomeSettings 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) { public BCLBiome(ResourceLocation biomeID, Biome biome) {
@ -164,7 +167,10 @@ public class BCLBiome extends BCLBiomeSettings {
return biomeID; 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. * Getter for biome from buil-in registry. For datapack biomes will be same as actual biome.
* @return {@link 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). * Getter for actual biome (biome from current world registry with same {@link ResourceLocation} id).
* @return {@link Biome}. * @return {@link Biome}.
*/ */
public Biome getActualBiome() { public Holder<Biome> getActualBiome() {
return this.actualBiome; return this.actualBiome;
} }
@ -196,19 +202,23 @@ public class BCLBiome extends BCLBiomeSettings {
if (edge != null && edge != this) { if (edge != null && edge != this) {
edge.updateActualBiomes(biomeRegistry); 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) { if (actualBiome==null) {
BCLib.LOGGER.error("Unable to find actual Biome for " + biomeID); BCLib.LOGGER.error("Unable to find actual Biome for " + biomeID);
} }
if (!this.structures.isEmpty()) { if (!this.structureTags.isEmpty()) {
structures.forEach(s -> BiomeAPI.addBiomeStructure(BiomeAPI.getBiomeKey(actualBiome), s)); structureTags.forEach(tagKey -> TagAPI.addBiomeTag(tagKey, actualBiome.value()));
} }
if (this.surfaceInit != null) { if (this.surfaceInit != null) {
surfaceInit.accept(actualBiome); surfaceInit.accept(actualBiome);
} }
} }
/** /**
* Getter for custom data. Will get custom data object or null if object doesn't exists. * 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. * Adds structures to this biome. For internal use only.
* Used inside {@link ru.bclib.api.biomes.BCLBiomeBuilder}. * Used inside {@link ru.bclib.api.biomes.BCLBiomeBuilder}.
*/ */
public void attachStructures(List<ConfiguredStructureFeature> structures) { public void attachStructures(List<TagKey<Biome>> structures) {
this.structures.addAll(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 * Returns the group used in the config Files for this biome
* *

View file

@ -1,40 +1,59 @@
package ru.bclib.world.features; package ru.bclib.world.features;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries; 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.ResourceKey;
import net.minecraft.resources.ResourceLocation; 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.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.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; 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.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementModifier; import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import ru.bclib.api.features.BCLCommonFeatures;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Optional; import java.util.Optional;
public class BCLFeature { public class BCLFeature {
private PlacedFeature placedFeature; private final Holder<PlacedFeature> placedFeature;
private Decoration featureStep; private final Decoration featureStep;
private Feature<?> feature; private final Feature<?> feature;
public BCLFeature(ResourceLocation id, Feature<?> feature, Decoration featureStep, PlacedFeature placedFeature) {
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.placedFeature = placedFeature;
this.featureStep = featureStep; this.featureStep = featureStep;
this.feature = feature; this.feature = feature;
if (!BuiltinRegistries.PLACED_FEATURE.containsKey(id)) { 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)) { if (!Registry.FEATURE.containsKey(id) && !containsObj(Registry.FEATURE, feature)) {
Registry.register(Registry.FEATURE, id, 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) { private static <E> boolean containsObj(Registry<E> registry, E obj) {
Optional<Entry<ResourceKey<E>, E>> optional = registry Optional<Entry<ResourceKey<E>, E>> optional = registry
@ -57,7 +76,7 @@ public class BCLFeature {
* Get configured feature. * Get configured feature.
* @return {@link PlacedFeature}. * @return {@link PlacedFeature}.
*/ */
public PlacedFeature getPlacedFeature() { public Holder<PlacedFeature> getPlacedFeature() {
return placedFeature; return placedFeature;
} }
@ -68,92 +87,4 @@ public class BCLFeature {
public Decoration getDecoration() { public Decoration getDecoration() {
return featureStep; 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;
import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtIo;
@ -50,7 +51,7 @@ public abstract class NBTStructureFeature extends DefaultFeature {
protected abstract void addStructureData(StructurePlaceSettings data); protected abstract void addStructureData(StructurePlaceSettings data);
protected BlockPos getGround(WorldGenLevel world, BlockPos center) { protected BlockPos getGround(WorldGenLevel world, BlockPos center) {
Biome biome = world.getBiome(center); Holder<Biome> biome = world.getBiome(center);
ResourceLocation id = BiomeAPI.getBiomeID(biome); ResourceLocation id = BiomeAPI.getBiomeID(biome);
if (id.getNamespace().contains("moutain") || id.getNamespace().contains("lake")) { if (id.getNamespace().contains("moutain") || id.getNamespace().contains("lake")) {
int y = getAverageY(world, center); int y = getAverageY(world, center);
@ -148,7 +149,7 @@ public abstract class NBTStructureFeature extends DefaultFeature {
if (!isTerrain(stateSt)) { if (!isTerrain(stateSt)) {
if (merge == TerrainMerge.SURFACE) { if (merge == TerrainMerge.SURFACE) {
boolean isTop = mut.getY() == surfMax && state.getMaterial().isSolidBlocking(); 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); BlockState top = (isTop ? BiomeAPI.findTopMaterial(b) : BiomeAPI.findUnderMaterial(b)).orElse(defaultBlock);
BlocksHelper.setWithoutUpdate(world, mut, top); BlocksHelper.setWithoutUpdate(world, mut, top);
} }
@ -159,7 +160,7 @@ public abstract class NBTStructureFeature extends DefaultFeature {
else { else {
if (isTerrain(state) && state.getMaterial().isSolidBlocking()) { if (isTerrain(state) && state.getMaterial().isSolidBlocking()) {
if (merge == TerrainMerge.SURFACE) { if (merge == TerrainMerge.SURFACE) {
Biome b = world.getBiome(mut); Holder<Biome> b = world.getBiome(mut);
BlockState bottom = BiomeAPI.findUnderMaterial(b).orElse(defaultBlock); BlockState bottom = BiomeAPI.findUnderMaterial(b).orElse(defaultBlock);
BlocksHelper.setWithoutUpdate(world, mut, bottom); BlocksHelper.setWithoutUpdate(world, mut, bottom);
} }

View file

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

View file

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

View file

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

View file

@ -1,17 +1,27 @@
package ru.bclib.world.structures; package ru.bclib.world.structures;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.structure.v1.FabricStructureBuilder;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.QuartPos; 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.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.GenerationStep;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature; import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; 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.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.List;
import java.util.Random; import java.util.Random;
@ -19,23 +29,40 @@ import java.util.Random;
public class BCLStructureFeature { public class BCLStructureFeature {
private static final Random RANDOM = new Random(354); private static final Random RANDOM = new Random(354);
private final StructureFeature<NoneFeatureConfiguration> structure; private final StructureFeature<NoneFeatureConfiguration> structure;
private final ConfiguredStructureFeature<?, ?> featureConfigured; private final Holder<ConfiguredStructureFeature<?, ?>> featureConfigured;
private final GenerationStep.Decoration featureStep; private final GenerationStep.Decoration featureStep;
private final List<ResourceLocation> biomes = Lists.newArrayList(); private final List<ResourceLocation> biomes = Lists.newArrayList();
private final ResourceLocation id; 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) { 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.id = id;
this.featureStep = step; this.featureStep = step;
this.structure = FabricStructureBuilder //parts from vanilla for Structure generation
.create(id, structure) //public static final ResourceKey<ConfiguredStructureFeature<?, ?>> JUNGLE_TEMPLE =
.step(step) // BuiltinStructures.createKey("jungle_pyramid");
.defaultConfig(spacing, separation, RANDOM.nextInt(8192)) //public static final Holder<ConfiguredStructureFeature<?, ?>> JUNGLE_TEMPLE =
.register(); // StructureFeatures.register(BuiltinStructures.JUNGLE_TEMPLE, StructureFeature.JUNGLE_TEMPLE.configured(NoneFeatureConfiguration.INSTANCE, BiomeTags.HAS_JUNGLE_TEMPLE));
this.featureConfigured = this.structure.configured(NoneFeatureConfiguration.NONE); //public static final Holder<StructureSet> JUNGLE_TEMPLES =
BuiltinRegistries.register(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE, id, this.featureConfigured); // StructureSets.register(BuiltinStructureSets.JUNGLE_TEMPLES, StructureFeatures.JUNGLE_TEMPLE, new RandomSpreadStructurePlacement(32, 8, RandomSpreadType.LINEAR, 14357619));
//TODO: 1.18 check if structures are added correctly //public static final StructureFeature<NoneFeatureConfiguration> JUNGLE_TEMPLE =
//FlatChunkGeneratorConfigAccessor.getStructureToFeatures().put(this.structure, this.featureConfigured); // 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; return structure;
} }
public ConfiguredStructureFeature<?, ?> getFeatureConfigured() { public Holder<ConfiguredStructureFeature<?, ?>> getFeatureConfigured() {
return featureConfigured; return featureConfigured;
} }

View file

@ -52,5 +52,7 @@
"title.bclib.datafixer.error": "Fehler beim Reparieren der Welt", "title.bclib.datafixer.error": "Fehler beim Reparieren der Welt",
"message.bclib.datafixer.error": "Es gab Fehler beim Reparieren der Welt. Das bedeutet, dass dieser Level wahrscheinlich in einem inkonsistenten Zustand ist und Sie ihn nicht spielen sollten. Bitte stellen Sie Ihr Backup wieder her und beheben Sie die unten aufgeführten Fehler, bevor Sie es erneut versuchen.", "message.bclib.datafixer.error": "Es gab Fehler beim Reparieren der Welt. Das bedeutet, dass dieser Level wahrscheinlich in einem inkonsistenten Zustand ist und Sie ihn nicht spielen sollten. Bitte stellen Sie Ihr Backup wieder her und beheben Sie die unten aufgeführten Fehler, bevor Sie es erneut versuchen.",
"title.bclib.datafixer.error.continue": "Continue and Mark as Fixed", "title.bclib.datafixer.error.continue": "Continue and Mark as Fixed",
"title.config.bclib.main.ui.suppressExperimentalDialogOnLoad": "Disable Experimental Warning Screen on Load" "title.config.bclib.main.ui.suppressExperimentalDialogOnLoad": "Disable Experimental Warning Screen on Load",
"tooltip.bclib.place_on": "Lebt auf: %s"
} }

View file

@ -54,5 +54,7 @@
"title.bclib.datafixer.error.continue": "Proceed and mark as fixed", "title.bclib.datafixer.error.continue": "Proceed and mark as fixed",
"title.config.bclib.client.rendering.customFogRendering": "Custom Fog Rendering", "title.config.bclib.client.rendering.customFogRendering": "Custom Fog Rendering",
"title.config.bclib.client.rendering.netherThickFog": "Nether Thick Fog" "title.config.bclib.client.rendering.netherThickFog": "Nether Thick Fog",
"tooltip.bclib.place_on": "Survives on: %s"
} }

View file

@ -1,6 +1,7 @@
accessWidener v1 named accessWidener v1 named
# Classes # Classes
accessible class net/minecraft/server/MinecraftServer$ReloadableResources
accessible class net/minecraft/client/Minecraft$ExperimentalDialogType accessible class net/minecraft/client/Minecraft$ExperimentalDialogType
accessible class net/minecraft/world/level/levelgen/SurfaceRules$Context accessible class net/minecraft/world/level/levelgen/SurfaceRules$Context
accessible class net/minecraft/world/level/levelgen/SurfaceRules$Condition accessible class net/minecraft/world/level/levelgen/SurfaceRules$Condition

View file

@ -4,7 +4,6 @@
"package": "ru.bclib.mixin.client", "package": "ru.bclib.mixin.client",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"client": [ "client": [
"SimpleReloadableResourceManagerMixin",
"EnchantingTableBlockMixin", "EnchantingTableBlockMixin",
"ClientRecipeBookMixin", "ClientRecipeBookMixin",
"ModelManagerMixin", "ModelManagerMixin",
@ -14,7 +13,8 @@
"ModelBakeryMixin", "ModelBakeryMixin",
"WorldPresetMixin", "WorldPresetMixin",
"MinecraftMixin", "MinecraftMixin",
"GameMixin" "GameMixin",
"BlockMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1

View file

@ -4,7 +4,6 @@
"package": "ru.bclib.mixin.common", "package": "ru.bclib.mixin.common",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"mixins": [ "mixins": [
"SimpleReloadableResourceManagerMixin",
"BiomeGenerationSettingsAccessor", "BiomeGenerationSettingsAccessor",
"shears.DiggingEnchantmentMixin", "shears.DiggingEnchantmentMixin",
"shears.ItemPredicateBuilderMixin", "shears.ItemPredicateBuilderMixin",
@ -13,7 +12,6 @@
"NoiseGeneratorSettingsMixin", "NoiseGeneratorSettingsMixin",
"SurfaceRulesContextAccessor", "SurfaceRulesContextAccessor",
"shears.TripWireBlockMixin", "shears.TripWireBlockMixin",
"StructureSettingsAccessor",
"MobSpawnSettingsAccessor", "MobSpawnSettingsAccessor",
"shears.BeehiveBlockMixin", "shears.BeehiveBlockMixin",
"shears.PumpkinBlockMixin", "shears.PumpkinBlockMixin",
@ -21,8 +19,8 @@
"ComposterBlockAccessor", "ComposterBlockAccessor",
"PotionBrewingAccessor", "PotionBrewingAccessor",
"RecipeManagerAccessor", "RecipeManagerAccessor",
"DiggerItemAccessor",
"shears.SnowGolemMixin", "shears.SnowGolemMixin",
"EnchantmentMenuMixin",
"MinecraftServerMixin", "MinecraftServerMixin",
"NetherBiomeDataMixin", "NetherBiomeDataMixin",
"PistonBaseBlockMixin", "PistonBaseBlockMixin",
@ -42,7 +40,10 @@
"AnvilBlockMixin", "AnvilBlockMixin",
"AnvilMenuMixin", "AnvilMenuMixin",
"TagLoaderMixin", "TagLoaderMixin",
"MainMixin" "MainMixin",
"BiomeAccessor",
"StructureFeatureAccessor",
"StructureFeaturesAccessor"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1

View file

@ -37,9 +37,9 @@
"bclib.mixins.client.json" "bclib.mixins.client.json"
], ],
"depends": { "depends": {
"fabricloader": ">=0.12.9", "fabricloader": ">=0.13.3",
"fabric": ">=0.44.0", "fabric": ">=0.48.0",
"minecraft": "1.18.x" "minecraft": "1.18.2"
}, },
"custom":{ "custom":{
"modmenu":{ "modmenu":{