Пример #1
0
        public LoginServer(IPAddress listen, ushort clientManagerPort, ushort searchManagerPort, Action <string, string> log, Action <string, string> logError)
        {
            ServicePointManager.SetTcpKeepAlive(true, 60 * 1000 * 10, 1000);

            Log      = log;
            LogError = logError;

            GeoIP.Initialize(log, Category);

            ThreadClientManager = new Thread(StartServerClientManager)
            {
                Name = "Login Thread Client Manager"
            };
            ThreadClientManager.Start(new AddressInfo()
            {
                Address = listen,
                Port    = clientManagerPort
            });

            ThreadSearchManager = new Thread(StartServerSearchManager)
            {
                Name = "Login Thread Search Manager"
            };
            ThreadSearchManager.Start(new AddressInfo()
            {
                Address = listen,
                Port    = searchManagerPort
            });
        }
Пример #2
0
        public ServerListReport(IPAddress listen, ushort port, Action <string, string> log, Action <string, string> logError)
        {
            Log      = log;
            LogError = logError;

            GeoIP.Initialize(log, Category);

            Servers = new ConcurrentDictionary <string, GameServer>();

            Thread = new Thread(StartServer)
            {
                Name = "Server Reporting Socket Thread"
            };
            Thread.Start(new AddressInfo()
            {
                Address = listen,
                Port    = port
            });

            new Thread(StartCleanup)
            {
                Name = "Server Reporting Cleanup Thread"
            }.Start();

            new Thread(StartDynamicInfoReload)
            {
                Name = "Dynamic Info Reload Thread"
            }.Start();
        }
        public ServerListReport(IPAddress listen, ushort port)
        {
            GeoIP.Initialize(Log, Category);

            StartServer(new AddressInfo()
            {
                Address = listen,
                Port    = port
            });
        }
Пример #4
0
        public HttpServer(IPAddress listen, ushort port)
        {
            GeoIP.Initialize(Log, Category);

            _thread = new Thread(StartServer)
            {
                Name = "Http Socket Thread"
            };

            _thread.Start(new AddressInfo()
            {
                Address = listen,
                Port    = port
            });
        }
Пример #5
0
        public ServerNatNeg(IPAddress listen, ushort port, Action <string, string> log, Action <string, string> logError)
        {
            Log      = log;
            LogError = logError;

            GeoIP.Initialize(log, Category);

            Thread = new Thread(StartServer)
            {
                Name = "Server NatNeg Socket Thread"
            };
            Thread.Start(new AddressInfo()
            {
                Address = listen,
                Port    = port
            });
        }
Пример #6
0
        //  public static void SendToAllConnected()
        //  {
        //_socket.
        //    }
        public ServerListReport(IPAddress listen, ushort port, Action <string, string> log, Action <string, string> logError, string gameName)
        {
            if (gameName != null)
            {
                _gameName = gameName;
            }
            List <byte> initialMessage = new byte[] { 0x09, 0x00, 0x00, 0x00, 0x00 }.ToList();

            initialMessage.AddRange(Encoding.ASCII.GetBytes(_gameName));
            initialMessage.Add(0x00);
            //Console.WriteLine("[initial:]" + _initialMessage[0] + _initialMessage[1] + _initialMessage[2] + _initialMessage[3] + _initialMessage[4] + ',' + _initialMessage[5] + ',' + _initialMessage[6] + ',' + _initialMessage[7] + ',' + _initialMessage[8] + ',' + _initialMessage[9]);
            _initialMessage = initialMessage.ToArray();
            //Console.WriteLine("[initial:]" + _initialMessage[0] + _initialMessage[1] + _initialMessage[2] + _initialMessage[3] + _initialMessage[4] + ',' + _initialMessage[5] + ',' + _initialMessage[6] + ',' + _initialMessage[7] + ',' + _initialMessage[8]);

            Log      = log;
            LogError = logError;

            GeoIP.Initialize(log, Category);

            Servers = new ConcurrentDictionary <string, GameServer>();

            Thread = new Thread(StartServer)
            {
                Name = "Server Reporting Socket Thread"
            };
            Thread.Start(new AddressInfo()
            {
                Address = listen,
                Port    = port
            });

            new Thread(StartCleanup)
            {
                Name = "Server Reporting Cleanup Thread"
            }.Start();

            new Thread(StartDynamicInfoReload)
            {
                Name = "Dynamic Info Reload Thread"
            }.Start();
        }
