// Execute UNBAN or UNANNOY or UNBLOCKCHAT
        public bool DoUnban(MPBanMode banMode)
        {
            if (banMode == MPBanMode.Annoy)
            {
                // UNANNOY also implies UNBLOCKCHAT
                DoUnban(MPBanMode.BlockChat);
            }
            if (String.IsNullOrEmpty(arg))
            {
                MPBanPlayers.UnbanAll(banMode);
                ReturnTo(String.Format("ban list {0} cleared by {1}", banMode, senderEntry.name));
            }
            else
            {
                // check against names in ban list (may not be current player names)
                string pattern = arg.ToUpper();
                var    banList = MPBanPlayers.GetList(banMode);
                int    cnt     = banList.RemoveAll(entry => (MatchPlayerName(entry.name, pattern) != 0));
                if (cnt > 0)
                {
                    MPBanPlayers.OnUpdate(banMode, false);
                }
                else
                {
                    // check the currently connected players
                    if (SelectPlayer(arg))
                    {
                        cnt = MPBanPlayers.Unban(selectedPlayerEntry, banMode);
                    }
                }

                if (cnt > 0)
                {
                    ReturnTo(String.Format("{0} players UNBANNED from {1} list by {2}", cnt, banMode, senderEntry.name));
                }
                else
                {
                    ReturnToSender(String.Format("Un{0}: no player {1} found", banMode, arg));
                }
            }
            return(false);
        }
        // Execute STATUS command
        public bool DoStatus()
        {
            string creator;

            if (MPBanPlayers.MatchCreator != null && !String.IsNullOrEmpty(MPBanPlayers.MatchCreator.name))
            {
                creator = MPBanPlayers.MatchCreator.name;
            }
            else
            {
                creator = "<UNKNOWN>";
            }

            GetTrustedPlayerIds();
            ReturnToSender(String.Format("STATUS: {0}'s game, your auth: {1}", creator, CheckPermission(senderEntry)));
            ReturnToSender(String.Format("STATUS: bans: {0}, annoys: {1}, blocks: {2}, auth: {3} trust: {4}",
                                         MPBanPlayers.GetList(MPBanMode.Ban).Count,
                                         MPBanPlayers.GetList(MPBanMode.Annoy).Count,
                                         MPBanPlayers.GetList(MPBanMode.BlockChat).Count,
                                         authenticatedPlayers.Count,
                                         trustedPlayers.Count));
            return(false);
        }
        // Execute a command: Returns true if the caller should forward the chat message
        // to the clients, and false if not (when it was a special command for the server)
        public bool Execute()
        {
            if (!IsEnabled())
            {
                // chat commands are not enabled
                return(true);
            }

            if (cmd == Command.None)
            {
                // there might be BlockChat-Banned players, and we can just ignore their ramblings
                if (MPBanPlayers.GetList(MPBanMode.BlockChat).Count > 0)
                {
                    MPBanEntry we = FindPlayerEntryForConnection(sender_conn, inLobby);
                    if (we != null && MPBanPlayers.IsBanned(we, MPBanMode.BlockChat))
                    {
                        // send the message back to the sender ONLY
                        MPChatTools.SendTo(inLobby, sender_message, sender_conn, -1, false, false, sender_name, sender_team, isTeamMessage, sender_conn);
                        return(false);
                    }
                }
                return(true);
            }
            senderEntry = FindPlayerEntryForConnection(sender_conn, inLobby);
            if (senderEntry == null || String.IsNullOrEmpty(senderEntry.name))
            {
                Debug.LogFormat("CHATCMD {0}: {1} {2}: failed to identify sender", cmd, cmdName, arg);
                return(false);
            }
            Debug.LogFormat("CHATCMD {0}: {1} {2} by {3}", cmd, cmdName, arg, senderEntry.name);
            if (needAuth)
            {
                if (!CheckPermission(senderEntry))
                {
                    ReturnToSender(String.Format("You do not have the permission for command {0}!", cmd));
                    Debug.LogFormat("CHATCMD {0}: client is not authenticated!", cmd);
                    return(false);
                }
            }
            bool result = false;

            switch (cmd)
            {
            case Command.GivePerm:
                result = DoPerm(true);
                break;

            case Command.RevokePerm:
                result = DoPerm(false);
                break;

            case Command.Auth:
                result = DoAuth();
                break;

            case Command.Kick:
                result = DoKickBan(true, false, MPBanMode.Ban);
                break;

            case Command.Ban:
                result = DoKickBan(false, true, MPBanMode.Ban);
                break;

            case Command.Annoy:
                result = DoKickBan(false, true, MPBanMode.Annoy);
                break;

            case Command.KickBan:
                result = DoKickBan(true, true, MPBanMode.Ban);
                break;

            case Command.Unban:
                result = DoUnban(MPBanMode.Ban);
                break;

            case Command.Unannoy:
                result = DoUnban(MPBanMode.Annoy);
                break;

            case Command.BlockChat:
                result = DoKickBan(false, true, MPBanMode.BlockChat);
                break;

            case Command.UnblockChat:
                result = DoUnban(MPBanMode.BlockChat);
                break;

            case Command.End:
                result = DoEnd();
                break;

            case Command.Start:
                result = DoStart();
                break;

            case Command.Status:
                result = DoStatus();
                break;

            case Command.Say:
                result = DoSay();
                break;

            case Command.Test:
                result = DoTest();
                break;

            default:
                Debug.LogFormat("CHATCMD {0}: {1} {2} was not handled by server", cmd, cmdName, arg);
                result = true;     // treat it as normal chat message
                break;
            }
            return(result);
        }