package net.minecraft.world.level.block;

import net.minecraft.world.item.DyeColor;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.CacheBuilder;
import org.apache.logging.log4j.LogManager;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.phys.Vec3;
import net.minecraft.util.Mth;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.Util;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.stats.Stat;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import java.util.Collections;
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.core.Registry;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.MenuProvider;
import net.minecraft.network.protocol.game.DebugPackets;
import java.util.Random;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.Tag;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.entity.EntityType;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.item.BlockItem;
import it.unimi.dsi.fastutil.objects.Object2ByteLinkedOpenHashMap;
import net.minecraft.world.item.Item;
import javax.annotation.Nullable;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.shapes.VoxelShape;
import com.google.common.cache.LoadingCache;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.IdMapper;
import org.apache.logging.log4j.Logger;
import net.minecraft.world.level.ItemLike;

public class Block implements ItemLike {
    protected static final Logger LOGGER;
    public static final IdMapper<BlockState> BLOCK_STATE_REGISTRY;
    private static final Direction[] UPDATE_SHAPE_ORDER;
    private static final LoadingCache<VoxelShape, Boolean> SHAPE_FULL_BLOCK_CACHE;
    private static final VoxelShape RIGID_SUPPORT_SHAPE;
    private static final VoxelShape CENTER_SUPPORT_SHAPE;
    protected final int lightEmission;
    protected final float destroySpeed;
    protected final float explosionResistance;
    protected final boolean isTicking;
    protected final SoundType soundType;
    protected final Material material;
    protected final MaterialColor materialColor;
    private final float friction;
    private final float speedFactor;
    private final float jumpFactor;
    protected final StateDefinition<Block, BlockState> stateDefinition;
    private BlockState defaultBlockState;
    protected final boolean hasCollision;
    private final boolean dynamicShape;
    private final boolean canOcclude;
    @Nullable
    private ResourceLocation drops;
    @Nullable
    private String descriptionId;
    @Nullable
    private Item item;
    private static final ThreadLocal<Object2ByteLinkedOpenHashMap<BlockStatePairKey>> OCCLUSION_CACHE;
    
    public static int getId(@Nullable final BlockState byj) {
        if (byj == null) {
            return 0;
        }
        final int integer2 = Block.BLOCK_STATE_REGISTRY.getId(byj);
        return (integer2 == -1) ? 0 : integer2;
    }
    
    public static BlockState stateById(final int integer) {
        final BlockState byj2 = Block.BLOCK_STATE_REGISTRY.byId(integer);
        return (byj2 == null) ? Blocks.AIR.defaultBlockState() : byj2;
    }
    
    public static Block byItem(@Nullable final Item bei) {
        if (bei instanceof BlockItem) {
            return ((BlockItem)bei).getBlock();
        }
        return Blocks.AIR;
    }
    
    public static BlockState pushEntitiesUp(final BlockState byj1, final BlockState byj2, final Level bjw, final BlockPos fk) {
        final VoxelShape cwf5 = Shapes.joinUnoptimized(byj1.getCollisionShape(bjw, fk), byj2.getCollisionShape(bjw, fk), BooleanOp.ONLY_SECOND).move(fk.getX(), fk.getY(), fk.getZ());
        final List<Entity> list6 = bjw.getEntities(null, cwf5.bounds());
        for (final Entity akq8 : list6) {
            final double double9 = Shapes.collide(Direction.Axis.Y, akq8.getBoundingBox().move(0.0, 1.0, 0.0), Stream.<VoxelShape>of(cwf5), -1.0);
            akq8.teleportTo(akq8.getX(), akq8.getY() + 1.0 + double9, akq8.getZ());
        }
        return byj2;
    }
    
    public static VoxelShape box(final double double1, final double double2, final double double3, final double double4, final double double5, final double double6) {
        return Shapes.box(double1 / 16.0, double2 / 16.0, double3 / 16.0, double4 / 16.0, double5 / 16.0, double6 / 16.0);
    }
    
    @Deprecated
    public boolean isValidSpawn(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final EntityType<?> aku) {
        return byj.isFaceSturdy(bjg, fk, Direction.UP) && this.lightEmission < 14;
    }
    