Пример #7
0
        static void Initialize(Arguments args)
        {
            Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);

            // Load the engine version as early as possible so it can be written to exception logs
            try
            {
                EngineVersion = File.ReadAllText(Platform.ResolvePath(Path.Combine(".", "VERSION"))).Trim();
            }
            catch { }

            if (string.IsNullOrEmpty(EngineVersion))
            {
                EngineVersion = "Unknown";
            }

            Console.WriteLine("Engine version is {0}", EngineVersion);

            // Special case handling of Game.Mod argument: if it matches a real filesystem path
            // then we use this to override the mod search path, and replace it with the mod id
            var modID            = args.GetValue("Game.Mod", null);
            var explicitModPaths = new string[0];

            if (modID != null && (File.Exists(modID) || Directory.Exists(modID)))
            {
                explicitModPaths = new[] { modID };
                modID            = Path.GetFileNameWithoutExtension(modID);
            }

            InitializeSettings(args);

            Log.AddChannel("perf", "perf.log");
            Log.AddChannel("debug", "debug.log");
            Log.AddChannel("server", "server.log");
            Log.AddChannel("sound", "sound.log");
            Log.AddChannel("graphics", "graphics.log");
            Log.AddChannel("geoip", "geoip.log");
            Log.AddChannel("irc", "irc.log");
            Log.AddChannel("nat", "nat.log");

            Sound    = new Sound();
            Renderer = new Renderer(Settings.Graphics);
            GeoIP.Initialize();

            if (Settings.Server.DiscoverNatDevices)
            {
                discoverNat = UPnP.DiscoverNatDevices(Settings.Server.NatDiscoveryTimeout);
            }

            var modSearchArg   = args.GetValue("Engine.ModSearchPaths", null);
            var modSearchPaths = modSearchArg != null?
                                 FieldLoader.GetValue <string[]>("Engine.ModsPath", modSearchArg) :
                                     new[] { Path.Combine(".", "mods") };

            Mods = new InstalledMods(modSearchPaths, explicitModPaths);
            Console.WriteLine("Internal mods:");
            foreach (var mod in Mods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Metadata.Title, mod.Value.Metadata.Version);
            }

            ExternalMods = new ExternalMods();

            Manifest currentMod;

            if (modID != null && Mods.TryGetValue(modID, out currentMod))
            {
                var launchPath = args.GetValue("Engine.LaunchPath", Assembly.GetEntryAssembly().Location);

                // Sanitize input from platform-specific launchers
                // Process.Start requires paths to not be quoted, even if they contain spaces
                if (launchPath.First() == '"' && launchPath.Last() == '"')
                {
                    launchPath = launchPath.Substring(1, launchPath.Length - 2);
                }

                ExternalMods.Register(Mods[modID], launchPath, ModRegistration.User);

                ExternalMod activeMod;
                if (ExternalMods.TryGetValue(ExternalMod.MakeKey(Mods[modID]), out activeMod))
                {
                    ExternalMods.ClearInvalidRegistrations(activeMod, ModRegistration.User);
                }
            }

            Console.WriteLine("External mods:");
            foreach (var mod in ExternalMods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
            }

            InitializeMod(modID, args);
        }
