public void Dispose()
 {
     talker?.UnsubscribeEvents(this);
     talker?.Dispose();
     timer?.Dispose();
     process?.UnsubscribeEvents(this);
     Context = null;
     scriptPath = null;
     gamePrivateMessages = null;
     process = null;
     talker = null;
 }
Example #2
0
        /// <summary>
        /// Starts spring game
        /// </summary>
        /// <param name="client">tasclient to get current battle from</param>
        /// <param name="priority">spring process priority</param>
        /// <param name="affinity">spring process cpu affinity</param>
        /// <param name="scriptOverride">if set, overrides generated script with supplied one</param>
        /// <param name="userName">lobby user name - used to submit score</param>
        /// <param name="passwordHash">lobby password hash - used to submit score</param>
        /// <returns>generates script</returns>
        public string StartGame(TasClient client, ProcessPriorityClass?priority, int?affinity, string scriptOverride, bool useSafeMode = false, bool useMultithreaded = false)
        {
            if (!File.Exists(paths.Executable) && !File.Exists(paths.DedicatedServer))
            {
                throw new ApplicationException(string.Format("Spring or dedicated server executable not found: {0}, {1}", paths.Executable, paths.DedicatedServer));
            }

            this.client = client;
            wasKilled   = false;

            if (!IsRunning)
            {
                gameEndedOk   = false;
                IsBattleOver  = false;
                lobbyUserName = client.UserName;
                lobbyPassword = client.UserPassword;
                battleResult  = new BattleResult();

                talker              = new Talker();
                talker.SpringEvent += talker_SpringEvent;
                isHosting           = client != null && client.MyBattle != null && client.MyBattle.Founder.Name == client.MyUser.Name;

                if (isHosting)
                {
                    scriptPath = Utils.MakePath(paths.WritableDirectory, "script_" + client.MyBattle.Founder + ".txt").Replace('\\', '/');
                }
                else
                {
                    scriptPath = Utils.MakePath(paths.WritableDirectory, "script.txt").Replace('\\', '/');
                }

                statsPlayers.Clear();
                statsData.Clear();
                StartContext = null;

                string script;
                if (!string.IsNullOrEmpty(scriptOverride))
                {
                    battleResult.IsMission = true;
                    isHosting = false;
                    script    = scriptOverride;
                }
                else
                {
                    List <UserBattleStatus> players;
                    battleGuid = Guid.NewGuid();
                    var service = new SpringieService()
                    {
                        Proxy = null
                    };
                    SpringBattleStartSetup startSetup = null;
                    if (isHosting && GlobalConst.IsZkMod(client.MyBattle.ModName))
                    {
                        try {
                            StartContext = client.MyBattle.GetContext();
                            startSetup   = service.GetSpringBattleStartSetup(StartContext);
                            if (startSetup.BalanceTeamsResult != null)
                            {
                                StartContext.Players = startSetup.BalanceTeamsResult.Players;
                                StartContext.Bots    = startSetup.BalanceTeamsResult.Bots;
                            }
                            connectedPlayers.Clear();
                            foreach (var p in StartContext.Players)
                            {
                                p.IsIngame = true;
                            }
                        } catch (Exception ex) {
                            Trace.TraceError("Error getting start setup: {0}", ex);
                        }
                    }

                    script = client.MyBattle.GenerateScript(out players, client.MyUser, talker.LoopbackPort, battleGuid.ToString(), startSetup);
                    battleResult.IsMission     = client.MyBattle.IsMission;
                    battleResult.IsBots        = client.MyBattle.Bots.Any();
                    battleResult.Title         = client.MyBattle.Title;
                    battleResult.Mod           = client.MyBattle.ModName;
                    battleResult.Map           = client.MyBattle.MapName;
                    battleResult.EngineVersion = paths.SpringVersion;
                    talker.SetPlayers(players);
                    statsPlayers = players.ToDictionary(x => x.Name,
                                                        x => new BattlePlayerResult
                    {
                        LobbyID       = x.LobbyUser.LobbyID,
                        AllyNumber    = x.AllyNumber,
                        CommanderType = null,
                        // todo commandertype
                        IsSpectator   = x.IsSpectator,
                        IsVictoryTeam = false,
                        Rank          = x.LobbyUser.Rank,
                    });
                }
                if (isHosting)
                {
                    timer.Start();
                }

                File.WriteAllText(scriptPath, script);

                LogLines = new StringBuilder();

                var optirun = Environment.GetEnvironmentVariable("OPTIRUN");

                process = new Process();
                process.StartInfo.CreateNoWindow = true;
                List <string> arg = new List <string>();


                if (string.IsNullOrEmpty(optirun))
                {
                    if (UseDedicatedServer)
                    {
                        process.StartInfo.FileName         = paths.DedicatedServer;
                        process.StartInfo.WorkingDirectory = Path.GetDirectoryName(paths.DedicatedServer);
                    }
                    else
                    {
                        process.StartInfo.FileName         = useMultithreaded ? paths.MtExecutable : paths.Executable;
                        process.StartInfo.WorkingDirectory = Path.GetDirectoryName(paths.Executable);
                    }
                }
                else
                {
                    Trace.TraceInformation("Using optirun {0} to start the game (OPTIRUN env var defined)", optirun);
                    process.StartInfo.FileName = optirun;
                    arg.Add(string.Format("\"{0}\"", (useMultithreaded ? paths.MtExecutable : paths.Executable)));
                }



                arg.Add(string.Format("--config \"{0}\"", paths.GetSpringConfigPath()));
                process.StartInfo.EnvironmentVariables["OMP_WAIT_POLICY"] = "ACTIVE";

                if (useSafeMode)
                {
                    arg.Add("--safemode");
                }
                arg.Add(string.Format("\"{0}\"", scriptPath));
                //Trace.TraceInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);

                process.StartInfo.Arguments              = string.Join(" ", arg);
                process.StartInfo.UseShellExecute        = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;
                process.Exited             += springProcess_Exited;
                process.ErrorDataReceived  += process_ErrorDataReceived;
                process.OutputDataReceived += process_OutputDataReceived;
                process.EnableRaisingEvents = true;

                gamePrivateMessages    = new Dictionary <string, int>();
                battleResult.StartTime = DateTime.UtcNow;
                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                if (IsRunning && SpringStarted != null)
                {
                    SpringStarted(this, EventArgs.Empty);
                }

                Utils.StartAsync(() =>
                {
                    Thread.Sleep(1000);
                    try {
                        if (priority != null)
                        {
                            process.PriorityClass = priority.Value;
                        }
                        if (affinity != null)
                        {
                            process.ProcessorAffinity = (IntPtr)affinity.Value;
                        }
                    } catch (Exception ex) {
                        Trace.TraceWarning("Error setting spring process affinity: {0}", ex);
                    }
                });

                return(script);
            }
            else
            {
                Trace.TraceError("Spring already running");
            }
            return(null);
        }
