Converted Default Structures

This commit is contained in:
Frank 2022-05-31 16:24:50 +02:00
parent 38f337cd15
commit aede1b6f2b
5 changed files with 136 additions and 176 deletions

View file

@ -65,6 +65,10 @@ public class TagAPI {
return BIOMES.makeTag(new ResourceLocation(modID, name)); return BIOMES.makeTag(new ResourceLocation(modID, name));
} }
public static TagKey<Biome> makeStructureTag(String modID, String name) {
return TagAPI.makeBiomeTag(modID, "has_structure/" + name);
}
/** /**
* Get or create {@link Block} {@link TagKey} with mod namespace. * Get or create {@link Block} {@link TagKey} with mod namespace.

View file

@ -78,10 +78,28 @@ public class BCLStructure<S extends Structure> {
int spacing, int spacing,
int separation, int separation,
boolean adaptNoise) { boolean adaptNoise) {
this(id,
structureBuilder,
step,
spacing,
separation,
adaptNoise,
Structure.simpleCodec(structureBuilder),
null);
}
public BCLStructure(ResourceLocation id,
Function<Structure.StructureSettings, S> structureBuilder,
GenerationStep.Decoration step,
int spacing,
int separation,
boolean adaptNoise,
Codec<S> codec,
TagKey<Biome> biomeTag) {
this.id = id; this.id = id;
this.featureStep = step; this.featureStep = step;
this.STRUCTURE_CODEC = Structure.simpleCodec(structureBuilder); this.STRUCTURE_CODEC = codec;
//parts from vanilla for Structure generation //parts from vanilla for Structure generation
//public static final ResourceKey<ConfiguredStructure<?, ?>> JUNGLE_TEMPLE = //public static final ResourceKey<ConfiguredStructure<?, ?>> JUNGLE_TEMPLE =
// BuiltinStructures.createKey("jungle_pyramid"); // BuiltinStructures.createKey("jungle_pyramid");
@ -101,7 +119,9 @@ public class BCLStructure<S extends Structure> {
this.structureSetKey = ResourceKey.create(Registry.STRUCTURE_SET_REGISTRY, id); this.structureSetKey = ResourceKey.create(Registry.STRUCTURE_SET_REGISTRY, id);
this.structureType = registerStructureType(id, STRUCTURE_CODEC); this.structureType = registerStructureType(id, STRUCTURE_CODEC);
this.biomeTag = TagAPI.makeBiomeTag(id.getNamespace(), "has_structure/" + id.getPath()); this.biomeTag = biomeTag == null
? TagAPI.makeStructureTag(id.getNamespace(), id.getPath())
: biomeTag;
this.baseStructure = structureBuilder.apply(structure(biomeTag, featureStep, TerrainAdjustment.NONE)); this.baseStructure = structureBuilder.apply(structure(biomeTag, featureStep, TerrainAdjustment.NONE));
this.structure = StructuresAccessor.callRegister(structureKey, this.baseStructure); this.structure = StructuresAccessor.callRegister(structureKey, this.baseStructure);
StructureSets.register(structureSetKey, this.structure, spreadConfig); StructureSets.register(structureSetKey, this.structure, spreadConfig);

View file

@ -39,7 +39,7 @@ public class StructureNBT {
} }
public static Rotation getRandomRotation(RandomSource random) { public static Rotation getRandomRotation(RandomSource random) {
return Rotation.getRandom(random) == Rotation.NONE ? Rotation.CLOCKWISE_90 : Rotation.COUNTERCLOCKWISE_90; return Rotation.getRandom(random);
} }
public static Mirror getRandomMirror(RandomSource random) { public static Mirror getRandomMirror(RandomSource random) {
@ -73,7 +73,7 @@ public class StructureNBT {
data, data,
world.getRandom(), world.getRandom(),
Block.UPDATE_CLIENTS Block.UPDATE_CLIENTS
); );
return true; return true;
} }

View file

@ -5,29 +5,23 @@ import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.ServerLevelAccessor; import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.StructurePiece;
import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece;
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext;
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType;
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.util.BlocksHelper;
public class TemplatePiece extends TemplateStructurePiece { public class TemplatePiece extends TemplateStructurePiece {
public static final StructurePieceType INSTANCE = setTemplatePieceId(TemplatePiece::new, public static final StructurePieceType INSTANCE = setTemplatePieceId(TemplatePiece::new,
"template_piece"); "template_piece");
private static StructurePieceType setFullContextPieceId(StructurePieceType structurePieceType, String id) { private static StructurePieceType setFullContextPieceId(StructurePieceType structurePieceType, String id) {
@ -51,52 +45,31 @@ public class TemplatePiece extends TemplateStructurePiece {
Mirror mirror, Mirror mirror,
BlockPos halfSize) { BlockPos halfSize) {
super(INSTANCE, super(INSTANCE,
0, 0,
structureTemplateManager, structureTemplateManager,
resourceLocation, resourceLocation,
resourceLocation.toString(), resourceLocation.toString(),
makeSettings(rotation, mirror, halfSize), makeSettings(rotation, mirror, halfSize),
shiftPos(halfSize, centerPos)); shiftPos(rotation, mirror, halfSize, centerPos));
System.out.println("Piece: " + resourceLocation);
System.out.println(" - " + centerPos);
System.out.println(" - " + boundingBox);
System.out.println(" - " + templatePosition);
} }
public TemplatePiece(StructureTemplateManager structureTemplateManager, CompoundTag compoundTag) { public TemplatePiece(StructureTemplateManager structureTemplateManager, CompoundTag compoundTag) {
super(INSTANCE, super(INSTANCE,
compoundTag, compoundTag,
structureTemplateManager, structureTemplateManager,
(ResourceLocation resourceLocation) -> makeSettings(compoundTag)); (ResourceLocation resourceLocation) -> makeSettings(compoundTag));
} }
private static BlockPos shiftPos(Rotation rotation,
@Override Mirror mirror,
public void postProcess(WorldGenLevel level, BlockPos halfSize,
StructureManager structureManager,
ChunkGenerator chunkGenerator,
RandomSource randomSource,
BoundingBox boundingBox,
ChunkPos chunkPos,
BlockPos blockPos) {
super.postProcess(level,
structureManager,
chunkGenerator,
randomSource,
boundingBox,
chunkPos,
blockPos);
BlocksHelper.setWithoutUpdate(level, new BlockPos(boundingBox.minX(), boundingBox.minY(), boundingBox.minZ()),
Blocks.YELLOW_CONCRETE);
BlocksHelper.setWithoutUpdate(level, new BlockPos(boundingBox.maxX(), boundingBox.maxY(), boundingBox.maxZ()),
Blocks.LIGHT_BLUE_CONCRETE);
BlocksHelper.setWithoutUpdate(level, boundingBox.getCenter(),
Blocks.LIME_CONCRETE);
BlocksHelper.setWithoutUpdate(level, blockPos,
Blocks.ORANGE_CONCRETE);
}
private static BlockPos shiftPos(BlockPos halfSize,
BlockPos pos) { BlockPos pos) {
return pos.offset(-(2 * halfSize.getX()), 0, -(2 * halfSize.getZ())); halfSize = StructureTemplate.transform(halfSize, mirror, rotation, halfSize);
//return pos; return pos.offset(-halfSize.getX(), 0, -halfSize.getZ());
} }
private static StructurePlaceSettings makeSettings(CompoundTag compoundTag) { private static StructurePlaceSettings makeSettings(CompoundTag compoundTag) {
@ -134,72 +107,3 @@ public class TemplatePiece extends TemplateStructurePiece {
} }
} }
class TemplatePiece2 extends StructurePiece {
public static final StructurePieceType INSTANCE = register("template_piece_bcl", TemplatePiece2::new);
private static StructurePieceType register(String id, StructurePieceType pieceType) {
return Registry.register(Registry.STRUCTURE_PIECE, BCLib.makeID(id), pieceType);
}
public static void ensureStaticInitialization() {
}
public final StructureWorldNBT structure;
public final BlockPos pos;
public final Rotation rot;
public final Mirror mir;
protected TemplatePiece2(StructureWorldNBT structure,
BlockPos pos,
Rotation rot,
Mirror mir) {
super(INSTANCE, 0, structure.boundingBox(rot, pos));
this.structure = structure;
this.rot = rot;
this.mir = mir;
this.pos = pos;
}
public TemplatePiece2(StructurePieceSerializationContext ctx, CompoundTag compoundTag) {
super(INSTANCE, compoundTag);
ResourceLocation location = new ResourceLocation(compoundTag.getString("L"));
int offsetY = compoundTag.getInt("OY");
StructurePlacementType type = StructurePlacementType.valueOf(compoundTag.getString("T"));
this.structure = new StructureWorldNBT(location, offsetY, type);
this.rot = Rotation.valueOf(compoundTag.getString("Rot"));
this.mir = Mirror.valueOf(compoundTag.getString("Mir"));
this.pos = new BlockPos(
compoundTag.getInt("PX"),
compoundTag.getInt("PY"),
compoundTag.getInt("PZ")
);
}
@Override
protected void addAdditionalSaveData(StructurePieceSerializationContext structurePieceSerializationContext,
CompoundTag tag) {
tag.putString("L", structure.location.toString());
tag.putInt("OY", structure.offsetY);
tag.putString("T", structure.type.name());
tag.putString("Rot", this.rot.name());
tag.putString("Mir", this.mir.name());
tag.putInt("PX", this.pos.getX());
tag.putInt("PY", this.pos.getY());
tag.putInt("PZ", this.pos.getZ());
}
@Override
public void postProcess(WorldGenLevel worldGenLevel,
StructureManager structureManager,
ChunkGenerator chunkGenerator,
RandomSource randomSource,
BoundingBox boundingBox,
ChunkPos chunkPos,
BlockPos blockPos) {
structure.generate(worldGenLevel, this.pos, this.rot, this.mir);
}
}

View file

@ -21,22 +21,24 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.BiPredicate;
public abstract class TemplateStructure extends Structure { public abstract class TemplateStructure extends Structure {
protected final List<Config> configs; protected final List<Config> configs;
public static <T extends TemplateStructure> Codec<T> simpleCodec(BiFunction instancer) { public static <T extends TemplateStructure> Codec<T> simpleTemplateCodec(BiFunction<StructureSettings, List<Config>, T> instancer) {
return RecordCodecBuilder.create((instance) -> instance return RecordCodecBuilder.create((instance) -> instance
.group( .group(
Structure.settingsCodec(instance), Structure.settingsCodec(instance),
ExtraCodecs.nonEmptyList(Config.CODEC.listOf()) ExtraCodecs.nonEmptyList(Config.CODEC.listOf())
.fieldOf("configs") .fieldOf("configs")
.forGetter((T ruinedPortalStructure) -> ruinedPortalStructure.configs) .forGetter((T ruinedPortalStructure) -> ruinedPortalStructure.configs)
) )
.apply(instance, instancer) .apply(instance, instancer)
); );
} }
protected TemplateStructure(StructureSettings structureSettings, protected TemplateStructure(StructureSettings structureSettings,
ResourceLocation location, ResourceLocation location,
int offsetY, int offsetY,
@ -68,54 +70,84 @@ public abstract class TemplateStructure extends Structure {
return null; return null;
} }
protected boolean isLavaPlaceable(BlockState state, BlockState before) {
return state.is(Blocks.AIR) && before.is(Blocks.LAVA);
}
protected boolean isFloorPlaceable(BlockState state, BlockState before) {
return state.is(Blocks.AIR) && before.getMaterial().isSolid();
}
@Override @Override
public Optional<GenerationStub> findGenerationPoint(GenerationContext ctx) { public Optional<GenerationStub> findGenerationPoint(GenerationContext ctx) {
WorldGenerationContext worldGenerationContext = new WorldGenerationContext(ctx.chunkGenerator(), WorldGenerationContext worldGenerationContext = new WorldGenerationContext(ctx.chunkGenerator(),
ctx.heightAccessor()); ctx.heightAccessor());
final Config config = randomConfig(ctx.random()); final Config config = randomConfig(ctx.random());
if (config == null) return Optional.empty(); if (config == null) return Optional.empty();
ChunkPos chunkPos = ctx.chunkPos(); ChunkPos chunkPos = ctx.chunkPos();
final int x = chunkPos.getMiddleBlockX(); final int x = chunkPos.getMiddleBlockX();
final int z = chunkPos.getMiddleBlockZ(); final int z = chunkPos.getMiddleBlockZ();
NoiseColumn column = ctx.chunkGenerator().getBaseColumn(x, z, ctx.heightAccessor(), ctx.randomState()); NoiseColumn column = ctx.chunkGenerator().getBaseColumn(x, z, ctx.heightAccessor(), ctx.randomState());
final int seaLevel = ctx.chunkGenerator().getSeaLevel();
StructureTemplate structureTemplate = ctx.structureTemplateManager().getOrCreate(config.location); StructureTemplate structureTemplate = ctx.structureTemplateManager().getOrCreate(config.location);
final int maxHeight = worldGenerationContext.getGenDepth() - 4 - (structureTemplate.getSize(Rotation.NONE)
.getY() + config.offsetY);
int y = seaLevel;
BlockState state = column.getBlock(y - 1);
for (; y < maxHeight; y++) {
BlockState below = state; BiPredicate<BlockState, BlockState> isCorrectBase;
state = column.getBlock(y); int searchStep;
if (state.is(Blocks.AIR) && below.is(Blocks.LAVA)) break; if (config.type == StructurePlacementType.LAVA) {
isCorrectBase = this::isLavaPlaceable;
searchStep = 1;
} else if (config.type == StructurePlacementType.CEIL) {
isCorrectBase = this::isFloorPlaceable;
searchStep = -1;
} else {
isCorrectBase = this::isFloorPlaceable;
searchStep = 1;
} }
if (y >= maxHeight) return Optional.empty();
final int seaLevel =
ctx.chunkGenerator().getSeaLevel()
+ (searchStep > 0 ? 0 : (structureTemplate.getSize(Rotation.NONE).getY() + config.offsetY));
final int maxHeight =
worldGenerationContext.getGenDepth()
- 4
- (searchStep > 0 ? (structureTemplate.getSize(Rotation.NONE).getY() + config.offsetY) : 0);
int y = searchStep > 0 ? seaLevel : maxHeight - 1;
BlockState state = column.getBlock(y - searchStep);
for (; y < maxHeight && y >= seaLevel; y += searchStep) {
BlockState before = state;
state = column.getBlock(y);
if (isCorrectBase.test(state, before)) break;
}
if (y >= maxHeight || y < seaLevel) return Optional.empty();
BlockPos halfSize = new BlockPos(structureTemplate.getSize().getX() / 2, BlockPos halfSize = new BlockPos(structureTemplate.getSize().getX() / 2,
0, 0,
structureTemplate.getSize().getZ() / 2); structureTemplate.getSize().getZ() / 2);
Rotation rotation = StructureNBT.getRandomRotation(ctx.random()); Rotation rotation = StructureNBT.getRandomRotation(ctx.random());
Mirror mirror = StructureNBT.getRandomMirror(ctx.random()); Mirror mirror = StructureNBT.getRandomMirror(ctx.random());
BlockPos centerPos = new BlockPos(x, y, z); BlockPos centerPos = new BlockPos(x,
y - (searchStep == 1 ? 0 : (structureTemplate.getSize(Rotation.NONE).getY())),
z);
BoundingBox boundingBox = structureTemplate.getBoundingBox(centerPos, rotation, halfSize, mirror); BoundingBox boundingBox = structureTemplate.getBoundingBox(centerPos, rotation, halfSize, mirror);
// if (!structure.canGenerate(ctx.chunkGenerator()., centerPos)) // if (!structure.canGenerate(ctx.chunkGenerator()., centerPos))
return Optional.of(new GenerationStub(centerPos, return Optional.of(new GenerationStub(centerPos,
structurePiecesBuilder -> structurePiecesBuilder ->
structurePiecesBuilder.addPiece( structurePiecesBuilder.addPiece(
new TemplatePiece(ctx.structureTemplateManager(), new TemplatePiece(ctx.structureTemplateManager(),
config.location, config.location,
centerPos.offset( centerPos.offset(
0, 0,
config.offsetY, config.offsetY,
0), 0),
rotation, rotation,
mirror, mirror,
halfSize)) halfSize))
)); ));
} }
@ -123,28 +155,28 @@ public abstract class TemplateStructure extends Structure {
public record Config(ResourceLocation location, int offsetY, StructurePlacementType type, float chance) { public record Config(ResourceLocation location, int offsetY, StructurePlacementType type, float chance) {
public static final Codec<Config> CODEC = public static final Codec<Config> CODEC =
RecordCodecBuilder.create((instance) -> RecordCodecBuilder.create((instance) ->
instance.group( instance.group(
ResourceLocation.CODEC ResourceLocation.CODEC
.fieldOf("location") .fieldOf("location")
.forGetter((cfg) -> cfg.location), .forGetter((cfg) -> cfg.location),
Codec Codec
.INT .INT
.fieldOf("offset_y") .fieldOf("offset_y")
.orElse(0) .orElse(0)
.forGetter((cfg) -> cfg.offsetY), .forGetter((cfg) -> cfg.offsetY),
StructurePlacementType.CODEC StructurePlacementType.CODEC
.fieldOf("placement") .fieldOf("placement")
.orElse(StructurePlacementType.FLOOR) .orElse(StructurePlacementType.FLOOR)
.forGetter((cfg) -> cfg.type), .forGetter((cfg) -> cfg.type),
Codec Codec
.FLOAT .FLOAT
.fieldOf("chance") .fieldOf("chance")
.orElse(1.0f) .orElse(1.0f)
.forGetter((cfg) -> cfg.chance) .forGetter((cfg) -> cfg.chance)
) )
.apply(instance, Config::new) .apply(instance, Config::new)
); );
} }
} }