Template Structures (but missaligned)
This commit is contained in:
parent
86a92c560b
commit
38f337cd15
6 changed files with 307 additions and 137 deletions
|
@ -25,6 +25,7 @@ import org.betterx.bclib.util.Logger;
|
|||
import org.betterx.bclib.world.generator.BCLibEndBiomeSource;
|
||||
import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
|
||||
import org.betterx.bclib.world.generator.GeneratorOptions;
|
||||
import org.betterx.bclib.world.structures.TemplatePiece;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -58,6 +59,7 @@ public class BCLib implements ModInitializer {
|
|||
);
|
||||
|
||||
BCLibPatch.register();
|
||||
TemplatePiece.ensureStaticInitialization();
|
||||
Configs.save();
|
||||
if (isDevEnvironment()) {
|
||||
Biome.BiomeBuilder builder = new Biome.BiomeBuilder()
|
||||
|
|
|
@ -12,10 +12,12 @@ import net.minecraft.world.level.levelgen.placement.EnvironmentScanPlacement;
|
|||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.api.features.BCLFeatureBuilder;
|
||||
import org.betterx.bclib.world.structures.StructureNBT;
|
||||
|
||||
public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<FC> {
|
||||
public static final Feature<TemplateFeatureConfig> INSTANCE = BCLFeature.register("template",
|
||||
new TemplateFeature(TemplateFeatureConfig.CODEC));
|
||||
new TemplateFeature(
|
||||
TemplateFeatureConfig.CODEC));
|
||||
|
||||
public static <T extends TemplateFeatureConfig> BCLFeature createAndRegister(TemplateFeatureConfig configuration,
|
||||
int onveEveryChunk) {
|
||||
|
@ -28,7 +30,9 @@ public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<F
|
|||
.distanceToTopAndBottom10()
|
||||
.modifier(EnvironmentScanPlacement.scanningFor(Direction.DOWN,
|
||||
BlockPredicate.solid(),
|
||||
BlockPredicate.matchesBlocks(Blocks.AIR, Blocks.WATER, Blocks.LAVA),
|
||||
BlockPredicate.matchesBlocks(Blocks.AIR,
|
||||
Blocks.WATER,
|
||||
Blocks.LAVA),
|
||||
12))
|
||||
.modifier(BiomeFilter.biome())
|
||||
.buildAndRegister(configuration);
|
||||
|
@ -40,6 +44,10 @@ public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<F
|
|||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<FC> ctx) {
|
||||
return ctx.config().structure.generateInRandomOrientation(ctx.level(), ctx.origin(), ctx.random());
|
||||
return ctx.config().structure.generateIfPlaceable(ctx.level(),
|
||||
ctx.origin(),
|
||||
StructureNBT.getRandomRotation(ctx.random()),
|
||||
StructureNBT.getRandomMirror(ctx.random())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,7 @@ import java.util.Map;
|
|||
public class StructureNBT {
|
||||
public final ResourceLocation location;
|
||||
protected StructureTemplate structure;
|
||||
protected Mirror mirror = Mirror.NONE;
|
||||
protected Rotation rotation = Rotation.NONE;
|
||||
|
||||
|
||||
protected StructureNBT(ResourceLocation location) {
|
||||
this.location = location;
|
||||
|
@ -39,44 +38,33 @@ public class StructureNBT {
|
|||
this.structure = structure;
|
||||
}
|
||||
|
||||
public static Rotation getRandomRotation(RandomSource random) {
|
||||
return Rotation.getRandom(random) == Rotation.NONE ? Rotation.CLOCKWISE_90 : Rotation.COUNTERCLOCKWISE_90;
|
||||
}
|
||||
|
||||
public static Mirror getRandomMirror(RandomSource random) {
|
||||
return Mirror.values()[random.nextInt(3)];
|
||||
}
|
||||
|
||||
private static final Map<ResourceLocation, StructureNBT> STRUCTURE_CACHE = Maps.newHashMap();
|
||||
|
||||
public static StructureNBT create(ResourceLocation location) {
|
||||
return STRUCTURE_CACHE.computeIfAbsent(location, r -> new StructureNBT(r));
|
||||
}
|
||||
|
||||
public StructureNBT setRotation(Rotation rotation) {
|
||||
this.rotation = rotation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Mirror getMirror() {
|
||||
return mirror;
|
||||
}
|
||||
|
||||
public StructureNBT setMirror(Mirror mirror) {
|
||||
this.mirror = mirror;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void randomRM(RandomSource random) {
|
||||
rotation = Rotation.values()[random.nextInt(4)];
|
||||
mirror = Mirror.values()[random.nextInt(3)];
|
||||
}
|
||||
|
||||
public boolean generateCentered(ServerLevelAccessor world, BlockPos pos) {
|
||||
public boolean generateCentered(ServerLevelAccessor world, BlockPos pos, Rotation rotation, Mirror mirror) {
|
||||
if (structure == null) {
|
||||
BCLib.LOGGER.error("No structure: " + location.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
MutableBlockPos blockpos2 = new MutableBlockPos().set(structure.getSize());
|
||||
if (this.mirror == Mirror.FRONT_BACK)
|
||||
if (mirror == Mirror.FRONT_BACK)
|
||||
blockpos2.setX(-blockpos2.getX());
|
||||
if (this.mirror == Mirror.LEFT_RIGHT)
|
||||
if (mirror == Mirror.LEFT_RIGHT)
|
||||
blockpos2.setZ(-blockpos2.getZ());
|
||||
blockpos2.set(blockpos2.rotate(rotation));
|
||||
StructurePlaceSettings data = new StructurePlaceSettings().setRotation(this.rotation).setMirror(this.mirror);
|
||||
StructurePlaceSettings data = new StructurePlaceSettings().setRotation(rotation).setMirror(mirror);
|
||||
BlockPos newPos = pos.offset(-blockpos2.getX() >> 1, 0, -blockpos2.getZ() >> 1);
|
||||
structure.placeInWorld(
|
||||
world,
|
||||
|
@ -118,7 +106,7 @@ public class StructureNBT {
|
|||
return template;
|
||||
}
|
||||
|
||||
public BlockPos getSize() {
|
||||
public BlockPos getSize(Rotation rotation) {
|
||||
if (rotation == Rotation.NONE || rotation == Rotation.CLOCKWISE_180)
|
||||
return new BlockPos(structure.getSize());
|
||||
else {
|
||||
|
@ -133,7 +121,7 @@ public class StructureNBT {
|
|||
return location.getPath();
|
||||
}
|
||||
|
||||
public BoundingBox getBoundingBox(BlockPos pos) {
|
||||
return structure.getBoundingBox(new StructurePlaceSettings().setRotation(this.rotation).setMirror(mirror), pos);
|
||||
public BoundingBox getBoundingBox(BlockPos pos, Rotation rotation, Mirror mirror) {
|
||||
return structure.getBoundingBox(new StructurePlaceSettings().setRotation(rotation).setMirror(mirror), pos);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ package org.betterx.bclib.world.structures;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
|
||||
|
@ -33,27 +33,29 @@ public class StructureWorldNBT extends StructureNBT {
|
|||
}
|
||||
|
||||
|
||||
public boolean generateInRandomOrientation(ServerLevelAccessor level, BlockPos pos, RandomSource random) {
|
||||
randomRM(random);
|
||||
return generate(level, pos);
|
||||
}
|
||||
|
||||
public boolean generate(ServerLevelAccessor level, BlockPos pos) {
|
||||
if (canGenerate(level, pos)) {
|
||||
return generateCentered(level, pos.above(offsetY));
|
||||
public boolean generateIfPlaceable(ServerLevelAccessor level,
|
||||
BlockPos pos,
|
||||
Rotation r,
|
||||
Mirror m) {
|
||||
if (canGenerate(level, pos, r)) {
|
||||
return generate(level, pos, r, m);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean canGenerate(LevelAccessor level, BlockPos pos) {
|
||||
public boolean generate(ServerLevelAccessor level, BlockPos pos, Rotation r, Mirror m) {
|
||||
return generateCentered(level, pos.above(offsetY), r, m);
|
||||
}
|
||||
|
||||
protected boolean canGenerate(LevelAccessor level, BlockPos pos, Rotation rotation) {
|
||||
if (type == StructurePlacementType.FLOOR)
|
||||
return canGenerateFloor(level, pos);
|
||||
return canGenerateFloor(level, pos, rotation);
|
||||
else if (type == StructurePlacementType.LAVA)
|
||||
return canGenerateLava(level, pos);
|
||||
return canGenerateLava(level, pos, rotation);
|
||||
else if (type == StructurePlacementType.UNDER)
|
||||
return canGenerateUnder(level, pos);
|
||||
return canGenerateUnder(level, pos, rotation);
|
||||
else if (type == StructurePlacementType.CEIL)
|
||||
return canGenerateCeil(level, pos);
|
||||
return canGenerateCeil(level, pos, rotation);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
@ -67,46 +69,35 @@ public class StructureWorldNBT extends StructureNBT {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected boolean canGenerateFloor(LevelAccessor world, BlockPos pos) {
|
||||
protected boolean canGenerateFloor(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getAirFraction(world, pos) > 0.6 && getAirFractionFoundation(world, pos) < 0.5;
|
||||
return getAirFraction(world, pos, rotation) > 0.6 && getAirFractionFoundation(world, pos, rotation) < 0.5;
|
||||
}
|
||||
|
||||
protected boolean canGenerateLava(LevelAccessor world, BlockPos pos) {
|
||||
protected boolean canGenerateLava(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getLavaFractionFoundation(world, pos) > 0.9 && getAirFraction(world, pos) > 0.9;
|
||||
return getLavaFractionFoundation(world, pos, rotation) > 0.9 && getAirFraction(world, pos, rotation) > 0.9;
|
||||
}
|
||||
|
||||
protected boolean canGenerateUnder(LevelAccessor world, BlockPos pos) {
|
||||
protected boolean canGenerateUnder(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getAirFraction(world, pos) < 0.2;
|
||||
return getAirFraction(world, pos, rotation) < 0.2;
|
||||
}
|
||||
|
||||
protected boolean canGenerateCeil(LevelAccessor world, BlockPos pos) {
|
||||
protected boolean canGenerateCeil(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getAirFractionBottom(world, pos) > 0.8 && getAirFraction(world, pos) < 0.6;
|
||||
return getAirFractionBottom(world, pos, rotation) > 0.8 && getAirFraction(world, pos, rotation) < 0.6;
|
||||
}
|
||||
|
||||
public BoundingBox boundingBox(Rotation r, BlockPos p) {
|
||||
MutableBlockPos size = new MutableBlockPos().set(new BlockPos(structure.getSize()).rotate(rotation));
|
||||
size.setX(Math.abs(size.getX()) >> 1);
|
||||
size.setY(Math.abs(size.getY()) >> 1);
|
||||
size.setZ(Math.abs(size.getZ()) >> 1);
|
||||
return new BoundingBox(
|
||||
p.getX() - size.getX(),
|
||||
p.getY() - size.getY(),
|
||||
p.getZ() - size.getZ(),
|
||||
p.getX() + size.getX(),
|
||||
p.getY() + size.getY(),
|
||||
p.getZ() + size.getZ()
|
||||
);
|
||||
return getBoundingBox(p, r, Mirror.NONE);
|
||||
}
|
||||
|
||||
protected float getAirFraction(LevelAccessor world, BlockPos pos) {
|
||||
protected float getAirFraction(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
final MutableBlockPos POS = new MutableBlockPos();
|
||||
int airCount = 0;
|
||||
|
||||
|
@ -134,7 +125,7 @@ public class StructureWorldNBT extends StructureNBT {
|
|||
return (float) airCount / count;
|
||||
}
|
||||
|
||||
private float getLavaFractionFoundation(LevelAccessor world, BlockPos pos) {
|
||||
private float getLavaFractionFoundation(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
final MutableBlockPos POS = new MutableBlockPos();
|
||||
int lavaCount = 0;
|
||||
|
||||
|
@ -161,7 +152,7 @@ public class StructureWorldNBT extends StructureNBT {
|
|||
return (float) lavaCount / count;
|
||||
}
|
||||
|
||||
private float getAirFractionFoundation(LevelAccessor world, BlockPos pos) {
|
||||
private float getAirFractionFoundation(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
final MutableBlockPos POS = new MutableBlockPos();
|
||||
int airCount = 0;
|
||||
|
||||
|
@ -189,7 +180,7 @@ public class StructureWorldNBT extends StructureNBT {
|
|||
return (float) airCount / count;
|
||||
}
|
||||
|
||||
private float getAirFractionBottom(LevelAccessor world, BlockPos pos) {
|
||||
private float getAirFractionBottom(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
final MutableBlockPos POS = new MutableBlockPos();
|
||||
int airCount = 0;
|
||||
|
||||
|
|
|
@ -6,31 +6,151 @@ import net.minecraft.nbt.CompoundTag;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
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.Rotation;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
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.pieces.StructurePieceSerializationContext;
|
||||
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.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
|
||||
public class TemplatePiece extends StructurePiece {
|
||||
public static final StructurePieceType INSTANCE = register("template_piece", TemplatePiece::new);
|
||||
public class TemplatePiece extends TemplateStructurePiece {
|
||||
public static final StructurePieceType INSTANCE = setTemplatePieceId(TemplatePiece::new,
|
||||
"template_piece");
|
||||
|
||||
|
||||
private static StructurePieceType setFullContextPieceId(StructurePieceType structurePieceType, String id) {
|
||||
return Registry.register(Registry.STRUCTURE_PIECE, BCLib.makeID(id), structurePieceType);
|
||||
}
|
||||
|
||||
private static StructurePieceType setTemplatePieceId(StructurePieceType.StructureTemplateType structureTemplateType,
|
||||
String string) {
|
||||
return setFullContextPieceId(structureTemplateType, string);
|
||||
}
|
||||
|
||||
|
||||
public static void ensureStaticInitialization() {
|
||||
}
|
||||
|
||||
|
||||
public TemplatePiece(StructureTemplateManager structureTemplateManager,
|
||||
ResourceLocation resourceLocation,
|
||||
BlockPos centerPos,
|
||||
Rotation rotation,
|
||||
Mirror mirror,
|
||||
BlockPos halfSize) {
|
||||
super(INSTANCE,
|
||||
0,
|
||||
structureTemplateManager,
|
||||
resourceLocation,
|
||||
resourceLocation.toString(),
|
||||
makeSettings(rotation, mirror, halfSize),
|
||||
shiftPos(halfSize, centerPos));
|
||||
}
|
||||
|
||||
public TemplatePiece(StructureTemplateManager structureTemplateManager, CompoundTag compoundTag) {
|
||||
super(INSTANCE,
|
||||
compoundTag,
|
||||
structureTemplateManager,
|
||||
(ResourceLocation resourceLocation) -> makeSettings(compoundTag));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void postProcess(WorldGenLevel level,
|
||||
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) {
|
||||
return pos.offset(-(2 * halfSize.getX()), 0, -(2 * halfSize.getZ()));
|
||||
//return pos;
|
||||
}
|
||||
|
||||
private static StructurePlaceSettings makeSettings(CompoundTag compoundTag) {
|
||||
return makeSettings(
|
||||
Rotation.valueOf(compoundTag.getString("R")),
|
||||
Mirror.valueOf(compoundTag.getString("M")),
|
||||
new BlockPos(compoundTag.getInt("RX"), compoundTag.getInt("RY"), compoundTag.getInt("RZ")));
|
||||
|
||||
}
|
||||
|
||||
private static StructurePlaceSettings makeSettings(Rotation rotation, Mirror mirror, BlockPos halfSize) {
|
||||
return new StructurePlaceSettings().setRotation(rotation)
|
||||
.setMirror(mirror)
|
||||
.setRotationPivot(halfSize)
|
||||
.addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionalSaveData(StructurePieceSerializationContext structurePieceSerializationContext,
|
||||
CompoundTag tag) {
|
||||
super.addAdditionalSaveData(structurePieceSerializationContext, tag);
|
||||
tag.putString("R", this.placeSettings.getRotation().name());
|
||||
tag.putString("M", this.placeSettings.getMirror().name());
|
||||
tag.putInt("RX", this.placeSettings.getRotationPivot().getX());
|
||||
tag.putInt("RY", this.placeSettings.getRotationPivot().getY());
|
||||
tag.putInt("RZ", this.placeSettings.getRotationPivot().getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleDataMarker(String string,
|
||||
BlockPos blockPos,
|
||||
ServerLevelAccessor serverLevelAccessor,
|
||||
RandomSource randomSource,
|
||||
BoundingBox boundingBox) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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 TemplatePiece(StructureWorldNBT structure,
|
||||
protected TemplatePiece2(StructureWorldNBT structure,
|
||||
BlockPos pos,
|
||||
Rotation rot,
|
||||
Mirror mir) {
|
||||
|
@ -41,7 +161,7 @@ public class TemplatePiece extends StructurePiece {
|
|||
this.pos = pos;
|
||||
}
|
||||
|
||||
public TemplatePiece(StructurePieceSerializationContext ctx, CompoundTag compoundTag) {
|
||||
public TemplatePiece2(StructurePieceSerializationContext ctx, CompoundTag compoundTag) {
|
||||
super(INSTANCE, compoundTag);
|
||||
|
||||
ResourceLocation location = new ResourceLocation(compoundTag.getString("L"));
|
||||
|
@ -64,7 +184,7 @@ public class TemplatePiece extends StructurePiece {
|
|||
|
||||
tag.putString("L", structure.location.toString());
|
||||
tag.putInt("OY", structure.offsetY);
|
||||
tag.putString("T", structure.type.getSerializedName());
|
||||
tag.putString("T", structure.type.name());
|
||||
tag.putString("Rot", this.rot.name());
|
||||
tag.putString("Mir", this.mir.name());
|
||||
tag.putInt("PX", this.pos.getX());
|
||||
|
@ -80,6 +200,6 @@ public class TemplatePiece extends StructurePiece {
|
|||
BoundingBox boundingBox,
|
||||
ChunkPos chunkPos,
|
||||
BlockPos blockPos) {
|
||||
structure.generateInRandomOrientation(worldGenLevel, blockPos, randomSource);
|
||||
structure.generate(worldGenLevel, this.pos, this.rot, this.mir);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,88 +2,149 @@ package org.betterx.bclib.world.structures;
|
|||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.WorldGenerationContext;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
|
||||
import com.mojang.datafixers.util.Function4;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public abstract class TemplateStructure extends Structure {
|
||||
public static <T extends TemplateStructure> Codec<T> simpleCodec(Function4 instancer) {
|
||||
protected final List<Config> configs;
|
||||
|
||||
public static <T extends TemplateStructure> Codec<T> simpleCodec(BiFunction instancer) {
|
||||
return RecordCodecBuilder.create((instance) -> instance
|
||||
.group(
|
||||
Structure.settingsCodec(instance),
|
||||
ResourceLocation.CODEC
|
||||
.fieldOf("location")
|
||||
.forGetter((T cfg) -> cfg.structure.location),
|
||||
|
||||
Codec
|
||||
.INT
|
||||
.fieldOf("offset_y")
|
||||
.orElse(0)
|
||||
.forGetter((T cfg) -> cfg.structure.offsetY),
|
||||
|
||||
StructurePlacementType.CODEC
|
||||
.fieldOf("placement")
|
||||
.orElse(StructurePlacementType.FLOOR)
|
||||
.forGetter((T cfg) -> cfg.structure.type)
|
||||
ExtraCodecs.nonEmptyList(Config.CODEC.listOf())
|
||||
.fieldOf("configs")
|
||||
.forGetter((T ruinedPortalStructure) -> ruinedPortalStructure.configs)
|
||||
)
|
||||
.apply(instance, instancer)
|
||||
);
|
||||
}
|
||||
|
||||
public final StructureWorldNBT structure;
|
||||
|
||||
protected TemplateStructure(StructureSettings structureSettings,
|
||||
ResourceLocation location,
|
||||
int offsetY,
|
||||
StructurePlacementType type) {
|
||||
super(structureSettings);
|
||||
structure = StructureWorldNBT.create(location, offsetY, type);
|
||||
StructurePlacementType type,
|
||||
float chance) {
|
||||
this(structureSettings, List.of(new Config(location, offsetY, type, chance)));
|
||||
}
|
||||
|
||||
protected TemplateStructure(StructureSettings structureSettings,
|
||||
List<Config> configs) {
|
||||
super(structureSettings);
|
||||
this.configs = configs;
|
||||
}
|
||||
|
||||
protected Config randomConfig(RandomSource random) {
|
||||
Config config = null;
|
||||
if (this.configs.size() > 1) {
|
||||
final float chanceSum = configs.parallelStream().map(c -> c.chance()).reduce(0.0f, (p, c) -> p + c);
|
||||
float rnd = random.nextFloat() * chanceSum;
|
||||
|
||||
for (Config c : configs) {
|
||||
rnd -= c.chance();
|
||||
if (rnd <= 0) return c;
|
||||
}
|
||||
} else {
|
||||
return this.configs.get(0);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<GenerationStub> findGenerationPoint(GenerationContext ctx) {
|
||||
WorldGenerationContext worldGenerationContext = new WorldGenerationContext(ctx.chunkGenerator(),
|
||||
ctx.heightAccessor());
|
||||
final Config config = randomConfig(ctx.random());
|
||||
if (config == null) return Optional.empty();
|
||||
|
||||
ChunkPos chunkPos = ctx.chunkPos();
|
||||
final int x = chunkPos.getMiddleBlockX();
|
||||
final int z = chunkPos.getMiddleBlockZ();
|
||||
int y = ctx
|
||||
.chunkGenerator()
|
||||
.getFirstOccupiedHeight(x,
|
||||
z,
|
||||
Heightmap.Types.WORLD_SURFACE_WG,
|
||||
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);
|
||||
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;
|
||||
state = column.getBlock(y);
|
||||
if (state.is(Blocks.AIR) && below.is(Blocks.LAVA)) break;
|
||||
}
|
||||
if (y >= maxHeight) return Optional.empty();
|
||||
|
||||
|
||||
BlockPos halfSize = new BlockPos(structureTemplate.getSize().getX() / 2,
|
||||
0,
|
||||
structureTemplate.getSize().getZ() / 2);
|
||||
Rotation rotation = StructureNBT.getRandomRotation(ctx.random());
|
||||
Mirror mirror = StructureNBT.getRandomMirror(ctx.random());
|
||||
BlockPos centerPos = new BlockPos(x, y, z);
|
||||
Rotation rotation = Rotation.getRandom(ctx.random());
|
||||
BoundingBox bb = structure.boundingBox(rotation, centerPos);
|
||||
BoundingBox boundingBox = structureTemplate.getBoundingBox(centerPos, rotation, halfSize, mirror);
|
||||
|
||||
|
||||
// if (!structure.canGenerate(ctx.chunkGenerator()., centerPos))
|
||||
return Optional.of(new GenerationStub(centerPos,
|
||||
structurePiecesBuilder -> this.generatePieces(structurePiecesBuilder, centerPos, rotation, ctx)));
|
||||
structurePiecesBuilder ->
|
||||
structurePiecesBuilder.addPiece(
|
||||
new TemplatePiece(ctx.structureTemplateManager(),
|
||||
config.location,
|
||||
centerPos.offset(
|
||||
0,
|
||||
config.offsetY,
|
||||
0),
|
||||
rotation,
|
||||
mirror,
|
||||
halfSize))
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
private void generatePieces(StructurePiecesBuilder structurePiecesBuilder,
|
||||
BlockPos centerPos,
|
||||
Rotation rotation,
|
||||
Structure.GenerationContext generationContext) {
|
||||
WorldgenRandom worldgenRandom = generationContext.random();
|
||||
public record Config(ResourceLocation location, int offsetY, StructurePlacementType type, float chance) {
|
||||
public static final Codec<Config> CODEC =
|
||||
RecordCodecBuilder.create((instance) ->
|
||||
instance.group(
|
||||
ResourceLocation.CODEC
|
||||
.fieldOf("location")
|
||||
.forGetter((cfg) -> cfg.location),
|
||||
|
||||
Mirror mirror = Mirror.values()[worldgenRandom.nextInt(3)];
|
||||
Codec
|
||||
.INT
|
||||
.fieldOf("offset_y")
|
||||
.orElse(0)
|
||||
.forGetter((cfg) -> cfg.offsetY),
|
||||
|
||||
structurePiecesBuilder.addPiece(new TemplatePiece(structure, centerPos, rotation, mirror));
|
||||
StructurePlacementType.CODEC
|
||||
.fieldOf("placement")
|
||||
.orElse(StructurePlacementType.FLOOR)
|
||||
.forGetter((cfg) -> cfg.type),
|
||||
Codec
|
||||
.FLOAT
|
||||
.fieldOf("chance")
|
||||
.orElse(1.0f)
|
||||
.forGetter((cfg) -> cfg.chance)
|
||||
)
|
||||
.apply(instance, Config::new)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue