LogAndReportCrash() public static method

public static LogAndReportCrash ( [ message, [ assembly, [ exception, bool shutdownImminent ) : void
message [
assembly [
exception [
shutdownImminent bool
return void
Beispiel #1
0
        static void BackgroundLoop()
        {
            while (!Server.IsShuttingDown)
            {
                if (BackgroundTasks.Count > 0)
                {
                    SchedulerTask task;
                    lock ( BackgroundTaskListLock ) {
                        task = BackgroundTasks.Dequeue();
                    }
                    task.IsExecuting = true;
#if DEBUG_SCHEDULER
                    FireEvent(TaskExecuting, task);
#endif

#if DEBUG
                    task.Callback(task);
#else
                    try {
                        task.Callback(task);
                    } catch (Exception ex) {
                        Logger.LogAndReportCrash("Exception thrown by ScheduledTask callback", "fCraft", ex, false);
                    } finally {
                        task.IsExecuting = false;
                    }
#endif

#if DEBUG_SCHEDULER
                    FireEvent(TaskExecuted, task);
#endif
                }
                Thread.Sleep(10);
            }
        }
Beispiel #2
0
        static void ExecuteBackgroundTask([NotNull] SchedulerTask task)
        {
            if (task == null)
            {
                throw new ArgumentNullException("task");
            }
            task.IsExecuting = true;
#if DEBUG_SCHEDULER
            FireEvent(TaskExecuting, task);
#endif

#if DEBUG
            task.Callback(task);
#else
            try {
                task.Callback(task);
            } catch (Exception ex) {
                Logger.LogAndReportCrash("Exception thrown by ScheduledTask callback", "fCraft", ex, false);
            } finally {
                task.IsExecuting = false;
            }
#endif

#if DEBUG_SCHEDULER
            FireEvent(TaskExecuted, task);
#endif
        }
Beispiel #3
0
        static void ExecuteBackgroundTask(SchedulerTask task)
        {
            task.IsExecuting = true;
#if DEBUG_SCHEDULER
            task.ExecuteStart = DateTime.UtcNow;
            FireEvent(TaskExecuting, task);
#endif

#if DEBUG
            task.Callback(task);
#else
            try {
                task.Callback(task);
            } catch (Exception ex) {
                Logger.LogAndReportCrash("Exception thrown by ScheduledTask callback", "ProCraft", ex, false);
            } finally {
                task.IsExecuting = false;
            }
#endif

#if DEBUG_SCHEDULER
            task.ExecuteEnd = DateTime.UtcNow;
            FireEvent(TaskExecuted, task);
#endif
        }
Beispiel #4
0
        private int ProcessDrawOps(int maxTotalUpdates)
        {
            if (World == null)
            {
                throw new InvalidOperationException("No world assigned");
            }
            int blocksDrawnTotal = 0;

            for (int i = 0; i < drawOps.Count; i++)
            {
                DrawOperation op = drawOps[i];

                // remove a cancelled drawOp from the list
                if (op.IsCancelled)
                {
                    op.End();
                    drawOps.RemoveAt(i);
                    i--;
                    continue;
                }

                // draw a batch of blocks
                int blocksToDraw = maxTotalUpdates / (drawOps.Count - i);
                op.StartBatch();
#if DEBUG
                int blocksDrawn = op.DrawBatch(blocksToDraw);
#else
                int blocksDrawn;
                try
                {
                    blocksDrawn = op.DrawBatch(blocksToDraw);
                }
                catch (Exception ex)
                {
                    Logger.LogAndReportCrash("DrawOp error", "fCraft", ex, false);
                    op.Player.Message("&WError occured in your draw command: {0}: {1}",
                                      ex.GetType().Name, ex.Message);
                    drawOps.RemoveAt(i);
                    op.End();
                    return(blocksDrawnTotal);
                }
#endif
                blocksDrawnTotal += blocksDrawn;
                if (blocksDrawn > 0)
                {
                    HasChangedSinceSave = true;
                }
                maxTotalUpdates -= blocksDrawn;

                // remove a completed drawOp from the list
                if (op.IsDone)
                {
                    op.End();
                    drawOps.RemoveAt(i);
                    i--;
                }
            }
            return(blocksDrawnTotal);
        }
Beispiel #5
0
        private static void MainLoop() {
            while ( !Server.IsShuttingDown ) {
                DateTime ticksNow = DateTime.UtcNow;

                SchedulerTask[] taskListCache = taskCache;

                for ( int i = 0; i < taskListCache.Length && !Server.IsShuttingDown; i++ ) {
                    SchedulerTask task = taskListCache[i];
                    if ( task.IsStopped || task.NextTime > ticksNow )
                        continue;
                    if ( task.IsRecurring && task.AdjustForExecutionTime ) {
                        task.NextTime += task.Interval;
                    }

                    if ( task.IsBackground ) {
                        lock ( BackgroundTaskListLock ) {
                            BackgroundTasks.Enqueue( task );
                        }
                    } else {
                        task.IsExecuting = true;

#if DEBUG_SCHEDULER
                        FireEvent( TaskExecuting, task );
#endif

#if DEBUG
                        task.Callback( task );
                        task.IsExecuting = false;
#else
                        try {
                            task.Callback( task );
                        } catch ( Exception ex ) {
                            Logger.LogAndReportCrash( "Exception thrown by ScheduledTask callback", "fCraft", ex, false );
                        } finally {
                            task.IsExecuting = false;
                        }
#endif

#if DEBUG_SCHEDULER
                        FireEvent( TaskExecuted, task );
#endif
                    }

                    if ( !task.IsRecurring || task.MaxRepeats == 1 ) {
                        task.Stop();
                        continue;
                    }
                    task.MaxRepeats--;

                    ticksNow = DateTime.UtcNow;
                    if ( !task.AdjustForExecutionTime ) {
                        task.NextTime = ticksNow.Add( task.Interval );
                    }
                }

                Thread.Sleep( 10 );
            }
        }
Beispiel #6
0
        internal static bool LoadWorldList()
        {
            if (File.Exists(Paths.WorldListFileName))
            {
                try {
                    LoadWorldListXml();
                } catch (Exception ex) {
                    Logger.LogAndReportCrash("Error occured while trying to load the world list.", "fCraft", ex, true);
                    return(false);
                }
            }
            else
            {
                Logger.Log("Server.Start: No world list found. Creating default \"main\" world.", LogType.SystemActivity);
                CreateDefaultMainWorld();
            }

            if (Worlds.Count == 0)
            {
                Logger.Log("Server.Start: Could not load any of the specified worlds, or no worlds were specified. " +
                           "Creating default \"main\" world.", LogType.Error);
                CreateDefaultMainWorld();
            }

            // if there is no default world still, die.
            if (MainWorld == null)
            {
                throw new Exception("Could not create any worlds");
            }
            else
            {
                if (MainWorld.AccessSecurity.HasRestrictions())
                {
                    Logger.Log("Server.LoadWorldList: Main world cannot have any access restrictions. " +
                               "Access permission for \"{0}\" has been reset.", LogType.Warning,
                               MainWorld.Name);
                    MainWorld.AccessSecurity.Reset();
                }
                MainWorld.ToggleNeverUnloadFlag(true);
            }

            return(true);
        }
Beispiel #7
0
        internal static void LoadBinary()
        {
            lock ( SaveLoadLocker ) {
                if (File.Exists(Paths.PlayerDBFileName + ".bin"))
                {
                    Stopwatch sw = Stopwatch.StartNew();
                    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();

                        lock ( AddLocker ) {
                            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;
                                switch (version)
                                {
                                default:
                                    // Versions 2-5 differ in semantics only, not in actual serialization format.
                                    info = PlayerInfo.LoadBinaryFormat0(reader);
                                    break;
                                }

                                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);
                                    list.Add(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);
                            }

                            RunCompatibilityChecks(version);
                        }
                    }
                    sw.Stop();
                    Logger.Log(LogType.Debug,
                               "PlayerDB.LoadBinary: Done loading player DB ({0} records) in {1}ms. MaxID={2}",
                               Trie.Count, sw.ElapsedMilliseconds, maxID);
                }
                else
                {
                    Logger.Log(LogType.Warning, "PlayerDB.Load: No player DB file found.");
                }
                UpdateCache();
                IsLoaded = true;
            }
        }
Beispiel #8
0
        internal static void Load()
        {
            //LoadBinary();
            //return;
            lock ( SaveLoadLocker ) {
                if (File.Exists(Paths.PlayerDBFileName))
                {
                    Stopwatch sw = Stopwatch.StartNew();
                    using (FileStream fs = OpenRead(Paths.PlayerDBFileName)) {
                        using (StreamReader reader = new StreamReader(fs, Encoding.UTF8, true, BufferSize)) {
                            string header = reader.ReadLine();

                            if (header == null)
                            {
                                return;                  // if PlayerDB is an empty file
                            }
                            lock ( AddLocker ) {
                                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)
                                        {
                                            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);
                                            list.Add(info);
                                        }
#if !DEBUG
                                    }
                                    catch (Exception ex) {
                                        Logger.LogAndReportCrash("Error while parsing PlayerInfo record",
                                                                 "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);
                            }
                        }
                    }
                    sw.Stop();
                    Logger.Log(LogType.Debug,
                               "PlayerDB.Load: Done loading player DB ({0} records) in {1}ms. MaxID={2}",
                               Trie.Count, sw.ElapsedMilliseconds, maxID);
                }
                else
                {
                    Logger.Log(LogType.Warning, "PlayerDB.Load: No player DB file found.");
                }
                UpdateCache();
                IsLoaded = true;
            }
        }
Beispiel #9
0
        internal static bool LoadWorldList()
        {
            World newMainWorld = null;

            Worlds = new World[0];
            if (File.Exists(Paths.WorldListFileName))
            {
                try {
                    XDocument doc  = XDocument.Load(Paths.WorldListFileName);
                    XElement  root = doc.Root;
                    if (root != null)
                    {
                        foreach (XElement el in root.Elements("World"))
                        {
#if !DEBUG
                            try {
#endif
                            LoadWorldListEntry(el);
#if !DEBUG
                        }
                        catch (Exception ex) {
                            Logger.LogAndReportCrash("An error occured while trying to parse one of the entries on the world list",
                                                     "800Craft", ex, false);
                        }
#endif
                        }

                        XAttribute temp;
                        if ((temp = root.Attribute("main")) != null)
                        {
                            World suggestedMainWorld = FindWorldExact(temp.Value);

                            if (suggestedMainWorld != null)
                            {
                                newMainWorld = suggestedMainWorld;
                            }
                            else if (firstWorld != null)
                            {
                                // if specified main world does not exist, use first-defined world
                                Logger.Log(LogType.Warning,
                                           "The specified main world \"{0}\" does not exist. " +
                                           "\"{1}\" was designated main instead. You can use /WMain to change it.",
                                           temp.Value, firstWorld.Name);
                                newMainWorld = firstWorld;
                            }
                            // if firstWorld was also null, LoadWorldList() should try creating a new mainWorld
                        }
                        else if (firstWorld != null)
                        {
                            newMainWorld = firstWorld;
                        }
                    }
                } catch (Exception ex) {
                    Logger.LogAndReportCrash("Error occured while trying to load the world list.", "800Craft", ex, true);
                    return(false);
                }

                if (newMainWorld == null)
                {
                    Logger.Log(LogType.Error,
                               "Server.Start: Could not load any of the specified worlds, or no worlds were specified. " +
                               "Creating default \"main\" world.");
                    newMainWorld = AddWorld(null, "main", MapGeneratorOld.GenerateFlatgrass(128, 128, 64), true);
                }
            }
            else
            {
                Logger.Log(LogType.SystemActivity,
                           "Server.Start: No world list found. Creating default \"main\" world.");
                newMainWorld = AddWorld(null, "main", MapGeneratorOld.GenerateFlatgrass(128, 128, 64), true);
            }

            // if there is no default world still, die.
            if (newMainWorld == null)
            {
                throw new Exception("Could not create any worlds.");
            }
            else if (newMainWorld.AccessSecurity.HasRestrictions)
            {
                Logger.Log(LogType.Warning,
                           "Server.LoadWorldList: Main world cannot have any access restrictions. " +
                           "Access permission for \"{0}\" has been reset.",
                           newMainWorld.Name);
                newMainWorld.AccessSecurity.Reset();
            }

            MainWorld = newMainWorld;

            return(true);
        }
Beispiel #10
0
        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)
                    {
                        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);
                        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);
        }
