}; // 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); }); }
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); }
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(); }
public ForumListManager(ZkLobbyServer zkLobbyServer) { server = zkLobbyServer; CachePublicForumList(); ZkDataContext.AfterEntityChange += ZkDataContextOnAfterEntityChange; }
public BattleListUpdater(ZkLobbyServer server) { this.server = server; timer = new Timer(UpdateIntervalSeconds * 1000); timer.Elapsed += TimerOnElapsed; timer.Start(); }
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(); }
public ConnectedUser(ZkLobbyServer server, User user) { this.server = server; User = user; LoadFriendsIgnores(); }
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; }
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)); } }
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); }
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); }
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); }
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(); }
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(); }
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(); }
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(); }
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); }
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(); }
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(); }
public ZklsRelaySource(ZkLobbyServer server) { this.server = server; server.Said += Said; }
public ZkServerTraceListener(ZkLobbyServer zkLobbyServer = null) { this.ZkLobbyServer = zkLobbyServer; }
public NewsListManager(ZkLobbyServer zkLobbyServer) { server = zkLobbyServer; CacheNewsList(); }
public ServerRunner(string geoIPpath, IPlanetwarsEventCreator creator) { ZkLobbyServer = new ZkLobbyServer(geoIPpath, creator); }
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(); } }
public ServerRunner(string geoIPpath, IPlanetwarsEventCreator creator, ITopPlayerProvider topPlayerProvider) { ZkLobbyServer = new ZkLobbyServer(geoIPpath, creator, topPlayerProvider); }
public LoginChecker(ZkLobbyServer server, string geoipPath) { this.server = server; geoIP = new DatabaseReader(Path.Combine(geoipPath, "GeoLite2-Country.mmdb"), FileAccessMode.Memory); }