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.BCLibEndBiomeSource;
|
||||||
import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
|
import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
|
||||||
import org.betterx.bclib.world.generator.GeneratorOptions;
|
import org.betterx.bclib.world.generator.GeneratorOptions;
|
||||||
|
import org.betterx.bclib.world.structures.TemplatePiece;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -49,15 +50,16 @@ public class BCLib implements ModInitializer {
|
||||||
AnvilRecipe.register();
|
AnvilRecipe.register();
|
||||||
|
|
||||||
DataExchangeAPI.registerDescriptors(List.of(
|
DataExchangeAPI.registerDescriptors(List.of(
|
||||||
HelloClient.DESCRIPTOR,
|
HelloClient.DESCRIPTOR,
|
||||||
HelloServer.DESCRIPTOR,
|
HelloServer.DESCRIPTOR,
|
||||||
RequestFiles.DESCRIPTOR,
|
RequestFiles.DESCRIPTOR,
|
||||||
SendFiles.DESCRIPTOR,
|
SendFiles.DESCRIPTOR,
|
||||||
Chunker.DESCRIPTOR
|
Chunker.DESCRIPTOR
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
BCLibPatch.register();
|
BCLibPatch.register();
|
||||||
|
TemplatePiece.ensureStaticInitialization();
|
||||||
Configs.save();
|
Configs.save();
|
||||||
if (isDevEnvironment()) {
|
if (isDevEnvironment()) {
|
||||||
Biome.BiomeBuilder builder = new Biome.BiomeBuilder()
|
Biome.BiomeBuilder builder = new Biome.BiomeBuilder()
|
||||||
|
|
|
@ -12,24 +12,28 @@ import net.minecraft.world.level.levelgen.placement.EnvironmentScanPlacement;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import org.betterx.bclib.api.features.BCLFeatureBuilder;
|
import org.betterx.bclib.api.features.BCLFeatureBuilder;
|
||||||
|
import org.betterx.bclib.world.structures.StructureNBT;
|
||||||
|
|
||||||
public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<FC> {
|
public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<FC> {
|
||||||
public static final Feature<TemplateFeatureConfig> INSTANCE = BCLFeature.register("template",
|
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,
|
public static <T extends TemplateFeatureConfig> BCLFeature createAndRegister(TemplateFeatureConfig configuration,
|
||||||
int onveEveryChunk) {
|
int onveEveryChunk) {
|
||||||
return BCLFeatureBuilder
|
return BCLFeatureBuilder
|
||||||
.start(new ResourceLocation(configuration.structure.location.getNamespace(),
|
.start(new ResourceLocation(configuration.structure.location.getNamespace(),
|
||||||
"feature_" + configuration.structure.location.getPath()), INSTANCE)
|
"feature_" + configuration.structure.location.getPath()), INSTANCE)
|
||||||
.decoration(GenerationStep.Decoration.SURFACE_STRUCTURES)
|
.decoration(GenerationStep.Decoration.SURFACE_STRUCTURES)
|
||||||
.oncePerChunks(onveEveryChunk)
|
.oncePerChunks(onveEveryChunk)
|
||||||
.squarePlacement()
|
.squarePlacement()
|
||||||
.distanceToTopAndBottom10()
|
.distanceToTopAndBottom10()
|
||||||
.modifier(EnvironmentScanPlacement.scanningFor(Direction.DOWN,
|
.modifier(EnvironmentScanPlacement.scanningFor(Direction.DOWN,
|
||||||
BlockPredicate.solid(),
|
BlockPredicate.solid(),
|
||||||
BlockPredicate.matchesBlocks(Blocks.AIR, Blocks.WATER, Blocks.LAVA),
|
BlockPredicate.matchesBlocks(Blocks.AIR,
|
||||||
12))
|
Blocks.WATER,
|
||||||
|
Blocks.LAVA),
|
||||||
|
12))
|
||||||
.modifier(BiomeFilter.biome())
|
.modifier(BiomeFilter.biome())
|
||||||
.buildAndRegister(configuration);
|
.buildAndRegister(configuration);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +44,10 @@ public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<F
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean place(FeaturePlaceContext<FC> ctx) {
|
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 class StructureNBT {
|
||||||
public final ResourceLocation location;
|
public final ResourceLocation location;
|
||||||
protected StructureTemplate structure;
|
protected StructureTemplate structure;
|
||||||
protected Mirror mirror = Mirror.NONE;
|
|
||||||
protected Rotation rotation = Rotation.NONE;
|
|
||||||
|
|
||||||
protected StructureNBT(ResourceLocation location) {
|
protected StructureNBT(ResourceLocation location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
@ -39,44 +38,33 @@ public class StructureNBT {
|
||||||
this.structure = structure;
|
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();
|
private static final Map<ResourceLocation, StructureNBT> STRUCTURE_CACHE = Maps.newHashMap();
|
||||||
|
|
||||||
public static StructureNBT create(ResourceLocation location) {
|
public static StructureNBT create(ResourceLocation location) {
|
||||||
return STRUCTURE_CACHE.computeIfAbsent(location, r -> new StructureNBT(r));
|
return STRUCTURE_CACHE.computeIfAbsent(location, r -> new StructureNBT(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
public StructureNBT setRotation(Rotation rotation) {
|
public boolean generateCentered(ServerLevelAccessor world, BlockPos pos, Rotation rotation, Mirror mirror) {
|
||||||
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) {
|
|
||||||
if (structure == null) {
|
if (structure == null) {
|
||||||
BCLib.LOGGER.error("No structure: " + location.toString());
|
BCLib.LOGGER.error("No structure: " + location.toString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MutableBlockPos blockpos2 = new MutableBlockPos().set(structure.getSize());
|
MutableBlockPos blockpos2 = new MutableBlockPos().set(structure.getSize());
|
||||||
if (this.mirror == Mirror.FRONT_BACK)
|
if (mirror == Mirror.FRONT_BACK)
|
||||||
blockpos2.setX(-blockpos2.getX());
|
blockpos2.setX(-blockpos2.getX());
|
||||||
if (this.mirror == Mirror.LEFT_RIGHT)
|
if (mirror == Mirror.LEFT_RIGHT)
|
||||||
blockpos2.setZ(-blockpos2.getZ());
|
blockpos2.setZ(-blockpos2.getZ());
|
||||||
blockpos2.set(blockpos2.rotate(rotation));
|
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);
|
BlockPos newPos = pos.offset(-blockpos2.getX() >> 1, 0, -blockpos2.getZ() >> 1);
|
||||||
structure.placeInWorld(
|
structure.placeInWorld(
|
||||||
world,
|
world,
|
||||||
|
@ -85,7 +73,7 @@ public class StructureNBT {
|
||||||
data,
|
data,
|
||||||
world.getRandom(),
|
world.getRandom(),
|
||||||
Block.UPDATE_CLIENTS
|
Block.UPDATE_CLIENTS
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +106,7 @@ public class StructureNBT {
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockPos getSize() {
|
public BlockPos getSize(Rotation rotation) {
|
||||||
if (rotation == Rotation.NONE || rotation == Rotation.CLOCKWISE_180)
|
if (rotation == Rotation.NONE || rotation == Rotation.CLOCKWISE_180)
|
||||||
return new BlockPos(structure.getSize());
|
return new BlockPos(structure.getSize());
|
||||||
else {
|
else {
|
||||||
|
@ -133,7 +121,7 @@ public class StructureNBT {
|
||||||
return location.getPath();
|
return location.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundingBox getBoundingBox(BlockPos pos) {
|
public BoundingBox getBoundingBox(BlockPos pos, Rotation rotation, Mirror mirror) {
|
||||||
return structure.getBoundingBox(new StructurePlaceSettings().setRotation(this.rotation).setMirror(mirror), pos);
|
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;
|
||||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.RandomSource;
|
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.minecraft.world.level.ServerLevelAccessor;
|
import net.minecraft.world.level.ServerLevelAccessor;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
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.block.Rotation;
|
||||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
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) {
|
public boolean generateIfPlaceable(ServerLevelAccessor level,
|
||||||
randomRM(random);
|
BlockPos pos,
|
||||||
return generate(level, pos);
|
Rotation r,
|
||||||
}
|
Mirror m) {
|
||||||
|
if (canGenerate(level, pos, r)) {
|
||||||
public boolean generate(ServerLevelAccessor level, BlockPos pos) {
|
return generate(level, pos, r, m);
|
||||||
if (canGenerate(level, pos)) {
|
|
||||||
return generateCentered(level, pos.above(offsetY));
|
|
||||||
}
|
}
|
||||||
return false;
|
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)
|
if (type == StructurePlacementType.FLOOR)
|
||||||
return canGenerateFloor(level, pos);
|
return canGenerateFloor(level, pos, rotation);
|
||||||
else if (type == StructurePlacementType.LAVA)
|
else if (type == StructurePlacementType.LAVA)
|
||||||
return canGenerateLava(level, pos);
|
return canGenerateLava(level, pos, rotation);
|
||||||
else if (type == StructurePlacementType.UNDER)
|
else if (type == StructurePlacementType.UNDER)
|
||||||
return canGenerateUnder(level, pos);
|
return canGenerateUnder(level, pos, rotation);
|
||||||
else if (type == StructurePlacementType.CEIL)
|
else if (type == StructurePlacementType.CEIL)
|
||||||
return canGenerateCeil(level, pos);
|
return canGenerateCeil(level, pos, rotation);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -67,46 +69,35 @@ public class StructureWorldNBT extends StructureNBT {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canGenerateFloor(LevelAccessor world, BlockPos pos) {
|
protected boolean canGenerateFloor(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||||
if (containsBedrock(world, pos)) return false;
|
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;
|
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;
|
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;
|
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) {
|
public BoundingBox boundingBox(Rotation r, BlockPos p) {
|
||||||
MutableBlockPos size = new MutableBlockPos().set(new BlockPos(structure.getSize()).rotate(rotation));
|
return getBoundingBox(p, r, Mirror.NONE);
|
||||||
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()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float getAirFraction(LevelAccessor world, BlockPos pos) {
|
protected float getAirFraction(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||||
final MutableBlockPos POS = new MutableBlockPos();
|
final MutableBlockPos POS = new MutableBlockPos();
|
||||||
int airCount = 0;
|
int airCount = 0;
|
||||||
|
|
||||||
|
@ -134,7 +125,7 @@ public class StructureWorldNBT extends StructureNBT {
|
||||||
return (float) airCount / count;
|
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();
|
final MutableBlockPos POS = new MutableBlockPos();
|
||||||
int lavaCount = 0;
|
int lavaCount = 0;
|
||||||
|
|
||||||
|
@ -161,7 +152,7 @@ public class StructureWorldNBT extends StructureNBT {
|
||||||
return (float) lavaCount / count;
|
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();
|
final MutableBlockPos POS = new MutableBlockPos();
|
||||||
int airCount = 0;
|
int airCount = 0;
|
||||||
|
|
||||||
|
@ -189,7 +180,7 @@ public class StructureWorldNBT extends StructureNBT {
|
||||||
return (float) airCount / count;
|
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();
|
final MutableBlockPos POS = new MutableBlockPos();
|
||||||
int airCount = 0;
|
int airCount = 0;
|
||||||
|
|
||||||
|
|
|
@ -6,34 +6,154 @@ 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.ChunkPos;
|
||||||
|
import net.minecraft.world.level.ServerLevelAccessor;
|
||||||
import net.minecraft.world.level.StructureManager;
|
import net.minecraft.world.level.StructureManager;
|
||||||
import net.minecraft.world.level.WorldGenLevel;
|
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.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.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.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.StructurePlaceSettings;
|
||||||
|
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 StructurePiece {
|
public class TemplatePiece extends TemplateStructurePiece {
|
||||||
public static final StructurePieceType INSTANCE = register("template_piece", TemplatePiece::new);
|
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) {
|
private static StructurePieceType register(String id, StructurePieceType pieceType) {
|
||||||
return Registry.register(Registry.STRUCTURE_PIECE, BCLib.makeID(id), pieceType);
|
return Registry.register(Registry.STRUCTURE_PIECE, BCLib.makeID(id), pieceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ensureStaticInitialization() {
|
||||||
|
}
|
||||||
|
|
||||||
public final StructureWorldNBT structure;
|
public final StructureWorldNBT structure;
|
||||||
public final BlockPos pos;
|
public final BlockPos pos;
|
||||||
public final Rotation rot;
|
public final Rotation rot;
|
||||||
public final Mirror mir;
|
public final Mirror mir;
|
||||||
|
|
||||||
protected TemplatePiece(StructureWorldNBT structure,
|
protected TemplatePiece2(StructureWorldNBT structure,
|
||||||
BlockPos pos,
|
BlockPos pos,
|
||||||
Rotation rot,
|
Rotation rot,
|
||||||
Mirror mir) {
|
Mirror mir) {
|
||||||
super(INSTANCE, 0, structure.boundingBox(rot, pos));
|
super(INSTANCE, 0, structure.boundingBox(rot, pos));
|
||||||
this.structure = structure;
|
this.structure = structure;
|
||||||
this.rot = rot;
|
this.rot = rot;
|
||||||
|
@ -41,7 +161,7 @@ public class TemplatePiece extends StructurePiece {
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TemplatePiece(StructurePieceSerializationContext ctx, CompoundTag compoundTag) {
|
public TemplatePiece2(StructurePieceSerializationContext ctx, CompoundTag compoundTag) {
|
||||||
super(INSTANCE, compoundTag);
|
super(INSTANCE, compoundTag);
|
||||||
|
|
||||||
ResourceLocation location = new ResourceLocation(compoundTag.getString("L"));
|
ResourceLocation location = new ResourceLocation(compoundTag.getString("L"));
|
||||||
|
@ -64,7 +184,7 @@ public class TemplatePiece extends StructurePiece {
|
||||||
|
|
||||||
tag.putString("L", structure.location.toString());
|
tag.putString("L", structure.location.toString());
|
||||||
tag.putInt("OY", structure.offsetY);
|
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("Rot", this.rot.name());
|
||||||
tag.putString("Mir", this.mir.name());
|
tag.putString("Mir", this.mir.name());
|
||||||
tag.putInt("PX", this.pos.getX());
|
tag.putInt("PX", this.pos.getX());
|
||||||
|
@ -80,6 +200,6 @@ public class TemplatePiece extends StructurePiece {
|
||||||
BoundingBox boundingBox,
|
BoundingBox boundingBox,
|
||||||
ChunkPos chunkPos,
|
ChunkPos chunkPos,
|
||||||
BlockPos blockPos) {
|
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.core.BlockPos;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
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.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.Mirror;
|
||||||
import net.minecraft.world.level.block.Rotation;
|
import net.minecraft.world.level.block.Rotation;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
import net.minecraft.world.level.levelgen.WorldGenerationContext;
|
||||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
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.Codec;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
public abstract class TemplateStructure extends Structure {
|
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
|
return RecordCodecBuilder.create((instance) -> instance
|
||||||
.group(
|
.group(
|
||||||
Structure.settingsCodec(instance),
|
Structure.settingsCodec(instance),
|
||||||
ResourceLocation.CODEC
|
ExtraCodecs.nonEmptyList(Config.CODEC.listOf())
|
||||||
.fieldOf("location")
|
.fieldOf("configs")
|
||||||
.forGetter((T cfg) -> cfg.structure.location),
|
.forGetter((T ruinedPortalStructure) -> ruinedPortalStructure.configs)
|
||||||
|
)
|
||||||
Codec
|
.apply(instance, instancer)
|
||||||
.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)
|
|
||||||
)
|
|
||||||
.apply(instance, instancer)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final StructureWorldNBT structure;
|
|
||||||
|
|
||||||
protected TemplateStructure(StructureSettings structureSettings,
|
protected TemplateStructure(StructureSettings structureSettings,
|
||||||
ResourceLocation location,
|
ResourceLocation location,
|
||||||
int offsetY,
|
int offsetY,
|
||||||
StructurePlacementType type) {
|
StructurePlacementType type,
|
||||||
super(structureSettings);
|
float chance) {
|
||||||
structure = StructureWorldNBT.create(location, offsetY, type);
|
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
|
@Override
|
||||||
public Optional<GenerationStub> findGenerationPoint(GenerationContext ctx) {
|
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();
|
ChunkPos chunkPos = ctx.chunkPos();
|
||||||
final int x = chunkPos.getMiddleBlockX();
|
final int x = chunkPos.getMiddleBlockX();
|
||||||
final int z = chunkPos.getMiddleBlockZ();
|
final int z = chunkPos.getMiddleBlockZ();
|
||||||
int y = ctx
|
NoiseColumn column = ctx.chunkGenerator().getBaseColumn(x, z, ctx.heightAccessor(), ctx.randomState());
|
||||||
.chunkGenerator()
|
final int seaLevel = ctx.chunkGenerator().getSeaLevel();
|
||||||
.getFirstOccupiedHeight(x,
|
StructureTemplate structureTemplate = ctx.structureTemplateManager().getOrCreate(config.location);
|
||||||
z,
|
final int maxHeight = worldGenerationContext.getGenDepth() - 4 - (structureTemplate.getSize(Rotation.NONE)
|
||||||
Heightmap.Types.WORLD_SURFACE_WG,
|
.getY() + config.offsetY);
|
||||||
ctx.heightAccessor(),
|
int y = seaLevel;
|
||||||
ctx.randomState());
|
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);
|
BlockPos centerPos = new BlockPos(x, y, z);
|
||||||
Rotation rotation = Rotation.getRandom(ctx.random());
|
BoundingBox boundingBox = structureTemplate.getBoundingBox(centerPos, rotation, halfSize, mirror);
|
||||||
BoundingBox bb = structure.boundingBox(rotation, centerPos);
|
|
||||||
|
|
||||||
// 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 -> 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,
|
public record Config(ResourceLocation location, int offsetY, StructurePlacementType type, float chance) {
|
||||||
BlockPos centerPos,
|
public static final Codec<Config> CODEC =
|
||||||
Rotation rotation,
|
RecordCodecBuilder.create((instance) ->
|
||||||
Structure.GenerationContext generationContext) {
|
instance.group(
|
||||||
WorldgenRandom worldgenRandom = generationContext.random();
|
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