void Player_DetachProgressPacketReceived(DetachProgressPacket packet)
        {
            // must synchronize these messages from server because MP clients don't get grind damage events.

            switch (packet.State)
            {
            case DetachState.EnemyBlock:
                Main.Notifications.Print(Channel.Detach, "Detach Mode: Cannot detach enemy blocks.", MyFontEnum.Red, 3000);
                break;

            case DetachState.SingleBlock:
                Main.Notifications.Print(Channel.Detach, "Detach Mode: Nothing to detach from, block is free floating.", MyFontEnum.Debug, 2000);
                break;

            case DetachState.NoStandalone:
                Main.Notifications.Print(Channel.Detach, "Detach Mode: This block cannot exist standalone.", MyFontEnum.Red, 3000);
                break;

            case DetachState.Detaching:
                Main.Notifications.Print(Channel.Detach, $"Detach Mode: Detaching [{packet.Progress.ToString()}%]...", MyFontEnum.Debug, 500);
                break;

            case DetachState.DetachComplete:
                Main.Notifications.Print(Channel.Detach, "Detach Mode: Block is detached!", MyFontEnum.Green, 2000);
                break;

            case DetachState.ZeroGrindAmount:
                Main.Notifications.Print(Channel.Detach, "Detach Mode: Something else is preventing grinding, cannot detach.", MyFontEnum.Red, 1000);
                break;

            default:
                Main.Notifications.Print(Channel.Detach, $"Detach Mode: unknown state received: {packet.State.ToString()}", MyFontEnum.Red, 5000);
                break;
            }
        }
        public override void Register()
        {
            ModePacket     = new DetachModePacket();
            ProgressPacket = new DetachProgressPacket();

            if (Networking.IsPlayer)
            {
                Local_DetachData = new DetachData();
                Main.GrinderHandler.GrinderChanged += Local_EquippedGrinderChanged;
                DetachProgressPacket.OnReceive     += Player_DetachProgressPacketReceived;
            }

            if (MyAPIGateway.Session.IsServer)
            {
                Server_DetachData = new Dictionary <ulong, DetachData>();
                Main.GrindDamageHandler.GrindingBlock          += Server_GrindingBlock;
                DetachModePacket.OnReceive                     += Server_DetachModePacketReceived;
                MyVisualScriptLogicProvider.PlayerDisconnected += Server_PlayerDisconnected;
            }
        }