Example #3
0
        private void talker_SpringEvent(object sender, Talker.SpringEventArgs e) {
            //this.client.Say(SayPlace.Battle, "",string.Format("type:{0} param:{1} player:{2}-{3} text:{4}",e.EventType.ToString(), e.Param,e.PlayerNumber, e.PlayerName, e.Text),false);
            try {
                switch (e.EventType) {
                    case Talker.SpringEventType.PLAYER_JOINED:
                        if (StartContext != null) {
                            foreach (var p in StartContext.Players.Where(x => x.Name == e.PlayerName)) {
                                connectedPlayers[p.Name] = true;
                                p.IsIngame = true;
                            }
                        }
                        if (PlayerJoined != null) PlayerJoined(this, new SpringLogEventArgs(e.PlayerName));
                        break;

                    case Talker.SpringEventType.PLAYER_LEFT:
                        if (StartContext != null) {
                            foreach (var p in StartContext.Players.Where(x => x.Name == e.PlayerName)) {
                                connectedPlayers[p.Name] = false;
                                p.IsIngame = false;
                            }
                        }
                        if (e.Param == 0 && PlayerDisconnected != null) PlayerDisconnected(this, new SpringLogEventArgs(e.PlayerName));
                        if (PlayerLeft != null) PlayerLeft(this, new SpringLogEventArgs(e.PlayerName));

                        break;

                    case Talker.SpringEventType.GAME_LUAMSG:
                        HandleSpecialMessages(e);
                        break;

                    case Talker.SpringEventType.PLAYER_CHAT:
                        if (e.Param == 255) HandleSpecialMessages(e);

                        // only public chat
                        if (PlayerSaid != null && (e.Param == Talker.TO_EVERYONE || e.Param == Talker.TO_EVERYONE_LEGACY) && !string.IsNullOrEmpty(e.PlayerName)) PlayerSaid(this, new SpringLogEventArgs(e.PlayerName, e.Text));
                        break;

                    case Talker.SpringEventType.PLAYER_DEFEATED:
                        StatsMarkDead(e.PlayerName, true);
                        if (PlayerLost != null) PlayerLost(this, new SpringLogEventArgs(e.PlayerName));
                        break;

                    case Talker.SpringEventType.SERVER_GAMEOVER:
                        if (StartContext != null) foreach (var p in StartContext.Players) p.IsIngame = false;
                        IsBattleOver = true;

                        if (battleResult.IngameStartTime != null)
                        {
                            gameEndedOk = true;
                            battleResult.Duration = (int)DateTime.UtcNow.Subtract(battleResult.IngameStartTime ?? battleResult.StartTime).TotalSeconds;
                            if (GameOver != null) GameOver(this, new SpringLogEventArgs(e.PlayerName));
                        }  else 
                        {
                            //gameover before gamestart
                            client.Say(SayPlace.Battle, "", "DEBUG: recieved GAMEOVER before STARTPLAYING!", true);
                        }

                        break;

                    case Talker.SpringEventType.PLAYER_READY:
                        if (e.Param == 1) statsPlayers[e.PlayerName].IsIngameReady = true;
                        break;

                    case Talker.SpringEventType.SERVER_STARTPLAYING:
                        battleResult.IngameStartTime = DateTime.UtcNow;
                        foreach (var p in statsPlayers) {
                            p.Value.IsIngameReady = true;
                        }

                        foreach (var p in StartContext.Players) {
                            bool state;
                            if (!connectedPlayers.TryGetValue(p.Name, out state) || !state) p.IsIngame = false;
                        }
                        BattleStarted(this, EventArgs.Empty);
                        break;

                    case Talker.SpringEventType.SERVER_QUIT:
                        if (StartContext != null) foreach (var p in StartContext.Players) p.IsIngame = false;
                        IsBattleOver = true;
                        //Program.main.AutoHost.SayBattle("dbg quit ");
                        //if (GameOver != null) GameOver(this, new SpringLogEventArgs(e.PlayerName));
                        break;
                }
            } catch (Exception ex) {
                Trace.TraceError("Error processing spring message:{0}", ex);
            }
        }
