Пример #1
0
        };                                                                      // licho, kingraptor

        public ChannelManager(ZkLobbyServer server)
        {
            this.server = server;


            using (var db = new ZkDataContext())
            {
                factionChannels = new ConcurrentDictionary <string, Faction>(db.Factions.Where(x => !x.IsDeleted).ToDictionary(x => x.Shortcut, x => x));
                clanChannels    =
                    new ConcurrentDictionary <string, Clan>(db.Clans.Where(x => !x.IsDeleted).ToList().ToDictionary(x => x.GetClanChannel(), x => x));

                // restore topics from db
                foreach (var channelTopic in db.LobbyChannelTopics)
                {
                    server.Channels[channelTopic.ChannelName] = new Channel()
                    {
                        Name  = channelTopic.ChannelName,
                        Topic = new Topic()
                        {
                            Text = channelTopic.Topic, SetBy = channelTopic.Author, SetDate = channelTopic.SetDate
                        }
                    };
                }
            }

            // set "zk" as deluge
            server.Channels.AddOrUpdate("zk", s => new Channel()
            {
                Name = "zk", IsDeluge = true
            }, (s, ch) =>
            {
                ch.IsDeluge = true;
                return(ch);
            });
        }
Пример #2
0
        public ChatRelay(ZkLobbyServer zkServer, List <string> channels)
        {
            this.channels = channels;
            this.server   = zkServer;

            discord = new DiscordClient();

            springRelay = new SpringRelaySource(channels);
            sources.Add(springRelay);
            zklsRelay = new ZklsRelaySource(zkServer);
            sources.Add(zklsRelay);
            discordZkRelay = new DiscordRelaySource(discord, DiscordZkServerID, SaySource.Discord);
            sources.Add(discordZkRelay);
            discordSpringRelay = new DiscordRelaySource(discord, DiscordSpringServerID, SaySource.DiscordSpring);
            sources.Add(discordSpringRelay);


            restrictedSources.Add(zklsRelay);
            restrictedSources.Add(discordZkRelay);

            discord.Connect(new Secrets().GetNightwatchDiscordToken(), TokenType.Bot);

            foreach (var s in sources)
            {
                s.OnChatRelayMessage += OnAnySourceMessage;
            }

            timer = new Timer(TimerCallback, this, 1000, 2000);
        }
Пример #3
0
        public MatchMakerBattle(ZkLobbyServer server, MatchMaker.ProposedBattle bat, string mapname) : base(server, null)
        {
            ApplicableRating   = RatingCategory.MatchMaking;
            IsMatchMakerBattle = true;
            EngineVersion      = server.Engine;
            ModName            = server.Game;
            FounderName        = "MatchMaker #" + BattleID;
            Title      = "MatchMaker " + BattleID;
            Mode       = bat.QueueType.Mode;
            MaxPlayers = bat.Size;
            Prototype  = bat;
            MapName    = mapname;

            foreach (var pe in bat.Players)
            {
                Users[pe.Name] = new UserBattleStatus(pe.Name, pe.LobbyUser, GenerateClientScriptPassword(pe.Name));
            }

            if (ModOptions == null)
            {
                ModOptions = new Dictionary <string, string>();
            }

            // proper way to send some extra start setup data
            if (bat.QueueType.Mode != AutohostMode.GameChickens)
            {
                SetCompetitiveModoptions();
            }
            ModOptions["MatchMakerType"] = bat.QueueType.Name;

            ValidateAndFillDetails();
        }
Пример #4
0
        public ForumListManager(ZkLobbyServer zkLobbyServer)
        {
            server = zkLobbyServer;
            CachePublicForumList();

            ZkDataContext.AfterEntityChange += ZkDataContextOnAfterEntityChange;
        }
Пример #5
0
 public BattleListUpdater(ZkLobbyServer server)
 {
     this.server    = server;
     timer          = new Timer(UpdateIntervalSeconds * 1000);
     timer.Elapsed += TimerOnElapsed;
     timer.Start();
 }
Пример #6
0
        public MatchMakerBattle(ZkLobbyServer server, MatchMaker.ProposedBattle bat) : base(server, null)
        {
            IsMatchMakerBattle = true;
            EngineVersion      = server.Engine;
            ModName            = server.Game;
            FounderName        = "MatchMaker #" + BattleID;
            Title      = "MatchMaker " + BattleID;
            Mode       = bat.QueueType.Mode;
            MaxPlayers = bat.Size;
            Prototype  = bat;

            foreach (var pe in bat.Players)
            {
                Users[pe.Name] = new UserBattleStatus(pe.Name, pe.LobbyUser, GenerateClientScriptPassword(pe.Name));
            }

            if (ModOptions == null)
            {
                ModOptions = new Dictionary <string, string>();
            }

            // hacky way to send some extra start setup data
            if (bat.QueueType.Mode != AutohostMode.GameChickens)
            {
                ModOptions["mutespec"] = "mute";
            }
            ModOptions["MatchMakerType"] = bat.QueueType.Name;

            ValidateAndFillDetails();
        }
Пример #7
0
        public ConnectedUser(ZkLobbyServer server, User user)
        {
            this.server = server;
            User        = user;

            LoadFriendsIgnores();
        }
Пример #8
0
        public ClientConnection(ITransport transport, ZkLobbyServer server)
        {
            this.server    = server;
            number         = Interlocked.Increment(ref server.ClientCounter);
            this.transport = transport;

            transport.ConnectAndRun(OnCommandReceived, OnConnected, OnConnectionClosed).ConfigureAwait(false);
        }
 public ZkServerTraceListener(ZkLobbyServer zkLobbyServer = null)
 {
     using (var db = new ZkDataContext())
     {
         var oldEntry = DateTime.UtcNow.AddDays(-14);
         db.Database.ExecuteSqlCommand("delete from LogEntries where Time < {0}", oldEntry);
     }
     this.ZkLobbyServer = zkLobbyServer;
 }
