333 lines
13 KiB
Java
333 lines
13 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.collect.Lists
|
|
* com.mojang.logging.LogUtils
|
|
* it.unimi.dsi.fastutil.shorts.ShortList
|
|
* org.jspecify.annotations.Nullable
|
|
* org.slf4j.Logger
|
|
*/
|
|
package net.minecraft.world.level.chunk;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.mojang.logging.LogUtils;
|
|
import it.unimi.dsi.fastutil.shorts.ShortList;
|
|
import java.util.Collections;
|
|
import java.util.EnumSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Holder;
|
|
import net.minecraft.core.HolderLookup;
|
|
import net.minecraft.core.SectionPos;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.util.ProblemReporter;
|
|
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.CarvingMask;
|
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
|
import net.minecraft.world.level.chunk.PalettedContainerFactory;
|
|
import net.minecraft.world.level.chunk.UpgradeData;
|
|
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.level.storage.TagValueOutput;
|
|
import net.minecraft.world.ticks.LevelChunkTicks;
|
|
import net.minecraft.world.ticks.ProtoChunkTicks;
|
|
import net.minecraft.world.ticks.TickContainerAccess;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class ProtoChunk
|
|
extends ChunkAccess {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private volatile @Nullable LevelLightEngine lightEngine;
|
|
private volatile ChunkStatus status = ChunkStatus.EMPTY;
|
|
private final List<CompoundTag> entities = Lists.newArrayList();
|
|
private @Nullable CarvingMask carvingMask;
|
|
private @Nullable BelowZeroRetrogen belowZeroRetrogen;
|
|
private final ProtoChunkTicks<Block> blockTicks;
|
|
private final ProtoChunkTicks<Fluid> fluidTicks;
|
|
|
|
public ProtoChunk(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, PalettedContainerFactory containerFactory, @Nullable BlendingData blendingData) {
|
|
this(chunkPos, upgradeData, null, new ProtoChunkTicks<Block>(), new ProtoChunkTicks<Fluid>(), levelHeightAccessor, containerFactory, blendingData);
|
|
}
|
|
|
|
public ProtoChunk(ChunkPos chunkPos, UpgradeData upgradeData, LevelChunkSection @Nullable [] sections, ProtoChunkTicks<Block> blockTicks, ProtoChunkTicks<Fluid> fluidTicks, LevelHeightAccessor levelHeightAccessor, PalettedContainerFactory containerFactory, @Nullable BlendingData blendingData) {
|
|
super(chunkPos, upgradeData, levelHeightAccessor, containerFactory, 0L, sections, blendingData);
|
|
this.blockTicks = blockTicks;
|
|
this.fluidTicks = fluidTicks;
|
|
}
|
|
|
|
@Override
|
|
public TickContainerAccess<Block> getBlockTicks() {
|
|
return this.blockTicks;
|
|
}
|
|
|
|
@Override
|
|
public TickContainerAccess<Fluid> getFluidTicks() {
|
|
return this.fluidTicks;
|
|
}
|
|
|
|
@Override
|
|
public ChunkAccess.PackedTicks getTicksForSerialization(long currentTick) {
|
|
return new ChunkAccess.PackedTicks(this.blockTicks.pack(currentTick), this.fluidTicks.pack(currentTick));
|
|
}
|
|
|
|
@Override
|
|
public BlockState getBlockState(BlockPos pos) {
|
|
int y = pos.getY();
|
|
if (this.isOutsideBuildHeight(y)) {
|
|
return Blocks.VOID_AIR.defaultBlockState();
|
|
}
|
|
LevelChunkSection section = this.getSection(this.getSectionIndex(y));
|
|
if (section.hasOnlyAir()) {
|
|
return Blocks.AIR.defaultBlockState();
|
|
}
|
|
return section.getBlockState(pos.getX() & 0xF, y & 0xF, pos.getZ() & 0xF);
|
|
}
|
|
|
|
@Override
|
|
public FluidState getFluidState(BlockPos pos) {
|
|
int y = pos.getY();
|
|
if (this.isOutsideBuildHeight(y)) {
|
|
return Fluids.EMPTY.defaultFluidState();
|
|
}
|
|
LevelChunkSection section = this.getSection(this.getSectionIndex(y));
|
|
if (section.hasOnlyAir()) {
|
|
return Fluids.EMPTY.defaultFluidState();
|
|
}
|
|
return section.getFluidState(pos.getX() & 0xF, y & 0xF, pos.getZ() & 0xF);
|
|
}
|
|
|
|
@Override
|
|
public @Nullable BlockState setBlockState(BlockPos pos, BlockState state, @Block.UpdateFlags int flags) {
|
|
int x = pos.getX();
|
|
int y = pos.getY();
|
|
int z = pos.getZ();
|
|
if (this.isOutsideBuildHeight(y)) {
|
|
return Blocks.VOID_AIR.defaultBlockState();
|
|
}
|
|
int sectionIndex = this.getSectionIndex(y);
|
|
LevelChunkSection section = this.getSection(sectionIndex);
|
|
boolean wasEmpty = section.hasOnlyAir();
|
|
if (wasEmpty && state.is(Blocks.AIR)) {
|
|
return state;
|
|
}
|
|
int localX = SectionPos.sectionRelative(x);
|
|
int localY = SectionPos.sectionRelative(y);
|
|
int localZ = SectionPos.sectionRelative(z);
|
|
BlockState oldState = section.setBlockState(localX, localY, localZ, state);
|
|
if (this.status.isOrAfter(ChunkStatus.INITIALIZE_LIGHT)) {
|
|
boolean isEmpty = section.hasOnlyAir();
|
|
if (isEmpty != wasEmpty) {
|
|
this.lightEngine.updateSectionStatus(pos, isEmpty);
|
|
}
|
|
if (LightEngine.hasDifferentLightProperties(oldState, state)) {
|
|
this.skyLightSources.update(this, localX, y, localZ);
|
|
this.lightEngine.checkBlock(pos);
|
|
}
|
|
}
|
|
EnumSet<Heightmap.Types> heightmapsAfter = this.getPersistedStatus().heightmapsAfter();
|
|
EnumSet<Heightmap.Types> toPrime = null;
|
|
for (Heightmap.Types type : heightmapsAfter) {
|
|
Heightmap heightmap = (Heightmap)this.heightmaps.get(type);
|
|
if (heightmap != null) continue;
|
|
if (toPrime == null) {
|
|
toPrime = EnumSet.noneOf(Heightmap.Types.class);
|
|
}
|
|
toPrime.add(type);
|
|
}
|
|
if (toPrime != null) {
|
|
Heightmap.primeHeightmaps(this, toPrime);
|
|
}
|
|
for (Heightmap.Types type : heightmapsAfter) {
|
|
((Heightmap)this.heightmaps.get(type)).update(localX, y, localZ, state);
|
|
}
|
|
return oldState;
|
|
}
|
|
|
|
@Override
|
|
public void setBlockEntity(BlockEntity blockEntity) {
|
|
this.pendingBlockEntities.remove(blockEntity.getBlockPos());
|
|
this.blockEntities.put(blockEntity.getBlockPos(), blockEntity);
|
|
}
|
|
|
|
@Override
|
|
public @Nullable BlockEntity getBlockEntity(BlockPos pos) {
|
|
return (BlockEntity)this.blockEntities.get(pos);
|
|
}
|
|
|
|
public Map<BlockPos, BlockEntity> getBlockEntities() {
|
|
return this.blockEntities;
|
|
}
|
|
|
|
public void addEntity(CompoundTag tag) {
|
|
this.entities.add(tag);
|
|
}
|
|
|
|
@Override
|
|
public void addEntity(Entity entity) {
|
|
if (entity.isPassenger()) {
|
|
return;
|
|
}
|
|
try (ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(entity.problemPath(), LOGGER);){
|
|
TagValueOutput output = TagValueOutput.createWithContext(reporter, entity.registryAccess());
|
|
entity.save(output);
|
|
this.addEntity(output.buildResult());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setStartForStructure(Structure structure, StructureStart structureStart) {
|
|
BelowZeroRetrogen belowZeroRetrogen = this.getBelowZeroRetrogen();
|
|
if (belowZeroRetrogen != null && structureStart.isValid()) {
|
|
BoundingBox boundingBox = structureStart.getBoundingBox();
|
|
LevelHeightAccessor heightAccessor = this.getHeightAccessorForGeneration();
|
|
if (boundingBox.minY() < heightAccessor.getMinY() || boundingBox.maxY() > heightAccessor.getMaxY()) {
|
|
return;
|
|
}
|
|
}
|
|
super.setStartForStructure(structure, structureStart);
|
|
}
|
|
|
|
public List<CompoundTag> getEntities() {
|
|
return this.entities;
|
|
}
|
|
|
|
@Override
|
|
public ChunkStatus getPersistedStatus() {
|
|
return this.status;
|
|
}
|
|
|
|
public void setPersistedStatus(ChunkStatus status) {
|
|
this.status = status;
|
|
if (this.belowZeroRetrogen != null && status.isOrAfter(this.belowZeroRetrogen.targetStatus())) {
|
|
this.setBelowZeroRetrogen(null);
|
|
}
|
|
this.markUnsaved();
|
|
}
|
|
|
|
@Override
|
|
public Holder<Biome> getNoiseBiome(int quartX, int quartY, int quartZ) {
|
|
if (this.getHighestGeneratedStatus().isOrAfter(ChunkStatus.BIOMES)) {
|
|
return super.getNoiseBiome(quartX, quartY, quartZ);
|
|
}
|
|
throw new IllegalStateException("Asking for biomes before we have biomes");
|
|
}
|
|
|
|
public static short packOffsetCoordinates(BlockPos blockPos) {
|
|
int x = blockPos.getX();
|
|
int y = blockPos.getY();
|
|
int z = blockPos.getZ();
|
|
int dx = x & 0xF;
|
|
int dy = y & 0xF;
|
|
int dz = z & 0xF;
|
|
return (short)(dx | dy << 4 | dz << 8);
|
|
}
|
|
|
|
public static BlockPos unpackOffsetCoordinates(short packedCoord, int sectionY, ChunkPos chunkPos) {
|
|
int posX = SectionPos.sectionToBlockCoord(chunkPos.x, packedCoord & 0xF);
|
|
int posY = SectionPos.sectionToBlockCoord(sectionY, packedCoord >>> 4 & 0xF);
|
|
int posZ = SectionPos.sectionToBlockCoord(chunkPos.z, packedCoord >>> 8 & 0xF);
|
|
return new BlockPos(posX, posY, posZ);
|
|
}
|
|
|
|
@Override
|
|
public void markPosForPostprocessing(BlockPos blockPos) {
|
|
if (!this.isOutsideBuildHeight(blockPos)) {
|
|
ChunkAccess.getOrCreateOffsetList(this.postProcessing, this.getSectionIndex(blockPos.getY())).add(ProtoChunk.packOffsetCoordinates(blockPos));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void addPackedPostProcess(ShortList packedOffsets, int sectionIndex) {
|
|
ChunkAccess.getOrCreateOffsetList(this.postProcessing, sectionIndex).addAll(packedOffsets);
|
|
}
|
|
|
|
public Map<BlockPos, CompoundTag> getBlockEntityNbts() {
|
|
return Collections.unmodifiableMap(this.pendingBlockEntities);
|
|
}
|
|
|
|
@Override
|
|
public @Nullable CompoundTag getBlockEntityNbtForSaving(BlockPos blockPos, HolderLookup.Provider registryAccess) {
|
|
BlockEntity blockEntity = this.getBlockEntity(blockPos);
|
|
if (blockEntity != null) {
|
|
return blockEntity.saveWithFullMetadata(registryAccess);
|
|
}
|
|
return (CompoundTag)this.pendingBlockEntities.get(blockPos);
|
|
}
|
|
|
|
@Override
|
|
public void removeBlockEntity(BlockPos pos) {
|
|
this.blockEntities.remove(pos);
|
|
this.pendingBlockEntities.remove(pos);
|
|
}
|
|
|
|
public @Nullable 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 data) {
|
|
this.carvingMask = data;
|
|
}
|
|
|
|
public void setLightEngine(LevelLightEngine lightEngine) {
|
|
this.lightEngine = lightEngine;
|
|
}
|
|
|
|
public void setBelowZeroRetrogen(@Nullable BelowZeroRetrogen belowZeroRetrogen) {
|
|
this.belowZeroRetrogen = belowZeroRetrogen;
|
|
}
|
|
|
|
@Override
|
|
public @Nullable BelowZeroRetrogen getBelowZeroRetrogen() {
|
|
return this.belowZeroRetrogen;
|
|
}
|
|
|
|
private static <T> LevelChunkTicks<T> unpackTicks(ProtoChunkTicks<T> ticks) {
|
|
return new LevelChunkTicks<T>(ticks.scheduledTicks());
|
|
}
|
|
|
|
public LevelChunkTicks<Block> unpackBlockTicks() {
|
|
return ProtoChunk.unpackTicks(this.blockTicks);
|
|
}
|
|
|
|
public LevelChunkTicks<Fluid> unpackFluidTicks() {
|
|
return ProtoChunk.unpackTicks(this.fluidTicks);
|
|
}
|
|
|
|
@Override
|
|
public LevelHeightAccessor getHeightAccessorForGeneration() {
|
|
if (this.isUpgrading()) {
|
|
return BelowZeroRetrogen.UPGRADE_HEIGHT_ACCESSOR;
|
|
}
|
|
return this;
|
|
}
|
|
}
|
|
|