/// <summary>
        /// Generates script for hosting a game
        /// </summary>
        public static string GenerateHostScript(BattleContext startContext, SpringBattleStartSetup startSetup, int loopbackListenPort,
                                                string zkSearchTag, string host, int port, string myname = null, string mypassword = null)
        {
            var previousCulture = Thread.CurrentThread.CurrentCulture;
            try {
                Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

                var script = new StringBuilder();

                script.AppendLine("[GAME]");
                script.AppendLine("{");

                script.AppendFormat("  ZkSearchTag={0};\n", zkSearchTag);
                script.AppendFormat("  Mapname={0};\n", startContext.Map);

                script.AppendFormat("  StartPosType={0};\n", startContext.IsMission ? 3 : 2);

                script.AppendFormat("  GameType={0};\n", startContext.Mod);
                script.AppendFormat("  ModHash=1;\n");
                script.AppendFormat("  MapHash=1;\n");

                script.AppendFormat("  AutohostPort={0};\n", loopbackListenPort);
                script.AppendLine();
                script.AppendFormat("  HostIP={0};\n", host);
                script.AppendFormat("  HostPort={0};\n", port);
                //script.AppendFormat("  SourcePort={0};\n", 8300);
                script.AppendFormat("  IsHost=1;\n");
                script.AppendLine();

                if (!string.IsNullOrEmpty(myname)) script.AppendFormat("  MyPlayerName={0};\n", myname);
                if (!string.IsNullOrEmpty(mypassword) || !string.IsNullOrEmpty(myname)) script.AppendFormat("  MyPasswd={0};\n", mypassword??myname);

                GeneratePlayerSection(script, startContext, startSetup);

                return script.ToString();
            } finally {
                Thread.CurrentThread.CurrentCulture = previousCulture;
            }
        }
예제 #2
0
        public static void ScriptAddUser(StringBuilder script, int userNum, List<UserBattleStatus> playersExport, SpringBattleStartSetup startSetup, int teamNum, UserBattleStatus status)
        {
            var export = status.Clone();
            export.TeamNumber = teamNum;
            playersExport.Add(status);

            // PLAYERS
            script.AppendFormat("  [PLAYER{0}]\n", userNum);
            script.AppendLine("  {");
            script.AppendFormat("     Name={0};\n", status.Name);

            script.AppendFormat("     Spectator={0};\n", status.IsSpectator ? 1 : 0);
            if (!status.IsSpectator) script.AppendFormat("     Team={0};\n", teamNum);

            if (status.LobbyUser != null)
            {
                script.AppendFormat("     Rank={0};\n", status.LobbyUser.Rank);
                script.AppendFormat("     CountryCode={0};\n", status.LobbyUser.Country);
                script.AppendFormat("     LobbyID={0};\n", status.LobbyUser.LobbyID);
                script.AppendFormat("     LobbyRank={0};\n", status.LobbyUser.Rank);
            }
            if (status.ScriptPassword != null) script.AppendFormat("     Password={0};\n", status.ScriptPassword);

            if (startSetup != null)
            {
                var entry = startSetup.UserParameters.FirstOrDefault(x => x.LobbyID == status.LobbyUser.LobbyID);
                if (entry != null) foreach (var kvp in entry.Parameters) script.AppendFormat("     {0}={1};\n", kvp.Key, kvp.Value);
            }
            script.AppendLine("  }");
        }