Пример #8
0
        public Server(List <IPEndPoint> endpoints, ServerSettings settings, ModData modData, ServerType type)
        {
            Log.AddChannel("server", "server.log", true);

            SocketException lastException   = null;
            var             checkReadServer = new List <Socket>();

            foreach (var endpoint in endpoints)
            {
                var listener = new TcpListener(endpoint);
                try
                {
                    try
                    {
                        listener.Server.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 1);
                    }
                    catch (Exception ex)
                    {
                        if (ex is SocketException || ex is ArgumentException)
                        {
                            Log.Write("server", "Failed to set socket option on {0}: {1}", endpoint.ToString(), ex.Message);
                        }
                        else
                        {
                            throw;
                        }
                    }

                    listener.Start();
                    listeners.Add(listener);
                    checkReadServer.Add(listener.Server);
                }
                catch (SocketException ex)
                {
                    lastException = ex;
                    Log.Write("server", "Failed to listen on {0}: {1}", endpoint.ToString(), ex.Message);
                }
            }

            if (listeners.Count == 0)
            {
                throw lastException;
            }

            Type     = type;
            Settings = settings;

            Settings.Name = OpenRA.Settings.SanitizedServerName(Settings.Name);

            ModData = modData;

            playerDatabase = modData.Manifest.Get <PlayerDatabase>();

            randomSeed = (int)DateTime.Now.ToBinary();

            if (type != ServerType.Local && settings.EnableGeoIP)
            {
                GeoIP.Initialize();
            }

            if (UPnP.Status == UPnPStatus.Enabled)
            {
                UPnP.ForwardPort(Settings.ListenPort, Settings.ListenPort).Wait();
            }

            foreach (var trait in modData.Manifest.ServerTraits)
            {
                serverTraits.Add(modData.ObjectCreator.CreateObject <ServerTrait>(trait));
            }

            serverTraits.TrimExcess();

            LobbyInfo = new Session
            {
                GlobalSettings =
                {
                    RandomSeed         = randomSeed,
                    Map                = settings.Map,
                    ServerName         = settings.Name,
                    EnableSingleplayer = settings.EnableSingleplayer || Type != ServerType.Dedicated,
                    EnableSyncReports  = settings.EnableSyncReports,
                    GameUid            = Guid.NewGuid().ToString(),
                    Dedicated          = Type == ServerType.Dedicated
                }
            };

            new Thread(_ =>
            {
                foreach (var t in serverTraits.WithInterface <INotifyServerStart>())
                {
                    t.ServerStarted(this);
                }

                Log.Write("server", "Initial mod: {0}", ModData.Manifest.Id);
                Log.Write("server", "Initial map: {0}", LobbyInfo.GlobalSettings.Map);

                while (true)
                {
                    var checkRead = new List <Socket>();
                    if (State == ServerState.WaitingPlayers)
                    {
                        checkRead.AddRange(checkReadServer);
                    }

                    checkRead.AddRange(Conns.Select(c => c.Socket));
                    checkRead.AddRange(PreConns.Select(c => c.Socket));

                    // Block for at most 1 second in order to guarantee a minimum tick rate for ServerTraits
                    // Decrease this to 100ms to improve responsiveness if we are waiting for an authentication query
                    var localTimeout = waitingForAuthenticationCallback > 0 ? 100000 : 1000000;
                    if (checkRead.Count > 0)
                    {
                        Socket.Select(checkRead, null, null, localTimeout);
                    }

                    if (State == ServerState.ShuttingDown)
                    {
                        EndGame();
                        break;
                    }

                    foreach (var s in checkRead)
                    {
                        var serverIndex = checkReadServer.IndexOf(s);
                        if (serverIndex >= 0)
                        {
                            AcceptConnection(listeners[serverIndex]);
                            continue;
                        }

                        var preConn = PreConns.SingleOrDefault(c => c.Socket == s);
                        if (preConn != null)
                        {
                            preConn.ReadData(this);
                            continue;
                        }

                        var conn = Conns.SingleOrDefault(c => c.Socket == s);
                        conn?.ReadData(this);
                    }

                    delayedActions.PerformActions(0);

                    // PERF: Dedicated servers need to drain the action queue to remove references blocking the GC from cleaning up disposed objects.
                    if (Type == ServerType.Dedicated)
                    {
                        Game.PerformDelayedActions();
                    }

                    foreach (var t in serverTraits.WithInterface <ITick>())
                    {
                        t.Tick(this);
                    }

                    if (State == ServerState.ShuttingDown)
                    {
                        EndGame();
                        if (UPnP.Status == UPnPStatus.Enabled)
                        {
                            UPnP.RemovePortForward().Wait();
                        }
                        break;
                    }
                }

                foreach (var t in serverTraits.WithInterface <INotifyServerShutdown>())
                {
                    t.ServerShutdown(this);
                }

                PreConns.Clear();
                Conns.Clear();

                foreach (var listener in listeners)
                {
                    try { listener.Stop(); }
                    catch { }
                }
            })
            {
                IsBackground = true
            }.Start();
        }
