public static async Task Teleport(ISession session, CancellationToken cancellationToken, Random random) { bool ShownSoftBanMessage = false; int stopsToHit = 20; //We should return to the main loop after some point, might as well limit this. //Not sure where else we could put this? Configs maybe if we incorporate //deciding how many pokestops in a row we want to hit before doing things like recycling? //might increase xp/hr not stopping every 5 stops. - Pocket //TODO: run through this with a fine-tooth comb and optimize it. var pokestopList = await GetPokeStops(session); for (int stopsHit = 0; stopsHit < stopsToHit; stopsHit++) { session.Runtime.BreakOutOfPathing = false; if (pokestopList.Count > 0) { //start at 0 ends with 19 = 20 for the leechers{ cancellationToken.ThrowIfCancellationRequested(); var distanceFromStart = LocationUtils.CalculateDistanceInMeters( session.Client.InitialLatitude, session.Client.InitialLongitude, session.Client.CurrentLatitude, session.Client.CurrentLongitude); // Edge case for when the client somehow ends up outside the defined radius if (session.LogicSettings.MaxTravelDistanceInMeters != 0 && distanceFromStart > session.LogicSettings.MaxTravelDistanceInMeters) { session.EventDispatcher.Send(new WarnEvent() { Message = session.Translation.GetTranslation(TranslationString.FarmPokestopsOutsideRadius, distanceFromStart) }); await Task.Delay(1000, cancellationToken); await session.Navigation.Move( new GeoCoordinate(session.Settings.DefaultLatitude, session.Settings.DefaultLongitude), session.LogicSettings.WalkingSpeedMin, session.LogicSettings.WalkingSpeedMax, null, null, cancellationToken, session); } if (session.ForceMoveJustDone) { session.ForceMoveJustDone = false; } if (session.ForceMoveTo != null) { await ForceMoveTask.Execute(session, cancellationToken); pokestopList = await GetPokeStops(session); } var displayStatsHit = 0; var eggWalker = new EggWalker(1000, session); if (pokestopList.Count <= 0) { session.EventDispatcher.Send(new WarnEvent { Message = session.Translation.GetTranslation(TranslationString.FarmPokestopsNoUsableFound) }); } session.EventDispatcher.Send(new PokeStopListEvent { Forts = session.MapCache.baseFortDatas.ToList() }); cancellationToken.ThrowIfCancellationRequested(); //resort pokestopList = pokestopList.OrderBy( i => LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude, session.Client.CurrentLongitude, i.Latitude, i.Longitude)).ToList(); if (session.LogicSettings.UsePokeStopLuckyNumber) { if (pokestopList.Count >= session.LogicSettings.PokestopSkipLuckyNumberMinUse) { int rng = random.Next(session.LogicSettings.PokestopSkipLuckyMin, session.LogicSettings.PokestopSkipLuckyMax); #if DEBUG Logger.Write("Skip Pokestop RNG: " + rng.ToString() + " against " + session.LogicSettings.PokestopSkipLuckyNumber.ToString(), LogLevel.Debug); #endif if (rng == session.LogicSettings.PokestopSkipLuckyNumber) { #if DEBUG Logger.Write("Skipping Pokestop due to the rng god's will.", LogLevel.Debug); #endif pokestopList.RemoveAt(0); } } } var pokeStop = pokestopList[0]; pokestopList.RemoveAt(0); session.Runtime.TargetStopID = pokeStop.Id; var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude, session.Client.CurrentLongitude, pokeStop.Latitude, pokeStop.Longitude); var fortInfo = await session.Client.Fort.GetFort(pokeStop.Id, pokeStop.Latitude, pokeStop.Longitude); session.EventDispatcher.Send(new FortTargetEvent { Id = fortInfo.FortId, Name = fortInfo.Name, Distance = distance, Latitude = fortInfo.Latitude, Longitude = fortInfo.Longitude, Description = fortInfo.Description, url = fortInfo.ImageUrls[0] }); if (session.LogicSettings.Teleport) { await session.Client.Player.UpdatePlayerLocation(fortInfo.Latitude, fortInfo.Longitude, session.Client.Settings.DefaultAltitude); } else { await session.Navigation.Move(new GeoCoordinate(pokeStop.Latitude, pokeStop.Longitude), session.LogicSettings.WalkingSpeedMin, session.LogicSettings.WalkingSpeedMax, async() => { if (session.LogicSettings.CatchWildPokemon) { // Catch normal map Pokemon await CatchNearbyPokemonsTask.Execute(session, cancellationToken); //Catch Incense Pokemon remove this for time contraints //await CatchIncensePokemonsTask.Execute(session, cancellationToken); } return(true); }, async() => { await UseNearbyPokestopsTask.Execute(session, cancellationToken); return(true); }, cancellationToken, session); } if (!session.ForceMoveJustDone) { FortSearchResponse fortSearch; var timesZeroXPawarded = 0; var fortTry = 0; //Current check const int retryNumber = 50; //How many times it needs to check to clear softban const int zeroCheck = 5; //How many times it checks fort before it thinks it's softban if (session.Runtime.BreakOutOfPathing) { continue; } do { cancellationToken.ThrowIfCancellationRequested(); fortSearch = await session.Client.Fort.SearchFort(pokeStop.Id, pokeStop.Latitude, pokeStop.Longitude); if (fortSearch.ExperienceAwarded > 0 && timesZeroXPawarded > 0) { timesZeroXPawarded = 0; } if (fortSearch.ExperienceAwarded == 0) { timesZeroXPawarded++; if (timesZeroXPawarded > zeroCheck) { if ((int)fortSearch.CooldownCompleteTimestampMs != 0) { break; // Check if successfully looted, if so program can continue as this was "false alarm". } fortTry += 1; if (!ShownSoftBanMessage) { session.EventDispatcher.Send(new FortFailedEvent { Name = fortInfo.Name, Try = fortTry, Max = retryNumber - zeroCheck }); ShownSoftBanMessage = true; } await Task.Delay(session.LogicSettings.DelaySoftbanRetry); } } else { session.EventDispatcher.Send(new FortUsedEvent { Id = pokeStop.Id, Name = fortInfo.Name, Exp = fortSearch.ExperienceAwarded, Gems = fortSearch.GemsAwarded, Items = StringUtils.GetSummedFriendlyNameOfItemAwardList(fortSearch.ItemsAwarded), Latitude = pokeStop.Latitude, Longitude = pokeStop.Longitude, InventoryFull = fortSearch.Result == FortSearchResponse.Types.Result.InventoryFull, Description = fortInfo.Description, url = fortInfo.ImageUrls[0] }); session.MapCache.UsedPokestop(pokeStop, session); session.EventDispatcher.Send(new InventoryNewItemsEvent() { Items = fortSearch.ItemsAwarded.ToItemList() }); break; //Continue with program as loot was succesfull. } } while (fortTry < retryNumber - zeroCheck); //Stop trying if softban is cleaned earlier or if 40 times fort looting failed. ShownSoftBanMessage = false; await Task.Delay(session.LogicSettings.DelayPokestop); //Catch Lure Pokemon if (session.LogicSettings.CatchWildPokemon) { if (pokeStop.LureInfo != null) { await CatchLurePokemonsTask.Execute(session, pokeStop.BaseFortData, cancellationToken); } // Catch normal map Pokemon if (session.LogicSettings.Teleport) { await CatchNearbyPokemonsTask.Execute(session, cancellationToken); } //Catch Incense Pokemon await CatchIncensePokemonsTask.Execute(session, cancellationToken); } await eggWalker.ApplyDistance(distance, cancellationToken); if (++stopsHit % 5 == 0) //TODO: OR item/pokemon bag is full { // need updated stardust information for upgrading, so refresh your profile now await DownloadProfile(session); if (fortSearch.ItemsAwarded.Count > 0) { await session.Inventory.RefreshCachedInventory(); } await RecycleItemsTask.Execute(session, cancellationToken); if (session.LogicSettings.EvolveAllPokemonWithEnoughCandy || session.LogicSettings.EvolveAllPokemonAboveIv) { await EvolvePokemonTask.Execute(session, cancellationToken); } if (session.LogicSettings.AutomaticallyLevelUpPokemon) { await LevelUpPokemonTask.Execute(session, cancellationToken); } if (session.LogicSettings.TransferDuplicatePokemon) { await TransferDuplicatePokemonTask.Execute(session, cancellationToken); } if (session.LogicSettings.RenamePokemon) { await RenamePokemonTask.Execute(session, cancellationToken); } if (++displayStatsHit >= 4) { await DisplayPokemonStatsTask.Execute(session); } } } if (session.LogicSettings.SnipeAtPokestops || session.LogicSettings.UseSnipeLocationServer) { await SnipePokemonTask.Execute(session, cancellationToken); } } } }