Example #1
0
        public World( string _path ) {
            path = _path;
            Color.Init();
            Map.Init();

            // start the logger
            log = new Logger( this );

            // load config
            classes = new ClassList( this );
            config = new Config( this, classes, log );
            
            // start tasks service
            tasks = new Tasks();

            db = new PlayerDB( this );
            bans = new IPBanList( this );

            cmd = new Commands( this );
            heartbeat = new Heartbeat( this );
        }
Example #2
0
        internal static PlayerInfo Load(string[] fields)
        {
            PlayerInfo info = new PlayerInfo {
                Name = fields[0]
            };

            if (fields[1].Length == 0 || !IPAddress.TryParse(fields[1], out info.LastIP))      // LEGACY
            {
                info.LastIP = IPAddress.None;
            }

            info.Rank = RankManager.ParseRank(fields[2]) ?? RankManager.DefaultRank;
            fields[3].ToDateTime(ref info.RankChangeDate);
            info.RankChangedBy = fields[4];

            info.Banned = (fields[5] == "b");

            // ban information
            if (fields[6].ToDateTime(ref info.BanDate))
            {
                info.BannedBy  = Unescape(fields[7]);
                info.BanReason = Unescape(fields[10]);
            }

            // unban information
            if (fields[8].ToDateTime(ref info.UnbanDate))
            {
                info.UnbannedBy  = Unescape(fields[9]);
                info.UnbanReason = Unescape(fields[11]);
            }

            // failed logins
            fields[12].ToDateTime(ref info.LastFailedLoginDate);

            if (fields[13].Length > 1 || !IPAddress.TryParse(fields[13], out info.LastFailedLoginIP))      // LEGACY
            {
                info.LastFailedLoginIP = IPAddress.None;
            }
            if (fields[14].Length > 0)
            {
                info.FailedLoginCount = Int32.Parse(fields[14]);
            }
            fields[15].ToDateTime(ref info.FirstLoginDate);

            // login/logout times
            fields[16].ToDateTime(ref info.LastLoginDate);
            fields[17].ToTimeSpan(ref info.TotalTime);

            // stats
            if (fields[18].Length > 0)
            {
                Int32.TryParse(fields[18], out info.BlocksBuilt);
            }
            if (fields[19].Length > 0)
            {
                Int32.TryParse(fields[19], out info.BlocksDeleted);
            }
            Int32.TryParse(fields[20], out info.TimesVisited);
            if (fields[20].Length > 0)
            {
                Int32.TryParse(fields[21], out info.LinesWritten);
            }
            // fields 22-23 are no longer in use

            if (fields[24].Length > 0)
            {
                info.PreviousRank = RankManager.ParseRank(fields[24]);
            }
            if (fields[25].Length > 0)
            {
                info.RankChangeReason = Unescape(fields[25]);
            }
            Int32.TryParse(fields[26], out info.TimesKicked);
            Int32.TryParse(fields[27], out info.TimesKickedOthers);
            Int32.TryParse(fields[28], out info.TimesBannedOthers);

            info.ID = Int32.Parse(fields[29]);
            if (info.ID < 256)
            {
                info.ID = PlayerDB.GetNextID();
            }

            int rankChangeTypeCode;

            if (Int32.TryParse(fields[30], out rankChangeTypeCode))
            {
                info.RankChangeType = (RankChangeType)rankChangeTypeCode;
                if (!Enum.IsDefined(typeof(RankChangeType), rankChangeTypeCode))
                {
                    info.GuessRankChangeType();
                }
            }
            else
            {
                info.GuessRankChangeType();
            }

            fields[31].ToDateTime(ref info.LastKickDate);
            if (!fields[32].ToDateTime(ref info.LastSeen) || info.LastSeen < info.LastLoginDate)
            {
                info.LastSeen = info.LastLoginDate;
            }
            Int64.TryParse(fields[33], out info.BlocksDrawn);

            info.LastKickBy     = Unescape(fields[34]);
            info.LastKickReason = Unescape(fields[35]);

            fields[36].ToDateTime(ref info.BannedUntil);
            info.IsFrozen = (fields[37] == "f");
            info.FrozenBy = Unescape(fields[38]);
            fields[39].ToDateTime(ref info.FrozenOn);
            fields[40].ToDateTime(ref info.MutedUntil);
            info.MutedBy  = Unescape(fields[41]);
            info.Password = Unescape(fields[42]);
            // fields[43] is "online", and is ignored

            int bandwidthUseModeCode;

            if (Int32.TryParse(fields[44], out bandwidthUseModeCode))
            {
                info.BandwidthUseMode = (BandwidthUseMode)bandwidthUseModeCode;
                if (!Enum.IsDefined(typeof(BandwidthUseMode), bandwidthUseModeCode))
                {
                    info.BandwidthUseMode = BandwidthUseMode.Default;
                }
            }
            else
            {
                info.BandwidthUseMode = BandwidthUseMode.Default;
            }

            if (info.LastSeen < info.FirstLoginDate)
            {
                info.LastSeen = info.FirstLoginDate;
            }
            if (info.LastLoginDate < info.FirstLoginDate)
            {
                info.LastLoginDate = info.FirstLoginDate;
            }

            return(info);
        }
Example #3
0
        internal static PlayerInfo LoadOldFormat(string[] fields, bool convertDatesToUtc)
        {
            PlayerInfo info = new PlayerInfo {
                Name = fields[0]
            };

            if (fields[1].Length == 0 || !IPAddress.TryParse(fields[1], out info.LastIP))      // LEGACY
            {
                info.LastIP = IPAddress.None;
            }

            info.Rank = RankManager.ParseRank(fields[2]) ?? RankManager.DefaultRank;
            DateTimeUtil.TryParseLocalDate(fields[3], out info.RankChangeDate);
            info.RankChangedBy = fields[4];
            if (info.RankChangedBy == "-")
            {
                info.RankChangedBy = "";
            }

            info.Banned = (fields[5] == "b");

            // ban information
            if (DateTimeUtil.TryParseLocalDate(fields[6], out info.BanDate))
            {
                info.BannedBy  = fields[7];
                info.BanReason = UnescapeOldFormat(fields[10]);
                if (info.BanReason == "-")
                {
                    info.BanReason = "";
                }
            }

            // unban information
            if (DateTimeUtil.TryParseLocalDate(fields[8], out info.UnbanDate))
            {
                info.UnbannedBy  = fields[9];
                info.UnbanReason = UnescapeOldFormat(fields[11]);
                if (info.UnbanReason == "-")
                {
                    info.UnbanReason = "";
                }
            }

            // failed logins
            if (fields[12].Length > 1)
            {
                DateTimeUtil.TryParseLocalDate(fields[12], out info.LastFailedLoginDate);
            }
            if (fields[13].Length > 1 || !IPAddress.TryParse(fields[13], out info.LastFailedLoginIP))      // LEGACY
            {
                info.LastFailedLoginIP = IPAddress.None;
            }
            if (fields[14].Length > 0)
            {
                info.FailedLoginCount = Int32.Parse(fields[14]);
            }

            // login/logout times
            DateTimeUtil.TryParseLocalDate(fields[15], out info.FirstLoginDate);
            DateTimeUtil.TryParseLocalDate(fields[16], out info.LastLoginDate);
            TimeSpan.TryParse(fields[17], out info.TotalTime);

            // stats
            if (fields[18].Length > 0)
            {
                Int32.TryParse(fields[18], out info.BlocksBuilt);
            }
            if (fields[19].Length > 0)
            {
                Int32.TryParse(fields[19], out info.BlocksDeleted);
            }
            Int32.TryParse(fields[20], out info.TimesVisited);
            if (fields[20].Length > 0)
            {
                Int32.TryParse(fields[21], out info.LinesWritten);
            }
            // fields 22-23 are no longer in use

            if (fields.Length > MinFieldCount)
            {
                if (fields[24].Length > 0)
                {
                    info.PreviousRank = RankManager.ParseRank(fields[24]);
                }
                if (fields[25].Length > 0)
                {
                    info.RankChangeReason = UnescapeOldFormat(fields[25]);
                }
                Int32.TryParse(fields[26], out info.TimesKicked);
                Int32.TryParse(fields[27], out info.TimesKickedOthers);
                Int32.TryParse(fields[28], out info.TimesBannedOthers);
                if (fields.Length > 29)
                {
                    info.ID = Int32.Parse(fields[29]);
                    if (info.ID < 256)
                    {
                        info.ID = PlayerDB.GetNextID();
                    }
                    int rankChangeTypeCode;
                    if (Int32.TryParse(fields[30], out rankChangeTypeCode))
                    {
                        info.RankChangeType = (RankChangeType)rankChangeTypeCode;
                        if (!Enum.IsDefined(typeof(RankChangeType), rankChangeTypeCode))
                        {
                            info.GuessRankChangeType();
                        }
                    }
                    else
                    {
                        info.GuessRankChangeType();
                    }
                    DateTimeUtil.TryParseLocalDate(fields[31], out info.LastKickDate);
                    if (!DateTimeUtil.TryParseLocalDate(fields[32], out info.LastSeen) || info.LastSeen < info.LastLoginDate)
                    {
                        info.LastSeen = info.LastLoginDate;
                    }
                    Int64.TryParse(fields[33], out info.BlocksDrawn);

                    info.LastKickBy     = fields[34];
                    info.LastKickReason = UnescapeOldFormat(fields[35]);
                }
                else
                {
                    info.ID = PlayerDB.GetNextID();
                    info.GuessRankChangeType();
                    info.LastSeen = info.LastLoginDate;
                }

                if (fields.Length > 36)
                {
                    DateTimeUtil.TryParseLocalDate(fields[36], out info.BannedUntil);
                    info.IsFrozen = (fields[37] == "f");
                    info.FrozenBy = UnescapeOldFormat(fields[38]);
                    DateTimeUtil.TryParseLocalDate(fields[39], out info.FrozenOn);
                    DateTimeUtil.TryParseLocalDate(fields[40], out info.MutedUntil);
                    info.MutedBy  = UnescapeOldFormat(fields[41]);
                    info.Password = UnescapeOldFormat(fields[42]);
                    // fields[43] is "online", and is ignored
                }

                if (fields.Length > 44)
                {
                    if (fields[44].Length != 0)
                    {
                        info.BandwidthUseMode = (BandwidthUseMode)Int32.Parse(fields[44]);
                    }
                }
            }

            if (info.LastSeen < info.FirstLoginDate)
            {
                info.LastSeen = info.FirstLoginDate;
            }
            if (info.LastLoginDate < info.FirstLoginDate)
            {
                info.LastLoginDate = info.FirstLoginDate;
            }

            if (convertDatesToUtc)
            {
                if (info.RankChangeDate != DateTime.MinValue)
                {
                    info.RankChangeDate = info.RankChangeDate.ToUniversalTime();
                }
                if (info.BanDate != DateTime.MinValue)
                {
                    info.BanDate = info.BanDate.ToUniversalTime();
                }
                if (info.UnbanDate != DateTime.MinValue)
                {
                    info.UnbanDate = info.UnbanDate.ToUniversalTime();
                }
                if (info.LastFailedLoginDate != DateTime.MinValue)
                {
                    info.LastFailedLoginDate = info.LastFailedLoginDate.ToUniversalTime();
                }
                if (info.FirstLoginDate != DateTime.MinValue)
                {
                    info.FirstLoginDate = info.FirstLoginDate.ToUniversalTime();
                }
                if (info.LastLoginDate != DateTime.MinValue)
                {
                    info.LastLoginDate = info.LastLoginDate.ToUniversalTime();
                }
                if (info.LastKickDate != DateTime.MinValue)
                {
                    info.LastKickDate = info.LastKickDate.ToUniversalTime();
                }
                if (info.LastSeen != DateTime.MinValue)
                {
                    info.LastSeen = info.LastSeen.ToUniversalTime();
                }
                if (info.BannedUntil != DateTime.MinValue)
                {
                    info.BannedUntil = info.BannedUntil.ToUniversalTime();
                }
                if (info.FrozenOn != DateTime.MinValue)
                {
                    info.FrozenOn = info.FrozenOn.ToUniversalTime();
                }
                if (info.MutedUntil != DateTime.MinValue)
                {
                    info.MutedUntil = info.MutedUntil.ToUniversalTime();
                }
            }

            return(info);
        }