Пример #9
0
        static void Initialize(Arguments args)
        {
            var supportDirArg = args.GetValue("Engine.SupportDir", null);

            if (supportDirArg != null)
            {
                Platform.OverrideSupportDir(supportDirArg);
            }

            Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);

            // Load the engine version as early as possible so it can be written to exception logs
            try
            {
                EngineVersion = File.ReadAllText(Platform.ResolvePath(Path.Combine(".", "VERSION"))).Trim();
            }
            catch { }

            if (string.IsNullOrEmpty(EngineVersion))
            {
                EngineVersion = "Unknown";
            }

            Console.WriteLine("Engine version is {0}", EngineVersion);

            // Special case handling of Game.Mod argument: if it matches a real filesystem path
            // then we use this to override the mod search path, and replace it with the mod id
            var modID            = args.GetValue("Game.Mod", null);
            var explicitModPaths = new string[0];

            if (modID != null && (File.Exists(modID) || Directory.Exists(modID)))
            {
                explicitModPaths = new[] { modID };
                modID            = Path.GetFileNameWithoutExtension(modID);
            }

            InitializeSettings(args);

            Log.AddChannel("perf", "perf.log");
            Log.AddChannel("debug", "debug.log");
            Log.AddChannel("server", "server.log", true);
            Log.AddChannel("sound", "sound.log");
            Log.AddChannel("graphics", "graphics.log");
            Log.AddChannel("geoip", "geoip.log");
            Log.AddChannel("nat", "nat.log");

            var platforms = new[] { Settings.Game.Platform, "Default", null };

            foreach (var p in platforms)
            {
                if (p == null)
                {
                    throw new InvalidOperationException("Failed to initialize platform-integration library. Check graphics.log for details.");
                }

                Settings.Game.Platform = p;
                try
                {
                    var rendererPath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + p + ".dll"));
                    var assembly     = Assembly.LoadFile(rendererPath);

                    var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
                    if (platformType == null)
                    {
                        throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation.");
                    }

                    var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null);
                    Renderer = new Renderer(platform, Settings.Graphics);
                    Sound    = new Sound(platform, Settings.Sound);

                    break;
                }
                catch (Exception e)
                {
                    Log.Write("graphics", "{0}", e);
                    Console.WriteLine("Renderer initialization failed. Check graphics.log for details.");

                    if (Renderer != null)
                    {
                        Renderer.Dispose();
                    }

                    if (Sound != null)
                    {
                        Sound.Dispose();
                    }
                }
            }

            GeoIP.Initialize();

            if (Settings.Server.DiscoverNatDevices)
            {
                discoverNat = UPnP.DiscoverNatDevices(Settings.Server.NatDiscoveryTimeout);
            }

            var modSearchArg   = args.GetValue("Engine.ModSearchPaths", null);
            var modSearchPaths = modSearchArg != null?
                                 FieldLoader.GetValue <string[]>("Engine.ModsPath", modSearchArg) :
                                     new[] { Path.Combine(".", "mods") };

            Mods = new InstalledMods(modSearchPaths, explicitModPaths);
            Console.WriteLine("Internal mods:");
            foreach (var mod in Mods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Metadata.Title, mod.Value.Metadata.Version);
            }

            modLaunchWrapper = args.GetValue("Engine.LaunchWrapper", null);

            ExternalMods = new ExternalMods();

            Manifest currentMod;

            if (modID != null && Mods.TryGetValue(modID, out currentMod))
            {
                var launchPath = args.GetValue("Engine.LaunchPath", Assembly.GetEntryAssembly().Location);

                // Sanitize input from platform-specific launchers
                // Process.Start requires paths to not be quoted, even if they contain spaces
                if (launchPath.First() == '"' && launchPath.Last() == '"')
                {
                    launchPath = launchPath.Substring(1, launchPath.Length - 2);
                }

                ExternalMods.Register(Mods[modID], launchPath, ModRegistration.User);

                ExternalMod activeMod;
                if (ExternalMods.TryGetValue(ExternalMod.MakeKey(Mods[modID]), out activeMod))
                {
                    ExternalMods.ClearInvalidRegistrations(activeMod, ModRegistration.User);
                }
            }

            Console.WriteLine("External mods:");
            foreach (var mod in ExternalMods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
            }

            InitializeMod(modID, args);
        }