Example #4
0
        private void springProcess_Exited(object sender, EventArgs e) {
            var isCrash = process.ExitCode != 0 && !wasKilled;
            try {
                if (!process.WaitForExit(2000)) process.Kill();
            } catch {}

            process = null;
            talker.Close();
            talker = null;
            Thread.Sleep(1000);
            var logText = LogLines.ToString();
            ParseInfolog(logText, isCrash);

            try {
                File.WriteAllText(Path.Combine(paths.WritableDirectory, string.Format("infolog_{0}.txt", battleResult.EngineBattleID)), logText);
            } catch (Exception ex) {
                Trace.TraceWarning("Error saving infolog: {0}", ex);
            }

            GameExited = DateTime.Now;

            if (StartContext != null) foreach (var p in StartContext.Players) p.IsIngame = false;
            IsBattleOver = true;

            if (SpringExited != null) SpringExited(this, new EventArgs<bool>(isCrash));
        }
Example #5
0
        private void HandleSpecialMessages(Talker.SpringEventArgs e) {
            try {
                if (string.IsNullOrEmpty(e.Text) || !e.Text.StartsWith("SPRINGIE:")) return;

                int count;
                if (!gamePrivateMessages.TryGetValue(e.Text, out count)) count = 0;
                count++;
                gamePrivateMessages[e.Text] = count;
                if (count != 2) return; // only send if count matches 2 exactly

                var text = e.Text.Substring(9);
                if (text.StartsWith("READY:")) {
                    var name = text.Substring(6);
                    BattlePlayerResult entry;
                    if (statsPlayers.TryGetValue(name, out entry)) entry.IsIngameReady = true;
                }
                if (text == "FORCE") ForceStart();

                statsData.Add(text);
            } catch (Exception ex) {
                Trace.TraceError("Error while processing '{0}' :{1}", e.Text, ex);
            }
        }