Example #4
0
        /// <summary> Bans given IP address and all accounts on that IP. All players from IP are kicked.
        /// Throws PlayerOpException on problems. </summary>
        /// <param name="targetAddress"> IP address that is being banned. </param>
        /// <param name="player"> Player who is banning. </param>
        /// <param name="reason"> Reason for ban. May be empty, if permitted by server configuration. </param>
        /// <param name="announce"> Whether ban should be publicly announced on the server. </param>
        /// <param name="raiseEvents"> Whether AddingIPBan, AddedIPBan, BanChanging, and BanChanged events should be raised. </param>
        public static void BanAll([NotNull] this IPAddress targetAddress, [NotNull] Player player, [CanBeNull] string reason,
                                  bool announce, bool raiseEvents)
        {
            if (targetAddress == null)
            {
                throw new ArgumentNullException("targetAddress");
            }
            if (player == null)
            {
                throw new ArgumentNullException("player");
            }
            if (reason != null && reason.Trim().Length == 0)
            {
                reason = null;
            }

            if (!player.Can(Permission.Ban, Permission.BanIP, Permission.BanAll))
            {
                PlayerOpException.ThrowPermissionMissing(player, null, "ban-all",
                                                         Permission.Ban, Permission.BanIP, Permission.BanAll);
            }

            // Check if player is trying to ban self
            if (targetAddress.Equals(player.IP) && !player.IsSuper)
            {
                PlayerOpException.ThrowCannotTargetSelf(player, null, "ban-all");
            }

            // Check if a non-bannable address was given (0.0.0.0 or 255.255.255.255)
            if (targetAddress.Equals(IPAddress.None) || targetAddress.Equals(IPAddress.Any))
            {
                PlayerOpException.ThrowInvalidIP(player, null, targetAddress);
            }

            // Check if any high-ranked players use this address
            PlayerInfo[] allPlayersOnIP        = PlayerDB.FindPlayers(targetAddress);
            PlayerInfo   infoWhomPlayerCantBan = allPlayersOnIP.FirstOrDefault(info => !player.Can(Permission.Ban, info.Rank));

            if (infoWhomPlayerCantBan != null)
            {
                PlayerOpException.ThrowPermissionLimitIP(player, infoWhomPlayerCantBan, targetAddress);
            }

            PlayerOpException.CheckBanReason(reason, player, null, false);
            bool somethingGotBanned = false;

            // Ban the IP
            if (!Contains(targetAddress))
            {
                IPBanInfo banInfo = new IPBanInfo(targetAddress, null, player.Name, reason);
                if (Add(banInfo, raiseEvents))
                {
                    Logger.Log(LogType.UserActivity,
                               "{0} banned {1} (BanAll {1}). Reason: {2}",
                               player.Name, targetAddress, reason ?? "");

                    // Announce ban on the server
                    if (announce)
                    {
                        var can = Server.Players.Can(Permission.ViewPlayerIPs);
                        can.Message("&W{0} was banned by {1}", targetAddress, player.ClassyName);
                        var cant = Server.Players.Cant(Permission.ViewPlayerIPs);
                        cant.Message("&WAn IP was banned by {0}", player.ClassyName);
                    }
                    somethingGotBanned = true;
                }
            }

            // Ban individual players
            foreach (PlayerInfo targetAlt in allPlayersOnIP)
            {
                if (targetAlt.BanStatus != BanStatus.NotBanned)
                {
                    continue;
                }

                // Raise PlayerInfo.BanChanging event
                PlayerInfoBanChangingEventArgs e = new PlayerInfoBanChangingEventArgs(targetAlt, player, false, reason, announce);
                if (raiseEvents)
                {
                    PlayerInfo.RaiseBanChangingEvent(e);
                    if (e.Cancel)
                    {
                        continue;
                    }
                    reason = e.Reason;
                }

                // Do the ban
                if (targetAlt.ProcessBan(player, player.Name, reason))
                {
                    if (raiseEvents)
                    {
                        PlayerInfo.RaiseBanChangedEvent(e);
                    }

                    // Log and announce ban
                    Logger.Log(LogType.UserActivity,
                               "{0} banned {1} (BanAll {2}). Reason: {3}",
                               player.Name, targetAlt.Name, targetAddress, reason ?? "");
                    if (announce)
                    {
                        Server.Message("&WPlayer {0}&W was banned by {1}&W (BanAll)",
                                       targetAlt.ClassyName, player.ClassyName);
                    }
                    somethingGotBanned = true;
                }
            }

            // If no one ended up getting banned, quit here
            if (!somethingGotBanned)
            {
                PlayerOpException.ThrowNoOneToBan(player, null, targetAddress);
            }

            // Announce BanAll reason towards the end of all bans
            if (announce && ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null)
            {
                Server.Message("&WBanAll reason: {0}", reason);
            }

            // Kick all players from IP
            Player[] targetsOnline = Server.Players.FromIP(targetAddress).ToArray();
            if (targetsOnline.Length > 0)
            {
                string kickReason;
                if (reason != null)
                {
                    kickReason = String.Format("Banned by {0}: {1}", player.Name, reason);
                }
                else
                {
                    kickReason = String.Format("Banned by {0}", player.Name);
                }
                for (int i = 0; i < targetsOnline.Length; i++)
                {
                    targetsOnline[i].Kick(kickReason, LeaveReason.BanAll);
                }
            }
        }
