/// <summary>
        /// Tell the plugin we have a new call partner
        /// </summary>
        /// <param name="args">args[0] - handle | args[1] - bool | args[2] - string[]</param>
        private static void OnEstablishCallRelayed(object[] args)
        {
            ushort handle = Convert.ToUInt16(args[0]);
            bool   direct = (bool)args[1];

            string[] relays = Newtonsoft.Json.JsonConvert.DeserializeObject <string[]>((string)args[2]);

            Player player = Entities.Players.GetAtRemote(handle);

            if (player == null || !VoiceManager.TryGetVoiceClient(handle, out VoiceClient voiceClient))
            {
                return;
            }

            RAGE.Vector3 ownPosition    = RAGE.Elements.Player.LocalPlayer.Position;
            RAGE.Vector3 playerPosition = player.Position;

            VoiceManager.ExecuteCommand(
                new PluginCommand(
                    Command.PhoneCommunicationUpdate,
                    VoiceManager.ServerUniqueIdentifier,
                    new PhoneCommunication(
                        voiceClient.TeamSpeakName,
                        RAGE.Game.Zone.GetZoneScumminess(RAGE.Game.Zone.GetZoneAtCoords(ownPosition.X, ownPosition.Y, ownPosition.Z)) +
                        RAGE.Game.Zone.GetZoneScumminess(RAGE.Game.Zone.GetZoneAtCoords(playerPosition.X, playerPosition.Y, playerPosition.Z)),
                        direct,
                        relays
                        )
                    )
                );
        }
        /// <summary>
        /// When someone is talking on our radio channel
        /// </summary>
        /// <param name="args">args[0] - handle | args[1] - isOnRadio | args[2] - stateChange | args[3] - direct | args[4] - relays</param>
        private static void OnPlayerIsSendingRelayed(object[] args)
        {
            ushort handle      = Convert.ToUInt16(args[0]);
            bool   isOnRadio   = (bool)args[1];
            bool   stateChange = (bool)args[2];
            bool   direct      = (bool)args[3];

            string[] relays = Newtonsoft.Json.JsonConvert.DeserializeObject <string[]>((string)args[4]);

            Player player = Entities.Players.GetAtRemote(handle);

            if (player == null)
            {
                return;
            }

            if (Player.LocalPlayer == player)
            {
                VoiceManager.PlaySound("selfMicClick", false, "MicClick");
            }
            else
            {
                if (!VoiceManager.TryGetVoiceClient(handle, out VoiceClient voiceClient))
                {
                    return;
                }

                if (isOnRadio)
                {
                    VoiceManager.ExecuteCommand(
                        new PluginCommand(
                            Command.RadioCommunicationUpdate,
                            VoiceManager.ServerUniqueIdentifier,
                            new RadioCommunication(
                                voiceClient.TeamSpeakName,
                                RadioType.LongRange | RadioType.Distributed,
                                RadioType.LongRange | RadioType.Distributed,
                                stateChange,
                                direct,
                                relays
                                )
                            )
                        );
                }
                else
                {
                    VoiceManager.ExecuteCommand(
                        new PluginCommand(
                            Command.StopRadioCommunication,
                            VoiceManager.ServerUniqueIdentifier,
                            new RadioCommunication(
                                voiceClient.TeamSpeakName,
                                stateChange
                                )
                            )
                        );
                }
            }
        }
        /// <summary>
        /// When someone is talking on our radio channel
        /// </summary>
        /// <param name="args">args[0] - handle | args[1] - isOnRadio</param>
        private static void OnPlayerIsSending(object[] args)
        {
            ushort handle    = Convert.ToUInt16(args[0]);
            bool   isOnRadio = (bool)args[1];

            Player player = Entities.Players.GetAtRemote(handle);

            if (player == null)
            {
                return;
            }

            if (Player.LocalPlayer == player)
            {
                VoiceManager.PlaySound("selfMicClick", false, "MicClick");
            }
            else
            {
                if (!VoiceManager.TryGetVoiceClient(handle, out VoiceClient voiceClient))
                {
                    return;
                }

                if (isOnRadio)
                {
                    VoiceManager.ExecuteCommand(
                        new PluginCommand(
                            Command.RadioCommunicationUpdate,
                            VoiceManager.ServerUniqueIdentifier,
                            new RadioCommunication(
                                voiceClient.TeamSpeakName,
                                RadioType.LongRange | RadioType.Distributed,
                                RadioType.LongRange | RadioType.Distributed,
                                true
                                )
                            )
                        );
                }
                else
                {
                    VoiceManager.ExecuteCommand(
                        new PluginCommand(
                            Command.StopRadioCommunication,
                            VoiceManager.ServerUniqueIdentifier,
                            new RadioCommunication(
                                voiceClient.TeamSpeakName,
                                true
                                )
                            )
                        );
                }
            }
        }
        /// <summary>
        /// Tell plugin the player is alive again, se we can hear him
        /// </summary>
        /// <param name="args">[0] - handle</param>
        public static void OnPlayerRevived(object[] args)
        {
            ushort handle = Convert.ToUInt16(args[0]);

            Player player = Entities.Players.GetAtRemote(handle);

            if (player == null || !VoiceManager.TryGetVoiceClient(handle, out VoiceClient voiceClient))
            {
                return;
            }

            voiceClient.IsAlive = true;
        }
        /// <summary>
        /// Tell the plugin to end the call
        /// </summary>
        /// <param name="args">args[0] - handle</param>
        private static void OnEndCall(object[] args)
        {
            ushort handle = Convert.ToUInt16(args[0]);

            Player player = Entities.Players.GetAtRemote(handle);

            if (player == null || !VoiceManager.TryGetVoiceClient(handle, out VoiceClient voiceClient))
            {
                return;
            }

            VoiceManager.ExecuteCommand(
                new PluginCommand(
                    Command.StopPhoneCommunication,
                    VoiceManager.ServerUniqueIdentifier,
                    new PhoneCommunication(
                        voiceClient.TeamSpeakName
                        )
                    )
                );
        }