internal void LoadBinary() { using (PlayerDB.GetWriteLock()) { if (File.Exists(Paths.PlayerDBFileName + ".bin")) { using (FileStream fs = OpenRead(Paths.PlayerDBFileName + ".bin")) { BinaryReader reader = new BinaryReader(fs); int version = reader.ReadInt32(); if (version > FormatVersion) { Logger.Log(LogType.Warning, "PlayerDB.LoadBinary: Attempting to load unsupported PlayerDB format ({0}). Errors may occur.", version); } else if (version < FormatVersion) { Logger.Log(LogType.Warning, "PlayerDB.LoadBinary: Converting PlayerDB to a newer format (version {0} to {1}).", version, FormatVersion); } maxID = reader.ReadInt32(); int rankCount = reader.ReadInt32(); rankMapping = new Dictionary <int, Rank>(rankCount); for (int i = 0; i < rankCount; i++) { byte rankIndex = reader.ReadByte(); string rankName = reader.ReadString(); Rank rank = Rank.Parse(rankName); if (rank == null) { Logger.Log(LogType.Error, "PlayerDB.LoadBinary: Could not parse rank: \"{0}\". Assigning rank {1} instead.", rankName, RankManager.DefaultRank); rank = RankManager.DefaultRank; } rankMapping.Add(rankIndex, rank); } int records = reader.ReadInt32(); int emptyRecords = 0; for (int i = 0; i < records; i++) { #if !DEBUG try { #endif PlayerInfo info = LoadBinaryFormat0(reader); if (info.ID > maxID) { maxID = info.ID; Logger.Log(LogType.Warning, "PlayerDB.LoadBinary: Adjusting wrongly saved MaxID ({0} to {1})."); } // 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.LoadBinary: 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.LoadBinary: Duplicate record for player \"{0}\" skipped.", info.Name); } else { trie.Add(info.Name, info); } #if !DEBUG } catch (Exception ex) { Logger.LogAndReportCrash("Error while parsing PlayerInfo record", "fCraft", ex, false); } #endif } if (emptyRecords > 0) { Logger.Log(LogType.Warning, "PlayerDB.LoadBinary: Skipped {0} empty records.", emptyRecords); } } } else { Logger.Log(LogType.Warning, "PlayerDB.Load: No player DB file found."); } } }
/// <summary> Initializes the provider, and allocates PlayerInfo objects for all players. </summary> public IEnumerable <PlayerInfo> Load() { //LoadBinary(); //return; using (PlayerDB.GetWriteLock()) { if (File.Exists(Paths.PlayerDBFileName)) { using (FileStream fs = OpenRead(Paths.PlayerDBFileName)) { using (StreamReader reader = new StreamReader(fs, Encoding.UTF8, true, BufferSize)) { string header = reader.ReadLine(); if (header == null) { // if PlayerDB is an empty file Logger.Log(LogType.Warning, "PlayerDB.Load: PlayerDB file is empty."); return(null); } 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 >= MinFieldCount) { #if !DEBUG try { #endif PlayerInfo info; switch (version) { case 0: info = LoadFormat0(fields); break; case 1: info = LoadFormat1(fields); break; default: // Versions 2-5 differ in semantics only, not in actual serialization format. info = LoadFormat2(fields); break; } if (info.ID > maxID) { maxID = info.ID; Logger.Log(LogType.Warning, "PlayerDB.Load: Adjusting wrongly saved MaxID ({0} to {1})."); } // 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); } #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, MinFieldCount); } } if (emptyRecords > 0) { Logger.Log(LogType.Warning, "PlayerDB.Load: Skipped {0} empty records.", emptyRecords); } } } } else { Logger.Log(LogType.Warning, "PlayerDB.Load: No player DB file found."); } } return(trie.Values); }