예제 #3
0
        void GeneratePlayerSection(List<UserBattleStatus> playersExport,
            User localUser,
            SpringBattleStartSetup startSetup,
            List<UserBattleStatus> users,
            StringBuilder script,
            List<StartPos> positions,
            List<BotBattleStatus> bots)
        {
            if (mod != null && mod.IsMission) // mission stuff
            {
                var aiNum = 0;
                var declaredTeams = new HashSet<int>();
                var orderedUsers = users.OrderBy(x => x.TeamNumber).ToList();
                for (var i = 0; i < orderedUsers.Count; i++)
                {
                    var u = orderedUsers[i];
                    ScriptAddUser(script, i, playersExport, startSetup, u.TeamNumber, u);
                    if (!u.IsSpectator && !declaredTeams.Contains(u.TeamNumber))
                    {
                        ScriptAddTeam(script, u.TeamNumber, positions, i, u,mod,Details);
                        declaredTeams.Add(u.TeamNumber);
                    }
                }

                for (var i = 0; i < orderedUsers.Count; i++)
                {
                    var u = orderedUsers[i];
                    foreach (var b in bots.Where(x => x.owner == u.Name))
                    {
                        ScriptAddBot(script, aiNum++, b.TeamNumber, i, b);
                        if (!declaredTeams.Contains(b.TeamNumber))
                        {
                            ScriptAddTeam(script, b.TeamNumber, positions, i, b,mod,Details);
                            declaredTeams.Add(b.TeamNumber);
                        }
                    }
                }
            }
            else
            {
                // ordinary battle stuff

                var userNum = 0;
                var teamNum = 0;
                var aiNum = 0;
                //players is excluding self (so "springie doesn't appear as spec ingame") & excluding bots (bots is added later for each owner)
                foreach (var u in users.Where(u => !bots.Any(b => b.Name == u.Name)).OrderBy(x => x.TeamNumber).Where(x => x.Name != localUser.Name)) 
                {
                    ScriptAddUser(script, userNum, playersExport, startSetup, teamNum, u);

                    if (!u.IsSpectator)
                    {
                        ScriptAddTeam(script, teamNum, positions, userNum, u,mod,Details);
                        teamNum++;
                    }

                    foreach (var b in bots.Where(x => x.owner == u.Name))
                    {
                        ScriptAddBot(script, aiNum, teamNum, userNum, b);
                        aiNum++;
                        ScriptAddTeam(script, teamNum, positions, userNum, b,mod,Details);
                        teamNum++;
                    }
                    userNum++;
                }
            }

            // ALLIANCES
            script.AppendLine();
            foreach (var allyNumber in
                users.Where(x => !x.IsSpectator).Select(x => x.AllyNumber).Union(bots.Select(x => x.AllyNumber)).Union(Rectangles.Keys).Distinct())
            {
                // get allies from each player, bot and rectangles (for koth)
                script.AppendFormat("[ALLYTEAM{0}]\n", allyNumber);
                script.AppendLine("{");
                script.AppendFormat("     NumAllies={0};\n", 0);
                double left = 0, top = 0, right = 1, bottom = 1;
                BattleRect rect;
                if (Rectangles.TryGetValue(allyNumber, out rect)) rect.ToFractions(out left, out top, out right, out bottom);
                script.AppendFormat(CultureInfo.InvariantCulture,"     StartRectLeft={0};\n", left);
                script.AppendFormat(CultureInfo.InvariantCulture,"     StartRectTop={0};\n", top);
                script.AppendFormat(CultureInfo.InvariantCulture,"     StartRectRight={0};\n", right);
                script.AppendFormat(CultureInfo.InvariantCulture,"     StartRectBottom={0};\n", bottom);
                script.AppendLine("}");
            }

            script.AppendLine();
            script.AppendFormat("  NumRestrictions={0};\n", DisabledUnits.Count);
            script.AppendLine();

            if (!mod.IsMission)
            {
                script.AppendLine("  [RESTRICT]");
                script.AppendLine("  {");
                for (var i = 0; i < DisabledUnits.Count; ++i)
                {
                    script.AppendFormat("    Unit{0}={1};\n", i, DisabledUnits[i]);
                    script.AppendFormat("    Limit{0}=0;\n", i);
                }
                script.AppendLine("  }");

                script.AppendLine("  [MODOPTIONS]");
                script.AppendLine("  {");

                var options = new Dictionary<string, string>();

                // put standard modoptions to options dictionary
                foreach (var o in mod.Options.Where(x => x.Type != OptionType.Section))
                {
                    var v = o.Default;
                    if (ModOptions.ContainsKey(o.Key)) v = ModOptions[o.Key];
                    options[o.Key] = v;
                }

                // replace/add custom modoptions from startsetup (if they exist)
                if (startSetup != null && startSetup.ModOptions != null) foreach (var entry in startSetup.ModOptions) options[entry.Key] = entry.Value;

                // write final options to script
                foreach (var kvp in options) script.AppendFormat("    {0}={1};\n", kvp.Key, kvp.Value);

                script.AppendLine("  }");
            }

            script.AppendLine("}");
        }
