示例#1
0
        /// <summary>
        ///     Sets up all the things that Springie needs to know for the battle: how to balance, who to get extra commanders,
        ///     what PlanetWars structures to create, etc.
        /// </summary>
        public static LobbyHostingContext GetDedicatedServerStartSetup(LobbyHostingContext context)
        {
            var ret = context;

            try
            {
                var mode = context.Mode;

                var commProfiles = new LuaTable();
                var db           = new ZkDataContext();

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


                // write Planetwars details to modoptions (for widget)
                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["attackingFaction"]      = attacker.Shortcut;
                    ret.ModOptions["attackingFactionName"]  = attacker.Name;
                    ret.ModOptions["attackingFactionColor"] = attacker.Color;
                    if (defender != null)
                    {
                        ret.ModOptions["defendingFaction"]      = defender.Shortcut;
                        ret.ModOptions["defendingFactionName"]  = defender.Name;
                        ret.ModOptions["defendingFactionColor"] = defender.Color;
                    }
                    else
                    {
                        ret.ModOptions["defendingFaction"]      = "Mercenary";
                        ret.ModOptions["defendingFactionName"]  = "Local militia";
                        ret.ModOptions["defendingFactionColor"] = "#CCCCCC";
                    }
                    ret.ModOptions["planet"] = planet.Name;
                }

                // write player custom keys (level, elo, is muted, etc.)
                foreach (var p in context.Players)
                {
                    var user = db.Accounts.Where(x => x.AccountID == p.LobbyID).Include(x => x.RelalationsByOwner).FirstOrDefault();
                    if (user != null)
                    {
                        var userParams = new Dictionary <string, string>();
                        ret.UserParameters[p.Name] = userParams;

                        userParams["LobbyID"]     = user.AccountID.ToString();
                        userParams["CountryCode"] = user.HideCountry ? "??" : user.Country;

                        var userBanMuted = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanMute) != null;
                        if (userBanMuted)
                        {
                            userParams["muted"] = "1";
                        }
                        userParams["faction"]  = user.Faction != null ? user.Faction.Shortcut : "";
                        userParams["clan"]     = user.Clan != null ? user.Clan.Shortcut : "";
                        userParams["clanfull"] = user.Clan != null ? user.Clan.ClanName : "";

                        userParams["level"] = user.Level.ToString();
                        //userParams["mm_elo"] = Math.Round(user.EffectiveMmElo).ToString();
                        //userParams["casual_elo"] = Math.Round(user.EffectiveElo).ToString();

                        userParams["elo"] = Math.Round(user.GetBestRating().Elo).ToString();

                        userParams["icon"]      = user.GetIconName();
                        userParams["avatar"]    = user.Avatar;
                        userParams["badges"]    = string.Join(",", user.GetBadges());
                        userParams["admin"]     = user.AdminLevel >= AdminLevel.Moderator ? "1" : "0";
                        userParams["room_boss"] = p.Name == context.FounderName ? "1" : "0";
                        if (p.PartyID.HasValue)
                        {
                            userParams["PartyID"] = p.PartyID.ToString();
                        }

                        var userSpecChatBlocked = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanSpecChat) != null;;
                        userParams["can_spec_chat"] = userSpecChatBlocked ? "0" : "1";

                        userParams["ignored"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Ignore).Select(x => x.Target.Name));
                        userParams["friends"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Friend).Select(x => x.Target.Name));

                        if (!p.IsSpectator)
                        {
                            // set valid PW structure attackers
                            if (mode == AutohostMode.Planetwars)
                            {
                                userParams["pwRank"] = (user.AccountRolesByAccountID.Where(
                                                            x =>
                                                            !x.RoleType.IsClanOnly &&
                                                            (x.RoleType.RestrictFactionID == null || x.RoleType.RestrictFactionID == user.FactionID)).OrderBy(x => x.RoleType.DisplayOrder).Select(x => (int?)x.RoleType.DisplayOrder).FirstOrDefault() ?? 999).ToString();


                                var 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["canAttackPwStructures"] = "1";
                                }

                                userParams["pwInstructions"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(GetPwInstructions(planet, user, db, attacker)));
                            }

                            if (accountIDsWithExtraComms.Contains(user.AccountID))
                            {
                                userParams["extracomm"] = "1";
                            }

                            var commProfileIDs       = new LuaTable();
                            var userCommandersBanned = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanCommanders) != null;
                            if (!userCommandersBanned)
                            {
                                // set up commander data
                                foreach (var c in user.Commanders.Where(x => x.Unlock != null && x.ProfileNumber <= GlobalConst.CommanderProfileCount)
                                         )
                                {
                                    try
                                    {
                                        var commProfile = new LuaTable();

                                        if (string.IsNullOrEmpty(c.Name) || c.Name.Any(x => x == '"'))
                                        {
                                            c.Name = c.CommanderID.ToString();
                                        }
                                        commProfiles.Add("c" + c.CommanderID, commProfile);
                                        commProfileIDs.Add("c" + c.CommanderID);

                                        // process decoration icons
                                        var decorations = new LuaTable();
                                        foreach (var d in
                                                 c.CommanderDecorations.Where(x => x.Unlock != null).OrderBy(x => x.SlotID).Select(x => x.Unlock))
                                        {
                                            var 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);
                                                    var entry = new LuaTable();
                                                    entry.Add("image", iconName);
                                                    decorations.Add("icon_" + iconPosition.ToLower(), entry);
                                                }
                                            }
                                            else
                                            {
                                                decorations.Add(d.Code);
                                            }
                                        }

                                        commProfile["name"]        = c.Name.Substring(0, Math.Min(25, c.Name.Length));
                                        commProfile["chassis"]     = c.Unlock.Code;
                                        commProfile["decorations"] = decorations;

                                        var modules = new LuaTable();
                                        commProfile["modules"] = modules;

                                        for (var i = 1; i <= GlobalConst.NumCommanderLevels; i++)
                                        {
                                            var modulesForLevel = new LuaTable();
                                            modules.Add(modulesForLevel);
                                            var modulesOrdered = c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel == i).ToList();
                                            var slots          = db.CommanderSlots.ToList().Where(x => x.MorphLevel == i && (x.ChassisID == null || (x.ChassisID == c.ChassisUnlockID))).ToList();
                                            slots.Sort(delegate(CommanderSlot x, CommanderSlot y)
                                            {
                                                UnlockTypes type1 = x.UnlockType;
                                                UnlockTypes type2 = y.UnlockType;
                                                if (type1 == UnlockTypes.WeaponManualFire || type1 == UnlockTypes.WeaponBoth)
                                                {
                                                    type1 = UnlockTypes.Weapon;
                                                }
                                                if (type2 == UnlockTypes.WeaponManualFire || type2 == UnlockTypes.WeaponBoth)
                                                {
                                                    type2 = UnlockTypes.Weapon;
                                                }
                                                int result = type1.CompareTo(type2);
                                                if (result == 0)
                                                {
                                                    return(x.CommanderSlotID.CompareTo(y.CommanderSlotID));
                                                }
                                                else
                                                {
                                                    return(result);
                                                }
                                            });
                                            foreach (var slot in slots)
                                            {
                                                String value  = String.Empty;
                                                var    module = c.CommanderModules.FirstOrDefault(x => x.SlotID == slot.CommanderSlotID);
                                                if (module != null)
                                                {
                                                    value = module.Unlock.Code;
                                                }
                                                modulesForLevel.Add(value);
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Trace.TraceError(ex.ToString());
                                        throw new ApplicationException(
                                                  $"Error processing commander: {c.CommanderID} - {c.Name} of player {user.AccountID} - {user.Name}",
                                                  ex);
                                    }
                                }
                            }
                            else
                            {
                                userParams["jokecomm"] = "1";
                            }

                            userParams["commanders"] = commProfileIDs.ToBase64String();
                        }
                    }
                }
                ret.ModOptions["commanderTypes"] = commProfiles.ToBase64String();

                // set PW structures
                if (mode == AutohostMode.Planetwars)
                {
                    var owner = planet.Faction != null ? planet.Faction.Shortcut : "";

                    var pwStructures = new LuaTable();
                    foreach (
                        var s in planet.PlanetStructures.Where(x => x.StructureType != null && !string.IsNullOrEmpty(x.StructureType.IngameUnitName)))
                    {
                        pwStructures.Add(s.StructureType.IngameUnitName,
                                         new LuaTable
                        {
                            { "unitname", s.StructureType.IngameUnitName },
                            { "owner", s.Account?.Name },
                            { "canBeEvacuated", s.StructureType.IsIngameEvacuable },
                            { "canBeDestroyed", s.StructureType.IsIngameDestructible },
                            //{ "isDestroyed", s.IsDestroyed ? true : false },
                            {
                                "name", $"{owner} {s.StructureType.Name} ({(s.Account != null ? s.Account.Name : "unowned")})"
                            },
                            { "description", s.StructureType.Description }
                        });
                    }
                    ret.ModOptions["planetwarsStructures"] = pwStructures.ToBase64String();
                }

                return(ret);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                throw;
            }
        }
        static bool listOnlyThatLevelsModules = false;  // may cause bugs

        /// <summary>
        /// Sets up all the things that Springie needs to know for the battle: how to balance, who to get extra commanders, what PlanetWars structures to create, etc.
        /// </summary>
        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();

                // calculate to whom to send extra comms
                var accountIDsWithExtraComms = new List <int>();
                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;

                // write Planetwars details to modoptions (for widget)
                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
                    });
                }

                // write player custom keys (level, elo, is muted, etc.)
                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)
                        {
                            // set valid PW structure attackers
                            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)
                            {
                                // set up commander data
                                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()
                });

                // set PW structures
                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;
            }
        }
