public static PlayerJoinResult AutohostPlayerJoined(BattleContext context, int accountID)
        {
            var          res  = new PlayerJoinResult();
            var          db   = new ZkDataContext();
            AutohostMode mode = context.GetMode();

            if (mode == AutohostMode.Planetwars)
            {
                Planet planet = db.Galaxies.Single(x => x.IsDefault).Planets.SingleOrDefault(x => x.Resource.InternalName == context.Map);
                if (planet == null)
                {
                    res.PublicMessage = "Invalid map";
                    return(res);
                }
                Account account = db.Accounts.Find(accountID); // accountID is in fact lobbyID

                if (account != null)
                {
                    var config = context.GetConfig();
                    if (account.Level < config.MinLevel)
                    {
                        res.PrivateMessage = string.Format("Sorry, PlanetWars is competive online campaign for experienced players. You need to be at least level {0} to play here. To increase your level, play more games on other hosts or open multiplayer game and play against computer AI bots.  You can still spectate this game, however.", config.MinLevel);
                        res.ForceSpec      = true;
                        return(res);
                    }


                    string owner = "";
                    if (planet.Account != null)
                    {
                        owner = planet.Account.Name;
                    }
                    string facRoles = string.Join(",",
                                                  account.AccountRolesByAccountID.Where(x => !x.RoleType.IsClanOnly).Select(x => x.RoleType.Name).ToList());
                    if (!string.IsNullOrEmpty(facRoles))
                    {
                        facRoles += " of " + account.Faction.Name + ", ";
                    }

                    string clanRoles = string.Join(",",
                                                   account.AccountRolesByAccountID.Where(x => x.RoleType.IsClanOnly).Select(x => x.RoleType.Name).ToList());
                    if (!string.IsNullOrEmpty(clanRoles))
                    {
                        clanRoles += " of " + account.Clan.ClanName;
                    }

                    res.PublicMessage = string.Format("Greetings {0} {1}{2}, welcome to {3} planet {4} {6}/PlanetWars/Planet/{5}",
                                                      account.Name,
                                                      facRoles,
                                                      clanRoles,
                                                      owner,
                                                      planet.Name,
                                                      planet.PlanetID,
                                                      GlobalConst.BaseSiteUrl);

                    return(res);
                }
            }
            Account acc = db.Accounts.Find(accountID); // accountID is in fact lobbyID

            if (acc != null)
            {
                AutohostConfig config = context.GetConfig();
                if (acc.Level < config.MinLevel)
                {
                    res.PrivateMessage = string.Format("Sorry, you need to be at least level {0} to play here. To increase your level, play more games on other hosts or open multiplayer game and play against computer AI bots. You can still spectate this game, however.",
                                                       config.MinLevel);
                    res.ForceSpec = true;
                    return(res);
                }
                else if (acc.Level > config.MaxLevel)
                {
                    res.PrivateMessage = string.Format("Sorry, your level must be {0} or lower to play here. Pick on someone your own size! You can still spectate this game, however.",
                                                       config.MaxLevel);
                    res.ForceSpec = true;
                    return(res);
                }

                // FIXME: use 1v1 Elo for 1v1
                if (acc.EffectiveElo < config.MinElo)
                {
                    res.PrivateMessage = string.Format("Sorry, you need to have an Elo rating of at least {0} to play here. Win games against human opponents to raise your Elo. You can still spectate this game, however.",
                                                       config.MinElo);
                    res.ForceSpec = true;
                    return(res);
                }
                else if (acc.EffectiveElo > config.MaxElo)
                {
                    res.PrivateMessage = string.Format("Sorry, your Elo rating must be {0} or lower to play here. Pick on someone your own size! You can still spectate this game, however.",
                                                       config.MaxElo);
                    res.ForceSpec = true;
                    return(res);
                }
            }

            return(null);
        }
        /// <summary>
        /// Picks a map and writes a message if applicable
        /// </summary>
        /// <param name="context">The battle whose map needs selection</param>
        /// <param name="pickNew">If false and not in PlanetWars, don't pick a new map</param>
        /// <remarks>
        ///     <para>For Planetwars, picks the map given by the Planetwars matchmaker; else picks a featured map with the appropriate tags</para>
        ///     <para>For team and chickens games, picks a map of appropriate size based on current player count</para>
        ///     <para>For FFA, prefer maps that have a number of boxes equal to player count, or at least a number of boxes that is a multiple of player count</para>
        /// </remarks>
        public static RecommendedMapResult GetRecommendedMap(BattleContext context, bool pickNew)
        {
            var mode   = context.GetMode();
            var config = context.GetConfig();
            var res    = new RecommendedMapResult();

            using (var db = new ZkDataContext()) {
                if (mode == AutohostMode.Planetwars)
                {
                    var info = Global.PlanetWarsMatchMaker.GetBattleInfo(context.AutohostName);
                    if (info != null)
                    {
                        res.MapName = info.Map;
                        res.Message = String.Format("Welcome to planet {0} {2}/PlanetWars/Planet/{1} attacked", info.Name, info.PlanetID, GlobalConst.BaseSiteUrl);
                    }
                    else
                    {
                        res.MapName = context.Map;
                    }
                }
                else
                {
                    if (!pickNew)
                    {
                        // autohost is not managed or has valid featured map - check disabled
                        res.MapName = context.Map;
                        return(res);
                    }
                    List <Resource> list    = null;
                    var             players = context.Players.Count(x => !x.IsSpectator);
                    if (config != null && config.SplitBiggerThan != null && players > config.SplitBiggerThan)
                    {
                        players = players / 2;                                                                                     // expect the split
                    }
                    switch (mode)
                    {
                    case AutohostMode.Generic:
                    case AutohostMode.Teams:
                    case AutohostMode.None:
                        var ret = db.Resources.Where(x => x.TypeID == ResourceType.Map && x.FeaturedOrder != null && x.MapIsTeams != false && x.MapIsSpecial != true);
                        if (players > 11)
                        {
                            ret = ret.Where(x => (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) > 16 * 16);
                        }
                        else if (players > 8)
                        {
                            ret = ret.Where(x => (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) > 16 * 16 && (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) <= 24 * 24);
                        }
                        else if (players > 5)
                        {
                            ret = ret.Where(x => (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) <= 24 * 24 || x.MapIs1v1 == true);
                        }
                        else
                        {
                            ret = ret.Where(x => (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) <= 16 * 16 || x.MapIs1v1 == true);
                        }
                        list = ret.ToList();

                        break;

                    case AutohostMode.Game1v1:
                        list = db.Resources.Where(x => x.TypeID == ResourceType.Map && x.FeaturedOrder != null && x.MapIs1v1 == true && x.MapIsSpecial != true).ToList();
                        break;

                    case AutohostMode.GameChickens:
                        ret = db.Resources.Where(x => x.TypeID == ResourceType.Map && x.FeaturedOrder != null && x.MapIsSpecial != true && (x.MapIsChickens == true || x.MapWaterLevel == 1));
                        if (players > 5)
                        {
                            ret = ret.Where(x => (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) > 16 * 16);
                        }
                        else if (players > 4)
                        {
                            ret = ret.Where(x => (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) > 16 * 16 && (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) <= 24 * 24);
                        }
                        else if (players > 2)
                        {
                            ret = ret.Where(x => (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) <= 24 * 24 || x.MapIs1v1 == true);
                        }
                        else
                        {
                            ret = ret.Where(x => (x.MapHeight * x.MapHeight + x.MapWidth * x.MapWidth) <= 16 * 16 || x.MapIs1v1 == true);
                        }
                        list = ret.ToList();

                        break;

                    case AutohostMode.GameFFA:
                        list = db.Resources.Where(x => x.TypeID == ResourceType.Map && x.FeaturedOrder != null && x.MapIsFfa == true && x.MapFFAMaxTeams == players).ToList();
                        if (!list.Any())
                        {
                            list = db.Resources.Where(x => x.TypeID == ResourceType.Map && x.FeaturedOrder != null && x.MapIsFfa == true && (players % x.MapFFAMaxTeams == 0)).ToList();
                        }
                        if (!list.Any())
                        {
                            list = db.Resources.Where(x => x.TypeID == ResourceType.Map && x.FeaturedOrder != null && x.MapIsFfa == true).ToList();
                        }

                        break;
                    }
                    if (list != null)
                    {
                        var r = new Random();
                        if (list.Count > 0)
                        {
                            res.MapName = list[r.Next(list.Count)].InternalName;
                        }
                    }
                }
            }
            return(res);
        }