Beispiel #11
0
        internal static bool LoadWorldList()
        {
            World firstWorld   = null;
            World newMainWorld = null;

            lock ( SyncRoot ) {
                Worlds = new World[0];
                if (File.Exists(Paths.WorldListFileName))
                {
#if !DEBUG
                    try {
#endif
                    XDocument doc = XDocument.Load(Paths.WorldListFileName);
                    XElement root = doc.Root;
                    if (root != null)
                    {
                        foreach (XElement el in root.Elements("World"))
                        {
#if DEBUG
                            World newWorld = AddWorld(el);
#else
                            World newWorld;
                            try {
                                newWorld = AddWorld(el);
                            } catch (Exception ex) {
                                Logger.LogAndReportCrash("An error occurred while trying to parse one of the entries on the world list",
                                                         "fCraft", ex, false);
                                continue;
                            }
#endif
                            if (firstWorld == null)
                            {
                                firstWorld = newWorld;
                            }
                        }

                        XAttribute temp;
                        if ((temp = root.Attribute("main")) != null)
                        {
                            World suggestedMainWorld = FindWorldExact(temp.Value);

                            if (suggestedMainWorld != null)
                            {
                                newMainWorld = suggestedMainWorld;
                            }
                            else if (firstWorld != null)
                            {
                                // if specified main world does not exist, use first-defined world
                                Logger.Log(LogType.Warning,
                                           "The specified main world \"{0}\" does not exist. " +
                                           "\"{1}\" was designated main instead. You can use /WMain to change it.",
                                           temp.Value, firstWorld.Name);
                                newMainWorld = firstWorld;
                            }
                            // if firstWorld was also null, LoadWorldList() should try creating a new mainWorld
                        }
                        else if (firstWorld != null)
                        {
                            newMainWorld = firstWorld;
                        }

                        foreach (XElement mainedRankEl in root.Elements(RankMainXmlTagName))
                        {
                            temp = mainedRankEl.Attribute("rank");
                            if (temp == null)
                            {
                                Logger.Log(LogType.Warning,
                                           "WorldManager.Load: Malformed RankMain element: \"rank\" attribute missing.");
                                continue;
                            }

                            string rankName = temp.Value;
                            Rank   rank     = Rank.Parse(rankName);
                            if (rank == null)
                            {
                                Logger.Log(LogType.Warning,
                                           "Rank main defined for an unrecognized rank \"{0}\"",
                                           rankName);
                                continue;
                            }

                            temp = mainedRankEl.Attribute("world");
                            if (temp == null)
                            {
                                Logger.Log(LogType.Warning,
                                           "WorldManager.Load: Malformed RankMain element: \"world\" attribute missing.");
                                continue;
                            }

                            string worldName = temp.Value;
                            World  world     = FindWorldExact(mainedRankEl.Value);
                            if (world == null)
                            {
                                Logger.Log(LogType.Warning,
                                           "Rank main for \"{0}\" set to an unrecognized world \"{1}\"",
                                           rank.Name, worldName);
                                continue;
                            }

                            if (rank < world.AccessSecurity.MinRank)
                            {
                                world.AccessSecurity.MinRank = rank;
                                Logger.Log(LogType.Warning,
                                           "WorldManager: Lowered access MinRank of world {0} to {1}+ to allow it to be the main world for that rank.",
                                           world.Name, rank.Name);
                            }
                            rank.MainWorld = world;
                        }
                    }
#if !DEBUG
                }
                catch (XmlException ex) {
                    string errorMsg = "WorldManager.LoadWorldList: worlds.xml is not properly formatted: " + ex.Message;
                    Logger.LogAndReportCrash("World list failed to load", "fCraft",
                                             new MisconfigurationException(errorMsg, ex), true);
                    return(false);
                } catch (Exception ex) {
                    Logger.LogAndReportCrash("World list failed to load", "fCraft", ex, true);
                    return(false);
                }
#endif

                    if (newMainWorld == null)
                    {
                        Logger.Log(LogType.Error,
                                   "Server.Start: Could not load any of the specified worlds, or no worlds were specified. " +
                                   "Creating default \"main\" world.");
                        newMainWorld = AddWorld(null, "main", MapGenerator.GenerateFlatgrass(128, 128, 64), true);
                    }
                }
                else
                {
                    Logger.Log(LogType.SystemActivity,
                               "Server.Start: No world list found. Creating default \"main\" world.");
                    newMainWorld = AddWorld(null, "main", MapGenerator.GenerateFlatgrass(128, 128, 64), true);
                }

                if (newMainWorld.AccessSecurity.HasRestrictions)
                {
                    Logger.Log(LogType.Warning,
                               "Server.LoadWorldList: Main world cannot have any access restrictions. " +
                               "Access permission for \"{0}\" has been reset.",
                               newMainWorld.Name);
                    newMainWorld.AccessSecurity.Reset();
                }

                MainWorld = newMainWorld;
            }
            return(true);
        }
