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;
}