// This constructor is used to create dummy players (such as Console and /dummy) // It will soon be replaced by a generic Entity class internal Player( World _world, string _name ) { world = _world; name = _name; nick = name; info = new PlayerInfo( _name, ClassList.highestClass ); }
// This constructor is used to create dummy players (such as Console and /dummy) // It will soon be replaced by a generic Entity class internal Player( World world, string name ) { if( name == null ) throw new ArgumentNullException( "name" ); World = world; Info = new PlayerInfo( name, RankManager.HighestRank, true, RankChangeType.AutoPromoted ); spamBlockLog = new Queue<DateTime>( Info.Rank.AntiGriefBlocks ); ResetAllBinds(); }
public void Create( BoundingBox bounds, PlayerInfo createdBy ) { if( bounds == null ) throw new ArgumentNullException( "bounds" ); if( createdBy == null ) throw new ArgumentNullException( "createdBy" ); CreatedDate = DateTime.UtcNow; Bounds = bounds; CreatedBy = createdBy; }
// Throws a PlayerOpException if reason is required but missing. internal static void CheckKickReason( [CanBeNull] string reason, [NotNull] Player player, PlayerInfo targetInfo ) { if( player == null ) throw new ArgumentNullException( "player" ); if( ConfigKey.RequireKickReason.Enabled() && String.IsNullOrEmpty( reason ) ) { const string msg = "Please specify a kick reason."; const string colorMsg = "&S" + msg; throw new PlayerOpException( player, targetInfo, PlayerOpExceptionCode.ReasonRequired, msg, colorMsg ); } }
/// <summary> Adds a new PlayerInfo entry for a player who has never been online, by name. </summary> /// <returns> A newly-created PlayerInfo entry. </returns> public PlayerInfo AddUnrecognizedPlayer( string name, Rank startingRank, RankChangeType rankChangeType ) { if( name == null ) throw new ArgumentNullException( "name" ); if( startingRank == null ) throw new ArgumentNullException( "startingRank" ); int id = GetNextID(); PlayerInfo info = new PlayerInfo( id, name, startingRank, rankChangeType, false ); trie.Add( name, info ); return info; }
/// <summary> Adds a new PlayerInfo entry for an actual, logged-in player. </summary> /// <returns> A newly-created PlayerInfo entry. </returns> public PlayerInfo AddPlayer( string name, Rank startingRank, RankChangeType rankChangeType, IPAddress address ) { if( name == null ) throw new ArgumentNullException( "name" ); if( address == null ) throw new ArgumentNullException( "address" ); int id = GetNextID(); PlayerInfo info = new PlayerInfo( id, name, startingRank, rankChangeType, address ); trie.Add( name, info ); return info; }
public bool CanRevoke( PlayerInfo player ) { PermissionLimits limits = GetLimit( player ); if( limits == null ) { return false; } else { return limits.CanRevoke; } }
// Normal constructor internal Player( World _world, string _name, Session _session, Position _pos ) { world = _world; name = _name; nick = name; session = _session; pos = _pos; info = world.db.FindPlayerInfo( this ); }
internal static PlayerInfo AddSuperPlayer( ReservedPlayerID id, [NotNull] string name, [NotNull] Rank rank ) { if( name == null ) throw new ArgumentNullException( "name" ); CheckIfLoaded(); PlayerInfo newInfo = new PlayerInfo( (int)id, name, rank, RankChangeType.AutoPromoted, true ) { RaisePropertyChangedEvents = true }; return newInfo; }
// Normal constructor internal Player( World world, string name, Session session, Position position ) { if( name == null ) throw new ArgumentNullException( "name" ); if( session == null ) throw new ArgumentNullException( "session" ); World = world; Session = session; Position = position; Info = PlayerDB.FindOrCreateInfoForPlayer( name, session.IP ); spamBlockLog = new Queue<DateTime>( Info.Rank.AntiGriefBlocks ); ResetAllBinds(); }
PermissionLimits GetPlayerLimit( PlayerInfo player ) { PermissionLimits limiter; if( playerInclusions.TryGetValue( player.Name, out limiter ) ) { return limiter; } else if( Parent != null ) { return Parent.GetPlayerLimit( player ); } else { return null; } }
public bool Can( PlayerInfo player, int quantity ) { if( ( Node.Flags & PermissionFlags.NeedsQuantity ) == 0 ) { throw new PermissionCheckException( "Quantity limit is not applicable to " + Node.Name ); } PermissionLimits limits = GetLimit( player ); if( limits == null ) { return false; } else { return ( limits.MaxQuantity <= quantity ); } }
//Function to format and return a player's score entry. Returns null if no score found public static String GetPlayerScoreEntry( PlayerInfo player ) { string toReturn = null; foreach ( String s in PlayerKillScores ) { if ( s.Contains( '$' ) ) { if ( s.Split( '$' )[0] == player.Name ) { toReturn = s; } } } return toReturn; }
public PlayerOpException( [NotNull] Player player, PlayerInfo target, PlayerOpExceptionCode errorCode, [NotNull] string message, [NotNull] string messageColored ) : base( message ) { if( player == null ) throw new ArgumentNullException( "player" ); if( message == null ) throw new ArgumentNullException( "message" ); if( messageColored == null ) throw new ArgumentNullException( "messageColored" ); Player = player; Target = target; ErrorCode = errorCode; MessageColored = messageColored; }
// Throws a PlayerOpException if reason is required but missing. internal static void CheckRankChangeReason( [CanBeNull] string reason, [NotNull] Player player, PlayerInfo targetInfo, bool promoting ) { if( player == null ) throw new ArgumentNullException( "player" ); if( ConfigKey.RequireRankChangeReason.Enabled() && String.IsNullOrEmpty( reason ) ) { string msg; if( promoting ) { msg = "Please specify a promotion reason."; } else { msg = "Please specify a demotion reason."; } string colorMsg = "&S" + msg; throw new PlayerOpException( player, targetInfo, PlayerOpExceptionCode.ReasonRequired, msg, colorMsg ); } }
public PlayerInfo FindPlayerInfo( Player player ) { if( player == null ) return null; locker.EnterWriteLock(); PlayerInfo info = tree.Get( player.name ); if( info == null ) { info = new PlayerInfo( world, player ); tree.Add( player.name, info ); list.Add( info ); } locker.ExitWriteLock(); return info; }
public static bool FindPlayerInfo( string name, out PlayerInfo info ) { if( name == null ) { info = null; return false; } bool noDupe; locker.EnterWriteLock(); noDupe = tree.Get( name, out info ); locker.ExitWriteLock(); return noDupe; }
// returns the PREVIOUS state of the player public PermissionOverride Include( PlayerInfo info ) { if( info == null ) throw new ArgumentNullException( "info" ); lock( playerPermissionListLock ) { if( includedPlayers.ContainsValue( info ) ) { UpdatePlayerListCache(); return PermissionOverride.Allow; } else if( excludedPlayers.ContainsValue( info ) ) { excludedPlayers.Remove( info.Name.ToLower() ); UpdatePlayerListCache(); return PermissionOverride.Deny; } else { includedPlayers.Add( info.Name.ToLower(), info ); UpdatePlayerListCache(); return PermissionOverride.None; } } }
public static PlayerInfo AddFakeEntry( string name, RankChangeType rankChangeType ) { if( name == null ) throw new ArgumentNullException( "name" ); PlayerInfo info; lock( AddLocker ) { info = Trie.Get( name ); if( info != null ) throw new ArgumentException( "A PlayerDB entry already exists for this name." ); var e = new PlayerInfoCreatingEventArgs( name, IPAddress.None, RankManager.DefaultRank, true ); Server.RaisePlayerInfoCreatingEvent( e ); if( e.Cancel ) throw new OperationCanceledException( "Cancelled by a plugin." ); info = new PlayerInfo( name, e.StartingRank, false, rankChangeType ); List.Add( info ); Trie.Add( info.Name, info ); UpdateCache(); } Server.RaisePlayerInfoCreatedEvent( info, false ); return info; }
// Adds a name to the tree. public bool Add( string name, PlayerInfo payload ) { StringNode temp = root; int code; for( int i = 0; i < name.Length; i++ ) { code = CharCode( name[i] ); if( temp.children[code] == null ) { temp.children[code] = new StringNode(); } if( temp.tag == EMPTY ) { temp.tag = (byte)code; } else { temp.tag = MULTI; } temp = temp.children[code]; } if( temp.payload != null ) return false; temp.payload = payload; count++; return true; }
// Searches for players starting with namePart. // Returns false if more than one name matched. // Returns true and sets info to null if no names matched. public bool Get( string namePart, out PlayerInfo info ) { StringNode temp = root; int code; for( int i = 0; i < namePart.Length; i++ ) { code = CharCode( namePart[i] ); if( temp.children[code] == null ) { info = null; return true; // early detection of no matches } temp = temp.children[code]; } if( temp.payload != null ) { info = temp.payload; return true; // exact match } else if( temp.tag == MULTI ) { info = null; return false; // multiple matches } for( ; temp.tag < MULTI; temp = temp.children[temp.tag] ) ; info = temp.payload; return true; // one autocompleted match }
public void Load() { if( File.Exists( FileName ) ) { using( StreamReader reader = File.OpenText( FileName ) ) { reader.ReadLine(); // header while( !reader.EndOfStream ) { string[] fields = reader.ReadLine().Split( ',' ); if( fields.Length == PlayerInfo.fieldCount ) { try { PlayerInfo info = new PlayerInfo(world, fields ); tree.Add( info.name, info ); list.Add( info ); } catch( FormatException ex ) { world.log.Log( "PlayerDB.Load: Could not parse a record: {0}.", LogType.Error, ex.Message ); } catch( IOException ex ) { world.log.Log( "PlayerDB.Load: Error while trying to read from file: {0}.", LogType.Error, ex.Message ); } } } } world.log.Log( "PlayerDB.Load: Done loading player DB ({0} records).", LogType.Debug, tree.Count() ); } else { world.log.Log( "PlayerDB.Load: No player DB file found.", LogType.Warning ); } }
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]); } } }
public bool Unignore( PlayerInfo other ) { lock( ignoreLock ) { if( ignoreList.Contains( other ) ) { ignoreList.Remove( other ); return true; } else { return false; } } }
/// <summary> Unbans given IP address and all accounts on that IP. </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> /// <exception cref="ArgumentNullException"> targetAddress or player is null. </exception> /// <exception cref="PlayerOpException"> Permission or configuration issues arise, or if everyone has already been unbanned. </exception> 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 = reason.Trim(' '); } if (reason != null && reason.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; lock ( BanListLock ) { CheckIfLoaded(); // 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); } }
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]); } } }
internal static void SwapPlayerInfo([NotNull] PlayerInfo p1, [NotNull] PlayerInfo p2) { if (p1 == null) { throw new ArgumentNullException("p1"); } if (p2 == null) { throw new ArgumentNullException("p2"); } lock ( AddLocker ) { lock ( SaveLoadLocker ) { if (p1.IsOnline || p2.IsOnline) { throw new Exception("Both players must be offline to swap info."); } Swap(ref p1.BanDate, ref p2.BanDate); Swap(ref p1.BandwidthUseMode, ref p2.BandwidthUseMode); Swap(ref p1.BanStatus, ref p2.BanStatus); Swap(ref p1.BannedBy, ref p2.BannedBy); Swap(ref p1.BannedUntil, ref p2.BannedUntil); Swap(ref p1.BanReason, ref p2.BanReason); Swap(ref p1.BlocksBuilt, ref p2.BlocksBuilt); Swap(ref p1.BlocksDeleted, ref p2.BlocksDeleted); Swap(ref p1.BlocksDrawn, ref p2.BlocksDrawn); Swap(ref p1.DisplayedName, ref p2.DisplayedName); Swap(ref p1.FirstLoginDate, ref p2.FirstLoginDate); Swap(ref p1.FrozenBy, ref p2.FrozenBy); Swap(ref p1.FrozenOn, ref p2.FrozenOn); Swap(ref p1.ID, ref p2.ID); Swap(ref p1.IsFrozen, ref p2.IsFrozen); //Swap( ref p1.IsHidden, ref p2.IsHidden ); Swap(ref p1.LastFailedLoginDate, ref p2.LastFailedLoginDate); Swap(ref p1.LastFailedLoginIP, ref p2.LastFailedLoginIP); //Swap( ref p1.LastIP, ref p2.LastIP ); Swap(ref p1.LastKickBy, ref p2.LastKickBy); Swap(ref p1.LastKickDate, ref p2.LastKickDate); Swap(ref p1.LastKickReason, ref p2.LastKickReason); //Swap( ref p1.LastLoginDate, ref p2.LastLoginDate ); //Swap( ref p1.LastSeen, ref p2.LastSeen ); //Swap( ref p1.LeaveReason, ref p2.LeaveReason ); Swap(ref p1.MessagesWritten, ref p2.MessagesWritten); Swap(ref p1.MutedBy, ref p2.MutedBy); Swap(ref p1.MutedUntil, ref p2.MutedUntil); //Swap( ref p1.Name, ref p2.Name ); //Swap( ref p1.Online, ref p2.Online ); Swap(ref p1.Password, ref p2.Password); //Swap( ref p1.PlayerObject, ref p2.PlayerObject ); Swap(ref p1.PreviousRank, ref p2.PreviousRank); Rank p1Rank = p1.Rank; p1.Rank = p2.Rank; p2.Rank = p1Rank; Swap(ref p1.RankChangeDate, ref p2.RankChangeDate); Swap(ref p1.RankChangedBy, ref p2.RankChangedBy); Swap(ref p1.RankChangeReason, ref p2.RankChangeReason); Swap(ref p1.RankChangeType, ref p2.RankChangeType); Swap(ref p1.TimesBannedOthers, ref p2.TimesBannedOthers); Swap(ref p1.TimesKicked, ref p2.TimesKicked); Swap(ref p1.TimesKickedOthers, ref p2.TimesKickedOthers); Swap(ref p1.TimesVisited, ref p2.TimesVisited); Swap(ref p1.TotalTime, ref p2.TotalTime); Swap(ref p1.UnbanDate, ref p2.UnbanDate); Swap(ref p1.UnbannedBy, ref p2.UnbannedBy); Swap(ref p1.UnbanReason, ref p2.UnbanReason); list.Sort(PlayerIDComparer.Instance); } } }
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); } } }
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."); } } }
public bool IsIgnoring( PlayerInfo other ) { lock( ignoreLock ) { return ignoreList.Contains( other ); } }
/// <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> /// <exception cref="ArgumentNullException"> targetAddress or player is null. </exception> /// <exception cref="PlayerOpException"> Permission or configuration issues arise, or if everyone has already been banned. </exception> 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 = reason.Trim(' '); } if (reason != null && reason.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; lock ( BanListLock ) { CheckIfLoaded(); // 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++) { if (targetsOnline[i].Info.BanStatus != BanStatus.IPBanExempt) { targetsOnline[i].Kick(kickReason, LeaveReason.BanAll); } } } }
// Throws a PlayerOpException if reason is required but missing. internal static void CheckKickReason([CanBeNull] string reason, [NotNull] Player player, PlayerInfo targetInfo) { if (player == null) { throw new ArgumentNullException("player"); } if (ConfigKey.RequireKickReason.Enabled() && String.IsNullOrEmpty(reason)) { const string msg = "Please specify a kick reason."; const string colorMsg = "&S" + msg; throw new PlayerOpException(player, targetInfo, PlayerOpExceptionCode.ReasonRequired, msg, colorMsg); } }
public static PlayerInfo FindPlayerInfoOrPrintMatches([NotNull] Player player, [NotNull] string partialName, bool includeSelf) { if (player == null) { throw new ArgumentNullException("player"); } if (partialName == null) { throw new ArgumentNullException("partialName"); } CheckIfLoaded(); // If name starts with '!', return matches for online players only if (partialName.Length > 1 && partialName[0] == '!') { partialName = partialName.Substring(1); Player targetPlayer = Server.FindPlayerOrPrintMatches(player, partialName, includeSelf, false, true); if (targetPlayer != null) { return(targetPlayer.Info); } else { player.Message("No online players found matching \"{0}\"", partialName); return(null); } } // Repeat last-used player name if (partialName == "-") { if (player.LastUsedPlayerName != null) { partialName = player.LastUsedPlayerName; } else { player.Message("Cannot repeat player name: you haven't used any names yet."); return(null); } } // Make sure player name is valid if (!Player.ContainsValidCharacters(partialName)) { player.MessageInvalidPlayerName(partialName); return(null); } // Search for exact matches first PlayerInfo target = FindPlayerInfoExact(partialName); // If no exact match was found, look for partial matches if (target == null || target == player.Info && !includeSelf) { PlayerInfo[] targets = FindPlayers(partialName); if (!includeSelf && targets.Length > 1) { targets = targets.Where(p => p != player.Info).ToArray(); } if (targets.Length == 0) { // No matches player.MessageNoPlayer(partialName); return(null); } else if (targets.Length > 1) { // More than one match Array.Sort(targets, new PlayerInfoComparer(player)); player.MessageManyMatches("player", targets.Take(25).ToArray()); return(null); } // else: one match! target = targets[0]; } // If a single name has been found, set it as LastUsedPlayerName if (includeSelf || target != player.Info) { player.LastUsedPlayerName = target.Name; } return(target); }
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."); } }
internal static void PlayerUnbannedHandler(PlayerInfo player, Player unbanner, string reason) { PlayerSomethingMessage(unbanner, "unbanned", player, reason); }
/// <summary> Searches for player names starting with namePart, returning just one or none of the matches. </summary> /// <param name="partialName"> Partial or full player name. </param> /// <param name="result"> PlayerInfo to output (will be set to null if no single match was found). </param> /// <returns> true if one or zero matches were found, false if multiple matches were found. </returns> internal static bool FindOneByPartialName( [NotNull] string partialName, [CanBeNull] out PlayerInfo result ) { if( partialName == null ) throw new ArgumentNullException( "partialName" ); CheckIfLoaded(); return provider.FindOneByPartialName( partialName, out result ); }
public bool Ignore( PlayerInfo other ) { lock( ignoreLock ) { if( !ignoreList.Contains( other ) ) { ignoreList.Add( other ); return true; } else { return false; } } }
/// <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> /// <exception cref="ArgumentNullException"> targetAddress or player is null. </exception> /// <exception cref="PlayerOpException"> Permission or configuration issues arise, or if IP is already banned. </exception> 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 = reason.Trim(' '); } if (reason != null && reason.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"); } lock ( BanListLock ) { CheckIfLoaded(); // 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); } } }
static bool PlayerIsInactive([NotNull] IDictionary <IPAddress, List <PlayerInfo> > playersByIP, [NotNull] PlayerInfo player, bool checkIP) { if (playersByIP == null) { throw new ArgumentNullException("playersByIP"); } if (player == null) { throw new ArgumentNullException("player"); } if (player.BanStatus != BanStatus.NotBanned || player.UnbanDate != DateTime.MinValue || player.IsFrozen || player.IsMuted || player.TimesKicked != 0 || player.Rank != RankManager.DefaultRank || player.PreviousRank != null) { return(false); } if (player.TotalTime.TotalMinutes > 30 || player.TimeSinceLastSeen.TotalDays < 30) { return(false); } if (IPBanList.Get(player.LastIP) != null) { return(false); } if (checkIP) { return(playersByIP[player.LastIP].All(other => (other == player) || PlayerIsInactive(playersByIP, other, false))); } return(true); }
// warn player if others are still online from target's IP static void WarnIfOtherPlayersOnIP( Player player, PlayerInfo targetInfo, Player except ) { Player[] otherPlayers = Server.Players.FromIP( targetInfo.LastIP ) .Except( except ) .ToArray(); if( otherPlayers.Length > 0 ) { player.Message( "&WWarning: Other player(s) share IP with {0}&W: {1}", targetInfo.ClassyName, otherPlayers.JoinToClassyString() ); } }
public static void Untempban(Player player, PlayerInfo target) { if (!target.IsBanned) return; else target.Unban(player, "Tempban Expired", true, true); }
public void Edit( PlayerInfo editedBy ) { if( editedBy == null ) throw new ArgumentNullException( "editedBy" ); EditedDate = DateTime.UtcNow; EditedBy = editedBy; }
static void CheckPaidStatusCallback(SchedulerTask task) { PlayerInfo info = (PlayerInfo)task.UserState; info.AccountType = Player.CheckPaidStatus(info.Name); }
public static IEnumerable <Player> NotIgnoring([NotNull] this IEnumerable <Player> source, [NotNull] PlayerInfo playerInfo) { if (source == null) { throw new ArgumentNullException("source"); } if (playerInfo == null) { throw new ArgumentNullException("playerInfo"); } foreach (Player otherPlayer in source) { if (!otherPlayer.IsIgnoring(playerInfo)) { yield return(otherPlayer); } } }
// freeze target if player is allowed to do so static void FreezeIfAllowed( Player player, PlayerInfo targetInfo ) { if( targetInfo.IsOnline && !targetInfo.IsFrozen && player.Can( Permission.Freeze, targetInfo.Rank ) ) { try { targetInfo.Freeze( player, true, true ); player.Message( "Player {0}&S has been frozen while you retry.", targetInfo.ClassyName ); } catch( PlayerOpException ) { } } }
internal static PlayerInfo LoadFormat1(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].ToDateTimeLegacy(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].ToDateTimeLegacy(ref info.BanDate)) { if (fields[7].Length > 0) { info.BannedBy = Unescape(fields[7]); } if (fields[10].Length > 0) { info.BanReason = Unescape(fields[10]); } } // unban information if (fields[8].ToDateTimeLegacy(ref info.UnbanDate)) { if (fields[9].Length > 0) { info.UnbannedBy = Unescape(fields[9]); } if (fields[11].Length > 0) { info.UnbanReason = Unescape(fields[11]); } } // failed logins fields[12].ToDateTimeLegacy(ref info.LastFailedLoginDate); if (fields[13].Length > 1 || !IPAddress.TryParse(fields[13], out info.LastFailedLoginIP)) // LEGACY { info.LastFailedLoginIP = IPAddress.None; } // skip 14 fields[15].ToDateTimeLegacy(ref info.FirstLoginDate); // login/logout times fields[16].ToDateTimeLegacy(ref info.LastLoginDate); fields[17].ToTimeSpanLegacy(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.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 = 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].ToDateTimeLegacy(ref info.LastKickDate); if (!fields[32].ToDateTimeLegacy(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 = Unescape(fields[34]); } if (fields[34].Length > 0) { info.LastKickReason = Unescape(fields[35]); } fields[36].ToDateTimeLegacy(ref info.BannedUntil); info.IsFrozen = (fields[37] == "f"); if (fields[38].Length > 0) { info.FrozenBy = Unescape(fields[38]); } fields[39].ToDateTimeLegacy(ref info.FrozenOn); fields[40].ToDateTimeLegacy(ref info.MutedUntil); if (fields[41].Length > 0) { info.MutedBy = Unescape(fields[41]); } info.Password = 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 (info.LastSeen < info.FirstLoginDate) { info.LastSeen = info.FirstLoginDate; } if (info.LastLoginDate < info.FirstLoginDate) { info.LastLoginDate = info.FirstLoginDate; } return(info); }
internal static PlayerInfo LoadFormat0(string[] fields, bool convertDatesToUtc) { 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; DateTimeUtil.TryParseLocalDate(fields[3], out info.RankChangeDate); if (fields[4].Length > 0) { info.RankChangedBy = fields[4]; if (info.RankChangedBy == "-") { info.RankChangedBy = null; } } 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 (DateTimeUtil.TryParseLocalDate(fields[6], out info.BanDate)) { if (fields[7].Length > 0) { info.BannedBy = fields[7]; } if (fields[10].Length > 0) { info.BanReason = UnescapeOldFormat(fields[10]); if (info.BanReason == "-") { info.BanReason = null; } } } // unban information if (DateTimeUtil.TryParseLocalDate(fields[8], out info.UnbanDate)) { if (fields[9].Length > 0) { info.UnbannedBy = fields[9]; } if (fields[11].Length > 0) { info.UnbanReason = UnescapeOldFormat(fields[11]); if (info.UnbanReason == "-") { info.UnbanReason = null; } } } // 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; } // skip 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.MessagesWritten); } // fields 22-23 are no longer in use if (fields.Length > MinFieldCount) { if (fields[24].Length > 0) { info.PreviousRank = Rank.Parse(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(); } byte rankChangeTypeCode; if (Byte.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); if (fields[34].Length > 0) { info.LastKickBy = UnescapeOldFormat(fields[34]); } if (fields[35].Length > 0) { 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"); if (fields[38].Length > 0) { info.FrozenBy = UnescapeOldFormat(fields[38]); } DateTimeUtil.TryParseLocalDate(fields[39], out info.FrozenOn); DateTimeUtil.TryParseLocalDate(fields[40], out info.MutedUntil); if (fields[41].Length > 0) { 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); }
// Throws a PlayerOpException if reason is required but missing. internal static void CheckRankChangeReason([CanBeNull] string reason, [NotNull] Player player, PlayerInfo targetInfo, bool promoting) { if (player == null) { throw new ArgumentNullException("player"); } if (ConfigKey.RequireRankChangeReason.Enabled() && String.IsNullOrEmpty(reason)) { string msg; if (promoting) { msg = "Please specify a promotion reason."; } else { msg = "Please specify a demotion reason."; } string colorMsg = "&S" + msg; throw new PlayerOpException(player, targetInfo, PlayerOpExceptionCode.ReasonRequired, msg, colorMsg); } }
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] ); } }
static void LoadInternal(StreamReader reader, string header) { int version = IdentifyFormatVersion(header); if (version > FormatVersion) { Logger.Log(LogType.Warning, "PlayerDB.Load: Attempting to load unsupported PlayerDB format ({0}). Errors may occur.", version); } else if (version < FormatVersion) { Logger.Log(LogType.Warning, "PlayerDB.Load: Converting PlayerDB to a newer format (version {0} to {1}).", version, FormatVersion); } int emptyRecords = 0; while (true) { string line = reader.ReadLine(); if (line == null) { break; } string[] fields = line.Split(','); if (fields.Length >= PlayerInfo.MinFieldCount) { #if !DEBUG try { #endif PlayerInfo info; switch (version) { case 0: info = PlayerInfo.LoadFormat0(fields, true); break; case 1: info = PlayerInfo.LoadFormat1(fields); break; default: // Versions 2-5 differ in semantics only, not in actual serialization format. info = PlayerInfo.LoadFormat2(fields); break; } if (info.ID > maxID) { Logger.Log(LogType.Warning, "PlayerDB.Load: Adjusting wrongly saved MaxID ({0} to {1}).", maxID, info.ID); maxID = info.ID; } // A record is considered "empty" if the player has never logged in. // Empty records may be created by /Import, /Ban, and /Rank commands on typos. // Deleting such records should have no negative impact on DB completeness. if ((info.LastIP.Equals(IPAddress.None) || info.LastIP.Equals(IPAddress.Any) || info.TimesVisited == 0) && !info.IsBanned && info.Rank == RankManager.DefaultRank) { Logger.Log(LogType.SystemActivity, "PlayerDB.Load: Skipping an empty record for player \"{0}\"", info.Name); emptyRecords++; continue; } // Check for duplicates. Unless PlayerDB.txt was altered externally, this does not happen. if (Trie.ContainsKey(info.Name)) { Logger.Log(LogType.Error, "PlayerDB.Load: Duplicate record for player \"{0}\" skipped.", info.Name); } else { Trie.Add(info.Name, info); list.Add(info); } #if !DEBUG } catch (Exception ex) { Logger.LogAndReportCrash("Error while parsing PlayerInfo record: " + line, "fCraft", ex, false); } #endif } else { Logger.Log(LogType.Error, "PlayerDB.Load: Unexpected field count ({0}), expecting at least {1} fields for a PlayerDB entry.", fields.Length, PlayerInfo.MinFieldCount); } } if (emptyRecords > 0) { Logger.Log(LogType.Warning, "PlayerDB.Load: Skipped {0} empty records.", emptyRecords); } RunCompatibilityChecks(version); }