Beispiel #12
0
        public static bool Save(bool saveSalt)
        {
            XDocument file = new XDocument();

            XElement config = new XElement(ConfigXmlRootName);

            config.Add(new XAttribute("version", ConfigVersion));
            if (saveSalt)
            {
                config.Add(new XAttribute("salt", Server.Salt));
            }

            // save general settings
            foreach (ConfigSection section in Enum.GetValues(typeof(ConfigSection)))
            {
                XElement sectionEl = new XElement("Section");
                sectionEl.Add(new XAttribute("name", section));
                foreach (ConfigKey key in KeyMetadata.Values.Where(a => a.Section == section).Select(a => a.Key))
                {
                    if (IsDefault(key))
                    {
                        sectionEl.Add(new XComment(new XElement(key.ToString(), Settings[key]).ToString()));
                    }
                    else
                    {
                        sectionEl.Add(new XElement(key.ToString(), Settings[key]));
                    }
                }
                config.Add(sectionEl);
            }

            // save console options
            XElement consoleOptions = new XElement("ConsoleOptions");

            for (int i = 0; i < Logger.ConsoleOptions.Length; i++)
            {
                if (Logger.ConsoleOptions[i])
                {
                    consoleOptions.Add(new XElement(((LogType)i).ToString()));
                }
            }
            config.Add(consoleOptions);

            // save logfile options
            XElement logFileOptions = new XElement("LogFileOptions");

            for (int i = 0; i < Logger.LogFileOptions.Length; i++)
            {
                if (Logger.LogFileOptions[i])
                {
                    logFileOptions.Add(new XElement(((LogType)i).ToString()));
                }
            }
            config.Add(logFileOptions);

            // save ranks
            XElement ranksTag = new XElement("Ranks");

            foreach (Rank rank in RankManager.Ranks)
            {
                ranksTag.Add(rank.Serialize());
            }
            config.Add(ranksTag);

            // save legacy rank mapping
            XElement legacyRankMappingTag = new XElement("LegacyRankMapping");

            foreach (KeyValuePair <string, string> pair in RankManager.LegacyRankMapping)
            {
                XElement rankPair = new XElement("LegacyRankPair");
                rankPair.Add(new XAttribute("from", pair.Key), new XAttribute("to", pair.Value));
                legacyRankMappingTag.Add(rankPair);
            }
            config.Add(legacyRankMappingTag);


            file.Add(config);
            try {
                // write out the changes
                string tempFileName = Paths.ConfigFileName + ".temp";
                file.Save(tempFileName);
                Paths.MoveOrReplace(tempFileName, Paths.ConfigFileName);
                return(true);
            } catch (Exception ex) {
                Logger.LogAndReportCrash("Config failed to save", "fCraft", ex, true);
                return(false);
            }
        }
