Added StructureBuilder

This commit is contained in:
Frank 2022-05-31 17:39:46 +02:00
parent 359ad3c46b
commit 2623a817d0
5 changed files with 318 additions and 158 deletions

View file

@ -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<Pair<GenerationStep.Carving, Holder<? extends ConfiguredWorldCarver<?>>>> 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<ConfiguredWorldCarver<?>>) oKey.get());
step,
(ResourceKey<ConfiguredWorldCarver<?>>) 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());
}
/**

View file

@ -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<S extends Structure> {
private final Holder<Structure> structure;
private final GenerationStep.Decoration featureStep;
private final List<ResourceLocation> biomes = Lists.newArrayList();
private final ResourceLocation id;
public final TagKey<Biome> biomeTag;
public final ResourceKey<Structure> structureKey;
public final S baseStructure;
public final ResourceKey<StructureSet> structureSetKey;
public final StructurePlacement spreadConfig;
public final StructureType<S> structureType;
public final Codec<S> STRUCTURE_CODEC;
private static HolderSet<Biome> biomes(TagKey<Biome> tagKey) {
return BuiltinRegistries.BIOME.getOrCreateTag(tagKey);
}
private static Structure.StructureSettings structure(TagKey<Biome> tagKey,
Map<MobCategory, StructureSpawnOverride> map,
GenerationStep.Decoration decoration,
TerrainAdjustment terrainAdjustment) {
return new Structure.StructureSettings(biomes(tagKey), map, decoration, terrainAdjustment);
}
private static Structure.StructureSettings structure(TagKey<Biome> tagKey,
GenerationStep.Decoration decoration,
TerrainAdjustment terrainAdjustment) {
return structure(tagKey, Map.of(), decoration, terrainAdjustment);
}
private static <S extends Structure> StructureType<S> registerStructureType(ResourceLocation id,
Codec<S> codec) {
return Registry.register(Registry.STRUCTURE_TYPES, id, () -> codec);
}
protected BCLStructure(@NotNull ResourceLocation id,
@NotNull Function<Structure.StructureSettings, S> structureBuilder,
GenerationStep.Decoration step,
@NotNull StructurePlacement placement,
@NotNull Codec<S> codec,
@NotNull TagKey<Biome> 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<Structure> 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<ResourceLocation> getBiomes() {
return biomes;
}
}

View file

@ -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<S extends Structure> {
private static final BCLStructureBuilder INSTANCE = new BCLStructureBuilder();
private ResourceLocation structureID;
private Function<Structure.StructureSettings, S> structureBuilder;
private GenerationStep.Decoration step;
private Codec<S> codec;
private StructurePlacement placement;
private TagKey<Biome> biomeTag;
private TerrainAdjustment terrainAdjustment;
private BCLStructureBuilder() {
}
public static <S extends Structure> BCLStructureBuilder<S> start(ResourceLocation structureID,
Function<Structure.StructureSettings, S> 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<S> step(TerrainAdjustment value) {
this.terrainAdjustment = value;
return this;
}
public BCLStructureBuilder<S> step(GenerationStep.Decoration value) {
this.step = value;
return this;
}
public BCLStructureBuilder<S> codec(Codec<S> value) {
this.codec = value;
return this;
}
public BCLStructureBuilder<S> placement(StructurePlacement value) {
this.placement = value;
return this;
}
public BCLStructureBuilder<S> randomPlacement(int spacing, int separation) {
this.placement = new RandomSpreadStructurePlacement(spacing,
separation,
RandomSpreadType.LINEAR,
13323129 + spacing + separation + structureID.toString().hashCode() % 10000
);
;
return this;
}
public BCLStructureBuilder<S> biomeTag(String modID, String path) {
this.biomeTag = TagAPI.makeStructureTag(modID, path);
return this;
}
public BCLStructureBuilder<S> biomeTag(TagKey<Biome> tag) {
this.biomeTag = tag;
return this;
}
public BCLStructure<S> 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
);
}
}

View file

@ -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<S extends Structure> {
private static final Random RANDOM = new Random(354);
private final Holder<Structure> structure;
private final GenerationStep.Decoration featureStep;
private final List<ResourceLocation> biomes = Lists.newArrayList();
private final ResourceLocation id;
public final TagKey<Biome> biomeTag;
public final ResourceKey<Structure> structureKey;
public final S baseStructure;
public final ResourceKey<StructureSet> structureSetKey;
public final RandomSpreadStructurePlacement spreadConfig;
public final StructureType<S> structureType;
public final Codec<S> STRUCTURE_CODEC;
private static HolderSet<Biome> biomes(TagKey<Biome> tagKey) {
return BuiltinRegistries.BIOME.getOrCreateTag(tagKey);
}
private static Structure.StructureSettings structure(TagKey<Biome> tagKey,
Map<MobCategory, StructureSpawnOverride> map,
GenerationStep.Decoration decoration,
TerrainAdjustment terrainAdjustment) {
return new Structure.StructureSettings(biomes(tagKey), map, decoration, terrainAdjustment);
}
private static Structure.StructureSettings structure(TagKey<Biome> tagKey,
GenerationStep.Decoration decoration,
TerrainAdjustment terrainAdjustment) {
return structure(tagKey, Map.of(), decoration, terrainAdjustment);
}
private static <S extends Structure> StructureType<S> registerStructureType(ResourceLocation id,
Codec<S> 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<S extends Structure> extends org.betterx.bclib.api.structures.BCLStructure<S> {
@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<Structure.StructureSettings, S> structureBuilder,
GenerationStep.Decoration step,
@ -72,6 +39,16 @@ public class BCLStructure<S extends Structure> {
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<Structure.StructureSettings, S> structureBuilder,
GenerationStep.Decoration step,
@ -88,6 +65,20 @@ public class BCLStructure<S extends Structure> {
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<Structure.StructureSettings, S> structureBuilder,
GenerationStep.Decoration step,
@ -96,104 +87,10 @@ public class BCLStructure<S extends Structure> {
boolean adaptNoise,
Codec<S> codec,
TagKey<Biome> biomeTag) {
this.id = id;
this.featureStep = step;
this.STRUCTURE_CODEC = codec;
//parts from vanilla for Structure generation
//public static final ResourceKey<ConfiguredStructure<?, ?>> JUNGLE_TEMPLE =
// BuiltinStructures.createKey("jungle_pyramid");
//public static final Holder<ConfiguredStructure<?, ?>> JUNGLE_TEMPLE =
// Structures.register(BuiltinStructures.JUNGLE_TEMPLE, Structure.JUNGLE_TEMPLE.configured(NoneFeatureConfiguration.INSTANCE, BiomeTags.HAS_JUNGLE_TEMPLE));
//public static final Holder<StructureSet> JUNGLE_TEMPLES =
// StructureSets.register(BuiltinStructureSets.JUNGLE_TEMPLES, Structures.JUNGLE_TEMPLE, new RandomSpreadStructurePlacement(32, 8, RandomSpreadType.LINEAR, 14357619));
//public static final Structure<NoneFeatureConfiguration> 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<Structure> 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<ResourceLocation> getBiomes() {
return biomes;
}
}

View file

@ -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,