public void ThreadRun()
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            try
            {
                _cfgFile = new FLDataFile("flopenserver.cfg", false);
                FLPath   = _cfgFile.GetSetting("server", "fl_path").Str(0);
                AcctPath = _cfgFile.GetSetting("server", "acct_path").Str(0);

                if (AcctPath == "")
                {
                    AcctPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
                               @"\My Games\Freelancer\Accts\MultiPlayer";
                }

                if (_cfgFile.SettingExists("server", "server_id"))
                {
                    ServerID = _cfgFile.GetSetting("server", "server_id").Str(0);
                }

                if (_cfgFile.SettingExists("server", "version"))
                {
                    server_version = _cfgFile.GetSetting("server", "version").Str(0);
                }

                if (server_version == "")
                {
                    FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(FLPath + @"\EXE\Freelancer.exe");
                    var             ver = new int[4];
                    ver[0] = myFileVersionInfo.FileMajorPart;
                    ver[1] = myFileVersionInfo.FileMinorPart;
                    ver[2] = myFileVersionInfo.FileBuildPart;
                    ver[3] = myFileVersionInfo.FilePrivatePart;

                    var sb = new StringBuilder();
                    foreach (var num in ver)
                    {
                        sb.Append(".");
                        if (num < 10)
                        {
                            sb.Append("0");
                        }
                        sb.Append(num);
                    }

                    server_version = sb.ToString().Substring(1);
                }


                ServerDescription = _cfgFile.GetSetting("server", "description").Str(0);
                server_news       = _cfgFile.GetSetting("server", "news").Str(0);

                foreach (FLDataFile.Setting set in _cfgFile.GetSettings("intro_msg"))
                {
                    IntroMsg += set.Line;
                }

                foreach (FLDataFile.Setting set in _cfgFile.GetSettings("banner_msg"))
                {
                    BannerMsg += set.Line;
                }

                foreach (FLDataFile.Setting set in _cfgFile.GetSettings("user_help_msg"))
                {
                    UserHelpMsg += set.Line;
                }

                foreach (FLDataFile.Setting set in _cfgFile.GetSettings("admin_help_msg"))
                {
                    AdminHelpMsg += set.Line;
                }
            }
            catch (Exception e)
            {
                _log.AddLog(LogType.ERROR, "error: flopenserver.cfg not found or missing parameter " + e.Message);
                return;
            }

            string name        = _cfgFile.GetSetting("server", "name").Str(0);
            uint   port        = _cfgFile.GetSetting("server", "port").UInt(0);
            var    max_players = (int)_cfgFile.GetSetting("server", "max_players").UInt(0);

            if (ServerID == null)
            {
                ReadFLDefaults();
            }

            _log.AddLog(LogType.GENERAL, "cfg_file = " + _cfgFile.FilePath);
            _log.AddLog(LogType.GENERAL, "fl_path = " + FLPath);
            _log.AddLog(LogType.GENERAL, "acct_path = " + AcctPath);
            _log.AddLog(LogType.GENERAL, "server_id = " + ServerID);
            _log.AddLog(LogType.GENERAL, "version = " + server_version);
            _log.AddLog(LogType.GENERAL, "name = " + name);
            _log.AddLog(LogType.GENERAL, "port = " + port);
            _log.AddLog(LogType.GENERAL, "max_players = " + max_players);


            ArchetypeDB.Load(FLPath, _log);
            UniverseDB.Load(FLPath, _log);
            News.Load(FLPath, _log);
            _log.AddLog(LogType.GENERAL, "Ready to start");

            try
            {
                string[] arg     = server_version.Split('.');
                uint     major   = uint.Parse(arg[0]) & 0xFF;
                uint     minor   = uint.Parse(arg[1]) & 0xFF;
                uint     patch   = uint.Parse(arg[2]) & 0xFF;
                uint     build   = uint.Parse(arg[3]) & 0xFF;
                uint     version = (major << 24) | (minor << 16) | (patch << 8) | build;
                server_version = version.ToString(CultureInfo.InvariantCulture);
            }
            catch
            {
                _log.AddLog(LogType.ERROR, "invalid server version string");
                server_version = "0";
            }

            // Try to start the direct play server. Complain if it fails but don't pass the exception on.
            try
            {
                _dplay = new DirectPlayServer(this, _log, (int)port)
                {
                    server_name        = name + "\0",
                    server_id          = ServerID,
                    server_description = ServerDescription + "\0",
                    server_version     = server_version,
                    max_players        = (uint)max_players
                };
                _log.AddLog(LogType.GENERAL, "Server started");
            }
            catch (Exception e)
            {
                _log.AddLog(LogType.ERROR, "Cannot open socket reason={0}", e.Message);
            }

            _dplay.GotMessage      += _dplay_GotMessage;
            _dplay.PlayerConnected += _dplay_PlayerConnected;
            _dplay.PlayerDestroyed += _dplay_PlayerDestroyed;

            // Kick off the game runner threads. We have one thread per system. New
            // players who have not selected a character are assigned to a random
            // runner thread.
            uint baseObjid = 1;

            foreach (var starSystem in UniverseDB.Systems.Values)
            {
                _runners[starSystem] = new DPGameRunner(this, _log, baseObjid, starSystem);
                baseObjid           += 10000;
            }
        }