Пример #10
0
 public ChannelManager(ZkLobbyServer server)
 {
     this.server = server;
     using (var db = new ZkDataContext()) {
         factionChannels = new ConcurrentDictionary <string, Faction>(db.Factions.Where(x => !x.IsDeleted).ToDictionary(x => x.Shortcut, x => x));
         clanChannels    =
             new ConcurrentDictionary <string, Clan>(db.Clans.Where(x => !x.IsDeleted).ToList().ToDictionary(x => x.GetClanChannel(), x => x));
     }
 }
Пример #11
0
        public LoginChecker(ZkLobbyServer server, string geoipPath)
        {
            this.server = server;
            geoIP       = new DatabaseReader(Path.Combine(geoipPath, "GeoLite2-Country.mmdb"), FileAccessMode.Memory);

            var keys = RsaSignatures.GenerateKeys();

            ServerPubKey      = keys.PubKey;
            passwordDecryptor = new RsaSignatures(keys.PrivKey);
        }
Пример #12
0
        public ClientConnection(ITransport transport, ZkLobbyServer server)
        {
            this.server    = server;
            number         = Interlocked.Increment(ref server.ClientCounter);
            this.transport = transport;

            challengeToken = Guid.NewGuid().ToString(); // generate random challenge token

            transport.ConnectAndRun(OnCommandReceived, OnConnected, OnConnectionClosed).ConfigureAwait(false);
        }
        public ClientConnection(ITransport transport, ZkLobbyServer state)
        {
            this.state     = state;
            number         = Interlocked.Increment(ref state.ClientCounter);
            this.transport = transport;
            timer          = new Timer(GlobalConst.LobbyProtocolPingInterval * 1000);
            timer.Elapsed += TimerOnElapsed;

            transport.ConnectAndRun(OnCommandReceived, OnConnected, OnConnectionClosed);
        }
Пример #14
0
        public ChatRelay(ZkLobbyServer zkServer, string password, List <string> channels)
        {
            this.zkServer            = zkServer;
            this.springTas           = new TasClient(null, "ChatRelay", 0);
            this.channels            = channels;
            springTas.LoginAccepted += OnSpringTasLoginAccepted;
            springTas.Said          += OnSpringTasSaid;
            zkServer.Said           += OnZkServerSaid;

            SetupSpringTasConnection(password);
        }
Пример #15
0
        public MatchMaker(ZkLobbyServer server)
        {
            this.server = server;

            Func <Resource, bool> IsTeamsMap = x => (x.MapSupportLevel >= MapSupportLevel.MatchMaker) && (x.MapIsTeams != false) && (x.TypeID == ResourceType.Map) && x.MapIsSpecial != true;
            Func <Resource, bool> IsCoopMap  = x => (x.MapSupportLevel >= MapSupportLevel.MatchMaker) && (x.TypeID == ResourceType.Map) && x.MapIsSpecial != true;
            Func <Resource, bool> Is1v1Map   = x => (x.MapSupportLevel >= MapSupportLevel.MatchMaker) && (x.TypeID == ResourceType.Map) && x.MapIs1v1 == true && x.MapIsSpecial != true;

            queueConfigs.Add(new QueueConfig()
            {
                Name              = "Teams",
                Description       = "Play 2v2 to 4v4 with players of similar skill.",
                MinSize           = 4,
                MaxSize           = 8,
                MaxPartySize      = 4,
                EloCutOffExponent = 0.96,
                Mode              = AutohostMode.Teams,
                MapSelector       = IsTeamsMap,
            });

            queueConfigs.Add(new QueueConfig()
            {
                Name              = "Coop",
                Description       = "Play together, against AI or chickens",
                MinSize           = 2,
                MaxSize           = 5,
                MaxPartySize      = 5,
                EloCutOffExponent = 0,
                Mode              = AutohostMode.GameChickens,
                MapSelector       = IsCoopMap,
            });

            queueConfigs.Add(new QueueConfig()
            {
                Name              = "1v1",
                Description       = "1v1 with opponent of similar skill",
                MinSize           = 2,
                MaxSize           = 2,
                EloCutOffExponent = 0.975,
                MaxPartySize      = 1,
                Mode              = AutohostMode.Game1v1,
                MapSelector       = Is1v1Map,
            });

            UpdateQueues();

            timer           = new Timer(TimerSeconds * 1000);
            timer.AutoReset = true;
            timer.Elapsed  += TimerTick;
            timer.Start();

            queuesCounts = CountQueuedPeople(players.Values);
            ingameCounts = CountIngamePeople();
        }