    @Deprecated
    public boolean isAir(final BlockState byj) {
        return false;
    }
    
    @Deprecated
    public int getLightEmission(final BlockState byj) {
        return this.lightEmission;
    }
    
    @Deprecated
    public Material getMaterial(final BlockState byj) {
        return this.material;
    }
    
    @Deprecated
    public MaterialColor getMapColor(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return this.materialColor;
    }
    
    @Deprecated
    public void updateNeighbourShapes(final BlockState byj, final LevelAccessor bjx, final BlockPos fk, final int integer) {
        try (final BlockPos.PooledMutableBlockPos b6 = BlockPos.PooledMutableBlockPos.acquire()) {
            for (final Direction fp11 : Block.UPDATE_SHAPE_ORDER) {
                b6.set((Vec3i)fk).move(fp11);
                final BlockState byj2 = bjx.getBlockState(b6);
                final BlockState byj3 = byj2.updateShape(fp11.getOpposite(), byj, bjx, b6, fk);
                updateOrDestroy(byj2, byj3, bjx, b6, integer);
            }
        }
    }
    
    public boolean is(final Tag<Block> aaz) {
        return aaz.contains(this);
    }
    
    public static BlockState updateFromNeighbourShapes(final BlockState byj, final LevelAccessor bjx, final BlockPos fk) {
        BlockState byj2 = byj;
        final BlockPos.MutableBlockPos a5 = new BlockPos.MutableBlockPos();
        for (final Direction fp9 : Block.UPDATE_SHAPE_ORDER) {
            a5.set(fk).move(fp9);
            byj2 = byj2.updateShape(fp9, bjx.getBlockState(a5), bjx, fk, a5);
        }
        return byj2;
    }
    
    public static void updateOrDestroy(final BlockState byj1, final BlockState byj2, final LevelAccessor bjx, final BlockPos fk, final int integer) {
        if (byj2 != byj1) {
            if (byj2.isAir()) {
                if (!bjx.isClientSide()) {
                    bjx.destroyBlock(fk, (integer & 0x20) == 0x0);
                }
            }
            else {
                bjx.setBlock(fk, byj2, integer & 0xFFFFFFDF);
            }
        }
    }
    
    @Deprecated
    public void updateIndirectNeighbourShapes(final BlockState byj, final LevelAccessor bjx, final BlockPos fk, final int integer) {
    }
    
    @Deprecated
    public BlockState updateShape(final BlockState byj1, final Direction fp, final BlockState byj3, final LevelAccessor bjx, final BlockPos fk5, final BlockPos fk6) {
        return byj1;
    }
    
    @Deprecated
    public BlockState rotate(final BlockState byj, final Rotation btu) {
        return byj;
    }
    
    @Deprecated
    public BlockState mirror(final BlockState byj, final Mirror bsu) {
        return byj;
    }
    
    public Block(final Properties c) {
        final StateDefinition.Builder<Block, BlockState> a3 = new StateDefinition.Builder<Block, BlockState>(this);
        this.createBlockStateDefinition(a3);
        this.material = c.material;
        this.materialColor = c.materialColor;
        this.hasCollision = c.hasCollision;
        this.soundType = c.soundType;
        this.lightEmission = c.lightEmission;
        this.explosionResistance = c.explosionResistance;
        this.destroySpeed = c.destroyTime;
        this.isTicking = c.isTicking;
        this.friction = c.friction;
        this.speedFactor = c.speedFactor;
        this.jumpFactor = c.jumpFactor;
        this.dynamicShape = c.dynamicShape;
        this.drops = c.drops;
        this.canOcclude = c.canOcclude;
        this.stateDefinition = a3.<BlockState>create(BlockState::new);
        this.registerDefaultState(this.stateDefinition.any());
    }
    
    public static boolean isExceptionForConnection(final Block bph) {
        return bph instanceof LeavesBlock || bph == Blocks.BARRIER || bph == Blocks.CARVED_PUMPKIN || bph == Blocks.JACK_O_LANTERN || bph == Blocks.MELON || bph == Blocks.PUMPKIN || bph.is(BlockTags.SHULKER_BOXES);
    }
    
    @Deprecated
    public boolean isRedstoneConductor(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return byj.getMaterial().isSolidBlocking() && byj.isCollisionShapeFullBlock(bjg, fk) && !byj.isSignalSource();
    }
    