예제 #4
0
        /// <summary>
        /// Generates script
        /// </summary>
        /// <param name="playersExport">list of players</param>
        /// <param name="localUser">myself</param>
        /// <param name="loopbackListenPort">listen port for autohost interface</param>
        /// <param name="zkSearchTag">hackish search tag</param>
        /// <param name="startSetup">structure with custom extra data</param>
        /// <returns></returns>
        public string GenerateScript(out List<UserBattleStatus> playersExport,
                                     User localUser,
                                     int loopbackListenPort,
                                     string zkSearchTag,
                                     SpringBattleStartSetup startSetup)
        {
            var previousCulture = Thread.CurrentThread.CurrentCulture;
            try
            {
                Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

                playersExport = new List<UserBattleStatus>();
                var isHost = localUser.Name == Founder.Name;
                var myUbs = Users.SingleOrDefault(x => x.Name == localUser.Name);
                if (!isHost)
                {
                    var sb = new StringBuilder();
                    sb.AppendLine("[GAME]");
                    sb.AppendLine("{");
                    sb.AppendFormat("HostIP={0};\n", Ip);
                    sb.AppendFormat("HostPort={0};\n", HostPort);
                    sb.AppendLine("IsHost=0;");
                    sb.AppendFormat("MyPlayerName={0};\n", localUser.Name);
                    if (myUbs != null)
                    {
                        if (myUbs.ScriptPassword != null) sb.AppendFormat("MyPasswd={0};\n", myUbs.ScriptPassword);
                    }
                    else
                    {
                        sb.AppendFormat("MyPasswd={0};\n", localUser.Name); // used for mid-game join .. if no userbattlestatus, use own name
                    }
                    sb.AppendLine("}");
                    return sb.ToString();
                }
                else
                {
                    if (mod == null) throw new ApplicationException("Mod not downloaded yet");

                    var script = new StringBuilder();

                    script.AppendLine("[GAME]");
                    script.AppendLine("{");

                    script.AppendFormat("   ZkSearchTag={0};\n", zkSearchTag);
                    script.AppendFormat("  Mapname={0};\n", MapName);

                    if (mod.IsMission) script.AppendFormat("  StartPosType=3;\n");
                    else
                    {
                        if (Details.StartPos == BattleStartPos.Choose) script.AppendFormat("  StartPosType=2;\n");
                        else script.AppendFormat("  StartPosType=3;\n"); // workaround for random/fixed
                        // script.AppendFormat("  StartPosType={0};\n", (int)Details.StartPos);
                    }

                    script.AppendFormat("  GameType={0};\n", ModName);
                    if (ModHash.HasValue)
                        script.AppendFormat("  ModHash={0};\n", ModHash.Value != 0 ? (uint)ModHash.Value : 1);
                            // hack dont set to 1 when dedi srever is patched
                    if (MapHash.HasValue) script.AppendFormat("  MapHash={0};\n", MapHash.Value != 0 ? (uint)MapHash.Value : 1);
                    script.AppendFormat("  AutohostPort={0};\n", loopbackListenPort);
                    script.AppendLine();
                    script.AppendFormat("  HostIP={0};\n", Ip);
                    script.AppendFormat("  HostPort={0};\n", HostPort);
                    script.AppendFormat("  SourcePort={0};\n", 8300);
                    script.AppendFormat("  IsHost=1;\n");
                    script.AppendLine();

                    //script.AppendFormat("  MyPlayerName={0};\n", localUser.Name);

                    var positions = map.Positions != null ? map.Positions.ToList() : new List<StartPos>();
                    if (Details.StartPos == BattleStartPos.Random) positions = positions.Shuffle();

                    List<UserBattleStatus> users;
                    List<BotBattleStatus> bots;

                    if (startSetup != null && startSetup.BalanceTeamsResult != null && startSetup.BalanceTeamsResult.Players != null)
                    {
                        // if there is a balance results as a part of start setup, use values from this (override lobby state)
                        users = new List<UserBattleStatus>(this.Users.Select(x => x.Clone()));
                        bots = new List<BotBattleStatus>(this.Bots.Select(x => (BotBattleStatus)x.Clone()));
                        foreach (var p in startSetup.BalanceTeamsResult.Players)
                        {
                            var us = users.FirstOrDefault(x => x.Name == p.Name);
                            if (us == null)
                            {
                                us = new UserBattleStatus(p.Name, new User() {LobbyID = p.LobbyID}, Password);
                                users.Add(us);
                            }
                            us.TeamNumber = p.TeamID;
                            us.IsSpectator = p.IsSpectator;
                            us.AllyNumber = p.AllyID;

                        }
                        foreach (var p in startSetup.BalanceTeamsResult.Bots)
                        {
                            var bot = bots.FirstOrDefault(x => x.Name == p.BotName);
                            if (bot == null)
                            {
                                bot = new BotBattleStatus(p.BotName, p.Owner, p.BotAI);
                                bots.Add(bot);
                            }
                            bot.AllyNumber = bot.AllyNumber;
                            bot.TeamNumber = bot.TeamNumber;
                        }

                        foreach (var u in users.Where(x => !startSetup.BalanceTeamsResult.Players.Any(y => y.Name == x.Name)))
                        {
                            u.IsSpectator = true;
                        } // spec those not known at the time of balance
                    }
                    else
                    {
                        users = this.Users;
                        bots = this.Bots;
                    }


                    GeneratePlayerSection(playersExport, localUser, startSetup, users, script, positions, bots);

                    return script.ToString();
                }
            }
            finally
            {
                Thread.CurrentThread.CurrentCulture = previousCulture;
            }
        }