Example #5
0
        /// <summary> Unbans given IP address and all accounts on that IP. Throws PlayerOpException on problems. </summary>
        /// <param name="targetAddress"> IP address that is being unbanned. </param>
        /// <param name="player"> Player who is unbanning. </param>
        /// <param name="reason"> Reason for unban. May be null or empty, if permitted by server configuration. </param>
        /// <param name="announce"> Whether unban should be publicly announced on the server. </param>
        /// <param name="raiseEvents"> Whether RemovingIPBan, RemovedIPBan, BanChanging, and BanChanged events should be raised. </param>
        public static void UnbanAll([NotNull] this IPAddress targetAddress, [NotNull] Player player, [CanBeNull] string reason,
                                    bool announce, bool raiseEvents)
        {
            if (targetAddress == null)
            {
                throw new ArgumentNullException("targetAddress");
            }
            if (player == null)
            {
                throw new ArgumentNullException("player");
            }
            if (reason != null && reason.Trim().Length == 0)
            {
                reason = null;
            }

            if (!player.Can(Permission.Ban, Permission.BanIP, Permission.BanAll))
            {
                PlayerOpException.ThrowPermissionMissing(player, null, "unban-all",
                                                         Permission.Ban, Permission.BanIP, Permission.BanAll);
            }

            // Check if player is trying to unban self
            if (targetAddress.Equals(player.IP) && !player.IsSuper)
            {
                PlayerOpException.ThrowCannotTargetSelf(player, null, "unban-all");
            }

            // Check if a non-bannable address was given (0.0.0.0 or 255.255.255.255)
            if (targetAddress.Equals(IPAddress.None) || targetAddress.Equals(IPAddress.Any))
            {
                PlayerOpException.ThrowInvalidIP(player, null, targetAddress);
            }

            PlayerOpException.CheckBanReason(reason, player, null, true);
            bool somethingGotUnbanned = false;

            // Unban the IP
            if (Contains(targetAddress))
            {
                if (Remove(targetAddress, raiseEvents))
                {
                    Logger.Log(LogType.UserActivity,
                               "{0} unbanned {1} (UnbanAll {1}). Reason: {2}",
                               player.Name, targetAddress, reason ?? "");

                    // Announce unban on the server
                    if (announce)
                    {
                        var can = Server.Players.Can(Permission.ViewPlayerIPs);
                        can.Message("&W{0} was unbanned by {1}", targetAddress, player.ClassyName);
                        var cant = Server.Players.Cant(Permission.ViewPlayerIPs);
                        cant.Message("&WAn IP was unbanned by {0}", player.ClassyName);
                    }

                    somethingGotUnbanned = true;
                }
            }

            // Unban individual players
            PlayerInfo[] allPlayersOnIP = PlayerDB.FindPlayers(targetAddress);
            foreach (PlayerInfo targetAlt in allPlayersOnIP)
            {
                if (targetAlt.BanStatus != BanStatus.Banned)
                {
                    continue;
                }

                // Raise PlayerInfo.BanChanging event
                PlayerInfoBanChangingEventArgs e = new PlayerInfoBanChangingEventArgs(targetAlt, player, true, reason, announce);
                if (raiseEvents)
                {
                    PlayerInfo.RaiseBanChangingEvent(e);
                    if (e.Cancel)
                    {
                        continue;
                    }
                    reason = e.Reason;
                }

                // Do the ban
                if (targetAlt.ProcessUnban(player.Name, reason))
                {
                    if (raiseEvents)
                    {
                        PlayerInfo.RaiseBanChangedEvent(e);
                    }

                    // Log and announce ban
                    Logger.Log(LogType.UserActivity,
                               "{0} unbanned {1} (UnbanAll {2}). Reason: {3}",
                               player.Name, targetAlt.Name, targetAddress, reason ?? "");
                    if (announce)
                    {
                        Server.Message("&WPlayer {0}&W was unbanned by {1}&W (UnbanAll)",
                                       targetAlt.ClassyName, player.ClassyName);
                    }
                    somethingGotUnbanned = true;
                }
            }

            // If no one ended up getting unbanned, quit here
            if (!somethingGotUnbanned)
            {
                PlayerOpException.ThrowNoOneToUnban(player, null, targetAddress);
            }

            // Announce UnbanAll reason towards the end of all unbans
            if (announce && ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null)
            {
                Server.Message("&WUnbanAll reason: {0}", reason);
            }
        }
Example #6
0
        public Zone(string raw, World world)
        {
            string[] parts = raw.Split(',');

            string[] header = parts[0].Split(' ');
            Name   = header[0];
            Bounds = new BoundingBox(Int32.Parse(header[1]), Int32.Parse(header[2]), Int32.Parse(header[3]),
                                     Int32.Parse(header[4]), Int32.Parse(header[5]), Int32.Parse(header[6]));

            Rank buildRank = RankManager.ParseRank(header[7]);

            // if all else fails, fall back to lowest class
            if (buildRank == null)
            {
                if (world != null)
                {
                    Controller.MinRank = world.BuildSecurity.MinRank;
                }
                else
                {
                    Controller.MinRank = null;
                }
                Logger.Log("Zone: Error parsing zone definition: unknown rank \"{0}\". Permission reset to default ({1}).", LogType.Error,
                           header[7], Controller.MinRank.Name);
            }
            else
            {
                Controller.MinRank = buildRank;
            }


            // Part 2:
            foreach (string player in parts[1].Split(' '))
            {
                if (!Player.IsValidName(player))
                {
                    continue;
                }
                PlayerInfo info = PlayerDB.FindPlayerInfoExact(player);
                if (info == null)
                {
                    continue;                // player name not found in the DB (discarded)
                }
                Controller.Include(info);
            }

            // Part 3: excluded list
            foreach (string player in parts[2].Split(' '))
            {
                if (!Player.IsValidName(player))
                {
                    continue;
                }
                PlayerInfo info = PlayerDB.FindPlayerInfoExact(player);
                if (info == null)
                {
                    continue;                // player name not found in the DB (discarded)
                }
                Controller.Exclude(info);
            }

            Controller.UpdatePlayerListCache();

            // Part 4: extended header
            if (parts.Length > 3)
            {
                string[] xheader = parts[3].Split(' ');
                CreatedBy = PlayerDB.FindPlayerInfoExact(xheader[0]);
                if (CreatedBy != null)
                {
                    CreatedDate = DateTime.Parse(xheader[1]);
                }
                EditedBy = PlayerDB.FindPlayerInfoExact(xheader[2]);
                if (EditedBy != null)
                {
                    EditedDate = DateTime.Parse(xheader[3]);
                }
            }
        }
Example #7
0
        /// <summary> Bans given IP address. All players from IP are kicked. If an associated PlayerInfo is known,
        /// use a different overload of this method instead. Throws PlayerOpException on problems. </summary>
        /// <param name="targetAddress"> IP address that is being banned. </param>
        /// <param name="player"> Player who is banning. </param>
        /// <param name="reason"> Reason for ban. May be empty, if permitted by server configuration. </param>
        /// <param name="announce"> Whether ban should be publicly announced on the server. </param>
        /// <param name="raiseEvents"> Whether AddingIPBan and AddedIPBan events should be raised. </param>
        public static void BanIP([NotNull] this IPAddress targetAddress, [NotNull] Player player, [CanBeNull] string reason,
                                 bool announce, bool raiseEvents)
        {
            if (targetAddress == null)
            {
                throw new ArgumentNullException("targetAddress");
            }
            if (player == null)
            {
                throw new ArgumentNullException("player");
            }
            if (reason != null && reason.Trim().Length == 0)
            {
                reason = null;
            }

            // Check if player can ban IPs in general
            if (!player.Can(Permission.Ban, Permission.BanIP))
            {
                PlayerOpException.ThrowPermissionMissing(player, null, "IP-ban", Permission.Ban, Permission.BanIP);
            }

            // Check if a non-bannable address was given (0.0.0.0 or 255.255.255.255)
            if (targetAddress.Equals(IPAddress.None) || targetAddress.Equals(IPAddress.Any))
            {
                PlayerOpException.ThrowInvalidIP(player, null, targetAddress);
            }

            // Check if player is trying to ban self
            if (targetAddress.Equals(player.IP) && !player.IsSuper)
            {
                PlayerOpException.ThrowCannotTargetSelf(player, null, "IP-ban");
            }

            // Check if target is already banned
            IPBanInfo existingBan = Get(targetAddress);

            if (existingBan != null)
            {
                string msg;
                if (player.Can(Permission.ViewPlayerIPs))
                {
                    msg = String.Format("IP address {0} is already banned.", targetAddress);
                }
                else
                {
                    msg = String.Format("Given IP address is already banned.");
                }
                string colorMsg = "&S" + msg;
                throw new PlayerOpException(player, null, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg);
            }

            // Check if any high-ranked players use this address
            PlayerInfo infoWhomPlayerCantBan = PlayerDB.FindPlayers(targetAddress)
                                               .FirstOrDefault(info => !player.Can(Permission.Ban, info.Rank));

            if (infoWhomPlayerCantBan != null)
            {
                PlayerOpException.ThrowPermissionLimitIP(player, infoWhomPlayerCantBan, targetAddress);
            }

            PlayerOpException.CheckBanReason(reason, player, null, false);

            // Actually ban
            IPBanInfo banInfo = new IPBanInfo(targetAddress, null, player.Name, reason);
            bool      result  = Add(banInfo, raiseEvents);

            if (result)
            {
                Logger.Log(LogType.UserActivity,
                           "{0} banned {1} (BanIP {1}). Reason: {2}",
                           player.Name, targetAddress, reason ?? "");
                if (announce)
                {
                    // Announce ban on the server
                    var can = Server.Players.Can(Permission.ViewPlayerIPs);
                    can.Message("&W{0} was banned by {1}", targetAddress, player.ClassyName);
                    var cant = Server.Players.Cant(Permission.ViewPlayerIPs);
                    cant.Message("&WAn IP was banned by {0}", player.ClassyName);
                    if (ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null)
                    {
                        Server.Message("&WBanIP reason: {0}", reason);
                    }
                }

                // Kick all players connected from address
                string kickReason;
                if (reason != null)
                {
                    kickReason = String.Format("IP-Banned by {0}: {1}", player.Name, reason);
                }
                else
                {
                    kickReason = String.Format("IP-Banned by {0}", player.Name);
                }
                foreach (Player other in Server.Players.FromIP(targetAddress))
                {
                    if (other.Info.BanStatus != BanStatus.IPBanExempt)
                    {
                        other.Kick(kickReason, LeaveReason.BanIP);   // TODO: check side effects of not using DoKick
                    }
                }
            }
            else
            {
                // address is already banned
                string msg;
                if (player.Can(Permission.ViewPlayerIPs))
                {
                    msg = String.Format("{0} is already banned.", targetAddress);
                }
                else
                {
                    msg = "Given IP address is already banned.";
                }
                string colorMsg = "&S" + msg;
                throw new PlayerOpException(player, null, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg);
            }
        }
