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; } }