diff --git a/bclib.gradle b/bclib.gradle index 3ff8796e..ec8dbbaf 100644 --- a/bclib.gradle +++ b/bclib.gradle @@ -7,8 +7,8 @@ buildscript { gradlePluginPortal() } } -sourceCompatibility = JavaVersion.VERSION_16 -targetCompatibility = JavaVersion.VERSION_16 +sourceCompatibility = JavaVersion.VERSION_17 +targetCompatibility = JavaVersion.VERSION_17 archivesBaseName = project.archives_base_name version = project.mod_version diff --git a/gradle.properties b/gradle.properties index 5b8a020f..47e71b78 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,12 +6,12 @@ loom_version=0.10-SNAPSHOT # Fabric Properties # check these on https://fabricmc.net/versions.html -minecraft_version= 1.18-pre1 -loader_version= 0.12.5 -fabric_version = 0.42.2+1.18 +minecraft_version= 1.18 +loader_version= 0.12.6 +fabric_version = 0.43.1+1.18 # Mod Properties -mod_version = 0.5.1 +mod_version = 0.5.5 maven_group = ru.bclib archives_base_name = bclib diff --git a/src/main/java/ru/bclib/BCLib.java b/src/main/java/ru/bclib/BCLib.java index 18e94261..1e450f96 100644 --- a/src/main/java/ru/bclib/BCLib.java +++ b/src/main/java/ru/bclib/BCLib.java @@ -3,7 +3,6 @@ package ru.bclib; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; import ru.bclib.api.TagAPI; import ru.bclib.api.WorldDataAPI; @@ -23,8 +22,6 @@ import ru.bclib.world.generator.BCLibNetherBiomeSource; import ru.bclib.world.generator.GeneratorOptions; import ru.bclib.world.surface.BCLSurfaceBuilders; -import java.lang.reflect.Array; -import java.lang.reflect.Field; import java.util.List; public class BCLib implements ModInitializer { diff --git a/src/main/java/ru/bclib/BCLibPatch.java b/src/main/java/ru/bclib/BCLibPatch.java index d7db7d40..44e4bc51 100644 --- a/src/main/java/ru/bclib/BCLibPatch.java +++ b/src/main/java/ru/bclib/BCLibPatch.java @@ -3,7 +3,7 @@ package ru.bclib; import net.minecraft.nbt.CompoundTag; import ru.bclib.api.datafixer.DataFixerAPI; import ru.bclib.api.datafixer.Patch; -import ru.bclib.api.datafixer.PatchFunction; +import ru.bclib.interfaces.PatchFunction; diff --git a/src/main/java/ru/bclib/api/BiomeAPI.java b/src/main/java/ru/bclib/api/BiomeAPI.java index 50260684..4cd48391 100644 --- a/src/main/java/ru/bclib/api/BiomeAPI.java +++ b/src/main/java/ru/bclib/api/BiomeAPI.java @@ -1,13 +1,17 @@ package ru.bclib.api; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.impl.biome.InternalBiomeData; +import net.fabricmc.fabric.impl.biome.NetherBiomeData; +import net.fabricmc.fabric.impl.biome.TheEndBiomeData; import net.fabricmc.fabric.mixin.biome.modification.GenerationSettingsAccessor; +import net.fabricmc.fabric.mixin.biome.modification.SpawnSettingsAccessor; import net.minecraft.client.Minecraft; import net.minecraft.core.Registry; import net.minecraft.data.BuiltinRegistries; @@ -15,11 +19,16 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.random.WeightedRandomList; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.Biome.ClimateParameters; +import net.minecraft.world.biome.Biome.ClimateParameters; import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData; import net.minecraft.world.level.levelgen.GenerationStep.Decoration; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; @@ -31,6 +40,8 @@ import ru.bclib.world.features.BCLFeature; import ru.bclib.world.generator.BiomePicker; import ru.bclib.world.structures.BCLStructureFeature; +import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; @@ -114,8 +125,8 @@ public class BiomeAPI { registerBiome(biome); NETHER_BIOME_PICKER.addBiome(biome); Random random = new Random(biome.getID().hashCode()); - //TODO: (1.18) did they add depth and scale as two new params here??? - Climate.ParameterPoint parameters = Climate.parameters( + //TODO: (1.18) did they add depth and scale as two new params here??? + ClimateParameters parameters = new ClimateParameters( MHelper.randRange(-1.5F, 1.5F, random), MHelper.randRange(-1.5F, 1.5F, random), MHelper.randRange(-1.5F, 1.5F, random), @@ -396,7 +407,10 @@ public class BiomeAPI { biomes.forEach(biome -> { ResourceLocation biomeID = getBiomeID(biome); boolean modify = isDatapackBiome(biomeID); - if (!modify && !MODIFIED_BIOMES.contains(biomeID)) { + if (biome != BuiltinRegistries.BIOME.get(biomeID)) { + modify = true; + } + else if (!modify && !MODIFIED_BIOMES.contains(biomeID)) { MODIFIED_BIOMES.add(biomeID); modify = true; } @@ -417,13 +431,7 @@ public class BiomeAPI { public static void addBiomeFeature(Biome biome, ConfiguredFeature feature, Decoration step) { GenerationSettingsAccessor accessor = (GenerationSettingsAccessor) biome.getGenerationSettings(); List>>> biomeFeatures = getMutableList(accessor.fabric_getFeatures()); - int index = step.ordinal(); - if (biomeFeatures.size() < index) { - for (int i = biomeFeatures.size(); i <= index; i++) { - biomeFeatures.add(Lists.newArrayList()); - } - } - List>> list = getMutableList(biomeFeatures.get(index)); + List>> list = getList(step, biomeFeatures); list.add(() -> feature); accessor.fabric_setFeatures(biomeFeatures); } @@ -437,18 +445,30 @@ public class BiomeAPI { GenerationSettingsAccessor accessor = (GenerationSettingsAccessor) biome.getGenerationSettings(); List>>> biomeFeatures = getMutableList(accessor.fabric_getFeatures()); for (BCLFeature feature: features) { - int index = feature.getFeatureStep().ordinal(); - if (biomeFeatures.size() < index) { - for (int i = biomeFeatures.size(); i <= index; i++) { - biomeFeatures.add(Lists.newArrayList()); - } - } - List>> list = getMutableList(biomeFeatures.get(index)); + List>> list = getList(feature.getFeatureStep(), biomeFeatures); list.add(feature::getFeatureConfigured); } accessor.fabric_setFeatures(biomeFeatures); } + /** + * Getter for correct feature list from all biome feature list of lists. + * @param step feature {@link Decoration} step. + * @param lists biome accessor lists. + * @return mutable {@link ConfiguredFeature} list. + */ + private static List>> getList(Decoration step, List>>> lists) { + int index = step.ordinal(); + if (lists.size() <= index) { + for (int i = lists.size(); i <= index; i++) { + lists.add(Lists.newArrayList()); + } + } + List>> list = getMutableList(lists.get(index)); + lists.set(index, list); + return list; + } + /** * Adds new structure feature to existing biome. * @param biome {@link Biome} to add structure feature in. @@ -475,10 +495,41 @@ public class BiomeAPI { accessor.fabric_setStructureFeatures(biomeStructures); } + /** + * Adds mob spawning to specified biome. + * @param biome {@link Biome} to add mob spawning. + * @param entityType {@link EntityType} mob type. + * @param weight spawn weight. + * @param minGroupCount minimum mobs in group. + * @param maxGroupCount maximum mobs in group. + */ + public static void addBiomeMobSpawn(Biome biome, EntityType entityType, int weight, int minGroupCount, int maxGroupCount) { + MobCategory category = entityType.getCategory(); + SpawnSettingsAccessor accessor = (SpawnSettingsAccessor) biome.getMobSettings(); + Map> spawners = getMutableMap(accessor.fabric_getSpawners()); + List mobs = spawners.containsKey(category) ? getMutableList(spawners.get(category).unwrap()) : Lists.newArrayList(); + mobs.add(new SpawnerData(entityType, weight, minGroupCount, maxGroupCount)); + spawners.put(category, WeightedRandomList.create(mobs)); + accessor.fabric_setSpawners(spawners); + } + private static List getMutableList(List input) { - if (input instanceof ImmutableList) { + if (input!=null) { + System.out.println("getMutableList: " + input.getClass().getName()); + for (Class cl : input.getClass().getInterfaces()){ + System.out.println(" - " + cl.getName()); + } + } + if (/*input instanceof ImmutableList ||*/ !(input instanceof ArrayList || input instanceof LinkedList)) { return Lists.newArrayList(input); } return input; } + + private static Map getMutableMap(Map input) { + if (input instanceof ImmutableMap) { + return Maps.newHashMap(input); + } + return input; + } } diff --git a/src/main/java/ru/bclib/api/ComposterAPI.java b/src/main/java/ru/bclib/api/ComposterAPI.java new file mode 100644 index 00000000..ae9eda80 --- /dev/null +++ b/src/main/java/ru/bclib/api/ComposterAPI.java @@ -0,0 +1,22 @@ +package ru.bclib.api; + +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Block; +import ru.bclib.mixin.common.ComposterBlockAccessor; + +public class ComposterAPI { + public static Block allowCompost(float chance, Block block){ + if (block != null) { + allowCompost(chance, block.asItem()); + } + return block; + } + + public static Item allowCompost(float chance, Item item){ + if (item != null && item != Items.AIR) { + ComposterBlockAccessor.callAdd(chance, item); + } + return item; + } +} diff --git a/src/main/java/ru/bclib/api/LifeCycleAPI.java b/src/main/java/ru/bclib/api/LifeCycleAPI.java new file mode 100644 index 00000000..c50b83b9 --- /dev/null +++ b/src/main/java/ru/bclib/api/LifeCycleAPI.java @@ -0,0 +1,120 @@ +package ru.bclib.api; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.world.level.CustomSpawner; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.ServerLevelData; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; + +/** + * provides some lifetime hooks for a Minecraft instance + */ +public class LifeCycleAPI { + private final static List onLoadLevelBiomes = new ArrayList<>(2); + private final static List onLoadLevel = new ArrayList<>(2); + + /** + * A callback function that is used for each new ServerLevel instance + */ + public interface LevelLoadBiomesCall { + void onLoad(ServerLevel world, long seed, Registry registry); + } + + /** + * A callback function that is used for each new ServerLevel instance + */ + public interface LevelLoadCall { + void onLoad( + ServerLevel world, + MinecraftServer minecraftServer, + Executor executor, + LevelStorageSource.LevelStorageAccess levelStorageAccess, + ServerLevelData serverLevelData, + ResourceKey resourceKey, + DimensionType dimensionType, + ChunkProgressListener chunkProgressListener, + ChunkGenerator chunkGenerator, + boolean bl, + long l, + List list, + boolean bl2); + } + + /** + * Register a callback that is called when a new {@code ServerLevel is instantiated}. + * This callback will receive the world seed as well as it's biome registry. + * @param call The calbback Method + */ + public static void onLevelLoad(LevelLoadBiomesCall call){ + onLoadLevelBiomes.add(call); + } + + /** + * Register a callback that is called when a new {@code ServerLevel is instantiated}. + * This callbacl will receiv all parameters that were passed to the ServerLevel's constructor + * @param call The calbback Method + */ + public static void onLevelLoad(LevelLoadCall call){ + onLoadLevel.add(call); + } + + /** + * For internal use, You should not call this method! + * @param minecraftServer + * @param executor + * @param levelStorageAccess + * @param serverLevelData + * @param resourceKey + * @param dimensionType + * @param chunkProgressListener + * @param chunkGenerator + * @param bl + * @param l + * @param list + * @param bl2 + */ + public static void _runLevelLoad(ServerLevel world, + MinecraftServer minecraftServer, + Executor executor, + LevelStorageSource.LevelStorageAccess levelStorageAccess, + ServerLevelData serverLevelData, + ResourceKey resourceKey, + DimensionType dimensionType, + ChunkProgressListener chunkProgressListener, + ChunkGenerator chunkGenerator, + boolean bl, + long l, + List list, + boolean bl2){ + onLoadLevel.forEach(c -> c.onLoad( + world, + minecraftServer, + executor, + levelStorageAccess, + serverLevelData, + resourceKey, + dimensionType, + chunkProgressListener, + chunkGenerator, + bl, + l, + list, + bl2) + ); + + final long seed = world.getSeed(); + final Registry biomeRegistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); + onLoadLevelBiomes.forEach(c -> c.onLoad(world, seed, biomeRegistry)); + } +} diff --git a/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java b/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java index b63505c9..1a832f6f 100644 --- a/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java +++ b/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java @@ -32,6 +32,7 @@ import ru.bclib.util.Logger; import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.EOFException; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -570,6 +571,9 @@ public class DataFixerAPI { private static List getAllPlayers(File dir) { List list = new ArrayList<>(); dir = new File(dir, "playerdata"); + if (!dir.exists() || !dir.isDirectory()) { + return list; + } for (File file : dir.listFiles()) { if (file.isFile() && file.getName().endsWith(".dat")) { list.add(file); @@ -604,7 +608,7 @@ public class DataFixerAPI { private static CompoundTag readNbt(File file) throws IOException { try { return NbtIo.readCompressed(file); - } catch (ZipException e){ + } catch (ZipException | EOFException e){ return NbtIo.read(file); } } diff --git a/src/main/java/ru/bclib/api/datafixer/ForcedLevelPatch.java b/src/main/java/ru/bclib/api/datafixer/ForcedLevelPatch.java index 34951454..333d473b 100644 --- a/src/main/java/ru/bclib/api/datafixer/ForcedLevelPatch.java +++ b/src/main/java/ru/bclib/api/datafixer/ForcedLevelPatch.java @@ -3,6 +3,8 @@ package ru.bclib.api.datafixer; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import org.jetbrains.annotations.NotNull; +import ru.bclib.interfaces.PatchBiFunction; +import ru.bclib.interfaces.PatchFunction; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java b/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java index 26065093..831470ff 100644 --- a/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java +++ b/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java @@ -7,6 +7,8 @@ import net.minecraft.nbt.Tag; import org.jetbrains.annotations.NotNull; import ru.bclib.BCLib; import ru.bclib.api.WorldDataAPI; +import ru.bclib.interfaces.PatchBiFunction; +import ru.bclib.interfaces.PatchFunction; import ru.bclib.util.ModUtil; import java.io.File; diff --git a/src/main/java/ru/bclib/api/datafixer/Patch.java b/src/main/java/ru/bclib/api/datafixer/Patch.java index bc64e3c5..30a26ce7 100644 --- a/src/main/java/ru/bclib/api/datafixer/Patch.java +++ b/src/main/java/ru/bclib/api/datafixer/Patch.java @@ -3,6 +3,8 @@ package ru.bclib.api.datafixer; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import org.jetbrains.annotations.NotNull; +import ru.bclib.interfaces.PatchBiFunction; +import ru.bclib.interfaces.PatchFunction; import ru.bclib.util.ModUtil; import java.util.ArrayList; diff --git a/src/main/java/ru/bclib/api/spawning/SpawnRuleBuilder.java b/src/main/java/ru/bclib/api/spawning/SpawnRuleBuilder.java new file mode 100644 index 00000000..02ca1ccd --- /dev/null +++ b/src/main/java/ru/bclib/api/spawning/SpawnRuleBuilder.java @@ -0,0 +1,308 @@ +package ru.bclib.api.spawning; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import net.fabricmc.fabric.mixin.object.builder.SpawnRestrictionAccessor; +import net.minecraft.core.BlockPos; +import net.minecraft.world.Difficulty; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.SpawnPlacements.SpawnPredicate; +import net.minecraft.world.entity.SpawnPlacements.Type; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.phys.AABB; +import ru.bclib.interfaces.SpawnRule; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +public class SpawnRuleBuilder { + private static final Map RULES_CACHE = Maps.newHashMap(); + private static final SpawnRuleBuilder INSTANCE = new SpawnRuleBuilder(); + private List rules = Lists.newArrayList(); + private SpawnRuleEntry entryInstance; + private EntityType entityType; + + private SpawnRuleBuilder() {} + + /** + * Starts new rule building process. + * @return prepared {@link SpawnRuleBuilder} instance. + */ + public static SpawnRuleBuilder start(EntityType entityType) { + INSTANCE.entityType = entityType; + INSTANCE.rules.clear(); + return INSTANCE; + } + + /** + * Stop entity spawn on peaceful {@link Difficulty} + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder notPeaceful() { + entryInstance = getFromCache("not_peaceful", () -> { + return new SpawnRuleEntry(0, (type, world, spawnReason, pos, random) -> world.getDifficulty() != Difficulty.PEACEFUL); + }); + rules.add(entryInstance); + return this; + } + + /** + * Restricts entity spawn above world surface (flying mobs). + * @param minHeight minimal spawn height. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder aboveGround(int minHeight) { + entryInstance = getFromCache("above_ground", () -> { + return new SpawnRuleEntry(0, (type, world, spawnReason, pos, random) -> { + if (pos.getY() < world.getMinBuildHeight() + 2) { + return false; + } + return pos.getY() > world.getHeight(Types.WORLD_SURFACE, pos.getX(), pos.getZ()) + minHeight; + }); + }); + rules.add(entryInstance); + return this; + } + + /** + * Restricts entity spawn below world logical height (useful for Nether mobs). + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder belowMaxHeight() { + entryInstance = getFromCache("below_max_height", () -> { + return new SpawnRuleEntry(0, (type, world, spawnReason, pos, random) -> pos.getY() < world.dimensionType().logicalHeight()); + }); + rules.add(entryInstance); + return this; + } + + /** + * Restricts spawning only to vanilla valid blocks. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder onlyOnValidBlocks() { + entryInstance = getFromCache("only_on_valid_blocks", () -> { + return new SpawnRuleEntry(0, (type, world, spawnReason, pos, random) -> { + BlockPos below = pos.below(); + return world.getBlockState(below).isValidSpawn(world, below, type); + }); + }); + rules.add(entryInstance); + return this; + } + + /** + * Restricts spawning only to specified blocks. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder onlyOnBlocks(Block... blocks) { + final Block[] floorBlocks = blocks; + Arrays.sort(floorBlocks, Comparator.comparing(Block::getDescriptionId)); + + StringBuilder builder = new StringBuilder("only_on_blocks"); + for (Block block : floorBlocks) { + builder.append('_'); + builder.append(block.getDescriptionId()); + } + + entryInstance = getFromCache(builder.toString(), () -> { + return new SpawnRuleEntry(0, (type, world, spawnReason, pos, random) -> { + Block below = world.getBlockState(pos.below()).getBlock(); + for (Block floor: floorBlocks) { + if (floor == below) { + return true; + } + } + return false; + }); + }); + + rules.add(entryInstance); + return this; + } + + /** + * Will spawn entity with 1 / chance probability (randomly). + * @param chance probability limit. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder withChance(int chance) { + entryInstance = getFromCache("with_chance_" + chance, () -> { + return new SpawnRuleEntry(1, (type, world, spawnReason, pos, random) -> random.nextInt(chance) == 0); + }); + rules.add(entryInstance); + return this; + } + + /** + * Will spawn entity only below specified brightness value. + * @param lightLevel light level upper limit. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder belowBrightness(int lightLevel) { + entryInstance = getFromCache("below_brightness_" + lightLevel, () -> { + return new SpawnRuleEntry(2, (type, world, spawnReason, pos, random) -> world.getMaxLocalRawBrightness(pos) <= lightLevel); + }); + rules.add(entryInstance); + return this; + } + + /** + * Will spawn entity only above specified brightness value. + * @param lightLevel light level lower limit. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder aboveBrightness(int lightLevel) { + entryInstance = getFromCache("above_brightness_" + lightLevel, () -> { + return new SpawnRuleEntry(2, (type, world, spawnReason, pos, random) -> world.getMaxLocalRawBrightness(pos) >= lightLevel); + }); + rules.add(entryInstance); + return this; + } + + /** + * Entity spawn will follow common vanilla spawn rules - spawn in darkness and not on peaceful level. + * @param lightLevel light level upper limit. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder hostile(int lightLevel) { + return notPeaceful().belowBrightness(lightLevel); + } + + /** + * Entity spawn will follow common vanilla spawn rules - spawn in darkness (below light level 7) and not on peaceful level. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder vanillaHostile() { + return hostile(7); + } + + /** + * Will spawn entity only if count of nearby entities will be lower than specified. + * @param selectorType selector {@link EntityType} to search. + * @param count max entity count. + * @param side side of box to search in. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder maxNearby(EntityType selectorType, int count, int side) { + final Class baseClass = selectorType.getBaseClass(); + entryInstance = getFromCache("max_nearby_" + selectorType.getDescriptionId()+"_"+count+"_"+side, () -> { + return new SpawnRuleEntry(3, (type, world, spawnReason, pos, random) -> { + try { + final AABB box = new AABB(pos).inflate(side, world.getHeight(), side); + final List list = world.getEntitiesOfClass(baseClass, box, (entity) -> true); + return list.size() < count; + } + catch (Exception e) { + return true; + } + }); + }); + rules.add(entryInstance); + return this; + } + + /** + * Will spawn entity only if count of nearby entities with same type will be lower than specified. + * @param count max entity count. + * @param side side of box to search in. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder maxNearby(int count, int side) { + return maxNearby(entityType, count, side); + } + + /** + * Will spawn entity only if count of nearby entities with same type will be lower than specified. + * @param count max entity count. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder maxNearby(int count) { + return maxNearby(entityType, count, 256); + } + + /** + * Allows to add custom spawning rule for specific entities. + * @param rule {@link SpawnRule} rule, can be a lambda expression. + * @return same {@link SpawnRuleBuilder} instance. + */ + public SpawnRuleBuilder customRule(SpawnRule rule) { + rules.add(new SpawnRuleEntry(7, rule)); + return this; + } + + /** + * Finalize spawning rule creation. + * @param spawnType {@link Type} of spawn. + * @param heightmapType {@link Types} heightmap type. + */ + public void build(Type spawnType, Types heightmapType) { + final List rulesCopy = Lists.newArrayList(this.rules); + Collections.sort(rulesCopy); + + SpawnPredicate predicate = (entityType, serverLevelAccessor, mobSpawnType, blockPos, random) -> { + for (SpawnRuleEntry rule: rulesCopy) { + if (!rule.canSpawn(entityType, serverLevelAccessor, mobSpawnType, blockPos, random)) { + return false; + } + } + return true; + }; + + SpawnRestrictionAccessor.callRegister(entityType, spawnType, heightmapType, predicate); + } + + /** + * Finalize spawning rule creation with No Restrictions spawn type, useful for flying entities. + * @param heightmapType {@link Types} heightmap type. + */ + public void buildNoRestrictions(Types heightmapType) { + build(Type.NO_RESTRICTIONS, heightmapType); + } + + /** + * Finalize spawning rule creation with On Ground spawn type, useful for common entities. + * @param heightmapType {@link Types} heightmap type. + */ + public void buildOnGround(Types heightmapType) { + build(Type.ON_GROUND, heightmapType); + } + + /** + * Finalize spawning rule creation with In Water spawn type, useful for water entities. + * @param heightmapType {@link Types} heightmap type. + */ + public void buildInWater(Types heightmapType) { + build(Type.IN_WATER, heightmapType); + } + + /** + * Finalize spawning rule creation with In Lava spawn type, useful for lava entities. + * @param heightmapType {@link Types} heightmap type. + */ + public void buildInLava(Types heightmapType) { + build(Type.IN_LAVA, heightmapType); + } + + /** + * Internal function, will take entry from cache or create it if necessary. + * @param name {@link String} entry internal name. + * @param supplier {@link Supplier} for {@link SpawnRuleEntry}. + * @return new or existing {@link SpawnRuleEntry}. + */ + private static SpawnRuleEntry getFromCache(String name, Supplier supplier) { + SpawnRuleEntry entry = RULES_CACHE.get(name); + if (entry == null) { + entry = supplier.get(); + RULES_CACHE.put(name, entry); + } + return entry; + } +} diff --git a/src/main/java/ru/bclib/api/spawning/SpawnRuleEntry.java b/src/main/java/ru/bclib/api/spawning/SpawnRuleEntry.java new file mode 100644 index 00000000..710860c6 --- /dev/null +++ b/src/main/java/ru/bclib/api/spawning/SpawnRuleEntry.java @@ -0,0 +1,30 @@ +package ru.bclib.api.spawning; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.level.LevelAccessor; +import org.jetbrains.annotations.NotNull; +import ru.bclib.interfaces.SpawnRule; + +import java.util.Random; + +public class SpawnRuleEntry implements Comparable { + private final SpawnRule rule; + private final byte priority; + + public SpawnRuleEntry(int priority, SpawnRule rule) { + this.priority = (byte) priority; + this.rule = rule; + } + + boolean canSpawn(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { + return rule.canSpawn(type, world, spawnReason, pos, random); + } + + @Override + public int compareTo(@NotNull SpawnRuleEntry entry) { + return Integer.compare(priority, entry.priority); + } +} diff --git a/src/main/java/ru/bclib/blockentities/BaseBarrelBlockEntity.java b/src/main/java/ru/bclib/blockentities/BaseBarrelBlockEntity.java index f517d01b..9965baf5 100644 --- a/src/main/java/ru/bclib/blockentities/BaseBarrelBlockEntity.java +++ b/src/main/java/ru/bclib/blockentities/BaseBarrelBlockEntity.java @@ -94,7 +94,7 @@ public class BaseBarrelBlockEntity extends RandomizableContainerBlockEntity { } private void scheduleUpdate() { - level.getBlockTicks().scheduleTick(getBlockPos(), getBlockState().getBlock(), 5); + level.getBlockTicks().schedule(getBlockPos(), getBlockState().getBlock(), 5); } public void tick() { diff --git a/src/main/java/ru/bclib/blocks/BaseAnvilBlock.java b/src/main/java/ru/bclib/blocks/BaseAnvilBlock.java index 9aca2c1d..dc5826af 100644 --- a/src/main/java/ru/bclib/blocks/BaseAnvilBlock.java +++ b/src/main/java/ru/bclib/blocks/BaseAnvilBlock.java @@ -40,7 +40,7 @@ public abstract class BaseAnvilBlock extends AnvilBlock implements BlockModelPro public IntegerProperty durability; public BaseAnvilBlock(MaterialColor color) { - super(FabricBlockSettings.copyOf(Blocks.ANVIL).mapColor(color)); + super(FabricBlockSettings.copyOf(Blocks.ANVIL).color(color)); } @Override diff --git a/src/main/java/ru/bclib/blocks/BaseChainBlock.java b/src/main/java/ru/bclib/blocks/BaseChainBlock.java index 9abdb58e..a0c5863c 100644 --- a/src/main/java/ru/bclib/blocks/BaseChainBlock.java +++ b/src/main/java/ru/bclib/blocks/BaseChainBlock.java @@ -28,7 +28,7 @@ import java.util.Optional; public class BaseChainBlock extends ChainBlock implements BlockModelProvider, RenderLayerProvider { public BaseChainBlock(MaterialColor color) { - super(FabricBlockSettings.copyOf(Blocks.CHAIN).mapColor(color)); + super(FabricBlockSettings.copyOf(Blocks.CHAIN).color(color)); } @Override diff --git a/src/main/java/ru/bclib/blocks/BaseFurnaceBlock.java b/src/main/java/ru/bclib/blocks/BaseFurnaceBlock.java index 09958ec8..ef5c0557 100644 --- a/src/main/java/ru/bclib/blocks/BaseFurnaceBlock.java +++ b/src/main/java/ru/bclib/blocks/BaseFurnaceBlock.java @@ -39,7 +39,7 @@ import java.util.Optional; public class BaseFurnaceBlock extends FurnaceBlock implements BlockModelProvider, RenderLayerProvider { public BaseFurnaceBlock(Block source) { - super(FabricBlockSettings.copyOf(source).luminance(state -> state.getValue(LIT) ? 13 : 0)); + super(FabricBlockSettings.copyOf(source).lightLevel(state -> state.getValue(LIT) ? 13 : 0)); } @Override diff --git a/src/main/java/ru/bclib/blocks/BaseLeavesBlock.java b/src/main/java/ru/bclib/blocks/BaseLeavesBlock.java index 63b000ec..e0a72abf 100644 --- a/src/main/java/ru/bclib/blocks/BaseLeavesBlock.java +++ b/src/main/java/ru/bclib/blocks/BaseLeavesBlock.java @@ -29,13 +29,13 @@ public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider, private static FabricBlockSettings makeLeaves(MaterialColor color) { return FabricBlockSettings.copyOf(Blocks.OAK_LEAVES) - .mapColor(color) + .color(color) .breakByTool(FabricToolTags.HOES) .breakByTool(FabricToolTags.SHEARS) .breakByHand(true) - .allowsSpawning((state, world, pos, type) -> false) - .suffocates((state, world, pos) -> false) - .blockVision((state, world, pos) -> false); + .isValidSpawn((state, world, pos, type) -> false) + .isSuffocating((state, world, pos) -> false) + .isViewBlocking((state, world, pos) -> false); } public BaseLeavesBlock(Block sapling, MaterialColor color, Consumer customizeProperties) { @@ -54,7 +54,7 @@ public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider, } public BaseLeavesBlock(Block sapling, MaterialColor color, int light) { - super(makeLeaves(color).luminance(light)); + super(makeLeaves(color).lightLevel(light)); this.sapling = sapling; } diff --git a/src/main/java/ru/bclib/blocks/BaseOreBlock.java b/src/main/java/ru/bclib/blocks/BaseOreBlock.java index f529c082..31963438 100644 --- a/src/main/java/ru/bclib/blocks/BaseOreBlock.java +++ b/src/main/java/ru/bclib/blocks/BaseOreBlock.java @@ -30,8 +30,8 @@ public class BaseOreBlock extends OreBlock implements BlockModelProvider { public BaseOreBlock(Item drop, int minCount, int maxCount, int experience) { this(drop, minCount, maxCount, experience, FabricBlockSettings.of(Material.STONE, MaterialColor.SAND) - .hardness(3F) - .resistance(9F) + .destroyTime(3F) + .explosionResistance(9F) .requiresCorrectToolForDrops() .sound(SoundType.STONE)); diff --git a/src/main/java/ru/bclib/blocks/BaseSignBlock.java b/src/main/java/ru/bclib/blocks/BaseSignBlock.java index 07a479ad..2d5cdffe 100644 --- a/src/main/java/ru/bclib/blocks/BaseSignBlock.java +++ b/src/main/java/ru/bclib/blocks/BaseSignBlock.java @@ -105,7 +105,7 @@ public class BaseSignBlock extends SignBlock implements BlockModelProvider, Cust @Override public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { if (state.getValue(WATERLOGGED)) { - world.getLiquidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + world.getFluidTicks().schedule(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } if (!canSurvive(state, world, pos)) { return state.getValue(WATERLOGGED) ? state.getFluidState() @@ -191,6 +191,6 @@ public class BaseSignBlock extends SignBlock implements BlockModelProvider, Cust @Override public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) { - return new BlockItem(this, settings.maxCount(16)); + return new BlockItem(this, settings.stacksTo(16)); } } \ No newline at end of file diff --git a/src/main/java/ru/bclib/blocks/BaseSlabBlock.java b/src/main/java/ru/bclib/blocks/BaseSlabBlock.java index 80550b77..ed9a6004 100644 --- a/src/main/java/ru/bclib/blocks/BaseSlabBlock.java +++ b/src/main/java/ru/bclib/blocks/BaseSlabBlock.java @@ -36,7 +36,8 @@ public class BaseSlabBlock extends SlabBlock implements BlockModelProvider { @Override @SuppressWarnings("deprecation") public List getDrops(BlockState state, LootContext.Builder builder) { - return Collections.singletonList(new ItemStack(this)); + int count = state.getValue(TYPE) == SlabType.DOUBLE ? 2 : 1; + return Collections.singletonList(new ItemStack(this, count)); } @Override diff --git a/src/main/java/ru/bclib/blocks/BaseStripableLogBlock.java b/src/main/java/ru/bclib/blocks/BaseStripableLogBlock.java index eb82ebbe..28127de4 100644 --- a/src/main/java/ru/bclib/blocks/BaseStripableLogBlock.java +++ b/src/main/java/ru/bclib/blocks/BaseStripableLogBlock.java @@ -20,7 +20,7 @@ public class BaseStripableLogBlock extends BaseRotatedPillarBlock { private final Block striped; public BaseStripableLogBlock(MaterialColor color, Block striped) { - super(FabricBlockSettings.copyOf(striped).mapColor(color)); + super(FabricBlockSettings.copyOf(striped).color(color)); this.striped = striped; } diff --git a/src/main/java/ru/bclib/blocks/SimpleLeavesBlock.java b/src/main/java/ru/bclib/blocks/SimpleLeavesBlock.java index 4f4d1128..51d6bf29 100644 --- a/src/main/java/ru/bclib/blocks/SimpleLeavesBlock.java +++ b/src/main/java/ru/bclib/blocks/SimpleLeavesBlock.java @@ -12,7 +12,7 @@ public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerPr public SimpleLeavesBlock(MaterialColor color) { super(FabricBlockSettings.of(Material.LEAVES) .strength(0.2F) - .mapColor(color) + .color(color) .sound(SoundType.GRASS) .noOcclusion() .isValidSpawn((state, world, pos, type) -> false) @@ -25,7 +25,7 @@ public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerPr public SimpleLeavesBlock(MaterialColor color, int light) { super(FabricBlockSettings.of(Material.LEAVES) .luminance(light) - .mapColor(color) + .color(color) .strength(0.2F) .sound(SoundType.GRASS) .noOcclusion() diff --git a/src/main/java/ru/bclib/blocks/StripableBarkBlock.java b/src/main/java/ru/bclib/blocks/StripableBarkBlock.java index d87f973a..328c6f1d 100644 --- a/src/main/java/ru/bclib/blocks/StripableBarkBlock.java +++ b/src/main/java/ru/bclib/blocks/StripableBarkBlock.java @@ -20,7 +20,7 @@ public class StripableBarkBlock extends BaseBarkBlock { private final Block striped; public StripableBarkBlock(MaterialColor color, Block striped) { - super(FabricBlockSettings.copyOf(striped).mapColor(color)); + super(FabricBlockSettings.copyOf(striped).color(color)); this.striped = striped; } diff --git a/src/main/java/ru/bclib/blocks/WallMushroomBlock.java b/src/main/java/ru/bclib/blocks/WallMushroomBlock.java index a4aabaf3..f03999e7 100644 --- a/src/main/java/ru/bclib/blocks/WallMushroomBlock.java +++ b/src/main/java/ru/bclib/blocks/WallMushroomBlock.java @@ -20,7 +20,7 @@ public abstract class WallMushroomBlock extends BaseWallPlantBlock { .breakByTool(FabricToolTags.AXES) .breakByHand(true) .luminance(light) - .hardness(0.2F) + .destroyTime(0.2F) .sound(SoundType.GRASS) .sound(SoundType.WOOD) .noCollission()); diff --git a/src/main/java/ru/bclib/blocks/properties/StringProperty.java b/src/main/java/ru/bclib/blocks/properties/StringProperty.java new file mode 100644 index 00000000..8aaff298 --- /dev/null +++ b/src/main/java/ru/bclib/blocks/properties/StringProperty.java @@ -0,0 +1,61 @@ +package ru.bclib.blocks.properties; + +import com.google.common.collect.Sets; +import net.minecraft.world.level.block.state.properties.Property; + +import java.util.Collection; +import java.util.Collections; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +@Deprecated +public class StringProperty extends Property { + private final Set values; + + public static StringProperty create(String name, String... values) { + return new StringProperty(name, values); + } + + protected StringProperty(String string, String... values) { + super(string, String.class); + this.values = Sets.newHashSet(values); + } + + public void addValue(String name) { + values.add(name); + } + + @Override + public Collection getPossibleValues() { + return Collections.unmodifiableSet(values); + } + + @Override + public String getName(String comparable) { + return comparable; + } + + @Override + public Optional getValue(String string) { + if (values.contains(string)) { + return Optional.of(string); + } + else { + return Optional.empty(); + } + } + + @Override + public int generateHashCode() { + return super.generateHashCode() + Objects.hashCode(values); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof StringProperty that)) return false; + if (!super.equals(o)) return false; + return values.equals(that.values); + } +} diff --git a/src/main/java/ru/bclib/config/Config.java b/src/main/java/ru/bclib/config/Config.java index ba2c8afb..a883116e 100644 --- a/src/main/java/ru/bclib/config/Config.java +++ b/src/main/java/ru/bclib/config/Config.java @@ -21,8 +21,8 @@ import java.util.List; import java.util.Map; public abstract class Config { + protected final static Map AUTO_SYNC_CONFIGS = new HashMap<>(); public static final String CONFIG_SYNC_PREFIX = "CONFIG_"; - protected final static Map autoSyncConfigs = new HashMap<>(); protected final ConfigKeeper keeper; protected final boolean autoSync; public final String configID; @@ -51,7 +51,7 @@ public abstract class Config { else DataExchangeAPI.addAutoSyncFile(aid.modID, aid.uniqueID, keeper.getConfigFile()); - autoSyncConfigs.put(aid, this); + AUTO_SYNC_CONFIGS.put(aid, this); BCLib.LOGGER.info("Added Config " + configID + " to auto sync (" + (diffContent?"content diff":"file hash") + ")"); } } @@ -70,7 +70,7 @@ public abstract class Config { } public static void reloadSyncedConfig(AutoSyncID aid, File file) { - Config cfg = autoSyncConfigs.get(aid); + Config cfg = AUTO_SYNC_CONFIGS.get(aid); if (cfg != null) { cfg.reload(); } diff --git a/src/main/java/ru/bclib/config/ConfigKeeper.java b/src/main/java/ru/bclib/config/ConfigKeeper.java index f3e6263e..e3711670 100644 --- a/src/main/java/ru/bclib/config/ConfigKeeper.java +++ b/src/main/java/ru/bclib/config/ConfigKeeper.java @@ -23,9 +23,9 @@ import java.util.function.Supplier; public final class ConfigKeeper { private final Map> configEntries = Maps.newHashMap(); - private JsonObject configObject; private final ConfigWriter writer; + private JsonObject configObject; private boolean changed = false; public ConfigKeeper(String modID, String group) { @@ -33,7 +33,7 @@ public final class ConfigKeeper { this.configObject = writer.load(); } - File getConfigFile() { + public File getConfigFile() { return this.writer.getConfigFile(); } @@ -141,7 +141,9 @@ public final class ConfigKeeper { } String paramKey = key.getEntry(); - paramKey += " [default: " + entry.getDefault() + "]"; + if (entry.hasDefaultInName()) { + paramKey += " [default: " + entry.getDefault() + "]"; + } this.changed |= entry.setLocation(obj, paramKey); } @@ -328,7 +330,6 @@ public final class ConfigKeeper { } public static class StringArrayEntry extends ArrayEntry { - public StringArrayEntry(List defaultValue) { super(defaultValue); } @@ -341,10 +342,14 @@ public final class ConfigKeeper { protected void add(JsonArray array, String el){ array.add(el); } + + @Override + protected boolean hasDefaultInName() { + return false; + } } public static class EnumEntry> extends Entry { - private final Type type; public EnumEntry(T defaultValue) { @@ -372,7 +377,6 @@ public final class ConfigKeeper { } public static abstract class RangeEntry> extends Entry { - private final T min, max; public RangeEntry(T defaultValue, T minVal, T maxVal) { @@ -396,7 +400,6 @@ public final class ConfigKeeper { } public static abstract class Entry { - protected final T defaultValue; protected Consumer writer; protected Supplier reader; @@ -448,5 +451,9 @@ public final class ConfigKeeper { public void setDefault() { this.setValue(defaultValue); } + + protected boolean hasDefaultInName() { + return true; + } } } diff --git a/src/main/java/ru/bclib/config/Configs.java b/src/main/java/ru/bclib/config/Configs.java index 2926b235..deac17d2 100644 --- a/src/main/java/ru/bclib/config/Configs.java +++ b/src/main/java/ru/bclib/config/Configs.java @@ -3,6 +3,9 @@ package ru.bclib.config; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import ru.bclib.BCLib; +import ru.bclib.config.ConfigKeeper.StringArrayEntry; + +import java.util.Collections; public class Configs { // Client and Server-Config must be the first entries. They are not part of the Auto-Sync process @@ -11,18 +14,24 @@ public class Configs { public static final ClientConfig CLIENT_CONFIG = new ClientConfig(); public static final ServerConfig SERVER_CONFIG = new ServerConfig(); - public static final PathConfig GENERATOR_CONFIG = new PathConfig(BCLib.MOD_ID, "generator", false); public static final PathConfig MAIN_CONFIG = new PathConfig(BCLib.MOD_ID, "main", true, true); - public static final String MAIN_PATCH_CATEGORY = "patches"; public static final PathConfig RECIPE_CONFIG = new PathConfig(BCLib.MOD_ID, "recipes"); - + public static final PathConfig BIOMES_CONFIG = new PathConfig(BCLib.MOD_ID, "biomes", false); + public static final String MAIN_PATCH_CATEGORY = "patches"; public static void save() { MAIN_CONFIG.saveChanges(); RECIPE_CONFIG.saveChanges(); GENERATOR_CONFIG.saveChanges(); + initForcedConfig(); + } + + private static void initForcedConfig() { + BIOMES_CONFIG.keeper.registerEntry(new ConfigKey("end_biomes", "force_include"), new StringArrayEntry(Collections.EMPTY_LIST)); + BIOMES_CONFIG.keeper.registerEntry(new ConfigKey("nether_biomes", "force_include"), new StringArrayEntry(Collections.EMPTY_LIST)); + BIOMES_CONFIG.saveChanges(); } } diff --git a/src/main/java/ru/bclib/config/PathConfig.java b/src/main/java/ru/bclib/config/PathConfig.java index 062e60ec..0bf8d1d3 100644 --- a/src/main/java/ru/bclib/config/PathConfig.java +++ b/src/main/java/ru/bclib/config/PathConfig.java @@ -6,7 +6,6 @@ import ru.bclib.config.ConfigKeeper.FloatRange; import ru.bclib.config.ConfigKeeper.IntegerRange; public class PathConfig extends Config { - public PathConfig(String modID, String group, boolean autoSync, boolean diffContent) { super(modID, group, autoSync, diffContent); } diff --git a/src/main/java/ru/bclib/entity/DespawnableAnimal.java b/src/main/java/ru/bclib/entity/DespawnableAnimal.java new file mode 100644 index 00000000..197673a1 --- /dev/null +++ b/src/main/java/ru/bclib/entity/DespawnableAnimal.java @@ -0,0 +1,16 @@ +package ru.bclib.entity; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.level.Level; + +public abstract class DespawnableAnimal extends Animal { + protected DespawnableAnimal(EntityType entityType, Level level) { + super(entityType, level); + } + + @Override + public boolean removeWhenFarAway(double d) { + return !this.hasCustomName(); + } +} diff --git a/src/main/java/ru/bclib/gui/gridlayout/GridScreen.java b/src/main/java/ru/bclib/gui/gridlayout/GridScreen.java index 663ca0dd..3d21990e 100644 --- a/src/main/java/ru/bclib/gui/gridlayout/GridScreen.java +++ b/src/main/java/ru/bclib/gui/gridlayout/GridScreen.java @@ -18,6 +18,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import org.jetbrains.annotations.Nullable; import ru.bclib.gui.gridlayout.GridLayout.Alignment; +import ru.bclib.util.Pair; @Environment(EnvType.CLIENT) diff --git a/src/main/java/ru/bclib/interfaces/IStructureFeatures.java b/src/main/java/ru/bclib/interfaces/IStructureFeatures.java deleted file mode 100644 index 11ac69be..00000000 --- a/src/main/java/ru/bclib/interfaces/IStructureFeatures.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.bclib.interfaces; - -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -public interface IStructureFeatures { - public void bclib_registerStructure(Consumer, ResourceKey>> callback); -} diff --git a/src/main/java/ru/bclib/api/datafixer/PatchBiFunction.java b/src/main/java/ru/bclib/interfaces/PatchBiFunction.java similarity index 52% rename from src/main/java/ru/bclib/api/datafixer/PatchBiFunction.java rename to src/main/java/ru/bclib/interfaces/PatchBiFunction.java index 6bd8da12..4bb345af 100644 --- a/src/main/java/ru/bclib/api/datafixer/PatchBiFunction.java +++ b/src/main/java/ru/bclib/interfaces/PatchBiFunction.java @@ -1,4 +1,7 @@ -package ru.bclib.api.datafixer; +package ru.bclib.interfaces; + +import ru.bclib.api.datafixer.MigrationProfile; +import ru.bclib.api.datafixer.PatchDidiFailException; @FunctionalInterface public interface PatchBiFunction { diff --git a/src/main/java/ru/bclib/api/datafixer/PatchFunction.java b/src/main/java/ru/bclib/interfaces/PatchFunction.java similarity index 50% rename from src/main/java/ru/bclib/api/datafixer/PatchFunction.java rename to src/main/java/ru/bclib/interfaces/PatchFunction.java index 7d429d68..809d55e0 100644 --- a/src/main/java/ru/bclib/api/datafixer/PatchFunction.java +++ b/src/main/java/ru/bclib/interfaces/PatchFunction.java @@ -1,4 +1,7 @@ -package ru.bclib.api.datafixer; +package ru.bclib.interfaces; + +import ru.bclib.api.datafixer.MigrationProfile; +import ru.bclib.api.datafixer.PatchDidiFailException; @FunctionalInterface public interface PatchFunction { diff --git a/src/main/java/ru/bclib/interfaces/SpawnRule.java b/src/main/java/ru/bclib/interfaces/SpawnRule.java new file mode 100644 index 00000000..8dffc463 --- /dev/null +++ b/src/main/java/ru/bclib/interfaces/SpawnRule.java @@ -0,0 +1,14 @@ +package ru.bclib.interfaces; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.level.LevelAccessor; + +import java.util.Random; + +@FunctionalInterface +public interface SpawnRule { + boolean canSpawn(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random); +} diff --git a/src/main/java/ru/bclib/mixin/client/MinecraftMixin.java b/src/main/java/ru/bclib/mixin/client/MinecraftMixin.java index aba7f73b..f1cb2523 100644 --- a/src/main/java/ru/bclib/mixin/client/MinecraftMixin.java +++ b/src/main/java/ru/bclib/mixin/client/MinecraftMixin.java @@ -2,6 +2,7 @@ package ru.bclib.mixin.client; import com.mojang.datafixers.util.Function4; import net.minecraft.client.Minecraft; +import net.minecraft.client.Minecraft.ExperimentalDialogType; import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.color.item.ItemColors; import net.minecraft.client.main.GameConfig; @@ -25,11 +26,6 @@ import ru.bclib.api.dataexchange.DataExchangeAPI; import ru.bclib.api.datafixer.DataFixerAPI; import ru.bclib.interfaces.CustomColorProvider; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; import java.util.function.Function; @Mixin(Minecraft.class) @@ -53,48 +49,13 @@ public abstract class MinecraftMixin { }); } -// @Shadow -// protected abstract void doLoadLevel(String string, RegistryHolder registryHolder, Function function, Function4 function4, boolean bl, ExperimentalDialogType experimentalDialogType); -// + @Shadow + protected abstract void doLoadLevel(String string, RegistryHolder registryHolder, Function function, Function4 function4, boolean bl, ExperimentalDialogType experimentalDialogType); + @Shadow @Final private LevelStorageSource levelSource; - Method doLoadLevel = null; - Object experimentalDialogType_BACKUP = null; - - private void bclib_doLoadLevel_BACKUP(String levelID, RegistryHolder registryHolder, Function function, Function4 function4, boolean bl){ - if (experimentalDialogType_BACKUP==null) { - try { - Class experimentalDialogType = Class.forName("net.minecraft.client.Minecraft$ExperimentalDialogType"); - Field f = experimentalDialogType.getDeclaredField("$VALUES"); - f.setAccessible(true); - experimentalDialogType_BACKUP = Array.get(f.get(null), 2); - } catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException e) { - e.printStackTrace(); - } - } - - if (doLoadLevel==null) { - for (Method m : Minecraft.class.getDeclaredMethods()) { - if (m.getName().equals("doLoadLevel")) { - doLoadLevel = m; - break; - } - } - } - - if (doLoadLevel!=null && experimentalDialogType_BACKUP!=null){ - doLoadLevel.setAccessible(true); - try { - doLoadLevel.invoke(this, new Object[]{levelID, registryHolder, function, function4, bl, experimentalDialogType_BACKUP}); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - } - + @Inject(method = "loadLevel", cancellable = true, at = @At("HEAD")) private void bclib_callFixerOnLoad(String levelID, CallbackInfo ci) { DataExchangeAPI.prepareServerside(); diff --git a/src/main/java/ru/bclib/mixin/client/StructureFeaturesMixin.java b/src/main/java/ru/bclib/mixin/client/StructureFeaturesMixin.java deleted file mode 100644 index b37a0d77..00000000 --- a/src/main/java/ru/bclib/mixin/client/StructureFeaturesMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.bclib.mixin.client; - -import net.minecraft.data.worldgen.StructureFeatures; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; -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.IStructureFeatures; - -import java.util.LinkedList; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -@Mixin(StructureFeatures.class) -public abstract class StructureFeaturesMixin implements IStructureFeatures { - @Inject(method="registerStructures", at=@At("TAIL")) - private static void bclib_registerStructures(BiConsumer, ResourceKey> biConsumer, CallbackInfo ci){ - bclib_callbacks.forEach(consumer -> consumer.accept(biConsumer)); - bclib_callbacks.clear(); - } - - private static List, ResourceKey>> > bclib_callbacks = new LinkedList<>(); - public void bclib_registerStructure(Consumer, ResourceKey>> callback){ - bclib_callbacks.add(callback); - } -} diff --git a/src/main/java/ru/bclib/mixin/common/ChunkGeneratorMixin.java b/src/main/java/ru/bclib/mixin/common/BiomeMixin.java similarity index 61% rename from src/main/java/ru/bclib/mixin/common/ChunkGeneratorMixin.java rename to src/main/java/ru/bclib/mixin/common/BiomeMixin.java index a18fbe2a..26f16bcb 100644 --- a/src/main/java/ru/bclib/mixin/common/ChunkGeneratorMixin.java +++ b/src/main/java/ru/bclib/mixin/common/BiomeMixin.java @@ -2,9 +2,7 @@ package ru.bclib.mixin.common; import net.minecraft.core.BlockPos; import net.minecraft.server.level.WorldGenRegion; -import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.StructureFeatureManager; -import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.WorldgenRandom; @@ -14,17 +12,17 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(ChunkGenerator.class) -public class ChunkGeneratorMixin { +@Mixin(Biome.class) +public class BiomeMixin { private int bclib_featureIteratorSeed; - @ModifyArg(method = "applyBiomeDecoration", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldgenRandom;setFeatureSeed(JII)V")) + @ModifyArg(method = "generate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldgenRandom;setFeatureSeed(JII)J")) private long bclib_updateFeatureSeed(long seed) { return Long.rotateRight(seed, bclib_featureIteratorSeed++); } - @Inject(method = "applyBiomeDecoration", at = @At("HEAD")) - private void bclib_obBiomeGenerate(WorldGenLevel level, ChunkPos pos, StructureFeatureManager manager, CallbackInfo ci) { + @Inject(method = "generate", at = @At("HEAD")) + private void bclib_obBiomeGenerate(StructureFeatureManager structureFeatureManager, ChunkGenerator chunkGenerator, WorldGenRegion worldGenRegion, long l, WorldgenRandom worldgenRandom, BlockPos blockPos, CallbackInfo info) { bclib_featureIteratorSeed = 0; } } diff --git a/src/main/java/ru/bclib/mixin/common/BoneMealItemMixin.java b/src/main/java/ru/bclib/mixin/common/BoneMealItemMixin.java index 432345f1..52357c1a 100644 --- a/src/main/java/ru/bclib/mixin/common/BoneMealItemMixin.java +++ b/src/main/java/ru/bclib/mixin/common/BoneMealItemMixin.java @@ -29,7 +29,7 @@ public class BoneMealItemMixin { Level world = context.getLevel(); BlockPos blockPos = context.getClickedPos(); if (!world.isClientSide) { - //BlockPos offset = blockPos.relative(context.getClickedFace()); + BlockPos offseted = blockPos.relative(context.getClickedFace()); if (BonemealAPI.isTerrain(world.getBlockState(blockPos).getBlock())) { boolean consume = false; if (BonemealAPI.isSpreadableTerrain(world.getBlockState(blockPos).getBlock())) { diff --git a/src/main/java/ru/bclib/mixin/common/ChunkBiomeContainerMixin.java b/src/main/java/ru/bclib/mixin/common/ChunkBiomeContainerMixin.java index 3ad2c2a8..5518fd1f 100644 --- a/src/main/java/ru/bclib/mixin/common/ChunkBiomeContainerMixin.java +++ b/src/main/java/ru/bclib/mixin/common/ChunkBiomeContainerMixin.java @@ -2,8 +2,8 @@ package ru.bclib.mixin.common; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.core.BlockPos; -import net.minecraft.util.BitStorage; import net.minecraft.util.Mth; +import net.minecraft.util.SimpleBitStorage; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.chunk.ChunkBiomeContainer; import org.spongepowered.asm.mixin.Final; @@ -40,7 +40,7 @@ public class ChunkBiomeContainerMixin implements BiomeSetter { if (bclib_hasHydrogen && be_shouldWriteToHydrogen()) { try { ChunkBiomeContainer self = (ChunkBiomeContainer) (Object) this; - BitStorage storage = be_getHydrogenStorage(self); + SimpleBitStorage storage = be_getHydrogenStorage(self); Biome[] palette = be_getHydrogenPalette(self); int paletteIndex = be_getHydrogenPaletteIndex(biome, palette); if (paletteIndex == -1) { @@ -57,7 +57,7 @@ public class ChunkBiomeContainerMixin implements BiomeSetter { catch (Exception e) { int size = storage.getSize(); int bits = Mth.ceillog2(palette.length); - BitStorage newStorage = new BitStorage(bits, size); + SimpleBitStorage newStorage = new SimpleBitStorage(bits, size); for (int i = 0; i < size; i++) { newStorage.set(i, storage.get(i)); } @@ -105,8 +105,8 @@ public class ChunkBiomeContainerMixin implements BiomeSetter { return field; } - private BitStorage be_getHydrogenStorage(ChunkBiomeContainer container) throws Exception { - return (BitStorage) be_getField("intArray").get(container); + private SimpleBitStorage be_getHydrogenStorage(ChunkBiomeContainer container) throws Exception { + return (SimpleBitStorage) be_getField("intArray").get(container); } private Biome[] be_getHydrogenPalette(ChunkBiomeContainer container) throws Exception { @@ -128,7 +128,7 @@ public class ChunkBiomeContainerMixin implements BiomeSetter { be_getField("palette").set(container, palette); } - private void be_setHydrogenStorage(ChunkBiomeContainer container, BitStorage storage) throws Exception { + private void be_setHydrogenStorage(ChunkBiomeContainer container, SimpleBitStorage storage) throws Exception { be_getField("intArray").set(container, storage); } } diff --git a/src/main/java/ru/bclib/mixin/common/DimensionTypeMixin.java b/src/main/java/ru/bclib/mixin/common/DimensionTypeMixin.java deleted file mode 100644 index 5e589aeb..00000000 --- a/src/main/java/ru/bclib/mixin/common/DimensionTypeMixin.java +++ /dev/null @@ -1,67 +0,0 @@ -package ru.bclib.mixin.common; - -import com.mojang.serialization.Lifecycle; -import net.minecraft.core.MappedRegistry; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.MultiNoiseBiomeSource; -import net.minecraft.world.level.biome.TheEndBiomeSource; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.levelgen.synth.NormalNoise; -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.CallbackInfoReturnable; -import ru.bclib.world.generator.BCLibEndBiomeSource; -import ru.bclib.world.generator.BCLibNetherBiomeSource; -import ru.bclib.world.generator.GeneratorOptions; - -@Mixin(value = DimensionType.class, priority = 100) -public class DimensionTypeMixin { - @Inject(method="defaultDimensions(Lnet/minecraft/core/RegistryAccess;JZ)Lnet/minecraft/core/MappedRegistry;", at=@At("HEAD"), cancellable = true) - static void bclib_defaultDimensions(RegistryAccess registryAccess, long l, boolean bl, CallbackInfoReturnable> cir){ - MappedRegistry mappedRegistry = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY, Lifecycle.experimental()); - Registry registry = registryAccess.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); - Registry registry2 = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY); - Registry registry3 = registryAccess.registryOrThrow(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY); - Registry registry4 = registryAccess.registryOrThrow(Registry.NOISE_REGISTRY); - - mappedRegistry.register(LevelStem.NETHER, new LevelStem( - () -> registry.getOrThrow(DimensionType.NETHER_LOCATION), - bclib_replaceNetherBiomeSource(registry2, registry3, registry4, l, bl) - ), Lifecycle.stable()); - - mappedRegistry.register(LevelStem.END, new LevelStem( - () -> registry.getOrThrow(DimensionType.END_LOCATION), - bclib_replaceEndBiomeSource(registry2, registry3, registry4, l) - ), Lifecycle.stable()); - cir.setReturnValue(mappedRegistry); - } - - private static ChunkGenerator bclib_replaceNetherBiomeSource(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, Registry noiseRegistry , long seed, boolean bl) { - return new NoiseBasedChunkGenerator( - noiseRegistry, - GeneratorOptions.customNetherBiomeSource() - ? new BCLibNetherBiomeSource(biomeRegistry, seed) - : MultiNoiseBiomeSource.Preset.NETHER.biomeSource(biomeRegistry, bl), - seed, - () -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.NETHER) - ); - } - - private static ChunkGenerator bclib_replaceEndBiomeSource(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, Registry noiseRegistry , long seed) { - return new NoiseBasedChunkGenerator( - noiseRegistry, - GeneratorOptions.customEndBiomeSource() - ? new BCLibEndBiomeSource(biomeRegistry, seed) - : new TheEndBiomeSource(biomeRegistry, seed), - seed, - () -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END) - ); - } -} \ No newline at end of file diff --git a/src/main/java/ru/bclib/mixin/common/LayerLightSectionStorageMixin.java b/src/main/java/ru/bclib/mixin/common/LayerLightSectionStorageMixin.java new file mode 100644 index 00000000..a222afef --- /dev/null +++ b/src/main/java/ru/bclib/mixin/common/LayerLightSectionStorageMixin.java @@ -0,0 +1,35 @@ +package ru.bclib.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.chunk.DataLayer; +import net.minecraft.world.level.lighting.LayerLightSectionStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(LayerLightSectionStorage.class) +public class LayerLightSectionStorageMixin { + @Shadow + protected DataLayer getDataLayer(long sectionPos, boolean cached) { + return null; + } + + @Inject(method = "getStoredLevel", at = @At(value = "HEAD"), cancellable = true) + private void bclib_lightFix(long blockPos, CallbackInfoReturnable info) { + try { + long pos = SectionPos.blockToSection(blockPos); + DataLayer dataLayer = this.getDataLayer(pos, true); + info.setReturnValue(dataLayer.get( + SectionPos.sectionRelative(BlockPos.getX(blockPos)), + SectionPos.sectionRelative(BlockPos.getY(blockPos)), + SectionPos.sectionRelative(BlockPos.getZ(blockPos)) + )); + } + catch (Exception e) { + info.setReturnValue(0); + } + } +} diff --git a/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java b/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java index b19e285b..0b7cfc6a 100644 --- a/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java +++ b/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java @@ -12,7 +12,6 @@ import net.minecraft.server.level.progress.ChunkProgressListenerFactory; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.players.GameProfileCache; import net.minecraft.world.level.Level; -import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess; import net.minecraft.world.level.storage.WorldData; import org.spongepowered.asm.mixin.Final; diff --git a/src/main/java/ru/bclib/mixin/common/ServerLevelMixin.java b/src/main/java/ru/bclib/mixin/common/ServerLevelMixin.java index 8de68864..91c2c4d2 100644 --- a/src/main/java/ru/bclib/mixin/common/ServerLevelMixin.java +++ b/src/main/java/ru/bclib/mixin/common/ServerLevelMixin.java @@ -1,5 +1,9 @@ package ru.bclib.mixin.common; +import java.util.List; +import java.util.concurrent.Executor; +import java.util.function.Supplier; + import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -17,10 +21,7 @@ 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.api.BiomeAPI; - -import java.util.List; -import java.util.concurrent.Executor; -import java.util.function.Supplier; +import ru.bclib.api.LifeCycleAPI; @Mixin(ServerLevel.class) public abstract class ServerLevelMixin extends Level { @@ -32,6 +33,9 @@ public abstract class ServerLevelMixin extends Level { @Inject(method = "*", at = @At("TAIL")) private void bclib_onServerWorldInit(MinecraftServer server, Executor workerExecutor, LevelStorageSource.LevelStorageAccess session, ServerLevelData properties, ResourceKey registryKey, DimensionType dimensionType, ChunkProgressListener worldGenerationProgressListener, ChunkGenerator chunkGenerator, boolean debugWorld, long l, List list, boolean bl, CallbackInfo info) { + ServerLevel world = ServerLevel.class.cast(this); + LifeCycleAPI._runLevelLoad(world, server, workerExecutor, session, properties, registryKey, dimensionType, worldGenerationProgressListener, chunkGenerator, debugWorld, l, list, bl); + BiomeAPI.initRegistry(server); BiomeAPI.applyModifications(ServerLevel.class.cast(this)); @@ -40,5 +44,7 @@ public abstract class ServerLevelMixin extends Level { } bclib_lastWorld = session.getLevelId(); + + } } diff --git a/src/main/java/ru/bclib/mixin/common/SimpleReloadableResourceManagerMixin.java b/src/main/java/ru/bclib/mixin/common/SimpleReloadableResourceManagerMixin.java index 94f5ea2d..d2ff94df 100644 --- a/src/main/java/ru/bclib/mixin/common/SimpleReloadableResourceManagerMixin.java +++ b/src/main/java/ru/bclib/mixin/common/SimpleReloadableResourceManagerMixin.java @@ -26,7 +26,7 @@ public class SimpleReloadableResourceManagerMixin { }; @Inject(method = "hasResource", at = @At("HEAD"), cancellable = true) - private void hasResource(ResourceLocation resourceLocation, CallbackInfoReturnable info) { + private void bclib_hasResource(ResourceLocation resourceLocation, CallbackInfoReturnable info) { if (resourceLocation.getNamespace().equals("minecraft")) { for (String key: BCLIB_MISSING_RESOURCES) { if (resourceLocation.getPath().equals(key)) { diff --git a/src/main/java/ru/bclib/mixin/common/WorldGenRegionMixin.java b/src/main/java/ru/bclib/mixin/common/WorldGenRegionMixin.java index 398e2d7e..a8866f3e 100644 --- a/src/main/java/ru/bclib/mixin/common/WorldGenRegionMixin.java +++ b/src/main/java/ru/bclib/mixin/common/WorldGenRegionMixin.java @@ -3,7 +3,6 @@ package ru.bclib.mixin.common; import net.minecraft.core.BlockPos; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkAccess; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -15,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; public class WorldGenRegionMixin { @Final @Shadow - private ChunkAccess center; + private ChunkPos center; @Inject(method = "ensureCanWrite", at = @At("HEAD"), cancellable = true) private void be_alterBlockCheck(BlockPos blockPos, CallbackInfoReturnable info) { diff --git a/src/main/java/ru/bclib/recipes/AnvilRecipe.java b/src/main/java/ru/bclib/recipes/AnvilRecipe.java index 378a7fd9..4d8eab82 100644 --- a/src/main/java/ru/bclib/recipes/AnvilRecipe.java +++ b/src/main/java/ru/bclib/recipes/AnvilRecipe.java @@ -140,13 +140,12 @@ public class AnvilRecipe implements Recipe, UnknownReceipBookCategory @Override public NonNullList getIngredients() { NonNullList defaultedList = NonNullList.create(); - defaultedList.add(Ingredient.of(TagAPI.ITEM_HAMMERS.getValues() - .stream() - .filter(hammer -> ((TieredItem) hammer).getTier() - .getLevel() >= toolLevel) - .map(ItemStack::new))); + defaultedList.add(Ingredient.of(TagAPI.ITEM_HAMMERS + .getValues() + .stream() + .filter(hammer -> ((TieredItem) hammer).getTier().getLevel() >= toolLevel) + .map(ItemStack::new))); defaultedList.add(input); - return defaultedList; } @@ -252,7 +251,7 @@ public class AnvilRecipe implements Recipe, UnknownReceipBookCategory } public Builder checkConfig(PathConfig config) { - exist |= config.getBoolean("anvil", id.getPath(), true); + exist &= config.getBoolean("anvil", id.getPath(), true); return this; } diff --git a/src/main/java/ru/bclib/recipes/FurnaceRecipe.java b/src/main/java/ru/bclib/recipes/FurnaceRecipe.java index fbdd57ea..a1986232 100644 --- a/src/main/java/ru/bclib/recipes/FurnaceRecipe.java +++ b/src/main/java/ru/bclib/recipes/FurnaceRecipe.java @@ -39,7 +39,7 @@ public class FurnaceRecipe { } public FurnaceRecipe checkConfig(PathConfig config) { - exist |= config.getBoolean("furnace", id.getPath(), true); + exist &= config.getBoolean("furnace", id.getPath(), true); return this; } diff --git a/src/main/java/ru/bclib/recipes/GridRecipe.java b/src/main/java/ru/bclib/recipes/GridRecipe.java index 71a6bbc9..95d68cfb 100644 --- a/src/main/java/ru/bclib/recipes/GridRecipe.java +++ b/src/main/java/ru/bclib/recipes/GridRecipe.java @@ -55,7 +55,7 @@ public class GridRecipe { } public GridRecipe checkConfig(PathConfig config) { - exist |= config.getBoolean("grid", id.getPath(), true); + exist &= config.getBoolean("grid", id.getPath(), true); return this; } diff --git a/src/main/java/ru/bclib/recipes/SmithingTableRecipe.java b/src/main/java/ru/bclib/recipes/SmithingTableRecipe.java index a74c6184..464ed15d 100644 --- a/src/main/java/ru/bclib/recipes/SmithingTableRecipe.java +++ b/src/main/java/ru/bclib/recipes/SmithingTableRecipe.java @@ -40,7 +40,7 @@ public class SmithingTableRecipe { private SmithingTableRecipe() {} public SmithingTableRecipe checkConfig(PathConfig config) { - exist |= config.getBoolean("smithing", id.getPath(), true); + exist &= config.getBoolean("smithing", id.getPath(), true); return this; } diff --git a/src/main/java/ru/bclib/util/ModUtil.java b/src/main/java/ru/bclib/util/ModUtil.java index cf3019ee..8f4b973a 100644 --- a/src/main/java/ru/bclib/util/ModUtil.java +++ b/src/main/java/ru/bclib/util/ModUtil.java @@ -31,7 +31,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.LinkedList; import java.util.Locale; import java.util.Map; import java.util.Optional; diff --git a/src/main/java/ru/bclib/world/biomes/BCLBiome.java b/src/main/java/ru/bclib/world/biomes/BCLBiome.java index 0cf21cbb..ebdf2a73 100644 --- a/src/main/java/ru/bclib/world/biomes/BCLBiome.java +++ b/src/main/java/ru/bclib/world/biomes/BCLBiome.java @@ -7,6 +7,8 @@ import com.google.gson.JsonObject; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import ru.bclib.config.Configs; import ru.bclib.util.JsonFactory; import ru.bclib.util.StructureHelper; import ru.bclib.util.WeightedList; @@ -38,6 +40,7 @@ public class BCLBiome { private Biome actualBiome; public BCLBiome(BCLBiomeDef definition) { + definition.loadConfigValues(Configs.BIOMES_CONFIG); this.mcID = definition.getID(); this.readStructureList(); if (structuresFeature != null) { @@ -53,8 +56,15 @@ public class BCLBiome { public BCLBiome(ResourceLocation id, Biome biome, float fogDensity, float genChance) { this.mcID = id; this.biome = biome; - this.genChance = genChance; - this.fogDensity = fogDensity; + if (id.equals(Biomes.THE_VOID.location())) { + this.genChance = fogDensity; + this.fogDensity = genChance; + } + else { + String biomePath = id.getNamespace() + "." + id.getPath(); + this.genChance = Configs.BIOMES_CONFIG.getFloat(biomePath, "generation_chance", genChance); + this.fogDensity = Configs.BIOMES_CONFIG.getFloat(biomePath, "fog_density", fogDensity); + } this.readStructureList(); this.customData = Maps.newHashMap(); subbiomes.add(this, 1); diff --git a/src/main/java/ru/bclib/world/biomes/BCLBiomeDef.java b/src/main/java/ru/bclib/world/biomes/BCLBiomeDef.java index 389e350d..8d91066f 100644 --- a/src/main/java/ru/bclib/world/biomes/BCLBiomeDef.java +++ b/src/main/java/ru/bclib/world/biomes/BCLBiomeDef.java @@ -4,8 +4,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import net.minecraft.core.Registry; import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.data.worldgen.StructureFeatures; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.Music; import net.minecraft.sounds.Musics; @@ -33,9 +31,8 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder; import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilder; import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderBaseConfiguration; -import net.minecraft.resources.ResourceKey; import ru.bclib.config.IdConfig; -import ru.bclib.interfaces.IStructureFeatures; +import ru.bclib.config.PathConfig; import ru.bclib.util.ColorUtil; import ru.bclib.world.features.BCLFeature; import ru.bclib.world.structures.BCLStructureFeature; @@ -48,8 +45,7 @@ public class BCLBiomeDef { public static final int DEF_FOLIAGE_OVERWORLD = ColorUtil.color(110, 143, 64); public static final int DEF_FOLIAGE_NETHER = ColorUtil.color(117, 10, 10); public static final int DEF_FOLIAGE_END = ColorUtil.color(197, 210, 112); - - protected final IStructureFeatures structureFeatures = (IStructureFeatures)new StructureFeatures(); + private final List> structures = Lists.newArrayList(); private final List features = Lists.newArrayList(); private final List carvers = Lists.newArrayList(); @@ -118,7 +114,6 @@ public class BCLBiomeDef { /** * Used to load biome settings from config. - * * @param config - {@link IdConfig}. * @return this {@link BCLBiomeDef}. */ @@ -129,9 +124,21 @@ public class BCLBiomeDef { return this; } + /** + * Used to load biome settings from config. + * @param config - {@link PathConfig}. + * @return this {@link BCLBiomeDef}. + */ + public BCLBiomeDef loadConfigValues(PathConfig config) { + String biomePath = id.getNamespace() + "." + id.getPath(); + this.fogDensity = config.getFloat(biomePath, "fog_density", this.fogDensity); + this.genChance = config.getFloat(biomePath, "generation_chance", this.genChance); + this.edgeSize = config.getInt(biomePath, "edge_size", this.edgeSize); + return this; + } + /** * Set category of the biome. - * * @param category - {@link BiomeCategory}. * @return this {@link BCLBiomeDef}. */ @@ -340,8 +347,7 @@ public class BCLBiomeDef { }); generationSettings.surfaceBuilder(surface == null ? net.minecraft.data.worldgen.SurfaceBuilders.END : surface); - //TODO: (1.18) Removed now. Seems to part of a registry step per biome now - //structures.forEach((structure) -> generationSettings.addStructureStart(structure)); + structures.forEach((structure) -> generationSettings.addStructureStart(structure)); features.forEach((info) -> generationSettings.addFeature(info.featureStep, info.feature)); carvers.forEach((info) -> generationSettings.addCarver(info.carverStep, info.carver)); @@ -359,27 +365,17 @@ public class BCLBiomeDef { if (particleConfig != null) effects.ambientParticle(particleConfig); effects.backgroundMusic(music != null ? new Music(music, 600, 2400, true) : Musics.END); - Biome biome = new Biome.BiomeBuilder().precipitation(precipitation) - .biomeCategory(category) - //.depth(depth) //TODO: No longer available in 1.18 - //.scale(0.2F) - .temperature(temperature) - .downfall(downfall) - .specialEffects(effects.build()) - .mobSpawnSettings(spawnSettings.build()) - .generationSettings(generationSettings.build()) - .build(); - - structureFeatures.bclib_registerStructure(biConsumer -> { - ResourceKey biomeKey = ResourceKey.create(Registry.BIOME_REGISTRY, BuiltinRegistries.BIOME.getKey(biome)); - System.out.println("Biome:" + biomeKey); - structures.forEach((structure) -> { - biConsumer.accept(structure, biomeKey); - }); - - }); - - return biome; + return new Biome.BiomeBuilder() + .precipitation(precipitation) + .biomeCategory(category) + .depth(depth) + .scale(0.2F) + .temperature(temperature) + .downfall(downfall) + .effects(effects.build()) + .spawnSettings(spawnSettings.build()) + .generationSettings(generationSettings.build()) + .build(); } private static final class SpawnInfo { diff --git a/src/main/java/ru/bclib/world/features/BCLFeature.java b/src/main/java/ru/bclib/world/features/BCLFeature.java index b7b898d0..c4a8e4bb 100644 --- a/src/main/java/ru/bclib/world/features/BCLFeature.java +++ b/src/main/java/ru/bclib/world/features/BCLFeature.java @@ -4,11 +4,9 @@ import net.minecraft.core.Registry; import net.minecraft.data.BuiltinRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.GenerationStep.Decoration; import net.minecraft.world.level.levelgen.VerticalAnchor; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; -import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.configurations.CountConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; @@ -16,59 +14,81 @@ import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguratio import net.minecraft.world.level.levelgen.placement.ChanceDecoratorConfiguration; import net.minecraft.world.level.levelgen.placement.FeatureDecorator; import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest; -import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTest; -import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest; -import ru.bclib.api.TagAPI; public class BCLFeature { - private static final RuleTest ANY_TERRAIN = new TagMatchTest(TagAPI.BLOCK_GEN_TERRAIN); private ConfiguredFeature featureConfigured; - private GenerationStep.Decoration featureStep; - private Feature feature; + private Decoration featureStep; + private net.minecraft.world.level.levelgen.feature.Feature feature; - public BCLFeature(Feature feature, ConfiguredFeature configuredFeature, GenerationStep.Decoration featureStep) { + public BCLFeature(net.minecraft.world.level.levelgen.feature.Feature feature, ConfiguredFeature configuredFeature, Decoration featureStep) { this.featureConfigured = configuredFeature; this.featureStep = featureStep; this.feature = feature; } - public BCLFeature(ResourceLocation id, Feature feature, GenerationStep.Decoration featureStep, ConfiguredFeature configuredFeature) { + public BCLFeature(ResourceLocation id, net.minecraft.world.level.levelgen.feature.Feature feature, Decoration featureStep, ConfiguredFeature configuredFeature) { this.featureConfigured = Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, id, configuredFeature); this.feature = Registry.register(Registry.FEATURE, id, feature); this.featureStep = featureStep; } - public static BCLFeature makeVegetationFeature(ResourceLocation id, Feature feature, int density) { + /** + * Get raw feature. + * @return {@link net.minecraft.world.level.levelgen.feature.Feature}. + */ + public net.minecraft.world.level.levelgen.feature.Feature getFeature() { + return feature; + } + + /** + * Get configured feature. + * @return {@link ConfiguredFeature}. + */ + public ConfiguredFeature getFeatureConfigured() { + return featureConfigured; + } + + /** + * Get feature decoration step. + * @return {@link Decoration}. + */ + public Decoration getFeatureStep() { + return featureStep; + } + + /** + * Will create a basic plant feature. + * @param id {@link ResourceLocation} feature ID. + * @param feature {@link net.minecraft.world.level.levelgen.feature.Feature} with {@link NoneFeatureConfiguration} config. + * @param density iterations per chunk. + * @return new BCLFeature instance. + */ + public static BCLFeature makeVegetationFeature(ResourceLocation id, net.minecraft.world.level.levelgen.feature.Feature feature, int density) { ConfiguredFeature configured = feature .configured(FeatureConfiguration.NONE) .decorated(BCLDecorators.HEIGHTMAP_SQUARE) .countRandom(density); - return new BCLFeature(id, feature, GenerationStep.Decoration.VEGETAL_DECORATION, configured); + return new BCLFeature(id, feature, Decoration.VEGETAL_DECORATION, configured); } - public static BCLFeature makeRawGenFeature(ResourceLocation id, Feature feature, int chance) { - ConfiguredFeature configured = feature - .configured(FeatureConfiguration.NONE) - .decorated(FeatureDecorator.CHANCE.configured(new ChanceDecoratorConfiguration(chance))); - return new BCLFeature(id, feature, GenerationStep.Decoration.RAW_GENERATION, configured); - } - - @Deprecated - public static BCLFeature makeLakeFeature(ResourceLocation id, Feature feature, int chance) { - ConfiguredFeature configured = feature - .configured(FeatureConfiguration.NONE) - .decorated(FeatureDecorator.LAVA_LAKE.configured(new ChanceDecoratorConfiguration(chance))); - return new BCLFeature(id, feature, GenerationStep.Decoration.LAKES, configured); - } - - public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, int veins, int veinSize, int offset, int minY, int maxY) { + /** + * Will create a basic ore feature. + * @param id {@link ResourceLocation} feature ID. + * @param blockOre {@link Decoration} feature step. + * @param hostBlock {@link Block} to generate feature in. + * @param veins iterations per chunk. + * @param veinSize size of ore vein. + * @param minY minimum height. + * @param maxY maximum height. + * @return new BCLFeature instance. + */ + public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, int minY, int maxY) { OreConfiguration featureConfig = new OreConfiguration( - new BlockMatchTest(Blocks.END_STONE), + new BlockMatchTest(hostBlock), blockOre.defaultBlockState(), veinSize ); - OreConfiguration config = new OreConfiguration(ANY_TERRAIN, blockOre.defaultBlockState(), 33); - ConfiguredFeature oreFeature = Feature.ORE + ConfiguredFeature oreFeature = net.minecraft.world.level.levelgen.feature.Feature.ORE .configured(featureConfig) .rangeUniform( VerticalAnchor.absolute(minY), @@ -77,46 +97,95 @@ public class BCLFeature { .squared() .count(veins); return new BCLFeature( - Feature.ORE, + net.minecraft.world.level.levelgen.feature.Feature.ORE, Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, id, oreFeature), - GenerationStep.Decoration.UNDERGROUND_ORES + Decoration.UNDERGROUND_ORES ); } - public static BCLFeature makeChunkFeature(ResourceLocation id, Feature feature) { + /** + * Will create feature which will be generated once in each chunk. + * @param id {@link ResourceLocation} feature ID. + * @param step {@link Decoration} feature step. + * @param feature {@link net.minecraft.world.level.levelgen.feature.Feature} with {@link NoneFeatureConfiguration} config. + * @return new BCLFeature instance. + */ + public static BCLFeature makeChunkFeature(ResourceLocation id, Decoration step, net.minecraft.world.level.levelgen.feature.Feature feature) { ConfiguredFeature configured = feature .configured(FeatureConfiguration.NONE) .decorated(FeatureDecorator.COUNT.configured(new CountConfiguration(1))); - return new BCLFeature(id, feature, GenerationStep.Decoration.LOCAL_MODIFICATIONS, configured); + return new BCLFeature(id, feature, step, configured); } - public static BCLFeature makeChansedFeature(ResourceLocation id, Feature feature, int chance) { + /** + * Will create feature with chanced decoration, chance for feature to generate per chunk is 1 / chance. + * @param id {@link ResourceLocation} feature ID. + * @param step {@link Decoration} feature step. + * @param feature {@link net.minecraft.world.level.levelgen.feature.Feature} with {@link NoneFeatureConfiguration} config. + * @param chance chance for feature to be generated in. + * @return new BCLFeature instance. + */ + public static BCLFeature makeChancedFeature(ResourceLocation id, Decoration step, net.minecraft.world.level.levelgen.feature.Feature feature, int chance) { ConfiguredFeature configured = feature .configured(FeatureConfiguration.NONE) .decorated(FeatureDecorator.CHANCE.configured(new ChanceDecoratorConfiguration(chance))); - return new BCLFeature(id, feature, GenerationStep.Decoration.SURFACE_STRUCTURES, configured); + return new BCLFeature(id, feature, step, configured); } - public static BCLFeature makeCountRawFeature(ResourceLocation id, Feature feature, int chance) { - ConfiguredFeature configured = feature.configured(FeatureConfiguration.NONE) - .decorated(FeatureDecorator.COUNT.configured(new CountConfiguration(chance))); - return new BCLFeature(id, feature, GenerationStep.Decoration.RAW_GENERATION, configured); + /** + * Will create feature with specified generation iterations per chunk. + * @param id {@link ResourceLocation} feature ID. + * @param step {@link Decoration} feature step. + * @param feature {@link net.minecraft.world.level.levelgen.feature.Feature} with {@link NoneFeatureConfiguration} config. + * @param count iterations steps. + * @return new BCLFeature instance. + */ + public static BCLFeature makeCountFeature(ResourceLocation id, Decoration step, net.minecraft.world.level.levelgen.feature.Feature feature, int count) { + ConfiguredFeature configured = feature + .configured(FeatureConfiguration.NONE) + .decorated(FeatureDecorator.COUNT.configured(new CountConfiguration(count))); + return new BCLFeature(id, feature, step, configured); } - public static BCLFeature makeFeatureConfigured(ResourceLocation id, Feature feature) { + /** + * Makes simple configured feature with {@link NoneFeatureConfiguration} set to NONE. + * @param id {@link ResourceLocation} feature ID. + * @param step {@link Decoration} feature step. + * @param feature {@link net.minecraft.world.level.levelgen.feature.Feature} with {@link NoneFeatureConfiguration} config. + * @return new BCLFeature instance. + */ + public static BCLFeature makeFeatureConfigured(ResourceLocation id, Decoration step, net.minecraft.world.level.levelgen.feature.Feature feature) { ConfiguredFeature configured = feature.configured(FeatureConfiguration.NONE); - return new BCLFeature(id, feature, GenerationStep.Decoration.RAW_GENERATION, configured); + return new BCLFeature(id, feature, step, configured); } - public Feature getFeature() { - return feature; + @Deprecated(forRemoval = true) + public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, int offset, int minY, int maxY) { + return makeOreFeature(id, blockOre, hostBlock, veins, veinSize, minY, maxY); } - public ConfiguredFeature getFeatureConfigured() { - return featureConfigured; + @Deprecated(forRemoval = true) + public static BCLFeature makeRawGenFeature(ResourceLocation id, net.minecraft.world.level.levelgen.feature.Feature feature, int chance) { + return makeChancedFeature(id, Decoration.RAW_GENERATION, feature, chance); } - public GenerationStep.Decoration getFeatureStep() { - return featureStep; + @Deprecated(forRemoval = true) + public static BCLFeature makeChunkFeature(ResourceLocation id, net.minecraft.world.level.levelgen.feature.Feature feature) { + return makeChunkFeature(id, Decoration.LOCAL_MODIFICATIONS, feature); + } + + @Deprecated(forRemoval = true) + public static BCLFeature makeChansedFeature(ResourceLocation id, net.minecraft.world.level.levelgen.feature.Feature feature, int chance) { + return makeChancedFeature(id, Decoration.SURFACE_STRUCTURES, feature, chance); + } + + @Deprecated(forRemoval = true) + public static BCLFeature makeCountRawFeature(ResourceLocation id, net.minecraft.world.level.levelgen.feature.Feature feature, int chance) { + return makeCountFeature(id, Decoration.RAW_GENERATION, feature, chance); + } + + @Deprecated(forRemoval = true) + public static BCLFeature makeFeatureConfigured(ResourceLocation id, net.minecraft.world.level.levelgen.feature.Feature feature) { + return makeFeatureConfigured(id, Decoration.RAW_GENERATION, feature); } } diff --git a/src/main/java/ru/bclib/world/features/NBTStructureFeature.java b/src/main/java/ru/bclib/world/features/NBTStructureFeature.java index acaed3ec..37aa0050 100644 --- a/src/main/java/ru/bclib/world/features/NBTStructureFeature.java +++ b/src/main/java/ru/bclib/world/features/NBTStructureFeature.java @@ -18,6 +18,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderConfiguration; import ru.bclib.api.BiomeAPI; import ru.bclib.api.TagAPI; import ru.bclib.util.BlocksHelper; diff --git a/src/main/java/ru/bclib/world/generator/BCLibEndBiomeSource.java b/src/main/java/ru/bclib/world/generator/BCLibEndBiomeSource.java index 7e236521..97bd8e81 100644 --- a/src/main/java/ru/bclib/world/generator/BCLibEndBiomeSource.java +++ b/src/main/java/ru/bclib/world/generator/BCLibEndBiomeSource.java @@ -9,13 +9,13 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome.BiomeCategory; 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.TheEndBiomeSource; -import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.world.level.levelgen.synth.SimplexNoise; import ru.bclib.BCLib; import ru.bclib.api.BiomeAPI; +import ru.bclib.config.ConfigKeeper.StringArrayEntry; +import ru.bclib.config.Configs; import ru.bclib.noise.OpenSimplexNoise; import ru.bclib.world.biomes.BCLBiome; @@ -48,7 +48,7 @@ public class BCLibEndBiomeSource extends BiomeSource { BiomeAPI.END_LAND_BIOME_PICKER.clearMutables(); BiomeAPI.END_VOID_BIOME_PICKER.clearMutables(); - this.possibleBiomes().forEach(biome -> { + this.possibleBiomes.forEach(biome -> { ResourceLocation key = biomeRegistry.getKey(biome); if (!BiomeAPI.hasBiome(key)) { BCLBiome bclBiome = new BCLBiome(key, biome, 1, 1); @@ -64,6 +64,8 @@ public class BCLibEndBiomeSource extends BiomeSource { } }); + Configs.BIOMES_CONFIG.saveChanges(); + BiomeAPI.END_LAND_BIOME_PICKER.getBiomes().forEach(biome -> biome.updateActualBiomes(biomeRegistry)); BiomeAPI.END_VOID_BIOME_PICKER.getBiomes().forEach(biome -> biome.updateActualBiomes(biomeRegistry)); @@ -86,8 +88,19 @@ public class BCLibEndBiomeSource extends BiomeSource { } private static List getBiomes(Registry biomeRegistry) { + List include = Configs.BIOMES_CONFIG.getEntry("force_include", "end_biomes", StringArrayEntry.class).getValue(); + return biomeRegistry.stream().filter(biome -> { ResourceLocation key = biomeRegistry.getKey(biome); + + if (include.contains(key.toString())) { + return true; + } + + if (GeneratorOptions.addEndBiomesByCategory() && biome.getBiomeCategory() == BiomeCategory.THEEND) { + return true; + } + BCLBiome bclBiome = BiomeAPI.getBiome(key); if (bclBiome != BiomeAPI.EMPTY_BIOME) { if (bclBiome.hasParentBiome()) { @@ -100,7 +113,7 @@ public class BCLibEndBiomeSource extends BiomeSource { } @Override - public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) { + public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) { long i = (long) biomeX * (long) biomeX; long j = (long) biomeZ * (long) biomeZ; long check = GeneratorOptions.isFarEndBiomes() ? 65536L : 625L; diff --git a/src/main/java/ru/bclib/world/generator/BCLibNetherBiomeSource.java b/src/main/java/ru/bclib/world/generator/BCLibNetherBiomeSource.java index e992b5b3..754b8d7d 100644 --- a/src/main/java/ru/bclib/world/generator/BCLibNetherBiomeSource.java +++ b/src/main/java/ru/bclib/world/generator/BCLibNetherBiomeSource.java @@ -8,9 +8,10 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome.BiomeCategory; import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.Climate; import ru.bclib.BCLib; import ru.bclib.api.BiomeAPI; +import ru.bclib.config.ConfigKeeper.StringArrayEntry; +import ru.bclib.config.Configs; import ru.bclib.world.biomes.BCLBiome; import java.util.LinkedList; @@ -37,7 +38,7 @@ public class BCLibNetherBiomeSource extends BiomeSource { BiomeAPI.NETHER_BIOME_PICKER.clearMutables(); - this.possibleBiomes().forEach(biome -> { + this.possibleBiomes.forEach(biome -> { ResourceLocation key = biomeRegistry.getKey(biome); if (!BiomeAPI.hasBiome(key)) { BCLBiome bclBiome = new BCLBiome(key, biome, 1, 1); @@ -53,6 +54,7 @@ public class BCLibNetherBiomeSource extends BiomeSource { } }); + Configs.BIOMES_CONFIG.saveChanges(); BiomeAPI.NETHER_BIOME_PICKER.getBiomes().forEach(biome -> biome.updateActualBiomes(biomeRegistry)); BiomeAPI.NETHER_BIOME_PICKER.rebuild(); @@ -64,8 +66,19 @@ public class BCLibNetherBiomeSource extends BiomeSource { } private static List getBiomes(Registry biomeRegistry) { + List include = Configs.BIOMES_CONFIG.getEntry("force_include", "nether_biomes", StringArrayEntry.class).getValue(); + return biomeRegistry.stream().filter(biome -> { ResourceLocation key = biomeRegistry.getKey(biome); + + if (include.contains(key.toString())) { + return true; + } + + if (GeneratorOptions.addNetherBiomesByCategory() && biome.getBiomeCategory() == BiomeCategory.NETHER) { + return true; + } + BCLBiome bclBiome = BiomeAPI.getBiome(key); if (bclBiome != BiomeAPI.EMPTY_BIOME) { if (bclBiome.hasParentBiome()) { @@ -78,7 +91,7 @@ public class BCLibNetherBiomeSource extends BiomeSource { } @Override - public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) { + public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) { if ((biomeX & 63) == 0 && (biomeZ & 63) == 0) { biomeMap.clearCache(); } diff --git a/src/main/java/ru/bclib/world/generator/BiomeMap.java b/src/main/java/ru/bclib/world/generator/BiomeMap.java index 43614a3d..a244029c 100644 --- a/src/main/java/ru/bclib/world/generator/BiomeMap.java +++ b/src/main/java/ru/bclib/world/generator/BiomeMap.java @@ -2,7 +2,6 @@ package ru.bclib.world.generator; import com.google.common.collect.Maps; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.level.levelgen.WorldgenRandom; import ru.bclib.noise.OpenSimplexNoise; import ru.bclib.util.MHelper; diff --git a/src/main/java/ru/bclib/world/generator/GeneratorOptions.java b/src/main/java/ru/bclib/world/generator/GeneratorOptions.java index a2b80ad4..af5c084d 100644 --- a/src/main/java/ru/bclib/world/generator/GeneratorOptions.java +++ b/src/main/java/ru/bclib/world/generator/GeneratorOptions.java @@ -14,6 +14,8 @@ public class GeneratorOptions { private static boolean farEndBiomes = true; private static boolean customNetherBiomeSource = true; private static boolean customEndBiomeSource = true; + private static boolean addNetherBiomesByCategory = false; + private static boolean addEndBiomesByCategory = false; public static void init() { biomeSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap", "biomeSize", 256); @@ -21,6 +23,8 @@ public class GeneratorOptions { biomeSizeEndVoid = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeVoid", 256); customNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customNetherBiomeSource", true); customEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customEndBiomeSource", true); + addNetherBiomesByCategory = Configs.GENERATOR_CONFIG.getBoolean("options", "addNetherBiomesByCategory", false); + addEndBiomesByCategory = Configs.GENERATOR_CONFIG.getBoolean("options", "addEndBiomesByCategory", false); } public static int getBiomeSizeNether() { @@ -58,4 +62,12 @@ public class GeneratorOptions { public static boolean customEndBiomeSource() { return customEndBiomeSource; } + + public static boolean addNetherBiomesByCategory() { + return addNetherBiomesByCategory; + } + + public static boolean addEndBiomesByCategory() { + return addEndBiomesByCategory; + } } diff --git a/src/main/java/ru/bclib/world/structures/BCLStructureFeature.java b/src/main/java/ru/bclib/world/structures/BCLStructureFeature.java index bef51070..4497bfc7 100644 --- a/src/main/java/ru/bclib/world/structures/BCLStructureFeature.java +++ b/src/main/java/ru/bclib/world/structures/BCLStructureFeature.java @@ -1,6 +1,7 @@ package ru.bclib.world.structures; import net.fabricmc.fabric.api.structure.v1.FabricStructureBuilder; +import net.fabricmc.fabric.mixin.structure.FlatChunkGeneratorConfigAccessor; import net.minecraft.data.BuiltinRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.levelgen.GenerationStep; @@ -24,9 +25,7 @@ public class BCLStructureFeature { .register(); this.featureConfigured = this.structure.configured(NoneFeatureConfiguration.NONE); BuiltinRegistries.register(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE, id, this.featureConfigured); - // TODO: (1.18) Find Alternative for this mapping - //FlatLevelGeneratorSettings.getStructureToFeatures().put(this.structure, this.featureConfigured); - + FlatChunkGeneratorConfigAccessor.getStructureToFeatures().put(this.structure, this.featureConfigured); } public StructureFeature getStructure() { diff --git a/src/main/java/ru/bclib/world/surface/DoubleBlockSurfaceBuilder.java b/src/main/java/ru/bclib/world/surface/DoubleBlockSurfaceBuilder.java index 3a2b1b6d..434b1a39 100644 --- a/src/main/java/ru/bclib/world/surface/DoubleBlockSurfaceBuilder.java +++ b/src/main/java/ru/bclib/world/surface/DoubleBlockSurfaceBuilder.java @@ -5,7 +5,7 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.BlockColumn; +import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder; import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilder; import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderBaseConfiguration; @@ -43,13 +43,13 @@ public class DoubleBlockSurfaceBuilder extends SurfaceBuilder