package net.minecraft.server.level;

import net.minecraft.world.level.ChunkPos;
import javax.annotation.Nullable;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.block.Block;
import net.minecraft.tags.Tag;
import net.minecraft.tags.BlockTags;
import net.minecraft.core.BlockPos;

public class PlayerRespawnLogic {
    @Nullable
    protected static BlockPos getOverworldRespawnPos(final ServerLevel zd, final int integer2, final int integer3, final boolean boolean4) {
        final BlockPos.MutableBlockPos a5 = new BlockPos.MutableBlockPos(integer2, 0, integer3);
        final Biome bre6 = zd.getBiome(a5);
        final boolean boolean5 = zd.dimensionType().hasCeiling();
        final BlockState cfj8 = bre6.getSurfaceBuilderConfig().getTopMaterial();
        if (boolean4 && !cfj8.getBlock().is(BlockTags.VALID_SPAWN)) {
            return null;
        }
        final LevelChunk chj9 = zd.getChunk(integer2 >> 4, integer3 >> 4);
        final int integer4 = boolean5 ? zd.getChunkSource().getGenerator().getSpawnHeight() : chj9.getHeight(Heightmap.Types.MOTION_BLOCKING, integer2 & 0xF, integer3 & 0xF);
        if (integer4 < 0) {
            return null;
        }
        final int integer5 = chj9.getHeight(Heightmap.Types.WORLD_SURFACE, integer2 & 0xF, integer3 & 0xF);
        if (integer5 <= integer4 && integer5 > chj9.getHeight(Heightmap.Types.OCEAN_FLOOR, integer2 & 0xF, integer3 & 0xF)) {
            return null;
        }
        for (int integer6 = integer4 + 1; integer6 >= 0; --integer6) {
            a5.set(integer2, integer6, integer3);
            final BlockState cfj9 = zd.getBlockState(a5);
            if (!cfj9.getFluidState().isEmpty()) {
                break;
            }
            if (cfj9.equals(cfj8)) {
                return a5.above().immutable();
            }
        }
        return null;
    }
    
    @Nullable
    public static BlockPos getSpawnPosInChunk(final ServerLevel zd, final ChunkPos bph, final boolean boolean3) {
        for (int integer4 = bph.getMinBlockX(); integer4 <= bph.getMaxBlockX(); ++integer4) {
            for (int integer5 = bph.getMinBlockZ(); integer5 <= bph.getMaxBlockZ(); ++integer5) {
                final BlockPos fu6 = getOverworldRespawnPos(zd, integer4, integer5, boolean3);
                if (fu6 != null) {
                    return fu6;
                }
            }
        }
        return null;
    }
}
