public override async Task RunAsync(string parameters, CancellationToken cancellationToken) { var split = parameters.Split(' '); if (split.Length != 2) { this.Logger?.LogCommandOutput("{err}Invalid amount of parameters."); return; } var planet = await SaliensApi.GetPlanetAsync(split[0]); if (planet == null) { this.Logger?.LogCommandOutput("{err}Unknown planet id."); return; } if (!int.TryParse(split[1], out int zonePos)) { this.Logger?.LogCommandOutput("{err}Invalid zone position."); return; } if (zonePos >= planet.Zones.Count) { this.Logger?.LogCommandOutput("{err}Unknown zone position."); return; } this.Logger?.LogCommandOutput(planet.Zones[zonePos].ToConsoleBlock()); }
public override async Task RunAsync(string parameters, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(Program.Settings.Token)) { this.Logger?.LogCommandOutput("{{warn}}No token has been set."); return; } var playerInfo = await SaliensApi.GetPlayerInfoAsync(Program.Settings.Token); if (string.IsNullOrWhiteSpace(playerInfo?.ActivePlanet)) { this.Logger?.LogCommandOutput("No planet has been joined."); return; } if (string.IsNullOrWhiteSpace(playerInfo?.ActiveZoneGame)) { this.Logger?.LogCommandOutput("No zone has been joined."); return; } if (!int.TryParse(playerInfo.ActiveZonePosition, out int zonePos)) { this.Logger?.LogCommandOutput("Invalid zone."); return; } var planet = await SaliensApi.GetPlanetAsync(playerInfo.ActivePlanet); this.Logger?.LogCommandOutput(planet.Zones[zonePos].ToConsoleBlock()); }
public override async Task <string> Run(string parameters, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(Program.Saliens.Token)) { return("{{warn}}No token has been set."); } if (Program.Saliens.PlanetDetails == null) { return("No planet information available yet."); } var planet = Program.Saliens.JoinedPlanet; if (planet == null) { return("No planet has been joined."); } if (planet.Zones == null) { planet = await SaliensApi.GetPlanet(parameters); var index = Program.Saliens.PlanetDetails.FindIndex(p => p.Id == parameters); Program.Saliens.PlanetDetails[index] = planet; } return(planet.ToConsoleBlock()); }
protected override string FormatState(PlayerInfoResponse playerInfo, DiscordPresence presence) { bool hasActivePlanet = !string.IsNullOrWhiteSpace(playerInfo.ActivePlanet); bool hasActiveZone = !string.IsNullOrWhiteSpace(playerInfo.ActiveZonePosition); bool hasActiveBossZone = !string.IsNullOrWhiteSpace(playerInfo.ActiveBossGame); var state = "Inactive"; if (hasActivePlanet && (hasActiveZone || hasActiveBossZone)) { state = $"Planet {playerInfo.ActivePlanet} - "; if (hasActiveBossZone) { state += $"Boss Zone"; } else if (hasActiveZone) { state += $"Zone {playerInfo.ActiveZonePosition}"; } var planet = SaliensApi.GetPlanet(playerInfo.ActivePlanet); if (hasActiveZone && int.TryParse(playerInfo.ActiveZonePosition, out int zonePos)) { var zone = planet.Zones[zonePos]; if (zone != null) { state += $" ({zone.RealDifficulty.ToString().Substring(0, 1)})"; } } } else if (hasActivePlanet && !hasActiveZone) { state = $"Planet {playerInfo.ActivePlanet}"; } return(state); }
private async Task UpdatePlayerInfo(TimeSpan?forceCacheExpiryTime = null) { if (string.IsNullOrEmpty(this.Token)) { return; } this.PlayerInfo = await SaliensApi.GetPlayerInfoAsync(this.Token, forceCacheExpiryTime); this.State = BotState.Idle; if (!string.IsNullOrWhiteSpace(this.PlayerInfo.ActivePlanet)) { this.ActivePlanet = await SaliensApi.GetPlanetAsync(this.PlayerInfo.ActivePlanet, forceCacheExpiryTime); this.State = BotState.OnPlanet; if (int.TryParse(this.PlayerInfo.ActiveZonePosition, out int zonePosition)) { this.ActiveZone = this.ActivePlanet.Zones[zonePosition]; this.ActiveZoneStartDate = DateTime.Now - this.PlayerInfo.TimeInZone; this.State = BotState.InZone; } if (!string.IsNullOrWhiteSpace(this.PlayerInfo.ActiveBossGame)) { this.ActiveZone = this.ActivePlanet.Zones.FirstOrDefault(z => z.GameId == this.PlayerInfo.ActiveBossGame); this.ActiveZoneStartDate = DateTime.Now - this.PlayerInfo.TimeInZone; this.State = BotState.InBossZone; } } this.PresenceUpdateTrigger.SetSaliensPlayerState(this.PlayerInfo); }
private async Task JoinBossZone(int zonePosition) { for (int i = 0; i < 5; i++) { try { this.Logger?.LogMessage($"{{action}}Joining {{zone}}BOSS zone {zonePosition}{{action}}..."); await SaliensApi.JoinBossZoneAsync(this.Token, zonePosition); // States this.ActiveZone = this.ActivePlanet.Zones[zonePosition]; this.ActiveZoneStartDate = DateTime.Now; this.PlayerInfo.ActiveZoneGame = null; this.PlayerInfo.ActiveBossGame = this.ActiveZone.GameId; this.PlayerInfo.ActiveZonePosition = zonePosition.ToString(); this.PlayerInfo.TimeInZone = TimeSpan.FromSeconds(0); this.State = BotState.InBossZone; this.PresenceUpdateTrigger.SetSaliensPlayerState(this.PlayerInfo); return; } catch (SaliensApiException ex) { switch (ex.EResult) { case EResult.Fail: case EResult.Busy: case EResult.RateLimitExceeded: this.Logger?.LogMessage($"{{warn}}Failed to join boss zone: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; case EResult.Expired: case EResult.NoMatch: default: this.Logger?.LogMessage($"{{warn}}Failed to join boss zone: {ex.Message}"); ResetState(); throw; } } catch (WebException ex) { this.Logger?.LogMessage($"{{warn}}Failed to join boss zone: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; } } // States, only set when failed ResetState(); void ResetState() { this.State = BotState.OnPlanet; } }
private async Task JoinPlanet(string planetId) { for (int i = 0; i < 5; i++) { try { var planet = await SaliensApi.GetPlanetAsync(planetId); this.Logger?.LogMessage($"{{action}}Joining planet {{planet}}{planetId} ({planet.State.Name}){{action}}..."); await SaliensApi.JoinPlanetAsync(this.Token, planetId); // States this.ActivePlanet = planet; this.PlayerInfo.ActivePlanet = planetId; this.State = BotState.OnPlanet; this.PresenceUpdateTrigger.SetSaliensPlayerState(this.PlayerInfo); return; } catch (SaliensApiException ex) { switch (ex.EResult) { case EResult.Fail: case EResult.Busy: case EResult.RateLimitExceeded: this.Logger?.LogMessage($"{{warn}}Failed to join planet: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; case EResult.Expired: case EResult.NoMatch: default: this.Logger?.LogMessage($"{{warn}}Failed to join planet: {ex.Message}"); ResetState(); throw; } } catch (WebException ex) { this.Logger?.LogMessage($"{{warn}}Failed to join planet: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; } } // States, only set when failed ResetState(); void ResetState() { this.State = BotState.Idle; } }
public override async Task RunAsync(string parameters, CancellationToken cancellationToken) { var planet = await SaliensApi.GetPlanetAsync(parameters); if (planet == null) { this.Logger?.LogCommandOutput("{err}Unknown planet id."); return; } this.Logger?.LogCommandOutput(planet.ToConsoleBlock()); }
public override async Task RunAsync(string parameters, CancellationToken cancellationToken) { if (!string.IsNullOrWhiteSpace(parameters) && parameters != "all" && parameters != "live") { this.Logger?.LogCommandOutput("{err}Invalid parameter."); return; } var planetDetails = (await SaliensApi.GetPlanetsAsync()).Values.OrderBy(p => p.State.Priority); var active = planetDetails.Where(p => p.State.Running); var future = planetDetails.Where(p => !p.State.Active && !p.State.Captured); if (parameters == "all") { var captured = planetDetails.Where(p => p.State.Captured); this.Logger?.LogCommandOutput("Captured planets:"); await PrintPlanets(captured); this.Logger?.LogCommandOutput(""); this.Logger?.LogCommandOutput("Upcoming planets:"); await PrintPlanets(future); this.Logger?.LogCommandOutput(""); } this.Logger?.LogCommandOutput("Active planets:"); await PrintPlanets(active); this.Logger?.LogCommandOutput(""); if (string.IsNullOrWhiteSpace(parameters)) { this.Logger?.LogCommandOutput("Upcoming planets:"); await PrintPlanets(future.Take(2)); this.Logger?.LogCommandOutput(""); } this.Logger?.LogCommandOutput($"To get a list of all planets, use the command: {{command}}planets {{param}}all{{reset}}{Environment.NewLine}{Environment.NewLine}" + $"To see more information about a planet, use the command: {{command}}planet {{param}}<id>{{reset}}{Environment.NewLine}" + $"where {{param}}<id>{{reset}} is replaced with the planet id."); async Task PrintPlanets(IEnumerable <Planet> planets) { var results = await Task.WhenAll(planets.Select(p => p.Zones == null ? SaliensApi.GetPlanetAsync(p.Id) : Task.FromResult(p))); foreach (var planet in results) { this.Logger?.LogCommandOutput(planet.ToConsoleLine()); } } }
private async Task <List <Planet> > GetActivePlanets() { var planets = (await SaliensApi.GetPlanetsAsync()).Values .OrderBy(p => p.State.Priority); var activePlanets = await Task.WhenAll(planets .Where(p => p.State.Running) .Select(p => SaliensApi.GetPlanetAsync(p.Id))); // Get the next 2 future planets, if available var lastPlanetIndex = planets.ToList().FindIndex(p => p.Id == activePlanets.Last().Id); var lastPlanets = (await Task.WhenAll(planets.Skip(lastPlanetIndex + 1) .Take(2) .Select(p => SaliensApi.GetPlanetAsync(p.Id)))); return(activePlanets.Concat(lastPlanets).ToList()); }
public override async Task <string> Run(string parameters, CancellationToken cancellationToken) { var split = parameters.Split(' '); if (split.Length != 2) { return("{err}Invalid amount of parameters."); } if (Program.Saliens.PlanetDetails == null) { return("No planet information available yet."); } var planet = Program.Saliens.PlanetDetails.FirstOrDefault(p => p.Id == split[0]); if (planet == null) { return("{err}Unknown planet id."); } if (!int.TryParse(split[1], out int zonePos)) { return("{err}Invalid zone position."); } if (planet.Zones == null || planet.Zones.Count == 0) { var index = Program.Saliens.PlanetDetails.FindIndex(p => p.Id == planet.Id); planet = await SaliensApi.GetPlanet(planet.Id); Program.Saliens.PlanetDetails[index] = planet; } var zone = planet.Zones.FirstOrDefault(z => z.ZonePosition == zonePos); if (zone == null) { return("{err}Unknown zone position."); } return(zone.ToConsoleBlock()); }
public override async Task <string> Run(string parameters, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(Program.Saliens.Token)) { return("{warn}No token has been set."); } var info = await SaliensApi.GetPlayerInfo(Program.Settings.Token); Program.Saliens.PlayerInfo = info; return($"Level: {{level}}{info.Level}{{reset}}{Environment.NewLine}" + $"XP: {{xp}}{long.Parse(info.Score).ToString("#,##0")}{{reset}} (required for next level: {{reqxp}}{long.Parse(info.NextLevelScore).ToString("#,##0")}{{reset}}){Environment.NewLine}" + $"Clan: {info.ClanInfo.Name}{Environment.NewLine}" + $"Active planet: {{planet}}{info.ActivePlanet} {{reset}}{Environment.NewLine}" + $"Time spent on planet: {info.TimeOnPlanet.ToString()}{Environment.NewLine}" + $"Active zone: {{zone}}{info.ActiveZonePosition} ({info.ActiveZoneGame}){{reset}}{Environment.NewLine}" + $"Time spent in zone: {info.TimeInZone.TotalSeconds} seconds"); }
private async Task <List <Zone> > FindMostWantedZones() { var activeZones = (await SaliensApi.GetPlanetAsync(this.ActivePlanet.Id)).Zones.Where(z => !z.Captured); // Filter out blacklisted games var zones = activeZones.OrderBy(p => 0); if (this.Strategy.HasFlag(BotStrategy.FocusBosses)) { zones = zones.ThenByDescending(z => z.BossActive ? 1 : 0); } if (this.Strategy.HasFlag(BotStrategy.MostDifficultZonesFirst)) { zones = zones.ThenByDescending(z => z.RealDifficulty); } else if (this.Strategy.HasFlag(BotStrategy.LeastDifficultZonesFirst)) { zones = zones.ThenBy(z => z.RealDifficulty); } if (this.Strategy.HasFlag(BotStrategy.MostCompletedZonesFirst)) { zones = zones.ThenByDescending(z => z.CaptureProgress); } else if (this.Strategy.HasFlag(BotStrategy.LeastCompletedZonesFirst)) { zones = zones.ThenBy(z => z.CaptureProgress); } if (this.Strategy.HasFlag(BotStrategy.TopDown)) { zones = zones.ThenBy(z => z.ZonePosition); } else if (this.Strategy.HasFlag(BotStrategy.BottomUp)) { zones = zones.ThenByDescending(z => z.ZonePosition); } // Filter out blacklisted games return(zones .Where(z => !string.IsNullOrWhiteSpace(z.GameId) && !(this.BlacklistedGames.ContainsKey(z.GameId) && this.BlacklistedGames[z.GameId] > DateTime.Now)) .ToList()); }
public override async Task RunAsync(string parameters, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(parameters)) { // Show the current overridden planet id if (!string.IsNullOrWhiteSpace(Program.Settings.OverridePlanetId)) { this.Logger?.LogCommandOutput($"The planet id is currently overridden to: {{value}}{Program.Settings.OverridePlanetId}"); } else { this.Logger?.LogCommandOutput("You have currently no planet id override set."); } this.Logger?.LogCommandOutput("You can override the planet id by appending the planet id to this command: {command}overrideplanetid {param}<id>"); this.Logger?.LogCommandOutput("where {param}<id> is replaced with the planet id, or {param}remove{reset} if you wish to remove it."); } else { // Set the overridden planet id if (parameters == "remove") { Program.Settings.OverridePlanetId.Value = null; this.Logger?.LogCommandOutput("Your planet id override has been removed."); } else { var planet = await SaliensApi.GetPlanetAsync(parameters); if (planet == null) { this.Logger?.LogCommandOutput("{err}Invalid planet id. Check the planets for ids."); } else { Program.Settings.OverridePlanetId.Value = parameters; this.Logger?.LogCommandOutput("Your planet id override has been saved."); } } } }
public override async Task RunAsync(string parameters, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(parameters)) { // Show the current token if (!string.IsNullOrWhiteSpace(Program.Settings.Token)) { this.Logger?.LogCommandOutput($"Your token is currently set to: {{value}}{Program.Settings.Token}{{reset}}."); } else { this.Logger?.LogCommandOutput("You have currently no token set."); } this.Logger?.LogCommandOutput("You can change the token by appending the token to this command: {command}token {param}<your_token>"); this.Logger?.LogCommandOutput("where {param}<your_token>{reset} is replaced with your token."); } else { // Set the token try { var playerInfo = await SaliensApi.GetPlayerInfoAsync(parameters); if (playerInfo != null) { Program.Settings.Token.Value = parameters; this.Logger?.LogCommandOutput("Your token has been saved."); } else { this.Logger?.LogCommandOutput("{{err}}Invalid token."); } } catch (WebException ex) { this.Logger?.LogCommandOutput($"{{err}}Invalid response. {ex.Message}"); } } }
public override async Task <string> Run(string parameters, CancellationToken cancellationToken) { if (Program.Saliens.PlanetDetails == null) { return("No planet information available yet."); } var planet = Program.Saliens.PlanetDetails.FirstOrDefault(p => p.Id == parameters); if (planet == null) { return("{err}Unknown planet id."); } if (planet.Zones == null || planet.Zones.Count == 0) { // Zones not available yet, request them manually var index = Program.Saliens.PlanetDetails.FindIndex(p => p.Id == planet.Id); planet = await SaliensApi.GetPlanet(planet.Id); Program.Saliens.PlanetDetails[index] = planet; } var active = planet.Zones.Where(z => !z.Captured); var captured = planet.Zones.Where(z => z.Captured); return($"Zones on {{planet}}planet {planet.Id} ({planet.State.Name}){{reset}}{Environment.NewLine}" + $"Captured zones:{Environment.NewLine}" + $"{string.Join(Environment.NewLine, captured.Select(z => z.ToConsoleLine()))}{Environment.NewLine}{Environment.NewLine}" + $"Active zones:{Environment.NewLine}" + $"{string.Join(Environment.NewLine, active.Select(z => z.ToConsoleLine()))}{Environment.NewLine}{Environment.NewLine}" + $"To see more information about a zone, use the command: {{command}}zone {{param}}<planet_id> <zone_pos>{{reset}}{Environment.NewLine}" + $"where {{param}}<planet_id>{{reset}} is replaced with the planet id,{Environment.NewLine}" + $"and {{param}}<zone_pos>{{reset}} is replaced with the zone position"); }
public override async Task <string> Run(string parameters, CancellationToken cancellationToken) { if (Program.Saliens.PlanetDetails == null) { return("No planet information available yet."); } var planet = Program.Saliens.PlanetDetails.FirstOrDefault(p => p.Id == parameters); if (planet == null) { return("{err}Unknown planet id."); } if (planet.Zones == null) { planet = await SaliensApi.GetPlanet(parameters); var index = Program.Saliens.PlanetDetails.FindIndex(p => p.Id == parameters); Program.Saliens.PlanetDetails[index] = planet; } return(planet.ToConsoleBlock()); }
private void PresenceLoopThread() { while (!this.cancelSource.Token.IsCancellationRequested) { if (string.IsNullOrWhiteSpace(this.ApiToken)) { return; } TimeSpan timeToWait = TimeSpan.FromSeconds(fallbackRefreshRate); try { var playerInfo = SaliensApi.GetPlayerInfo(this.ApiToken); this.presence.Logger?.LogMessage($"Updating Discord presence with {playerInfo.Score} XP"); this.presence.SetSaliensPlayerState(playerInfo); if (!string.IsNullOrWhiteSpace(playerInfo.ActiveZonePosition)) { if (playerInfo.TimeInZone < TimeSpan.FromSeconds(110)) { timeToWait = TimeSpan.FromSeconds(110) - playerInfo.TimeInZone; } else if (playerInfo.TimeInZone < TimeSpan.FromSeconds(120)) { timeToWait = TimeSpan.FromSeconds(120) - playerInfo.TimeInZone; } timeToWait += TimeSpan.FromSeconds(5); } } catch (Exception ex) { this.presence.Logger?.LogException(ex); } this.cancelSource.Token.WaitHandle.WaitOne(timeToWait); } }
public override async Task RunAsync(string parameters, CancellationToken cancellationToken) { var planet = await SaliensApi.GetPlanetAsync(parameters); if (planet == null) { this.Logger?.LogCommandOutput("{err}Unknown planet id."); return; } var active = planet.Zones.Where(z => !z.Captured); var captured = planet.Zones.Where(z => z.Captured); this.Logger?.LogCommandOutput($"Zones on {{planet}}planet {planet.Id} ({planet.State.Name}){{reset}}{Environment.NewLine}" + $"Captured zones:{Environment.NewLine}" + $"{string.Join(Environment.NewLine, captured.Select(z => z.ToConsoleLine()))}{Environment.NewLine}{Environment.NewLine}" + $"Active zones:{Environment.NewLine}" + $"{string.Join(Environment.NewLine, active.Select(z => z.ToConsoleLine()))}{Environment.NewLine}{Environment.NewLine}" + $"To see more information about a zone, use the command: {{command}}zone {{param}}<planet_id> <zone_pos>{{reset}}{Environment.NewLine}" + $"where {{param}}<planet_id>{{reset}} is replaced with the planet id,{Environment.NewLine}" + $"and {{param}}<zone_pos>{{reset}} is replaced with the zone position"); }
public override async Task <string> Run(string parameters, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(parameters)) { // Show the current token if (!string.IsNullOrWhiteSpace(Program.Saliens.Token)) { this.WriteConsole($"Your token is currently set to: {{value}}{Program.Saliens.Token}{{reset}}."); } else { this.WriteConsole("You have currently no token set."); } this.WriteConsole("You can change the token by appending the token to this command: {command}token {param}<your_token>"); this.WriteConsole("where {param}<your_token>{reset} is replaced with your token."); return(""); } else { // Set the token try { Program.Saliens.PlayerInfo = await SaliensApi.GetPlayerInfo(parameters); Program.Settings.Token = parameters; Program.Settings.Save(); return("Your token has been saved."); } catch (WebException ex) { return($"{{err}}Invalid response. {ex.Message}"); } } }
public async Task <BossLevelState> ReportBossDamage(int startLevel, long startXp, bool useHealAbility, int damageToBoss, int damageTaken) { for (int i = 0; i < 5; i++) { try { var message = $"{{action}}Reporting boss damage {{value}}+{damageToBoss.ToString("#,##0")}"; if (damageTaken > 0) { message += $"{{action}}, {{negvalue}}-{damageTaken.ToString("#,##0")}"; } if (useHealAbility) { message += $"{{action}}, {{value}}+Heal"; } message += $"{{action}}..."; this.Logger?.LogMessage(message); var response = await SaliensApi.ReportBossDamageAsync(this.Token, useHealAbility, damageToBoss, damageTaken); if (response.BossStatus == null) { return(BossLevelState.WaitingForPlayers); } BossPlayer currentPlayer = null; var bossHpColor = MathUtils.ScaleColor(response.BossStatus.BossMaxHp - response.BossStatus.BossHp, response.BossStatus.BossMaxHp, new[] { "{svlow}", "{slow}", "{smed}", "{shigh}", "{svhigh}" }); this.Logger?.LogMessage($"{bossHpColor}Boss HP: {response.BossStatus.BossHp.ToString("#,##0")}/{response.BossStatus.BossMaxHp.ToString("#,##0")}{{reset}} - {{lasers}}{response.NumLaserUses} lasers{{reset}} - {{heals}}{response.NumTeamHeals} heals"); foreach (var player in response.BossStatus.BossPlayers.OrderBy(p => p.Name)) { var playerStartLevel = player.LevelOnJoin; long.TryParse(player.ScoreOnJoin, out long playerStartXp); var isCurrentPlayer = playerStartLevel == startLevel && playerStartXp == startXp; if (isCurrentPlayer) { currentPlayer = player; } var playerColor = isCurrentPlayer ? "{player}" : "{reset}"; var hpColor = MathUtils.ScaleColor(player.MaxHp - player.Hp, player.MaxHp, new[] { "{svlow}", "{slow}", "{smed}", "{shigh}", "{svhigh}" }); this.Logger?.LogMessage($"{playerColor}{(player.Name.Length > 16 ? player.Name.Substring(0, 16) : player.Name).PadLeft(16)}: " + $"{hpColor}HP {player.Hp.ToString("#,##0").PadLeft(7)}/{player.MaxHp.ToString("#,##0").PadLeft(7)}{playerColor} - " + $"XP {player.XpEarned.ToString("#,##0").PadLeft(9)}/{(playerStartXp + player.XpEarned).ToString("#,##0").PadLeft(12)}"); } if (response.GameOver && currentPlayer != null && long.TryParse(this.PlayerInfo.Score, out long oldScore)) { // States this.PlayerInfo.Score = (oldScore + currentPlayer.XpEarned).ToString(); this.PlayerInfo.Level = currentPlayer.NewLevel; this.PlayerInfo.NextLevelScore = currentPlayer.NextLevelScore; } return(response.GameOver ? BossLevelState.GameOver : BossLevelState.Active); } catch (SaliensApiException ex) { switch (ex.EResult) { case EResult.Fail: case EResult.Busy: case EResult.RateLimitExceeded: this.Logger?.LogMessage($"{{warn}}Failed to report boss damage: {ex.Message} - Giving it a second ({i + 1}/5)..."); await Task.Delay(1000); continue; case EResult.Expired: case EResult.NoMatch: default: this.Logger?.LogMessage($"{{warn}}Failed to report boss damage: {ex.Message}"); ResetState(); throw; } } catch (WebException ex) { this.Logger?.LogMessage($"{{warn}}Failed to report boss damage: {ex.Message} - Giving it a second ({i + 1}/5)..."); await Task.Delay(1000); continue; } } // States, only set when failed ResetState(); void ResetState() { this.ActiveZone = null; this.PlayerInfo.ActiveBossGame = null; this.PlayerInfo.ActiveZonePosition = null; this.State = BotState.ForcedZoneLeave; } return(BossLevelState.Error); }
public async Task ReportScore(int score) { for (int i = 0; i < 5; i++) { try { this.Logger?.LogMessage($"{{action}}Reporting score {{xp}}{score.ToString("#,##0")}{{action}}..."); var stopwatch = new Stopwatch(); stopwatch.Start(); var response = await SaliensApi.ReportScoreAsync(this.Token, score); stopwatch.Stop(); // Only change the network delay if the last delay was lower // Don't want to be too eager for an occasional spike if (this.reportScoreNetworkDelay.TotalMilliseconds == 0 || stopwatch.Elapsed < this.reportScoreNetworkDelay) { this.reportScoreNetworkDelay = stopwatch.Elapsed; } if (!string.IsNullOrWhiteSpace(response.NewScore)) { if (!string.IsNullOrWhiteSpace(response.NextLevelScore)) { this.Logger?.LogMessage($"XP: {{oldxp}}{long.Parse(response.OldScore).ToString("#,##0")}{{reset}} -> {{xp}}{long.Parse(response.NewScore).ToString("#,##0")}{{reset}} (next level at {{reqxp}}{long.Parse(response.NextLevelScore).ToString("#,##0")}{{reset}})"); } else { this.Logger?.LogMessage($"XP: {{oldxp}}{long.Parse(response.OldScore).ToString("#,##0")}{{reset}} -> {{xp}}{long.Parse(response.NewScore).ToString("#,##0")}"); } } if (response.NewLevel != response.OldLevel) { this.Logger?.LogMessage($"New level: {{oldlevel}}{response.OldLevel}{{reset}} -> {{level}}{response.NewLevel}{{reset}}"); } // States this.PlayerInfo.Score = response.NewScore; this.PlayerInfo.Level = response.NewLevel; this.PlayerInfo.NextLevelScore = response.NextLevelScore; this.ActiveZone = null; this.PlayerInfo.ActiveZoneGame = null; this.PlayerInfo.ActiveZonePosition = null; this.PlayerInfo.TimeInZone = TimeSpan.FromSeconds(0); this.State = BotState.OnPlanet; return; } catch (SaliensApiException ex) { switch (ex.EResult) { case EResult.Fail: case EResult.Busy: case EResult.RateLimitExceeded: case EResult.TimeIsOutOfSync: if (ex.EResult == EResult.TimeIsOutOfSync) { // Decrease the delay with a small amount this.reportScoreNetworkDelay -= TimeSpan.FromMilliseconds(25); } this.Logger?.LogMessage($"{{warn}}Failed to submit score: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; case EResult.Expired: case EResult.NoMatch: default: this.Logger?.LogMessage($"{{warn}}Failed to submit score: {ex.Message}"); ResetState(); throw; } } catch (WebException ex) { this.Logger?.LogMessage($"{{warn}}Failed to submit score: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; } } // States, only set when failed ResetState(); void ResetState() { this.ActiveZone = null; this.PlayerInfo.ActiveZoneGame = null; this.PlayerInfo.ActiveZonePosition = null; this.State = BotState.ForcedZoneLeave; } }
private async Task JoinZone(int zonePosition) { for (int i = 0; i < 5; i++) { try { this.Logger?.LogMessage($"{{action}}Joining {{zone}}zone {zonePosition}{{action}}..."); var stopwatch = new Stopwatch(); stopwatch.Start(); await SaliensApi.JoinZoneAsync(this.Token, zonePosition); stopwatch.Stop(); var startDate = DateTime.Now; // If the request took too long, resynchronize the start date if (stopwatch.Elapsed > TimeSpan.FromSeconds(1)) { var playerInfo = await SaliensApi.GetPlayerInfoAsync(this.Token, TimeSpan.FromSeconds(0)); var diff = (startDate - (DateTime.Now - playerInfo.TimeInZone)); if (diff > TimeSpan.FromSeconds(0)) { this.Logger?.LogMessage($"{{action}}Recalibrated zone join time with {{value}}{diff.Negate().TotalSeconds.ToString("0.###")} seconds"); startDate = DateTime.Now - playerInfo.TimeInZone; } } // States this.ActiveZone = this.ActivePlanet.Zones[zonePosition]; this.ActiveZoneStartDate = startDate; this.PlayerInfo.ActiveZoneGame = this.ActiveZone.GameId; this.PlayerInfo.ActiveZonePosition = zonePosition.ToString(); this.PlayerInfo.TimeInZone = TimeSpan.FromSeconds(0); this.State = BotState.InZone; this.PresenceUpdateTrigger.SetSaliensPlayerState(this.PlayerInfo); return; } catch (SaliensApiException ex) { switch (ex.EResult) { case EResult.Fail: case EResult.Busy: case EResult.RateLimitExceeded: this.Logger?.LogMessage($"{{warn}}Failed to join zone: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; case EResult.Expired: case EResult.NoMatch: default: this.Logger?.LogMessage($"{{warn}}Failed to join zone: {ex.Message}"); ResetState(); throw; } } catch (WebException ex) { this.Logger?.LogMessage($"{{warn}}Failed to join zone: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; } } // States, only set when failed ResetState(); void ResetState() { this.State = BotState.OnPlanet; } }
public override async Task <string> Run(string parameters, CancellationToken cancellationToken) { if (!string.IsNullOrWhiteSpace(parameters) && parameters != "all" && parameters != "live") { return("{err}Invalid parameter."); } if (Program.Saliens.PlanetDetails == null) { return("No planet information available yet."); } var planetDetails = Program.Saliens.PlanetDetails.OrderBy(p => p.State.Priority); var active = planetDetails.Where(p => p.State.Running); var future = planetDetails.Where(p => !p.State.Active && !p.State.Captured); if (parameters == "all" || parameters == "live") { var captured = planetDetails.Where(p => p.State.Captured); this.WriteConsole("Captured planets:"); await PrintPlanets(captured); this.WriteConsole(""); this.WriteConsole("Upcoming planets:"); await PrintPlanets(future); this.WriteConsole(""); } this.WriteConsole("Active planets:"); await PrintPlanets(active); this.WriteConsole(""); if (string.IsNullOrWhiteSpace(parameters)) { this.WriteConsole("Upcoming planets:"); await PrintPlanets(future.Take(1)); this.WriteConsole(""); } return($"To get a list of all planets, use the command: {{command}}planets {{param}}all{{reset}}{Environment.NewLine}" + $"To fully refresh the list of planets, use the command: {{command}}planets {{param}}live{{reset}}{Environment.NewLine}{Environment.NewLine}" + $"To see more information about a planet, use the command: {{command}}planet {{param}}<id>{{reset}}{Environment.NewLine}" + $"where {{param}}<id>{{reset}} is replaced with the planet id."); async Task PrintPlanets(IEnumerable <Planet> planets) { var tasks = planets.Select(p => parameters == "live" || p.Zones == null ? SaliensApi.GetPlanet(p.Id) : Task.FromResult(p)); foreach (var task in tasks) { var planet = await task; var i = Program.Saliens.PlanetDetails.FindIndex(p => p.Id == planet.Id); Program.Saliens.PlanetDetails[i] = planet; this.WriteConsole(planet.ToConsoleLine()); } } }
private async Task LeaveGame(string gameId) { for (int i = 0; i < 5; i++) { try { await SaliensApi.LeaveGameAsync(this.Token, gameId); if (this.HasActivePlanet && this.ActivePlanet.Id == gameId) { this.Logger?.LogMessage($"{{action}}Leaving planet {{planet}}{gameId} ({this.ActivePlanet.State.Name}){{action}}..."); // States this.ActivePlanet = null; this.PlayerInfo.ActivePlanet = null; this.PlayerInfo.TimeOnPlanet = TimeSpan.FromSeconds(0); this.State = BotState.Idle; } else if (this.HasActiveZone && this.ActiveZone.GameId == gameId) { this.Logger?.LogMessage($"{{action}}Leaving zone {{zone}}{this.ActiveZone.ZonePosition} ({gameId}){{action}}..."); // States this.ActiveZone = null; this.PlayerInfo.ActiveBossGame = null; this.PlayerInfo.ActiveZoneGame = null; this.PlayerInfo.ActiveZonePosition = null; this.PlayerInfo.TimeInZone = TimeSpan.FromSeconds(0); this.State = BotState.OnPlanet; } this.PresenceUpdateTrigger.SetSaliensPlayerState(this.PlayerInfo); return; } catch (SaliensApiException ex) { switch (ex.EResult) { case EResult.Fail: case EResult.Busy: case EResult.RateLimitExceeded: this.Logger?.LogMessage($"{{warn}}Failed to leave game: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; case EResult.Expired: case EResult.NoMatch: default: this.Logger?.LogMessage($"{{warn}}Failed to leave game: {ex.Message}"); ResetState(); throw; } } catch (WebException ex) { this.Logger?.LogMessage($"{{warn}}Failed to leave game: {ex.Message} - Giving it a few seconds ({i + 1}/5)..."); await Task.Delay(2000); continue; } } // States, only set when failed ResetState(); void ResetState() { this.State = BotState.Invalid; // Just reset } }
private async Task <List <Planet> > FindMostWantedPlanets() { var mostWantedPlanets = new List <Planet>(); var activePlanets = (await SaliensApi.GetPlanetsWithZonesAsync(true)).Values; // Overridden planet if (!string.IsNullOrWhiteSpace(this.OverridePlanetId)) { try { var planet = await SaliensApi.GetPlanetAsync(this.OverridePlanetId); if (planet.State.Running) { mostWantedPlanets.Add(planet); } } catch (SaliensApiException ex) { switch (ex.EResult) { case EResult.InvalidParam: case EResult.Expired: case EResult.NoMatch: case EResult.ValueOutOfRange: Program.Settings.OverridePlanetId.Value = null; break; default: throw; } } } // Force current joined planet if FocusCurrentPlanet is selected if (this.Strategy.HasFlag(BotStrategy.FocusCurrentPlanet) && this.HasActivePlanet) { var planet = await SaliensApi.GetPlanetAsync(this.ActivePlanet.Id); if (planet.State.Running) { mostWantedPlanets.Add(planet); } } if (this.Strategy.HasFlag(BotStrategy.FocusRandomPlanet)) { mostWantedPlanets.AddRange(activePlanets .Where(p => !mostWantedPlanets.Any(mp => mp.Id == p.Id)) .ToList() .Shuffle()); } else { // As of 26th June, the planet difficulty is always low, so let's skip it for now var planets = activePlanets.OrderBy(p => 0); if (this.Strategy.HasFlag(BotStrategy.FocusBosses)) { planets = planets.ThenByDescending(p => p.Zones.Any(z => z.BossActive) ? 1 : 0); } if (this.Strategy.HasFlag(BotStrategy.MostDifficultPlanetsFirst)) { planets = planets //.ThenByDescending(p => (int)p.State.Difficulty) .ThenByDescending(p => p.MaxFreeZonesDifficulty) .ThenByDescending(p => p.WeightedAverageFreeZonesDifficulty); } else if (this.Strategy.HasFlag(BotStrategy.LeastDifficultPlanetsFirst)) { planets = planets //.ThenBy(p => (int)p.State.Difficulty) .ThenBy(p => p.MaxFreeZonesDifficulty) .ThenBy(p => p.WeightedAverageFreeZonesDifficulty); } if (this.Strategy.HasFlag(BotStrategy.MostCompletedPlanetsFirst)) { planets = planets.ThenByDescending(p => p.State.CaptureProgress); } else if (this.Strategy.HasFlag(BotStrategy.LeastCompletedPlanetsFirst)) { planets = planets.ThenBy(p => p.State.CaptureProgress); } if (this.Strategy.HasFlag(BotStrategy.TopDown)) { planets = planets.ThenBy(p => p.Id); } else if (this.Strategy.HasFlag(BotStrategy.BottomUp)) { planets = planets.ThenByDescending(p => p.Id); } mostWantedPlanets.AddRange(planets); } // Filter out blacklisted games return(mostWantedPlanets .Where(p => !(this.BlacklistedGames.ContainsKey(p.Id) && this.BlacklistedGames[p.Id] > DateTime.Now)) .ToList()); }
private async Task Loop() { this.BotActivated?.Invoke(this, null); while (!this.cancelSource.Token.IsCancellationRequested) { try { this.Logger?.LogMessage($"{{verb}}State: {this.State}"); switch (this.State) { case BotState.Idle: await this.DoIdle(); break; case BotState.Resume: await this.DoResume(); break; case BotState.OnPlanet: await this.DoOnPlanet(); break; case BotState.InZone: await this.DoInZone(); break; case BotState.InZoneEnd: await this.DoInZoneEnd(); break; case BotState.InBossZone: await this.DoInBossZone(); break; case BotState.ForcedZoneLeave: await this.DoForcedZoneLeave(); break; case BotState.Invalid: default: await this.DoInvalid(); break; } } catch (OperationCanceledException) { } catch (SaliensApiException ex) { // Update states this.Logger?.LogMessage($"{{action}}Updating states..."); await this.UpdatePlayerInfo(TimeSpan.FromSeconds(5)); await SaliensApi.GetPlanetsWithZonesAsync(true, TimeSpan.FromSeconds(5)); switch (ex.EResult) { case EResult.Expired: case EResult.NoMatch: if (this.State == BotState.InZone || this.State == BotState.InZoneEnd) { this.State = BotState.ForcedZoneLeave; } break; case EResult.InvalidState: default: this.State = BotState.Invalid; break; } } catch (Exception ex) { this.Logger?.LogException(ex); this.State = BotState.Invalid; } } this.BotDeactivated?.Invoke(this, null); }