Ejemplo n.º 1
0
        public static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "Main";
            try
            {
                string MODInfo = "Terraria's Dedicated Server Mod. (" + VERSION_NUMBER + " {" + Statics.CURRENT_TERRARIA_RELEASE + "}) #"
                                 + Statics.BUILD;
                try
                {
                    Console.Title = MODInfo;
                }
                catch
                {
                }

                var lis = new Logging.LogTraceListener();
                System.Diagnostics.Trace.Listeners.Clear();
                System.Diagnostics.Trace.Listeners.Add(lis);
                System.Diagnostics.Debug.Listeners.Clear();
                System.Diagnostics.Debug.Listeners.Add(lis);

                ProgramLog.Log("Initializing " + MODInfo);

                ProgramLog.Log("Setting up Paths.");
                if (!SetupPaths())
                {
                    return;
                }

                Platform.InitPlatform();

                ProgramLog.Log("Setting up Properties.");
                bool propertiesExist = File.Exists("server.properties");
                SetupProperties();

                if (!propertiesExist)
                {
                    ProgramLog.Console.Print("New properties file created. Would you like to exit for editing? [Y/n]: ");
                    if (Console.ReadLine().ToLower() == "y")
                    {
                        ProgramLog.Console.Print("Complete, Press any Key to Exit...");
                        Console.ReadKey(true);
                        return;
                    }
                }

                var logFile = Statics.DataPath + Path.DirectorySeparatorChar + "server.log";
                ProgramLog.OpenLogFile(logFile);

                string PIDFile = properties.PIDFile.Trim();
                if (PIDFile.Length > 0)
                {
                    string ProcessUID = Process.GetCurrentProcess().Id.ToString();
                    bool   Issue      = false;
                    if (File.Exists(PIDFile))
                    {
                        try
                        {
                            File.Delete(PIDFile);
                        }
                        catch (Exception)
                        {
                            ProgramLog.Console.Print("Issue deleting PID file, Continue? [Y/n]: ");
                            if (Console.ReadLine().ToLower() == "n")
                            {
                                ProgramLog.Console.Print("Press any Key to Exit...");
                                Console.ReadKey(true);
                                return;
                            }
                            Issue = true;
                        }
                    }
                    if (!Issue)
                    {
                        try
                        {
                            File.WriteAllText(PIDFile, ProcessUID);
                        }
                        catch (Exception)
                        {
                            ProgramLog.Console.Print("Issue creating PID file, Continue? [Y/n]: ");
                            if (Console.ReadLine().ToLower() == "n")
                            {
                                ProgramLog.Console.Print("Press any Key to Exit...");
                                Console.ReadKey(true);
                                return;
                            }
                        }
                        ProgramLog.Log("PID File Created, Process ID: " + ProcessUID);
                    }
                }

                ParseArgs(args);

                try
                {
                    if (UpdateManager.performProcess())
                    {
                        ProgramLog.Log("Restarting into new update!");
                        return;
                    }
                }
                catch (UpdateCompleted)
                {
                    throw;
                }
                catch (Exception e)
                {
                    ProgramLog.Log(e, "Error updating");
                }

                LoadMonitor.Start();

                ProgramLog.Log("Starting remote console server");
                RemoteConsole.RConServer.Start("rcon_logins.properties");

                ProgramLog.Log("Starting permissions manager");
                permissionManager = new PermissionManager();

                ProgramLog.Log("Preparing Server Data...");

                using (var prog = new ProgressLogger(1, "Loading item definitions"))
                    Collections.Registries.Item.Load();
                using (var prog = new ProgressLogger(1, "Loading NPC definitions"))
                    Collections.Registries.NPC.Load(Collections.Registries.NPC_FILE);
                using (var prog = new ProgressLogger(1, "Loading projectile definitions"))
                    Collections.Registries.Projectile.Load(Collections.Registries.PROJECTILE_FILE);

                commandParser = new CommandParser();
                commandParser.ReadPermissionNodes();

                ProgramLog.Log("Loading plugins...");
                Terraria_Server.Plugins.PluginManager.Initialize(Statics.PluginPath, Statics.LibrariesPath);

                var ctx = new HookContext()
                {
                    Sender = new ConsoleSender()
                };

                var eArgs = new HookArgs.ServerStateChange()
                {
                    ServerChangeState = ServerState.INITIALIZING
                };

                HookPoints.ServerStateChange.Invoke(ref ctx, ref eArgs);
                PluginManager.LoadPlugins();
                ProgramLog.Log("Plugins loaded: " + PluginManager.PluginCount);

                string   worldFile = properties.WorldPath;
                FileInfo file      = new FileInfo(worldFile);

                if (!file.Exists)
                {
                    try
                    {
                        file.Directory.Create();
                    }
                    catch (Exception exception)
                    {
                        ProgramLog.Log(exception);
                        ProgramLog.Console.Print("Press any key to continue...");
                        Console.ReadKey(true);
                        return;
                    }

                    ctx = new HookContext
                    {
                        Sender = World.Sender,
                    };

                    eArgs = new HookArgs.ServerStateChange
                    {
                        ServerChangeState = ServerState.GENERATING
                    };

                    HookPoints.ServerStateChange.Invoke(ref ctx, ref eArgs);

                    ProgramLog.Log("Generating world '{0}'", worldFile);

                    string seed = properties.Seed;
                    if (seed == "-1")
                    {
                        seed = new Random().Next(100).ToString();
                        ProgramLog.Log("Generated seed: {0}", seed);
                    }

                    int worldX = properties.GetMapSizes()[0];
                    int worldY = properties.GetMapSizes()[1];
                    if (properties.UseCustomTiles)
                    {
                        int X = properties.MaxTilesX;
                        int Y = properties.MaxTilesY;
                        if (X > 0 && Y > 0)
                        {
                            worldX = X;
                            worldY = Y;
                        }

                        if (worldX < (int)World.MAP_SIZE.SMALL_X || worldY < (int)World.MAP_SIZE.SMALL_Y)
                        {
                            ProgramLog.Log("World dimensions need to be equal to or larger than {0} by {1}; using built-in 'small'", (int)World.MAP_SIZE.SMALL_X, (int)World.MAP_SIZE.SMALL_Y);
                            worldX = (int)((int)World.MAP_SIZE.SMALL_Y * 3.5);
                            worldY = (int)World.MAP_SIZE.SMALL_Y;
                        }

                        ProgramLog.Log("Generating world with custom map size: {0}x{1}", worldX, worldY);
                    }

                    Terraria_Server.Main.maxTilesX = worldX;
                    Terraria_Server.Main.maxTilesY = worldY;

                    WorldIO.clearWorld();
                    Terraria_Server.Main.Initialize();
                    if (properties.UseCustomGenOpts)
                    {
                        WorldGen.numDungeons = properties.DungeonAmount;
                        WorldModify.ficount  = properties.FloatingIslandAmount;
                    }
                    else
                    {
                        WorldGen.numDungeons = 1;
                        WorldModify.ficount  = (int)((double)Terraria_Server.Main.maxTilesX * 0.0008); //The Statics one was generating with default values, We want it to use the actual tileX for the world
                    }
                    WorldGen.GenerateWorld(seed);
                    WorldIO.saveWorld(worldFile, true);
                }

                ctx = new HookContext
                {
                    Sender = World.Sender,
                };

                eArgs = new HookArgs.ServerStateChange
                {
                    ServerChangeState = ServerState.LOADING
                };

                HookPoints.ServerStateChange.Invoke(ref ctx, ref eArgs);

                // TODO: read map size from world file instead of config
                int worldXtiles = properties.GetMapSizes()[0];
                int worldYtiles = properties.GetMapSizes()[1];

                if (properties.UseCustomTiles)
                {
                    int X = properties.MaxTilesX;
                    int Y = properties.MaxTilesY;
                    if (X > 0 && Y > 0)
                    {
                        worldXtiles = X;
                        worldYtiles = Y;
                    }

                    if (worldXtiles < (int)World.MAP_SIZE.SMALL_X || worldYtiles < (int)World.MAP_SIZE.SMALL_Y)
                    {
                        ProgramLog.Log("World dimensions need to be equal to or larger than {0} by {1}; using built-in 'small'", (int)World.MAP_SIZE.SMALL_X, (int)World.MAP_SIZE.SMALL_Y);
                        worldXtiles = (int)((int)World.MAP_SIZE.SMALL_Y * 3.5);
                        worldYtiles = (int)World.MAP_SIZE.SMALL_Y;
                    }

                    ProgramLog.Log("Using world with custom map size: {0}x{1}", worldXtiles, worldYtiles);
                }

                World world = new World(worldXtiles, worldYtiles);
                world.SavePath = worldFile;

                Server.InitializeData(world, properties.MaxPlayers,
                                      Statics.DataPath + Path.DirectorySeparatorChar + "whitelist.txt",
                                      Statics.DataPath + Path.DirectorySeparatorChar + "banlist.txt",
                                      Statics.DataPath + Path.DirectorySeparatorChar + "oplist.txt");
                NetPlay.password   = properties.Password;
                NetPlay.serverPort = properties.Port;
                NetPlay.serverSIP  = properties.ServerIP;
                Terraria_Server.Main.Initialize();

                Terraria_Server.Main.maxTilesX    = worldXtiles;
                Terraria_Server.Main.maxTilesY    = worldYtiles;
                Terraria_Server.Main.maxSectionsX = worldXtiles / 200;
                Terraria_Server.Main.maxSectionsY = worldYtiles / 150;

                WorldIO.LoadWorld(Server.World.SavePath);

                ctx = new HookContext
                {
                    Sender = World.Sender,
                };

                eArgs = new HookArgs.ServerStateChange
                {
                    ServerChangeState = ServerState.LOADED
                };

                HookPoints.ServerStateChange.Invoke(ref ctx, ref eArgs);

                updateThread = new ProgramThread("Updt", Program.UpdateLoop);

                ProgramLog.Log("Starting the Server");
                NetPlay.StartServer();

                while (!NetPlay.ServerUp)
                {
                }

                ProgramLog.Console.Print("You can now insert Commands.");

                while (!Statics.Exit)
                {
                    try
                    {
                        string line = Console.ReadLine();
                        if (line.Length > 0)
                        {
                            commandParser.ParseConsoleCommand(line);
                        }
                    }
                    catch (ExitException e)
                    {
                        ProgramLog.Log(e.Message);
                        break;
                    }
                    catch (Exception e)
                    {
                        ProgramLog.Log(e, "Issue parsing console command");
                    }
                }

                while (WorldModify.saveLock || NetPlay.ServerUp)
                {
                    Thread.Sleep(100);
                }

                ProgramLog.Log("Exiting...");
                Thread.Sleep(1000);
            }
            catch (UpdateCompleted)
            {
            }
            catch (Exception e)
            {
                try
                {
                    using (StreamWriter streamWriter = new StreamWriter(Statics.DataPath + Path.DirectorySeparatorChar + "crashlog.txt", true))
                    {
                        streamWriter.WriteLine(DateTime.Now);
                        streamWriter.WriteLine("Crash Log Generated by TDSM #" + Statics.BUILD + " for " + //+ " r" + Statics.revision + " for " +
                                               VERSION_NUMBER + " {" + Statics.CURRENT_TERRARIA_RELEASE + "}");
                        streamWriter.WriteLine(e);
                        streamWriter.WriteLine("");
                    }
                    ProgramLog.Log(e, "Program crash");
                    ProgramLog.Log("Please send crashlog.txt to http://tdsm.org/");
                }
                catch
                {
                }
            }

            if (File.Exists(properties.PIDFile.Trim()))
            {
                File.Delete(properties.PIDFile.Trim());
            }

            Thread.Sleep(500);
            ProgramLog.Log("Log end.");
            ProgramLog.Close();

            RemoteConsole.RConServer.Stop();
        }
        public static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "Main";

            //header: Terraria's Dedicated Server Mod. (1.1.2 #36) ~ Build: 37 [CodeName]
            string codeName = Statics.CODENAME.Length > 0 ? String.Format(" [{0}]", Statics.CODENAME) : String.Empty;
            string MODInfo  = String.Format(
                "Terraria's Dedicated Server Mod. ({0} #{1}) ~ Build: {2}{3}",
                Statics.VERSION_NUMBER,
                Statics.CURRENT_TERRARIA_RELEASE,
                Statics.BUILD,
                codeName
                );

            try
            {
                try
                {
                    Console.Title = MODInfo;
                }
                catch { }

                var lis = new Logging.LogTraceListener();
                System.Diagnostics.Trace.Listeners.Clear();
                System.Diagnostics.Trace.Listeners.Add(lis);
                System.Diagnostics.Debug.Listeners.Clear();
                System.Diagnostics.Debug.Listeners.Add(lis);

                using (var prog = new ProgressLogger(1, "Loading language definitions"))
                    Languages.LoadClass(Collections.Registries.LANGUAGE_FILE);

                if (Languages.Startup_Initializing == null)
                {
                    ProgramLog.Error.Log("Please update the language file, either by deleting or finding another online.");
                    Console.ReadKey(true);
                    return;
                }

                ProgramLog.Log("{0} {1}", Languages.Startup_Initializing, MODInfo);

                ProgramLog.Log(Languages.Startup_SettingUpPaths);
                if (!SetupPaths())
                {
                    return;
                }

                Platform.InitPlatform();

                ProgramLog.Log(Languages.Startup_SettingUpProperties);
                bool propertiesExist = File.Exists("server.properties");
                SetupProperties();

                if (!propertiesExist)
                {
                    ProgramLog.Console.Print(Languages.Startup_NoPropertiesFileFound);
                    if (Console.ReadLine().ToLower() == "y")
                    {
                        //ProgramLog.Console.Print(Languages.Startup_PropertiesCreationComplete);
                        ProgramLog.Log(Languages.ExitRequestCommand);
                        //Console.ReadKey(true);
                        return;
                    }
                }

                var logFile = Statics.DataPath + Path.DirectorySeparatorChar + "server.log";
                ProgramLog.OpenLogFile(logFile);

                string PIDFile = properties.PIDFile.Trim();
                if (PIDFile.Length > 0)
                {
                    string ProcessUID = Process.GetCurrentProcess().Id.ToString();
                    bool   Issue      = false;
                    if (File.Exists(PIDFile))
                    {
                        try
                        {
                            File.Delete(PIDFile);
                        }
                        catch (Exception)
                        {
                            ProgramLog.Console.Print(Languages.Startup_IssueDeletingPID);
                            if (Console.ReadLine().ToLower() == "n")
                            {
                                ProgramLog.Console.Print(Languages.Startup_PressAnyKeyToExit);
                                Console.ReadKey(true);
                                return;
                            }
                            Issue = true;
                        }
                    }
                    if (!Issue)
                    {
                        try
                        {
                            File.WriteAllText(PIDFile, ProcessUID);
                        }
                        catch (Exception)
                        {
                            ProgramLog.Console.Print(Languages.Startup_IssueCreatingPID);
                            if (Console.ReadLine().ToLower() == "n")
                            {
                                ProgramLog.Console.Print(Languages.Startup_PressAnyKeyToExit);
                                Console.ReadKey(true);
                                return;
                            }
                        }
                        ProgramLog.Log(Languages.Startup_PIDCreated + ProcessUID);
                    }
                }

                ParseArgs(args);

                try
                {
                    if (UpdateManager.PerformProcess())
                    {
                        ProgramLog.Log(Languages.Startup_RestartingIntoNewUpdate);
                        return;
                    }
                }
                catch (UpdateCompleted)
                {
                    throw;
                }
                catch (Exception e)
                {
                    ProgramLog.Log(e, Languages.Startup_ErrorUpdating);
                }

                LoadMonitor.Start();

                ProgramLog.Log(Languages.Startup_StartingRCON);
                RemoteConsole.RConServer.Start("rcon_logins.properties");

                ProgramLog.Log(Languages.Startup_StartingPermissions);
                permissionManager = new PermissionManager();

                ProgramLog.Log(Languages.Startup_PreparingServerData);

                using (var prog = new ProgressLogger(1, Languages.Startup_LoadingItemDefinitions))
                    Collections.Registries.Item.Load();
                using (var prog = new ProgressLogger(1, Languages.Startup_LoadingNPCDefinitions))
                    Collections.Registries.NPC.Load(Collections.Registries.NPC_FILE);
                using (var prog = new ProgressLogger(1, Languages.Startup_LoadingProjectileDefinitions))
                    Collections.Registries.Projectile.Load(Collections.Registries.PROJECTILE_FILE);

                //if (Languages.IsOutOfDate())
                //    ProgramLog.Error.Log(
                //        String.Format("{0}\n{1}",
                //        Languages.Startup_LanguageFileOOD, Languages.Startup_LanguageFileUpdate)
                //        , true);

                commandParser = new CommandParser();
                commandParser.ReadPermissionNodes();

                LoadPlugins();

                /* Save access languages - once only */
                Languages.Save(Collections.Registries.LANGUAGE_FILE);

                HookContext ctx;
                HookArgs.ServerStateChange eArgs;

                string   worldFile = properties.WorldPath;
                FileInfo file      = new FileInfo(worldFile);

                if (!file.Exists)
                {
                    try
                    {
                        file.Directory.Create();
                    }
                    catch (Exception exception)
                    {
                        ProgramLog.Log(exception);
                        ProgramLog.Console.Print(Languages.Startup_PressAnyKeyToExit);
                        Console.ReadKey(true);
                        return;
                    }

                    ctx = new HookContext
                    {
                        Sender = World.Sender,
                    };

                    eArgs = new HookArgs.ServerStateChange
                    {
                        ServerChangeState = ServerState.GENERATING
                    };

                    HookPoints.ServerStateChange.Invoke(ref ctx, ref eArgs);

                    ProgramLog.Log("{0} '{1}'", Languages.Startup_GeneratingWorld, worldFile);

                    string seed = properties.Seed;
                    if (seed == "-1")
                    {
                        seed = WorldModify.genRand.Next(Int32.MaxValue).ToString();
                        ProgramLog.Log("{0} {1}", Languages.Startup_GeneratedSeed, seed);
                    }

                    int worldX = properties.GetMapSizes()[0];
                    int worldY = properties.GetMapSizes()[1];
                    if (properties.UseCustomTiles)
                    {
                        int X = properties.MaxTilesX;
                        int Y = properties.MaxTilesY;
                        if (X > 0 && Y > 0)
                        {
                            worldX = X;
                            worldY = Y;
                        }

                        if (worldX < (int)World.MAP_SIZE.SMALL_X || worldY < (int)World.MAP_SIZE.SMALL_Y)
                        {
                            ProgramLog.Log("{0} {1}x{2}", Languages.Startup_WorldSizingError, (int)World.MAP_SIZE.SMALL_X, (int)World.MAP_SIZE.SMALL_Y);
                            worldX = (int)((int)World.MAP_SIZE.SMALL_Y * 3.5);
                            worldY = (int)World.MAP_SIZE.SMALL_Y;
                        }

                        ProgramLog.Log("{0} {1}x{2}", Languages.Startup_GeneratingWithCustomSize, worldX, worldY);
                    }

                    Terraria_Server.Main.maxTilesX = worldX;
                    Terraria_Server.Main.maxTilesY = worldY;

                    WorldIO.ClearWorld();
                    Terraria_Server.Main.Initialize();
                    if (properties.UseCustomGenOpts)
                    {
                        WorldGen.numDungeons = properties.DungeonAmount;
                        WorldModify.ficount  = properties.FloatingIslandAmount;
                    }
                    else
                    {
                        WorldGen.numDungeons = 1;
                        WorldModify.ficount  = (int)((double)Terraria_Server.Main.maxTilesX * 0.0008);                        //The Statics one was generating with default values, We want it to use the actual tileX for the world
                    }
                    WorldGen.GenerateWorld(null, seed);
                    WorldIO.SaveWorld(worldFile, true);
                }

                ctx = new HookContext
                {
                    Sender = World.Sender,
                };

                eArgs = new HookArgs.ServerStateChange
                {
                    ServerChangeState = ServerState.LOADING
                };

                HookPoints.ServerStateChange.Invoke(ref ctx, ref eArgs);

                // TODO: read map size from world file instead of config
                int worldXtiles = properties.GetMapSizes()[0];
                int worldYtiles = properties.GetMapSizes()[1];

                if (properties.UseCustomTiles)
                {
                    int X = properties.MaxTilesX;
                    int Y = properties.MaxTilesY;
                    if (X > 0 && Y > 0)
                    {
                        worldXtiles = X;
                        worldYtiles = Y;
                    }

                    if (worldXtiles < (int)World.MAP_SIZE.SMALL_X || worldYtiles < (int)World.MAP_SIZE.SMALL_Y)
                    {
                        ProgramLog.Log("{0} {1}x{2}", Languages.Startup_WorldSizingError, (int)World.MAP_SIZE.SMALL_X, (int)World.MAP_SIZE.SMALL_Y);
                        worldXtiles = (int)((int)World.MAP_SIZE.SMALL_Y * 3.5);
                        worldYtiles = (int)World.MAP_SIZE.SMALL_Y;
                    }

                    ProgramLog.Log("{0} {1}x{2}", Languages.Startup_GeneratingWithCustomSize, worldXtiles, worldXtiles);
                }

                World.SavePath = worldFile;

                Server.InitializeData(properties.MaxPlayers,
                                      Statics.DataPath + Path.DirectorySeparatorChar + "whitelist.txt",
                                      Statics.DataPath + Path.DirectorySeparatorChar + "banlist.txt",
                                      Statics.DataPath + Path.DirectorySeparatorChar + "oplist.txt");
                NetPlay.password   = properties.Password;
                NetPlay.serverPort = properties.Port;
                NetPlay.serverSIP  = properties.ServerIP;
                Terraria_Server.Main.Initialize();

                Terraria_Server.Main.maxTilesX    = worldXtiles;
                Terraria_Server.Main.maxTilesY    = worldYtiles;
                Terraria_Server.Main.maxSectionsX = worldXtiles / 200;
                Terraria_Server.Main.maxSectionsY = worldYtiles / 150;

                WorldIO.LoadWorld(null, null, World.SavePath);

                ctx = new HookContext
                {
                    Sender = World.Sender,
                };

                eArgs = new HookArgs.ServerStateChange
                {
                    ServerChangeState = ServerState.LOADED
                };

                HookPoints.ServerStateChange.Invoke(ref ctx, ref eArgs);

                updateThread = new ProgramThread("Updt", Program.UpdateLoop);

                ProgramLog.Log(Languages.Startup_StartingTheServer);
                NetPlay.StartServer();

                while (!NetPlay.ServerUp)
                {
                }

                ThreadPool.QueueUserWorkItem(CommandThread);
                ProgramLog.Console.Print(Languages.Startup_YouCanNowInsertCommands);

                while (WorldModify.saveLock || NetPlay.ServerUp || Restarting)
                {
                    Thread.Sleep(100);
                }

                ProgramLog.Log(Languages.Startup_Exiting);
                Thread.Sleep(1000);
            }
            catch (UpdateCompleted) { }
            catch (Exception e)
            {
                try
                {
                    using (StreamWriter streamWriter = new StreamWriter(Statics.DataPath + Path.DirectorySeparatorChar + "crashlog.txt", true))
                    {
                        streamWriter.WriteLine(DateTime.Now);
                        streamWriter.WriteLine(String.Format("{0} {1}", Languages.Startup_CrashlogGeneratedBy, MODInfo));
                        streamWriter.WriteLine(e);
                        streamWriter.WriteLine();
                    }
                    ProgramLog.Log(e, Languages.Startup_ProgramCrash);
                    ProgramLog.Log("{0} crashlog.txt -> http://tdsm.org/", Languages.Startup_PleaseSend);
                }
                catch { }
            }

            if (properties != null && File.Exists(properties.PIDFile.Trim()))
            {
                File.Delete(properties.PIDFile.Trim());
            }

            Thread.Sleep(500);
            ProgramLog.Log(Languages.Startup_LogEnd);
            ProgramLog.Close();

            RemoteConsole.RConServer.Stop();
        }