Beispiel #13
0
        /// <summary>
        /// Loads config from file.
        /// </summary>
        /// <param name="skipRankList">If true, skips over rank definitions.</param>
        /// <param name="raiseReloadedEvent">Whether ConfigReloaded event should be raised.</param>
        /// <returns>True if loading succeeded.</returns>
        public static bool Load(bool skipRankList, bool raiseReloadedEvent)
        {
            bool fromFile = false;

            // try to load config file (XML)
            XDocument file;

            if (File.Exists(Paths.ConfigFileName))
            {
                try {
                    file = XDocument.Load(Paths.ConfigFileName);
                    if (file.Root == null || file.Root.Name != ConfigXmlRootName)
                    {
                        Logger.Log("Config.Load: Malformed or incompatible config file {0}. Loading defaults.", LogType.Warning, Paths.ConfigFileName);
                        file = new XDocument();
                        file.Add(new XElement(ConfigXmlRootName));
                    }
                    else
                    {
                        Logger.Log("Config.Load: Config file {0} loaded succesfully.", LogType.Debug, Paths.ConfigFileName);
                        fromFile = true;
                    }
                } catch (Exception ex) {
                    Logger.LogAndReportCrash("Config failed to load", "fCraft", ex, true);
                    return(false);
                }
            }
            else
            {
                // create a new one (with defaults) if no file exists
                file = new XDocument();
                file.Add(new XElement(ConfigXmlRootName));
            }

            XElement config = file.Root;

            XAttribute attr    = config.Attribute("version");
            int        version = 0;

            if (fromFile && (attr == null || !Int32.TryParse(attr.Value, out version) || version != ConfigVersion))
            {
                Logger.Log("Config.Load: Your config.xml was made for a different version of fCraft. " +
                           "Some obsolete settings might be ignored, and some recently-added settings will be set to their default values. " +
                           "It is recommended that you run ConfigTool to make sure everything is in order.", LogType.Warning);
            }

            // read rank definitions
            if (!skipRankList)
            {
                LoadRankList(config, version, fromFile);
            }

            // read log options for console
            XElement consoleOptions = config.Element("ConsoleOptions");

            if (consoleOptions != null)
            {
                LoadLogOptions(consoleOptions, Logger.ConsoleOptions);
            }
            else
            {
                if (fromFile)
                {
                    Logger.Log("Config.Load: using default console options.", LogType.Warning);
                }
                for (int i = 0; i < Logger.ConsoleOptions.Length; i++)
                {
                    Logger.ConsoleOptions[i] = true;
                }
                Logger.ConsoleOptions[(int)LogType.ConsoleInput] = false;
                Logger.ConsoleOptions[(int)LogType.Debug]        = false;
            }

            // read log options for logfile
            XElement logFileOptions = config.Element("LogFileOptions");

            if (logFileOptions != null)
            {
                LoadLogOptions(logFileOptions, Logger.LogFileOptions);
            }
            else
            {
                if (fromFile)
                {
                    Logger.Log("Config.Load: using default log file options.", LogType.Warning);
                }
                for (int i = 0; i < Logger.LogFileOptions.Length; i++)
                {
                    Logger.LogFileOptions[i] = true;
                }
            }

            // read the rest of the keys
            string[] keyNames = Enum.GetNames(typeof(ConfigKey));
            if (version < 139)
            {
                foreach (XElement element in config.Elements())
                {
                    ParseKeyElement(element, keyNames);
                }
            }
            else
            {
                foreach (XElement section in config.Elements("Section"))
                {
                    foreach (XElement keyElement in section.Elements())
                    {
                        ParseKeyElement(keyElement, keyNames);
                    }
                }
            }

            // key relation validation
            if (version < 134)
            {
                ConfigKey.MaxPlayersPerWorld.TrySetValue(ConfigKey.MaxPlayers.GetInt());
            }
            if (ConfigKey.MaxPlayersPerWorld.GetInt() > ConfigKey.MaxPlayers.GetInt())
            {
                Logger.Log("Value of MaxPlayersPerWorld ({0}) was lowered to match MaxPlayers ({1}).", LogType.Warning,
                           ConfigKey.MaxPlayersPerWorld.GetInt(),
                           ConfigKey.MaxPlayers.GetInt());
                ConfigKey.MaxPlayersPerWorld.TrySetValue(ConfigKey.MaxPlayers.GetInt());
            }

            if (raiseReloadedEvent)
            {
                RaiseReloadedEvent();
            }

            return(true);
        }
