コード例 #1
0
        void tas_MyBattleMapChanged(object sender, BattleInfoEventArgs e1)
        {
            lastMapChange = DateTime.Now;

            Battle b       = tas.MyBattle;
            string mapName = b.MapName.ToLower();

            if (SpawnConfig == null)
            {
                ComResetOptions(TasSayEventArgs.Default, new string[] { });
            }

            try {
                var    serv     = new SpringieService();
                string commands = serv.GetMapCommands(mapName);
                if (!string.IsNullOrEmpty(commands))
                {
                    foreach (string c in commands.Split('\n').Where(x => !string.IsNullOrEmpty(x)))
                    {
                        RunCommand(c);
                    }
                }
            } catch (Exception ex) {
                Trace.TraceError("Error procesing map commands: {0}", ex);
            }
        }
コード例 #2
0
 protected override void SuccessAction()
 {
     try {
         bool val;
         var  moves =
             tas.MyBattle.Users.Where(x => x.Name != tas.MyBattle.Founder.Name)
             .Where(x => !userVotes.TryGetValue(x.Name, out val) || val)
             .Select(x => new MovePlayerEntry()
         {
             BattleHost = host, PlayerName = x.Name
         })
             .ToArray();    // move all that didnt vote "no"
         var serv = new SpringieService();
         serv.MovePlayers(tas.UserName, tas.UserPassword, moves.ToArray());
     } catch (Exception ex) {
         ah.SayBattle(ex.ToString());
     }
 }
コード例 #3
0
        public void UpdateAll()
        {
            try
            {
                using (var serv = new SpringieService())
                {
                    serv.Timeout = 5000;
                    var configs = serv.GetClusterConfigs(Config.ClusterNode);

                    lock (autoHosts)
                    {
                        foreach (var conf in configs)
                        {
                            if (!autoHosts.Any(x => x.config.Login == conf.Login))
                            {
                                SpawnAutoHost(conf, null);
                            }
                            else
                            {
                                foreach (var ah in autoHosts.Where(x => x.config.Login == conf.Login && x.SpawnConfig == null))
                                {
                                    ah.config = conf;
                                }
                            }
                        }
                        var todel = autoHosts.Where(x => !configs.Any(y => y.Login == x.config.Login)).ToList();
                        foreach (var ah in todel)
                        {
                            StopAutohost(ah);
                        }
                    }
                }
            }
            catch (Exception ex) {
                Trace.TraceError("Error in periodic updates: {0}", ex);
            }
        }
コード例 #4
0
        public override void End()
        {
            bool val;

            try {
                var moves =
                    tas.MyBattle.Users.Where(x => x.Name != tas.MyBattle.Founder.Name)
                    .Where(x => userVotes.TryGetValue(x.Name, out val) && val)
                    .Select(x => new MovePlayerEntry()
                {
                    BattleHost = host, PlayerName = x.Name
                })
                    .ToArray();    // move those that voted yes if there are at least 2
                if (moves.Length > 1)
                {
                    var serv = new SpringieService();
                    serv.MovePlayers(tas.UserName, tas.UserPassword, moves.ToArray());
                }
            } catch (Exception ex) {
                ah.SayBattle(ex.ToString());
            }

            base.End();
        }