    @Deprecated
    public boolean isSuffocating(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return this.material.blocksMotion() && byj.isCollisionShapeFullBlock(bjg, fk);
    }
    
    @Deprecated
    public boolean isViewBlocking(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return byj.isSuffocating(bjg, fk);
    }
    
    @Deprecated
    public boolean isPathfindable(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final PathComputationType cqr) {
        switch (cqr) {
            case LAND: {
                return !byj.isCollisionShapeFullBlock(bjg, fk);
            }
            case WATER: {
                return bjg.getFluidState(fk).is(FluidTags.WATER);
            }
            case AIR: {
                return !byj.isCollisionShapeFullBlock(bjg, fk);
            }
            default: {
                return false;
            }
        }
    }
    
    @Deprecated
    public RenderShape getRenderShape(final BlockState byj) {
        return RenderShape.MODEL;
    }
    
    @Deprecated
    public boolean canBeReplaced(final BlockState byj, final BlockPlaceContext bcq) {
        return this.material.isReplaceable() && (bcq.getItemInHand().isEmpty() || bcq.getItemInHand().getItem() != this.asItem());
    }
    
    @Deprecated
    public boolean canBeReplaced(final BlockState byj, final Fluid coi) {
        return this.material.isReplaceable() || !this.material.isSolid();
    }
    
    @Deprecated
    public float getDestroySpeed(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return this.destroySpeed;
    }
    
    public boolean isRandomlyTicking(final BlockState byj) {
        return this.isTicking;
    }
    
    public boolean isEntityBlock() {
        return this instanceof EntityBlock;
    }
    
    @Deprecated
    public boolean hasPostProcess(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return false;
    }
    
    @Deprecated
    public boolean emissiveRendering(final BlockState byj) {
        return false;
    }
    
    public static boolean shouldRenderFace(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final Direction fp) {
        final BlockPos fk2 = fk.relative(fp);
        final BlockState byj2 = bjg.getBlockState(fk2);
        if (byj.skipRendering(byj2, fp)) {
            return false;
        }
        if (!byj2.canOcclude()) {
            return true;
        }
        final BlockStatePairKey a7 = new BlockStatePairKey(byj, byj2, fp);
        final Object2ByteLinkedOpenHashMap<BlockStatePairKey> object2ByteLinkedOpenHashMap8 = Block.OCCLUSION_CACHE.get();
        final byte byte9 = object2ByteLinkedOpenHashMap8.getAndMoveToFirst(a7);
        if (byte9 != 127) {
            return byte9 != 0;
        }
        final VoxelShape cwf10 = byj.getFaceOcclusionShape(bjg, fk, fp);
        final VoxelShape cwf11 = byj2.getFaceOcclusionShape(bjg, fk2, fp.getOpposite());
        final boolean boolean12 = Shapes.joinIsNotEmpty(cwf10, cwf11, BooleanOp.ONLY_FIRST);
        if (object2ByteLinkedOpenHashMap8.size() == 2048) {
            object2ByteLinkedOpenHashMap8.removeLastByte();
        }
        object2ByteLinkedOpenHashMap8.putAndMoveToFirst(a7, (byte)(byte)(boolean12 ? 1 : 0));
        return boolean12;
    }
    
    @Deprecated
    public final boolean canOcclude(final BlockState byj) {
        return this.canOcclude;
    }
    
    @Deprecated
    public boolean skipRendering(final BlockState byj1, final BlockState byj2, final Direction fp) {
        return false;
    }
    