예제 #5
0
        public static void GeneratePlayerSection(List<UserBattleStatus> playersExport,
            List<UserBattleStatus> users,
            StringBuilder script,
            List<BotBattleStatus> bots,
            IDictionary<int, BattleRect> _rectangles,
            Dictionary<string, string> _modOptions,
            User localUser = null,
            SpringBattleStartSetup startSetup = null
           )
        {
            // ordinary battle stuff

            var userNum = 0;
            var teamNum = 0;
            var aiNum = 0;

            //players is excluding self (so "springie doesn't appear as spec ingame") & excluding bots (bots is added later for each owner)
            var non_botUsers = users.Where(u => !bots.Any(b => b.Name == u.Name)); //.OrderBy(x => x.TeamNumber);
            if (localUser != null) //I am a server
                non_botUsers = non_botUsers.Where(x => x.Name != localUser.Name);

            foreach (var u in non_botUsers.OrderBy(x => x.TeamNumber))
            {
                ScriptAddUser(script, userNum, playersExport, startSetup, teamNum, u);

                if (!u.IsSpectator)
                {
                    ScriptAddTeam(script, teamNum, userNum, u);
                    teamNum++;
                }

                foreach (var b in bots.Where(x => x.owner == u.Name))
                {
                    ScriptAddBot(script, aiNum, teamNum, userNum, b);
                    aiNum++;
                    ScriptAddTeam(script, teamNum, userNum, b);
                    teamNum++;
                }
                userNum++;
            }

            // ALLIANCES
            script.AppendLine();
            foreach (var allyNumber in
                users.Where(x => !x.IsSpectator).Select(x => x.AllyNumber).Union(bots.Select(x => x.AllyNumber)).Union(_rectangles.Keys).Distinct())
            {
                // get allies from each player, bot and rectangles (for koth)
                script.AppendFormat("[ALLYTEAM{0}]\n", allyNumber);
                script.AppendLine("{");
                script.AppendFormat("     NumAllies={0};\n", 0);
                double left = 0, top = 0, right = 1, bottom = 1;
                BattleRect rect;
                if (_rectangles.TryGetValue(allyNumber, out rect)) rect.ToFractions(out left, out top, out right, out bottom);
                script.AppendFormat(CultureInfo.InvariantCulture, "     StartRectLeft={0};\n", left);
                script.AppendFormat(CultureInfo.InvariantCulture, "     StartRectTop={0};\n", top);
                script.AppendFormat(CultureInfo.InvariantCulture, "     StartRectRight={0};\n", right);
                script.AppendFormat(CultureInfo.InvariantCulture, "     StartRectBottom={0};\n", bottom);
                script.AppendLine("}");
            }

            script.AppendLine();

                script.AppendLine("  [MODOPTIONS]");
                script.AppendLine("  {");

                var options = new Dictionary<string, string>(_modOptions);

                // replace/add custom modoptions from startsetup (if they exist)
                if (startSetup != null && startSetup.ModOptions != null) foreach (var entry in startSetup.ModOptions) options[entry.Key] = entry.Value;

                // write final options to script
                foreach (var kvp in options) script.AppendFormat("    {0}={1};\n", kvp.Key, kvp.Value);

                script.AppendLine("  }");


            script.AppendLine("}");
        }
