Example #1
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;
        }
Example #2
0
 public string ConnectGame(string ip, int port, string myName, string myPassword = null)
 {
     battleResult = new BattleResult();
     lobbyUserName = myName;
     lobbyPassword = myPassword;
     isHosting = false;
     var script=  ScriptGenerator.GenerateConnectScript(ip, port, myName, myPassword);
     StartSpring(script);
     return script;
 }
Example #3
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;
        }
        public static string SubmitSpringBattleResult(BattleContext context,
                                                      string password,
                                                      BattleResult result,
                                                      List<BattlePlayerResult> players,
                                                      List<string> extraData)
        {
            try
            {
                Account acc = AuthServiceClient.VerifyAccountPlain(context.AutohostName, password);
                if (acc == null) throw new Exception("Account name or password not valid");
                AutohostMode mode = context.GetMode();
                var db = new ZkDataContext();

                if (extraData == null) extraData = new List<string>();


                var sb = new SpringBattle
                         {
                             HostAccountID = acc.AccountID,
                             Duration = result.Duration,
                             EngineGameID = result.EngineBattleID,
                             MapResourceID = db.Resources.Single(x => x.InternalName == result.Map).ResourceID,
                             ModResourceID = db.Resources.Single(x => x.InternalName == result.Mod).ResourceID,
                             HasBots = result.IsBots,
                             IsMission = result.IsMission,
                             PlayerCount = players.Count(x => !x.IsSpectator),
                             StartTime = result.StartTime,
                             Title = result.Title,
                             ReplayFileName = result.ReplayName,
                             EngineVersion = result.EngineVersion,
                         };
                db.SpringBattles.InsertOnSubmit(sb);

                foreach (BattlePlayerResult p in players)
                {
                    sb.SpringBattlePlayers.Add(new SpringBattlePlayer
                                               {
                                                   AccountID = db.Accounts.First(x => x.AccountID == p.LobbyID).AccountID,
                                                   AllyNumber = p.AllyNumber,
                                                   CommanderType = p.CommanderType,
                                                   IsInVictoryTeam = p.IsVictoryTeam,
                                                   IsSpectator = p.IsSpectator,
                                                   LoseTime = p.LoseTime
                                               });
                }

                db.SubmitChanges();

                // awards
                foreach (string line in extraData.Where(x => x.StartsWith("award")))
                {
                    string[] partsSpace = line.Substring(6).Split(new[] { ' ' }, 3);
                    string name = partsSpace[0];
                    string awardType = partsSpace[1];
                    string awardText = partsSpace[2];

                    SpringBattlePlayer player = sb.SpringBattlePlayers.FirstOrDefault(x => x.Account.Name == name);
                    if (player != null)
                    {
                        db.AccountBattleAwards.InsertOnSubmit(new AccountBattleAward
                                                              {
                                                                  AccountID = player.AccountID,
                                                                  SpringBattleID = sb.SpringBattleID,
                                                                  AwardKey = awardType,
                                                                  AwardDescription = awardText
                                                              });
                    }
                }

                var text = new StringBuilder();
                bool isPlanetwars = false;
                if (mode == AutohostMode.Planetwars && sb.SpringBattlePlayers.Count(x => !x.IsSpectator) >= 2 && sb.Duration >= GlobalConst.MinDurationForPlanetwars)
                {
                    // test that factions are not intermingled (each faction only has one ally number) - if they are it wasnt actually PW balanced
                    if (
                        sb.SpringBattlePlayers.Where(x => !x.IsSpectator && x.Account.Faction != null)
                          .GroupBy(x => x.Account.Faction)
                          .All(grp => grp.Select(x => x.AllyNumber).Distinct().Count() < 2))
                    {
                        isPlanetwars = true;

                        
                        List<int> winnerTeams =
    sb.SpringBattlePlayers.Where(x => x.IsInVictoryTeam && !x.IsSpectator).Select(x => x.AllyNumber).Distinct().ToList();
                        int? winNum = null;
                        if (winnerTeams.Count == 1)
                        {
                            winNum = winnerTeams[0];
                            if (winNum > 1)
                            {
                                winNum = null;
                                text.AppendLine("ERROR: Invalid winner");
                            } 
                        }

                        PlanetWarsTurnHandler.EndTurn(result.Map, extraData, db, winNum, sb.SpringBattlePlayers.Where(x => !x.IsSpectator).Select(x => x.Account).ToList(), text, sb, sb.SpringBattlePlayers.Where(x => !x.IsSpectator && x.AllyNumber == 0).Select(x => x.Account).ToList());

                        Global.PlanetWarsMatchMaker.RemoveFromRunningBattles(context.AutohostName);
                    }
                    else
                    {
                        text.AppendLine("Battle wasn't PlanetWars balanced, it counts as a normal team game only");
                    }

                }

                bool noElo = (extraData.FirstOrDefault(x => x.StartsWith("noElo", true, System.Globalization.CultureInfo.CurrentCulture)) != null);
                try
                {
                    db.SubmitChanges();
                }
                catch (System.Data.Linq.DuplicateKeyException ex)
                {
                    Trace.TraceError(ex.ToString());
                }

                Dictionary<int, int> orgLevels = sb.SpringBattlePlayers.Select(x => x.Account).ToDictionary(x => x.AccountID, x => x.Level);

                sb.CalculateAllElo(noElo, isPlanetwars);
                foreach (var u in sb.SpringBattlePlayers.Where(x => !x.IsSpectator)) u.Account.CheckLevelUp();
                
                db.SubmitAndMergeChanges();

                try
                {
                    foreach (Account a in sb.SpringBattlePlayers.Where(x => !x.IsSpectator).Select(x => x.Account)) Global.Server.PublishAccountUpdate(a);
                }
                catch (Exception ex)
                {
                    Trace.TraceError("error updating extension data: {0}", ex);
                }

                foreach (Account account in sb.SpringBattlePlayers.Select(x => x.Account))
                {
                    if (account.Level > orgLevels[account.AccountID])
                    {
                        try
                        {
                            string message =
                                string.Format("Congratulations {0}! You just leveled up to level {1}. {3}/Users/Detail/{2}",
                                              account.Name,
                                              account.Level,
                                              account.AccountID,
                                              GlobalConst.BaseSiteUrl);
                            //text.AppendLine(message);
                            Global.Server.GhostPm(account.Name, message);
                        }
                        catch (Exception ex)
                        {
                            Trace.TraceError("Error sending level up lobby message: {0}", ex);
                        }
                    }
                }

                text.AppendLine(string.Format("BATTLE DETAILS AND REPLAY ----> {1}/Battles/Detail/{0} <-----", sb.SpringBattleID, GlobalConst.BaseSiteUrl));

                /*
                // create debriefing room, join players there and output message
                string channelName = "B" + sb.SpringBattleID;
                var joinplayers = new List<string>();
                joinplayers.AddRange(context.Players.Select(x => x.Name)); // add those who were there at start
                joinplayers.AddRange(sb.SpringBattlePlayers.Select(x => x.Account.Name)); // add those who played
                Battle bat = Global.Server.Battles.Values.FirstOrDefault(x => x.Founder.Name == context.AutohostName); // add those in lobby atm


                var conf = context.GetConfig();
                if (bat != null && (conf == null || conf.MinToJuggle == null)) // if not qm room do not join those who are in battle
                {
                    List<string> inbatPlayers = bat.Users.Keys.ToList();
                    joinplayers.RemoveAll(x => inbatPlayers.Contains(x));
                }
                foreach (string jp in joinplayers.Distinct().Where(x => x != context.AutohostName)) tas.ForceJoinChannel(jp, channelName);
                tas.JoinChannel(channelName); // join nightwatch and say it
                tas.Say(SayPlace.Channel, channelName, text.ToString(), true);
                tas.LeaveChannel(channelName);*/

                //text.Append(string.Format("Debriefing in #{0} - zk://chat/channel/{0}  ", channelName));
                return text.ToString();
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                return ex.ToString();
            }
        }