Пример #10
0
        internal static void Initialize(Arguments args)
        {
            Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);

            // Special case handling of Game.Mod argument: if it matches a real filesystem path
            // then we use this to override the mod search path, and replace it with the mod id
            var    modArgument   = args.GetValue("Game.Mod", null);
            string customModPath = null;

            if (modArgument != null && (File.Exists(modArgument) || Directory.Exists(modArgument)))
            {
                customModPath = modArgument;
                args.ReplaceValue("Game.Mod", Path.GetFileNameWithoutExtension(modArgument));
            }

            InitializeSettings(args);

            Log.AddChannel("perf", "perf.log");
            Log.AddChannel("debug", "debug.log");
            Log.AddChannel("server", "server.log");
            Log.AddChannel("sound", "sound.log");
            Log.AddChannel("graphics", "graphics.log");
            Log.AddChannel("geoip", "geoip.log");
            Log.AddChannel("irc", "irc.log");
            Log.AddChannel("nat", "nat.log");

            var platforms = new[] { Settings.Game.Platform, "Default", null };

            foreach (var p in platforms)
            {
                if (p == null)
                {
                    throw new InvalidOperationException("Failed to initialize platform-integration library. Check graphics.log for details.");
                }

                Settings.Game.Platform = p;
                try
                {
                    var rendererPath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + p + ".dll"));
                    var assembly     = Assembly.LoadFile(rendererPath);

                    var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
                    if (platformType == null)
                    {
                        throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation.");
                    }

                    var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null);
                    Renderer = new Renderer(platform, Settings.Graphics);
                    Sound    = new Sound(platform, Settings.Sound);

                    break;
                }
                catch (Exception e)
                {
                    Log.Write("graphics", "{0}", e);
                    Console.WriteLine("Renderer initialization failed. Check graphics.log for details.");

                    if (Renderer != null)
                    {
                        Renderer.Dispose();
                    }

                    if (Sound != null)
                    {
                        Sound.Dispose();
                    }
                }
            }

            GeoIP.Initialize();

            if (!Settings.Server.DiscoverNatDevices)
            {
                Settings.Server.AllowPortForward = false;
            }
            else
            {
                discoverNat = UPnP.DiscoverNatDevices(Settings.Server.NatDiscoveryTimeout);
                Settings.Server.AllowPortForward = true;
            }

            GlobalChat = new GlobalChat();

            Mods = new InstalledMods(customModPath);
            Console.WriteLine("Available mods:");
            foreach (var mod in Mods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Metadata.Title, mod.Value.Metadata.Version);
            }

            InitializeMod(Settings.Game.Mod, args);
        }