Beispiel #3
0
        public static BalanceTeamsResult BalanceTeams(BattleContext context, bool isGameStart, int?allyCount, bool?clanWise)
        {
            var config      = context.GetConfig();
            var playerCount = context.Players.Count(x => !x.IsSpectator);

            // game is managed, is bigger than split limit and wants to start -> split into two and issue starts
            if (isGameStart && context.GetMode() != AutohostMode.None && config.SplitBiggerThan != null && config.SplitBiggerThan < playerCount)
            {
                new Thread(() =>
                {
                    try {
                        SplitAutohost(context, true);
                    } catch (Exception ex) {
                        Trace.TraceError("Error when splitting game:{0}", ex);
                    }
                }).Start();
                return(new BalanceTeamsResult
                {
                    CanStart = false,
                    Message =
                        string.Format("Game too big - splitting into two - max players is {0} here",
                                      config.SplitBiggerThan)
                });
            }


            if (clanWise == null && (config.AutohostMode == AutohostMode.Generic || config.AutohostMode == AutohostMode.Teams))
            {
                clanWise = true;
            }

            var res = PerformBalance(context, isGameStart, allyCount, clanWise, config, playerCount);

            if (context.GetMode() != AutohostMode.Planetwars) // planetwars skip other checks
            {
                if (isGameStart)
                {
                    if (playerCount < (config.MinToStart ?? 0))
                    {
                        res.Message  = string.Format("This host needs at least {0} people to start", config.MinToStart);
                        res.CanStart = false;
                        return(res);
                    }
                    if (playerCount > (config.MaxToStart ?? 99))
                    {
                        res.Message  = string.Format("This host can only start with at most {0} players", config.MaxToStart);
                        res.CanStart = false;
                        return(res);
                    }

                    // dont allow to start alone
                    if (playerCount <= 1)
                    {
                        if (res.DeleteBots)
                        {
                            return new BalanceTeamsResult
                                   {
                                       CanStart = false,
                                       Message  = "You cannot play alone on this host, wait for players or join another game room and play with bots."
                                   }
                        }
                        ;
                        if (!context.Bots.Any())
                        {
                            return new BalanceTeamsResult
                                   {
                                       CanStart = false,
                                       Message  = "Cannot play alone, you can add bots using button on bottom left."
                                   }
                        }
                        ;
                    }
                }
            }
            if (isGameStart)
            {
                VerifySpecCheaters(context, res);
            }

            return(res);
        }
        public static string SubmitSpringBattleResult(BattleContext context,
                                                      string password,
                                                      BattleResult result,
                                                      List <BattlePlayerResult> players,
                                                      List <string> extraData)
        {
            try
            {
                Account acc = AuthServiceClient.VerifyAccountPlain(context.AutohostName, password);
                if (acc == null)
                {
                    throw new Exception("Account name or password not valid");
                }
                AutohostMode mode = context.GetMode();
                var          db   = new ZkDataContext();

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


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

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

                db.SubmitChanges();

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

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

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


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

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

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

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

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

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

                db.SubmitAndMergeChanges();

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

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

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

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


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

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