예제 #6
0
        /// <summary>
        /// Generates script
        /// </summary>
        /// <param name="playersExport">list of players</param>
        /// <param name="localUser">myself</param>
        /// <param name="loopbackListenPort">listen port for autohost interface</param>
        /// <param name="zkSearchTag">hackish search tag</param>
        /// <param name="startSetup">structure with custom extra data</param>
        /// <returns></returns>
        public string GenerateScript(out List<UserBattleStatus> playersExport,
                                     User localUser,
                                     int loopbackListenPort,
                                     string zkSearchTag,
                                     SpringBattleStartSetup startSetup)
        {
            var previousCulture = Thread.CurrentThread.CurrentCulture;
            try
            {
                Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

                playersExport = new List<UserBattleStatus>();
                var isHost = localUser.Name == Founder.Name;

                var myUbs = Users[localUser.Name];
                if (!isHost)
                {
                    var sb = new StringBuilder();
                    sb.AppendLine("[GAME]");
                    sb.AppendLine("{");
                    sb.AppendFormat("HostIP={0};\n", Ip);
                    sb.AppendFormat("HostPort={0};\n", HostPort);
                    sb.AppendLine("IsHost=0;");
                    sb.AppendFormat("MyPlayerName={0};\n", localUser.Name);
                    if (myUbs != null)
                    {
                        if (myUbs.ScriptPassword != null) sb.AppendFormat("MyPasswd={0};\n", myUbs.ScriptPassword);
                    }
                    else
                    {
                        sb.AppendFormat("MyPasswd={0};\n", localUser.Name); // used for mid-game join .. if no userbattlestatus, use own name
                    }
                    sb.AppendLine("}");
                    return sb.ToString();
                }
                else
                {

                    var script = new StringBuilder();

                    script.AppendLine("[GAME]");
                    script.AppendLine("{");

                    script.AppendFormat("   ZkSearchTag={0};\n", zkSearchTag);
                    script.AppendFormat("  Mapname={0};\n", MapName);

                    script.AppendFormat("  StartPosType=2;\n");

                    script.AppendFormat("  GameType={0};\n", ModName);
                    script.AppendFormat("  ModHash=1;\n");
                    script.AppendFormat("  MapHash=1;\n");

                    script.AppendFormat("  AutohostPort={0};\n", loopbackListenPort);
                    script.AppendLine();
                    script.AppendFormat("  HostIP={0};\n", Ip);
                    script.AppendFormat("  HostPort={0};\n", HostPort);
                    script.AppendFormat("  SourcePort={0};\n", 8300);
                    script.AppendFormat("  IsHost=1;\n");
                    script.AppendLine();

                    //script.AppendFormat("  MyPlayerName={0};\n", localUser.Name);

                    List<UserBattleStatus> users;
                    List<BotBattleStatus> bots;

                    if (startSetup != null && startSetup.BalanceTeamsResult != null && startSetup.BalanceTeamsResult.Players != null)
                    {
                        // if there is a balance results as a part of start setup, use values from this (override lobby state)
                        users = Users.Values.ToList();
                        bots = new List<BotBattleStatus>(this.Bots.Values.Select(x => (BotBattleStatus)x.Clone()));
                        foreach (var p in startSetup.BalanceTeamsResult.Players)
                        {
                            var us = users.FirstOrDefault(x => x.Name == p.Name);
                            if (us == null)
                            {
                                us = new UserBattleStatus(p.Name, new User() { AccountID = p.LobbyID }, Password); // TODO this "password" use does not look right
                                users.Add(us);
                            }
                            us.TeamNumber = p.TeamID;
                            us.IsSpectator = p.IsSpectator;
                            us.AllyNumber = p.AllyID;

                        }
                        foreach (var p in startSetup.BalanceTeamsResult.Bots)
                        {
                            var bot = bots.FirstOrDefault(x => x.Name == p.BotName);
                            if (bot == null)
                            {
                                bot = new BotBattleStatus(p.BotName, p.Owner, p.BotAI);
                                bots.Add(bot);
                            }
                            bot.AllyNumber = bot.AllyNumber;
                            bot.TeamNumber = bot.TeamNumber;
                        }

                        foreach (var u in users.Where(x => !startSetup.BalanceTeamsResult.Players.Any(y => y.Name == x.Name)))
                        {
                            u.IsSpectator = true;
                        } // spec those not known at the time of balance
                    }
                    else
                    {
                        users = this.Users.Values.ToList();
                        bots = this.Bots.Values.ToList();
                    }


                    GeneratePlayerSection(playersExport, users, script, bots, Rectangles, ModOptions, localUser, startSetup);

                    return script.ToString();
                }
            }
            finally
            {
                Thread.CurrentThread.CurrentCulture = previousCulture;
            }
        }
