minecraft-src/net/minecraft/world/level/levelgen/structure/structures/JigsawStructure.java
2025-07-04 03:45:38 +03:00

172 lines
6.9 KiB
Java

package net.minecraft.world.level.levelgen.structure.structures;
import com.google.common.annotations.VisibleForTesting;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.List;
import java.util.Optional;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.WorldGenerationContext;
import net.minecraft.world.level.levelgen.heightproviders.HeightProvider;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.StructureType;
import net.minecraft.world.level.levelgen.structure.Structure.GenerationContext;
import net.minecraft.world.level.levelgen.structure.Structure.GenerationStub;
import net.minecraft.world.level.levelgen.structure.Structure.StructureSettings;
import net.minecraft.world.level.levelgen.structure.pools.DimensionPadding;
import net.minecraft.world.level.levelgen.structure.pools.JigsawPlacement;
import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
import net.minecraft.world.level.levelgen.structure.pools.alias.PoolAliasBinding;
import net.minecraft.world.level.levelgen.structure.pools.alias.PoolAliasLookup;
import net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings;
public final class JigsawStructure extends Structure {
public static final DimensionPadding DEFAULT_DIMENSION_PADDING = DimensionPadding.ZERO;
public static final LiquidSettings DEFAULT_LIQUID_SETTINGS = LiquidSettings.APPLY_WATERLOGGING;
public static final int MAX_TOTAL_STRUCTURE_RANGE = 128;
public static final int MIN_DEPTH = 0;
public static final int MAX_DEPTH = 20;
public static final MapCodec<JigsawStructure> CODEC = RecordCodecBuilder.<JigsawStructure>mapCodec(
instance -> instance.group(
settingsCodec(instance),
StructureTemplatePool.CODEC.fieldOf("start_pool").forGetter(jigsawStructure -> jigsawStructure.startPool),
ResourceLocation.CODEC.optionalFieldOf("start_jigsaw_name").forGetter(jigsawStructure -> jigsawStructure.startJigsawName),
Codec.intRange(0, 20).fieldOf("size").forGetter(jigsawStructure -> jigsawStructure.maxDepth),
HeightProvider.CODEC.fieldOf("start_height").forGetter(jigsawStructure -> jigsawStructure.startHeight),
Codec.BOOL.fieldOf("use_expansion_hack").forGetter(jigsawStructure -> jigsawStructure.useExpansionHack),
Heightmap.Types.CODEC.optionalFieldOf("project_start_to_heightmap").forGetter(jigsawStructure -> jigsawStructure.projectStartToHeightmap),
Codec.intRange(1, 128).fieldOf("max_distance_from_center").forGetter(jigsawStructure -> jigsawStructure.maxDistanceFromCenter),
Codec.list(PoolAliasBinding.CODEC).optionalFieldOf("pool_aliases", List.of()).forGetter(jigsawStructure -> jigsawStructure.poolAliases),
DimensionPadding.CODEC.optionalFieldOf("dimension_padding", DEFAULT_DIMENSION_PADDING).forGetter(jigsawStructure -> jigsawStructure.dimensionPadding),
LiquidSettings.CODEC.optionalFieldOf("liquid_settings", DEFAULT_LIQUID_SETTINGS).forGetter(jigsawStructure -> jigsawStructure.liquidSettings)
)
.apply(instance, JigsawStructure::new)
)
.validate(JigsawStructure::verifyRange);
private final Holder<StructureTemplatePool> startPool;
private final Optional<ResourceLocation> startJigsawName;
private final int maxDepth;
private final HeightProvider startHeight;
private final boolean useExpansionHack;
private final Optional<Heightmap.Types> projectStartToHeightmap;
private final int maxDistanceFromCenter;
private final List<PoolAliasBinding> poolAliases;
private final DimensionPadding dimensionPadding;
private final LiquidSettings liquidSettings;
private static DataResult<JigsawStructure> verifyRange(JigsawStructure structure) {
int i = switch (structure.terrainAdaptation()) {
case NONE -> 0;
case BURY, BEARD_THIN, BEARD_BOX, ENCAPSULATE -> 12;
};
return structure.maxDistanceFromCenter + i > 128
? DataResult.error(() -> "Structure size including terrain adaptation must not exceed 128")
: DataResult.success(structure);
}
public JigsawStructure(
StructureSettings settings,
Holder<StructureTemplatePool> startPool,
Optional<ResourceLocation> startJigsawName,
int maxDepth,
HeightProvider startHeight,
boolean useExpansionHack,
Optional<Heightmap.Types> projectStartToHeightmap,
int maxDistanceFromCenter,
List<PoolAliasBinding> poolAliases,
DimensionPadding dimensionPadding,
LiquidSettings liquidSettings
) {
super(settings);
this.startPool = startPool;
this.startJigsawName = startJigsawName;
this.maxDepth = maxDepth;
this.startHeight = startHeight;
this.useExpansionHack = useExpansionHack;
this.projectStartToHeightmap = projectStartToHeightmap;
this.maxDistanceFromCenter = maxDistanceFromCenter;
this.poolAliases = poolAliases;
this.dimensionPadding = dimensionPadding;
this.liquidSettings = liquidSettings;
}
public JigsawStructure(
StructureSettings settings,
Holder<StructureTemplatePool> startPool,
int maxDepth,
HeightProvider startHeight,
boolean useExpansionHack,
Heightmap.Types projectStartToHeightmap
) {
this(
settings,
startPool,
Optional.empty(),
maxDepth,
startHeight,
useExpansionHack,
Optional.of(projectStartToHeightmap),
80,
List.of(),
DEFAULT_DIMENSION_PADDING,
DEFAULT_LIQUID_SETTINGS
);
}
public JigsawStructure(StructureSettings settings, Holder<StructureTemplatePool> startPool, int maxDepth, HeightProvider startHeight, boolean useExpansionHack) {
this(
settings,
startPool,
Optional.empty(),
maxDepth,
startHeight,
useExpansionHack,
Optional.empty(),
80,
List.of(),
DEFAULT_DIMENSION_PADDING,
DEFAULT_LIQUID_SETTINGS
);
}
@Override
public Optional<GenerationStub> findGenerationPoint(GenerationContext context) {
ChunkPos chunkPos = context.chunkPos();
int i = this.startHeight.sample(context.random(), new WorldGenerationContext(context.chunkGenerator(), context.heightAccessor()));
BlockPos blockPos = new BlockPos(chunkPos.getMinBlockX(), i, chunkPos.getMinBlockZ());
return JigsawPlacement.addPieces(
context,
this.startPool,
this.startJigsawName,
this.maxDepth,
blockPos,
this.useExpansionHack,
this.projectStartToHeightmap,
this.maxDistanceFromCenter,
PoolAliasLookup.create(this.poolAliases, blockPos, context.seed()),
this.dimensionPadding,
this.liquidSettings
);
}
@Override
public StructureType<?> type() {
return StructureType.JIGSAW;
}
@VisibleForTesting
public Holder<StructureTemplatePool> getStartPool() {
return this.startPool;
}
@VisibleForTesting
public List<PoolAliasBinding> getPoolAliases() {
return this.poolAliases;
}
}