178 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
	
		
			6.9 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.LongIterator;
 | |
| 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 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;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| public class StructureManager {
 | |
| 	private final LevelAccessor level;
 | |
| 	private final WorldOptions worldOptions;
 | |
| 	private final StructureCheck structureCheck;
 | |
| 
 | |
| 	public StructureManager(LevelAccessor level, WorldOptions worldOptions, StructureCheck structureCheck) {
 | |
| 		this.level = level;
 | |
| 		this.worldOptions = worldOptions;
 | |
| 		this.structureCheck = structureCheck;
 | |
| 	}
 | |
| 
 | |
| 	public StructureManager forWorldGenRegion(WorldGenRegion region) {
 | |
| 		if (region.getLevel() != this.level) {
 | |
| 			throw new IllegalStateException("Using invalid structure manager (source level: " + region.getLevel() + ", region: " + region);
 | |
| 		} else {
 | |
| 			return new StructureManager(region, this.worldOptions, this.structureCheck);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public List<StructureStart> startsForStructure(ChunkPos chunkPos, Predicate<Structure> structurePredicate) {
 | |
| 		Map<Structure, LongSet> map = this.level.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences();
 | |
| 		Builder<StructureStart> builder = ImmutableList.builder();
 | |
| 
 | |
| 		for (Entry<Structure, LongSet> entry : map.entrySet()) {
 | |
| 			Structure structure = (Structure)entry.getKey();
 | |
| 			if (structurePredicate.test(structure)) {
 | |
| 				this.fillStartsForStructure(structure, (LongSet)entry.getValue(), builder::add);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return builder.build();
 | |
| 	}
 | |
| 
 | |
| 	public List<StructureStart> startsForStructure(SectionPos sectionPos, Structure structure) {
 | |
| 		LongSet longSet = this.level.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForStructure(structure);
 | |
| 		Builder<StructureStart> builder = ImmutableList.builder();
 | |
| 		this.fillStartsForStructure(structure, longSet, builder::add);
 | |
| 		return builder.build();
 | |
| 	}
 | |
| 
 | |
| 	public void fillStartsForStructure(Structure structure, LongSet structureRefs, Consumer<StructureStart> startConsumer) {
 | |
| 		LongIterator var4 = structureRefs.iterator();
 | |
| 
 | |
| 		while (var4.hasNext()) {
 | |
| 			long l = (Long)var4.next();
 | |
| 			SectionPos sectionPos = SectionPos.of(new ChunkPos(l), this.level.getMinSectionY());
 | |
| 			StructureStart structureStart = this.getStartForStructure(
 | |
| 				sectionPos, structure, this.level.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_STARTS)
 | |
| 			);
 | |
| 			if (structureStart != null && structureStart.isValid()) {
 | |
| 				startConsumer.accept(structureStart);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	public StructureStart getStartForStructure(SectionPos sectionPos, Structure structure, StructureAccess structureAccess) {
 | |
| 		return structureAccess.getStartForStructure(structure);
 | |
| 	}
 | |
| 
 | |
| 	public void setStartForStructure(SectionPos sectionPos, Structure structure, StructureStart structureStart, StructureAccess structureAccess) {
 | |
| 		structureAccess.setStartForStructure(structure, structureStart);
 | |
| 	}
 | |
| 
 | |
| 	public void addReferenceForStructure(SectionPos sectionPos, Structure structure, long reference, StructureAccess structureAccess) {
 | |
| 		structureAccess.addReferenceForStructure(structure, reference);
 | |
| 	}
 | |
| 
 | |
| 	public boolean shouldGenerateStructures() {
 | |
| 		return this.worldOptions.generateStructures();
 | |
| 	}
 | |
| 
 | |
| 	public StructureStart getStructureAt(BlockPos pos, Structure structure) {
 | |
| 		for (StructureStart structureStart : this.startsForStructure(SectionPos.of(pos), structure)) {
 | |
| 			if (structureStart.getBoundingBox().isInside(pos)) {
 | |
| 				return structureStart;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return StructureStart.INVALID_START;
 | |
| 	}
 | |
| 
 | |
| 	public StructureStart getStructureWithPieceAt(BlockPos pos, TagKey<Structure> structureTag) {
 | |
| 		return this.getStructureWithPieceAt(pos, holder -> holder.is(structureTag));
 | |
| 	}
 | |
| 
 | |
| 	public StructureStart getStructureWithPieceAt(BlockPos pos, HolderSet<Structure> structures) {
 | |
| 		return this.getStructureWithPieceAt(pos, structures::contains);
 | |
| 	}
 | |
| 
 | |
| 	public StructureStart getStructureWithPieceAt(BlockPos pos, Predicate<Holder<Structure>> predicate) {
 | |
| 		Registry<Structure> registry = this.registryAccess().lookupOrThrow(Registries.STRUCTURE);
 | |
| 
 | |
| 		for (StructureStart structureStart : this.startsForStructure(
 | |
| 			new ChunkPos(pos), structure -> (Boolean)registry.get(registry.getId(structure)).map(predicate::test).orElse(false)
 | |
| 		)) {
 | |
| 			if (this.structureHasPieceAt(pos, structureStart)) {
 | |
| 				return structureStart;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return StructureStart.INVALID_START;
 | |
| 	}
 | |
| 
 | |
| 	public StructureStart getStructureWithPieceAt(BlockPos pos, Structure structure) {
 | |
| 		for (StructureStart structureStart : this.startsForStructure(SectionPos.of(pos), structure)) {
 | |
| 			if (this.structureHasPieceAt(pos, structureStart)) {
 | |
| 				return structureStart;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return StructureStart.INVALID_START;
 | |
| 	}
 | |
| 
 | |
| 	public boolean structureHasPieceAt(BlockPos pos, StructureStart structureStart) {
 | |
| 		for (StructurePiece structurePiece : structureStart.getPieces()) {
 | |
| 			if (structurePiece.getBoundingBox().isInside(pos)) {
 | |
| 				return true;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	public boolean hasAnyStructureAt(BlockPos pos) {
 | |
| 		SectionPos sectionPos = SectionPos.of(pos);
 | |
| 		return this.level.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES).hasAnyStructureReferences();
 | |
| 	}
 | |
| 
 | |
| 	public Map<Structure, LongSet> getAllStructuresAt(BlockPos pos) {
 | |
| 		SectionPos sectionPos = SectionPos.of(pos);
 | |
| 		return this.level.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES).getAllReferences();
 | |
| 	}
 | |
| 
 | |
| 	public StructureCheckResult checkStructurePresence(ChunkPos chunkPos, Structure structure, StructurePlacement placement, boolean skipKnownStructures) {
 | |
| 		return this.structureCheck.checkStart(chunkPos, structure, placement, skipKnownStructures);
 | |
| 	}
 | |
| 
 | |
| 	public void addReference(StructureStart structureStart) {
 | |
| 		structureStart.addReference();
 | |
| 		this.structureCheck.incrementReference(structureStart.getChunkPos(), structureStart.getStructure());
 | |
| 	}
 | |
| 
 | |
| 	public RegistryAccess registryAccess() {
 | |
| 		return this.level.registryAccess();
 | |
| 	}
 | |
| }
 |