private void HandleDigging(byte[] message)
        {
            //Send Animation, this shouldn't only be sent when digging
            //Now handled in HandleAnimation(), this code isn't needed

            /*foreach (int i in VisibleEntities.ToArray())
             * {
             *  Entity e = Entity.Entities[i];
             *  if (!e.isPlayer) continue;
             *  Player p = e.p;
             *  if (p.level == level && p != this)
             *      p.SendAnimation(id, 1);
             * }*/

            if (message[0] == 0)
            {
                int  x         = util.EndianBitConverter.Big.ToInt32(message, 1);
                byte y         = message[5];
                int  z         = util.EndianBitConverter.Big.ToInt32(message, 6);
                byte direction = message[10];

                Point3 face = BlockData.GetFaceBlock(x, y, z, direction);

                byte rc = level.GetBlock(x, y, z); //block hit

                if (OnBlockChange != null)
                {
                    OnBlockChange(this, x, y, z, current_block_holding.id);
                    return;
                }

                if (OnBlockLeftClick != null)
                {
                    OnBlockLeftClick(this, x, y, z, direction);
                }
                if (PlayerBlockLeftClick != null)
                {
                    PlayerBlockLeftClick(this, x, y, z, direction);
                }
                if (cancelblockleft)
                {
                    cancelblockleft = false;
                    return;
                }

                if (BlockChange.LeftClicked.ContainsKey(rc))
                {
                    BlockChange.LeftClicked[rc].DynamicInvoke(this, new BCS(new Point3(x, y, z), 0, 0, 0, 0));
                }

                if (level.GetBlock((int)face.x, (int)face.y, (int)face.z) == 51)
                {
                    level.BlockChange((int)face.x, (int)face.y, (int)face.z, 0, 0);
                    Player.GlobalSoundEffect(face, 1004, level);
                }

                if (Server.mode == 1)
                {
                    if (BlockChange.Destroyed.ContainsKey(rc))
                    {
                        if (!(bool)BlockChange.Destroyed[rc].DynamicInvoke(this, new BCS(new Point3(x, y, z), 0, 0, 0, 0)))
                        {
                            //SendBlockChange(x, y, z, level.GetBlock(x, y, z), level.GetMeta(x, y, z));
                            Logger.Log("Delegate for " + rc + " Destroyed returned false");
                            return;
                        }
                    }

                    level.BlockChange(x, y, z, 0, 0);
                    goto doSound;
                }
                else if (BlockData.CanInstantBreak(rc))
                {
                    if (BlockChange.Destroyed.ContainsKey(rc))
                    {
                        if (!(bool)BlockChange.Destroyed[rc].DynamicInvoke(this, new BCS(new Point3(x, y, z), 0, 0, 0, 0)))
                        {
                            //SendBlockChange(x, y, z, level.GetBlock(x, y, z), level.GetMeta(x, y, z));
                            Logger.Log("Delegate for " + rc + " Destroyed returned false");
                            return;
                        }
                    }

                    short dropId = BlockDropSwitch(rc);
                    if (dropId != 0)
                    {
                        level.DropItem(x, y, z, dropId, level.GetMeta(x, y, z));
                    }

                    level.BlockChange(x, y, z, 0, 0);
                    goto doSound;
                }
                return;

doSound:
                Player.GlobalBreakEffect(x, y, z, rc, level, this);
            }
            if (message[0] == 2)
            {
                //Player is done digging
                int  x         = util.EndianBitConverter.Big.ToInt32(message, 1);
                byte y         = message[5];
                int  z         = util.EndianBitConverter.Big.ToInt32(message, 6);
                byte direction = message[10];

                Point3 face = BlockData.GetFaceBlock(x, y, z, direction);

                short id      = level.GetBlock(x, y, z);
                short storeId = id;
                byte  count   = 1;

                if (OnBlockBreak != null)
                {
                    OnBlockBreak(this, x, y, z, (byte)id, level.GetMeta(x, y, z));
                }
                if (PlayerBlockBreak != null)
                {
                    PlayerBlockBreak(this, x, y, z, (byte)id, level.GetMeta(x, y, z));
                }
                if (cancelbreak)
                {
                    cancelbreak = false;
                    return;
                }

                if (BlockChange.Destroyed.ContainsKey(id))
                {
                    if (!(bool)BlockChange.Destroyed[id].DynamicInvoke(this, new BCS(new Point3(x, y, z), 0, 0, 0, 0)))
                    {
                        //SendBlockChange(x, y, z, level.GetBlock(x, y, z), level.GetMeta(x, y, z));
                        Logger.Log("Delegate for " + id + " Destroyed returned false");
                        return;
                    }
                }

                id = BlockDropSwitch(id);

                if (id != 0)
                {
                    level.DropItem(x, y, z, id, level.GetMeta(x, y, z), count);
                }

                level.BlockChange(x, y, z, 0, 0);

                Player.GlobalBreakEffect(x, y, z, storeId, level, this);
            }
            if (message[0] == 4)
            {
                //TODO drop one of the item the player is holding!
                //inventory.Remove(inventory.current_index, 1);
            }
            if (message[0] == 5)
            {
                // TODO: Shoot arrow!
            }
        }