Beispiel #14
0
        static void Beat(SchedulerTask scheduledTask)
        {
            if (Server.IsShuttingDown)
            {
                return;
            }

            data = new HeartbeatData {
                IsPublic        = ConfigKey.IsPublic.GetBool(),
                MaxPlayers      = ConfigKey.MaxPlayers.GetInt(),
                PlayerCount     = Server.CountPlayers(false),
                ServerIP        = Server.IP,
                Port            = Server.Port,
                ProtocolVersion = Config.ProtocolVersion,
                Salt            = Server.Salt,
                ServerName      = ConfigKey.ServerName.GetString()
            };

            // This needs to be wrapped in try/catch because and exception in an event handler
            // would permanently stop heartbeat sending.
            try {
                if (RaiseHeartbeatSendingEvent(data))
                {
                    RescheduleHeartbeat();
                    return;
                }
            } catch (Exception ex) {
                Logger.LogAndReportCrash("Heartbeat.Sending handler failed", "fCraft", ex, false);
            }

            if (ConfigKey.HeartbeatEnabled.GetBool())
            {
                UriBuilder    ub = new UriBuilder(Uri);
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("public={0}&max={1}&users={2}&port={3}&version={4}&salt={5}&name={6}",
                                data.IsPublic,
                                data.MaxPlayers,
                                data.PlayerCount,
                                data.Port,
                                data.ProtocolVersion,
                                Uri.EscapeDataString(data.Salt),
                                Uri.EscapeDataString(data.ServerName));

                foreach (var pair in data.CustomData)
                {
                    sb.AppendFormat("&{0}={1}",
                                    Uri.EscapeDataString(pair.Key),
                                    Uri.EscapeDataString(pair.Value));
                }
                ub.Query = sb.ToString();

                request = (HttpWebRequest)WebRequest.Create(ub.Uri);
                request.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(BindIPEndPointCallback);
                request.Method      = "GET";
                request.Timeout     = Timeout;
                request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.BypassCache);

                request.BeginGetResponse(ResponseCallback, null);
            }
            else
            {
                // If heartbeats are disabled, the data is written to a text file (heartbeatdata.txt)
                const string tempFile = Paths.HeartbeatDataFileName + ".tmp";

                File.WriteAllLines(tempFile,
                                   new[] {
                    Server.Salt,
                    Server.IP.ToString(),
                    Server.Port.ToString(),
                    Server.CountPlayers(false).ToString(),
                    ConfigKey.MaxPlayers.GetString(),
                    ConfigKey.ServerName.GetString(),
                    ConfigKey.IsPublic.GetString()
                },
                                   Encoding.ASCII);

                Paths.MoveOrReplace(tempFile, Paths.HeartbeatDataFileName);
                RescheduleHeartbeat();
            }
        }
