minecraft-source/src/net/minecraft/world/level/Level.java

1092 lines
44 KiB
Java

package net.minecraft.world.level;
import org.apache.logging.log4j.LogManager;
import net.minecraft.tags.TagManager;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.network.protocol.Packet;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.entity.EntityType;
import java.util.function.Predicate;
import java.io.IOException;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.level.block.state.predicate.BlockMaterialPredicate;
import net.minecraft.world.level.material.Material;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.AABB;
import java.util.function.Consumer;
import net.minecraft.world.level.block.entity.BlockEntityType;
import java.util.Iterator;
import java.util.Collection;
import net.minecraft.world.level.block.entity.TickableBlockEntity;
import org.apache.logging.log4j.util.Supplier;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.ReportedException;
import net.minecraft.CrashReportCategory;
import net.minecraft.core.Registry;
import net.minecraft.CrashReport;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.block.Block;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.BlockPos;
import javax.annotation.Nullable;
import net.minecraft.server.MinecraftServer;
import com.google.common.collect.Lists;
import java.util.function.BiFunction;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.dimension.Dimension;
import java.util.Random;
import net.minecraft.world.level.block.entity.BlockEntity;
import java.util.List;
import net.minecraft.core.Direction;
import org.apache.logging.log4j.Logger;
public abstract class Level implements LevelAccessor, AutoCloseable {
protected static final Logger LOGGER;
private static final Direction[] DIRECTIONS;
public final List<BlockEntity> blockEntityList;
public final List<BlockEntity> tickableBlockEntities;
protected final List<BlockEntity> pendingBlockEntities;
protected final List<BlockEntity> blockEntitiesToUnload;
private final Thread thread;
private int skyDarken;
protected int randValue;
protected final int addend = 1013904223;
protected float oRainLevel;
protected float rainLevel;
protected float oThunderLevel;
protected float thunderLevel;
public final Random random;
public final Dimension dimension;
protected final ChunkSource chunkSource;
protected final LevelData levelData;
private final ProfilerFiller profiler;
public final boolean isClientSide;
protected boolean updatingBlockEntities;
private final WorldBorder worldBorder;
private final BiomeManager biomeManager;
protected Level(final LevelData crj, final DimensionType cbf, final BiFunction<Level, Dimension, ChunkSource> biFunction, final ProfilerFiller aim, final boolean boolean5) {
this.blockEntityList = Lists.newArrayList();
this.tickableBlockEntities = Lists.newArrayList();
this.pendingBlockEntities = Lists.newArrayList();
this.blockEntitiesToUnload = Lists.newArrayList();
this.randValue = new Random().nextInt();
this.random = new Random();
this.profiler = aim;
this.levelData = crj;
this.dimension = cbf.create(this);
this.chunkSource = biFunction.apply(this, this.dimension);
this.isClientSide = boolean5;
this.worldBorder = this.dimension.createWorldBorder();
this.thread = Thread.currentThread();
this.biomeManager = new BiomeManager(this, boolean5 ? crj.getSeed() : LevelData.obfuscateSeed(crj.getSeed()), cbf.getBiomeZoomer());
}
@Override
public boolean isClientSide() {
return this.isClientSide;
}
@Nullable
public MinecraftServer getServer() {
return null;
}
public void validateSpawn() {
this.setSpawnPos(new BlockPos(8, 64, 8));
}
public BlockState getTopBlockState(final BlockPos fk) {
BlockPos fk2;
for (fk2 = new BlockPos(fk.getX(), this.getSeaLevel(), fk.getZ()); !this.isEmptyBlock(fk2.above()); fk2 = fk2.above()) {}
return this.getBlockState(fk2);
}
public static boolean isInWorldBounds(final BlockPos fk) {
return !isOutsideBuildHeight(fk) && fk.getX() >= -30000000 && fk.getZ() >= -30000000 && fk.getX() < 30000000 && fk.getZ() < 30000000;
}
public static boolean isOutsideBuildHeight(final BlockPos fk) {
return isOutsideBuildHeight(fk.getY());
}
public static boolean isOutsideBuildHeight(final int integer) {
return integer < 0 || integer >= 256;
}
public LevelChunk getChunkAt(final BlockPos fk) {
return this.getChunk(fk.getX() >> 4, fk.getZ() >> 4);
}
@Override
public LevelChunk getChunk(final int integer1, final int integer2) {
return (LevelChunk)this.getChunk(integer1, integer2, ChunkStatus.FULL);
}
@Override
public ChunkAccess getChunk(final int integer1, final int integer2, final ChunkStatus cab, final boolean boolean4) {
final ChunkAccess bzv6 = this.chunkSource.getChunk(integer1, integer2, cab, boolean4);
if (bzv6 == null && boolean4) {
throw new IllegalStateException("Should always be able to create a chunk!");
}
return bzv6;
}
@Override
public boolean setBlock(final BlockPos fk, final BlockState byg, final int integer) {
if (isOutsideBuildHeight(fk)) {
return false;
}
if (!this.isClientSide && this.levelData.getGeneratorType() == LevelType.DEBUG_ALL_BLOCK_STATES) {
return false;
}
final LevelChunk cai5 = this.getChunkAt(fk);
final Block bpe6 = byg.getBlock();
final BlockState byg2 = cai5.setBlockState(fk, byg, (integer & 0x40) != 0x0);
if (byg2 != null) {
final BlockState byg3 = this.getBlockState(fk);
if (byg3 != byg2 && (byg3.getLightBlock(this, fk) != byg2.getLightBlock(this, fk) || byg3.getLightEmission() != byg2.getLightEmission() || byg3.useShapeForLightOcclusion() || byg2.useShapeForLightOcclusion())) {
this.profiler.push("queueCheckLight");
this.getChunkSource().getLightEngine().checkBlock(fk);
this.profiler.pop();
}
if (byg3 == byg) {
if (byg2 != byg3) {
this.setBlocksDirty(fk, byg2, byg3);
}
if ((integer & 0x2) != 0x0 && (!this.isClientSide || (integer & 0x4) == 0x0) && (this.isClientSide || (cai5.getFullStatus() != null && cai5.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING)))) {
this.sendBlockUpdated(fk, byg2, byg, integer);
}
if (!this.isClientSide && (integer & 0x1) != 0x0) {
this.blockUpdated(fk, byg2.getBlock());
if (byg.hasAnalogOutputSignal()) {
this.updateNeighbourForOutputSignal(fk, bpe6);
}
}
if ((integer & 0x10) == 0x0) {
final int integer2 = integer & 0xFFFFFFFE;
byg2.updateIndirectNeighbourShapes(this, fk, integer2);
byg.updateNeighbourShapes(this, fk, integer2);
byg.updateIndirectNeighbourShapes(this, fk, integer2);
}
this.onBlockStateChange(fk, byg2, byg3);
}
return true;
}
return false;
}
public void onBlockStateChange(final BlockPos fk, final BlockState byg2, final BlockState byg3) {
}
@Override
public boolean removeBlock(final BlockPos fk, final boolean boolean2) {
final FluidState cog4 = this.getFluidState(fk);
return this.setBlock(fk, cog4.createLegacyBlock(), 0x3 | (boolean2 ? 64 : 0));
}
@Override
public boolean destroyBlock(final BlockPos fk, final boolean boolean2, @Nullable final Entity akn) {
final BlockState byg5 = this.getBlockState(fk);
if (byg5.isAir()) {
return false;
}
final FluidState cog6 = this.getFluidState(fk);
this.levelEvent(2001, fk, Block.getId(byg5));
if (boolean2) {
final BlockEntity bwi7 = byg5.getBlock().isEntityBlock() ? this.getBlockEntity(fk) : null;
Block.dropResources(byg5, this, fk, bwi7, akn, ItemStack.EMPTY);
}
return this.setBlock(fk, cog6.createLegacyBlock(), 3);
}
public boolean setBlockAndUpdate(final BlockPos fk, final BlockState byg) {
return this.setBlock(fk, byg, 3);
}
public abstract void sendBlockUpdated(final BlockPos fk, final BlockState byg2, final BlockState byg3, final int integer);
@Override
public void blockUpdated(final BlockPos fk, final Block bpe) {
if (this.levelData.getGeneratorType() != LevelType.DEBUG_ALL_BLOCK_STATES) {
this.updateNeighborsAt(fk, bpe);
}
}
public void setBlocksDirty(final BlockPos fk, final BlockState byg2, final BlockState byg3) {
}
public void updateNeighborsAt(final BlockPos fk, final Block bpe) {
this.neighborChanged(fk.west(), bpe, fk);
this.neighborChanged(fk.east(), bpe, fk);
this.neighborChanged(fk.below(), bpe, fk);
this.neighborChanged(fk.above(), bpe, fk);
this.neighborChanged(fk.north(), bpe, fk);
this.neighborChanged(fk.south(), bpe, fk);
}
public void updateNeighborsAtExceptFromFacing(final BlockPos fk, final Block bpe, final Direction fp) {
if (fp != Direction.WEST) {
this.neighborChanged(fk.west(), bpe, fk);
}
if (fp != Direction.EAST) {
this.neighborChanged(fk.east(), bpe, fk);
}
if (fp != Direction.DOWN) {
this.neighborChanged(fk.below(), bpe, fk);
}
if (fp != Direction.UP) {
this.neighborChanged(fk.above(), bpe, fk);
}
if (fp != Direction.NORTH) {
this.neighborChanged(fk.north(), bpe, fk);
}
if (fp != Direction.SOUTH) {
this.neighborChanged(fk.south(), bpe, fk);
}
}
public void neighborChanged(final BlockPos fk1, final Block bpe, final BlockPos fk3) {
if (this.isClientSide) {
return;
}
final BlockState byg5 = this.getBlockState(fk1);
try {
byg5.neighborChanged(this, fk1, bpe, fk3, false);
}
catch (Throwable throwable6) {
final CrashReport h7 = CrashReport.forThrowable(throwable6, "Exception while updating neighbours");
final CrashReportCategory i8 = h7.addCategory("Block being updated");
i8.setDetail("Source block type", () -> {
try {
return String.format("ID #%s (%s // %s)", Registry.BLOCK.getKey(bpe), bpe.getDescriptionId(), bpe.getClass().getCanonicalName());
}
catch (Throwable throwable7) {
return "ID #" + Registry.BLOCK.getKey(bpe);
}
});
CrashReportCategory.populateBlockDetails(i8, fk1, byg5);
throw new ReportedException(h7);
}
}
@Override
public int getHeight(final Heightmap.Types a, final int integer2, final int integer3) {
int integer4;
if (integer2 < -30000000 || integer3 < -30000000 || integer2 >= 30000000 || integer3 >= 30000000) {
integer4 = this.getSeaLevel() + 1;
}
else if (this.hasChunk(integer2 >> 4, integer3 >> 4)) {
integer4 = this.getChunk(integer2 >> 4, integer3 >> 4).getHeight(a, integer2 & 0xF, integer3 & 0xF) + 1;
}
else {
integer4 = 0;
}
return integer4;
}
@Override
public LevelLightEngine getLightEngine() {
return this.getChunkSource().getLightEngine();
}
@Override
public BlockState getBlockState(final BlockPos fk) {
if (isOutsideBuildHeight(fk)) {
return Blocks.VOID_AIR.defaultBlockState();
}
final LevelChunk cai3 = this.getChunk(fk.getX() >> 4, fk.getZ() >> 4);
return cai3.getBlockState(fk);
}
@Override
public FluidState getFluidState(final BlockPos fk) {
if (isOutsideBuildHeight(fk)) {
return Fluids.EMPTY.defaultFluidState();
}
final LevelChunk cai3 = this.getChunkAt(fk);
return cai3.getFluidState(fk);
}
public boolean isDay() {
return this.dimension.getType() == DimensionType.OVERWORLD && this.skyDarken < 4;
}
public boolean isNight() {
return this.dimension.getType() == DimensionType.OVERWORLD && !this.isDay();
}
@Override
public void playSound(@Nullable final Player ayg, final BlockPos fk, final SoundEvent aah, final SoundSource aaj, final float float5, final float float6) {
this.playSound(ayg, fk.getX() + 0.5, fk.getY() + 0.5, fk.getZ() + 0.5, aah, aaj, float5, float6);
}
public abstract void playSound(@Nullable final Player ayg, final double double2, final double double3, final double double4, final SoundEvent aah, final SoundSource aaj, final float float7, final float float8);
public abstract void playSound(@Nullable final Player ayg, final Entity akn, final SoundEvent aah, final SoundSource aaj, final float float5, final float float6);
public void playLocalSound(final double double1, final double double2, final double double3, final SoundEvent aah, final SoundSource aaj, final float float6, final float float7, final boolean boolean8) {
}
@Override
public void addParticle(final ParticleOptions gt, final double double2, final double double3, final double double4, final double double5, final double double6, final double double7) {
}
public void addParticle(final ParticleOptions gt, final boolean boolean2, final double double3, final double double4, final double double5, final double double6, final double double7, final double double8) {
}
public void addAlwaysVisibleParticle(final ParticleOptions gt, final double double2, final double double3, final double double4, final double double5, final double double6, final double double7) {
}
public void addAlwaysVisibleParticle(final ParticleOptions gt, final boolean boolean2, final double double3, final double double4, final double double5, final double double6, final double double7, final double double8) {
}
public float getSunAngle(final float float1) {
final float float2 = this.getTimeOfDay(float1);
return float2 * 6.2831855f;
}
public boolean addBlockEntity(final BlockEntity bwi) {
if (this.updatingBlockEntities) {
Level.LOGGER.error("Adding block entity while ticking: {} @ {}", new Supplier[] { () -> Registry.BLOCK_ENTITY_TYPE.getKey(bwi.getType()), bwi::getBlockPos });
}
final boolean boolean3 = this.blockEntityList.add(bwi);
if (boolean3 && bwi instanceof TickableBlockEntity) {
this.tickableBlockEntities.add(bwi);
}
if (this.isClientSide) {
final BlockPos fk4 = bwi.getBlockPos();
final BlockState byg5 = this.getBlockState(fk4);
this.sendBlockUpdated(fk4, byg5, byg5, 2);
}
return boolean3;
}
public void addAllPendingBlockEntities(final Collection<BlockEntity> collection) {
if (this.updatingBlockEntities) {
this.pendingBlockEntities.addAll(collection);
}
else {
for (final BlockEntity bwi4 : collection) {
this.addBlockEntity(bwi4);
}
}
}
public void tickBlockEntities() {
final ProfilerFiller aim2 = this.getProfiler();
aim2.push("blockEntities");
if (!this.blockEntitiesToUnload.isEmpty()) {
this.tickableBlockEntities.removeAll(this.blockEntitiesToUnload);
this.blockEntityList.removeAll(this.blockEntitiesToUnload);
this.blockEntitiesToUnload.clear();
}
this.updatingBlockEntities = true;
final Iterator<BlockEntity> iterator3 = this.tickableBlockEntities.iterator();
while (iterator3.hasNext()) {
final BlockEntity bwi4 = iterator3.next();
if (!bwi4.isRemoved() && bwi4.hasLevel()) {
final BlockPos fk5 = bwi4.getBlockPos();
if (this.chunkSource.isTickingChunk(fk5) && this.getWorldBorder().isWithinBounds(fk5)) {
try {
aim2.push(() -> String.valueOf(BlockEntityType.getKey(bwi4.getType())));
if (bwi4.getType().isValid(this.getBlockState(fk5).getBlock())) {
((TickableBlockEntity)bwi4).tick();
}
else {
bwi4.logInvalidState();
}
aim2.pop();
}
catch (Throwable throwable6) {
final CrashReport h7 = CrashReport.forThrowable(throwable6, "Ticking block entity");
final CrashReportCategory i8 = h7.addCategory("Block entity being ticked");
bwi4.fillCrashReportCategory(i8);
throw new ReportedException(h7);
}
}
}
if (bwi4.isRemoved()) {
iterator3.remove();
this.blockEntityList.remove(bwi4);
if (!this.hasChunkAt(bwi4.getBlockPos())) {
continue;
}
this.getChunkAt(bwi4.getBlockPos()).removeBlockEntity(bwi4.getBlockPos());
}
}
this.updatingBlockEntities = false;
aim2.popPush("pendingBlockEntities");
if (!this.pendingBlockEntities.isEmpty()) {
for (int integer4 = 0; integer4 < this.pendingBlockEntities.size(); ++integer4) {
final BlockEntity bwi5 = this.pendingBlockEntities.get(integer4);
if (!bwi5.isRemoved()) {
if (!this.blockEntityList.contains(bwi5)) {
this.addBlockEntity(bwi5);
}
if (this.hasChunkAt(bwi5.getBlockPos())) {
final LevelChunk cai6 = this.getChunkAt(bwi5.getBlockPos());
final BlockState byg7 = cai6.getBlockState(bwi5.getBlockPos());
cai6.setBlockEntity(bwi5.getBlockPos(), bwi5);
this.sendBlockUpdated(bwi5.getBlockPos(), byg7, byg7, 3);
}
}
}
this.pendingBlockEntities.clear();
}
aim2.pop();
}
public void guardEntityTick(final Consumer<Entity> consumer, final Entity akn) {
try {
consumer.accept(akn);
}
catch (Throwable throwable4) {
final CrashReport h5 = CrashReport.forThrowable(throwable4, "Ticking entity");
final CrashReportCategory i6 = h5.addCategory("Entity being ticked");
akn.fillCrashReportCategory(i6);
throw new ReportedException(h5);
}
}
public boolean containsAnyBlocks(final AABB cvc) {
final int integer3 = Mth.floor(cvc.minX);
final int integer4 = Mth.ceil(cvc.maxX);
final int integer5 = Mth.floor(cvc.minY);
final int integer6 = Mth.ceil(cvc.maxY);
final int integer7 = Mth.floor(cvc.minZ);
final int integer8 = Mth.ceil(cvc.maxZ);
try (final BlockPos.PooledMutableBlockPos b9 = BlockPos.PooledMutableBlockPos.acquire()) {
for (int integer9 = integer3; integer9 < integer4; ++integer9) {
for (int integer10 = integer5; integer10 < integer6; ++integer10) {
for (int integer11 = integer7; integer11 < integer8; ++integer11) {
final BlockState byg14 = this.getBlockState(b9.set(integer9, integer10, integer11));
if (!byg14.isAir()) {
return true;
}
}
}
}
}
return false;
}
public boolean containsFireBlock(final AABB cvc) {
final int integer3 = Mth.floor(cvc.minX);
final int integer4 = Mth.ceil(cvc.maxX);
final int integer5 = Mth.floor(cvc.minY);
final int integer6 = Mth.ceil(cvc.maxY);
final int integer7 = Mth.floor(cvc.minZ);
final int integer8 = Mth.ceil(cvc.maxZ);
if (this.hasChunksAt(integer3, integer5, integer7, integer4, integer6, integer8)) {
try (final BlockPos.PooledMutableBlockPos b9 = BlockPos.PooledMutableBlockPos.acquire()) {
for (int integer9 = integer3; integer9 < integer4; ++integer9) {
for (int integer10 = integer5; integer10 < integer6; ++integer10) {
for (int integer11 = integer7; integer11 < integer8; ++integer11) {
final Block bpe14 = this.getBlockState(b9.set(integer9, integer10, integer11)).getBlock();
if (bpe14 == Blocks.FIRE || bpe14 == Blocks.LAVA) {
return true;
}
}
}
}
}
}
return false;
}
@Nullable
public BlockState containsBlock(final AABB cvc, final Block bpe) {
final int integer4 = Mth.floor(cvc.minX);
final int integer5 = Mth.ceil(cvc.maxX);
final int integer6 = Mth.floor(cvc.minY);
final int integer7 = Mth.ceil(cvc.maxY);
final int integer8 = Mth.floor(cvc.minZ);
final int integer9 = Mth.ceil(cvc.maxZ);
if (this.hasChunksAt(integer4, integer6, integer8, integer5, integer7, integer9)) {
try (final BlockPos.PooledMutableBlockPos b10 = BlockPos.PooledMutableBlockPos.acquire()) {
for (int integer10 = integer4; integer10 < integer5; ++integer10) {
for (int integer11 = integer6; integer11 < integer7; ++integer11) {
for (int integer12 = integer8; integer12 < integer9; ++integer12) {
final BlockState byg15 = this.getBlockState(b10.set(integer10, integer11, integer12));
if (byg15.getBlock() == bpe) {
return byg15;
}
}
}
}
}
}
return null;
}
public boolean containsMaterial(final AABB cvc, final Material cok) {
final int integer4 = Mth.floor(cvc.minX);
final int integer5 = Mth.ceil(cvc.maxX);
final int integer6 = Mth.floor(cvc.minY);
final int integer7 = Mth.ceil(cvc.maxY);
final int integer8 = Mth.floor(cvc.minZ);
final int integer9 = Mth.ceil(cvc.maxZ);
final BlockMaterialPredicate byo10 = BlockMaterialPredicate.forMaterial(cok);
return BlockPos.betweenClosedStream(integer4, integer6, integer8, integer5 - 1, integer7 - 1, integer9 - 1).anyMatch(fk -> byo10.test(this.getBlockState(fk)));
}
public Explosion explode(@Nullable final Entity akn, final double double2, final double double3, final double double4, final float float5, final Explosion.BlockInteraction a) {
return this.explode(akn, null, double2, double3, double4, float5, false, a);
}
public Explosion explode(@Nullable final Entity akn, final double double2, final double double3, final double double4, final float float5, final boolean boolean6, final Explosion.BlockInteraction a) {
return this.explode(akn, null, double2, double3, double4, float5, boolean6, a);
}
public Explosion explode(@Nullable final Entity akn, @Nullable final DamageSource ajw, final double double3, final double double4, final double double5, final float float6, final boolean boolean7, final Explosion.BlockInteraction a) {
final Explosion bjm13 = new Explosion(this, akn, double3, double4, double5, float6, boolean7, a);
if (ajw != null) {
bjm13.setDamageSource(ajw);
}
bjm13.explode();
bjm13.finalizeExplosion(true);
return bjm13;
}
public boolean extinguishFire(@Nullable final Player ayg, BlockPos fk, final Direction fp) {
fk = fk.relative(fp);
if (this.getBlockState(fk).getBlock() == Blocks.FIRE) {
this.levelEvent(ayg, 1009, fk, 0);
this.removeBlock(fk, false);
return true;
}
return false;
}
public String gatherChunkSourceStats() {
return this.chunkSource.gatherStats();
}
@Nullable
@Override
public BlockEntity getBlockEntity(final BlockPos fk) {
if (isOutsideBuildHeight(fk)) {
return null;
}
if (!this.isClientSide && Thread.currentThread() != this.thread) {
return null;
}
BlockEntity bwi3 = null;
if (this.updatingBlockEntities) {
bwi3 = this.getPendingBlockEntityAt(fk);
}
if (bwi3 == null) {
bwi3 = this.getChunkAt(fk).getBlockEntity(fk, LevelChunk.EntityCreationType.IMMEDIATE);
}
if (bwi3 == null) {
bwi3 = this.getPendingBlockEntityAt(fk);
}
return bwi3;
}
@Nullable
private BlockEntity getPendingBlockEntityAt(final BlockPos fk) {
for (int integer3 = 0; integer3 < this.pendingBlockEntities.size(); ++integer3) {
final BlockEntity bwi4 = this.pendingBlockEntities.get(integer3);
if (!bwi4.isRemoved() && bwi4.getBlockPos().equals(fk)) {
return bwi4;
}
}
return null;
}
public void setBlockEntity(final BlockPos fk, @Nullable final BlockEntity bwi) {
if (isOutsideBuildHeight(fk)) {
return;
}
if (bwi != null && !bwi.isRemoved()) {
if (this.updatingBlockEntities) {
bwi.setLevelAndPosition(this, fk);
final Iterator<BlockEntity> iterator4 = this.pendingBlockEntities.iterator();
while (iterator4.hasNext()) {
final BlockEntity bwi2 = iterator4.next();
if (bwi2.getBlockPos().equals(fk)) {
bwi2.setRemoved();
iterator4.remove();
}
}
this.pendingBlockEntities.add(bwi);
}
else {
this.getChunkAt(fk).setBlockEntity(fk, bwi);
this.addBlockEntity(bwi);
}
}
}
public void removeBlockEntity(final BlockPos fk) {
final BlockEntity bwi3 = this.getBlockEntity(fk);
if (bwi3 != null && this.updatingBlockEntities) {
bwi3.setRemoved();
this.pendingBlockEntities.remove(bwi3);
}
else {
if (bwi3 != null) {
this.pendingBlockEntities.remove(bwi3);
this.blockEntityList.remove(bwi3);
this.tickableBlockEntities.remove(bwi3);
}
this.getChunkAt(fk).removeBlockEntity(fk);
}
}
public boolean isLoaded(final BlockPos fk) {
return !isOutsideBuildHeight(fk) && this.chunkSource.hasChunk(fk.getX() >> 4, fk.getZ() >> 4);
}
public boolean loadedAndEntityCanStandOn(final BlockPos fk, final Entity akn) {
if (isOutsideBuildHeight(fk)) {
return false;
}
final ChunkAccess bzv4 = this.getChunk(fk.getX() >> 4, fk.getZ() >> 4, ChunkStatus.FULL, false);
return bzv4 != null && bzv4.getBlockState(fk).entityCanStandOn(this, fk, akn);
}
public void updateSkyBrightness() {
final double double2 = 1.0 - this.getRainLevel(1.0f) * 5.0f / 16.0;
final double double3 = 1.0 - this.getThunderLevel(1.0f) * 5.0f / 16.0;
final double double4 = 0.5 + 2.0 * Mth.clamp(Mth.cos(this.getTimeOfDay(1.0f) * 6.2831855f), -0.25, 0.25);
this.skyDarken = (int)((1.0 - double4 * double2 * double3) * 11.0);
}
public void setSpawnSettings(final boolean boolean1, final boolean boolean2) {
this.getChunkSource().setSpawnSettings(boolean1, boolean2);
}
protected void prepareWeather() {
if (this.levelData.isRaining()) {
this.rainLevel = 1.0f;
if (this.levelData.isThundering()) {
this.thunderLevel = 1.0f;
}
}
}
@Override
public void close() throws IOException {
this.chunkSource.close();
}
@Nullable
@Override
public BlockGetter getChunkForCollisions(final int integer1, final int integer2) {
return this.getChunk(integer1, integer2, ChunkStatus.FULL, false);
}
@Override
public List<Entity> getEntities(@Nullable final Entity akn, final AABB cvc, @Nullable final Predicate<? super Entity> predicate) {
final List<Entity> list5 = Lists.newArrayList();
final int integer6 = Mth.floor((cvc.minX - 2.0) / 16.0);
final int integer7 = Mth.floor((cvc.maxX + 2.0) / 16.0);
final int integer8 = Mth.floor((cvc.minZ - 2.0) / 16.0);
final int integer9 = Mth.floor((cvc.maxZ + 2.0) / 16.0);
for (int integer10 = integer6; integer10 <= integer7; ++integer10) {
for (int integer11 = integer8; integer11 <= integer9; ++integer11) {
final LevelChunk cai12 = this.getChunkSource().getChunk(integer10, integer11, false);
if (cai12 != null) {
cai12.getEntities(akn, cvc, list5, predicate);
}
}
}
return list5;
}
public <T extends Entity> List<T> getEntities(@Nullable final EntityType<T> akr, final AABB cvc, final Predicate<? super T> predicate) {
final int integer5 = Mth.floor((cvc.minX - 2.0) / 16.0);
final int integer6 = Mth.ceil((cvc.maxX + 2.0) / 16.0);
final int integer7 = Mth.floor((cvc.minZ - 2.0) / 16.0);
final int integer8 = Mth.ceil((cvc.maxZ + 2.0) / 16.0);
final List<T> list9 = Lists.newArrayList();
for (int integer9 = integer5; integer9 < integer6; ++integer9) {
for (int integer10 = integer7; integer10 < integer8; ++integer10) {
final LevelChunk cai12 = this.getChunkSource().getChunk(integer9, integer10, false);
if (cai12 != null) {
cai12.<Entity>getEntities(akr, cvc, list9, predicate);
}
}
}
return list9;
}
@Override
public <T extends Entity> List<T> getEntitiesOfClass(final Class<? extends T> class1, final AABB cvc, @Nullable final Predicate<? super T> predicate) {
final int integer5 = Mth.floor((cvc.minX - 2.0) / 16.0);
final int integer6 = Mth.ceil((cvc.maxX + 2.0) / 16.0);
final int integer7 = Mth.floor((cvc.minZ - 2.0) / 16.0);
final int integer8 = Mth.ceil((cvc.maxZ + 2.0) / 16.0);
final List<T> list9 = Lists.newArrayList();
final ChunkSource caa10 = this.getChunkSource();
for (int integer9 = integer5; integer9 < integer6; ++integer9) {
for (int integer10 = integer7; integer10 < integer8; ++integer10) {
final LevelChunk cai13 = caa10.getChunk(integer9, integer10, false);
if (cai13 != null) {
cai13.<T>getEntitiesOfClass(class1, cvc, list9, predicate);
}
}
}
return list9;
}
@Override
public <T extends Entity> List<T> getLoadedEntitiesOfClass(final Class<? extends T> class1, final AABB cvc, @Nullable final Predicate<? super T> predicate) {
final int integer5 = Mth.floor((cvc.minX - 2.0) / 16.0);
final int integer6 = Mth.ceil((cvc.maxX + 2.0) / 16.0);
final int integer7 = Mth.floor((cvc.minZ - 2.0) / 16.0);
final int integer8 = Mth.ceil((cvc.maxZ + 2.0) / 16.0);
final List<T> list9 = Lists.newArrayList();
final ChunkSource caa10 = this.getChunkSource();
for (int integer9 = integer5; integer9 < integer6; ++integer9) {
for (int integer10 = integer7; integer10 < integer8; ++integer10) {
final LevelChunk cai13 = caa10.getChunkNow(integer9, integer10);
if (cai13 != null) {
cai13.<T>getEntitiesOfClass(class1, cvc, list9, predicate);
}
}
}
return list9;
}
@Nullable
public abstract Entity getEntity(final int integer);
public void blockEntityChanged(final BlockPos fk, final BlockEntity bwi) {
if (this.hasChunkAt(fk)) {
this.getChunkAt(fk).markUnsaved();
}
}
@Override
public int getSeaLevel() {
return 63;
}
@Override
public Level getLevel() {
return this;
}
public LevelType getGeneratorType() {
return this.levelData.getGeneratorType();
}
public int getDirectSignalTo(final BlockPos fk) {
int integer3 = 0;
integer3 = Math.max(integer3, this.getDirectSignal(fk.below(), Direction.DOWN));
if (integer3 >= 15) {
return integer3;
}
integer3 = Math.max(integer3, this.getDirectSignal(fk.above(), Direction.UP));
if (integer3 >= 15) {
return integer3;
}
integer3 = Math.max(integer3, this.getDirectSignal(fk.north(), Direction.NORTH));
if (integer3 >= 15) {
return integer3;
}
integer3 = Math.max(integer3, this.getDirectSignal(fk.south(), Direction.SOUTH));
if (integer3 >= 15) {
return integer3;
}
integer3 = Math.max(integer3, this.getDirectSignal(fk.west(), Direction.WEST));
if (integer3 >= 15) {
return integer3;
}
integer3 = Math.max(integer3, this.getDirectSignal(fk.east(), Direction.EAST));
if (integer3 >= 15) {
return integer3;
}
return integer3;
}
public boolean hasSignal(final BlockPos fk, final Direction fp) {
return this.getSignal(fk, fp) > 0;
}
public int getSignal(final BlockPos fk, final Direction fp) {
final BlockState byg4 = this.getBlockState(fk);
if (byg4.isRedstoneConductor(this, fk)) {
return this.getDirectSignalTo(fk);
}
return byg4.getSignal(this, fk, fp);
}
public boolean hasNeighborSignal(final BlockPos fk) {
return this.getSignal(fk.below(), Direction.DOWN) > 0 || this.getSignal(fk.above(), Direction.UP) > 0 || this.getSignal(fk.north(), Direction.NORTH) > 0 || this.getSignal(fk.south(), Direction.SOUTH) > 0 || this.getSignal(fk.west(), Direction.WEST) > 0 || this.getSignal(fk.east(), Direction.EAST) > 0;
}
public int getBestNeighborSignal(final BlockPos fk) {
int integer3 = 0;
for (final Direction fp7 : Level.DIRECTIONS) {
final int integer4 = this.getSignal(fk.relative(fp7), fp7);
if (integer4 >= 15) {
return 15;
}
if (integer4 > integer3) {
integer3 = integer4;
}
}
return integer3;
}
public void disconnect() {
}
public void setGameTime(final long long1) {
this.levelData.setGameTime(long1);
}
@Override
public long getSeed() {
return this.levelData.getSeed();
}
public long getGameTime() {
return this.levelData.getGameTime();
}
public long getDayTime() {
return this.levelData.getDayTime();
}
public void setDayTime(final long long1) {
this.levelData.setDayTime(long1);
}
protected void tickTime() {
this.setGameTime(this.levelData.getGameTime() + 1L);
if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
this.setDayTime(this.levelData.getDayTime() + 1L);
}
}
@Override
public BlockPos getSharedSpawnPos() {
BlockPos fk2 = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn());
if (!this.getWorldBorder().isWithinBounds(fk2)) {
fk2 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0, this.getWorldBorder().getCenterZ()));
}
return fk2;
}
public void setSpawnPos(final BlockPos fk) {
this.levelData.setSpawn(fk);
}
public boolean mayInteract(final Player ayg, final BlockPos fk) {
return true;
}
public void broadcastEntityEvent(final Entity akn, final byte byte2) {
}
@Override
public ChunkSource getChunkSource() {
return this.chunkSource;
}
public void blockEvent(final BlockPos fk, final Block bpe, final int integer3, final int integer4) {
this.getBlockState(fk).triggerEvent(this, fk, integer3, integer4);
}
@Override
public LevelData getLevelData() {
return this.levelData;
}
public GameRules getGameRules() {
return this.levelData.getGameRules();
}
public float getThunderLevel(final float float1) {
return Mth.lerp(float1, this.oThunderLevel, this.thunderLevel) * this.getRainLevel(float1);
}
public void setThunderLevel(final float float1) {
this.oThunderLevel = float1;
this.thunderLevel = float1;
}
public float getRainLevel(final float float1) {
return Mth.lerp(float1, this.oRainLevel, this.rainLevel);
}
public void setRainLevel(final float float1) {
this.oRainLevel = float1;
this.rainLevel = float1;
}
public boolean isThundering() {
return this.dimension.isHasSkyLight() && !this.dimension.isHasCeiling() && this.getThunderLevel(1.0f) > 0.9;
}
public boolean isRaining() {
return this.getRainLevel(1.0f) > 0.2;
}
public boolean isRainingAt(final BlockPos fk) {
return this.isRaining() && this.canSeeSky(fk) && this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, fk).getY() <= fk.getY() && this.getBiome(fk).getPrecipitation() == Biome.Precipitation.RAIN;
}
public boolean isHumidAt(final BlockPos fk) {
final Biome bkq3 = this.getBiome(fk);
return bkq3.isHumid();
}
@Nullable
public abstract MapItemSavedData getMapData(final String string);
public abstract void setMapData(final MapItemSavedData crd);
public abstract int getFreeMapId();
public void globalLevelEvent(final int integer1, final BlockPos fk, final int integer3) {
}
public int getHeight() {
return this.dimension.isHasCeiling() ? 128 : 256;
}
public CrashReportCategory fillReportDetails(final CrashReport h) {
final CrashReportCategory i3 = h.addCategory("Affected level", 1);
i3.setDetail("All players", () -> this.players().size() + " total; " + this.players());
i3.setDetail("Chunk stats", this.chunkSource::gatherStats);
i3.setDetail("Level dimension", () -> this.dimension.getType().toString());
try {
this.levelData.fillCrashReportCategory(i3);
}
catch (Throwable throwable4) {
i3.setDetailError("Level Data Unobtainable", throwable4);
}
return i3;
}
public abstract void destroyBlockProgress(final int integer1, final BlockPos fk, final int integer3);
public void createFireworks(final double double1, final double double2, final double double3, final double double4, final double double5, final double double6, @Nullable final CompoundTag jt) {
}
public abstract Scoreboard getScoreboard();
public void updateNeighbourForOutputSignal(final BlockPos fk, final Block bpe) {
for (final Direction fp5 : Direction.Plane.HORIZONTAL) {
BlockPos fk2 = fk.relative(fp5);
if (this.hasChunkAt(fk2)) {
BlockState byg7 = this.getBlockState(fk2);
if (byg7.getBlock() == Blocks.COMPARATOR) {
byg7.neighborChanged(this, fk2, bpe, fk, false);
}
else {
if (!byg7.isRedstoneConductor(this, fk2)) {
continue;
}
fk2 = fk2.relative(fp5);
byg7 = this.getBlockState(fk2);
if (byg7.getBlock() != Blocks.COMPARATOR) {
continue;
}
byg7.neighborChanged(this, fk2, bpe, fk, false);
}
}
}
}
@Override
public DifficultyInstance getCurrentDifficultyAt(final BlockPos fk) {
long long3 = 0L;
float float5 = 0.0f;
if (this.hasChunkAt(fk)) {
float5 = this.getMoonBrightness();
long3 = this.getChunkAt(fk).getInhabitedTime();
}
return new DifficultyInstance(this.getDifficulty(), this.getDayTime(), long3, float5);
}
@Override
public int getSkyDarken() {
return this.skyDarken;
}
public void setSkyFlashTime(final int integer) {
}
@Override
public WorldBorder getWorldBorder() {
return this.worldBorder;
}
public void sendPacketToServer(final Packet<?> lt) {
throw new UnsupportedOperationException("Can't send packets to server unless you're on the client.");
}
@Override
public Dimension getDimension() {
return this.dimension;
}
@Override
public Random getRandom() {
return this.random;
}
@Override
public boolean isStateAtPosition(final BlockPos fk, final Predicate<BlockState> predicate) {
return predicate.test(this.getBlockState(fk));
}
public abstract RecipeManager getRecipeManager();
public abstract TagManager getTagManager();
public BlockPos getBlockRandomPos(final int integer1, final int integer2, final int integer3, final int integer4) {
this.randValue = this.randValue * 3 + 1013904223;
final int integer5 = this.randValue >> 2;
return new BlockPos(integer1 + (integer5 & 0xF), integer2 + (integer5 >> 16 & integer4), integer3 + (integer5 >> 8 & 0xF));
}
public boolean noSave() {
return false;
}
public ProfilerFiller getProfiler() {
return this.profiler;
}
@Override
public BiomeManager getBiomeManager() {
return this.biomeManager;
}
static {
LOGGER = LogManager.getLogger();
DIRECTIONS = Direction.values();
}
}