Пример #16
0
        public PlanetWarsMatchMaker(ZkLobbyServer.ZkLobbyServer server)
        {
            this.server    = server;
            AttackOptions  = new List <AttackOption>();
            RunningBattles = new Dictionary <int, AttackOption>();


            var db = new ZkDataContext();

            var gal = db.Galaxies.FirstOrDefault(x => x.IsDefault);

            if (gal == null)
            {
                return;
            }


            factions = db.Factions.Where(x => !x.IsDeleted).ToList();

            PlanetWarsMatchMakerState dbState = null;

            if (gal.MatchMakerState != null)
            {
                try
                {
                    dbState = JsonConvert.DeserializeObject <PlanetWarsMatchMakerState>(gal.MatchMakerState);
                }
                catch (Exception ex)
                {
                    Trace.TraceError(ex.ToString());
                }
            }
            if (dbState != null)
            {
                AttackerSideCounter    = dbState.AttackerSideCounter;
                AttackOptions          = dbState.AttackOptions;
                Challenge              = dbState.Challenge;
                ChallengeTime          = dbState.ChallengeTime;
                AttackerSideChangeTime = dbState.AttackerSideChangeTime;
                RunningBattles         = dbState.RunningBattles;
            }
            else
            {
                AttackerSideCounter    = gal.AttackerSideCounter;
                AttackerSideChangeTime = gal.AttackerSideChangeTime ?? DateTime.UtcNow;
            }

            timer           = new Timer(1045);
            timer.AutoReset = true;
            timer.Elapsed  += TimerOnElapsed;
            timer.Start();
        }
Пример #17
0
        public ServerBattle(ZkLobbyServer server, string founder)
        {
            BattleID           = Interlocked.Increment(ref BattleCounter);
            FounderName        = founder;
            battleInstanceGuid = Guid.NewGuid().ToString();

            this.server         = server;
            pollTimer           = new Timer(PollTimeout * 1000);
            pollTimer.Enabled   = false;
            pollTimer.AutoReset = false;
            pollTimer.Elapsed  += pollTimer_Elapsed;
            SetupSpring();
            PickHostingPort();
        }
Пример #18
0
        public TourneyBattle(ZkLobbyServer server, TourneyPrototype prototype) : base(server, null)
        {
            this.Prototype     = prototype;
            IsMatchMakerBattle = false;
            EngineVersion      = server.Engine;
            ModName            = server.Game;
            FounderName        = $"Tourney #{BattleID}";
            Title                   = prototype.Title;
            Mode                    = prototype.TeamPlayers.Max(x => x.Count) == 1 ? AutohostMode.Game1v1 : AutohostMode.Teams;
            MaxPlayers              = prototype.TeamPlayers.Sum(x => x.Count);
            ModOptions              = prototype.ModOptions;
            ModOptions["mutespec"]  = "mute";
            ModOptions["mutelobby"] = "mute";


            ValidateAndFillDetails();
        }
Пример #19
0
        public ChatRelay(ZkLobbyServer zkServer, List <string> channels)
        {
            this.channels = channels;
            this.server   = zkServer;

            discord = new DiscordSocketClient();


            springRelay = new SpringRelaySource(channels);
            sources.Add(springRelay);
            zklsRelay = new ZklsRelaySource(zkServer);
            sources.Add(zklsRelay);

            discordZkRelay = new DiscordRelaySource(discord, DiscordZkServerID, SaySource.Discord);
            sources.Add(discordZkRelay);
            discordSpringRelay = new DiscordRelaySource(discord, DiscordSpringServerID, SaySource.DiscordSpring);
            sources.Add(discordSpringRelay);


            restrictedSources.Add(zklsRelay);
            restrictedSources.Add(discordZkRelay);

            var token = new Secrets().GetNightwatchDiscordToken();

            Task.Factory.StartNew(async() =>
            {
                try
                {
                    await discord.StartAsync();
                    await discord.LoginAsync(TokenType.Bot, token);
                }
                catch (Exception ex)
                {
                    Trace.TraceError("Error initializing discord connection/relay: {0}", ex);
                }
            }).Wait();


            foreach (var s in sources)
            {
                s.OnChatRelayMessage += OnAnySourceMessage;
            }

            timer = new Timer(TimerCallback, this, 1000, 2000);
        }
Пример #20
0
        public TourneyBattle(ZkLobbyServer server, TourneyPrototype prototype) : base(server, null)
        {
            this.Prototype     = prototype;
            IsMatchMakerBattle = false;
            ApplicableRating   = RatingCategory.MatchMaking;
            EngineVersion      = server.Engine;
            ModName            = server.Game;
            FounderName        = $"Tourney #{BattleID}";
            Title      = prototype.Title;
            Mode       = prototype.TeamPlayers.Max(x => x.Count) == 1 ? AutohostMode.Game1v1 : AutohostMode.None;
            MaxPlayers = prototype.TeamPlayers.Sum(x => x.Count);
            ModOptions = prototype.ModOptions;

            SetCompetitiveModoptions();
            ModOptions["allyreclaim"] = "1"; // even more competitive than the above

            ValidateAndFillDetails();
        }
Пример #21
0
        public PlanetWarsServerBattle(ZkLobbyServer server, PlanetWarsMatchMaker.AttackOption option) : base(server, null)
        {
            IsMatchMakerBattle = true;
            ApplicableRating   = RatingCategory.Planetwars;
            EngineVersion      = server.Engine;
            ModName            = server.Game;
            FounderName        = "PlanetWars #" + BattleID;
            Title      = "PlanetWars " + BattleID;
            Mode       = AutohostMode.Planetwars;
            MapName    = option.Map;
            MaxPlayers = option.TeamSize * 2;
            prototype  = option;

            foreach (var pe in option.Attackers)
            {
                Users[pe] = new UserBattleStatus(pe, server.ConnectedUsers.Get(pe)?.User, GenerateClientScriptPassword(pe))
                {
                    AllyNumber = 0
                }
            }
            ;
            foreach (var pe in option.Defenders)
            {
                Users[pe] = new UserBattleStatus(pe, server.ConnectedUsers.Get(pe)?.User, GenerateClientScriptPassword(pe))
                {
                    AllyNumber = 1
                }
            }
            ;

            if (ModOptions == null)
            {
                ModOptions = new Dictionary <string, string>();
            }

            SetCompetitiveModoptions();

            ValidateAndFillDetails();
        }