Ejemplo n.º 2
0
        public void ThreadRun()
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            try
            {
                _cfgFile = new FLDataFile("flopenserver.cfg", false);
                FLPath   = _cfgFile.GetSetting("server", "fl_path").Str(0);
                AcctPath = _cfgFile.GetSetting("server", "acct_path").Str(0);

                if (AcctPath == "")
                {
                    AcctPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
                               @"\My Games\Freelancer\Accts\MultiPlayer";
                }

                if (_cfgFile.SettingExists("server", "server_id"))
                {
                    ServerID = _cfgFile.GetSetting("server", "server_id").Str(0);
                }

                if (_cfgFile.SettingExists("server", "version"))
                {
                    server_version = _cfgFile.GetSetting("server", "version").Str(0);
                }

                if (server_version == "")
                {
                    FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(FLPath + @"\EXE\Freelancer.exe");
                    var             ver = new int[4];
                    ver[0] = myFileVersionInfo.FileMajorPart;
                    ver[1] = myFileVersionInfo.FileMinorPart;
                    ver[2] = myFileVersionInfo.FileBuildPart;
                    ver[3] = myFileVersionInfo.FilePrivatePart;

                    var sb = new StringBuilder();
                    foreach (var num in ver)
                    {
                        sb.Append(".");
                        if (num < 10)
                        {
                            sb.Append("0");
                        }
                        sb.Append(num);
                    }

                    server_version = sb.ToString().Substring(1);
                }


                ServerDescription = _cfgFile.GetSetting("server", "description").Str(0);
                server_news       = _cfgFile.GetSetting("server", "news").Str(0);

                foreach (FLDataFile.Setting set in _cfgFile.GetSettings("intro_msg"))
                {
                    IntroMsg += set.Line;
                }

                foreach (FLDataFile.Setting set in _cfgFile.GetSettings("banner_msg"))
                {
                    BannerMsg += set.Line;
                }

                foreach (FLDataFile.Setting set in _cfgFile.GetSettings("user_help_msg"))
                {
                    UserHelpMsg += set.Line;
                }

                foreach (FLDataFile.Setting set in _cfgFile.GetSettings("admin_help_msg"))
                {
                    AdminHelpMsg += set.Line;
                }
            }
            catch (Exception e)
            {
                _log.AddLog(LogType.ERROR, "error: flopenserver.cfg not found or missing parameter " + e.Message);
                return;
            }

            string name        = _cfgFile.GetSetting("server", "name").Str(0);
            uint   port        = _cfgFile.GetSetting("server", "port").UInt(0);
            var    max_players = (int)_cfgFile.GetSetting("server", "max_players").UInt(0);

            if (ServerID == null)
            {
                ReadFLDefaults();
            }

            _log.AddLog(LogType.GENERAL, "cfg_file = " + _cfgFile.FilePath);
            _log.AddLog(LogType.GENERAL, "fl_path = " + FLPath);
            _log.AddLog(LogType.GENERAL, "acct_path = " + AcctPath);
            _log.AddLog(LogType.GENERAL, "server_id = " + ServerID);
            _log.AddLog(LogType.GENERAL, "version = " + server_version);
            _log.AddLog(LogType.GENERAL, "name = " + name);
            _log.AddLog(LogType.GENERAL, "port = " + port);
            _log.AddLog(LogType.GENERAL, "max_players = " + max_players);


            ArchetypeDB.Load(FLPath, _log);
            UniverseDB.Load(FLPath, _log);
            News.Load(FLPath, _log);
            _log.AddLog(LogType.GENERAL, "Ready to start");

            try
            {
                string[] arg     = server_version.Split('.');
                uint     major   = uint.Parse(arg[0]) & 0xFF;
                uint     minor   = uint.Parse(arg[1]) & 0xFF;
                uint     patch   = uint.Parse(arg[2]) & 0xFF;
                uint     build   = uint.Parse(arg[3]) & 0xFF;
                uint     version = (major << 24) | (minor << 16) | (patch << 8) | build;
                server_version = version.ToString(CultureInfo.InvariantCulture);
            }
            catch
            {
                _log.AddLog(LogType.ERROR, "invalid server version string");
                server_version = "0";
            }

            // Try to start the direct play server. Complain if it fails but don't pass the exception on.
            try
            {
                _dplay = new DirectPlayServer(this, _log, (int)port)
                {
                    server_name        = name + "\0",
                    server_id          = ServerID,
                    server_description = ServerDescription + "\0",
                    server_version     = server_version,
                    max_players        = (uint)max_players
                };
                _log.AddLog(LogType.GENERAL, "Server started");
            }
            catch (Exception e)
            {
                _log.AddLog(LogType.ERROR, "Cannot open socket reason={0}", e.Message);
            }

            // Kick off the game runner threads. We have one thread per system. New
            // players who have not selected a character are assigned to a random
            // runner thread.
            uint baseObjid = 1;

            foreach (var starSystem in UniverseDB.Systems.Values)
            {
                _runners[starSystem] = new DPGameRunner(this, _log, baseObjid, starSystem);
                baseObjid           += 10000;
            }

            // Run the event/timer processing loop for this thread.
            var currentTime = Utilities.GetTime();
            var running     = true;

            while (running)
            {
                // Calculate the delta time.
                var delta = Utilities.GetTime() - currentTime;
                currentTime += delta;

                // Call the reactor to return the next event the process
                // and run any timer functions.
                var nextEvent = Run(currentTime, delta);

                if (nextEvent is DPSessionConnectedEvent)
                {
                    // On receipt of a new connection, create a new player assigning it to a
                    // random game thread. Notify all game threads of the new player.
                    var serverEvent = nextEvent as DPSessionConnectedEvent;

                    var defaultRunner = _runners.ElementAt(_rand.Next(_runners.Count - 1)).Value;

                    var player = new Player.Player(serverEvent.dplayid, _log, NewPlayerID(), defaultRunner);
                    Players[serverEvent.dplayid] = player;

                    foreach (var runner in _runners.Values)
                    {
                        runner.AddEvent(new DPGameRunnerPlayerUpdateEvent(player));
                    }
                }
                else if (nextEvent is DPSessionTerminatedEvent)
                {
                    // The session has died. Tell all game threads that it is dead and the player
                    // is gone.
                    // TODO: save player?
                    var serverEvent = nextEvent as DPSessionTerminatedEvent;
                    if (Players.ContainsKey(serverEvent.dplayid))
                    {
                        var player = Players[serverEvent.dplayid];
                        Players.Remove(serverEvent.dplayid);

                        foreach (var runner in _runners.Values)
                        {
                            runner.AddEvent(new DPGameRunnerPlayerDeletedEvent(player.FLPlayerID));
                        }
                    }

                    // Kill the dplay connection if it is not already dead
                    try
                    {
                        /* fixme: dplay.DestroyClient(server_event.dplayid, null); */
                    }
                    catch
                    {
                    }
                }
                else if (nextEvent is DPGameRunnerPlayerUpdateEvent)
                {
                    // A game thread has sent a notification to say that the player has changed - either
                    // name, rank or system. We might change the assigned thread as a result.
                    // In any case, we notify all game threads of the current name, rank and system.
                    var serverEvent = nextEvent as DPGameRunnerPlayerUpdateEvent;

                    // Find runner for this system and if it's changed tell the old and new runners
                    // of the change in ownership.
                    var currRunner = serverEvent.runner;
                    var newRunner  = _runners[serverEvent.system];
                    if (newRunner != currRunner)
                    {
                        serverEvent.runner = newRunner;
                    }

                    // Notify all game threads of the current player info so they can update their
                    // player lists.
                    foreach (var runner in _runners.Values)
                    {
                        runner.AddEvent(serverEvent);
                    }
                }
                else if (nextEvent is DPSessionRxMessageFromClient)
                {
                    var server_event = nextEvent as DPSessionRxMessageFromClient;
                    if (Players.ContainsKey(server_event.dplayid))
                    {
                        Player.Player player = Players[server_event.dplayid];
                        player.Runner.AddEvent(new DPGameRunnerRxMsgEvent(player, server_event.msg));
                    }
                }
                else if (nextEvent is ReactorShutdownEvent)
                {
                    foreach (DPGameRunner runner in _runners.Values)
                    {
                        runner.AddEvent(new ReactorShutdownEvent());
                    }
                    running = false;
                }
            }
        }