Code/net/minecraft/world/level/levelgen/structure/pools/SinglePoolElement.java

193 lines
9.2 KiB
Java

package net.minecraft.world.level.levelgen.structure.pools;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.mojang.serialization.codecs.RecordCodecBuilder.Instance;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
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.Rotation;
import net.minecraft.world.level.block.state.properties.StructureMode;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor;
import net.minecraft.world.level.levelgen.structure.templatesystem.JigsawReplacementProcessor;
import net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
public class SinglePoolElement extends StructurePoolElement {
private static final Comparator<StructureTemplate.JigsawBlockInfo> HIGHEST_SELECTION_PRIORITY_FIRST = Comparator.comparingInt(StructureTemplate.JigsawBlockInfo::selectionPriority)
.reversed();
private static final Codec<Either<ResourceLocation, StructureTemplate>> TEMPLATE_CODEC = Codec.of(
SinglePoolElement::encodeTemplate, ResourceLocation.CODEC.map(Either::left)
);
public static final MapCodec<SinglePoolElement> CODEC = RecordCodecBuilder.mapCodec(
p_391071_ -> p_391071_.group(templateCodec(), processorsCodec(), projectionCodec(), overrideLiquidSettingsCodec()).apply(p_391071_, SinglePoolElement::new)
);
protected final Either<ResourceLocation, StructureTemplate> template;
protected final Holder<StructureProcessorList> processors;
protected final Optional<LiquidSettings> overrideLiquidSettings;
private static <T> DataResult<T> encodeTemplate(Either<ResourceLocation, StructureTemplate> p_210425_, DynamicOps<T> p_210426_, T p_210427_) {
Optional<ResourceLocation> optional = p_210425_.left();
return optional.isEmpty()
? DataResult.error(() -> "Can not serialize a runtime pool element")
: ResourceLocation.CODEC.encode(optional.get(), p_210426_, p_210427_);
}
protected static <E extends SinglePoolElement> RecordCodecBuilder<E, Holder<StructureProcessorList>> processorsCodec() {
return StructureProcessorType.LIST_CODEC.fieldOf("processors").forGetter(p_210464_ -> p_210464_.processors);
}
protected static <E extends SinglePoolElement> RecordCodecBuilder<E, Optional<LiquidSettings>> overrideLiquidSettingsCodec() {
return LiquidSettings.CODEC.optionalFieldOf("override_liquid_settings").forGetter(p_341934_ -> p_341934_.overrideLiquidSettings);
}
protected static <E extends SinglePoolElement> RecordCodecBuilder<E, Either<ResourceLocation, StructureTemplate>> templateCodec() {
return TEMPLATE_CODEC.fieldOf("location").forGetter(p_210431_ -> p_210431_.template);
}
protected SinglePoolElement(
Either<ResourceLocation, StructureTemplate> p_210415_,
Holder<StructureProcessorList> p_210416_,
StructureTemplatePool.Projection p_210417_,
Optional<LiquidSettings> p_344439_
) {
super(p_210417_);
this.template = p_210415_;
this.processors = p_210416_;
this.overrideLiquidSettings = p_344439_;
}
@Override
public Vec3i getSize(StructureTemplateManager p_227313_, Rotation p_227314_) {
StructureTemplate structuretemplate = this.getTemplate(p_227313_);
return structuretemplate.getSize(p_227314_);
}
private StructureTemplate getTemplate(StructureTemplateManager p_227300_) {
return this.template.map(p_227300_::getOrCreate, Function.identity());
}
public List<StructureTemplate.StructureBlockInfo> getDataMarkers(StructureTemplateManager p_227325_, BlockPos p_227326_, Rotation p_227327_, boolean p_227328_) {
StructureTemplate structuretemplate = this.getTemplate(p_227325_);
List<StructureTemplate.StructureBlockInfo> list = structuretemplate.filterBlocks(
p_227326_, new StructurePlaceSettings().setRotation(p_227327_), Blocks.STRUCTURE_BLOCK, p_227328_
);
List<StructureTemplate.StructureBlockInfo> list1 = Lists.newArrayList();
for (StructureTemplate.StructureBlockInfo structuretemplate$structureblockinfo : list) {
CompoundTag compoundtag = structuretemplate$structureblockinfo.nbt();
if (compoundtag != null) {
StructureMode structuremode = compoundtag.read("mode", StructureMode.LEGACY_CODEC).orElseThrow();
if (structuremode == StructureMode.DATA) {
list1.add(structuretemplate$structureblockinfo);
}
}
}
return list1;
}
@Override
public List<StructureTemplate.JigsawBlockInfo> getShuffledJigsawBlocks(StructureTemplateManager p_227320_, BlockPos p_227321_, Rotation p_227322_, RandomSource p_227323_) {
List<StructureTemplate.JigsawBlockInfo> list = this.getTemplate(p_227320_).getJigsaws(p_227321_, p_227322_);
Util.shuffle(list, p_227323_);
sortBySelectionPriority(list);
return list;
}
@VisibleForTesting
static void sortBySelectionPriority(List<StructureTemplate.JigsawBlockInfo> p_312992_) {
p_312992_.sort(HIGHEST_SELECTION_PRIORITY_FIRST);
}
@Override
public BoundingBox getBoundingBox(StructureTemplateManager p_227316_, BlockPos p_227317_, Rotation p_227318_) {
StructureTemplate structuretemplate = this.getTemplate(p_227316_);
return structuretemplate.getBoundingBox(new StructurePlaceSettings().setRotation(p_227318_), p_227317_);
}
@Override
public boolean place(
StructureTemplateManager p_227302_,
WorldGenLevel p_227303_,
StructureManager p_227304_,
ChunkGenerator p_227305_,
BlockPos p_227306_,
BlockPos p_227307_,
Rotation p_227308_,
BoundingBox p_227309_,
RandomSource p_227310_,
LiquidSettings p_342078_,
boolean p_227311_
) {
StructureTemplate structuretemplate = this.getTemplate(p_227302_);
StructurePlaceSettings structureplacesettings = this.getSettings(p_227308_, p_227309_, p_342078_, p_227311_);
if (!structuretemplate.placeInWorld(p_227303_, p_227306_, p_227307_, structureplacesettings, p_227310_, 18)) {
return false;
} else {
for (StructureTemplate.StructureBlockInfo structuretemplate$structureblockinfo : StructureTemplate.processBlockInfos(
p_227303_, p_227306_, p_227307_, structureplacesettings, this.getDataMarkers(p_227302_, p_227306_, p_227308_, false)
)) {
this.handleDataMarker(p_227303_, structuretemplate$structureblockinfo, p_227306_, p_227308_, p_227310_, p_227309_);
}
return true;
}
}
protected StructurePlaceSettings getSettings(Rotation p_210421_, BoundingBox p_210422_, LiquidSettings p_345518_, boolean p_210423_) {
StructurePlaceSettings structureplacesettings = new StructurePlaceSettings();
structureplacesettings.setBoundingBox(p_210422_);
structureplacesettings.setRotation(p_210421_);
structureplacesettings.setKnownShape(true);
structureplacesettings.setIgnoreEntities(false);
structureplacesettings.addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK);
structureplacesettings.setFinalizeEntities(true);
structureplacesettings.setLiquidSettings(this.overrideLiquidSettings.orElse(p_345518_));
if (!p_210423_) {
structureplacesettings.addProcessor(JigsawReplacementProcessor.INSTANCE);
}
this.processors.value().list().forEach(structureplacesettings::addProcessor);
this.getProjection().getProcessors().forEach(structureplacesettings::addProcessor);
return structureplacesettings;
}
@Override
public StructurePoolElementType<?> getType() {
return StructurePoolElementType.SINGLE;
}
@Override
public String toString() {
return "Single[" + this.template + "]";
}
@VisibleForTesting
public ResourceLocation getTemplateLocation() {
return this.template.orThrow();
}
}