diff --git a/src/main/java/org/betterx/bclib/api/biomes/BCLBiomeBuilder.java b/src/main/java/org/betterx/bclib/api/biomes/BCLBiomeBuilder.java index 474a7157..95ebb0b5 100644 --- a/src/main/java/org/betterx/bclib/api/biomes/BCLBiomeBuilder.java +++ b/src/main/java/org/betterx/bclib/api/biomes/BCLBiomeBuilder.java @@ -29,6 +29,7 @@ import net.fabricmc.fabric.api.biome.v1.BiomeModifications; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import org.betterx.bclib.api.structures.BCLStructure; import org.betterx.bclib.api.surface.SurfaceRuleBuilder; import org.betterx.bclib.entity.BCLEntityWrapper; import org.betterx.bclib.mixin.common.BiomeGenerationSettingsAccessor; @@ -37,7 +38,6 @@ import org.betterx.bclib.util.ColorUtil; import org.betterx.bclib.util.Pair; import org.betterx.bclib.util.TriFunction; import org.betterx.bclib.world.features.BCLFeature; -import org.betterx.bclib.world.structures.BCLStructure; import java.util.ArrayList; import java.util.List; @@ -53,7 +53,7 @@ public class BCLBiomeBuilder { private static final BCLBiomeBuilder INSTANCE = new BCLBiomeBuilder(); private static final SurfaceRules.ConditionSource SURFACE_NOISE = SurfaceRules.noiseCondition(Noises.SOUL_SAND_LAYER, - -0.012); + -0.012); private final List>>> carvers = new ArrayList<>( 1); @@ -157,7 +157,7 @@ public class BCLBiomeBuilder { int minGroupCount, int maxGroupCount) { getSpawns().addSpawn(entityType.getCategory(), - new SpawnerData(entityType, weight, minGroupCount, maxGroupCount)); + new SpawnerData(entityType, weight, minGroupCount, maxGroupCount)); return this; } @@ -619,8 +619,8 @@ public class BCLBiomeBuilder { var oKey = carver.unwrapKey(); if (oKey.isPresent()) { BiomeModifications.addCarver(ctx -> ctx.getBiomeKey().location().equals(immutableID), - step, - (ResourceKey>) oKey.get()); + step, + (ResourceKey>) oKey.get()); } //carvers.add(new Pair<>(step, carver)); return this; @@ -656,10 +656,10 @@ public class BCLBiomeBuilder { */ public BCLBiomeBuilder surface(Block surfaceBlock, Block subterrainBlock, int depth) { return surface(SurfaceRuleBuilder - .start() - .surface(surfaceBlock.defaultBlockState()) - .subsurface(subterrainBlock.defaultBlockState(), depth) - .build()); + .start() + .surface(surfaceBlock.defaultBlockState()) + .subsurface(subterrainBlock.defaultBlockState(), depth) + .build()); } /** diff --git a/src/main/java/org/betterx/bclib/api/structures/BCLStructure.java b/src/main/java/org/betterx/bclib/api/structures/BCLStructure.java new file mode 100644 index 00000000..004913bd --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/structures/BCLStructure.java @@ -0,0 +1,154 @@ +package org.betterx.bclib.api.structures; + +import net.minecraft.core.*; +import net.minecraft.data.BuiltinRegistries; +import net.minecraft.data.worldgen.StructureSets; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.structure.*; +import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement; + +import com.google.common.collect.Lists; +import com.mojang.serialization.Codec; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.mixin.common.StructuresAccessor; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import org.jetbrains.annotations.NotNull; + +public class BCLStructure { + private final Holder structure; + private final GenerationStep.Decoration featureStep; + private final List biomes = Lists.newArrayList(); + private final ResourceLocation id; + public final TagKey biomeTag; + public final ResourceKey structureKey; + public final S baseStructure; + public final ResourceKey structureSetKey; + public final StructurePlacement spreadConfig; + + public final StructureType structureType; + + public final Codec STRUCTURE_CODEC; + + + private static HolderSet biomes(TagKey tagKey) { + return BuiltinRegistries.BIOME.getOrCreateTag(tagKey); + } + + private static Structure.StructureSettings structure(TagKey tagKey, + Map map, + GenerationStep.Decoration decoration, + TerrainAdjustment terrainAdjustment) { + return new Structure.StructureSettings(biomes(tagKey), map, decoration, terrainAdjustment); + } + + private static Structure.StructureSettings structure(TagKey tagKey, + GenerationStep.Decoration decoration, + TerrainAdjustment terrainAdjustment) { + return structure(tagKey, Map.of(), decoration, terrainAdjustment); + } + + private static StructureType registerStructureType(ResourceLocation id, + Codec codec) { + return Registry.register(Registry.STRUCTURE_TYPES, id, () -> codec); + } + + protected BCLStructure(@NotNull ResourceLocation id, + @NotNull Function structureBuilder, + GenerationStep.Decoration step, + @NotNull StructurePlacement placement, + @NotNull Codec codec, + @NotNull TagKey biomeTag, + @NotNull TerrainAdjustment terrainAdjustment) { + this.id = id; + this.featureStep = step; + this.STRUCTURE_CODEC = codec; + this.spreadConfig = placement; + this.structureKey = ResourceKey.create(Registry.STRUCTURE_REGISTRY, id); + this.structureSetKey = ResourceKey.create(Registry.STRUCTURE_SET_REGISTRY, id); + + this.structureType = registerStructureType(id, STRUCTURE_CODEC); + + this.biomeTag = biomeTag; + this.baseStructure = structureBuilder.apply(structure(this.biomeTag, featureStep, terrainAdjustment)); + this.structure = StructuresAccessor.callRegister(structureKey, this.baseStructure); + StructureSets.register(structureSetKey, this.structure, spreadConfig); + } + + /** + * runs the {@code PieceGeneratorSupplier.Context::validBiome} from the given context at + * height=5 in the middle of the chunk. + * + * @param context The context to test with. + * @return true, if this feature can spawn in the current biome + */ + public static boolean isValidBiome(Structure.GenerationContext context) { + return isValidBiome(context, 5); + } + + /** + * runs the {@code PieceGeneratorSupplier.Context::validBiome} from the given context at the + * given height in the middle of the chunk. + * + * @param context The context to test with. + * @param yPos The Height to test for + * @return true, if this feature can spawn in the current biome + */ + public static boolean isValidBiome(Structure.GenerationContext context, int yPos) { + BlockPos blockPos = context.chunkPos().getMiddleBlockPosition(yPos); + return context.validBiome().test( + context + .chunkGenerator() + .getBiomeSource() + .getNoiseBiome( + QuartPos.fromBlock(blockPos.getX()), + QuartPos.fromBlock(blockPos.getY()), + QuartPos.fromBlock(blockPos.getZ()), + context.randomState().sampler() + ) + ); + } + + public Holder getStructure() { + return structure; + } + + public GenerationStep.Decoration getFeatureStep() { + return featureStep; + } + + /** + * Get the structure ID; + * + * @return {@link ResourceLocation} id. + */ + public ResourceLocation getID() { + return id; + } + + /** + * Adds biome into internal biome list, used in {@link BCLBiomeBuilder}. + * + * @param biome {@link ResourceLocation} biome ID. + */ + public void addInternalBiome(ResourceLocation biome) { + biomes.add(biome); + } + + /** + * Get biome list where this structure feature can generate. Only represents biomes made with {@link BCLBiomeBuilder} and only + * if structure was added during building process. Modification of this list will not affect structure generation. + * + * @return {@link List} of biome {@link ResourceLocation}. + */ + public List getBiomes() { + return biomes; + } +} diff --git a/src/main/java/org/betterx/bclib/api/structures/BCLStructureBuilder.java b/src/main/java/org/betterx/bclib/api/structures/BCLStructureBuilder.java new file mode 100644 index 00000000..ffe69875 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/structures/BCLStructureBuilder.java @@ -0,0 +1,108 @@ +package org.betterx.bclib.api.structures; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.TerrainAdjustment; +import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement; +import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadType; +import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement; + +import com.mojang.serialization.Codec; +import org.betterx.bclib.api.tag.TagAPI; + +import java.util.function.Function; + +public class BCLStructureBuilder { + private static final BCLStructureBuilder INSTANCE = new BCLStructureBuilder(); + + private ResourceLocation structureID; + private Function structureBuilder; + + private GenerationStep.Decoration step; + + private Codec codec; + + private StructurePlacement placement; + + private TagKey biomeTag; + + private TerrainAdjustment terrainAdjustment; + + private BCLStructureBuilder() { + } + + public static BCLStructureBuilder start(ResourceLocation structureID, + Function structureBuilder) { + INSTANCE.structureID = structureID; + INSTANCE.structureBuilder = structureBuilder; + + INSTANCE.step = GenerationStep.Decoration.SURFACE_STRUCTURES; + INSTANCE.terrainAdjustment = TerrainAdjustment.NONE; + INSTANCE.codec = null; + INSTANCE.placement = null; + INSTANCE.biomeTag = null; + + return INSTANCE; + } + + public BCLStructureBuilder step(TerrainAdjustment value) { + this.terrainAdjustment = value; + return this; + } + + public BCLStructureBuilder step(GenerationStep.Decoration value) { + this.step = value; + return this; + } + + public BCLStructureBuilder codec(Codec value) { + this.codec = value; + return this; + } + + public BCLStructureBuilder placement(StructurePlacement value) { + this.placement = value; + return this; + } + + public BCLStructureBuilder randomPlacement(int spacing, int separation) { + this.placement = new RandomSpreadStructurePlacement(spacing, + separation, + RandomSpreadType.LINEAR, + 13323129 + spacing + separation + structureID.toString().hashCode() % 10000 + ); + ; + return this; + } + + public BCLStructureBuilder biomeTag(String modID, String path) { + this.biomeTag = TagAPI.makeStructureTag(modID, path); + return this; + } + + public BCLStructureBuilder biomeTag(TagKey tag) { + this.biomeTag = tag; + return this; + } + + public BCLStructure build() { + if (placement == null) { + throw new IllegalStateException("Placement needs to be defined for " + this.structureID); + } + if (codec == null) codec(Structure.simpleCodec(structureBuilder)); + if (biomeTag == null) biomeTag(structureID.getNamespace(), structureID.getPath()); + + return new BCLStructure<>( + structureID, + structureBuilder, + step, + placement, + codec, + biomeTag, + terrainAdjustment + ); + } +} diff --git a/src/main/java/org/betterx/bclib/world/structures/BCLStructure.java b/src/main/java/org/betterx/bclib/world/structures/BCLStructure.java index 7a47bc5e..b7e1e927 100644 --- a/src/main/java/org/betterx/bclib/world/structures/BCLStructure.java +++ b/src/main/java/org/betterx/bclib/world/structures/BCLStructure.java @@ -1,69 +1,36 @@ package org.betterx.bclib.world.structures; -import net.minecraft.core.*; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.data.worldgen.StructureSets; -import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; -import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.GenerationStep; -import net.minecraft.world.level.levelgen.structure.*; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.TerrainAdjustment; import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement; import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadType; -import com.google.common.collect.Lists; import com.mojang.serialization.Codec; -import org.betterx.bclib.api.biomes.BCLBiomeBuilder; -import org.betterx.bclib.api.tag.TagAPI; -import org.betterx.bclib.mixin.common.StructuresAccessor; +import org.betterx.bclib.util.MHelper; -import java.util.List; -import java.util.Map; -import java.util.Random; import java.util.function.Function; -public class BCLStructure { - private static final Random RANDOM = new Random(354); - - private final Holder structure; - private final GenerationStep.Decoration featureStep; - private final List biomes = Lists.newArrayList(); - private final ResourceLocation id; - public final TagKey biomeTag; - public final ResourceKey structureKey; - public final S baseStructure; - public final ResourceKey structureSetKey; - public final RandomSpreadStructurePlacement spreadConfig; - - public final StructureType structureType; - - public final Codec STRUCTURE_CODEC; - - - private static HolderSet biomes(TagKey tagKey) { - return BuiltinRegistries.BIOME.getOrCreateTag(tagKey); - } - - private static Structure.StructureSettings structure(TagKey tagKey, - Map map, - GenerationStep.Decoration decoration, - TerrainAdjustment terrainAdjustment) { - return new Structure.StructureSettings(biomes(tagKey), map, decoration, terrainAdjustment); - } - - private static Structure.StructureSettings structure(TagKey tagKey, - GenerationStep.Decoration decoration, - TerrainAdjustment terrainAdjustment) { - return structure(tagKey, Map.of(), decoration, terrainAdjustment); - } - - private static StructureType registerStructureType(ResourceLocation id, - Codec codec) { - return Registry.register(Registry.STRUCTURE_TYPES, id, () -> codec); - } +@Deprecated(forRemoval = true) +/** + * Please use the {@link org.betterx.bclib.api.structures.BCLStructure} and + * {@link org.betterx.bclib.api.structures.BCLStructureBuilder} instead. + */ +public class BCLStructure extends org.betterx.bclib.api.structures.BCLStructure { + @Deprecated(forRemoval = true) + /** + * Please use the {@link org.betterx.bclib.api.structures.BCLStructureBuilder} instead: + * + * BCLStructureBuilder + * .start(id, structureBuilder) + * .step(step) + * .randomPlacement(spacing, separation) + * .build(); + */ public BCLStructure(ResourceLocation id, Function structureBuilder, GenerationStep.Decoration step, @@ -72,6 +39,16 @@ public class BCLStructure { this(id, structureBuilder, step, spacing, separation, false); } + @Deprecated(forRemoval = true) + /** + * Please use the {@link org.betterx.bclib.api.structures.BCLStructureBuilder} instead: + * + * BCLStructureBuilder + * .start(id, structureBuilder) + * .step(step) + * .randomPlacement(spacing, separation) + * .build(); + */ public BCLStructure(ResourceLocation id, Function structureBuilder, GenerationStep.Decoration step, @@ -88,6 +65,20 @@ public class BCLStructure { null); } + @Deprecated(forRemoval = true) + /** + * + * Please use the {@link org.betterx.bclib.api.structures.BCLStructureBuilder} instead: + * + * BCLStructureBuilder + * .start(id, structureBuilder) + * .step(step) + * .randomPlacement(spacing, separation) + * .codec(codec) + * .biomeTag(biomeTag) + * .build(); + * + */ public BCLStructure(ResourceLocation id, Function structureBuilder, GenerationStep.Decoration step, @@ -96,104 +87,10 @@ public class BCLStructure { boolean adaptNoise, Codec codec, TagKey biomeTag) { - this.id = id; - this.featureStep = step; - - this.STRUCTURE_CODEC = codec; - //parts from vanilla for Structure generation - //public static final ResourceKey> JUNGLE_TEMPLE = - // BuiltinStructures.createKey("jungle_pyramid"); - //public static final Holder> JUNGLE_TEMPLE = - // Structures.register(BuiltinStructures.JUNGLE_TEMPLE, Structure.JUNGLE_TEMPLE.configured(NoneFeatureConfiguration.INSTANCE, BiomeTags.HAS_JUNGLE_TEMPLE)); - //public static final Holder JUNGLE_TEMPLES = - // StructureSets.register(BuiltinStructureSets.JUNGLE_TEMPLES, Structures.JUNGLE_TEMPLE, new RandomSpreadStructurePlacement(32, 8, RandomSpreadType.LINEAR, 14357619)); - //public static final Structure JUNGLE_TEMPLE = - // Structure.register("jungle_pyramid", new JunglePyramidFeature(NoneFeatureConfiguration.CODEC), GenerationStep.Decoration.SURFACE_STRUCTURES); - // - - this.spreadConfig = new RandomSpreadStructurePlacement(spacing, + super(id, structureBuilder, step, new RandomSpreadStructurePlacement(spacing, separation, RandomSpreadType.LINEAR, - RANDOM.nextInt(8192)); - this.structureKey = ResourceKey.create(Registry.STRUCTURE_REGISTRY, id); - this.structureSetKey = ResourceKey.create(Registry.STRUCTURE_SET_REGISTRY, id); - this.structureType = registerStructureType(id, STRUCTURE_CODEC); - - this.biomeTag = biomeTag == null - ? TagAPI.makeStructureTag(id.getNamespace(), id.getPath()) - : biomeTag; - this.baseStructure = structureBuilder.apply(structure(this.biomeTag, featureStep, TerrainAdjustment.NONE)); - this.structure = StructuresAccessor.callRegister(structureKey, this.baseStructure); - StructureSets.register(structureSetKey, this.structure, spreadConfig); + MHelper.RANDOM.nextInt(8192)), codec, biomeTag, TerrainAdjustment.NONE); } - /** - * runs the {@code PieceGeneratorSupplier.Context::validBiome} from the given context at - * height=5 in the middle of the chunk. - * - * @param context The context to test with. - * @return true, if this feature can spawn in the current biome - */ - public static boolean isValidBiome(Structure.GenerationContext context) { - return isValidBiome(context, 5); - } - - /** - * runs the {@code PieceGeneratorSupplier.Context::validBiome} from the given context at the - * given height in the middle of the chunk. - * - * @param context The context to test with. - * @param yPos The Height to test for - * @return true, if this feature can spawn in the current biome - */ - public static boolean isValidBiome(Structure.GenerationContext context, int yPos) { - BlockPos blockPos = context.chunkPos().getMiddleBlockPosition(yPos); - return context.validBiome().test( - context - .chunkGenerator() - .getBiomeSource() - .getNoiseBiome( - QuartPos.fromBlock(blockPos.getX()), - QuartPos.fromBlock(blockPos.getY()), - QuartPos.fromBlock(blockPos.getZ()), - context.randomState().sampler() - ) - ); - } - - public Holder getStructure() { - return structure; - } - - public GenerationStep.Decoration getFeatureStep() { - return featureStep; - } - - /** - * Get the structure ID; - * - * @return {@link ResourceLocation} id. - */ - public ResourceLocation getID() { - return id; - } - - /** - * Adds biome into internal biome list, used in {@link BCLBiomeBuilder}. - * - * @param biome {@link ResourceLocation} biome ID. - */ - public void addInternalBiome(ResourceLocation biome) { - biomes.add(biome); - } - - /** - * Get biome list where this structure feature can generate. Only represents biomes made with {@link BCLBiomeBuilder} and only - * if structure was added during building process. Modification of this list will not affect structure generation. - * - * @return {@link List} of biome {@link ResourceLocation}. - */ - public List getBiomes() { - return biomes; - } } diff --git a/src/main/java/org/betterx/bclib/world/structures/TemplateStructure.java b/src/main/java/org/betterx/bclib/world/structures/TemplateStructure.java index b93ed084..9f15a678 100644 --- a/src/main/java/org/betterx/bclib/world/structures/TemplateStructure.java +++ b/src/main/java/org/betterx/bclib/world/structures/TemplateStructure.java @@ -17,6 +17,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import org.betterx.bclib.api.structures.BCLStructure; import java.util.List; import java.util.Optional; @@ -122,7 +123,7 @@ public abstract class TemplateStructure extends Structure { if (isCorrectBase.test(state, before)) break; } if (y >= maxHeight || y < seaLevel) return Optional.empty(); - + if (!BCLStructure.isValidBiome(ctx, y)) return Optional.empty(); BlockPos halfSize = new BlockPos(structureTemplate.getSize().getX() / 2, 0,