예제 #7
0
        static bool listOnlyThatLevelsModules = false;  // may cause bugs

        public static SpringBattleStartSetup GetSpringBattleStartSetup(BattleContext context) {
            try {
                AutohostMode mode = context.GetMode();
                var ret = new SpringBattleStartSetup();

                if (mode == AutohostMode.Planetwars)
                {
                    ret.BalanceTeamsResult = Balancer.BalanceTeams(context, true,null, null);
                    context.Players = ret.BalanceTeamsResult.Players;
                }
                
                var commanderTypes = new LuaTable();
                var db = new ZkDataContext();

                var accountIDsWithExtraComms = new List<int>();
                // calculate to whom to send extra comms
                if (mode == AutohostMode.Planetwars || mode == AutohostMode.Generic || mode == AutohostMode.GameFFA ||
                    mode == AutohostMode.Teams) {
                    IOrderedEnumerable<IGrouping<int, PlayerTeam>> groupedByTeam =
                        context.Players.Where(x => !x.IsSpectator).GroupBy(x => x.AllyID).OrderByDescending(x => x.Count());
                    IGrouping<int, PlayerTeam> biggest = groupedByTeam.FirstOrDefault();
                    if (biggest != null) {
                        foreach (var other in groupedByTeam.Skip(1)) {
                            int cnt = biggest.Count() - other.Count();
                            if (cnt > 0) {
                                foreach (Account a in
                                    other.Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID)).OrderByDescending(x => x.Elo*x.EloWeight).Take(
                                        cnt)) accountIDsWithExtraComms.Add(a.AccountID);
                            }
                        }
                    }
                }

                bool is1v1 = context.Players.Where(x => !x.IsSpectator).ToList().Count == 2 && context.Bots.Count == 0;



                Faction attacker = null;
                Faction defender = null;
                Planet planet = null;
                if (mode == AutohostMode.Planetwars) {
                    planet = db.Galaxies.First(x => x.IsDefault).Planets.First(x => x.Resource.InternalName == context.Map);
                    attacker =
                        context.Players.Where(x => x.AllyID == 0 && !x.IsSpectator)
                            .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID))
                            .Where(x => x.Faction != null)
                            .Select(x => x.Faction)
                            .First();

                    defender = planet.Faction;

                    if (attacker == defender) defender = null;

                    ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "attackingFaction", Value = attacker.Shortcut });
                    if (defender != null) ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "defendingFaction", Value = defender.Shortcut });
                    ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "planet", Value = planet.Name });
                }


                
                foreach (PlayerTeam p in context.Players) {
                    Account user = db.Accounts.Find(p.LobbyID);
                    if (user != null) {
                        var userParams = new List<SpringBattleStartSetup.ScriptKeyValuePair>();
                        ret.UserParameters.Add(new SpringBattleStartSetup.UserCustomParameters { LobbyID = p.LobbyID, Parameters = userParams });

                        bool userBanMuted = user.PunishmentsByAccountID.Any(x => !x.IsExpired && x.BanMute);
                        if (userBanMuted) userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "muted", Value = "1" });
                        userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair
                                       { Key = "faction", Value = user.Faction != null ? user.Faction.Shortcut : "" });
                        userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair
                                       { Key = "clan", Value = user.Clan != null ? user.Clan.Shortcut : "" });
                        userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "level", Value = user.Level.ToString() });
                        double elo =  mode == AutohostMode.Planetwars ? user.EffectivePwElo : (is1v1 ? user.Effective1v1Elo : user.EffectiveElo);
                        userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "elo", Value = Math.Round(elo).ToString() }); // elo for ingame is just ordering for auto /take
                        userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "avatar", Value = user.Avatar });
                        userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "admin", Value = (user.IsZeroKAdmin ? "1" : "0") });

                        if (!p.IsSpectator) {
                            if (mode == AutohostMode.Planetwars)
                            {
                                bool allied = user.Faction != null && defender != null && user.Faction != defender &&
                                              defender.HasTreatyRight(user.Faction, x => x.EffectPreventIngamePwStructureDestruction == true, planet);

                                if (!allied && user.Faction != null && (user.Faction == attacker || user.Faction == defender)) {
                                    userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "canAttackPwStructures", Value = "1" });
                                }
                            }

                            var pu = new LuaTable();
                            bool userUnlocksBanned = user.PunishmentsByAccountID.Any(x => !x.IsExpired && x.BanUnlocks);
                            bool userCommandersBanned = user.PunishmentsByAccountID.Any(x => !x.IsExpired && x.BanCommanders);

                            if (!userUnlocksBanned) {
                                if (mode != AutohostMode.Planetwars || user.Faction == null) foreach (Unlock unlock in user.AccountUnlocks.Select(x => x.Unlock)) pu.Add(unlock.Code);
                                else {
                                    foreach (Unlock unlock in
                                        user.AccountUnlocks.Select(x => x.Unlock).Union(user.Faction.GetFactionUnlocks().Select(x => x.Unlock)).Where(x => x.UnlockType == UnlockTypes.Unit)) pu.Add(unlock.Code);
                                }
                            }

                            userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "unlocks", Value = pu.ToBase64String() });

                            if (accountIDsWithExtraComms.Contains(user.AccountID)) userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "extracomm", Value = "1" });

                            var pc = new LuaTable();

                            if (!userCommandersBanned) {
                                foreach (Commander c in user.Commanders.Where(x => x.Unlock != null && x.ProfileNumber <= GlobalConst.CommanderProfileCount)) {
                                    try {
                                        if (string.IsNullOrEmpty(c.Name) || c.Name.Any(x => x == '"') )
                                        {
                                            c.Name = c.CommanderID.ToString();
                                        }
                                        LuaTable morphTable = new LuaTable();
                                        pc["[\"" + c.Name + "\"]"] = morphTable;

                                        // process decoration icons
                                        LuaTable decorations = new LuaTable();
                                        foreach (Unlock d in
                                                        c.CommanderDecorations.Where(x => x.Unlock != null).OrderBy(
                                                            x => x.SlotID).Select(x => x.Unlock))
                                        {
                                            CommanderDecorationIcon iconData = db.CommanderDecorationIcons.FirstOrDefault(x => x.DecorationUnlockID == d.UnlockID);
                                            if (iconData != null)
                                            {
                                                string iconName = null, iconPosition = null;
                                                // FIXME: handle avatars and preset/custom icons
                                                if (iconData.IconType == (int)DecorationIconTypes.Faction)
                                                {
                                                    iconName = user.Faction != null ? user.Faction.Shortcut : null;
                                                }
                                                else if (iconData.IconType == (int)DecorationIconTypes.Clan)
                                                {
                                                    iconName = user.Clan != null ? user.Clan.Shortcut : null;
                                                }

                                                if (iconName != null)
                                                {
                                                    iconPosition = CommanderDecoration.GetIconPosition(d);
                                                    LuaTable entry = new LuaTable();
                                                    entry.Add("image", iconName);
                                                    decorations.Add("icon_" + iconPosition.ToLower(), entry);
                                                }
                                            }
                                            else decorations.Add(d.Code);
                                        }
                                        

                                        string prevKey = null;
                                        for (int i = 0; i <= GlobalConst.NumCommanderLevels; i++) {
                                            string key = string.Format("c{0}_{1}_{2}", user.AccountID, c.ProfileNumber, i);
                                            morphTable.Add(key);    // TODO: maybe don't specify morph series in player data, only starting unit

                                            var comdef = new LuaTable();
                                            commanderTypes[key] = comdef;

                                            comdef["chassis"] = c.Unlock.Code + i;

                                            var modules = new LuaTable();
                                            comdef["modules"] = modules;
                                            
                                            comdef["decorations"] = decorations;

                                            comdef["name"] = c.Name.Substring(0, Math.Min(25, c.Name.Length)) + " level " + i;

                                            //if (i < GlobalConst.NumCommanderLevels)
                                            //{
                                            //    comdef["next"] = string.Format("c{0}_{1}_{2}", user.AccountID, c.ProfileNumber, i+1);
                                            //}
                                            //comdef["owner"] = user.Name;

                                            if (i > 0)
                                            {
                                                comdef["cost"] = c.GetTotalMorphLevelCost(i);

                                                if (listOnlyThatLevelsModules)
                                                {
                                                    if (prevKey != null) comdef["prev"] = prevKey;
                                                    prevKey = key;
                                                    foreach (Unlock m in
                                                        c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel == i && x.Unlock != null).OrderBy(
                                                            x => x.Unlock.UnlockType).ThenBy(x => x.SlotID).Select(x => x.Unlock)) modules.Add(m.Code);
                                                }
                                                else
                                                {
                                                    foreach (Unlock m in
                                                        c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel <= i && x.Unlock != null).OrderBy(
                                                            x => x.Unlock.UnlockType).ThenBy(x => x.SlotID).Select(x => x.Unlock)) modules.Add(m.Code);
                                                }
                                            }
                                        }
                                    } catch (Exception ex) {
                                        Trace.TraceError(ex.ToString());
                                        throw new ApplicationException(
                                            string.Format("Error processing commander: {0} - {1} of player {2} - {3}",
                                                          c.CommanderID,
                                                          c.Name,
                                                          user.AccountID,
                                                          user.Name),
                                            ex);
                                    }
                                }
                            }
                            else userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "jokecomm", Value = "1" });

                            userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "commanders", Value = pc.ToBase64String() });
                        }
                    }
                }

                ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "commanderTypes", Value = commanderTypes.ToBase64String() });
                if (mode == AutohostMode.Planetwars)
                {
                    string owner = planet.Faction != null ? planet.Faction.Shortcut : "";

                    var pwStructures = new LuaTable();
                    foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType!= null && !string.IsNullOrEmpty(x.StructureType.IngameUnitName))) {
                        pwStructures.Add("s" + s.StructureTypeID,
                                         new LuaTable
                                         {
                                             { "unitname", s.StructureType.IngameUnitName },
                                             //{ "isDestroyed", s.IsDestroyed ? true : false },
                                             { "name", string.Format("{0} {1} ({2})", owner, s.StructureType.Name, s.Account!= null ? s.Account.Name:"unowned") },
                                             { "description", s.StructureType.Description }
                                         });
                    }
                    ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair
                                       { Key = "planetwarsStructures", Value = pwStructures.ToBase64String() });
                }

                return ret;
            } catch (Exception ex) {
                Trace.TraceError(ex.ToString());
                throw;
            }
        }
        static void GeneratePlayerSection(StringBuilder script, BattleContext startContext, SpringBattleStartSetup setup)
        {
            // ordinary battle stuff

            var userNum = 0;
            var teamNum = 0;
            var aiNum = 0;

            foreach (var u in startContext.Players) {
                ScriptAddUser(script, userNum, u, teamNum, setup.UserParameters.FirstOrDefault(x => x.LobbyID == u.LobbyID));

                if (!u.IsSpectator) {
                    ScriptAddTeam(script, teamNum, userNum, u.AllyID);
                    teamNum++;
                }

                foreach (var b in startContext.Bots.Where(x => x.Owner == u.Name)) {
                    ScriptAddBot(script, aiNum, teamNum, userNum, b.BotAI, b.BotName);
                    aiNum++;
                    ScriptAddTeam(script, teamNum, userNum, b.AllyID);
                    teamNum++;
                }
                userNum++;
            }

            // ALLIANCES AND START BOXES
            var startboxes = new StringBuilder();
            startboxes.Append("return { ");
            script.AppendLine();
            for (var allyNumber = 0; allyNumber < Spring.MaxAllies; allyNumber++) {
                script.AppendFormat("[ALLYTEAM{0}]\n", allyNumber);
                script.AppendLine("{");
                script.AppendLine("     NumAllies=0;");
                BattleRect rect;
                if (startContext.Rectangles!=null && startContext.Rectangles.TryGetValue(allyNumber, out rect)) {
                    double left = 0, top = 0, right = 1, bottom = 1;
                    rect.ToFractions(out left, out top, out right, out bottom);
                    startboxes.AppendFormat(CultureInfo.InvariantCulture, "[{0}] = ", allyNumber);
                    startboxes.Append("{ ");
                    startboxes.AppendFormat(CultureInfo.InvariantCulture, "{0}, {1}, {2}, {3}", left, top, right, bottom);
                    startboxes.Append(" }, ");
                }
                script.AppendLine("}");
            }

            startboxes.Append("}");
            script.AppendLine();

            script.AppendLine("  [MODOPTIONS]");
            script.AppendLine("  {");

            script.AppendFormat("    startboxes={0};\n", startboxes.ToString());

            var options = new Dictionary<string, string>(startContext.ModOptions);

            // replace/add custom modoptions from startsetup (if they exist)
            if (setup != null && setup.ModOptions != null) foreach (var entry in setup.ModOptions) options[entry.Key] = entry.Value;

            // write final options to script
            foreach (var kvp in options) script.AppendFormat("    {0}={1};\n", kvp.Key, kvp.Value);

            script.AppendLine("  }");

            script.AppendLine("}");
        }
        static void ScriptAddUser(StringBuilder script, int userNum, PlayerTeam pteam, int teamNum,
                                  SpringBattleStartSetup.UserCustomParameters customParameters)
        {
            // PLAYERS
            script.AppendFormat("  [PLAYER{0}]\n", userNum);
            script.AppendLine("  {");
            script.AppendFormat("     Name={0};\n", pteam.Name);
            script.AppendFormat("     Spectator={0};\n", pteam.IsSpectator ? 1 : 0);
            if (!pteam.IsSpectator) script.AppendFormat("     Team={0};\n", teamNum);

            if (pteam.ScriptPassword != null) script.AppendFormat("     Password={0};\n", pteam.ScriptPassword);

            if (customParameters != null) foreach (var kvp in customParameters.Parameters) script.AppendFormat("     {0}={1};\n", kvp.Key, kvp.Value);
            script.AppendLine("  }");
        }