コード例 #5
0
        private void ParseInfolog(string text, bool isCrash)
        {
            if (string.IsNullOrEmpty(text))
            {
                Trace.TraceWarning("Infolog is empty");
                return;
            }
            try {
                var    hasError     = false;
                var    modName      = battleResult.Mod;
                var    mapName      = battleResult.Map;
                var    isCheating   = false;
                int?   score        = null;
                int    scoreFrame   = 0;
                string gameId       = null;
                string demoFileName = null;
                string missionVars  = "";

                foreach (var cycleline in text.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    var line      = cycleline;
                    var gameframe = 0;
                    if (line.StartsWith("[DedicatedServer]"))
                    {
                        line = line.Replace("[DedicatedServer] ", "");
                    }

                    if (line.StartsWith("["))
                    {
                        var idx = line.IndexOf("] ");
                        if (idx > 0)
                        {
                            int.TryParse(line.Substring(1, idx - 1), out gameframe);
                            if (idx >= 0)
                            {
                                line = line.Substring(idx + 2);
                            }
                        }
                    }

                    // FIXME: why are these even null in the first place?
                    if (mapName == null && line.StartsWith("Using map"))
                    {
                        mapName = line.Substring(10).Trim();
                    }

                    if (modName == null && line.StartsWith("Using game"))
                    {
                        modName = line.Substring(11).Trim();
                    }

                    if (line.StartsWith("recording demo"))
                    {
                        demoFileName = Path.GetFileName(line.Substring(15).Trim());                                     // 91.0
                    }
                    else if (line.StartsWith("[DedicatedServer] recording demo"))
                    {
                        demoFileName = Path.GetFileName(line.Substring(33).Trim());                                                              // 95.0 and later
                    }
                    if (line.StartsWith("Using demofile"))
                    {
                        return;                                    // do nothing if its demo
                    }
                    if (line.StartsWith("GameID: ") && gameId == null)
                    {
                        gameId = line.Substring(8).Trim();
                    }

                    if (line.StartsWith("STATS:"))
                    {
                        statsData.Add(line.Substring(6));
                    }

                    if (line.Contains("SCORE: ") && !isCheating && battleResult.IsMission)
                    {
                        var match = Regex.Match(line, "SCORE: ([^ ]+)");
                        if (match.Success)
                        {
                            // game score
                            var data = match.Groups[1].Value;
                            //Trace.TraceInformation("Score data (raw) : " + data);
                            data = Encoding.ASCII.GetString(Convert.FromBase64String(match.Groups[1].Value));
                            //Trace.TraceInformation("Score data (decoded) : " + data);
                            var parts = data.Split('/');
                            score = 0;
                            if (parts.Length > 1)
                            {
                                score     = Convert.ToInt32(parts[1]);
                                gameframe = Convert.ToInt32(parts[0]);
                            }
                            else
                            {
                                score = Convert.ToInt32(data);
                            }

                            scoreFrame = gameframe;
                        }
                    }
                    if (line.Contains("MISSIONVARS:") && battleResult.IsMission)
                    {
                        var match = Regex.Match(line, "MISSIONVARS: ([^ ]+)");
                        missionVars = match.Groups[1].Value.Trim();
                        Trace.TraceInformation(string.Format("Mission variables: {0} (original line: {1})", missionVars, line));
                    }

                    // obsolete, hanlded by pm messages
                    //if (line.StartsWith("STATS:")) statsData.Add(line.Substring(6));

                    if (line.StartsWith("Cheating!") || line.StartsWith("Cheating is enabled!"))
                    {
                        isCheating = true;
                    }

                    if (line.StartsWith("Error") || line.StartsWith("LuaRules") || line.StartsWith("Internal error") || line.StartsWith("LuaCOB") ||
                        (line.StartsWith("Failed to load") && !line.Contains("duplicate name")))
                    {
                        hasError = true;
                    }
                }
                if (score != null || !String.IsNullOrEmpty(missionVars))
                {
                    Trace.TraceInformation("Submitting score for mission " + modName);
                    try {
                        using (var service = new ContentService {
                            Proxy = null
                        }) {
                            service.SubmitMissionScoreCompleted += (s, e) =>
                            {
                                if (e.Error != null)
                                {
                                    if (e.Error is WebException)
                                    {
                                        Trace.TraceWarning("Error sending score: {0}", e.Error);
                                    }
                                    else
                                    {
                                        Trace.TraceError("Error sending score: {0}", e.Error);
                                    }
                                }
                            };
                            service.SubmitMissionScoreAsync(lobbyUserName, Utils.HashLobbyPassword(lobbyPassword), modName, score ?? 0, scoreFrame / 30, missionVars);
                        }
                    } catch (Exception ex) {
                        Trace.TraceError(string.Format("Error sending mission score: {0}", ex));
                    }
                }

                var modOk = GlobalConst.IsZkMod(modName);

                // submit main stats
                if (!isCheating && !isCrash && modOk && gameEndedOk)
                {
                    if (isHosting)
                    {
                        var service = new SpringieService()
                        {
                            Proxy = null
                        };
                        var mis = new ContentService()
                        {
                            Proxy = null
                        };
                        try {
                            battleResult.EngineBattleID = gameId;
                            battleResult.ReplayName     = demoFileName;

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

                            if (StartContext != null)
                            {
                                var result = service.SubmitSpringBattleResult(StartContext, lobbyPassword, battleResult, Enumerable.ToArray(statsPlayers.Values), statsData.ToArray());
                                if (result != null)
                                {
                                    foreach (var line in result.Split('\n'))
                                    {
                                        client.Say(TasClient.SayPlace.Battle, "", line, true);
                                    }
                                }
                            }
                        } catch (Exception ex) {
                            Trace.TraceError("Error sending game result: {0}", ex);
                        }
                    }

                    if (statsData.Count > 1)
                    {
                        // must be more than 1 line - 1 is player list
                        var statsService = new StatsCollector {
                            Proxy = null
                        };
                        try {
                            statsService.SubmitGameEx(gameId, modName, mapName, statsData.ToArray());
                        } catch (Exception ex) {
                            Trace.TraceError("Error sending game stats: {0}", ex);
                        }
                    }
                }
            } catch (Exception ex) {
                Trace.TraceError("Error processing spring log: {0}", ex);
            }
        }