Пример #11
0
        internal static void Initialize(Arguments args)
        {
            Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);

            InitializeSettings(args);

            Log.AddChannel("perf", "perf.log");
            Log.AddChannel("debug", "debug.log");
            Log.AddChannel("sync", "syncreport.log");
            Log.AddChannel("server", "server.log");
            Log.AddChannel("sound", "sound.log");
            Log.AddChannel("graphics", "graphics.log");
            Log.AddChannel("geoip", "geoip.log");
            Log.AddChannel("irc", "irc.log");

            if (Settings.Server.DiscoverNatDevices)
            {
                UPnP.TryNatDiscovery();
            }
            else
            {
                Settings.Server.NatDeviceAvailable = false;
                Settings.Server.AllowPortForward   = false;
            }

            GeoIP.Initialize();

            var renderers = new[] { Settings.Graphics.Renderer, "Default", null };

            foreach (var r in renderers)
            {
                if (r == null)
                {
                    throw new InvalidOperationException("No suitable renderers were found. Check graphics.log for details.");
                }

                Settings.Graphics.Renderer = r;
                try
                {
                    Renderer = new Renderer(Settings.Graphics, Settings.Server);
                    break;
                }
                catch (Exception e)
                {
                    Log.Write("graphics", "{0}", e);
                    Console.WriteLine("Renderer initialization failed. Fallback in place. Check graphics.log for details.");
                }
            }

            Sound = new Sound(Settings.Sound.Engine);

            GlobalChat = new GlobalChat();

            Console.WriteLine("Available mods:");
            foreach (var mod in ModMetadata.AllMods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
            }

            InitializeMod(Settings.Game.Mod, args);

            if (Settings.Server.DiscoverNatDevices)
            {
                RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.StoppingNatDiscovery);
            }
        }
Пример #12
0
        internal static void Initialize(Arguments args)
        {
            Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);

            InitializeSettings(args);

            Log.AddChannel("perf", "perf.log");
            Log.AddChannel("debug", "debug.log");
            Log.AddChannel("sync", "syncreport.log");
            Log.AddChannel("server", "server.log");
            Log.AddChannel("sound", "sound.log");
            Log.AddChannel("graphics", "graphics.log");
            Log.AddChannel("geoip", "geoip.log");
            Log.AddChannel("irc", "irc.log");
            Log.AddChannel("nat", "nat.log");

            var platforms = new[] { Settings.Game.Platform, "Default", null };

            foreach (var p in platforms)
            {
                if (p == null)
                {
                    throw new InvalidOperationException("Failed to initialize platform-integration library. Check graphics.log for details.");
                }

                Settings.Game.Platform = p;
                try
                {
                    var rendererPath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + p + ".dll"));
                    var assembly     = Assembly.LoadFile(rendererPath);

                    var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
                    if (platformType == null)
                    {
                        throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation.");
                    }

                    var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null);
                    Renderer = new Renderer(platform, Settings.Graphics);
                    Sound    = new Sound(platform, Settings.Sound);

                    break;
                }
                catch (Exception e)
                {
                    Log.Write("graphics", "{0}", e);
                    Console.WriteLine("Renderer initialization failed. Check graphics.log for details.");

                    if (Renderer != null)
                    {
                        Renderer.Dispose();
                    }

                    if (Sound != null)
                    {
                        Sound.Dispose();
                    }
                }
            }

            GeoIP.Initialize();

            if (!Game.Settings.Server.DiscoverNatDevices)
            {
                Game.Settings.Server.AllowPortForward = false;
            }
            else
            {
                discoverNat = UPnP.DiscoverNatDevices(Settings.Server.NatDiscoveryTimeout);
                Game.Settings.Server.AllowPortForward = true;
            }

            GlobalChat = new GlobalChat();

            Console.WriteLine("Available mods:");
            foreach (var mod in ModMetadata.AllMods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
            }

            InitializeMod(Settings.Game.Mod, args);
        }
Пример #13
0
 public ServerSteamPortRetranslator()
 {
     GeoIP.Initialize(Log, Category);
     StartServer();
 }