Example #6
0
        /// <summary>
        /// Starts spring game
        /// </summary>
        /// <param name="client">tasclient to get current battle from</param>
        /// <param name="priority">spring process priority</param>
        /// <param name="affinity">spring process cpu affinity</param>
        /// <param name="scriptOverride">if set, overrides generated script with supplied one</param>
        /// <param name="userName">lobby user name - used to submit score</param>
        /// <param name="passwordHash">lobby password hash - used to submit score</param>
        /// <returns>generates script</returns>
        public string StartGame(TasClient client, ProcessPriorityClass? priority, int? affinity, string scriptOverride, bool useSafeMode = false, bool useMultithreaded=false, BattleContext contextOverride = null, Battle battleOverride = null) {
            if (!File.Exists(paths.Executable) && !File.Exists(paths.DedicatedServer)) throw new ApplicationException(string.Format("Spring or dedicated server executable not found: {0}, {1}", paths.Executable, paths.DedicatedServer));

            this.client = client;
            wasKilled = false;

            if (!IsRunning) {
                gameEndedOk = false;
                IsBattleOver = false;
                lobbyUserName = client.UserName;
                lobbyPassword = client.UserPassword;
                battleResult = new BattleResult();

                talker = new Talker();
                talker.SpringEvent += talker_SpringEvent;
                var battle = battleOverride ?? client.MyBattle;
                isHosting = client != null && battle != null && battle.Founder.Name == client.MyUser.Name;

                if (isHosting) scriptPath = Utils.MakePath(paths.WritableDirectory, "script_" + battle.Founder + ".txt").Replace('\\', '/');
                else scriptPath = Utils.MakePath(paths.WritableDirectory, "script.txt").Replace('\\', '/');

                statsPlayers.Clear();
                statsData.Clear();
                StartContext = null;

                string script;
                if (!string.IsNullOrEmpty(scriptOverride)) {
                    battleResult.IsMission = true;
                    isHosting = false;
                    script = scriptOverride;
                }
                else {
                    List<UserBattleStatus> players;
                    battleGuid = Guid.NewGuid();
                    var service = GlobalConst.GetSpringieService();
                    SpringBattleStartSetup startSetup = null;
                    if (isHosting && GlobalConst.IsZkMod(battle.ModName)) {
                        try {
                            StartContext = contextOverride ?? battle.GetContext();
                            startSetup = service.GetSpringBattleStartSetup(StartContext);
                            if (startSetup.BalanceTeamsResult != null)
                            {
                                StartContext.Players = startSetup.BalanceTeamsResult.Players;
                                StartContext.Bots = startSetup.BalanceTeamsResult.Bots;
                            }
                            connectedPlayers.Clear();
                            foreach (var p in StartContext.Players)
                            {
                                p.IsIngame = true;
                            }
                        } catch (Exception ex) {
                            Trace.TraceError("Error getting start setup: {0}", ex);
                        }
                    }

                    script = battle.GenerateScript(out players, client.MyUser, talker.LoopbackPort, battleGuid.ToString(), startSetup);
                    battleResult.IsMission = battle.IsMission;
                    battleResult.IsBots = battle.Bots.Any();
                    battleResult.Title = battle.Title;
                    battleResult.Mod = battle.ModName;
                    battleResult.Map = battle.MapName;
                    battleResult.EngineVersion = paths.SpringVersion;
                    talker.SetPlayers(players);
                    statsPlayers = players.ToDictionary(x => x.Name,
                                                        x => new BattlePlayerResult
                                                                 {
                                                                     LobbyID = x.LobbyUser.AccountID,
                                                                     AllyNumber = x.AllyNumber,
                                                                     CommanderType = null,
                                                                     // todo commandertype
                                                                     IsSpectator = x.IsSpectator,
                                                                     IsVictoryTeam = false,
                                                                 });
                }
                if (isHosting) timer.Start();

                File.WriteAllText(scriptPath, script);

                LogLines = new StringBuilder();

                var optirun = Environment.GetEnvironmentVariable("OPTIRUN");

                process = new Process();
                process.StartInfo.CreateNoWindow = true;
                List<string> arg = new List<string>();


                if (string.IsNullOrEmpty(optirun))
                {
                    if (UseDedicatedServer)
                    {
                        process.StartInfo.FileName = paths.DedicatedServer;
                        process.StartInfo.WorkingDirectory = Path.GetDirectoryName(paths.DedicatedServer);
                    }
                    else
                    {
                        process.StartInfo.FileName = useMultithreaded ? paths.MtExecutable : paths.Executable;
                        process.StartInfo.WorkingDirectory = Path.GetDirectoryName(paths.Executable);
                    }
                }
                else
                {
                    Trace.TraceInformation("Using optirun {0} to start the game (OPTIRUN env var defined)", optirun);
                    process.StartInfo.FileName = optirun;
                    arg.Add(string.Format("\"{0}\"", (useMultithreaded ? paths.MtExecutable : paths.Executable)));
                }

                

                arg.Add(string.Format("--config \"{0}\"", paths.GetSpringConfigPath()));
                if (useSafeMode) arg.Add("--safemode");
                arg.Add(string.Format("\"{0}\"", scriptPath));
                //Trace.TraceInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);

                process.StartInfo.Arguments = string.Join(" ", arg);
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.Exited += springProcess_Exited;
                process.ErrorDataReceived += process_ErrorDataReceived;
                process.OutputDataReceived += process_OutputDataReceived;
                process.EnableRaisingEvents = true;

                gamePrivateMessages = new Dictionary<string, int>();
                battleResult.StartTime = DateTime.UtcNow;
                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                if (IsRunning && SpringStarted != null) SpringStarted(this, EventArgs.Empty);

                Utils.StartAsync(() =>
                    {
                        Thread.Sleep(1000);
                        try {
                            if (priority != null) process.PriorityClass = priority.Value;
                            if (affinity != null) process.ProcessorAffinity = (IntPtr)affinity.Value;
                        } catch (Exception ex) {
                            Trace.TraceWarning("Error setting spring process affinity: {0}", ex);
                        }
                    });

                return script;
            }
            else Trace.TraceError("Spring already running");
            return null;
        }
        private void HandleSpecialMessages(Talker.SpringEventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(e.Text) || !e.Text.StartsWith("SPRINGIE:")) return;

                int count;
                if (!gamePrivateMessages.TryGetValue(e.Text, out count)) count = 0;
                count++;
                gamePrivateMessages[e.Text] = count;
                if (count != 2) return; // only send if count matches 2 exactly

                var text = e.Text.Substring(9);
                if (text.StartsWith("READY:"))
                {
                    var name = text.Substring(6);
                    var entry = Context.ActualPlayers.FirstOrDefault(x => x.Name == name);
                    if (entry != null) entry.IsIngameReady = true;
                }
                if (text == "FORCE") ForceStart();

                Context.OutputExtras.Add(text);
            }
            catch (Exception ex)
            {
                Trace.TraceError("Error while processing '{0}' :{1}", e.Text, ex);
            }
        }
        private void talker_SpringEvent(object sender, Talker.SpringEventArgs e)
        {
            try
            {
                switch (e.EventType)
                {
                    case Talker.SpringEventType.PLAYER_JOINED:
                        var entry = Context?.GetOrAddPlayer(e.PlayerName);
                        if (entry != null) entry.IsIngame = true;
                        PlayerJoined?.Invoke(this, new SpringLogEventArgs(e.PlayerName));
                        break;

                    case Talker.SpringEventType.PLAYER_LEFT:
                        entry = Context?.GetOrAddPlayer(e.PlayerName);
                        if (entry != null) entry.IsIngame = false;

                        if (e.Param == 0) PlayerDisconnected?.Invoke(this, new SpringLogEventArgs(e.PlayerName));
                        PlayerLeft?.Invoke(this, new SpringLogEventArgs(e.PlayerName));
                        break;

                    case Talker.SpringEventType.GAME_LUAMSG:
                        HandleSpecialMessages(e);
                        break;

                    case Talker.SpringEventType.PLAYER_CHAT:
                        if (e.Param == 255) HandleSpecialMessages(e);
                        else AddToLogs(e);

                        // only public chat
                        if ((PlayerSaid != null) && ((e.Param == Talker.TO_EVERYONE) || (e.Param == Talker.TO_EVERYONE_LEGACY)) &&
                            !string.IsNullOrEmpty(e.PlayerName)) PlayerSaid(this, new SpringLogEventArgs(e.PlayerName, e.Text));
                        break;

                    case Talker.SpringEventType.PLAYER_DEFEATED:
                        MarkPlayerDead(e.PlayerName, true);
                        if (PlayerLost != null) PlayerLost(this, new SpringLogEventArgs(e.PlayerName));
                        break;

                    case Talker.SpringEventType.SERVER_GAMEOVER:
                        if (!Context.GameEndedOk) // server gameover runs multiple times
                        {
                            foreach (var p in Context.ActualPlayers)
                            {
                                if (!p.IsIngame && !p.IsSpectator) MarkPlayerDead(p.Name, true);
                                p.IsIngame = false;
                            }

                            // set victory team for all allied with currently alive
                            foreach (var p in Context.ActualPlayers.Where(x => !x.IsSpectator && (x.LoseTime == null))) foreach (var q in Context.ActualPlayers.Where(x => !x.IsSpectator && (x.AllyNumber == p.AllyNumber))) q.IsVictoryTeam = true;

                            if (Context.IngameStartTime != null)
                            {
                                Context.GameEndedOk = true;
                                Context.Duration = (int)DateTime.UtcNow.Subtract(Context.IngameStartTime ?? Context.StartTime).TotalSeconds;

                                GameOver?.Invoke(this, new SpringLogEventArgs(e.PlayerName));
                            }
                            else Trace.TraceWarning("recieved GAMEOVER before STARTPLAYING!");

                            Task.Delay(10000).ContinueWith(x => ExitGame());
                        }
                        break;

                    case Talker.SpringEventType.PLAYER_READY:
                        if (e.Param == 1)
                        {
                            entry = Context.GetOrAddPlayer(e.PlayerName);
                            if (entry != null) entry.IsIngameReady = true;
                        }
                        break;

                    case Talker.SpringEventType.SERVER_STARTPLAYING:
                        Context.ReplayName = e.ReplayFileName;
                        Context.EngineBattleID = e.GameID;
                        Context.IngameStartTime = DateTime.UtcNow;
                        foreach (var p in Context.ActualPlayers.Where(x => !x.IsSpectator)) p.IsIngameReady = true;

                        BattleStarted(this, EventArgs.Empty);
                        break;

                    case Talker.SpringEventType.SERVER_QUIT:
                        if (LobbyStartContext != null) foreach (var p in Context.ActualPlayers) p.IsIngame = false;
                        //if (GameOver != null) GameOver(this, new SpringLogEventArgs(e.PlayerName));
                        break;
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError("Error processing spring message:{0}", ex);
            }
        }
        private void dedicatedProcess_Exited(object sender, EventArgs e)
        {
            Context.IsCrash = (process.ExitCode != 0) && !Context.WasKilled;
            process.UnsubscribeEvents(this);
            try
            {
                if (!process.WaitForExit(2000)) process.Kill();
            }
            catch { }

            process = null;
            talker.UnsubscribeEvents(this);
            talker?.Close();
            talker = null;
            Thread.Sleep(1000);

            if (LobbyStartContext != null) foreach (var p in Context.ActualPlayers) p.IsIngame = false;

            if (File.Exists(scriptPath))
            {
                try
                {
                    File.Delete(scriptPath);
                } catch { }
            }

            DedicatedServerExited?.Invoke(this, Context);
            AnyDedicatedExited?.Invoke(this, Context);
        }
        private void AddToLogs(Talker.SpringEventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(e.Text) || string.IsNullOrEmpty(e.PlayerName)) return;

                var s = "CHATLOG:" + e.PlayerName + " ";
                switch (e.Param)
                {
                    case Talker.TO_EVERYONE:
                        s = s + "<PUBLIC> ";
                        break;
                    case Talker.TO_ALLIES:
                        s = s + "<ALLY> ";
                        break;
                    case Talker.TO_SPECTATORS:
                        s = s + "<SPEC> ";
                        break;
                    default:
                        s = s + "<PRIV> ";
                        break;
                }
                s = s + e.Text;
                Context.OutputExtras.Add(s);
            }
            catch (Exception ex)
            {
                Trace.TraceError("Error while processing '{0}' :{1}", e.Text, ex);
            }
        }
        public event EventHandler<SpringLogEventArgs> GameOver; // game has ended


        public string HostGame(LobbyHostingContext startContext, string host, int port)
        {
            if (!File.Exists(paths.GetDedicatedServerPath(startContext.EngineVersion))) throw new ApplicationException($"Dedicated server executable not found: {paths.GetDedicatedServerPath(startContext.EngineVersion)}");

            Context = new SpringBattleContext();
            Context.SetForHosting(startContext, host, port, null, null);

            if (!IsRunning)
            {
                talker = new Talker();
                talker.SpringEvent += talker_SpringEvent;
                Context.IsHosting = true;

                scriptPath = Utils.MakePath(paths.WritableDirectory, "script_" + startContext.FounderName + ".txt").Replace('\\', '/');

                var script = ScriptGenerator.GenerateHostScript(Context, talker.LoopbackPort);
                timer.Start();

                StartDedicated(script);
                return script;
            }
            else Trace.TraceError("Dedicated server already running");
            return null;
        }