コード例 #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)
        {
            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);
        }
コード例 #7
0
        void tas_BattleUserJoined(object sender, BattleUserEventArgs e1)
        {
            if (e1.BattleID != tas.MyBattleID)
            {
                return;
            }
            string name = e1.UserName;

            if (tas.ExistingUsers[name].BanLobby)
            {
                tas.Kick(name);
                return;
            }

            string welc = config.Welcome;

            if (welc != "")
            {
                welc = welc.Replace("%1", name);
                welc = welc.Replace("%2", GetUserLevel(name).ToString());
                welc = welc.Replace("%3", MainConfig.SpringieVersion);
                SayBattlePrivate(name, welc);
            }
            if (spring.IsRunning)
            {
                spring.AddUser(e1.UserName, e1.ScriptPassword);
                TimeSpan started = DateTime.Now.Subtract(spring.GameStarted);
                started = new TimeSpan((int)started.TotalHours, started.Minutes, started.Seconds);
                SayBattlePrivate(name, String.Format("GAME IS CURRENTLY IN PROGRESS, PLEASE WAIT TILL IT ENDS! Running for {0}", started));
                SayBattlePrivate(name, "If you say !notify, I will PM you when game ends.");
            }

            if (SpawnConfig == null)
            {
                try {
                    var serv             = new SpringieService();
                    PlayerJoinResult ret = serv.AutohostPlayerJoined(tas.MyBattle.GetContext(), tas.ExistingUsers[name].LobbyID);
                    if (ret != null)
                    {
                        if (!string.IsNullOrEmpty(ret.PrivateMessage))
                        {
                            tas.Say(TasClient.SayPlace.User, name, ret.PrivateMessage, false);
                        }
                        if (!string.IsNullOrEmpty(ret.PublicMessage))
                        {
                            tas.Say(TasClient.SayPlace.Battle, "", ret.PublicMessage, true);
                        }
                        if (ret.ForceSpec)
                        {
                            tas.ForceSpectator(name);
                        }
                        if (ret.Kick)
                        {
                            tas.Kick(name);
                        }
                    }
                } catch (Exception ex) {
                    SayBattle("ServerManage error: " + ex, false);
                }
            }

            if (SpawnConfig != null && SpawnConfig.Owner == name) // owner joins, set him boss
            {
                ComBoss(TasSayEventArgs.Default, new[] { name });
            }
        }