Beispiel #15
0
        static void LoadWorldListXml()
        {
            XDocument  doc        = XDocument.Load(Paths.WorldListFileName);
            XElement   root       = doc.Root;
            World      firstWorld = null;
            XAttribute temp;

            foreach (XElement el in root.Elements("World"))
            {
                try {
                    if ((temp = el.Attribute("name")) == null)
                    {
                        Logger.Log("Server.ParseWorldListXML: World tag with no name skipped.", LogType.Error);
                        continue;
                    }
                    string worldName = temp.Value;
                    if (!World.IsValidName(worldName))
                    {
                        Logger.Log("Server.ParseWorldListXML: Invalid world name skipped: \"{0}\"", LogType.Error, worldName);
                        continue;
                    }

                    if (Worlds.ContainsKey(worldName.ToLower()))
                    {
                        Logger.Log("Server.ParseWorldListXML: Duplicate world name ignored: \"{0}\"", LogType.Error, worldName);
                        continue;
                    }

                    World world;
                    try {
                        world = AddWorld(null, worldName, null, (el.Attribute("noUnload") != null));
                    } catch (WorldOpException ex) {
                        Logger.Log("Server.ParseWorldListXML: Error loading world \"{0}\": {1}", LogType.Error, worldName, ex.Message);
                        continue;
                    }

                    if ((temp = el.Attribute("hidden")) != null)
                    {
                        if (!Boolean.TryParse(temp.Value, out world.IsHidden))
                        {
                            Logger.Log("Server.ParseWorldListXML: Could not parse \"hidden\" attribute of world \"{0}\", assuming NOT hidden.",
                                       LogType.Warning, worldName);
                            world.IsHidden = false;
                        }
                    }
                    if (firstWorld == null)
                    {
                        firstWorld = world;
                    }

                    if (el.Element("accessSecurity") != null)
                    {
                        world.AccessSecurity = new SecurityController(el.Element("accessSecurity"));
                    }
                    else
                    {
                        world.AccessSecurity.MinRank = LoadWorldRankRestriction(world, "access", el);   // LEGACY
                    }

                    if (el.Element("buildSecurity") != null)
                    {
                        world.BuildSecurity = new SecurityController(el.Element("buildSecurity"));
                    }
                    else
                    {
                        world.BuildSecurity.MinRank = LoadWorldRankRestriction(world, "build", el);   // LEGACY
                    }

                    // Check the world's map file
                    string mapFullName = world.GetMapName();
                    string mapName     = Path.GetFileName(mapFullName);

                    if (Paths.FileExists(mapFullName, false))
                    {
                        if (!Paths.FileExists(mapFullName, true))
                        {
                            // Map file has wrong capitalization
                            FileInfo[] matches = Paths.FindFiles(mapFullName);
                            if (matches.Length == 1)
                            {
                                // Try to rename the map file to match world's capitalization
                                Paths.ForceRename(matches[0].FullName, mapName);
                                if (Paths.FileExists(mapFullName, true))
                                {
                                    Logger.Log("Server.LoadWorldListXML: Map file for world \"{0}\" was renamed from \"{1}\" to \"{2}\"", LogType.Warning,
                                               world.Name, matches[0].Name, mapName);
                                }
                                else
                                {
                                    Logger.Log("Server.LoadWorldListXML: Failed to rename map file of \"{0}\" from \"{1}\" to \"{2}\"", LogType.Error,
                                               world.Name, matches[0].Name, mapName);
                                    continue;
                                }
                            }
                            else
                            {
                                Logger.Log("Server.LoadWorldListXML: More than one map file exists matching the world name \"{0}\". " +
                                           "Please check the map directory and use /wload to load the correct file.", LogType.Warning,
                                           world.Name);
                                continue;
                            }
                        }
                        // Try loading the map header
                        try {
                            MapUtility.LoadHeader(world.GetMapName());
                        } catch (Exception ex) {
                            Logger.Log("Server.LoadWorldListXML: Could not load map file for world \"{0}\": {1}", LogType.Warning,
                                       world.Name, ex);
                        }
                    }
                    else
                    {
                        Logger.Log("Server.LoadWorldListXML: Map file for world \"{0}\" was not found.", LogType.Warning,
                                   world.Name);
                    }
                } catch (Exception ex) {
                    Logger.LogAndReportCrash("An error occured while trying to parse one of the entries on the world list",
                                             "fCraft", ex, false);
                }
            }

            if ((temp = root.Attribute("main")) != null)
            {
                MainWorld = FindWorldExact(temp.Value);
                // if specified main world does not exist, use first-defined world
                if (MainWorld == null && firstWorld != null)
                {
                    Logger.Log("The specified main world \"{0}\" does not exist. " +
                               "\"{1}\" was designated main instead. You can use /wmain to change it.",
                               LogType.Warning, temp.Value, firstWorld.Name);
                    MainWorld = firstWorld;
                }
                // if firstWorld was also null, LoadWorldList() should try creating a new mainWorld
            }
            else
            {
                MainWorld = firstWorld;
            }
        }