Example #8
0
        static void ZoneEditHandler(Player player, CommandReader cmd)
        {
            bool   changesWereMade = false;
            string zoneName        = cmd.Next();

            if (zoneName == null)
            {
                player.Message("No zone name specified. See &H/Help ZEdit");
                return;
            }

            Zone zone = player.WorldMap.Zones.Find(zoneName);

            if (zone == null)
            {
                player.MessageNoZone(zoneName);
                return;
            }

            string nextToken;

            while ((nextToken = cmd.Next()) != null)
            {
                // Clear whitelist
                if (nextToken.Equals("-*"))
                {
                    PlayerInfo[] oldWhitelist = zone.Controller.ExceptionList.Included;
                    if (oldWhitelist.Length > 0)
                    {
                        zone.Controller.ResetIncludedList();
                        player.Message("Whitelist of zone {0}&S cleared: {1}",
                                       zone.ClassyName, oldWhitelist.JoinToClassyString());
                        Logger.Log(LogType.UserActivity,
                                   "Player {0} cleared whitelist of zone {1} on world {2}: {3}",
                                   player.Name, zone.Name, player.World.Name,
                                   oldWhitelist.JoinToString(pi => pi.Name));
                    }
                    else
                    {
                        player.Message("Whitelist of zone {0}&S is empty.",
                                       zone.ClassyName);
                    }
                    continue;
                }

                // Clear blacklist
                if (nextToken.Equals("+*"))
                {
                    PlayerInfo[] oldBlacklist = zone.Controller.ExceptionList.Excluded;
                    if (oldBlacklist.Length > 0)
                    {
                        zone.Controller.ResetExcludedList();
                        player.Message("Blacklist of zone {0}&S cleared: {1}",
                                       zone.ClassyName, oldBlacklist.JoinToClassyString());
                        Logger.Log(LogType.UserActivity,
                                   "Player {0} cleared blacklist of zone {1} on world {2}: {3}",
                                   player.Name, zone.Name, player.World.Name,
                                   oldBlacklist.JoinToString(pi => pi.Name));
                    }
                    else
                    {
                        player.Message("Blacklist of zone {0}&S is empty.",
                                       zone.ClassyName);
                    }
                    continue;
                }

                if (nextToken.StartsWith("+"))
                {
                    PlayerInfo info = PlayerDB.FindByPartialNameOrPrintMatches(player, nextToken.Substring(1));
                    if (info == null)
                    {
                        return;
                    }

                    // prevent players from whitelisting themselves to bypass protection
                    if (!player.Info.Rank.AllowSecurityCircumvention && player.Info == info)
                    {
                        switch (zone.Controller.CheckDetailed(info))
                        {
                        case SecurityCheckResult.BlackListed:
                            player.Message("You are not allowed to remove yourself from the blacklist of zone {0}",
                                           zone.ClassyName);
                            continue;

                        case SecurityCheckResult.RankTooLow:
                            player.Message("You must be {0}+&S to add yourself to the whitelist of zone {1}",
                                           zone.Controller.MinRank.ClassyName, zone.ClassyName);
                            continue;
                        }
                    }

                    switch (zone.Controller.Include(info))
                    {
                    case PermissionOverride.Deny:
                        player.Message("{0}&S is no longer excluded from zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.None:
                        player.Message("{0}&S is now included in zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.Allow:
                        player.Message("{0}&S is already included in zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        break;
                    }
                }
                else if (nextToken.StartsWith("-"))
                {
                    PlayerInfo info = PlayerDB.FindByPartialNameOrPrintMatches(player, nextToken.Substring(1));
                    if (info == null)
                    {
                        return;
                    }

                    switch (zone.Controller.Exclude(info))
                    {
                    case PermissionOverride.Deny:
                        player.Message("{0}&S is already excluded from zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        break;

                    case PermissionOverride.None:
                        player.Message("{0}&S is now excluded from zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.Allow:
                        player.Message("{0}&S is no longer included in zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        changesWereMade = true;
                        break;
                    }
                }
                else
                {
                    Rank minRank = RankManager.FindRank(nextToken);

                    if (minRank != null)
                    {
                        // prevent players from lowering rank so bypass protection
                        if (!player.Info.Rank.AllowSecurityCircumvention &&
                            zone.Controller.MinRank > player.Info.Rank && minRank <= player.Info.Rank)
                        {
                            player.Message("You are not allowed to lower the zone's rank.");
                            continue;
                        }

                        if (zone.Controller.MinRank != minRank)
                        {
                            zone.Controller.MinRank = minRank;
                            player.Message("Permission for zone \"{0}\" changed to {1}+",
                                           zone.Name,
                                           minRank.ClassyName);
                            changesWereMade = true;
                        }
                    }
                    else
                    {
                        player.MessageNoRank(nextToken);
                    }
                }

                if (changesWereMade)
                {
                    zone.Edit(player.Info);
                }
                else
                {
                    player.Message("No changes were made to the zone.");
                }
            }
        }
Example #9
0
        static void ZoneAddHandler(Player player, CommandReader cmd)
        {
            World playerWorld = player.World;

            if (playerWorld == null)
            {
                PlayerOpException.ThrowNoWorld(player);
            }

            string givenZoneName = cmd.Next();

            if (givenZoneName == null)
            {
                CdZoneAdd.PrintUsage(player);
                return;
            }

            if (!player.Info.Rank.AllowSecurityCircumvention)
            {
                SecurityCheckResult buildCheck = playerWorld.BuildSecurity.CheckDetailed(player.Info);
                switch (buildCheck)
                {
                case SecurityCheckResult.BlackListed:
                    player.Message("Cannot add zones to world {0}&S: You are barred from building here.",
                                   playerWorld.ClassyName);
                    return;

                case SecurityCheckResult.RankTooLow:
                    player.Message("Cannot add zones to world {0}&S: You are not allowed to build here.",
                                   playerWorld.ClassyName);
                    return;

                    //case SecurityCheckResult.RankTooHigh: // TODO
                }
            }

            Zone           newZone        = new Zone();
            ZoneCollection zoneCollection = player.WorldMap.Zones;

            if (givenZoneName.StartsWith("+"))
            {
                // personal zone (/ZAdd +Name)
                givenZoneName = givenZoneName.Substring(1);

                // Find the target player
                PlayerInfo info = PlayerDB.FindByPartialNameOrPrintMatches(player, givenZoneName);
                if (info == null)
                {
                    return;
                }
                givenZoneName = info.Name;

                // Make sure that the name is not taken already.
                // If a zone named after the player already exists, try adding a number after the name (e.g. "Notch2")
                newZone.Name = givenZoneName;
                for (int i = 2; zoneCollection.Contains(newZone.Name); i++)
                {
                    newZone.Name = givenZoneName + i;
                }

                newZone.Controller.MinRank = info.Rank.NextRankUp ?? info.Rank;
                newZone.Controller.Include(info);
                player.Message("Zone: Creating a {0}+&S zone for player {1}&S. Place a block or type /Mark to use your location.",
                               newZone.Controller.MinRank.ClassyName, info.ClassyName);
                player.SelectionStart(2, ZoneAddCallback, newZone, CdZoneAdd.Permissions);
            }
            else
            {
                // Adding an ordinary, rank-restricted zone.
                if (!World.IsValidName(givenZoneName))
                {
                    player.Message("\"{0}\" is not a valid zone name", givenZoneName);
                    return;
                }

                if (zoneCollection.Contains(givenZoneName))
                {
                    player.Message("A zone with this name already exists. Use &H/ZEdit&S to edit.");
                    return;
                }

                newZone.Name = givenZoneName;

                string rankName = cmd.Next();
                if (rankName == null)
                {
                    player.Message("No rank was specified. See &H/Help zone");
                    return;
                }
                Rank minRank = RankManager.FindRank(rankName);

                if (minRank != null)
                {
                    string name;
                    while ((name = cmd.Next()) != null)
                    {
                        if (name.Length == 0)
                        {
                            continue;
                        }

                        PlayerInfo info = PlayerDB.FindByPartialNameOrPrintMatches(player, name.Substring(1));
                        if (info == null)
                        {
                            return;
                        }

                        if (name.StartsWith("+"))
                        {
                            newZone.Controller.Include(info);
                        }
                        else if (name.StartsWith("-"))
                        {
                            newZone.Controller.Exclude(info);
                        }
                    }

                    newZone.Controller.MinRank = minRank;
                    player.SelectionStart(2, ZoneAddCallback, newZone, CdZoneAdd.Permissions);
                    player.Message("Zone: Place a block or type &H/Mark&S to use your location.");
                }
                else
                {
                    player.MessageNoRank(rankName);
                }
            }
        }
Example #10
0
        public Zone([NotNull] string raw, [CanBeNull] World world)
            : this()
        {
            if (raw == null)
            {
                throw new ArgumentNullException("raw");
            }
            string[] parts = raw.Split(',');

            string[] header = parts[0].Split(' ');
            Name   = header[0];
            Bounds = new BoundingBox(Int32.Parse(header[1]), Int32.Parse(header[2]), Int32.Parse(header[3]),
                                     Int32.Parse(header[4]), Int32.Parse(header[5]), Int32.Parse(header[6]));

            Rank buildRank = Rank.Parse(header[7]);


            if (header.Length > 8)
            {
                // Part 5: Zone color
                try {
                    bool zoneShow;
                    if (bool.TryParse(header[8], out zoneShow))
                    {
                        ShowZone = zoneShow;
                    }
                    Color = header[9];
                    short zoneAlpha;
                    if (short.TryParse(header[10], out zoneAlpha))
                    {
                        Alpha = zoneAlpha;
                    }
                } catch (Exception ex) {
                    Logger.Log(LogType.Error, "Could not load Zone Colors for {0}", Name);
                    Logger.Log(LogType.Error, ex.StackTrace);
                }
            }

            if (header[0].Contains(SpecialZone.Door))
            {
                buildRank = RankManager.DefaultRank;
            }
            // if all else fails, fall back to lowest class... ignore door instances
            if (buildRank == null && !header[0].Contains(SpecialZone.Door))
            {
                if (world != null)
                {
                    Controller.MinRank = world.BuildSecurity.MinRank;
                }
                else
                {
                    Controller.ResetMinRank();
                }
                Logger.Log(LogType.Error,
                           "Zone: Error parsing zone definition: unknown rank \"{0}\". Permission reset to default ({1}). Ignore this message if you have recently changed rank permissions.",
                           header[7], Controller.MinRank.Name);
            }
            else
            {
                Controller.MinRank = buildRank;
            }

            if (PlayerDB.IsLoaded)
            {
                // Part 2:
                if (parts[1].Length > 0)
                {
                    foreach (string playerName in parts[1].Split(' '))
                    {
                        if (!Player.IsValidPlayerName(playerName))
                        {
                            Logger.Log(LogType.Warning,
                                       "Invalid entry in zone \"{0}\" whitelist: {1}", Name, playerName);
                            continue;
                        }
                        PlayerInfo info = PlayerDB.FindPlayerInfoExact(playerName);
                        if (info == null)
                        {
                            Logger.Log(LogType.Warning,
                                       "Unrecognized player in zone \"{0}\" whitelist: {1}", Name, playerName);
                            continue; // player name not found in the DB (discarded)
                        }
                        Controller.Include(info);
                    }
                }

                // Part 3: excluded list
                if (parts[2].Length > 0)
                {
                    foreach (string playerName in parts[2].Split(' '))
                    {
                        if (!Player.IsValidPlayerName(playerName))
                        {
                            Logger.Log(LogType.Warning,
                                       "Invalid entry in zone \"{0}\" blacklist: {1}", Name, playerName);
                            continue;
                        }
                        PlayerInfo info = PlayerDB.FindPlayerInfoExact(playerName);
                        if (info == null)
                        {
                            Logger.Log(LogType.Warning,
                                       "Unrecognized player in zone \"{0}\" whitelist: {1}", Name, playerName);
                            continue; // player name not found in the DB (discarded)
                        }
                        Controller.Exclude(info);
                    }
                }
            }
            else
            {
                RawWhitelist = parts[1];
                RawBlacklist = parts[2];
            }

            // Part 4: extended header
            if (parts.Length > 3)
            {
                string[] xheader = parts[3].Split(' ');
                if (xheader[0] == "-")
                {
                    CreatedBy   = null;
                    CreatedDate = DateTime.MinValue;
                }
                else
                {
                    CreatedBy   = xheader[0];
                    CreatedDate = DateTime.Parse(xheader[1]);
                }

                if (xheader[2] == "-")
                {
                    EditedBy   = null;
                    EditedDate = DateTime.MinValue;
                }
                else
                {
                    EditedBy   = xheader[2];
                    EditedDate = DateTime.Parse(xheader[3]);
                }
            }
        }
Example #11
0
        internal static void LoadAll()
        {
            try {
                if (!Directory.Exists("./Timers"))
                {
                    return;
                }

                string[] files = Directory.GetFiles("./Timers");
                foreach (string file in files)
                {
                    if (Path.GetExtension("./Timers/" + file) != ".txt")
                    {
                        continue;
                    }
                    string[] data = File.ReadAllLines(file);

                    DateTime   start   = default(DateTime);
                    DateTime   end     = default(DateTime);
                    PlayerInfo creator = null;
                    string     message = null;

                    foreach (string line in data)
                    {
                        if (line.Contains("StartDate: "))
                        {
                            string date = line.Remove(0, "StartDate: ".Length);
                            DateTime.TryParse(date, out start);
                        }
                        else if (line.Contains("EndDate: "))
                        {
                            string date = line.Remove(0, "EndDate: ".Length);
                            DateTime.TryParse(date, out end);
                        }
                        else if (line.Contains("CreatedBy: "))
                        {
                            string creatorName = line.Remove(0, "CreatedBy: ".Length);
                            creator = PlayerDB.FindPlayerInfoExact(creatorName);
                        }
                        else if (line.Contains("Message: "))
                        {
                            message = line.Remove(0, "Creator: ".Length);
                        }
                    }

                    if (creator == null)
                    {
                        creator = Player.Console.Info;
                    }
                    if (start.Ticks == 0 || end.Ticks == 0 || message == null)
                    {
                        Player.Console.Message("Error starting a Timer: {0}, {1}, {2}, {3}", start, end, creator.Name, message);
                        continue;
                    }

                    if (end < DateTime.UtcNow)
                    {
                        Player.Console.Message("Timer Expired: {0}, {1}, {2}, {3} Time Now: {4}", start, end, creator.Name, message, DateTime.UtcNow);
                        File.Delete(file);
                        continue;
                    }

                    ChatTimer.Start((end - DateTime.UtcNow), message, creator.Name);
                }

                if (files.Length > 0)
                {
                    Player.Console.Message("All Timers Loaded. ({0})", files.Length);
                }
                else
                {
                    Player.Console.Message("No Timers Were Loaded.");
                }
            } catch (Exception ex) {
                Player.Console.Message("Timer Loader Has Crashed: {0}", ex);
            }
        }
Example #12
0
        private static void ZoneEditHandler(Player player, Command cmd)
        {
            bool   changesWereMade = false;
            string zoneName        = cmd.Next();

            if (zoneName == null)
            {
                player.Message("No zone name specified. See &H/Help ZEdit");
                return;
            }

            Zone zone = player.WorldMap.Zones.Find(zoneName);

            if (zone == null)
            {
                player.MessageNoZone(zoneName);
                return;
            }

            string name;

            while ((name = cmd.Next()) != null)
            {
                if (name.StartsWith("+"))
                {
                    if (name.Length == 1)
                    {
                        CdZoneEdit.PrintUsage(player);
                        break;
                    }
                    PlayerInfo info = PlayerDB.FindPlayerInfoOrPrintMatches(player, name.Substring(1));
                    if (info == null)
                    {
                        return;
                    }

                    // prevent players from whitelisting themselves to bypass protection
                    if (!player.Info.Rank.AllowSecurityCircumvention && player.Info == info)
                    {
                        if (!zone.Controller.Check(info))
                        {
                            player.Message("You must be {0}+&S to add yourself to this zone's whitelist.",
                                           zone.Controller.MinRank.ClassyName);
                            continue;
                        }
                    }

                    switch (zone.Controller.Include(info))
                    {
                    case PermissionOverride.Deny:
                        player.Message("{0}&S is no longer excluded from zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.None:
                        player.Message("{0}&S is now included in zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.Allow:
                        player.Message("{0}&S is already included in zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        break;
                    }
                }
                else if (name.StartsWith("-"))
                {
                    if (name.Length == 1)
                    {
                        CdZoneEdit.PrintUsage(player);
                        break;
                    }
                    PlayerInfo info = PlayerDB.FindPlayerInfoOrPrintMatches(player, name.Substring(1));
                    if (info == null)
                    {
                        return;
                    }

                    switch (zone.Controller.Exclude(info))
                    {
                    case PermissionOverride.Deny:
                        player.Message("{0}&S is already excluded from zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        break;

                    case PermissionOverride.None:
                        player.Message("{0}&S is now excluded from zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.Allow:
                        player.Message("{0}&S is no longer included in zone {1}",
                                       info.ClassyName, zone.ClassyName);
                        changesWereMade = true;
                        break;
                    }
                }
                else if (name.ToLower().StartsWith("msg="))
                {
                    zone.Message    = name.Substring(4) + " " + (cmd.NextAll() ?? "");
                    changesWereMade = true;
                    player.Message("Zedit: Custom denied messaged changed to '" + zone.Message + "'");
                    break;
                }
                else
                {
                    Rank minRank = RankManager.FindRank(name);

                    if (minRank != null)
                    {
                        // prevent players from lowering rank so bypass protection
                        if (!player.Info.Rank.AllowSecurityCircumvention &&
                            zone.Controller.MinRank > player.Info.Rank && minRank <= player.Info.Rank)
                        {
                            player.Message("You are not allowed to lower the zone's rank.");
                            continue;
                        }

                        if (zone.Controller.MinRank != minRank)
                        {
                            zone.Controller.MinRank = minRank;
                            player.Message("Permission for zone \"{0}\" changed to {1}+",
                                           zone.Name,
                                           minRank.ClassyName);
                            changesWereMade = true;
                        }
                    }
                    else
                    {
                        player.MessageNoRank(name);
                    }
                }
            }
            if (changesWereMade)
            {
                zone.Edit(player.Info);
            }
            else
            {
                player.Message("No changes were made to the zone.");
            }
        }
Example #13
0
        public Zone([NotNull] string raw, [CanBeNull] World world)
            : this()
        {
            if (raw == null)
            {
                throw new ArgumentNullException("raw");
            }
            string[] parts = raw.Split(',');

            string[] header = parts[0].Split(' ');
            Name   = header[0];
            Bounds = new BoundingBox(Int32.Parse(header[1]), Int32.Parse(header[2]), Int32.Parse(header[3]),
                                     Int32.Parse(header[4]), Int32.Parse(header[5]), Int32.Parse(header[6]));

            // If no ranks are loaded (e.g. MapConverter/MapRenderer)(
            if (RankManager.Ranks.Count > 0)
            {
                Rank buildRank = Rank.Parse(header[7]);
                // if all else fails, fall back to lowest class
                if (buildRank == null)
                {
                    if (world != null)
                    {
                        Controller.MinRank = world.BuildSecurity.MinRank;
                    }
                    else
                    {
                        Controller.ResetMinRank();
                    }
                    Logger.Log(LogType.Error,
                               "Zone: Error parsing zone definition: unknown rank \"{0}\". Permission reset to default ({1}).",
                               header[7], Controller.MinRank.Name);
                }
                else
                {
                    Controller.MinRank = buildRank;
                }
            }

            // If PlayerDB is not loaded (e.g. ConfigGUI)
            if (PlayerDB.IsLoaded)
            {
                // Part 2:
                if (parts[1].Length > 0)
                {
                    foreach (string playerName in parts[1].Split(' '))
                    {
                        if (!Player.IsValidPlayerName(playerName))
                        {
                            Logger.Log(LogType.Warning,
                                       "Invalid entry in zone \"{0}\" whitelist: {1}", Name, playerName);
                            continue;
                        }
                        PlayerInfo info = PlayerDB.FindPlayerInfoExact(playerName);
                        if (info == null)
                        {
                            Logger.Log(LogType.Warning,
                                       "Unrecognized player in zone \"{0}\" whitelist: {1}", Name, playerName);
                            continue; // player name not found in the DB (discarded)
                        }
                        Controller.Include(info);
                    }
                }

                // Part 3: excluded list
                if (parts[2].Length > 0)
                {
                    foreach (string playerName in parts[2].Split(' '))
                    {
                        if (!Player.IsValidPlayerName(playerName))
                        {
                            Logger.Log(LogType.Warning,
                                       "Invalid entry in zone \"{0}\" blacklist: {1}", Name, playerName);
                            continue;
                        }
                        PlayerInfo info = PlayerDB.FindPlayerInfoExact(playerName);
                        if (info == null)
                        {
                            Logger.Log(LogType.Warning,
                                       "Unrecognized player in zone \"{0}\" whitelist: {1}", Name, playerName);
                            continue; // player name not found in the DB (discarded)
                        }
                        Controller.Exclude(info);
                    }
                }
            }
            else
            {
                RawWhitelist = parts[1];
                RawBlacklist = parts[2];
            }

            // Part 4: extended header
            if (parts.Length > 3)
            {
                string[] xheader = parts[3].Split(' ');
                if (xheader[0] == "-")
                {
                    CreatedBy   = null;
                    CreatedDate = DateTime.MinValue;
                }
                else
                {
                    CreatedBy   = xheader[0];
                    CreatedDate = DateTime.Parse(xheader[1]);
                }

                if (xheader[2] == "-")
                {
                    EditedBy   = null;
                    EditedDate = DateTime.MinValue;
                }
                else
                {
                    EditedBy   = xheader[2];
                    EditedDate = DateTime.Parse(xheader[3]);
                }
            }
        }
Example #14
0
        internal static PlayerInfo LoadFormat2(string[] fields)
        {
            PlayerInfo info = new PlayerInfo {
                Name = fields[0]
            };

            if (fields[1].Length == 0 || !IPAddress.TryParse(fields[1], out info.LastIP))
            {
                info.LastIP = IPAddress.None;
            }

            info.Rank = Rank.Parse(fields[2]) ?? RankManager.DefaultRank;
            fields[3].ToDateTime(ref info.RankChangeDate);
            if (fields[4].Length > 0)
            {
                info.RankChangedBy = fields[4];
            }

            switch (fields[5])
            {
            case "b":
                info.BanStatus = BanStatus.Banned;
                break;

            case "x":
                info.BanStatus = BanStatus.IPBanExempt;
                break;

            default:
                info.BanStatus = BanStatus.NotBanned;
                break;
            }

            // ban information
            if (fields[6].ToDateTime(ref info.BanDate))
            {
                if (fields[7].Length > 0)
                {
                    info.BannedBy = PlayerDB.Unescape(fields[7]);
                }
                if (fields[10].Length > 0)
                {
                    info.BanReason = PlayerDB.Unescape(fields[10]);
                }
            }

            // unban information
            if (fields[8].ToDateTime(ref info.UnbanDate))
            {
                if (fields[9].Length > 0)
                {
                    info.UnbannedBy = PlayerDB.Unescape(fields[9]);
                }
                if (fields[11].Length > 0)
                {
                    info.UnbanReason = PlayerDB.Unescape(fields[11]);
                }
            }

            // failed logins
            fields[12].ToDateTime(ref info.LastFailedLoginDate);

            if (fields[13].Length > 1 || !IPAddress.TryParse(fields[13], out info.LastFailedLoginIP))      // LEGACY
            {
                info.LastFailedLoginIP = IPAddress.None;
            }
            // skip 14

            fields[15].ToDateTime(ref info.FirstLoginDate);

            // login/logout times
            fields[16].ToDateTime(ref info.LastLoginDate);
            fields[17].ToTimeSpan(out info.TotalTime);

            // stats
            if (fields[18].Length > 0)
            {
                Int32.TryParse(fields[18], out info.BlocksBuilt);
            }
            if (fields[19].Length > 0)
            {
                Int32.TryParse(fields[19], out info.BlocksDeleted);
            }
            Int32.TryParse(fields[20], out info.TimesVisited);
            if (fields[20].Length > 0)
            {
                Int32.TryParse(fields[21], out info.MessagesWritten);
            }
            // fields 22-23 are no longer in use

            if (fields[24].Length > 0)
            {
                info.PreviousRank = Rank.Parse(fields[24]);
            }
            if (fields[25].Length > 0)
            {
                info.RankChangeReason = PlayerDB.Unescape(fields[25]);
            }
            Int32.TryParse(fields[26], out info.TimesKicked);
            Int32.TryParse(fields[27], out info.TimesKickedOthers);
            Int32.TryParse(fields[28], out info.TimesBannedOthers);

            info.ID = Int32.Parse(fields[29]);
            if (info.ID < 256)
            {
                info.ID = PlayerDB.GetNextID();
            }

            byte rankChangeTypeCode;

            if (Byte.TryParse(fields[30], out rankChangeTypeCode))
            {
                info.RankChangeType = (RankChangeType)rankChangeTypeCode;
                if (!Enum.IsDefined(typeof(RankChangeType), rankChangeTypeCode))
                {
                    info.GuessRankChangeType();
                }
            }
            else
            {
                info.GuessRankChangeType();
            }

            fields[31].ToDateTime(ref info.LastKickDate);
            if (!fields[32].ToDateTime(ref info.LastSeen) || info.LastSeen < info.LastLoginDate)
            {
                info.LastSeen = info.LastLoginDate;
            }
            Int64.TryParse(fields[33], out info.BlocksDrawn);

            if (fields[34].Length > 0)
            {
                info.LastKickBy = PlayerDB.Unescape(fields[34]);
            }
            if (fields[35].Length > 0)
            {
                info.LastKickReason = PlayerDB.Unescape(fields[35]);
            }

            fields[36].ToDateTime(ref info.BannedUntil);
            info.IsFrozen = (fields[37] == "f");
            if (fields[38].Length > 0)
            {
                info.FrozenBy = PlayerDB.Unescape(fields[38]);
            }
            fields[39].ToDateTime(ref info.FrozenOn);
            fields[40].ToDateTime(ref info.MutedUntil);
            if (fields[41].Length > 0)
            {
                info.MutedBy = PlayerDB.Unescape(fields[41]);
            }
            info.Password = PlayerDB.Unescape(fields[42]);
            // fields[43] is "online", and is ignored

            byte bandwidthUseModeCode;

            if (Byte.TryParse(fields[44], out bandwidthUseModeCode))
            {
                info.BandwidthUseMode = (BandwidthUseMode)bandwidthUseModeCode;
                if (!Enum.IsDefined(typeof(BandwidthUseMode), bandwidthUseModeCode))
                {
                    info.BandwidthUseMode = BandwidthUseMode.Default;
                }
            }
            else
            {
                info.BandwidthUseMode = BandwidthUseMode.Default;
            }

            if (fields.Length > 45)
            {
                if (fields[45].Length == 0)
                {
                    info.IsHidden = false;
                }
                else
                {
                    info.IsHidden = info.Rank.Can(Permission.Hide);
                }
            }
            if (fields.Length > 46)
            {
                fields[46].ToDateTime(ref info.LastModified);
            }
            if (fields.Length > 47 && fields[47].Length > 0)
            {
                info.DisplayedName = PlayerDB.Unescape(fields[47]);
            }
            if (fields.Length > 48)
            {
                byte accountTypeCode;
                if (Byte.TryParse(fields[48], out accountTypeCode))
                {
                    info.AccountType = (AccountType)accountTypeCode;
                    if (!Enum.IsDefined(typeof(AccountType), accountTypeCode))
                    {
                        info.AccountType = AccountType.Unknown;
                    }
                }
            }

            if (info.LastSeen < info.FirstLoginDate)
            {
                info.LastSeen = info.FirstLoginDate;
            }
            if (info.LastLoginDate < info.FirstLoginDate)
            {
                info.LastLoginDate = info.FirstLoginDate;
            }

            return(info);
        }
Example #15
0
        internal static void RealmBuild(Player player, Command cmd, string worldName, string name,
                                        string NameIfRankIsName)
        {
            // Print information about the current realm
            if (worldName == null)
            {
                if (player.World == null)
                {
                    player.Message("When calling /wbuild from console, you must specify a realm name.");
                }
                else
                {
                    player.Message(player.World.BuildSecurity.GetDescription(player.World, "realm", "modified"));
                }
                return;
            }

            // Find a realm by name
            World realm = WorldManager.FindWorldOrPrintMatches(player, worldName);

            if (realm == null)
            {
                return;
            }


            if (name == null)
            {
                player.Message(realm.BuildSecurity.GetDescription(realm, "realm", "modified"));
                return;
            }

            bool changesWereMade = false;

            do
            {
                if (name.Length < 2)
                {
                    continue;
                }
                // Whitelisting individuals
                if (name.StartsWith("+"))
                {
                    PlayerInfo info;
                    if (!PlayerDB.FindPlayerInfo(name.Substring(1), out info))
                    {
                        player.Message("More than one player found matching \"{0}\"", name.Substring(1));
                        continue;
                    }
                    else if (info == null)
                    {
                        player.MessageNoPlayer(name.Substring(1));
                        continue;
                    }


                    if (realm.BuildSecurity.CheckDetailed(info) == SecurityCheckResult.Allowed)
                    {
                        player.Message("{0}&S is already allowed to build in {1}&S (by rank)",
                                       info.ClassyName, realm.ClassyName);
                        continue;
                    }

                    Player target = info.PlayerObject;
                    if (target == player)
                    {
                        target = null;                   // to avoid duplicate messages
                    }
                    switch (realm.BuildSecurity.Include(info))
                    {
                    case PermissionOverride.Deny:
                        if (realm.BuildSecurity.Check(info))
                        {
                            player.Message("{0}&S is no longer barred from building in {1}",
                                           info.ClassyName, realm.ClassyName);
                            if (target != null)
                            {
                                target.Message(
                                    "You can now build in realm {0}&S (removed from blacklist by {1}&S).",
                                    realm.ClassyName, player.ClassyName);
                            }
                        }
                        else
                        {
                            player.Message("{0}&S was removed from the build blacklist of {1}&S. " +
                                           "Player is still NOT allowed to build (by rank).",
                                           info.ClassyName, realm.ClassyName);
                            if (target != null)
                            {
                                target.Message(
                                    "You were removed from the build blacklist of realm {0}&S by {1}&S. " +
                                    "You are still NOT allowed to build (by rank).",
                                    player.ClassyName, realm.ClassyName);
                            }
                        }
                        Logger.Log(LogType.UserActivity, "{0} removed {1} from the build blacklist of {2}",
                                   player.Name, info.Name, realm.Name);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.None:
                        player.Message("{0}&S is now allowed to build in {1}",
                                       info.ClassyName, realm.ClassyName);
                        if (target != null)
                        {
                            target.Message("You can now build in realm {0}&S (whitelisted by {1}&S).",
                                           realm.ClassyName, player.ClassyName);
                        }
                        Logger.Log(LogType.UserActivity, "{0} added {1} to the build whitelist on realm {2}",
                                   player.Name, info.Name, realm.Name);
                        break;

                    case PermissionOverride.Allow:
                        player.Message("{0}&S is already on the build whitelist of {1}",
                                       info.ClassyName, realm.ClassyName);
                        break;
                    }

                    // Blacklisting individuals
                }
                else if (name.StartsWith("-"))
                {
                    PlayerInfo info;
                    if (!PlayerDB.FindPlayerInfo(name.Substring(1), out info))
                    {
                        player.Message("More than one player found matching \"{0}\"", name.Substring(1));
                        continue;
                    }
                    else if (info == null)
                    {
                        player.MessageNoPlayer(name.Substring(1));
                        continue;
                    }

                    if (realm.BuildSecurity.CheckDetailed(info) == SecurityCheckResult.RankTooHigh ||
                        realm.BuildSecurity.CheckDetailed(info) == SecurityCheckResult.RankTooLow)
                    {
                        player.Message("{0}&S is already barred from building in {1}&S (by rank)",
                                       info.ClassyName, realm.ClassyName);
                        continue;
                    }

                    Player target = info.PlayerObject;
                    if (target == player)
                    {
                        target = null;                   // to avoid duplicate messages
                    }
                    switch (realm.BuildSecurity.Exclude(info))
                    {
                    case PermissionOverride.Deny:
                        player.Message("{0}&S is already on build blacklist of {1}",
                                       info.ClassyName, realm.ClassyName);
                        break;

                    case PermissionOverride.None:
                        player.Message("{0}&S is now barred from building in {1}",
                                       info.ClassyName, realm.ClassyName);
                        if (target != null)
                        {
                            target.Message("&WYou were barred by {0}&W from building in realm {1}",
                                           player.ClassyName, realm.ClassyName);
                        }
                        Logger.Log(LogType.UserActivity, "{0} added {1} to the build blacklist on realm {2}",
                                   player.Name, info.Name, realm.Name);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.Allow:
                        if (realm.BuildSecurity.Check(info))
                        {
                            player.Message("{0}&S is no longer on the build whitelist of {1}&S. " +
                                           "Player is still allowed to build (by rank).",
                                           info.ClassyName, realm.ClassyName);
                            if (target != null)
                            {
                                target.Message(
                                    "You were removed from the build whitelist of realm {0}&S by {1}&S. " +
                                    "You are still allowed to build (by rank).",
                                    player.ClassyName, realm.ClassyName);
                            }
                        }
                        else
                        {
                            player.Message("{0}&S is no longer allowed to build in {1}",
                                           info.ClassyName, realm.ClassyName);
                            if (target != null)
                            {
                                target.Message(
                                    "&WYou can no longer build in realm {0}&W (removed from whitelist by {1}&W).",
                                    realm.ClassyName, player.ClassyName);
                            }
                        }
                        Logger.Log(LogType.UserActivity, "{0} removed {1} from the build whitelist on realm {2}",
                                   player.Name, info.Name, realm.Name);
                        changesWereMade = true;
                        break;
                    }

                    // Setting minimum rank
                }
                else
                {
                    Rank rank = RankManager.FindRank(name);
                    if (rank == null)
                    {
                        player.MessageNoRank(name);
                    }
                    else if (!player.Info.Rank.AllowSecurityCircumvention &&
                             realm.BuildSecurity.MinRank > rank &&
                             realm.BuildSecurity.MinRank > player.Info.Rank)
                    {
                        player.Message("&WYou must be ranked {0}&W+ to lower build restrictions for realm {1}",
                                       realm.BuildSecurity.MinRank.ClassyName, realm.ClassyName);
                    }
                    else
                    {
                        // list players who are redundantly blacklisted
                        var          exceptionList    = realm.BuildSecurity.ExceptionList;
                        PlayerInfo[] noLongerExcluded =
                            exceptionList.Excluded.Where(excludedPlayer => excludedPlayer.Rank < rank).ToArray();
                        if (noLongerExcluded.Length > 0)
                        {
                            player.Message("Following players no longer need to be blacklisted on realm {0}&S: {1}",
                                           realm.ClassyName,
                                           noLongerExcluded.JoinToClassyString());
                        }

                        // list players who are redundantly whitelisted
                        PlayerInfo[] noLongerIncluded =
                            exceptionList.Included.Where(includedPlayer => includedPlayer.Rank >= rank).ToArray();
                        if (noLongerIncluded.Length > 0)
                        {
                            player.Message("Following players no longer need to be whitelisted on realm {0}&S: {1}",
                                           realm.ClassyName,
                                           noLongerIncluded.JoinToClassyString());
                        }

                        // apply changes
                        realm.BuildSecurity.MinRank = rank;
                        changesWereMade             = true;
                        if (realm.BuildSecurity.MinRank == RankManager.LowestRank)
                        {
                            Server.Message("{0}&S allowed anyone to build on realm {1}",
                                           player.ClassyName, realm.ClassyName);
                        }
                        else
                        {
                            Server.Message("{0}&S allowed only {1}+&S to build in realm {2}",
                                           player.ClassyName, realm.BuildSecurity.MinRank.ClassyName, realm.ClassyName);
                        }
                        Logger.Log(LogType.UserActivity, "{0} set build rank for realm {1} to {2}+",
                                   player.Name, realm.Name, realm.BuildSecurity.MinRank.Name);
                    }
                }
            } while ((name = cmd.Next()) != null);

            if (changesWereMade)
            {
                WorldManager.SaveWorldList();
            }
        }
Example #16
0
        internal static void RealmAccess(Player player, Command cmd, string worldName, string name)
        {
            // Print information about the current realm
            if (worldName == null)
            {
                if (player.World == null)
                {
                    player.Message("Error.");
                }
                else
                {
                    player.Message(player.World.AccessSecurity.GetDescription(player.World, "realm", "accessed"));
                }
                return;
            }

            // Find a realm by name
            World realm = WorldManager.FindWorldOrPrintMatches(player, worldName);

            if (realm == null)
            {
                return;
            }


            if (name == null)
            {
                player.Message(realm.AccessSecurity.GetDescription(realm, "realm", "accessed"));
                return;
            }
            if (realm == WorldManager.MainWorld)
            {
                player.Message("The main realm cannot have access restrictions.");
                return;
            }

            bool changesWereMade = false;

            do
            {
                if (name.Length < 2)
                {
                    continue;
                }
                // Whitelisting individuals
                if (name.StartsWith("+"))
                {
                    PlayerInfo info;
                    if (!PlayerDB.FindPlayerInfo(name.Substring(1), out info))
                    {
                        player.Message("More than one player found matching \"{0}\"", name.Substring(1));
                        continue;
                    }
                    else if (info == null)
                    {
                        player.MessageNoPlayer(name.Substring(1));
                        continue;
                    }

                    // prevent players from whitelisting themselves to bypass protection


                    if (realm.AccessSecurity.CheckDetailed(info) == SecurityCheckResult.Allowed)
                    {
                        player.Message("{0}&S is already allowed to access {1}&S (by rank)",
                                       info.ClassyName, realm.ClassyName);
                        continue;
                    }

                    Player target = info.PlayerObject;
                    if (target == player)
                    {
                        target = null;                   // to avoid duplicate messages
                    }
                    switch (realm.AccessSecurity.Include(info))
                    {
                    case PermissionOverride.Deny:
                        if (realm.AccessSecurity.Check(info))
                        {
                            player.Message("{0}&S is unbanned from Realm {1}",
                                           info.ClassyName, realm.ClassyName);
                            if (target != null)
                            {
                                target.Message(
                                    "You are now unbanned from Realm {0}&S (removed from blacklist by {1}&S).",
                                    realm.ClassyName, player.ClassyName);
                            }
                        }
                        else
                        {
                            player.Message("{0}&S was unbanned from Realm {1}&S. " +
                                           "Player is still NOT allowed to join (by rank).",
                                           info.ClassyName, realm.ClassyName);
                            if (target != null)
                            {
                                target.Message("You were Unbanned from Realm {0}&S by {1}&S. " +
                                               "You are still NOT allowed to join (by rank).",
                                               player.ClassyName, realm.ClassyName);
                            }
                        }
                        Logger.Log(LogType.UserActivity, "{0} removed {1} from the access blacklist of {2}",
                                   player.Name, info.Name, realm.Name);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.None:
                        player.Message("{0}&S is now allowed to access {1}",
                                       info.ClassyName, realm.ClassyName);
                        if (target != null)
                        {
                            target.Message("You can now access realm {0}&S (whitelisted by {1}&S).",
                                           realm.ClassyName, player.ClassyName);
                        }
                        Logger.Log(LogType.UserActivity, "{0} added {1} to the access whitelist on realm {2}",
                                   player.Name, info.Name, realm.Name);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.Allow:
                        player.Message("{0}&S is already on the access whitelist of {1}",
                                       info.ClassyName, realm.ClassyName);
                        break;
                    }

                    // Blacklisting individuals
                }
                else if (name.StartsWith("-"))
                {
                    PlayerInfo info;
                    if (!PlayerDB.FindPlayerInfo(name.Substring(1), out info))
                    {
                        player.Message("More than one player found matching \"{0}\"", name.Substring(1));
                        continue;
                    }
                    else if (info == null)
                    {
                        player.MessageNoPlayer(name.Substring(1));
                        continue;
                    }

                    if (realm.AccessSecurity.CheckDetailed(info) == SecurityCheckResult.RankTooHigh ||
                        realm.AccessSecurity.CheckDetailed(info) == SecurityCheckResult.RankTooLow)
                    {
                        player.Message("{0}&S is already barred from accessing {1}&S (by rank)",
                                       info.ClassyName, realm.ClassyName);
                        continue;
                    }

                    Player target = info.PlayerObject;
                    if (target == player)
                    {
                        target = null;                   // to avoid duplicate messages
                    }
                    switch (realm.AccessSecurity.Exclude(info))
                    {
                    case PermissionOverride.Deny:
                        player.Message("{0}&S is already banned from Realm {1}",
                                       info.ClassyName, realm.ClassyName);
                        break;

                    case PermissionOverride.None:
                        player.Message("{0}&S is now banned from accessing {1}",
                                       info.ClassyName, realm.ClassyName);
                        if (target != null)
                        {
                            target.Message("&WYou were banned by {0}&W from accessing realm {1}",
                                           player.ClassyName, realm.ClassyName);
                        }
                        Logger.Log(LogType.UserActivity, "{0} added {1} to the access blacklist on realm {2}",
                                   player.Name, info.Name, realm.Name);
                        changesWereMade = true;
                        break;

                    case PermissionOverride.Allow:
                        if (realm.AccessSecurity.Check(info))
                        {
                            player.Message("{0}&S is no longer on the access whitelist of {1}&S. " +
                                           "Player is still allowed to join (by rank).",
                                           info.ClassyName, realm.ClassyName);
                            if (target != null)
                            {
                                target.Message("You were banned from Realm {0}&S by {1}&S. " +
                                               "You are still allowed to join (by rank).",
                                               player.ClassyName, realm.ClassyName);
                            }
                        }
                        else
                        {
                            player.Message("{0}&S is no longer allowed to access {1}",
                                           info.ClassyName, realm.ClassyName);
                            if (target != null)
                            {
                                target.Message("&WYou were banned from Realm {0}&W (Banned by {1}&W).",
                                               realm.ClassyName, player.ClassyName);
                            }
                        }
                        Logger.Log(LogType.UserActivity, "{0} removed {1} from the access whitelist on realm {2}",
                                   player.Name, info.Name, realm.Name);
                        changesWereMade = true;
                        break;
                    }

                    // Setting minimum rank
                }
                else
                {
                    Rank rank = RankManager.FindRank(name);
                    if (rank == null)
                    {
                        player.MessageNoRank(name);
                    }

                    else
                    {
                        // list players who are redundantly blacklisted
                        var          exceptionList    = realm.AccessSecurity.ExceptionList;
                        PlayerInfo[] noLongerExcluded =
                            exceptionList.Excluded.Where(excludedPlayer => excludedPlayer.Rank < rank).ToArray();
                        if (noLongerExcluded.Length > 0)
                        {
                            player.Message(
                                "Following players no longer need to be blacklisted to be barred from {0}&S: {1}",
                                realm.ClassyName,
                                noLongerExcluded.JoinToClassyString());
                        }

                        // list players who are redundantly whitelisted
                        PlayerInfo[] noLongerIncluded =
                            exceptionList.Included.Where(includedPlayer => includedPlayer.Rank >= rank).ToArray();
                        if (noLongerIncluded.Length > 0)
                        {
                            player.Message("Following players no longer need to be whitelisted to access {0}&S: {1}",
                                           realm.ClassyName,
                                           noLongerIncluded.JoinToClassyString());
                        }

                        // apply changes
                        realm.AccessSecurity.MinRank = rank;
                        changesWereMade = true;
                        if (realm.AccessSecurity.MinRank == RankManager.LowestRank)
                        {
                            Server.Message("{0}&S made the realm {1}&S accessible to everyone.",
                                           player.ClassyName, realm.ClassyName);
                        }
                        else
                        {
                            Server.Message("{0}&S made the realm {1}&S accessible only by {2}+",
                                           player.ClassyName, realm.ClassyName,
                                           realm.AccessSecurity.MinRank.ClassyName);
                        }
                        Logger.Log(LogType.UserActivity, "{0} set access rank for realm {1} to {2}+",
                                   player.Name, realm.Name, realm.AccessSecurity.MinRank.Name);
                    }
                }
            } while ((name = cmd.Next()) != null);

            if (changesWereMade)
            {
                var playersWhoCantStay = realm.Players.Where(p => !p.CanJoin(realm));
                foreach (Player p in playersWhoCantStay)
                {
                    p.Message("&WYou are no longer allowed to join realm {0}", realm.ClassyName);
                    p.JoinWorld(WorldManager.MainWorld, WorldChangeReason.PermissionChanged);
                }

                WorldManager.SaveWorldList();
            }
        }