Пример #22
0
 public ZklsRelaySource(ZkLobbyServer server)
 {
     this.server  = server;
     server.Said += Said;
 }
 public ZkServerTraceListener(ZkLobbyServer zkLobbyServer = null)
 {
     this.ZkLobbyServer = zkLobbyServer;
 }
Пример #24
0
 public NewsListManager(ZkLobbyServer zkLobbyServer)
 {
     server = zkLobbyServer;
     CacheNewsList();
 }
Пример #25
0
 public ServerRunner(string geoIPpath, IPlanetwarsEventCreator creator)
 {
     ZkLobbyServer = new ZkLobbyServer(geoIPpath, creator);
 }
Пример #26
0
 static void SpecPlayerOnCondition(PlayerTeam player, Account account, string userMessage, ZkLobbyServer.ZkLobbyServer server)
 {
     player.IsSpectator = true;
     server.GhostPm(account.Name, userMessage);
 }
    /// <summary>
    /// Process planet wars turn
    /// </summary>
    /// <param name="mapName"></param>
    /// <param name="extraData"></param>
    /// <param name="db"></param>
    /// <param name="winnerSide">0 = first team wins, 1 = second team wins</param>
    /// <param name="players"></param>
    /// <param name="text"></param>
    /// <param name="sb"></param>
    ///
    public static void ResolveBattleOutcome(string mapName, List <string> extraData, ZkDataContext db, int?winnerSide, List <Account> players, List <Account> firstSidePlayers, StringBuilder text, SpringBattle sb, IPlanetwarsEventCreator eventCreator, ZkLobbyServer.ZkLobbyServer server)
    {
        if (extraData == null)
        {
            extraData = new List <string>();
        }
        Galaxy gal         = db.Galaxies.Single(x => x.IsDefault);
        Planet planet      = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        var    hqStructure = db.StructureTypes.FirstOrDefault(x => x.EffectDisconnectedMetalMalus != null || x.EffectDistanceMetalBonusMax != null);

        text.AppendFormat("Battle on {1}/PlanetWars/Planet/{0} has ended\n", planet.PlanetID, GlobalConst.BaseSiteUrl);

        bool firstFactionWon;
        bool wasFirstCcDestroyed  = false;
        bool wasSecondCcDestroyed = false;

        if (winnerSide != null)
        {
            if (winnerSide == 0)
            {
                firstFactionWon = true;
            }
            else
            {
                firstFactionWon = false;
            }

            wasFirstCcDestroyed  = extraData.Any(x => x.StartsWith("hqkilled,0"));
            wasSecondCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,1"));
        }
        else
        {
            text.AppendFormat("No winner on this battle!");
            Trace.TraceError("PW battle without a winner {0}", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        Faction firstFaction      = firstSidePlayers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        var     secondSidePlayers = players.Where(x => x.FactionID != firstFaction.FactionID && x.FactionID != null).ToList();
        Faction secondFaction     = null;

        if (secondSidePlayers.Any())
        {
            secondFaction = secondSidePlayers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        }

        Faction winningFaction;
        Faction losingFaction;
        bool    ccDestroyed = false;

        if (firstFactionWon)
        {
            winningFaction = firstFaction;
            losingFaction  = secondFaction;
            ccDestroyed    = wasFirstCcDestroyed;
        }
        else
        {
            winningFaction = secondFaction;
            losingFaction  = firstFaction;
            ccDestroyed    = wasSecondCcDestroyed;
        }

        if (winningFaction == null)
        {
            text.AppendFormat("Winning team had no players!");
            Trace.TraceError("PW battle where the winner had no players!", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        double baseInfluence   = GlobalConst.BaseInfluencePerBattle;
        double influenceChange = baseInfluence;
        double loserInfluence  = 0;
        double ipMultiplier    = 1;

        string influenceReport = "";
        string ipReason;

        bool reducedEnemyInfluence = false;
        bool flippedDominance      = false;
        bool planetConquered       = false;

        if (ccDestroyed)
        {
            ipMultiplier = GlobalConst.PlanetWarsLostCcMultiplier;
            ipReason     = "due to winning but losing Command Centre";
        }
        else
        {
            ipReason = "due to winning flawlessly";
        }


        influenceChange = (influenceChange) * ipMultiplier;
        if (influenceChange < 0)
        {
            influenceChange = 0;
        }
        influenceChange = Math.Floor(influenceChange * 100) / 100;

        PlanetFaction entry = planet.PlanetFactions.FirstOrDefault();

        if (entry == null)
        {
            entry = new PlanetFaction {
                Faction = winningFaction, Planet = planet,
            };
            planet.PlanetFactions.Add(entry);
        }
        // if non-winner currently dominates planet
        if (entry.Faction != winningFaction)
        {
            loserInfluence = entry.Influence;

            // if win is insufficient to change this
            if (loserInfluence >= influenceChange)
            {
                reducedEnemyInfluence = true;
                entry.Influence      -= influenceChange;
            }
            else // flip dominance
            {
                flippedDominance = true;
                planet.PlanetFactions.Remove(entry);
                entry = new PlanetFaction {
                    Faction = winningFaction, Planet = planet,
                };
                planet.PlanetFactions.Add(entry);
                entry.Influence += (influenceChange - loserInfluence);

                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }
        else // increase winner's existing dominance
        {
            if (entry.Influence < GlobalConst.PlanetWarsMaximumIP)
            {
                entry.Influence += influenceChange;
                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }

        string contestReport = "";
        int    newContested  = 0;

        if (planetConquered)
        {
            foreach (Link link in planet.LinksByPlanetID1.Union(planet.LinksByPlanetID2).ToList())
            {
                Planet        otherPlanet        = link.PlanetID1 == planet.PlanetID ? link.PlanetByPlanetID2 : link.PlanetByPlanetID1;
                PlanetFaction otherPlanetFaction = otherPlanet.PlanetFactions.FirstOrDefault();

                if (otherPlanetFaction.Faction != winningFaction && otherPlanetFaction.Influence > GlobalConst.BreakthroughInfluence)
                {
                    otherPlanetFaction.Influence = GlobalConst.BreakthroughInfluence;
                    if (newContested > 0)
                    {
                        contestReport += ", ";
                    }
                    contestReport += otherPlanet.Name;
                    newContested++;
                }
            }
        }
        if (newContested > 0)
        {
            contestReport = "Adjacent planets now contested: " + contestReport + ".";
        }

        // Check all planets to see if they are contested by a single faction
        string controlReport = "";
        int    newControlled = 0;

        foreach (Planet p1 in gal.Planets)
        {
            List <Faction> l = GetContestingFactions(p1);

            if (l.Count() == 1)
            {
                Faction       f      = l.FirstOrDefault(); // this faction should be made dominant if it is not already
                PlanetFaction cEntry = p1.PlanetFactions.FirstOrDefault();
                if (cEntry.Faction != f)
                {
                    p1.PlanetFactions.Remove(cEntry);
                    cEntry = new PlanetFaction {
                        Faction = f, Planet = p1, Influence = 0
                    };
                    p1.PlanetFactions.Add(cEntry);
                }
                if (cEntry.Influence != GlobalConst.PlanetWarsMaximumIP)
                {
                    cEntry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    if (newControlled > 0)
                    {
                        controlReport += ", ";
                    }
                    controlReport += p1.Name;
                    newControlled++;
                }
            }
        }
        if (newControlled > 0)
        {
            controlReport = "Planets automatically controlled: " + controlReport + ".";
        }

        // Update actual *control* of all planets
        PlanetWarsTurnHandler.SetPlanetOwners(eventCreator, db, sb);

        try
        {
            if (planetConquered)
            {
                influenceReport = String.Format("{0} conquered the planet, gained {1} influence ({2}% {3} of {4})",
                                                winningFaction.Shortcut,
                                                influenceChange,
                                                (int)(ipMultiplier * 100.0),
                                                ipReason,
                                                baseInfluence + " base");
            }
            else
            {
                if (reducedEnemyInfluence)
                {
                    influenceReport = String.Format("{0} reduced influence of {1} by {2} ({3}% {4} of {5}); {6} has {7} influence remaining on {8}",
                                                    winningFaction.Shortcut,
                                                    (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                    influenceChange,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    entry.Faction,
                                                    entry.Influence,
                                                    entry.Planet);
                }
                else
                {
                    if (flippedDominance)
                    {
                        influenceReport = String.Format("{0} took dominance from {1} and gained {2} influence ({3}% {4} of {5}); {6} now has {7} influence on {8}",
                                                        winningFaction.Shortcut,
                                                        (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                        influenceChange,
                                                        (int)(ipMultiplier * 100.0),
                                                        ipReason,
                                                        baseInfluence + " base",
                                                        entry.Faction,
                                                        entry.Influence,
                                                        entry.Planet);
                    }
                    else
                    {
                        influenceReport = String.Format("{0} gained {1} influence ({2}% {3} of {4}); {5} now has {6} influence on {7} ",
                                                        winningFaction.Shortcut,
                                                        influenceChange,
                                                        (int)(ipMultiplier * 100.0),
                                                        ipReason,
                                                        baseInfluence + " base",
                                                        entry.Faction,
                                                        entry.Influence,
                                                        entry.Planet);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // paranoia!
        try
        {
            var mainEvent = eventCreator.CreateEvent("{0} defeated {1} on {2} in {3}. {4}. {5} {6}",
                                                     winningFaction,
                                                     (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                     planet,
                                                     (sb == null) ? "no battle" : string.Format("B{0}", sb.SpringBattleID),
                                                     influenceReport,
                                                     contestReport,
                                                     controlReport
                                                     );
            db.Events.InsertOnSubmit(mainEvent);
            text.AppendLine(mainEvent.PlainText);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        db.SaveChanges();

        /*gal.Turn++;
         * db.SaveChanges();
         *
         * db = new ZkDataContext(); // is this needed - attempt to fix setplanetownersbeing buggy
         * SetPlanetOwners(eventCreator, db, sb != null ? db.SpringBattles.Find(sb.SpringBattleID) : null);
         * gal = db.Galaxies.Single(x => x.IsDefault);*/
    }
    public static void EndTurn(string mapName, List <string> extraData, ZkDataContext db, int?winNum, List <Account> players, StringBuilder text, SpringBattle sb, List <Account> attackers, IPlanetwarsEventCreator eventCreator, ZkLobbyServer.ZkLobbyServer server)
    {
        if (extraData == null)
        {
            extraData = new List <string>();
        }
        Galaxy gal         = db.Galaxies.Single(x => x.IsDefault);
        Planet planet      = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        var    hqStructure = db.StructureTypes.FirstOrDefault(x => x.EffectDisconnectedMetalMalus != null || x.EffectDistanceMetalBonusMax != null);

        text.AppendFormat("Battle on {1}/PlanetWars/Planet/{0} has ended\n", planet.PlanetID, GlobalConst.BaseSiteUrl);


        Faction attacker  = attackers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        var     defenders = players.Where(x => x.FactionID != attacker.FactionID && x.FactionID != null).ToList();
        bool    isAttackerWinner;
        bool    wasAttackerCcDestroyed = false;
        bool    wasDefenderCcDestroyed = false;

        if (winNum != null)
        {
            if (winNum == 0)
            {
                isAttackerWinner = true;
            }
            else
            {
                isAttackerWinner = false;
            }

            wasAttackerCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,0"));
            wasDefenderCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,1"));
        }
        else
        {
            text.AppendFormat("No winner on this battle!");
            Trace.TraceError("PW battle without a winner {0}", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        var evacuatedStructureTypeIDs = GetEvacuatedStructureTypes(extraData, db);

        string influenceReport = "";

        // distribute influence
        // save influence gains
        // give influence to main attackers
        double planetIpDefs = planet.GetEffectiveIpDefense();

        double  baseInfluence         = GlobalConst.BaseInfluencePerBattle;
        double  influenceChange       = baseInfluence;
        double  loserInfluence        = 0;
        Faction loserFaction          = attacker; // TODO make this less awful
        bool    reducedEnemyInfluence = false;
        bool    flippedDominance      = false;
        bool    planetConquered       = false;

        double shipBonus = planet.GetEffectiveShipIpBonus(attacker);

        double defenseBonus = -planetIpDefs;
        double techBonus    = attacker.GetFactionUnlocks().Count() * GlobalConst.InfluencePerTech;
        double ipMultiplier = 1;
        string ipReason;

        if (!isAttackerWinner)
        {
            if (wasDefenderCcDestroyed)
            {
                ipMultiplier = GlobalConst.PlanetWarsDefenderWinKillCcMultiplier;
                ipReason     = "from losing but killing defender's CC";
            }
            else
            {
                ipMultiplier = 0;
                ipReason     = "from losing horribly";
            }
        }
        else
        {
            if (wasAttackerCcDestroyed)
            {
                ipReason     = "from losing own CC";
                ipMultiplier = GlobalConst.PlanetWarsAttackerWinLoseCcMultiplier;
            }
            else
            {
                ipReason = "from winning flawlessly";
            }
        }

        influenceChange = (influenceChange + shipBonus + techBonus + defenseBonus) * ipMultiplier;
        if (influenceChange < 0)
        {
            influenceChange = 0;
        }
        influenceChange = Math.Floor(influenceChange * 100) / 100;

        // main winner influence
        // PlanetFaction entry = planet.PlanetFactions.FirstOrDefault(x => x.Faction == attacker);
        PlanetFaction entry = planet.PlanetFactions.FirstOrDefault();

        if (entry == null)
        {
            entry = new PlanetFaction {
                Faction = attacker, Planet = planet,
            };
            planet.PlanetFactions.Add(entry);
        }
        // if non-winner currently dominates planet
        if (entry.Faction != attacker)
        {
            loserFaction   = entry.Faction;
            loserInfluence = entry.Influence;

            // if win is insufficient to change this
            if (loserInfluence >= influenceChange)
            {
                reducedEnemyInfluence = true;
                entry.Influence      -= influenceChange;
            }
            else // flip dominance
            {
                flippedDominance = true;
                planet.PlanetFactions.Remove(entry);
                entry = new PlanetFaction {
                    Faction = attacker, Planet = planet,
                };
                planet.PlanetFactions.Add(entry);
                entry.Influence += (influenceChange - loserInfluence);

                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }
        else // increase winner's existing dominance
        {
            if (entry.Influence < GlobalConst.PlanetWarsMaximumIP)
            {
                entry.Influence += influenceChange;
                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }

        // TODO remove dependence on attacker

        if (planetConquered)
        {
            // Contest Adjacent Planets
            // GlobalConst.PlanetWarsBreakthroughIP
        }

        // Check all planets to see if they are contested by a single faction

        try
        {
            if (reducedEnemyInfluence)
            {
                influenceReport = String.Format("{0} reduced influence of {1} by {2} ({3}% {4} of {5}{6}{7}{8})",
                                                attacker.Shortcut,
                                                loserFaction.Shortcut,
                                                influenceChange,
                                                (int)(ipMultiplier * 100.0),
                                                ipReason,
                                                baseInfluence + " base",
                                                techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
            }
            else
            {
                if (flippedDominance)
                {
                    influenceReport = String.Format("{0} took dominance from {1} and gained {2} influence ({3}% {4} of {5}{6}{7}{8})",
                                                    attacker.Shortcut,
                                                    loserFaction.Shortcut,
                                                    influenceChange - loserInfluence,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                    shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                    defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
                }
                else
                {
                    influenceReport = String.Format("{0} gained {1} influence ({2}% {3} of {4}{5}{6}{7})",
                                                    attacker.Shortcut,
                                                    influenceChange,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                    shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                    defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
                }
            }
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // distribute metal
        var attackersTotalMetal = CalculateFactionMetalGain(planet, hqStructure, attacker, GlobalConst.PlanetWarsAttackerMetal, eventCreator, db, text, sb);
        var attackerMetal       = Math.Floor(attackersTotalMetal / attackers.Count);

        foreach (Account w in attackers)
        {
            w.ProduceMetal(attackerMetal);
            var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}",
                                              w,
                                              attackerMetal,
                                              sb);
            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }


        var defendersTotalMetal = planet.OwnerFactionID == null?Math.Floor(GlobalConst.PlanetWarsDefenderMetal) : CalculateFactionMetalGain(planet, hqStructure, planet.Faction, GlobalConst.PlanetWarsDefenderMetal, eventCreator, db, text, sb);

        if (defenders.Count > 0)
        {
            var defenderMetal = Math.Floor(defendersTotalMetal / defenders.Count);
            foreach (Account w in defenders)
            {
                w.ProduceMetal(defenderMetal);
                var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}", w, defenderMetal, sb);
                db.Events.InsertOnSubmit(ev);
                text.AppendLine(ev.PlainText);
            }
        }
        else
        {
            // planet had no defenders, give metal to owner's faction
            if (planet.OwnerFactionID != null)
            {
                planet.Faction.ProduceMetal(defendersTotalMetal);
                var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}", planet.Faction, defendersTotalMetal, sb);
                db.Events.InsertOnSubmit(ev);
            }
        }


        // remove attacker's dropships
        foreach (var pf in planet.PlanetFactions.Where(x => x.Faction == attacker))
        {
            pf.Dropships = 0;
        }


        // remove dropships staying for too long (return to faction pool)
        foreach (var pf in planet.PlanetFactions.Where(x => x.Faction != attacker && x.Dropships > 0 && x.DropshipsLastAdded != null))
        {
            if (DateTime.UtcNow.Subtract(pf.DropshipsLastAdded.Value).TotalMinutes > GlobalConst.PlanetWarsDropshipsStayForMinutes)
            {
                pf.Faction.ProduceDropships(pf.Dropships);
                pf.Dropships = 0;
            }
        }


        // add attack points
        foreach (Account acc in players)
        {
            int ap = acc.Faction == attacker ? GlobalConst.AttackPointsForVictory : GlobalConst.AttackPointsForDefeat;
            if (acc.Faction != null)
            {
                AccountPlanet apentry = planet.AccountPlanets.SingleOrDefault(x => x.AccountID == acc.AccountID);
                if (apentry == null)
                {
                    apentry = new AccountPlanet {
                        AccountID = acc.AccountID, PlanetID = planet.PlanetID
                    };
                    db.AccountPlanets.InsertOnSubmit(apentry);
                }

                apentry.AttackPoints += ap;
            }
            acc.PwAttackPoints += ap;
        }

        // paranoia!
        try
        {
            var mainEvent = eventCreator.CreateEvent("{0} attacked {1} {2} in {3} and {4}. {5}",
                                                     attacker,
                                                     planet.Faction,
                                                     planet,
                                                     sb,
                                                     isAttackerWinner ? "won" : "lost",
                                                     influenceReport
                                                     );
            db.Events.InsertOnSubmit(mainEvent);
            text.AppendLine(mainEvent.PlainText);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // destroy pw structures killed ingame
        if (!isAttackerWinner)
        {
            var handled = new List <string>();
            foreach (string line in extraData.Where(x => x.StartsWith("structurekilled", StringComparison.InvariantCulture)))
            {
                string[] data     = line.Substring(16).Split(',');
                string   unitName = data[0];
                if (handled.Contains(unitName))
                {
                    continue;
                }
                handled.Add(unitName);
                foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.IngameUnitName == unitName))
                {
                    if (s.StructureType.IsIngameDestructible)
                    {
                        s.ReactivateAfterDestruction();

                        var ev = eventCreator.CreateEvent("{0} has been disabled on {1} planet {2}. {3}", s.StructureType.Name, planet.Faction, planet, sb);
                        db.Events.InsertOnSubmit(ev);
                        text.AppendLine(ev.PlainText);
                    }
                }
            }
        }
        else
        {
            // attacker won disable all but evacuated
            foreach (var s in planet.PlanetStructures.Where(x => x.StructureType.IsIngameDestructible))
            {
                if (evacuatedStructureTypeIDs.Contains(s.StructureTypeID))
                {
                    var evSaved = eventCreator.CreateEvent("{0} structure {1} on planet {2} has been saved by evacuation. {3}",
                                                           planet.Faction,
                                                           s.StructureType,
                                                           planet,
                                                           sb);
                    db.Events.InsertOnSubmit(evSaved);
                    text.AppendLine(evSaved.PlainText);
                }
                else
                {
                    s.ReactivateAfterDestruction();
                }
            }
            // destroy structures by battle (usually defenses)
            foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.BattleDeletesThis).ToList())
            {
                if (evacuatedStructureTypeIDs.Contains(s.StructureTypeID))
                {
                    var evSaved = eventCreator.CreateEvent("{0} structure {1} on planet {2} has been saved by evacuation. {3}",
                                                           planet.Faction,
                                                           s.StructureType,
                                                           planet,
                                                           sb);
                    db.Events.InsertOnSubmit(evSaved);
                    text.AppendLine(evSaved.PlainText);
                }
                else
                {
                    planet.PlanetStructures.Remove(s);
                }
            }

            var ev = eventCreator.CreateEvent("All non-evacuated structures have been disabled on {0} planet {1}. {2}", planet.Faction, planet, sb);
            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }

        db.SaveChanges();

        // no longer used?
        //gal.DecayInfluence();
        //gal.SpreadInfluence();

        // process faction energies
        foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
        {
            fac.ProcessEnergy(gal.Turn);
        }

        // process production (incl. victory points)
        gal.ProcessProduction();
        db.SaveChanges();

        var vpFacs = db.Factions.Where(x => x.VictoryPoints > 0);

        if (vpFacs.Count() > 1)
        {
            foreach (var fac in vpFacs)
            {
                fac.VictoryPoints -= Math.Min(fac.VictoryPoints, GlobalConst.VictoryPointDecay);
            }
        }

        // delete one time activated structures
        gal.DeleteOneTimeActivated(eventCreator, db);
        db.SaveChanges();

        // process treaties
        foreach (var tr in db.FactionTreaties.Where(x => x.TreatyState == TreatyState.Accepted || x.TreatyState == TreatyState.Suspended))
        {
            var failedTradeFaction = tr.ProcessTrade(false);
            if (failedTradeFaction == null)
            {
                tr.TreatyState = TreatyState.Accepted;
                if (tr.TurnsTotal != null)
                {
                    tr.TurnsRemaining--;

                    if (tr.TurnsRemaining <= 0) // treaty expired
                    {
                        tr.TreatyState = TreatyState.Ended;
                        tr.FactionByAcceptingFactionID.ProduceMetal(tr.AcceptingFactionGuarantee ?? 0);
                        tr.FactionByProposingFactionID.ProduceMetal(tr.ProposingFactionGuarantee ?? 0);
                    }
                }
            }
            else
            {
                // failed to perform trade
                if (tr.TreatyUnableToTradeMode == TreatyUnableToTradeMode.Suspend)
                {
                    tr.TreatyState = TreatyState.Suspended;
                }
                else
                { // forced cancel
                    tr.CancelTreaty(failedTradeFaction);
                    db.Events.InsertOnSubmit(server.PlanetWarsEventCreator.CreateEvent("Treaty {0} between {1} and {2} cancelled by {3} because it failed to trade", tr, tr.FactionByProposingFactionID, tr.FactionByAcceptingFactionID, failedTradeFaction));
                }
            }
        }

        // burn extra energy
        foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
        {
            fac.ConvertExcessEnergyToMetal();
        }


        int?oldOwner = planet.OwnerAccountID;

        gal.Turn++;
        db.SaveChanges();

        db = new ZkDataContext(); // is this needed - attempt to fix setplanetownersbeing buggy
        SetPlanetOwners(eventCreator, db, sb != null ? db.SpringBattles.Find(sb.SpringBattleID) : null);
        gal = db.Galaxies.Single(x => x.IsDefault);

        var winByVictoryPoints = db.Factions.FirstOrDefault(x => !x.IsDeleted && x.VictoryPoints >= GlobalConst.PlanetWarsVictoryPointsToWin);

        if (winByVictoryPoints != null)
        {
            WinGame(db,
                    gal,
                    winByVictoryPoints,
                    eventCreator.CreateEvent("CONGRATULATIONS!! {0} has won the PlanetWars by getting enough victory points!", winByVictoryPoints));
            db.SaveChanges();
        }


        planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        if (planet.OwnerAccountID != oldOwner && planet.OwnerAccountID != null)
        {
            text.AppendFormat("Congratulations!! Planet {0} was conquered by {1} !!  {3}/PlanetWars/Planet/{2}\n",
                              planet.Name,
                              planet.Account.Name,
                              planet.PlanetID,
                              GlobalConst.BaseSiteUrl);
        }

        server.PublishUserProfilePlanetwarsPlayers();

        try
        {
            // store history
            foreach (Planet p in gal.Planets)
            {
                var hist = db.PlanetOwnerHistories.FirstOrDefault(x => x.PlanetID == p.PlanetID && x.Turn == gal.Turn);
                if (hist == null)
                {
                    hist = new PlanetOwnerHistory()
                    {
                        PlanetID = p.PlanetID, Turn = gal.Turn
                    };
                    db.PlanetOwnerHistories.Add(hist);
                }
                hist.OwnerAccountID = p.OwnerAccountID;
                hist.OwnerClanID    = p.OwnerAccountID != null ? p.Account.ClanID : null;
                hist.OwnerFactionID = p.OwnerFactionID;
            }

            db.SaveChanges();
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
            text.AppendLine("error saving history: " + ex);
        }

        //rotate map
        if (GlobalConst.RotatePWMaps)
        {
            db     = new ZkDataContext();
            gal    = db.Galaxies.Single(x => x.IsDefault);
            planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);
            var mapList = db.Resources.Where(x => x.MapPlanetWarsIcon != null && x.Planets.Where(p => p.GalaxyID == gal.GalaxyID).Count() == 0 && x.MapSupportLevel >= MapSupportLevel.Featured &&
                                             x.ResourceID != planet.MapResourceID && x.MapWaterLevel == planet.Resource.MapWaterLevel).ToList();
            if (mapList.Count > 0)
            {
                int      r          = new Random().Next(mapList.Count);
                int      resourceID = mapList[r].ResourceID;
                Resource newMap     = db.Resources.Single(x => x.ResourceID == resourceID);
                text.AppendLine(String.Format("Map cycler - {0} maps found, selected map {1} to replace map {2}", mapList.Count, newMap.InternalName, planet.Resource.InternalName));
                planet.Resource = newMap;
                gal.IsDirty     = true;
            }
            else
            {
                text.AppendLine("Map cycler - no maps found");
            }
            db.SaveChanges();
        }
    }
Пример #29
0
 public ServerRunner(string geoIPpath, IPlanetwarsEventCreator creator, ITopPlayerProvider topPlayerProvider)
 {
     ZkLobbyServer = new ZkLobbyServer(geoIPpath, creator, topPlayerProvider);
 }
Пример #30
0
 public LoginChecker(ZkLobbyServer server, string geoipPath)
 {
     this.server = server;
     geoIP       = new DatabaseReader(Path.Combine(geoipPath, "GeoLite2-Country.mmdb"), FileAccessMode.Memory);
 }