333 lines
12 KiB
Java
333 lines
12 KiB
Java
|
package net.minecraft.world.level.chunk;
|
||
|
|
||
|
import com.google.common.collect.Lists;
|
||
|
import it.unimi.dsi.fastutil.shorts.ShortList;
|
||
|
import java.util.Collections;
|
||
|
import java.util.EnumSet;
|
||
|
import java.util.List;
|
||
|
import java.util.Map;
|
||
|
import javax.annotation.Nullable;
|
||
|
import net.minecraft.core.BlockPos;
|
||
|
import net.minecraft.core.Holder;
|
||
|
import net.minecraft.core.HolderLookup;
|
||
|
import net.minecraft.core.Registry;
|
||
|
import net.minecraft.core.SectionPos;
|
||
|
import net.minecraft.nbt.CompoundTag;
|
||
|
import net.minecraft.world.entity.Entity;
|
||
|
import net.minecraft.world.level.ChunkPos;
|
||
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||
|
import net.minecraft.world.level.biome.Biome;
|
||
|
import net.minecraft.world.level.block.Block;
|
||
|
import net.minecraft.world.level.block.Blocks;
|
||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||
|
import net.minecraft.world.level.block.state.BlockState;
|
||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||
|
import net.minecraft.world.level.levelgen.BelowZeroRetrogen;
|
||
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||
|
import net.minecraft.world.level.levelgen.blending.BlendingData;
|
||
|
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||
|
import net.minecraft.world.level.levelgen.structure.Structure;
|
||
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||
|
import net.minecraft.world.level.lighting.LightEngine;
|
||
|
import net.minecraft.world.level.material.Fluid;
|
||
|
import net.minecraft.world.level.material.FluidState;
|
||
|
import net.minecraft.world.level.material.Fluids;
|
||
|
import net.minecraft.world.ticks.LevelChunkTicks;
|
||
|
import net.minecraft.world.ticks.ProtoChunkTicks;
|
||
|
import net.minecraft.world.ticks.TickContainerAccess;
|
||
|
|
||
|
public class ProtoChunk extends ChunkAccess {
|
||
|
@Nullable
|
||
|
private volatile LevelLightEngine lightEngine;
|
||
|
private volatile ChunkStatus status = ChunkStatus.EMPTY;
|
||
|
private final List<CompoundTag> entities = Lists.newArrayList();
|
||
|
@Nullable
|
||
|
private CarvingMask carvingMask;
|
||
|
@Nullable
|
||
|
private BelowZeroRetrogen belowZeroRetrogen;
|
||
|
private final ProtoChunkTicks<Block> blockTicks;
|
||
|
private final ProtoChunkTicks<Fluid> fluidTicks;
|
||
|
|
||
|
public ProtoChunk(ChunkPos p_188167_, UpgradeData p_188168_, LevelHeightAccessor p_188169_, Registry<Biome> p_188170_, @Nullable BlendingData p_188171_) {
|
||
|
this(p_188167_, p_188168_, null, new ProtoChunkTicks<>(), new ProtoChunkTicks<>(), p_188169_, p_188170_, p_188171_);
|
||
|
}
|
||
|
|
||
|
public ProtoChunk(
|
||
|
ChunkPos p_188173_,
|
||
|
UpgradeData p_188174_,
|
||
|
@Nullable LevelChunkSection[] p_188175_,
|
||
|
ProtoChunkTicks<Block> p_188176_,
|
||
|
ProtoChunkTicks<Fluid> p_188177_,
|
||
|
LevelHeightAccessor p_188178_,
|
||
|
Registry<Biome> p_188179_,
|
||
|
@Nullable BlendingData p_188180_
|
||
|
) {
|
||
|
super(p_188173_, p_188174_, p_188178_, p_188179_, 0L, p_188175_, p_188180_);
|
||
|
this.blockTicks = p_188176_;
|
||
|
this.fluidTicks = p_188177_;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public TickContainerAccess<Block> getBlockTicks() {
|
||
|
return this.blockTicks;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public TickContainerAccess<Fluid> getFluidTicks() {
|
||
|
return this.fluidTicks;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public ChunkAccess.PackedTicks getTicksForSerialization(long p_361508_) {
|
||
|
return new ChunkAccess.PackedTicks(this.blockTicks.pack(p_361508_), this.fluidTicks.pack(p_361508_));
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public BlockState getBlockState(BlockPos p_63264_) {
|
||
|
int i = p_63264_.getY();
|
||
|
if (this.isOutsideBuildHeight(i)) {
|
||
|
return Blocks.VOID_AIR.defaultBlockState();
|
||
|
} else {
|
||
|
LevelChunkSection levelchunksection = this.getSection(this.getSectionIndex(i));
|
||
|
return levelchunksection.hasOnlyAir()
|
||
|
? Blocks.AIR.defaultBlockState()
|
||
|
: levelchunksection.getBlockState(p_63264_.getX() & 15, i & 15, p_63264_.getZ() & 15);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public FluidState getFluidState(BlockPos p_63239_) {
|
||
|
int i = p_63239_.getY();
|
||
|
if (this.isOutsideBuildHeight(i)) {
|
||
|
return Fluids.EMPTY.defaultFluidState();
|
||
|
} else {
|
||
|
LevelChunkSection levelchunksection = this.getSection(this.getSectionIndex(i));
|
||
|
return levelchunksection.hasOnlyAir()
|
||
|
? Fluids.EMPTY.defaultFluidState()
|
||
|
: levelchunksection.getFluidState(p_63239_.getX() & 15, i & 15, p_63239_.getZ() & 15);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
@Override
|
||
|
public BlockState setBlockState(BlockPos p_63217_, BlockState p_63218_, int p_394843_) {
|
||
|
int i = p_63217_.getX();
|
||
|
int j = p_63217_.getY();
|
||
|
int k = p_63217_.getZ();
|
||
|
if (this.isOutsideBuildHeight(j)) {
|
||
|
return Blocks.VOID_AIR.defaultBlockState();
|
||
|
} else {
|
||
|
int l = this.getSectionIndex(j);
|
||
|
LevelChunkSection levelchunksection = this.getSection(l);
|
||
|
boolean flag = levelchunksection.hasOnlyAir();
|
||
|
if (flag && p_63218_.is(Blocks.AIR)) {
|
||
|
return p_63218_;
|
||
|
} else {
|
||
|
int i1 = SectionPos.sectionRelative(i);
|
||
|
int j1 = SectionPos.sectionRelative(j);
|
||
|
int k1 = SectionPos.sectionRelative(k);
|
||
|
BlockState blockstate = levelchunksection.setBlockState(i1, j1, k1, p_63218_);
|
||
|
if (this.status.isOrAfter(ChunkStatus.INITIALIZE_LIGHT)) {
|
||
|
boolean flag1 = levelchunksection.hasOnlyAir();
|
||
|
if (flag1 != flag) {
|
||
|
this.lightEngine.updateSectionStatus(p_63217_, flag1);
|
||
|
}
|
||
|
|
||
|
if (LightEngine.hasDifferentLightProperties(blockstate, p_63218_)) {
|
||
|
this.skyLightSources.update(this, i1, j, k1);
|
||
|
this.lightEngine.checkBlock(p_63217_);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EnumSet<Heightmap.Types> enumset1 = this.getPersistedStatus().heightmapsAfter();
|
||
|
EnumSet<Heightmap.Types> enumset = null;
|
||
|
|
||
|
for (Heightmap.Types heightmap$types : enumset1) {
|
||
|
Heightmap heightmap = this.heightmaps.get(heightmap$types);
|
||
|
if (heightmap == null) {
|
||
|
if (enumset == null) {
|
||
|
enumset = EnumSet.noneOf(Heightmap.Types.class);
|
||
|
}
|
||
|
|
||
|
enumset.add(heightmap$types);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (enumset != null) {
|
||
|
Heightmap.primeHeightmaps(this, enumset);
|
||
|
}
|
||
|
|
||
|
for (Heightmap.Types heightmap$types1 : enumset1) {
|
||
|
this.heightmaps.get(heightmap$types1).update(i1, j, k1, p_63218_);
|
||
|
}
|
||
|
|
||
|
return blockstate;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void setBlockEntity(BlockEntity p_156488_) {
|
||
|
this.pendingBlockEntities.remove(p_156488_.getBlockPos());
|
||
|
this.blockEntities.put(p_156488_.getBlockPos(), p_156488_);
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
@Override
|
||
|
public BlockEntity getBlockEntity(BlockPos p_63257_) {
|
||
|
return this.blockEntities.get(p_63257_);
|
||
|
}
|
||
|
|
||
|
public Map<BlockPos, BlockEntity> getBlockEntities() {
|
||
|
return this.blockEntities;
|
||
|
}
|
||
|
|
||
|
public void addEntity(CompoundTag p_63243_) {
|
||
|
this.entities.add(p_63243_);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void addEntity(Entity p_63183_) {
|
||
|
if (!p_63183_.isPassenger()) {
|
||
|
CompoundTag compoundtag = new CompoundTag();
|
||
|
p_63183_.save(compoundtag);
|
||
|
this.addEntity(compoundtag);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void setStartForStructure(Structure p_223432_, StructureStart p_223433_) {
|
||
|
BelowZeroRetrogen belowzeroretrogen = this.getBelowZeroRetrogen();
|
||
|
if (belowzeroretrogen != null && p_223433_.isValid()) {
|
||
|
BoundingBox boundingbox = p_223433_.getBoundingBox();
|
||
|
LevelHeightAccessor levelheightaccessor = this.getHeightAccessorForGeneration();
|
||
|
if (boundingbox.minY() < levelheightaccessor.getMinY() || boundingbox.maxY() > levelheightaccessor.getMaxY()) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
super.setStartForStructure(p_223432_, p_223433_);
|
||
|
}
|
||
|
|
||
|
public List<CompoundTag> getEntities() {
|
||
|
return this.entities;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public ChunkStatus getPersistedStatus() {
|
||
|
return this.status;
|
||
|
}
|
||
|
|
||
|
public void setPersistedStatus(ChunkStatus p_334912_) {
|
||
|
this.status = p_334912_;
|
||
|
if (this.belowZeroRetrogen != null && p_334912_.isOrAfter(this.belowZeroRetrogen.targetStatus())) {
|
||
|
this.setBelowZeroRetrogen(null);
|
||
|
}
|
||
|
|
||
|
this.markUnsaved();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Holder<Biome> getNoiseBiome(int p_204450_, int p_204451_, int p_204452_) {
|
||
|
if (this.getHighestGeneratedStatus().isOrAfter(ChunkStatus.BIOMES)) {
|
||
|
return super.getNoiseBiome(p_204450_, p_204451_, p_204452_);
|
||
|
} else {
|
||
|
throw new IllegalStateException("Asking for biomes before we have biomes");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static short packOffsetCoordinates(BlockPos p_63281_) {
|
||
|
int i = p_63281_.getX();
|
||
|
int j = p_63281_.getY();
|
||
|
int k = p_63281_.getZ();
|
||
|
int l = i & 15;
|
||
|
int i1 = j & 15;
|
||
|
int j1 = k & 15;
|
||
|
return (short)(l | i1 << 4 | j1 << 8);
|
||
|
}
|
||
|
|
||
|
public static BlockPos unpackOffsetCoordinates(short p_63228_, int p_63229_, ChunkPos p_63230_) {
|
||
|
int i = SectionPos.sectionToBlockCoord(p_63230_.x, p_63228_ & 15);
|
||
|
int j = SectionPos.sectionToBlockCoord(p_63229_, p_63228_ >>> 4 & 15);
|
||
|
int k = SectionPos.sectionToBlockCoord(p_63230_.z, p_63228_ >>> 8 & 15);
|
||
|
return new BlockPos(i, j, k);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void markPosForPostprocessing(BlockPos p_63266_) {
|
||
|
if (!this.isOutsideBuildHeight(p_63266_)) {
|
||
|
ChunkAccess.getOrCreateOffsetList(this.postProcessing, this.getSectionIndex(p_63266_.getY())).add(packOffsetCoordinates(p_63266_));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void addPackedPostProcess(ShortList p_362697_, int p_63226_) {
|
||
|
ChunkAccess.getOrCreateOffsetList(this.postProcessing, p_63226_).addAll(p_362697_);
|
||
|
}
|
||
|
|
||
|
public Map<BlockPos, CompoundTag> getBlockEntityNbts() {
|
||
|
return Collections.unmodifiableMap(this.pendingBlockEntities);
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
@Override
|
||
|
public CompoundTag getBlockEntityNbtForSaving(BlockPos p_63275_, HolderLookup.Provider p_335105_) {
|
||
|
BlockEntity blockentity = this.getBlockEntity(p_63275_);
|
||
|
return blockentity != null ? blockentity.saveWithFullMetadata(p_335105_) : this.pendingBlockEntities.get(p_63275_);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void removeBlockEntity(BlockPos p_63262_) {
|
||
|
this.blockEntities.remove(p_63262_);
|
||
|
this.pendingBlockEntities.remove(p_63262_);
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
public CarvingMask getCarvingMask() {
|
||
|
return this.carvingMask;
|
||
|
}
|
||
|
|
||
|
public CarvingMask getOrCreateCarvingMask() {
|
||
|
if (this.carvingMask == null) {
|
||
|
this.carvingMask = new CarvingMask(this.getHeight(), this.getMinY());
|
||
|
}
|
||
|
|
||
|
return this.carvingMask;
|
||
|
}
|
||
|
|
||
|
public void setCarvingMask(CarvingMask p_188188_) {
|
||
|
this.carvingMask = p_188188_;
|
||
|
}
|
||
|
|
||
|
public void setLightEngine(LevelLightEngine p_63210_) {
|
||
|
this.lightEngine = p_63210_;
|
||
|
}
|
||
|
|
||
|
public void setBelowZeroRetrogen(@Nullable BelowZeroRetrogen p_188184_) {
|
||
|
this.belowZeroRetrogen = p_188184_;
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
@Override
|
||
|
public BelowZeroRetrogen getBelowZeroRetrogen() {
|
||
|
return this.belowZeroRetrogen;
|
||
|
}
|
||
|
|
||
|
private static <T> LevelChunkTicks<T> unpackTicks(ProtoChunkTicks<T> p_188190_) {
|
||
|
return new LevelChunkTicks<>(p_188190_.scheduledTicks());
|
||
|
}
|
||
|
|
||
|
public LevelChunkTicks<Block> unpackBlockTicks() {
|
||
|
return unpackTicks(this.blockTicks);
|
||
|
}
|
||
|
|
||
|
public LevelChunkTicks<Fluid> unpackFluidTicks() {
|
||
|
return unpackTicks(this.fluidTicks);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public LevelHeightAccessor getHeightAccessorForGeneration() {
|
||
|
return (LevelHeightAccessor)(this.isUpgrading() ? BelowZeroRetrogen.UPGRADE_HEIGHT_ACCESSOR : this);
|
||
|
}
|
||
|
}
|