2025-11-24 22:52:51 +03:00

889 lines
37 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.google.common.collect.Lists
* com.mojang.serialization.Codec
* org.apache.commons.lang3.mutable.MutableBoolean
* org.jspecify.annotations.Nullable
*/
package net.minecraft.world.level;
import com.google.common.collect.Lists;
import com.mojang.serialization.Codec;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.SectionPos;
import net.minecraft.core.particles.ExplosionParticleInfo;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.protocol.Packet;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.AbortableIterationConsumer;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.util.StringRepresentable;
import net.minecraft.util.profiling.Profiler;
import net.minecraft.util.random.WeightedList;
import net.minecraft.world.TickRateManager;
import net.minecraft.world.attribute.EnvironmentAttributeSystem;
import net.minecraft.world.attribute.EnvironmentAttributes;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageSources;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.boss.EnderDragonPart;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.alchemy.PotionBrewing;
import net.minecraft.world.item.component.FireworkExplosion;
import net.minecraft.world.item.crafting.RecipeAccess;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.block.BaseFireBlock;
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.entity.FuelValues;
import net.minecraft.world.level.block.entity.TickingBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.PalettedContainerFactory;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.entity.EntityTypeTest;
import net.minecraft.world.level.entity.LevelEntityGetter;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.redstone.CollectingNeighborUpdater;
import net.minecraft.world.level.redstone.Orientation;
import net.minecraft.world.level.saveddata.maps.MapId;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.level.storage.WritableLevelData;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.Scoreboard;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.jspecify.annotations.Nullable;
public abstract class Level
implements LevelAccessor,
AutoCloseable {
public static final Codec<ResourceKey<Level>> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION);
public static final ResourceKey<Level> OVERWORLD = ResourceKey.create(Registries.DIMENSION, Identifier.withDefaultNamespace("overworld"));
public static final ResourceKey<Level> NETHER = ResourceKey.create(Registries.DIMENSION, Identifier.withDefaultNamespace("the_nether"));
public static final ResourceKey<Level> END = ResourceKey.create(Registries.DIMENSION, Identifier.withDefaultNamespace("the_end"));
public static final int MAX_LEVEL_SIZE = 30000000;
public static final int LONG_PARTICLE_CLIP_RANGE = 512;
public static final int SHORT_PARTICLE_CLIP_RANGE = 32;
public static final int MAX_BRIGHTNESS = 15;
public static final int MAX_ENTITY_SPAWN_Y = 20000000;
public static final int MIN_ENTITY_SPAWN_Y = -20000000;
private static final WeightedList<ExplosionParticleInfo> DEFAULT_EXPLOSION_BLOCK_PARTICLES = WeightedList.builder().add(new ExplosionParticleInfo(ParticleTypes.POOF, 0.5f, 1.0f)).add(new ExplosionParticleInfo(ParticleTypes.SMOKE, 1.0f, 1.0f)).build();
protected final List<TickingBlockEntity> blockEntityTickers = Lists.newArrayList();
protected final CollectingNeighborUpdater neighborUpdater;
private final List<TickingBlockEntity> pendingBlockEntityTickers = Lists.newArrayList();
private boolean tickingBlockEntities;
private final Thread thread;
private final boolean isDebug;
private int skyDarken;
protected int randValue = RandomSource.create().nextInt();
protected final int addend = 1013904223;
protected float oRainLevel;
protected float rainLevel;
protected float oThunderLevel;
protected float thunderLevel;
public final RandomSource random = RandomSource.create();
@Deprecated
private final RandomSource threadSafeRandom = RandomSource.createThreadSafe();
private final Holder<DimensionType> dimensionTypeRegistration;
protected final WritableLevelData levelData;
private final boolean isClientSide;
private final BiomeManager biomeManager;
private final ResourceKey<Level> dimension;
private final RegistryAccess registryAccess;
private final DamageSources damageSources;
private final PalettedContainerFactory palettedContainerFactory;
private long subTickCount;
protected Level(WritableLevelData levelData, ResourceKey<Level> dimension, RegistryAccess registryAccess, Holder<DimensionType> dimensionTypeRegistration, boolean isClientSide, boolean isDebug, long biomeZoomSeed, int maxChainedNeighborUpdates) {
this.levelData = levelData;
this.dimensionTypeRegistration = dimensionTypeRegistration;
this.dimension = dimension;
this.isClientSide = isClientSide;
this.thread = Thread.currentThread();
this.biomeManager = new BiomeManager(this, biomeZoomSeed);
this.isDebug = isDebug;
this.neighborUpdater = new CollectingNeighborUpdater(this, maxChainedNeighborUpdates);
this.registryAccess = registryAccess;
this.palettedContainerFactory = PalettedContainerFactory.create(registryAccess);
this.damageSources = new DamageSources(registryAccess);
}
@Override
public boolean isClientSide() {
return this.isClientSide;
}
@Override
public @Nullable MinecraftServer getServer() {
return null;
}
public boolean isInWorldBounds(BlockPos pos) {
return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos);
}
public static boolean isInSpawnableBounds(BlockPos pos) {
return !Level.isOutsideSpawnableHeight(pos.getY()) && Level.isInWorldBoundsHorizontal(pos);
}
private static boolean isInWorldBoundsHorizontal(BlockPos pos) {
return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000;
}
private static boolean isOutsideSpawnableHeight(int y) {
return y < -20000000 || y >= 20000000;
}
public LevelChunk getChunkAt(BlockPos pos) {
return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
}
@Override
public LevelChunk getChunk(int chunkX, int chunkZ) {
return (LevelChunk)this.getChunk(chunkX, chunkZ, ChunkStatus.FULL);
}
@Override
public @Nullable ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus status, boolean loadOrGenerate) {
ChunkAccess chunk = this.getChunkSource().getChunk(chunkX, chunkZ, status, loadOrGenerate);
if (chunk == null && loadOrGenerate) {
throw new IllegalStateException("Should always be able to create a chunk!");
}
return chunk;
}
@Override
public boolean setBlock(BlockPos pos, BlockState blockState, @Block.UpdateFlags int updateFlags) {
return this.setBlock(pos, blockState, updateFlags, 512);
}
@Override
public boolean setBlock(BlockPos pos, BlockState blockState, @Block.UpdateFlags int updateFlags, int updateLimit) {
if (this.isOutsideBuildHeight(pos)) {
return false;
}
if (!this.isClientSide() && this.isDebug()) {
return false;
}
LevelChunk chunk = this.getChunkAt(pos);
Block block = blockState.getBlock();
BlockState oldState = chunk.setBlockState(pos, blockState, updateFlags);
if (oldState != null) {
BlockState newState = this.getBlockState(pos);
if (newState == blockState) {
if (oldState != newState) {
this.setBlocksDirty(pos, oldState, newState);
}
if ((updateFlags & 2) != 0 && (!this.isClientSide() || (updateFlags & 4) == 0) && (this.isClientSide() || chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) {
this.sendBlockUpdated(pos, oldState, blockState, updateFlags);
}
if ((updateFlags & 1) != 0) {
this.updateNeighborsAt(pos, oldState.getBlock());
if (!this.isClientSide() && blockState.hasAnalogOutputSignal()) {
this.updateNeighbourForOutputSignal(pos, block);
}
}
if ((updateFlags & 0x10) == 0 && updateLimit > 0) {
int neighbourUpdateFlags = updateFlags & 0xFFFFFFDE;
oldState.updateIndirectNeighbourShapes(this, pos, neighbourUpdateFlags, updateLimit - 1);
blockState.updateNeighbourShapes(this, pos, neighbourUpdateFlags, updateLimit - 1);
blockState.updateIndirectNeighbourShapes(this, pos, neighbourUpdateFlags, updateLimit - 1);
}
this.updatePOIOnBlockStateChange(pos, oldState, newState);
}
return true;
}
return false;
}
public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
}
@Override
public boolean removeBlock(BlockPos pos, boolean movedByPiston) {
FluidState fluidState = this.getFluidState(pos);
return this.setBlock(pos, fluidState.createLegacyBlock(), 3 | (movedByPiston ? 64 : 0));
}
@Override
public boolean destroyBlock(BlockPos pos, boolean dropResources, @Nullable Entity breaker, int updateLimit) {
boolean destroyed;
BlockState blockState = this.getBlockState(pos);
if (blockState.isAir()) {
return false;
}
FluidState fluidState = this.getFluidState(pos);
if (!(blockState.getBlock() instanceof BaseFireBlock)) {
this.levelEvent(2001, pos, Block.getId(blockState));
}
if (dropResources) {
BlockEntity blockEntity = blockState.hasBlockEntity() ? this.getBlockEntity(pos) : null;
Block.dropResources(blockState, this, pos, blockEntity, breaker, ItemStack.EMPTY);
}
if (destroyed = this.setBlock(pos, fluidState.createLegacyBlock(), 3, updateLimit)) {
this.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(breaker, blockState));
}
return destroyed;
}
public void addDestroyBlockEffect(BlockPos pos, BlockState blockState) {
}
public boolean setBlockAndUpdate(BlockPos pos, BlockState blockState) {
return this.setBlock(pos, blockState, 3);
}
public abstract void sendBlockUpdated(BlockPos var1, BlockState var2, BlockState var3, int var4);
public void setBlocksDirty(BlockPos pos, BlockState oldState, BlockState newState) {
}
public void updateNeighborsAt(BlockPos pos, Block sourceBlock, @Nullable Orientation orientation) {
}
public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block blockObject, Direction skipDirection, @Nullable Orientation orientation) {
}
public void neighborChanged(BlockPos pos, Block changedBlock, @Nullable Orientation orientation) {
}
public void neighborChanged(BlockState state, BlockPos pos, Block changedBlock, @Nullable Orientation orientation, boolean movedByPiston) {
}
@Override
public void neighborShapeChanged(Direction direction, BlockPos pos, BlockPos neighborPos, BlockState neighborState, @Block.UpdateFlags int updateFlags, int updateLimit) {
this.neighborUpdater.shapeUpdate(direction, neighborState, pos, neighborPos, updateFlags, updateLimit);
}
@Override
public int getHeight(Heightmap.Types type, int x, int z) {
int y = x < -30000000 || z < -30000000 || x >= 30000000 || z >= 30000000 ? this.getSeaLevel() + 1 : (this.hasChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z)) ? this.getChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z)).getHeight(type, x & 0xF, z & 0xF) + 1 : this.getMinY());
return y;
}
@Override
public LevelLightEngine getLightEngine() {
return this.getChunkSource().getLightEngine();
}
@Override
public BlockState getBlockState(BlockPos pos) {
if (this.isOutsideBuildHeight(pos)) {
return Blocks.VOID_AIR.defaultBlockState();
}
LevelChunk chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
return chunk.getBlockState(pos);
}
@Override
public FluidState getFluidState(BlockPos pos) {
if (this.isOutsideBuildHeight(pos)) {
return Fluids.EMPTY.defaultFluidState();
}
LevelChunk chunk = this.getChunkAt(pos);
return chunk.getFluidState(pos);
}
public boolean isBrightOutside() {
return !this.dimensionType().hasFixedTime() && this.skyDarken < 4;
}
public boolean isDarkOutside() {
return !this.dimensionType().hasFixedTime() && !this.isBrightOutside();
}
@Override
public void playSound(@Nullable Entity except, BlockPos pos, SoundEvent sound, SoundSource source, float volume, float pitch) {
this.playSound(except, (double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, sound, source, volume, pitch);
}
public abstract void playSeededSound(@Nullable Entity var1, double var2, double var4, double var6, Holder<SoundEvent> var8, SoundSource var9, float var10, float var11, long var12);
public void playSeededSound(@Nullable Entity except, double x, double y, double z, SoundEvent sound, SoundSource source, float volume, float pitch, long seed) {
this.playSeededSound(except, x, y, z, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), source, volume, pitch, seed);
}
public abstract void playSeededSound(@Nullable Entity var1, Entity var2, Holder<SoundEvent> var3, SoundSource var4, float var5, float var6, long var7);
public void playSound(@Nullable Entity except, double x, double y, double z, SoundEvent sound, SoundSource source) {
this.playSound(except, x, y, z, sound, source, 1.0f, 1.0f);
}
public void playSound(@Nullable Entity except, double x, double y, double z, SoundEvent sound, SoundSource source, float volume, float pitch) {
this.playSeededSound(except, x, y, z, sound, source, volume, pitch, this.threadSafeRandom.nextLong());
}
public void playSound(@Nullable Entity except, double x, double y, double z, Holder<SoundEvent> sound, SoundSource source, float volume, float pitch) {
this.playSeededSound(except, x, y, z, sound, source, volume, pitch, this.threadSafeRandom.nextLong());
}
public void playSound(@Nullable Entity except, Entity sourceEntity, SoundEvent sound, SoundSource source, float volume, float pitch) {
this.playSeededSound(except, sourceEntity, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), source, volume, pitch, this.threadSafeRandom.nextLong());
}
public void playLocalSound(BlockPos pos, SoundEvent sound, SoundSource source, float volume, float pitch, boolean distanceDelay) {
this.playLocalSound((double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, sound, source, volume, pitch, distanceDelay);
}
public void playLocalSound(Entity sourceEntity, SoundEvent sound, SoundSource source, float volume, float pitch) {
}
public void playLocalSound(double x, double y, double z, SoundEvent sound, SoundSource source, float volume, float pitch, boolean distanceDelay) {
}
public void playPlayerSound(SoundEvent sound, SoundSource source, float volume, float pitch) {
}
@Override
public void addParticle(ParticleOptions particle, double x, double y, double z, double xd, double yd, double zd) {
}
public void addParticle(ParticleOptions particle, boolean overrideLimiter, boolean alwaysShow, double x, double y, double z, double xd, double yd, double zd) {
}
public void addAlwaysVisibleParticle(ParticleOptions particle, double x, double y, double z, double xd, double yd, double zd) {
}
public void addAlwaysVisibleParticle(ParticleOptions particle, boolean overrideLimiter, double x, double y, double z, double xd, double yd, double zd) {
}
public void addBlockEntityTicker(TickingBlockEntity ticker) {
(this.tickingBlockEntities ? this.pendingBlockEntityTickers : this.blockEntityTickers).add(ticker);
}
public void tickBlockEntities() {
this.tickingBlockEntities = true;
if (!this.pendingBlockEntityTickers.isEmpty()) {
this.blockEntityTickers.addAll(this.pendingBlockEntityTickers);
this.pendingBlockEntityTickers.clear();
}
Iterator<TickingBlockEntity> iterator = this.blockEntityTickers.iterator();
boolean tickBlockEntities = this.tickRateManager().runsNormally();
while (iterator.hasNext()) {
TickingBlockEntity ticker = iterator.next();
if (ticker.isRemoved()) {
iterator.remove();
continue;
}
if (!tickBlockEntities || !this.shouldTickBlocksAt(ticker.getPos())) continue;
ticker.tick();
}
this.tickingBlockEntities = false;
}
public <T extends Entity> void guardEntityTick(Consumer<T> tick, T entity) {
try {
tick.accept(entity);
}
catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "Ticking entity");
CrashReportCategory category = report.addCategory("Entity being ticked");
entity.fillCrashReportCategory(category);
throw new ReportedException(report);
}
}
public boolean shouldTickDeath(Entity entity) {
return true;
}
public boolean shouldTickBlocksAt(long chunkPos) {
return true;
}
public boolean shouldTickBlocksAt(BlockPos pos) {
return this.shouldTickBlocksAt(ChunkPos.asLong(pos));
}
public void explode(@Nullable Entity source, double x, double y, double z, float r, ExplosionInteraction blockInteraction) {
this.explode(source, Explosion.getDefaultDamageSource(this, source), null, x, y, z, r, false, blockInteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, DEFAULT_EXPLOSION_BLOCK_PARTICLES, SoundEvents.GENERIC_EXPLODE);
}
public void explode(@Nullable Entity source, double x, double y, double z, float r, boolean fire, ExplosionInteraction blockInteraction) {
this.explode(source, Explosion.getDefaultDamageSource(this, source), null, x, y, z, r, fire, blockInteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, DEFAULT_EXPLOSION_BLOCK_PARTICLES, SoundEvents.GENERIC_EXPLODE);
}
public void explode(@Nullable Entity source, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator damageCalculator, Vec3 boomPos, float r, boolean fire, ExplosionInteraction blockInteraction) {
this.explode(source, damageSource, damageCalculator, boomPos.x(), boomPos.y(), boomPos.z(), r, fire, blockInteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, DEFAULT_EXPLOSION_BLOCK_PARTICLES, SoundEvents.GENERIC_EXPLODE);
}
public void explode(@Nullable Entity source, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator damageCalculator, double x, double y, double z, float r, boolean fire, ExplosionInteraction interactionType) {
this.explode(source, damageSource, damageCalculator, x, y, z, r, fire, interactionType, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, DEFAULT_EXPLOSION_BLOCK_PARTICLES, SoundEvents.GENERIC_EXPLODE);
}
public abstract void explode(@Nullable Entity var1, @Nullable DamageSource var2, @Nullable ExplosionDamageCalculator var3, double var4, double var6, double var8, float var10, boolean var11, ExplosionInteraction var12, ParticleOptions var13, ParticleOptions var14, WeightedList<ExplosionParticleInfo> var15, Holder<SoundEvent> var16);
public abstract String gatherChunkSourceStats();
@Override
public @Nullable BlockEntity getBlockEntity(BlockPos pos) {
if (this.isOutsideBuildHeight(pos)) {
return null;
}
if (!this.isClientSide() && Thread.currentThread() != this.thread) {
return null;
}
return this.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE);
}
public void setBlockEntity(BlockEntity blockEntity) {
BlockPos pos = blockEntity.getBlockPos();
if (this.isOutsideBuildHeight(pos)) {
return;
}
this.getChunkAt(pos).addAndRegisterBlockEntity(blockEntity);
}
public void removeBlockEntity(BlockPos pos) {
if (this.isOutsideBuildHeight(pos)) {
return;
}
this.getChunkAt(pos).removeBlockEntity(pos);
}
public boolean isLoaded(BlockPos pos) {
if (this.isOutsideBuildHeight(pos)) {
return false;
}
return this.getChunkSource().hasChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
}
public boolean loadedAndEntityCanStandOnFace(BlockPos pos, Entity entity, Direction faceDirection) {
if (this.isOutsideBuildHeight(pos)) {
return false;
}
ChunkAccess chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false);
if (chunk == null) {
return false;
}
return chunk.getBlockState(pos).entityCanStandOnFace(this, pos, entity, faceDirection);
}
public boolean loadedAndEntityCanStandOn(BlockPos pos, Entity entity) {
return this.loadedAndEntityCanStandOnFace(pos, entity, Direction.UP);
}
public void updateSkyBrightness() {
this.skyDarken = (int)(15.0f - this.environmentAttributes().getDimensionValue(EnvironmentAttributes.SKY_LIGHT_LEVEL).floatValue());
}
public void setSpawnSettings(boolean spawnEnemies) {
this.getChunkSource().setSpawnSettings(spawnEnemies);
}
public abstract void setRespawnData(LevelData.RespawnData var1);
public abstract LevelData.RespawnData getRespawnData();
public LevelData.RespawnData getWorldBorderAdjustedRespawnData(LevelData.RespawnData respawnData) {
WorldBorder worldBorder = this.getWorldBorder();
if (!worldBorder.isWithinBounds(respawnData.pos())) {
BlockPos newPos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, BlockPos.containing(worldBorder.getCenterX(), 0.0, worldBorder.getCenterZ()));
return LevelData.RespawnData.of(respawnData.dimension(), newPos, respawnData.yaw(), respawnData.pitch());
}
return respawnData;
}
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.getChunkSource().close();
}
@Override
public @Nullable BlockGetter getChunkForCollisions(int chunkX, int chunkZ) {
return this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, false);
}
@Override
public List<Entity> getEntities(@Nullable Entity except, AABB bb, Predicate<? super Entity> selector) {
Profiler.get().incrementCounter("getEntities");
ArrayList output = Lists.newArrayList();
this.getEntities().get(bb, entity -> {
if (entity != except && selector.test((Entity)entity)) {
output.add(entity);
}
});
for (EnderDragonPart dragonPart : this.dragonParts()) {
if (dragonPart == except || dragonPart.parentMob == except || !selector.test(dragonPart) || !bb.intersects(dragonPart.getBoundingBox())) continue;
output.add(dragonPart);
}
return output;
}
@Override
public <T extends Entity> List<T> getEntities(EntityTypeTest<Entity, T> type, AABB bb, Predicate<? super T> selector) {
ArrayList output = Lists.newArrayList();
this.getEntities(type, bb, selector, output);
return output;
}
public <T extends Entity> void getEntities(EntityTypeTest<Entity, T> type, AABB bb, Predicate<? super T> selector, List<? super T> output) {
this.getEntities(type, bb, selector, output, Integer.MAX_VALUE);
}
public <T extends Entity> void getEntities(EntityTypeTest<Entity, T> type, AABB bb, Predicate<? super T> selector, List<? super T> output, int maxResults) {
Profiler.get().incrementCounter("getEntities");
this.getEntities().get(type, bb, e -> {
if (selector.test(e)) {
output.add((Object)e);
if (output.size() >= maxResults) {
return AbortableIterationConsumer.Continuation.ABORT;
}
}
if (e instanceof EnderDragon) {
EnderDragon enderDragon = (EnderDragon)e;
for (EnderDragonPart subEntity : enderDragon.getSubEntities()) {
Entity castSubPart = (Entity)type.tryCast(subEntity);
if (castSubPart == null || !selector.test(castSubPart)) continue;
output.add((Object)castSubPart);
if (output.size() < maxResults) continue;
return AbortableIterationConsumer.Continuation.ABORT;
}
}
return AbortableIterationConsumer.Continuation.CONTINUE;
});
}
public <T extends Entity> boolean hasEntities(EntityTypeTest<Entity, T> type, AABB bb, Predicate<? super T> selector) {
Profiler.get().incrementCounter("hasEntities");
MutableBoolean hasEntities = new MutableBoolean();
this.getEntities().get(type, bb, e -> {
if (selector.test(e)) {
hasEntities.setTrue();
return AbortableIterationConsumer.Continuation.ABORT;
}
if (e instanceof EnderDragon) {
EnderDragon enderDragon = (EnderDragon)e;
for (EnderDragonPart subEntity : enderDragon.getSubEntities()) {
Entity castSubPart = (Entity)type.tryCast(subEntity);
if (castSubPart == null || !selector.test(castSubPart)) continue;
hasEntities.setTrue();
return AbortableIterationConsumer.Continuation.ABORT;
}
}
return AbortableIterationConsumer.Continuation.CONTINUE;
});
return hasEntities.isTrue();
}
public List<Entity> getPushableEntities(Entity pusher, AABB boundingBox) {
return this.getEntities(pusher, boundingBox, EntitySelector.pushableBy(pusher));
}
public abstract @Nullable Entity getEntity(int var1);
public @Nullable Entity getEntity(UUID uuid) {
return this.getEntities().get(uuid);
}
public @Nullable Entity getEntityInAnyDimension(UUID uuid) {
return this.getEntity(uuid);
}
public @Nullable Player getPlayerInAnyDimension(UUID uuid) {
return this.getPlayerByUUID(uuid);
}
public abstract Collection<EnderDragonPart> dragonParts();
public void blockEntityChanged(BlockPos pos) {
if (this.hasChunkAt(pos)) {
this.getChunkAt(pos).markUnsaved();
}
}
public void onBlockEntityAdded(BlockEntity blockEntity) {
}
public long getDayTime() {
return this.levelData.getDayTime();
}
public boolean mayInteract(Entity entity, BlockPos pos) {
return true;
}
public void broadcastEntityEvent(Entity entity, byte event) {
}
public void broadcastDamageEvent(Entity entity, DamageSource source) {
}
public void blockEvent(BlockPos pos, Block block, int b0, int b1) {
this.getBlockState(pos).triggerEvent(this, pos, b0, b1);
}
@Override
public LevelData getLevelData() {
return this.levelData;
}
public abstract TickRateManager tickRateManager();
public float getThunderLevel(float a) {
return Mth.lerp(a, this.oThunderLevel, this.thunderLevel) * this.getRainLevel(a);
}
public void setThunderLevel(float thunderLevel) {
float clampedThunderLevel;
this.oThunderLevel = clampedThunderLevel = Mth.clamp(thunderLevel, 0.0f, 1.0f);
this.thunderLevel = clampedThunderLevel;
}
public float getRainLevel(float a) {
return Mth.lerp(a, this.oRainLevel, this.rainLevel);
}
public void setRainLevel(float rainLevel) {
float clampedRainLevel;
this.oRainLevel = clampedRainLevel = Mth.clamp(rainLevel, 0.0f, 1.0f);
this.rainLevel = clampedRainLevel;
}
public boolean canHaveWeather() {
return this.dimensionType().hasSkyLight() && !this.dimensionType().hasCeiling() && this.dimension() != END;
}
public boolean isThundering() {
return this.canHaveWeather() && (double)this.getThunderLevel(1.0f) > 0.9;
}
public boolean isRaining() {
return this.canHaveWeather() && (double)this.getRainLevel(1.0f) > 0.2;
}
public boolean isRainingAt(BlockPos pos) {
return this.precipitationAt(pos) == Biome.Precipitation.RAIN;
}
public Biome.Precipitation precipitationAt(BlockPos pos) {
if (!this.isRaining()) {
return Biome.Precipitation.NONE;
}
if (!this.canSeeSky(pos)) {
return Biome.Precipitation.NONE;
}
if (this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos).getY() > pos.getY()) {
return Biome.Precipitation.NONE;
}
Biome biome = this.getBiome(pos).value();
return biome.getPrecipitationAt(pos, this.getSeaLevel());
}
public abstract @Nullable MapItemSavedData getMapData(MapId var1);
public void globalLevelEvent(int type, BlockPos pos, int data) {
}
public CrashReportCategory fillReportDetails(CrashReport report) {
CrashReportCategory category = report.addCategory("Affected level", 1);
category.setDetail("All players", () -> {
List<? extends Player> players = this.players();
return players.size() + " total; " + players.stream().map(Player::debugInfo).collect(Collectors.joining(", "));
});
category.setDetail("Chunk stats", this.getChunkSource()::gatherStats);
category.setDetail("Level dimension", () -> this.dimension().identifier().toString());
try {
this.levelData.fillCrashReportCategory(category, this);
}
catch (Throwable t) {
category.setDetailError("Level Data Unobtainable", t);
}
return category;
}
public abstract void destroyBlockProgress(int var1, BlockPos var2, int var3);
public void createFireworks(double x, double y, double z, double xd, double yd, double zd, List<FireworkExplosion> explosions) {
}
public abstract Scoreboard getScoreboard();
public void updateNeighbourForOutputSignal(BlockPos pos, Block changedBlock) {
for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos relativePos = pos.relative(direction);
if (!this.hasChunkAt(relativePos)) continue;
BlockState state = this.getBlockState(relativePos);
if (state.is(Blocks.COMPARATOR)) {
this.neighborChanged(state, relativePos, changedBlock, null, false);
continue;
}
if (!state.isRedstoneConductor(this, relativePos) || !(state = this.getBlockState(relativePos = relativePos.relative(direction))).is(Blocks.COMPARATOR)) continue;
this.neighborChanged(state, relativePos, changedBlock, null, false);
}
}
@Override
public int getSkyDarken() {
return this.skyDarken;
}
public void setSkyFlashTime(int skyFlashTime) {
}
public void sendPacketToServer(Packet<?> packet) {
throw new UnsupportedOperationException("Can't send packets to server unless you're on the client.");
}
@Override
public DimensionType dimensionType() {
return this.dimensionTypeRegistration.value();
}
public Holder<DimensionType> dimensionTypeRegistration() {
return this.dimensionTypeRegistration;
}
public ResourceKey<Level> dimension() {
return this.dimension;
}
@Override
public RandomSource getRandom() {
return this.random;
}
@Override
public boolean isStateAtPosition(BlockPos pos, Predicate<BlockState> predicate) {
return predicate.test(this.getBlockState(pos));
}
@Override
public boolean isFluidAtPosition(BlockPos pos, Predicate<FluidState> predicate) {
return predicate.test(this.getFluidState(pos));
}
public abstract RecipeAccess recipeAccess();
public BlockPos getBlockRandomPos(int xo, int yo, int zo, int yMask) {
this.randValue = this.randValue * 3 + 1013904223;
int val = this.randValue >> 2;
return new BlockPos(xo + (val & 0xF), yo + (val >> 16 & yMask), zo + (val >> 8 & 0xF));
}
public boolean noSave() {
return false;
}
@Override
public BiomeManager getBiomeManager() {
return this.biomeManager;
}
public final boolean isDebug() {
return this.isDebug;
}
protected abstract LevelEntityGetter<Entity> getEntities();
@Override
public long nextSubTickCount() {
return this.subTickCount++;
}
@Override
public RegistryAccess registryAccess() {
return this.registryAccess;
}
public DamageSources damageSources() {
return this.damageSources;
}
@Override
public abstract EnvironmentAttributeSystem environmentAttributes();
public abstract PotionBrewing potionBrewing();
public abstract FuelValues fuelValues();
public int getClientLeafTintColor(BlockPos pos) {
return 0;
}
public PalettedContainerFactory palettedContainerFactory() {
return this.palettedContainerFactory;
}
public static enum ExplosionInteraction implements StringRepresentable
{
NONE("none"),
BLOCK("block"),
MOB("mob"),
TNT("tnt"),
TRIGGER("trigger");
public static final Codec<ExplosionInteraction> CODEC;
private final String id;
private ExplosionInteraction(String id) {
this.id = id;
}
@Override
public String getSerializedName() {
return this.id;
}
static {
CODEC = StringRepresentable.fromEnum(ExplosionInteraction::values);
}
}
}