Example #12
0
        public string HostGame(BattleContext context, string host, int port, string myName = null, string myPassword = null )
        {
            if (!File.Exists(paths.Executable) && !File.Exists(paths.DedicatedServer)) throw new ApplicationException(string.Format("Spring or dedicated server executable not found: {0}, {1}", paths.Executable, paths.DedicatedServer));

            wasKilled = false;
            string script = null;

            if (!IsRunning)
            {
                gameEndedOk = false;
                IsBattleOver = false;
                //lobbyUserName = client.UserName;
                //lobbyPassword = client.UserPassword;
                battleResult = new BattleResult();

                talker = new Talker();
                talker.SpringEvent += talker_SpringEvent;
                isHosting = true;

                if (isHosting) scriptPath = Utils.MakePath(paths.WritableDirectory, "script_" + myName + ".txt").Replace('\\', '/');
                else scriptPath = Utils.MakePath(paths.WritableDirectory, "script.txt").Replace('\\', '/');

                statsPlayers.Clear();
                statsData.Clear();

                battleGuid = Guid.NewGuid();
                var service = GlobalConst.GetSpringieService();
                SpringBattleStartSetup startSetup = null;
                if (isHosting && GlobalConst.IsZkMod(context.Mod))
                {
                    try
                    {
                        StartContext = context;
                        startSetup = service.GetSpringBattleStartSetup(StartContext);
                        if (startSetup.BalanceTeamsResult != null)
                        {
                            StartContext.Players = startSetup.BalanceTeamsResult.Players;
                            StartContext.Bots = startSetup.BalanceTeamsResult.Bots;
                        }
                        connectedPlayers.Clear();
                        foreach (var p in StartContext.Players)
                        {
                            p.IsIngame = true;
                        }
                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError("Error getting start setup: {0}", ex);
                    }

                    script = ScriptGenerator.GenerateHostScript(StartContext, startSetup, talker.LoopbackPort, battleGuid.ToString(), host,port, myName, myPassword);

                    statsPlayers = StartContext.Players.ToDictionary(x => x.Name,
                                                        x => new BattlePlayerResult
                                                                 {
                                                                     LobbyID = x.LobbyID,
                                                                     AllyNumber = x.AllyID,
                                                                     CommanderType = null,
                                                                     // todo commandertype
                                                                     IsSpectator = x.IsSpectator,
                                                                     IsVictoryTeam = false,
                                                                 });
                }
                if (isHosting) timer.Start();

                StartSpring(script);
                return script;
            }
            else Trace.TraceError("Spring already running");
            return null;
        }
        private void springProcess_Exited(object sender, EventArgs e)
        {
            Context.IsCrash = process.ExitCode != 0 && !Context.WasKilled;
            process.UnsubscribeEvents(this);
            try
            {
                if (!process.WaitForExit(2000)) process.Kill();
            }
            catch {}

            process = null;
            talker.UnsubscribeEvents(this);
            talker?.Close();
            talker = null;
            Thread.Sleep(1000);
            var logText = Context.LogLines.ToString();

            if (!string.IsNullOrEmpty(Context.InfoLogFileName))
            {
                try
                {
                    logText = File.ReadAllText(Context.InfoLogFileName);
                    File.Delete(Context.InfoLogFileName);
                }
                catch (Exception ex)
                {
                    Trace.TraceWarning("Error reading infolog: {0}",ex.Message);
                }
            }

            if (Context.IsHosting) ParseInfolog(logText);

            try
            {
                File.WriteAllText(Path.Combine(paths.WritableDirectory, $"infolog_{Context.EngineBattleID}.txt"), logText);
            }
            catch (Exception ex)
            {
                Trace.TraceWarning("Error saving infolog: {0}", ex);
            }

            GameExited = DateTime.Now;

            if (LobbyStartContext != null) foreach (var p in Context.ActualPlayers) p.IsIngame = false;

            SpringExited?.Invoke(this, Context);
            AnySpringExited?.Invoke(this, Context);
        }