Beispiel #16
0
        internal static void Load()
        {
            lock ( SaveLoadLocker ) {
                if (File.Exists(Paths.PlayerDBFileName))
                {
                    Stopwatch sw = Stopwatch.StartNew();
                    using (StreamReader reader = File.OpenText(Paths.PlayerDBFileName)) {
                        string header = reader.ReadLine();

                        if (header == null)
                        {
                            return;                  // if PlayerDB is an empty file
                        }
                        lock ( AddLocker ) {
                            int version = IdentifyFormatVersion(header);

                            while (!reader.EndOfStream)
                            {
                                string[] fields = reader.ReadLine().Split(',');
                                if (fields.Length >= PlayerInfo.MinFieldCount)
                                {
#if !DEBUG
                                    try {
#endif
                                    PlayerInfo info;
                                    if (version == 0)
                                    {
                                        info = PlayerInfo.LoadOldFormat(fields, true);
                                    }
                                    else
                                    {
                                        info = PlayerInfo.Load(fields);
                                    }
                                    if (Trie.ContainsKey(info.Name))
                                    {
                                        Logger.Log("PlayerDB.Load: Duplicate record for player \"{0}\" skipped.", LogType.Error, info.Name);
                                    }
                                    else
                                    {
                                        Trie.Add(info.Name, info);
                                        List.Add(info);
                                    }
#if !DEBUG
                                }
                                catch (Exception ex) {
                                    Logger.LogAndReportCrash("Error while parsing PlayerInfo record", "fCraft", ex, false);
                                }
#endif
                                }
                                else
                                {
                                    Logger.Log("PlayerDB.Load: Unexpected field count ({0}), expecting at least {1} fields for a PlayerDB entry.", LogType.Error,
                                               fields.Length,
                                               PlayerInfo.MinFieldCount);
                                }
                            }
                        }
                    }
                    List.TrimExcess();
                    sw.Stop();
                    Logger.Log("PlayerDB.Load: Done loading player DB ({0} records) in {1}ms.", LogType.Debug,
                               Trie.Count, sw.ElapsedMilliseconds);
                }
                else
                {
                    Logger.Log("PlayerDB.Load: No player DB file found.", LogType.Warning);
                }
                UpdateCache();
                IsLoaded = true;
            }
        }