示例#3
0
        public ActionResult CommanderProfile(int profileNumber, string name, int?chassis, string deleteCommander)
        {
            if (profileNumber < 1 || profileNumber > GlobalConst.CommanderProfileCount)
            {
                return(Content("WTF! get lost"));
            }

            var db = new ZkDataContext();

            using (var scope = new TransactionScope())
            {
                var unlocks = GetUserUnlockCountsListIncludingFree(db);

                Commander comm = db.Commanders.SingleOrDefault(x => x.ProfileNumber == profileNumber && x.AccountID == Global.AccountID);
                if (comm != null)
                {
                    if (!string.IsNullOrEmpty(deleteCommander))                     // delete commander
                    {
                        db.Commanders.DeleteOnSubmit(comm);
                        db.SaveChanges();
                        scope.Complete();
                        return(GetCommanderProfileView(profileNumber));
                    }
                }
                else
                {
                    comm = new Commander()
                    {
                        AccountID = Global.AccountID, ProfileNumber = profileNumber
                    };
                    db.Commanders.InsertOnSubmit(comm);
                }

                if (comm.Unlock == null)
                {
                    var chassisUnlock = unlocks.FirstOrDefault(x => x.Unlock.UnlockID == chassis);
                    if ((chassis == null || chassisUnlock == null))
                    {
                        return(GetCommanderProfileView(profileNumber));
                    }
                    else
                    {
                        comm.ChassisUnlockID = chassis.Value;
                        comm.Unlock          = chassisUnlock.Unlock;
                    }
                }

                if (!string.IsNullOrEmpty(name))
                {
                    if (name.Length > GlobalConst.MaxCommanderNameLength)
                    {
                        name = name.Substring(0, GlobalConst.MaxCommanderNameLength);
                    }
                    name      = Regex.Replace(name, @"[^\u0020-\u007E]", string.Empty); // remove unicode stuff
                    comm.Name = name;
                }

                // process modules
                foreach (var key in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
                {
                    var m = Regex.Match(key, "m([0-9]+)");
                    if (m.Success)
                    {
                        var slotId = int.Parse(m.Groups[1].Value);
                        int unlockId;
                        int.TryParse(Request.Form[key], out unlockId);

                        if (unlockId > 0)
                        {
                            CommanderSlot slot = db.CommanderSlots.SingleOrDefault(x => x.CommanderSlotID == slotId);
                            if (slot == null)
                            {
                                return(Content("WTF get lost!"));
                            }

                            Unlock unlock = db.Unlocks.SingleOrDefault(x => x.UnlockID == unlockId);
                            if (unlock == null)
                            {
                                return(Content("WTF get lost!"));
                            }

                            if (!unlocks.Any(x => x.Unlock.UnlockID == unlock.UnlockID))
                            {
                                return(Content("WTF get lost!"));
                            }
                            if (slot.MorphLevel < unlock.MorphLevel || !IsUnlockValidForSlot(unlock, slot))
                            {
                                return(Content(string.Format("WTF cannot use {0} in slot {1}", unlock.Name, slot.CommanderSlotID)));
                            }
                            if (!string.IsNullOrEmpty(unlock.LimitForChassis))
                            {
                                var validChassis = unlock.LimitForChassis.Split(',');
                                if (!validChassis.Contains(comm.Unlock.Code))
                                {
                                    return(Content(string.Format("{0} cannot be used in commander {1}", unlock.Name, comm.Unlock.Name)));
                                }
                            }
                            if (!IsPrerequisiteUnlockPresent(comm, unlock))
                            {
                                return(Content(string.Format("{0} missing prerequisite module", unlock.Name)));
                            }

                            var comSlot = comm.CommanderModules.SingleOrDefault(x => x.SlotID == slotId);
                            if (comSlot == null)
                            {
                                comSlot = new CommanderModule()
                                {
                                    SlotID = slotId
                                };
                                comm.CommanderModules.Add(comSlot);
                            }
                            comSlot.ModuleUnlockID = unlockId;
                        }
                        else
                        {
                            var oldModule = comm.CommanderModules.FirstOrDefault(x => x.SlotID == slotId);
                            if (oldModule != null)
                            {
                                comm.CommanderModules.Remove(oldModule);
                            }
                        }
                    }
                }

                // process decorations
                foreach (var key in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
                {
                    var d = Regex.Match(key, "d([0-9]+)");
                    if (d.Success)
                    {
                        var slotId = int.Parse(d.Groups[1].Value);
                        int unlockId;
                        int.TryParse(Request.Form[key], out unlockId);

                        if (unlockId > 0)
                        {
                            CommanderDecorationSlot decSlot = db.CommanderDecorationSlots.SingleOrDefault(x => x.CommanderDecorationSlotID == slotId);
                            if (decSlot == null)
                            {
                                return(Content("WTF get lost!"));
                            }

                            Unlock unlock = db.Unlocks.SingleOrDefault(x => x.UnlockID == unlockId && x.UnlockType == UnlockTypes.Decoration);
                            if (unlock == null)
                            {
                                return(Content("WTF get lost!"));
                            }

                            if (!unlocks.Any(x => x.Unlock.UnlockID == unlock.UnlockID))
                            {
                                return(Content("WTF get lost!"));
                            }
                            if (!string.IsNullOrEmpty(unlock.LimitForChassis))
                            {
                                var validChassis = unlock.LimitForChassis.Split(',');
                                if (!validChassis.Contains(comm.Unlock.Code))
                                {
                                    return(Content(string.Format("{0} cannot be used in commander {1}", unlock.Name, comm.Unlock.Name)));
                                }
                            }

                            var comSlot = comm.CommanderDecorations.SingleOrDefault(x => x.SlotID == slotId);
                            if (comSlot == null)
                            {
                                comSlot = new CommanderDecoration()
                                {
                                    SlotID = slotId
                                };
                                comm.CommanderDecorations.Add(comSlot);
                            }
                            comSlot.DecorationUnlockID = unlockId;
                        }
                        else
                        {
                            var oldDecoration = comm.CommanderDecorations.FirstOrDefault(x => x.SlotID == slotId);
                            if (oldDecoration != null)
                            {
                                comm.CommanderDecorations.Remove(oldDecoration);
                            }
                        }
                    }
                }

                // remove a module/decoration if ordered to
                foreach (var toDel in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
                {
                    var m = Regex.Match(toDel, "deleteSlot([0-9]+)");
                    if (m.Success)
                    {
                        var slotId = int.Parse(m.Groups[1].Value);
                        comm.CommanderModules.Remove(comm.CommanderModules.SingleOrDefault(x => x.SlotID == slotId));
                    }

                    var d = Regex.Match(toDel, "deleteDecorationSlot([0-9]+)");
                    if (d.Success)
                    {
                        var decSlotId = int.Parse(d.Groups[1].Value);
                        comm.CommanderDecorations.Remove(comm.CommanderDecorations.SingleOrDefault(x => x.SlotID == decSlotId));
                    }
                }

                // cleanup invalid modules?

                db.SaveChanges();
                foreach (var unlock in comm.CommanderModules.GroupBy(x => x.Unlock))
                {
                    if (unlock.Key == null)
                    {
                        continue;
                    }
                    var owned = unlocks.Where(x => x.Unlock.UnlockID == unlock.Key.UnlockID).Sum(x => (int?)x.Count) ?? 0;
                    if (owned < unlock.Count())
                    {
                        var toRemove = unlock.Count() - owned;

                        foreach (var m in unlock.OrderByDescending(x => x.SlotID))
                        {
                            db.CommanderModules.DeleteOnSubmit(m);
                            //comm.CommanderModules.Remove(m);
                            toRemove--;
                            if (toRemove <= 0)
                            {
                                break;
                            }
                        }
                    }
                }

                db.SaveChanges();
                scope.Complete();
            }

            return(GetCommanderProfileView(profileNumber));
        }
示例#4
0
        /// <summary>
        ///     Sets up all the things that Springie needs to know for the battle: how to balance, who to get extra commanders,
        ///     what PlanetWars structures to create, etc.
        /// </summary>
        public static LobbyHostingContext GetDedicatedServerStartSetup(LobbyHostingContext context)
        {
            var ret = context;

            try
            {
                var mode = context.Mode;

                var commProfiles = new LuaTable();
                var db           = new ZkDataContext();

                // calculate to whom to send extra comms
                var accountIDsWithExtraComms = new Dictionary <int, int>();
                if (mode == AutohostMode.Planetwars || mode == AutohostMode.GameFFA || mode == AutohostMode.Teams)
                {
                    var groupedByTeam = context.Players.Where(x => !x.IsSpectator).GroupBy(x => x.AllyID).OrderByDescending(x => x.Count());
                    var biggest       = groupedByTeam.FirstOrDefault();
                    if (biggest != null)
                    {
                        foreach (var other in groupedByTeam.Skip(1))
                        {
                            var cnt = biggest.Count() - other.Count();
                            if (cnt > 0)
                            {
                                // example case: 3 players on this team, 8 players on largest team
                                // 5 bonus comms to dole out to this team
                                // per_player = 1 (integer result of 5/3)
                                // remainder: 2, so now cnt = 2
                                // iterate over all players in this team
                                //  first player: cnt == 2, >0 so we give him a second extra comm
                                //  second player: cnt == 1, >0 so same deal
                                //  from now on cnt <= 0 so the last player only gets the one extra comm
                                int per_player = cnt / other.Count();
                                cnt = cnt % other.Count();
                                foreach (var a in other
                                         .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID))
                                         .OrderByDescending(x => x.GetRating(RatingCategory.Casual).Elo))
                                {
                                    accountIDsWithExtraComms.Add(a.AccountID, per_player + (cnt > 0 ? 1 : 0));
                                    cnt--;
                                }
                            }
                        }
                    }
                }


                // write Planetwars details to modoptions (for widget)
                Faction attacker = null;
                Faction defender = null;
                Planet  planet   = null;
                if (mode == AutohostMode.Planetwars)
                {
                    var galaxy = db.Galaxies.First(x => x.IsDefault);
                    planet   = galaxy.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["attackingFaction"]      = attacker.Shortcut;
                    ret.ModOptions["attackingFactionName"]  = attacker.Name;
                    ret.ModOptions["attackingFactionColor"] = attacker.Color;
                    if (defender != null)
                    {
                        ret.ModOptions["defendingFaction"]      = defender.Shortcut;
                        ret.ModOptions["defendingFactionName"]  = defender.Name;
                        ret.ModOptions["defendingFactionColor"] = defender.Color;
                    }
                    else
                    {
                        ret.ModOptions["defendingFaction"]      = "Mercenary";
                        ret.ModOptions["defendingFactionName"]  = "Local militia";
                        ret.ModOptions["defendingFactionColor"] = "#CCCCCC";
                    }
                    ret.ModOptions["planet"]        = planet.Name;
                    ret.ModOptions["pw_galaxyTurn"] = galaxy.Turn.ToString();

                    ret.ModOptions["pw_baseIP"]            = GlobalConst.BaseInfluencePerBattle.ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_dropshipIP"]        = planet.GetEffectiveShipIpBonus(attacker).ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_defenseIP"]         = planet.GetEffectiveIpDefense().ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_attackerIP"]        = (planet.PlanetFactions.FirstOrDefault(x => x.FactionID == attacker.FactionID)?.Influence ?? 0).ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_maxIP"]             = GlobalConst.PlanetWarsMaximumIP.ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_neededIP"]          = GlobalConst.InfluenceToCapturePlanet.ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_attackerWinLoseCC"] = GlobalConst.PlanetWarsAttackerWinLoseCcMultiplier.ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_defenderWinKillCC"] = GlobalConst.PlanetWarsDefenderWinKillCcMultiplier.ToString(CultureInfo.InvariantCulture);
                }

                // write player custom keys (level, elo, is muted, etc.)
                foreach (var p in context.Players)
                {
                    var user = db.Accounts.Where(x => x.AccountID == p.LobbyID).Include(x => x.RelalationsByOwner).FirstOrDefault();
                    if (user != null)
                    {
                        var userParams = new Dictionary <string, string>();
                        ret.UserParameters[p.Name] = userParams;

                        userParams["LobbyID"]     = user.AccountID.ToString();
                        userParams["CountryCode"] = user.HideCountry ? "??" : user.Country;

                        var userBanMuted = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanMute) != null;
                        if (userBanMuted)
                        {
                            userParams["muted"] = "1";
                        }
                        userParams["faction"]  = user.Faction != null ? user.Faction.Shortcut : "";
                        userParams["clan"]     = user.Clan != null ? user.Clan.Shortcut : "";
                        userParams["clanfull"] = user.Clan != null ? user.Clan.ClanName : "";

                        userParams["level"] = user.Level.ToString();
                        //userParams["mm_elo"] = Math.Round(user.EffectiveMmElo).ToString();
                        //userParams["casual_elo"] = Math.Round(user.EffectiveElo).ToString();

                        userParams["elo"]       = Math.Round(user.GetRating(context.ApplicableRating).Elo).ToString();
                        userParams["elo_order"] = context.Players.Where(x => !x.IsSpectator)
                                                  .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID))
                                                  .Where(x => x.GetRating(context.ApplicableRating).Elo > user.GetRating(context.ApplicableRating).Elo)
                                                  .Count()
                                                  .ToString();

                        userParams["icon"]      = user.GetIconName();
                        userParams["avatar"]    = user.Avatar;
                        userParams["badges"]    = string.Join(",", user.GetBadges());
                        userParams["admin"]     = user.AdminLevel >= AdminLevel.Moderator ? "1" : "0";
                        userParams["room_boss"] = p.Name == context.FounderName ? "1" : "0";
                        if (p.PartyID.HasValue)
                        {
                            userParams["PartyID"] = p.PartyID.ToString();
                        }

                        var userSpecChatBlocked = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanSpecChat) != null;;
                        userParams["can_spec_chat"] = userSpecChatBlocked ? "0" : "1";

                        userParams["ignored"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Ignore).Select(x => x.Target.Name));
                        userParams["friends"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Friend).Select(x => x.Target.Name));

                        if (!p.IsSpectator)
                        {
                            // set valid PW structure attackers
                            if (mode == AutohostMode.Planetwars)
                            {
                                userParams["pwRank"] = (user.AccountRolesByAccountID.Where(
                                                            x =>
                                                            !x.RoleType.IsClanOnly &&
                                                            (x.RoleType.RestrictFactionID == null || x.RoleType.RestrictFactionID == user.FactionID)).OrderBy(x => x.RoleType.DisplayOrder).Select(x => (int?)x.RoleType.DisplayOrder).FirstOrDefault() ?? 999).ToString();


                                var 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["canAttackPwStructures"] = "1";
                                }

                                userParams["pwInstructions"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(GetPwInstructions(planet, user, db, attacker)));
                            }

                            if (accountIDsWithExtraComms.ContainsKey(user.AccountID))
                            {
                                userParams["extracomm"] = accountIDsWithExtraComms[user.AccountID].ToString();
                            }

                            var commProfileIDs       = new LuaTable();
                            var userCommandersBanned = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanCommanders) != null;
                            if (!userCommandersBanned)
                            {
                                // set up commander data
                                foreach (var c in user.Commanders.Where(x => x.Unlock != null && x.ProfileNumber <= GlobalConst.CommanderProfileCount)
                                         )
                                {
                                    try
                                    {
                                        var commProfile = new LuaTable();

                                        if (string.IsNullOrEmpty(c.Name) || c.Name.Any(x => x == '"'))
                                        {
                                            c.Name = c.CommanderID.ToString();
                                        }
                                        commProfiles.Add("c" + c.CommanderID, commProfile);
                                        commProfileIDs.Add("c" + c.CommanderID);

                                        // process decoration icons
                                        var decorations = new LuaTable();
                                        foreach (var d in
                                                 c.CommanderDecorations.Where(x => x.Unlock != null).OrderBy(x => x.SlotID).Select(x => x.Unlock))
                                        {
                                            var 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);
                                                    var entry = new LuaTable();
                                                    entry.Add("image", iconName);
                                                    decorations.Add("icon_" + iconPosition.ToLower(), entry);
                                                }
                                            }
                                            else
                                            {
                                                decorations.Add(d.Code);
                                            }
                                        }

                                        commProfile["name"]        = LuaTable.SanitizeString(c.Name.Substring(0, Math.Min(25, c.Name.Length))) ?? "dummy";
                                        commProfile["chassis"]     = c.Unlock.Code;
                                        commProfile["decorations"] = decorations;

                                        var modules = new LuaTable();
                                        commProfile["modules"] = modules;

                                        for (var i = 1; i <= GlobalConst.NumCommanderLevels; i++)
                                        {
                                            var modulesForLevel = new LuaTable();
                                            modules.Add(modulesForLevel);
                                            //var modulesOrdered = c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel == i).ToList();
                                            var slots = db.CommanderSlots.ToList().Where(x => x.MorphLevel == i && (x.ChassisID == null || (x.ChassisID == c.ChassisUnlockID))).ToList();
                                            slots.Sort(delegate(CommanderSlot x, CommanderSlot y)
                                            {
                                                UnlockTypes type1 = x.UnlockType;
                                                UnlockTypes type2 = y.UnlockType;
                                                if (type1 == UnlockTypes.WeaponManualFire || type1 == UnlockTypes.WeaponBoth)
                                                {
                                                    type1 = UnlockTypes.Weapon;
                                                }
                                                if (type2 == UnlockTypes.WeaponManualFire || type2 == UnlockTypes.WeaponBoth)
                                                {
                                                    type2 = UnlockTypes.Weapon;
                                                }
                                                int result = type1.CompareTo(type2);
                                                if (result == 0)
                                                {
                                                    return(x.CommanderSlotID.CompareTo(y.CommanderSlotID));
                                                }
                                                else
                                                {
                                                    return(result);
                                                }
                                            });
                                            foreach (var slot in slots)
                                            {
                                                String value  = String.Empty;
                                                var    module = c.CommanderModules.FirstOrDefault(x => x.SlotID == slot.CommanderSlotID);
                                                if (module != null)
                                                {
                                                    value = module.Unlock.Code;
                                                }
                                                modulesForLevel.Add(value);
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Trace.TraceError(ex.ToString());
                                        throw new ApplicationException(
                                                  $"Error processing commander: {c.CommanderID} - {c.Name} of player {user.AccountID} - {user.Name}",
                                                  ex);
                                    }
                                }
                            }
                            else
                            {
                                userParams["jokecomm"] = "1";
                            }

                            userParams["commanders"] = commProfileIDs.ToBase64String();
                        }
                    }
                }
                ret.ModOptions["commanderTypes"] = commProfiles.ToBase64String();

                /* General-purpose identifier.
                 * Prefer the more specific ones below when possible */
                ret.ModOptions["serverType"] = "ZKLS";

                /* Access to commands normally accessible only by the host.
                 * Lua calls prepend the / on their own, but not the autohost,
                 * so /say doesn't need it, but the cheat command does */
                ret.ModOptions["cheatCommandPrefix"] = "say !hostsay /";

                /* The server is listening for SPRINGIE strings (the game can skip those otherwise).
                 * See https://github.com/ZeroK-RTS/Zero-K-Infrastructure/blob/master/Shared/LobbyClient/DedicatedServer.cs#L317 */
                ret.ModOptions["sendSpringieData"] = "1";

                // set PW structures
                if (mode == AutohostMode.Planetwars)
                {
                    var owner = planet.Faction != null ? planet.Faction.Shortcut : "";

                    var pwStructures = new LuaTable();
                    foreach (
                        var s in planet.PlanetStructures.Where(x => x.StructureType != null && !string.IsNullOrEmpty(x.StructureType.IngameUnitName)))
                    {
                        pwStructures.Add(s.StructureType.IngameUnitName,
                                         new LuaTable
                        {
                            { "unitname", s.StructureType.IngameUnitName },
                            { "owner", s.Account?.Name },
                            { "canBeEvacuated", s.StructureType.IsIngameEvacuable },
                            { "canBeDestroyed", s.StructureType.IsIngameDestructible },
                            { "isInactive", !s.IsActive },
                            {
                                "name", $"{owner} {s.StructureType.Name} ({(s.Account != null ? s.Account.Name : "unowned")})"
                            },
                            { "description", s.StructureType.Description }
                        });
                    }
                    ret.ModOptions["planetwarsStructures"] = pwStructures.ToBase64String();
                }

                return(ret);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                throw;
            }
        }