    @Deprecated
    public VoxelShape getShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
        return Shapes.block();
    }
    
    @Deprecated
    public VoxelShape getCollisionShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
        return this.hasCollision ? byj.getShape(bjg, fk) : Shapes.empty();
    }
    
    @Deprecated
    public VoxelShape getOcclusionShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return byj.getShape(bjg, fk);
    }
    
    @Deprecated
    public VoxelShape getInteractionShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return Shapes.empty();
    }
    
    public static boolean canSupportRigidBlock(final BlockGetter bjg, final BlockPos fk) {
        final BlockState byj3 = bjg.getBlockState(fk);
        return !byj3.is(BlockTags.LEAVES) && !Shapes.joinIsNotEmpty(byj3.getCollisionShape(bjg, fk).getFaceShape(Direction.UP), Block.RIGID_SUPPORT_SHAPE, BooleanOp.ONLY_SECOND);
    }
    
    public static boolean canSupportCenter(final LevelReader bjz, final BlockPos fk, final Direction fp) {
        final BlockState byj4 = bjz.getBlockState(fk);
        return !byj4.is(BlockTags.LEAVES) && !Shapes.joinIsNotEmpty(byj4.getCollisionShape(bjz, fk).getFaceShape(fp), Block.CENTER_SUPPORT_SHAPE, BooleanOp.ONLY_SECOND);
    }
    
    public static boolean isFaceSturdy(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final Direction fp) {
        return !byj.is(BlockTags.LEAVES) && isFaceFull(byj.getCollisionShape(bjg, fk), fp);
    }
    
    public static boolean isFaceFull(final VoxelShape cwf, final Direction fp) {
        final VoxelShape cwf2 = cwf.getFaceShape(fp);
        return isShapeFullBlock(cwf2);
    }
    
    public static boolean isShapeFullBlock(final VoxelShape cwf) {
        return Block.SHAPE_FULL_BLOCK_CACHE.getUnchecked(cwf);
    }
    
    @Deprecated
    public final boolean isSolidRender(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return byj.canOcclude() && isShapeFullBlock(byj.getOcclusionShape(bjg, fk));
    }
    
    public boolean propagatesSkylightDown(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return !isShapeFullBlock(byj.getShape(bjg, fk)) && byj.getFluidState().isEmpty();
    }
    
    @Deprecated
    public int getLightBlock(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        if (byj.isSolidRender(bjg, fk)) {
            return bjg.getMaxLightLevel();
        }
        return byj.propagatesSkylightDown(bjg, fk) ? 0 : 1;
    }
    
    @Deprecated
    public boolean useShapeForLightOcclusion(final BlockState byj) {
        return false;
    }
    
    @Deprecated
    public void randomTick(final BlockState byj, final ServerLevel xd, final BlockPos fk, final Random random) {
        this.tick(byj, xd, fk, random);
    }
    
    @Deprecated
    public void tick(final BlockState byj, final ServerLevel xd, final BlockPos fk, final Random random) {
    }
    
    public void animateTick(final BlockState byj, final Level bjw, final BlockPos fk, final Random random) {
    }
    
    public void destroy(final LevelAccessor bjx, final BlockPos fk, final BlockState byj) {
    }
    
    @Deprecated
    public void neighborChanged(final BlockState byj, final Level bjw, final BlockPos fk3, final Block bph, final BlockPos fk5, final boolean boolean6) {
        DebugPackets.sendNeighborsUpdatePacket(bjw, fk3);
    }
    
    public int getTickDelay(final LevelReader bjz) {
        return 10;
    }
    
    @Nullable
    @Deprecated
    public MenuProvider getMenuProvider(final BlockState byj, final Level bjw, final BlockPos fk) {
        return null;
    }
    
    @Deprecated
    public void onPlace(final BlockState byj1, final Level bjw, final BlockPos fk, final BlockState byj4, final boolean boolean5) {
    }
    
    @Deprecated
    public void onRemove(final BlockState byj1, final Level bjw, final BlockPos fk, final BlockState byj4, final boolean boolean5) {
        if (this.isEntityBlock() && byj1.getBlock() != byj4.getBlock()) {
            bjw.removeBlockEntity(fk);
        }
    }
    
    @Deprecated
    public float getDestroyProgress(final BlockState byj, final Player ayj, final BlockGetter bjg, final BlockPos fk) {
        final float float6 = byj.getDestroySpeed(bjg, fk);
        if (float6 == -1.0f) {
            return 0.0f;
        }
        final int integer7 = ayj.canDestroy(byj) ? 30 : 100;
        return ayj.getDestroySpeed(byj) / float6 / integer7;
    }
    
    @Deprecated
    public void spawnAfterBreak(final BlockState byj, final Level bjw, final BlockPos fk, final ItemStack ben) {
    }
    
    public ResourceLocation getLootTable() {
        if (this.drops == null) {
            final ResourceLocation sm2 = Registry.BLOCK.getKey(this);
            this.drops = new ResourceLocation(sm2.getNamespace(), "blocks/" + sm2.getPath());
        }
        return this.drops;
    }
    
    @Deprecated
    public List<ItemStack> getDrops(final BlockState byj, final LootContext.Builder a) {
        final ResourceLocation sm4 = this.getLootTable();
        if (sm4 == BuiltInLootTables.EMPTY) {
            return Collections.<ItemStack>emptyList();
        }
        final LootContext crx5 = a.<BlockState>withParameter(LootContextParams.BLOCK_STATE, byj).create(LootContextParamSets.BLOCK);
        final ServerLevel xd6 = crx5.getLevel();
        final LootTable csa7 = xd6.getServer().getLootTables().get(sm4);
        return csa7.getRandomItems(crx5);
    }
    
    public static List<ItemStack> getDrops(final BlockState byj, final ServerLevel xd, final BlockPos fk, @Nullable final BlockEntity bwl) {
        final LootContext.Builder a5 = new LootContext.Builder(xd).withRandom(xd.random).<BlockPos>withParameter(LootContextParams.BLOCK_POS, fk).<ItemStack>withParameter(LootContextParams.TOOL, ItemStack.EMPTY).<BlockEntity>withOptionalParameter(LootContextParams.BLOCK_ENTITY, bwl);
        return byj.getDrops(a5);
    }
    
    public static List<ItemStack> getDrops(final BlockState byj, final ServerLevel xd, final BlockPos fk, @Nullable final BlockEntity bwl, @Nullable final Entity akq, final ItemStack ben) {
        final LootContext.Builder a7 = new LootContext.Builder(xd).withRandom(xd.random).<BlockPos>withParameter(LootContextParams.BLOCK_POS, fk).<ItemStack>withParameter(LootContextParams.TOOL, ben).<Entity>withOptionalParameter(LootContextParams.THIS_ENTITY, akq).<BlockEntity>withOptionalParameter(LootContextParams.BLOCK_ENTITY, bwl);
        return byj.getDrops(a7);
    }
    
    public static void dropResources(final BlockState byj, final Level bjw, final BlockPos fk) {
        if (bjw instanceof ServerLevel) {
            getDrops(byj, (ServerLevel)bjw, fk, null).forEach(ben -> popResource(bjw, fk, ben));
        }
        byj.spawnAfterBreak(bjw, fk, ItemStack.EMPTY);
    }
    
    public static void dropResources(final BlockState byj, final Level bjw, final BlockPos fk, @Nullable final BlockEntity bwl) {
        if (bjw instanceof ServerLevel) {
            getDrops(byj, (ServerLevel)bjw, fk, bwl).forEach(ben -> popResource(bjw, fk, ben));
        }
        byj.spawnAfterBreak(bjw, fk, ItemStack.EMPTY);
    }
    
    public static void dropResources(final BlockState byj, final Level bjw, final BlockPos fk, @Nullable final BlockEntity bwl, final Entity akq, final ItemStack ben) {
        if (bjw instanceof ServerLevel) {
            getDrops(byj, (ServerLevel)bjw, fk, bwl, akq, ben).forEach(ben -> popResource(bjw, fk, ben));
        }
        byj.spawnAfterBreak(bjw, fk, ben);
    }
    
    public static void popResource(final Level bjw, final BlockPos fk, final ItemStack ben) {
        if (bjw.isClientSide || ben.isEmpty() || !bjw.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
            return;
        }
        final float float4 = 0.5f;
        final double double5 = bjw.random.nextFloat() * 0.5f + 0.25;
        final double double6 = bjw.random.nextFloat() * 0.5f + 0.25;
        final double double7 = bjw.random.nextFloat() * 0.5f + 0.25;
        final ItemEntity awb11 = new ItemEntity(bjw, fk.getX() + double5, fk.getY() + double6, fk.getZ() + double7, ben);
        awb11.setDefaultPickUpDelay();
        bjw.addFreshEntity(awb11);
    }
    
    protected void popExperience(final Level bjw, final BlockPos fk, int integer) {
        if (!bjw.isClientSide && bjw.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
            while (integer > 0) {
                final int integer2 = ExperienceOrb.getExperienceValue(integer);
                integer -= integer2;
                bjw.addFreshEntity(new ExperienceOrb(bjw, fk.getX() + 0.5, fk.getY() + 0.5, fk.getZ() + 0.5, integer2));
            }
        }
    }
    
    public float getExplosionResistance() {
        return this.explosionResistance;
    }
    
    public void wasExploded(final Level bjw, final BlockPos fk, final Explosion bjp) {
    }
    
    @Deprecated
    public boolean canSurvive(final BlockState byj, final LevelReader bjz, final BlockPos fk) {
        return true;
    }
    
    @Deprecated
    public InteractionResult use(final BlockState byj, final Level bjw, final BlockPos fk, final Player ayj, final InteractionHand ajk, final BlockHitResult cvg) {
        return InteractionResult.PASS;
    }
    
    public void stepOn(final Level bjw, final BlockPos fk, final Entity akq) {
    }
    
    @Nullable
    public BlockState getStateForPlacement(final BlockPlaceContext bcq) {
        return this.defaultBlockState();
    }
    
    @Deprecated
    public void attack(final BlockState byj, final Level bjw, final BlockPos fk, final Player ayj) {
    }
    
    @Deprecated
    public int getSignal(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final Direction fp) {
        return 0;
    }
    
    @Deprecated
    public boolean isSignalSource(final BlockState byj) {
        return false;
    }
    
    @Deprecated
    public void entityInside(final BlockState byj, final Level bjw, final BlockPos fk, final Entity akq) {
    }
    
    @Deprecated
    public int getDirectSignal(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final Direction fp) {
        return 0;
    }
    
    public void playerDestroy(final Level bjw, final Player ayj, final BlockPos fk, final BlockState byj, @Nullable final BlockEntity bwl, final ItemStack ben) {
        ayj.awardStat(Stats.BLOCK_MINED.get(this));
        ayj.causeFoodExhaustion(0.005f);
        dropResources(byj, bjw, fk, bwl, ayj, ben);
    }
    
    public void setPlacedBy(final Level bjw, final BlockPos fk, final BlockState byj, @Nullable final LivingEntity akz, final ItemStack ben) {
    }
    
    public boolean isPossibleToRespawnInThis() {
        return !this.material.isSolid() && !this.material.isLiquid();
    }
    
    public Component getName() {
        return new TranslatableComponent(this.getDescriptionId(), new Object[0]);
    }
    
    public String getDescriptionId() {
        if (this.descriptionId == null) {
            this.descriptionId = Util.makeDescriptionId("block", Registry.BLOCK.getKey(this));
        }
        return this.descriptionId;
    }
    
    @Deprecated
    public boolean triggerEvent(final BlockState byj, final Level bjw, final BlockPos fk, final int integer4, final int integer5) {
        return false;
    }
    
    @Deprecated
    public PushReaction getPistonPushReaction(final BlockState byj) {
        return this.material.getPushReaction();
    }
    
    @Deprecated
    public float getShadeBrightness(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return byj.isCollisionShapeFullBlock(bjg, fk) ? 0.2f : 1.0f;
    }
    
    public void fallOn(final Level bjw, final BlockPos fk, final Entity akq, final float float4) {
        akq.causeFallDamage(float4, 1.0f);
    }
    
    public void updateEntityAfterFallOn(final BlockGetter bjg, final Entity akq) {
        akq.setDeltaMovement(akq.getDeltaMovement().multiply(1.0, 0.0, 1.0));
    }
    
    public ItemStack getCloneItemStack(final BlockGetter bjg, final BlockPos fk, final BlockState byj) {
        return new ItemStack(this);
    }
    
    public void fillItemCategory(final CreativeModeTab bdd, final NonNullList<ItemStack> fy) {
        fy.add(new ItemStack(this));
    }
    
    @Deprecated
    public FluidState getFluidState(final BlockState byj) {
        return Fluids.EMPTY.defaultFluidState();
    }
    
    public float getFriction() {
        return this.friction;
    }
    
    public float getSpeedFactor() {
        return this.speedFactor;
    }
    
    public float getJumpFactor() {
        return this.jumpFactor;
    }
    
    @Deprecated
    public long getSeed(final BlockState byj, final BlockPos fk) {
        return Mth.getSeed(fk);
    }
    
    public void onProjectileHit(final Level bjw, final BlockState byj, final BlockHitResult cvg, final Entity akq) {
    }
    
    public void playerWillDestroy(final Level bjw, final BlockPos fk, final BlockState byj, final Player ayj) {
        bjw.levelEvent(ayj, 2001, fk, getId(byj));
    }
    
    public void handleRain(final Level bjw, final BlockPos fk) {
    }
    
    public boolean dropFromExplosion(final Explosion bjp) {
        return true;
    }
    
    @Deprecated
    public boolean hasAnalogOutputSignal(final BlockState byj) {
        return false;
    }
    
    @Deprecated
    public int getAnalogOutputSignal(final BlockState byj, final Level bjw, final BlockPos fk) {
        return 0;
    }
    
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
    }
    
    public StateDefinition<Block, BlockState> getStateDefinition() {
        return this.stateDefinition;
    }
    
    protected final void registerDefaultState(final BlockState byj) {
        this.defaultBlockState = byj;
    }
    
    public final BlockState defaultBlockState() {
        return this.defaultBlockState;
    }
    
    public OffsetType getOffsetType() {
        return OffsetType.NONE;
    }
    
    @Deprecated
    public Vec3 getOffset(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        final OffsetType b5 = this.getOffsetType();
        if (b5 == OffsetType.NONE) {
            return Vec3.ZERO;
        }
        final long long6 = Mth.getSeed(fk.getX(), 0, fk.getZ());
        return new Vec3(((long6 & 0xFL) / 15.0f - 0.5) * 0.5, (b5 == OffsetType.XYZ) ? (((long6 >> 4 & 0xFL) / 15.0f - 1.0) * 0.2) : 0.0, ((long6 >> 8 & 0xFL) / 15.0f - 0.5) * 0.5);
    }
    
    public SoundType getSoundType(final BlockState byj) {
        return this.soundType;
    }
    
    @Override
    public Item asItem() {
        if (this.item == null) {
            this.item = Item.byBlock(this);
        }
        return this.item;
    }
    
    public boolean hasDynamicShape() {
        return this.dynamicShape;
    }
    
    @Override
    public String toString() {
        return "Block{" + Registry.BLOCK.getKey(this) + "}";
    }
    
    public void appendHoverText(final ItemStack ben, @Nullable final BlockGetter bjg, final List<Component> list, final TooltipFlag bfw) {
    }
    
    static {
        LOGGER = LogManager.getLogger();
        BLOCK_STATE_REGISTRY = new IdMapper<BlockState>();
        UPDATE_SHAPE_ORDER = new Direction[] { Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP };
        SHAPE_FULL_BLOCK_CACHE = CacheBuilder.newBuilder().maximumSize(512L).weakKeys().<VoxelShape, Boolean>build(new CacheLoader<VoxelShape, Boolean>() {
            @Override
            public Boolean load(final VoxelShape cwf) {
                return !Shapes.joinIsNotEmpty(Shapes.block(), cwf, BooleanOp.NOT_SAME);
            }
        });
        RIGID_SUPPORT_SHAPE = Shapes.join(Shapes.block(), box(2.0, 0.0, 2.0, 14.0, 16.0, 14.0), BooleanOp.ONLY_FIRST);
        CENTER_SUPPORT_SHAPE = box(7.0, 0.0, 7.0, 9.0, 10.0, 9.0);
        final Object2ByteLinkedOpenHashMap<BlockStatePairKey> object2ByteLinkedOpenHashMap1;
        OCCLUSION_CACHE = ThreadLocal.<Object2ByteLinkedOpenHashMap<BlockStatePairKey>>withInitial(() -> {
            object2ByteLinkedOpenHashMap1 = new Object2ByteLinkedOpenHashMap<BlockStatePairKey>(2048, 0.25f) {
                protected void rehash(final int integer) {
                }
            };
            object2ByteLinkedOpenHashMap1.defaultReturnValue((byte)127);
            return object2ByteLinkedOpenHashMap1;
        });
    }
    
    public static final class BlockStatePairKey {
        private final BlockState first;
        private final BlockState second;
        private final Direction direction;
        
        public BlockStatePairKey(final BlockState byj1, final BlockState byj2, final Direction fp) {
            this.first = byj1;
            this.second = byj2;
            this.direction = fp;
        }
        
        @Override
        public boolean equals(final Object object) {
            if (this == object) {
                return true;
            }
            if (!(object instanceof BlockStatePairKey)) {
                return false;
            }
            final BlockStatePairKey a3 = (BlockStatePairKey)object;
            return this.first == a3.first && this.second == a3.second && this.direction == a3.direction;
        }
        
        @Override
        public int hashCode() {
            int integer2 = this.first.hashCode();
            integer2 = 31 * integer2 + this.second.hashCode();
            integer2 = 31 * integer2 + this.direction.hashCode();
            return integer2;
        }
    }
    
    public static class Properties {
        private Material material;
        private MaterialColor materialColor;
        private boolean hasCollision;
        private SoundType soundType;
        private int lightEmission;
        private float explosionResistance;
        private float destroyTime;
        private boolean isTicking;
        private float friction;
        private float speedFactor;
        private float jumpFactor;
        private ResourceLocation drops;
        private boolean canOcclude;
        private boolean dynamicShape;
        
        private Properties(final Material coo, final MaterialColor cop) {
            this.hasCollision = true;
            this.soundType = SoundType.STONE;
            this.friction = 0.6f;
            this.speedFactor = 1.0f;
            this.jumpFactor = 1.0f;
            this.canOcclude = true;
            this.material = coo;
            this.materialColor = cop;
        }
        
        public static Properties of(final Material coo) {
            return of(coo, coo.getColor());
        }
        
        public static Properties of(final Material coo, final DyeColor bdj) {
            return of(coo, bdj.getMaterialColor());
        }
        
        public static Properties of(final Material coo, final MaterialColor cop) {
            return new Properties(coo, cop);
        }
        
        public static Properties copy(final Block bph) {
            final Properties c2 = new Properties(bph.material, bph.materialColor);
            c2.material = bph.material;
            c2.destroyTime = bph.destroySpeed;
            c2.explosionResistance = bph.explosionResistance;
            c2.hasCollision = bph.hasCollision;
            c2.isTicking = bph.isTicking;
            c2.lightEmission = bph.lightEmission;
            c2.materialColor = bph.materialColor;
            c2.soundType = bph.soundType;
            c2.friction = bph.getFriction();
            c2.speedFactor = bph.getSpeedFactor();
            c2.dynamicShape = bph.dynamicShape;
            c2.canOcclude = bph.canOcclude;
            return c2;
        }
        
        public Properties noCollission() {
            this.hasCollision = false;
            this.canOcclude = false;
            return this;
        }
        
        public Properties noOcclusion() {
            this.canOcclude = false;
            return this;
        }
        
        public Properties friction(final float float1) {
            this.friction = float1;
            return this;
        }
        
        public Properties speedFactor(final float float1) {
            this.speedFactor = float1;
            return this;
        }
        
        public Properties jumpFactor(final float float1) {
            this.jumpFactor = float1;
            return this;
        }
        
        protected Properties sound(final SoundType bum) {
            this.soundType = bum;
            return this;
        }
        
        protected Properties lightLevel(final int integer) {
            this.lightEmission = integer;
            return this;
        }
        
        public Properties strength(final float float1, final float float2) {
            this.destroyTime = float1;
            this.explosionResistance = Math.max(0.0f, float2);
            return this;
        }
        
        protected Properties instabreak() {
            return this.strength(0.0f);
        }
        
        protected Properties strength(final float float1) {
            this.strength(float1, float1);
            return this;
        }
        
        protected Properties randomTicks() {
            this.isTicking = true;
            return this;
        }
        
        protected Properties dynamicShape() {
            this.dynamicShape = true;
            return this;
        }
        
        protected Properties noDrops() {
            this.drops = BuiltInLootTables.EMPTY;
            return this;
        }
        
        public Properties dropsLike(final Block bph) {
            this.drops = bph.getLootTable();
            return this;
        }
    }
    
    public enum OffsetType {
        NONE, 
        XZ, 
        XYZ;
    }
}
