minecraft-source/src/net/minecraft/world/level/chunk/LevelChunk.java

786 lines
30 KiB
Java

package net.minecraft.world.level.chunk;
import org.apache.logging.log4j.LogManager;
import net.minecraft.core.Registry;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkTickList;
import it.unimi.dsi.fastutil.shorts.ShortListIterator;
import net.minecraft.world.level.LevelAccessor;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import java.util.stream.StreamSupport;
import java.util.stream.Stream;
import java.util.Collections;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.boss.EnderDragonPart;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import java.util.function.Predicate;
import java.util.List;
import net.minecraft.world.phys.AABB;
import net.minecraft.util.Mth;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.ReportedException;
import net.minecraft.CrashReportCategory;
import net.minecraft.CrashReport;
import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.LevelType;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Collection;
import com.google.common.collect.Sets;
import java.util.Set;
import java.util.Iterator;
import net.minecraft.world.entity.EntityType;
import com.google.common.collect.Maps;
import net.minecraft.world.level.EmptyTickList;
import net.minecraft.world.level.ChunkPos;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.minecraft.server.level.ChunkHolder;
import java.util.function.Supplier;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.TickList;
import it.unimi.dsi.fastutil.shorts.ShortList;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.entity.Entity;
import net.minecraft.util.ClassInstanceMultiMap;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.Level;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.BlockPos;
import java.util.Map;
import org.apache.logging.log4j.Logger;
public class LevelChunk implements ChunkAccess {
private static final Logger LOGGER;
public static final LevelChunkSection EMPTY_SECTION;
private final LevelChunkSection[] sections;
private ChunkBiomeContainer biomes;
private final Map<BlockPos, CompoundTag> pendingBlockEntities;
private boolean loaded;
private final Level level;
private final Map<Heightmap.Types, Heightmap> heightmaps;
private final UpgradeData upgradeData;
private final Map<BlockPos, BlockEntity> blockEntities;
private final ClassInstanceMultiMap<Entity>[] entitySections;
private final Map<String, StructureStart> structureStarts;
private final Map<String, LongSet> structuresRefences;
private final ShortList[] postProcessing;
private TickList<Block> blockTicks;
private TickList<Fluid> liquidTicks;
private boolean lastSaveHadEntities;
private long lastSaveTime;
private volatile boolean unsaved;
private long inhabitedTime;
@Nullable
private Supplier<ChunkHolder.FullChunkStatus> fullStatus;
@Nullable
private Consumer<LevelChunk> postLoad;
private final ChunkPos chunkPos;
private volatile boolean isLightCorrect;
public LevelChunk(final Level bjt, final ChunkPos bje, final ChunkBiomeContainer bzw) {
this(bjt, bje, bzw, UpgradeData.EMPTY, EmptyTickList.empty(), EmptyTickList.empty(), 0L, null, null);
}
public LevelChunk(final Level bjt, final ChunkPos bje, final ChunkBiomeContainer bzw, final UpgradeData cas, final TickList<Block> bki5, final TickList<Fluid> bki6, final long long7, @Nullable final LevelChunkSection[] arr, @Nullable final Consumer<LevelChunk> consumer) {
this.sections = new LevelChunkSection[16];
this.pendingBlockEntities = Maps.newHashMap();
this.heightmaps = Maps.newEnumMap(Heightmap.Types.class);
this.blockEntities = Maps.newHashMap();
this.structureStarts = Maps.newHashMap();
this.structuresRefences = Maps.newHashMap();
this.postProcessing = new ShortList[16];
this.entitySections = new ClassInstanceMultiMap[16];
this.level = bjt;
this.chunkPos = bje;
this.upgradeData = cas;
for (final Heightmap.Types a15 : Heightmap.Types.values()) {
if (ChunkStatus.FULL.heightmapsAfter().contains(a15)) {
this.heightmaps.put(a15, new Heightmap(this, a15));
}
}
for (int integer12 = 0; integer12 < this.entitySections.length; ++integer12) {
this.entitySections[integer12] = new ClassInstanceMultiMap<Entity>(Entity.class);
}
this.biomes = bzw;
this.blockTicks = bki5;
this.liquidTicks = bki6;
this.inhabitedTime = long7;
this.postLoad = consumer;
if (arr != null) {
if (this.sections.length == arr.length) {
System.arraycopy(arr, 0, this.sections, 0, this.sections.length);
}
else {
LevelChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", arr.length, this.sections.length);
}
}
}
public LevelChunk(final Level bjt, final ProtoChunk caq) {
this(bjt, caq.getPos(), caq.getBiomes(), caq.getUpgradeData(), caq.getBlockTicks(), caq.getLiquidTicks(), caq.getInhabitedTime(), caq.getSections(), null);
for (final CompoundTag jt5 : caq.getEntities()) {
EntityType.loadEntityRecursive(jt5, bjt, akn -> {
this.addEntity(akn);
return akn;
});
}
for (final BlockEntity bwi5 : caq.getBlockEntities().values()) {
this.addBlockEntity(bwi5);
}
this.pendingBlockEntities.putAll(caq.getBlockEntityNbts());
for (int integer4 = 0; integer4 < caq.getPostProcessing().length; ++integer4) {
this.postProcessing[integer4] = caq.getPostProcessing()[integer4];
}
this.setAllStarts(caq.getAllStarts());
this.setAllReferences(caq.getAllReferences());
for (final Map.Entry<Heightmap.Types, Heightmap> entry5 : caq.getHeightmaps()) {
if (ChunkStatus.FULL.heightmapsAfter().contains(entry5.getKey())) {
this.getOrCreateHeightmapUnprimed(entry5.getKey()).setRawData(entry5.getValue().getRawData());
}
}
this.setLightCorrect(caq.isLightCorrect());
this.unsaved = true;
}
@Override
public Heightmap getOrCreateHeightmapUnprimed(final Heightmap.Types a) {
return this.heightmaps.computeIfAbsent(a, a -> new Heightmap(this, a));
}
@Override
public Set<BlockPos> getBlockEntitiesPos() {
final Set<BlockPos> set2 = Sets.newHashSet(this.pendingBlockEntities.keySet());
set2.addAll(this.blockEntities.keySet());
return set2;
}
@Override
public LevelChunkSection[] getSections() {
return this.sections;
}
@Override
public BlockState getBlockState(final BlockPos fk) {
final int integer3 = fk.getX();
final int integer4 = fk.getY();
final int integer5 = fk.getZ();
if (this.level.getGeneratorType() == LevelType.DEBUG_ALL_BLOCK_STATES) {
BlockState byg6 = null;
if (integer4 == 60) {
byg6 = Blocks.BARRIER.defaultBlockState();
}
if (integer4 == 70) {
byg6 = DebugLevelSource.getBlockStateFor(integer3, integer5);
}
return (byg6 == null) ? Blocks.AIR.defaultBlockState() : byg6;
}
try {
if (integer4 >= 0 && integer4 >> 4 < this.sections.length) {
final LevelChunkSection caj6 = this.sections[integer4 >> 4];
if (!LevelChunkSection.isEmpty(caj6)) {
return caj6.getBlockState(integer3 & 0xF, integer4 & 0xF, integer5 & 0xF);
}
}
return Blocks.AIR.defaultBlockState();
}
catch (Throwable throwable6) {
final CrashReport h7 = CrashReport.forThrowable(throwable6, "Getting block state");
final CrashReportCategory i8 = h7.addCategory("Block being got");
i8.setDetail("Location", () -> CrashReportCategory.formatLocation(integer3, integer4, integer5));
throw new ReportedException(h7);
}
}
@Override
public FluidState getFluidState(final BlockPos fk) {
return this.getFluidState(fk.getX(), fk.getY(), fk.getZ());
}
public FluidState getFluidState(final int integer1, final int integer2, final int integer3) {
try {
if (integer2 >= 0 && integer2 >> 4 < this.sections.length) {
final LevelChunkSection caj5 = this.sections[integer2 >> 4];
if (!LevelChunkSection.isEmpty(caj5)) {
return caj5.getFluidState(integer1 & 0xF, integer2 & 0xF, integer3 & 0xF);
}
}
return Fluids.EMPTY.defaultFluidState();
}
catch (Throwable throwable5) {
final CrashReport h6 = CrashReport.forThrowable(throwable5, "Getting fluid state");
final CrashReportCategory i7 = h6.addCategory("Block being got");
i7.setDetail("Location", () -> CrashReportCategory.formatLocation(integer1, integer2, integer3));
throw new ReportedException(h6);
}
}
@Nullable
@Override
public BlockState setBlockState(final BlockPos fk, final BlockState byg, final boolean boolean3) {
final int integer5 = fk.getX() & 0xF;
final int integer6 = fk.getY();
final int integer7 = fk.getZ() & 0xF;
LevelChunkSection caj8 = this.sections[integer6 >> 4];
if (caj8 == LevelChunk.EMPTY_SECTION) {
if (byg.isAir()) {
return null;
}
caj8 = new LevelChunkSection(integer6 >> 4 << 4);
this.sections[integer6 >> 4] = caj8;
}
final boolean boolean4 = caj8.isEmpty();
final BlockState byg2 = caj8.setBlockState(integer5, integer6 & 0xF, integer7, byg);
if (byg2 == byg) {
return null;
}
final Block bpe11 = byg.getBlock();
final Block bpe12 = byg2.getBlock();
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(integer5, integer6, integer7, byg);
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(integer5, integer6, integer7, byg);
this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(integer5, integer6, integer7, byg);
this.heightmaps.get(Heightmap.Types.WORLD_SURFACE).update(integer5, integer6, integer7, byg);
final boolean boolean5 = caj8.isEmpty();
if (boolean4 != boolean5) {
this.level.getChunkSource().getLightEngine().updateSectionStatus(fk, boolean5);
}
if (!this.level.isClientSide) {
byg2.onRemove(this.level, fk, byg, boolean3);
}
else if (bpe12 != bpe11 && bpe12 instanceof EntityBlock) {
this.level.removeBlockEntity(fk);
}
if (caj8.getBlockState(integer5, integer6 & 0xF, integer7).getBlock() != bpe11) {
return null;
}
if (bpe12 instanceof EntityBlock) {
final BlockEntity bwi14 = this.getBlockEntity(fk, EntityCreationType.CHECK);
if (bwi14 != null) {
bwi14.clearCache();
}
}
if (!this.level.isClientSide) {
byg.onPlace(this.level, fk, byg2, boolean3);
}
if (bpe11 instanceof EntityBlock) {
BlockEntity bwi14 = this.getBlockEntity(fk, EntityCreationType.CHECK);
if (bwi14 == null) {
bwi14 = ((EntityBlock)bpe11).newBlockEntity(this.level);
this.level.setBlockEntity(fk, bwi14);
}
else {
bwi14.clearCache();
}
}
this.unsaved = true;
return byg2;
}
@Nullable
public LevelLightEngine getLightEngine() {
return this.level.getChunkSource().getLightEngine();
}
@Override
public void addEntity(final Entity akn) {
this.lastSaveHadEntities = true;
final int integer3 = Mth.floor(akn.getX() / 16.0);
final int integer4 = Mth.floor(akn.getZ() / 16.0);
if (integer3 != this.chunkPos.x || integer4 != this.chunkPos.z) {
LevelChunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", integer3, integer4, this.chunkPos.x, this.chunkPos.z, akn);
akn.removed = true;
}
int integer5 = Mth.floor(akn.getY() / 16.0);
if (integer5 < 0) {
integer5 = 0;
}
if (integer5 >= this.entitySections.length) {
integer5 = this.entitySections.length - 1;
}
akn.inChunk = true;
akn.xChunk = this.chunkPos.x;
akn.yChunk = integer5;
akn.zChunk = this.chunkPos.z;
this.entitySections[integer5].add(akn);
}
@Override
public void setHeightmap(final Heightmap.Types a, final long[] arr) {
this.heightmaps.get(a).setRawData(arr);
}
public void removeEntity(final Entity akn) {
this.removeEntity(akn, akn.yChunk);
}
public void removeEntity(final Entity akn, int integer) {
if (integer < 0) {
integer = 0;
}
if (integer >= this.entitySections.length) {
integer = this.entitySections.length - 1;
}
this.entitySections[integer].remove(akn);
}
@Override
public int getHeight(final Heightmap.Types a, final int integer2, final int integer3) {
return this.heightmaps.get(a).getFirstAvailable(integer2 & 0xF, integer3 & 0xF) - 1;
}
@Nullable
private BlockEntity createBlockEntity(final BlockPos fk) {
final BlockState byg3 = this.getBlockState(fk);
final Block bpe4 = byg3.getBlock();
if (!bpe4.isEntityBlock()) {
return null;
}
return ((EntityBlock)bpe4).newBlockEntity(this.level);
}
@Nullable
@Override
public BlockEntity getBlockEntity(final BlockPos fk) {
return this.getBlockEntity(fk, EntityCreationType.CHECK);
}
@Nullable
public BlockEntity getBlockEntity(final BlockPos fk, final EntityCreationType a) {
BlockEntity bwi4 = this.blockEntities.get(fk);
if (bwi4 == null) {
final CompoundTag jt5 = this.pendingBlockEntities.remove(fk);
if (jt5 != null) {
final BlockEntity bwi5 = this.promotePendingBlockEntity(fk, jt5);
if (bwi5 != null) {
return bwi5;
}
}
}
if (bwi4 == null) {
if (a == EntityCreationType.IMMEDIATE) {
bwi4 = this.createBlockEntity(fk);
this.level.setBlockEntity(fk, bwi4);
}
}
else if (bwi4.isRemoved()) {
this.blockEntities.remove(fk);
return null;
}
return bwi4;
}
public void addBlockEntity(final BlockEntity bwi) {
this.setBlockEntity(bwi.getBlockPos(), bwi);
if (this.loaded || this.level.isClientSide()) {
this.level.setBlockEntity(bwi.getBlockPos(), bwi);
}
}
@Override
public void setBlockEntity(final BlockPos fk, final BlockEntity bwi) {
if (!(this.getBlockState(fk).getBlock() instanceof EntityBlock)) {
return;
}
bwi.setLevelAndPosition(this.level, fk);
bwi.clearRemoved();
final BlockEntity bwi2 = this.blockEntities.put(fk.immutable(), bwi);
if (bwi2 != null && bwi2 != bwi) {
bwi2.setRemoved();
}
}
@Override
public void setBlockEntityNbt(final CompoundTag jt) {
this.pendingBlockEntities.put(new BlockPos(jt.getInt("x"), jt.getInt("y"), jt.getInt("z")), jt);
}
@Nullable
@Override
public CompoundTag getBlockEntityNbtForSaving(final BlockPos fk) {
final BlockEntity bwi3 = this.getBlockEntity(fk);
if (bwi3 != null && !bwi3.isRemoved()) {
final CompoundTag jt4 = bwi3.save(new CompoundTag());
jt4.putBoolean("keepPacked", false);
return jt4;
}
CompoundTag jt4 = this.pendingBlockEntities.get(fk);
if (jt4 != null) {
jt4 = jt4.copy();
jt4.putBoolean("keepPacked", true);
}
return jt4;
}
@Override
public void removeBlockEntity(final BlockPos fk) {
if (this.loaded || this.level.isClientSide()) {
final BlockEntity bwi3 = this.blockEntities.remove(fk);
if (bwi3 != null) {
bwi3.setRemoved();
}
}
}
public void runPostLoad() {
if (this.postLoad != null) {
this.postLoad.accept(this);
this.postLoad = null;
}
}
public void markUnsaved() {
this.unsaved = true;
}
public void getEntities(@Nullable final Entity akn, final AABB cvc, final List<Entity> list, @Nullable final Predicate<? super Entity> predicate) {
int integer6 = Mth.floor((cvc.minY - 2.0) / 16.0);
int integer7 = Mth.floor((cvc.maxY + 2.0) / 16.0);
integer6 = Mth.clamp(integer6, 0, this.entitySections.length - 1);
integer7 = Mth.clamp(integer7, 0, this.entitySections.length - 1);
for (int integer8 = integer6; integer8 <= integer7; ++integer8) {
if (!this.entitySections[integer8].isEmpty()) {
for (final Entity akn2 : this.entitySections[integer8]) {
if (akn2.getBoundingBox().intersects(cvc) && akn2 != akn) {
if (predicate == null || predicate.test(akn2)) {
list.add(akn2);
}
if (!(akn2 instanceof EnderDragon)) {
continue;
}
for (final EnderDragonPart aun14 : ((EnderDragon)akn2).getSubEntities()) {
if (aun14 != akn && aun14.getBoundingBox().intersects(cvc) && (predicate == null || predicate.test(aun14))) {
list.add(aun14);
}
}
}
}
}
}
}
public <T extends Entity> void getEntities(@Nullable final EntityType<?> akr, final AABB cvc, final List<? super T> list, final Predicate<? super T> predicate) {
int integer6 = Mth.floor((cvc.minY - 2.0) / 16.0);
int integer7 = Mth.floor((cvc.maxY + 2.0) / 16.0);
integer6 = Mth.clamp(integer6, 0, this.entitySections.length - 1);
integer7 = Mth.clamp(integer7, 0, this.entitySections.length - 1);
for (int integer8 = integer6; integer8 <= integer7; ++integer8) {
for (final Entity akn10 : this.entitySections[integer8].<Entity>find(Entity.class)) {
if (akr != null && akn10.getType() != akr) {
continue;
}
final T akn11 = (T)akn10;
if (!akn10.getBoundingBox().intersects(cvc) || !predicate.test(akn11)) {
continue;
}
list.add(akn11);
}
}
}
public <T extends Entity> void getEntitiesOfClass(final Class<? extends T> class1, final AABB cvc, final List<T> list, @Nullable final Predicate<? super T> predicate) {
int integer6 = Mth.floor((cvc.minY - 2.0) / 16.0);
int integer7 = Mth.floor((cvc.maxY + 2.0) / 16.0);
integer6 = Mth.clamp(integer6, 0, this.entitySections.length - 1);
integer7 = Mth.clamp(integer7, 0, this.entitySections.length - 1);
for (int integer8 = integer6; integer8 <= integer7; ++integer8) {
for (final T akn10 : this.entitySections[integer8].find(class1)) {
if (akn10.getBoundingBox().intersects(cvc) && (predicate == null || predicate.test(akn10))) {
list.add(akn10);
}
}
}
}
public boolean isEmpty() {
return false;
}
@Override
public ChunkPos getPos() {
return this.chunkPos;
}
public void replaceWithPacketData(@Nullable final ChunkBiomeContainer bzw, final FriendlyByteBuf kv, final CompoundTag jt, final int integer) {
final boolean boolean6 = bzw != null;
final Predicate<BlockPos> predicate7 = boolean6 ? (fk -> true) : (fk -> (integer & 1 << (fk.getY() >> 4)) != 0x0);
Sets.newHashSet(this.blockEntities.keySet()).stream().filter(predicate7).forEach(this.level::removeBlockEntity);
for (int integer2 = 0; integer2 < this.sections.length; ++integer2) {
LevelChunkSection caj9 = this.sections[integer2];
if ((integer & 1 << integer2) == 0x0) {
if (boolean6 && caj9 != LevelChunk.EMPTY_SECTION) {
this.sections[integer2] = LevelChunk.EMPTY_SECTION;
}
}
else {
if (caj9 == LevelChunk.EMPTY_SECTION) {
caj9 = new LevelChunkSection(integer2 << 4);
this.sections[integer2] = caj9;
}
caj9.read(kv);
}
}
if (bzw != null) {
this.biomes = bzw;
}
for (final Heightmap.Types a11 : Heightmap.Types.values()) {
final String string12 = a11.getSerializationKey();
if (jt.contains(string12, 12)) {
this.setHeightmap(a11, jt.getLongArray(string12));
}
}
for (final BlockEntity bwi9 : this.blockEntities.values()) {
bwi9.clearCache();
}
}
@Override
public ChunkBiomeContainer getBiomes() {
return this.biomes;
}
public void setLoaded(final boolean boolean1) {
this.loaded = boolean1;
}
public Level getLevel() {
return this.level;
}
@Override
public Collection<Map.Entry<Heightmap.Types, Heightmap>> getHeightmaps() {
return Collections.unmodifiableSet(this.heightmaps.entrySet());
}
public Map<BlockPos, BlockEntity> getBlockEntities() {
return this.blockEntities;
}
public ClassInstanceMultiMap<Entity>[] getEntitySections() {
return this.entitySections;
}
@Override
public CompoundTag getBlockEntityNbt(final BlockPos fk) {
return this.pendingBlockEntities.get(fk);
}
@Override
public Stream<BlockPos> getLights() {
return StreamSupport.<BlockPos>stream(BlockPos.betweenClosed(this.chunkPos.getMinBlockX(), 0, this.chunkPos.getMinBlockZ(), this.chunkPos.getMaxBlockX(), 255, this.chunkPos.getMaxBlockZ()).spliterator(), false).filter(fk -> this.getBlockState(fk).getLightEmission() != 0);
}
@Override
public TickList<Block> getBlockTicks() {
return this.blockTicks;
}
@Override
public TickList<Fluid> getLiquidTicks() {
return this.liquidTicks;
}
@Override
public void setUnsaved(final boolean boolean1) {
this.unsaved = boolean1;
}
@Override
public boolean isUnsaved() {
return this.unsaved || (this.lastSaveHadEntities && this.level.getGameTime() != this.lastSaveTime);
}
public void setLastSaveHadEntities(final boolean boolean1) {
this.lastSaveHadEntities = boolean1;
}
@Override
public void setLastSaveTime(final long long1) {
this.lastSaveTime = long1;
}
@Nullable
@Override
public StructureStart getStartForFeature(final String string) {
return this.structureStarts.get(string);
}
@Override
public void setStartForFeature(final String string, final StructureStart cls) {
this.structureStarts.put(string, cls);
}
@Override
public Map<String, StructureStart> getAllStarts() {
return this.structureStarts;
}
@Override
public void setAllStarts(final Map<String, StructureStart> map) {
this.structureStarts.clear();
this.structureStarts.putAll(map);
}
@Override
public LongSet getReferencesForFeature(final String string) {
return this.structuresRefences.computeIfAbsent(string, string -> new LongOpenHashSet());
}
@Override
public void addReferenceForFeature(final String string, final long long2) {
this.structuresRefences.computeIfAbsent(string, string -> new LongOpenHashSet()).add(long2);
}
@Override
public Map<String, LongSet> getAllReferences() {
return this.structuresRefences;
}
@Override
public void setAllReferences(final Map<String, LongSet> map) {
this.structuresRefences.clear();
this.structuresRefences.putAll(map);
}
@Override
public long getInhabitedTime() {
return this.inhabitedTime;
}
@Override
public void setInhabitedTime(final long long1) {
this.inhabitedTime = long1;
}
public void postProcessGeneration() {
final ChunkPos bje2 = this.getPos();
for (int integer3 = 0; integer3 < this.postProcessing.length; ++integer3) {
if (this.postProcessing[integer3] != null) {
for (final Short short5 : this.postProcessing[integer3]) {
final BlockPos fk6 = ProtoChunk.unpackOffsetCoordinates(short5, integer3, bje2);
final BlockState byg7 = this.getBlockState(fk6);
final BlockState byg8 = Block.updateFromNeighbourShapes(byg7, this.level, fk6);
this.level.setBlock(fk6, byg8, 20);
}
this.postProcessing[integer3].clear();
}
}
this.unpackTicks();
for (final BlockPos fk7 : Sets.<BlockPos>newHashSet(this.pendingBlockEntities.keySet())) {
this.getBlockEntity(fk7);
}
this.pendingBlockEntities.clear();
this.upgradeData.upgrade(this);
}
@Nullable
private BlockEntity promotePendingBlockEntity(final BlockPos fk, final CompoundTag jt) {
BlockEntity bwi4;
if ("DUMMY".equals(jt.getString("id"))) {
final Block bpe5 = this.getBlockState(fk).getBlock();
if (bpe5 instanceof EntityBlock) {
bwi4 = ((EntityBlock)bpe5).newBlockEntity(this.level);
}
else {
bwi4 = null;
LevelChunk.LOGGER.warn("Tried to load a DUMMY block entity @ {} but found not block entity block {} at location", fk, this.getBlockState(fk));
}
}
else {
bwi4 = BlockEntity.loadStatic(jt);
}
if (bwi4 != null) {
bwi4.setLevelAndPosition(this.level, fk);
this.addBlockEntity(bwi4);
}
else {
LevelChunk.LOGGER.warn("Tried to load a block entity for block {} but failed at location {}", this.getBlockState(fk), fk);
}
return bwi4;
}
@Override
public UpgradeData getUpgradeData() {
return this.upgradeData;
}
@Override
public ShortList[] getPostProcessing() {
return this.postProcessing;
}
public void unpackTicks() {
if (this.blockTicks instanceof ProtoTickList) {
((ProtoTickList)this.blockTicks).copyOut(this.level.getBlockTicks(), fk -> this.getBlockState(fk).getBlock());
this.blockTicks = EmptyTickList.empty();
}
else if (this.blockTicks instanceof ChunkTickList) {
this.level.getBlockTicks().addAll(((ChunkTickList)this.blockTicks).ticks());
this.blockTicks = EmptyTickList.empty();
}
if (this.liquidTicks instanceof ProtoTickList) {
((ProtoTickList)this.liquidTicks).copyOut(this.level.getLiquidTicks(), fk -> this.getFluidState(fk).getType());
this.liquidTicks = EmptyTickList.empty();
}
else if (this.liquidTicks instanceof ChunkTickList) {
this.level.getLiquidTicks().addAll(((ChunkTickList)this.liquidTicks).ticks());
this.liquidTicks = EmptyTickList.empty();
}
}
public void packTicks(final ServerLevel xd) {
if (this.blockTicks == EmptyTickList.empty()) {
this.blockTicks = new ChunkTickList<Block>(Registry.BLOCK::getKey, xd.getBlockTicks().fetchTicksInChunk(this.chunkPos, true, false));
this.setUnsaved(true);
}
if (this.liquidTicks == EmptyTickList.empty()) {
this.liquidTicks = new ChunkTickList<Fluid>(Registry.FLUID::getKey, xd.getLiquidTicks().fetchTicksInChunk(this.chunkPos, true, false));
this.setUnsaved(true);
}
}
@Override
public ChunkStatus getStatus() {
return ChunkStatus.FULL;
}
public ChunkHolder.FullChunkStatus getFullStatus() {
if (this.fullStatus == null) {
return ChunkHolder.FullChunkStatus.BORDER;
}
return this.fullStatus.get();
}
public void setFullStatus(final Supplier<ChunkHolder.FullChunkStatus> supplier) {
this.fullStatus = supplier;
}
@Override
public boolean isLightCorrect() {
return this.isLightCorrect;
}
@Override
public void setLightCorrect(final boolean boolean1) {
this.isLightCorrect = boolean1;
this.setUnsaved(true);
}
static {
LOGGER = LogManager.getLogger();
EMPTY_SECTION = null;
}
public enum EntityCreationType {
IMMEDIATE,
QUEUED,
CHECK;
}
}