174 lines
7.4 KiB
Java
174 lines
7.4 KiB
Java
|
package net.minecraft.world.level;
|
||
|
|
||
|
import com.google.common.collect.ImmutableList;
|
||
|
import com.google.common.collect.ImmutableList.Builder;
|
||
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||
|
import java.util.List;
|
||
|
import java.util.Map;
|
||
|
import java.util.Map.Entry;
|
||
|
import java.util.function.Consumer;
|
||
|
import java.util.function.Predicate;
|
||
|
import javax.annotation.Nullable;
|
||
|
import net.minecraft.core.BlockPos;
|
||
|
import net.minecraft.core.Holder;
|
||
|
import net.minecraft.core.HolderSet;
|
||
|
import net.minecraft.core.Registry;
|
||
|
import net.minecraft.core.RegistryAccess;
|
||
|
import net.minecraft.core.SectionPos;
|
||
|
import net.minecraft.core.registries.Registries;
|
||
|
import net.minecraft.server.level.WorldGenRegion;
|
||
|
import net.minecraft.tags.TagKey;
|
||
|
import net.minecraft.world.level.chunk.StructureAccess;
|
||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||
|
import net.minecraft.world.level.levelgen.WorldOptions;
|
||
|
import net.minecraft.world.level.levelgen.structure.Structure;
|
||
|
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
||
|
import net.minecraft.world.level.levelgen.structure.StructureCheckResult;
|
||
|
import net.minecraft.world.level.levelgen.structure.StructurePiece;
|
||
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||
|
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
|
||
|
|
||
|
public class StructureManager {
|
||
|
private final LevelAccessor level;
|
||
|
private final WorldOptions worldOptions;
|
||
|
private final StructureCheck structureCheck;
|
||
|
|
||
|
public StructureManager(LevelAccessor p_249675_, WorldOptions p_248820_, StructureCheck p_249103_) {
|
||
|
this.level = p_249675_;
|
||
|
this.worldOptions = p_248820_;
|
||
|
this.structureCheck = p_249103_;
|
||
|
}
|
||
|
|
||
|
public StructureManager forWorldGenRegion(WorldGenRegion p_220469_) {
|
||
|
if (p_220469_.getLevel() != this.level) {
|
||
|
throw new IllegalStateException("Using invalid structure manager (source level: " + p_220469_.getLevel() + ", region: " + p_220469_);
|
||
|
} else {
|
||
|
return new StructureManager(p_220469_, this.worldOptions, this.structureCheck);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public List<StructureStart> startsForStructure(ChunkPos p_220478_, Predicate<Structure> p_220479_) {
|
||
|
Map<Structure, LongSet> map = this.level.getChunk(p_220478_.x, p_220478_.z, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences();
|
||
|
Builder<StructureStart> builder = ImmutableList.builder();
|
||
|
|
||
|
for (Entry<Structure, LongSet> entry : map.entrySet()) {
|
||
|
Structure structure = entry.getKey();
|
||
|
if (p_220479_.test(structure)) {
|
||
|
this.fillStartsForStructure(structure, entry.getValue(), builder::add);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return builder.build();
|
||
|
}
|
||
|
|
||
|
public List<StructureStart> startsForStructure(SectionPos p_220505_, Structure p_220506_) {
|
||
|
LongSet longset = this.level.getChunk(p_220505_.x(), p_220505_.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForStructure(p_220506_);
|
||
|
Builder<StructureStart> builder = ImmutableList.builder();
|
||
|
this.fillStartsForStructure(p_220506_, longset, builder::add);
|
||
|
return builder.build();
|
||
|
}
|
||
|
|
||
|
public void fillStartsForStructure(Structure p_220481_, LongSet p_220482_, Consumer<StructureStart> p_220483_) {
|
||
|
for (long i : p_220482_) {
|
||
|
SectionPos sectionpos = SectionPos.of(new ChunkPos(i), this.level.getMinSectionY());
|
||
|
StructureStart structurestart = this.getStartForStructure(
|
||
|
sectionpos, p_220481_, this.level.getChunk(sectionpos.x(), sectionpos.z(), ChunkStatus.STRUCTURE_STARTS)
|
||
|
);
|
||
|
if (structurestart != null && structurestart.isValid()) {
|
||
|
p_220483_.accept(structurestart);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
public StructureStart getStartForStructure(SectionPos p_220513_, Structure p_220514_, StructureAccess p_220515_) {
|
||
|
return p_220515_.getStartForStructure(p_220514_);
|
||
|
}
|
||
|
|
||
|
public void setStartForStructure(SectionPos p_220517_, Structure p_220518_, StructureStart p_220519_, StructureAccess p_220520_) {
|
||
|
p_220520_.setStartForStructure(p_220518_, p_220519_);
|
||
|
}
|
||
|
|
||
|
public void addReferenceForStructure(SectionPos p_220508_, Structure p_220509_, long p_220510_, StructureAccess p_220511_) {
|
||
|
p_220511_.addReferenceForStructure(p_220509_, p_220510_);
|
||
|
}
|
||
|
|
||
|
public boolean shouldGenerateStructures() {
|
||
|
return this.worldOptions.generateStructures();
|
||
|
}
|
||
|
|
||
|
public StructureStart getStructureAt(BlockPos p_220495_, Structure p_220496_) {
|
||
|
for (StructureStart structurestart : this.startsForStructure(SectionPos.of(p_220495_), p_220496_)) {
|
||
|
if (structurestart.getBoundingBox().isInside(p_220495_)) {
|
||
|
return structurestart;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return StructureStart.INVALID_START;
|
||
|
}
|
||
|
|
||
|
public StructureStart getStructureWithPieceAt(BlockPos p_220492_, TagKey<Structure> p_220493_) {
|
||
|
return this.getStructureWithPieceAt(p_220492_, p_327244_ -> p_327244_.is(p_220493_));
|
||
|
}
|
||
|
|
||
|
public StructureStart getStructureWithPieceAt(BlockPos p_220489_, HolderSet<Structure> p_335973_) {
|
||
|
return this.getStructureWithPieceAt(p_220489_, p_335973_::contains);
|
||
|
}
|
||
|
|
||
|
public StructureStart getStructureWithPieceAt(BlockPos p_328568_, Predicate<Holder<Structure>> p_330204_) {
|
||
|
Registry<Structure> registry = this.registryAccess().lookupOrThrow(Registries.STRUCTURE);
|
||
|
|
||
|
for (StructureStart structurestart : this.startsForStructure(
|
||
|
new ChunkPos(p_328568_), p_359959_ -> registry.get(registry.getId(p_359959_)).map(p_330204_::test).orElse(false)
|
||
|
)) {
|
||
|
if (this.structureHasPieceAt(p_328568_, structurestart)) {
|
||
|
return structurestart;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return StructureStart.INVALID_START;
|
||
|
}
|
||
|
|
||
|
public StructureStart getStructureWithPieceAt(BlockPos p_220525_, Structure p_220526_) {
|
||
|
for (StructureStart structurestart : this.startsForStructure(SectionPos.of(p_220525_), p_220526_)) {
|
||
|
if (this.structureHasPieceAt(p_220525_, structurestart)) {
|
||
|
return structurestart;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return StructureStart.INVALID_START;
|
||
|
}
|
||
|
|
||
|
public boolean structureHasPieceAt(BlockPos p_220498_, StructureStart p_220499_) {
|
||
|
for (StructurePiece structurepiece : p_220499_.getPieces()) {
|
||
|
if (structurepiece.getBoundingBox().isInside(p_220498_)) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public boolean hasAnyStructureAt(BlockPos p_220487_) {
|
||
|
SectionPos sectionpos = SectionPos.of(p_220487_);
|
||
|
return this.level.getChunk(sectionpos.x(), sectionpos.z(), ChunkStatus.STRUCTURE_REFERENCES).hasAnyStructureReferences();
|
||
|
}
|
||
|
|
||
|
public Map<Structure, LongSet> getAllStructuresAt(BlockPos p_220523_) {
|
||
|
SectionPos sectionpos = SectionPos.of(p_220523_);
|
||
|
return this.level.getChunk(sectionpos.x(), sectionpos.z(), ChunkStatus.STRUCTURE_REFERENCES).getAllReferences();
|
||
|
}
|
||
|
|
||
|
public StructureCheckResult checkStructurePresence(ChunkPos p_220474_, Structure p_220475_, StructurePlacement p_332450_, boolean p_220476_) {
|
||
|
return this.structureCheck.checkStart(p_220474_, p_220475_, p_332450_, p_220476_);
|
||
|
}
|
||
|
|
||
|
public void addReference(StructureStart p_220485_) {
|
||
|
p_220485_.addReference();
|
||
|
this.structureCheck.incrementReference(p_220485_.getChunkPos(), p_220485_.getStructure());
|
||
|
}
|
||
|
|
||
|
public RegistryAccess registryAccess() {
|
||
|
return this.level.registryAccess();
|
||
|
}
|
||
|
}
|