private void GenerateBotConnection(PokeTradeBot b, PokeTradeDetail <PK8> detail) { var file = b.Connection.IP; var name = string.Format(TrainerTradeStart, detail.ID, detail.Trainer.TrainerName, (Species)detail.TradeData.Species); File.WriteAllText($"{file}.txt", name); }
private void ReplyWithZ3Results(PokeTradeDetail <PK8> detail, PK8 result) { detail.SendNotification(this, "Calculating your seed(s)..."); if (result.IsShiny) { Connection.Log("The Pokemon is already shiny!"); // Do not bother checking for next shiny frame detail.SendNotification(this, "This Pokemon is already shiny! Raid seed calculation was not done."); detail.TradeFinished(this, result); return; } var ec = result.EncryptionConstant; var pid = result.PID; var IVs = result.IVs.Length == 0 ? GetBlankIVTemplate() : PKX.ReorderSpeedLast((int[])result.IVs.Clone()); if (Hub.Config.ShowAllZ3Results) { var matches = Z3Search.GetAllSeeds(ec, pid, IVs); foreach (var match in matches) { var msg = match.ToString(); detail.SendNotification(this, msg); } } else { var match = Z3Search.GetFirstSeed(ec, pid, IVs); var msg = match.ToString(); detail.SendNotification(this, msg); } }
private async Task PerformTrade(SAV8BS sav, PokeTradeDetail <PB8> detail, PokeRoutineType type, uint priority, CancellationToken token) { PokeTradeResult result; try { result = await PerformLinkCodeTrade(sav, detail, token).ConfigureAwait(false); if (result == PokeTradeResult.Success) { return; } } catch (SocketException socket) { Log(socket.Message); result = PokeTradeResult.ExceptionConnection; HandleAbortedTrade(detail, type, priority, result); throw; // let this interrupt the trade loop. re-entering the trade loop will recheck the connection. } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception e) #pragma warning restore CA1031 // Do not catch general exception types { Log(e.Message); result = PokeTradeResult.ExceptionInternal; } HandleAbortedTrade(detail, type, priority, result); }
public void CalculateAndNotify(T pkm, PokeTradeDetail <T> detail, SeedCheckSettings settings, PokeTradeBot bot) { var ec = pkm.EncryptionConstant; var pid = pkm.PID; var IVs = pkm.IVs.Length == 0 ? GetBlankIVTemplate() : PKX.ReorderSpeedLast((int[])pkm.IVs.Clone()); var name = SpeciesName.GetSpeciesName(pkm.Species, 2); var ot = pkm.OT_Name; var abilityNo = pkm.AbilityNumber; var ability = pkm.Ability; var gender = pkm.GetSaneGender(); var nature = pkm.Nature; if (settings.ShowAllZ3Results) { var matches = Z3Search.GetAllSeeds(ec, pid, IVs, name, ot, gender, abilityNo, ability, nature); foreach (var match in matches) { var lump = new PokeTradeSummary("Calculated Seed:", match); detail.SendNotification(bot, lump); } } else { var match = Z3Search.GetFirstSeed(ec, pid, IVs, name, ot, gender, abilityNo, ability, nature); var lump = new PokeTradeSummary("Calculated Seed:", match); detail.SendNotification(bot, lump); } }
private void GenerateBotConnection(PokeTradeBot b, PokeTradeDetail <PK8> detail) { var file = b.Config.ConnectionType == ConnectionType.WiFi ? b.Connection.IP : "USB" + b.Connection.UsbPortIndex; var name = string.Format(TrainerTradeStart, detail.ID, detail.Trainer.TrainerName, (Species)detail.TradeData.Species); File.WriteAllText($"{file}.txt", name); }
private async Task <PokeTradeResult> EndSeedCheckTradeAsync(PokeTradeDetail <PK8> detail, PK8 pk, CancellationToken token) { await ExitSeedCheckTrade(Hub.Config, token).ConfigureAwait(false); detail.TradeFinished(this, pk); if (DumpSetting.Dump && !string.IsNullOrEmpty(DumpSetting.DumpFolder)) { DumpPokemon(DumpSetting.DumpFolder, "seed", pk); } // Send results from separate thread; the bot doesn't need to wait for things to be calculated. #pragma warning disable 4014 Task.Run(() => { try { ReplyWithSeedCheckResults(detail, pk); } catch (Exception ex) { detail.SendNotification(this, $"Unable to calculate seeds: {ex.Message}\r\n{ex.StackTrace}"); } }, token); #pragma warning restore 4014 Hub.Counts.AddCompletedSeedCheck(); return(PokeTradeResult.Success); }
private void UpdateCountsAndExport(PokeTradeDetail <PB8> poke, PB8 received, PB8 toSend) { var counts = TradeSettings; if (poke.Type == PokeTradeType.Random) { counts.AddCompletedDistribution(); } else if (poke.Type == PokeTradeType.Clone) { counts.AddCompletedClones(); } else { counts.AddCompletedTrade(); } if (DumpSetting.Dump && !string.IsNullOrEmpty(DumpSetting.DumpFolder)) { var subfolder = poke.Type.ToString().ToLower(); DumpPokemon(DumpSetting.DumpFolder, subfolder, received); // received by bot if (poke.Type is PokeTradeType.Specific or PokeTradeType.Clone) { DumpPokemon(DumpSetting.DumpFolder, "traded", toSend); // sent to partner } } }
private void GenerateBotConnection <T>(PokeRoutineExecutorBase b, PokeTradeDetail <T> detail) where T : PKM, new() { var file = b.Connection.Name; var name = string.Format(TrainerTradeStart, detail.ID, detail.Trainer.TrainerName, (Species)detail.TradeData.Species); File.WriteAllText($"{file}.txt", name); }
public void CalculateAndNotify(T pkm, PokeTradeDetail <T> detail, SeedCheckSettings settings, PokeTradeBot bot) { const string msg = "Seed searching implementation not found. " + "Please let the person hosting the bot know that they need to provide the required Z3 files."; detail.SendNotification(bot, msg); }
public TradeEntry(PokeTradeDetail <T> trade, ulong userID, PokeRoutineType type, string username) { Trade = trade; UserID = userID; Type = type; Username = username; }
public bool TryPeek(out PokeTradeDetail <TPoke> detail, out uint priority) { var result = Queue.TryPeek(out var kvp); detail = kvp.Value; priority = kvp.Key; return(result); }
private void ReplyWithLegalityCheckResults(PokeTradeDetail <PK8> detail, PK8 result) { detail.SendNotification(this, "Performing Legality Analysis"); var la = new LegalityAnalysis(result); detail.SendNotification(this, la); LogUtil.LogInfo("Legality Check Completed.", "PokeTradeBot"); }
private async Task <PokeTradeResult> ProcessGiveawayUploadAsync(PokeTradeDetail <PK8> detail, CancellationToken token) { int ctr = 0; var time = TimeSpan.FromSeconds(Hub.Config.Trade.MaxDumpTradeTime); var start = DateTime.Now; var pkprev = new PK8(); var poolEntry = detail.PoolEntry; while (ctr < 1 && DateTime.Now - start < time) { var pk = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 3_000, 1_000, token).ConfigureAwait(false); if (pk == null || pk.Species < 1 || !pk.ChecksumValid || SearchUtil.HashByDetails(pk) == SearchUtil.HashByDetails(pkprev)) { continue; } // Save the new Pokémon for comparison next round. pkprev = pk; poolEntry.PK8 = pk; poolEntry.Pokemon = SpeciesName.GetSpeciesName(pk.Species, 2); if (Hub.Config.Legality.VerifyLegality) { LogUtil.LogInfo($"Performing legality check on {poolEntry.Pokemon}", "PokeTradeBot.GiveawayUpload"); var la = new LegalityAnalysis(poolEntry.PK8); var verbose = la.Report(true); LogUtil.LogInfo($"Shown Pokémon is {(la.Valid ? "Valid" : "Invalid")}.", "PokeTradeBot.GiveawayUpload"); detail.SendNotification(this, pk, $"Pokémon sent is {(la.Valid ? "Valid" : "Invalid")}."); detail.SendNotification(this, pk, verbose); if (!la.Valid) { detail.SendNotification(this, pk, $"Show a different pokemon to continue or exit the trade to end."); continue; } } LogUtil.LogInfo("Creating new database entry", "PokeTradeBot.GiveawayUpload"); Hub.GiveawayPoolDatabase.NewEntry(poolEntry); if (Hub.Config.Discord.ReturnPK8s) { detail.SendNotification(this, pk, "Here's what you showed me!"); } ctr++; } LogUtil.LogInfo($"Ended Giveaway pool upload", "PokeTradeBot.GiveawayUpload"); await ExitSeedCheckTrade(Hub.Config, token).ConfigureAwait(false); if (ctr == 0) { return(PokeTradeResult.TrainerTooSlow); } detail.Notifier.SendNotification(this, detail, $"Finished uploading Pokémon to the Giveaway Pool."); detail.Notifier.TradeFinished(this, detail, detail.TradeData); // blank pk8 return(PokeTradeResult.Success); }
public void SendNotification(PokeRoutineExecutor routine, PokeTradeDetail <T> info, PokeTradeSummary message) { var msg = message.Summary; if (message.Details.Count > 0) { msg += ", " + string.Join(", ", message.Details.Select(z => $"{z.Heading}: {z.Detail}")); } LogUtil.LogInfo(msg, routine.Connection.Name); }
private async Task <PokeTradeResult> ProcessDumpTradeAsync(PokeTradeDetail <PB8> detail, CancellationToken token) { int ctr = 0; var time = TimeSpan.FromSeconds(Hub.Config.Trade.MaxDumpTradeTime); var start = DateTime.Now; while (ctr < Hub.Config.Trade.MaxDumpsPerTrade && DateTime.Now - start < time) { // Wait for user input... Needs to be different from the previously offered Pokémon. var tradeOffered = await ReadUntilChanged(LinkTradePokemonOffset, lastOffered, 3_000, 1_000, false, true, token).ConfigureAwait(false); if (!tradeOffered) { continue; } // If we detected a change, they offered something. var pk = await ReadPokemon(LinkTradePokemonOffset, BoxFormatSlotSize, token).ConfigureAwait(false); var newEC = await SwitchConnection.ReadBytesAbsoluteAsync(LinkTradePokemonOffset, 8, token).ConfigureAwait(false); if (pk == null || pk.Species < 1 || !pk.ChecksumValid || lastOffered == newEC) { continue; } lastOffered = newEC; // Send results from separate thread; the bot doesn't need to wait for things to be calculated. if (DumpSetting.Dump) { var subfolder = detail.Type.ToString().ToLower(); DumpPokemon(DumpSetting.DumpFolder, subfolder, pk); // received } var la = new LegalityAnalysis(pk); var verbose = la.Report(true); Log($"Shown Pokémon is: {(la.Valid ? "Valid" : "Invalid")}."); detail.SendNotification(this, pk, verbose); ctr++; } Log($"Ended Dump loop after processing {ctr} Pokémon."); if (ctr == 0) { return(PokeTradeResult.TrainerTooSlow); } TradeSettings.AddCompletedDumps(); detail.Notifier.SendNotification(this, detail, $"Dumped {ctr} Pokémon."); detail.Notifier.TradeFinished(this, detail, detail.TradeData); // blank pk8 return(PokeTradeResult.Success); }
public void StartTrade(PokeTradeBot b, PokeTradeDetail <PK8> detail, PokeTradeHub <PK8> hub) { if (!CreateAssets) { return; } try { if (CreateTradeStart) { GenerateBotConnection(b, detail); } if (CreateWaitedTime) { GenerateWaitedTime(detail.Time); } if (CreateEstimatedTime) { GenerateEstimatedTime(hub); } if (CreateUsersInQueue) { GenerateUsersInQueue(hub.Queues.Info.Count); } if (CreateOnDeck) { GenerateOnDeck(hub); } if (CreateOnDeck2) { GenerateOnDeck2(hub); } if (CreateUserList) { GenerateUserList(hub); } if (CreateCompletedTrades) { GenerateCompletedTrades(hub.Config.Counts); } if (CreateTradeStartSprite) { GenerateBotSprite(b, detail); } } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception e) #pragma warning restore CA1031 // Do not catch general exception types { LogUtil.LogError(e.Message, nameof(StreamSettings)); } }
public bool Equals(PokeTradeDetail <TPoke>?other) { if (other is null) { return(false); } if (ReferenceEquals(this, other)) { return(true); } return(ReferenceEquals(Trainer, other.Trainer)); }
private static void GenerateBotSprite <T>(PokeRoutineExecutorBase b, PokeTradeDetail <T> detail) where T : PKM, new() { var func = CreateSpriteFile; if (func == null) { return; } var file = b.Connection.Name; var pk = detail.TradeData; func.Invoke(pk, $"sprite_{file}.png"); }
private static void GenerateBotSprite(PokeTradeBot b, PokeTradeDetail <PK8> detail) { var func = CreateSpriteFile; if (func == null) { return; } var file = b.Config.ConnectionType == ConnectionType.WiFi ? b.Connection.IP : "USB" + b.Connection.UsbPortIndex; var pk = detail.TradeData; func.Invoke(pk, $"sprite_{file}.png"); }
private static void GenerateBotSprite(PokeTradeBot b, PokeTradeDetail <PK8> detail) { var func = CreateSpriteFile; if (func == null) { return; } var file = b.Connection.IP; var pk = detail.TradeData; func.Invoke(pk, $"sprite_{file}.png"); }
private async Task <PokeTradeResult> ProcessDumpTradeAsync(PokeTradeDetail <PK8> detail, CancellationToken token) { int ctr = 0; var time = TimeSpan.FromSeconds(Hub.Config.Trade.MaxDumpTradeTime); var start = DateTime.Now; while (ctr < Hub.Config.Trade.MaxDumpsPerTrade && DateTime.Now - start < time) { bool found = await WaitForPokemonChanged(LinkTradePartnerPokemonOffset, 15_000, 1_000, token); if (!found) { continue; } var pk = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 3_000, 1_000, token).ConfigureAwait(false); if (pk == null || pk.Species < 1 || !pk.ChecksumValid) { continue; } // Send results from separate thread; the bot doesn't need to wait for things to be calculated. if (DumpSetting.Dump) { var subfolder = detail.Type.ToString().ToLower(); DumpPokemon(DumpSetting.DumpFolder, subfolder, pk); // received } var la = new LegalityAnalysis(pk); var verbose = la.Report(true); Log($"Shown Pokémon is {(la.Valid ? "Valid" : "Invalid")}."); detail.SendNotification(this, pk, verbose); ctr++; } Log($"Ended Dump loop after processing {ctr} Pokémon"); await ExitSeedCheckTrade(Hub.Config, token).ConfigureAwait(false); if (ctr == 0) { return(PokeTradeResult.TrainerTooSlow); } Hub.Counts.AddCompletedDumps(); detail.Notifier.SendNotification(this, detail, $"Dumped {ctr} Pokémon."); detail.Notifier.TradeFinished(this, detail, detail.TradeData); // blank pk8 return(PokeTradeResult.Success); }
private void HandleAbortedTrade(PokeTradeDetail <PB8> detail, PokeRoutineType type, uint priority, PokeTradeResult result) { detail.IsProcessing = false; if (result.ShouldAttemptRetry() && detail.Type != PokeTradeType.Random && !detail.IsRetry) { detail.IsRetry = true; Hub.Queues.Enqueue(type, detail, Math.Min(priority, PokeTradePriorities.Tier2)); detail.SendNotification(this, "Oops! Something happened. I'll requeue you for another attempt."); } else { detail.SendNotification(this, $"Oops! Something happened. Canceling the trade: {result}."); detail.TradeCanceled(this, result); } }
private bool FixMachamps(PK8 clone, PokeTradeDetail <PK8> poke, string TrainerName, bool adOT) { if (adOT && clone.OT_Name != $"{TrainerName}") { clone.OT_Name = $"{TrainerName}"; clone.ClearNickname(); clone.PKRS_Infected = false; clone.PKRS_Cured = false; clone.PKRS_Days = 0; clone.PKRS_Strain = 0; poke.SendNotification(this, $"```fix\nDetected an ad OT/Nickname with your {(Species)clone.Species}! Fixed it for you!```"); return(FixAds = false); } return(FixAds = true); }
private async Task <PokeTradeResult> ConfirmAndStartTrading(PokeTradeDetail <PB8> detail, CancellationToken token) { // We'll keep watching B1S1 for a change to indicate a trade started -> should try quitting at that point. var oldEC = await SwitchConnection.ReadBytesAbsoluteAsync(BoxStartOffset, 8, token).ConfigureAwait(false); await Click(A, 3_000, token).ConfigureAwait(false); for (int i = 0; i < 10; i++) { if (await IsUserBeingShifty(detail, token).ConfigureAwait(false)) { return(PokeTradeResult.SuspiciousActivity); } await Click(A, 1_500, token).ConfigureAwait(false); } var tradeCounter = 0; while (await IsUnionWork(UnionTalkingOffset, token).ConfigureAwait(false)) { await Click(A, 1_000, token).ConfigureAwait(false); tradeCounter++; var newEC = await SwitchConnection.ReadBytesAbsoluteAsync(BoxStartOffset, 8, token).ConfigureAwait(false); if (!newEC.SequenceEqual(oldEC)) { await Task.Delay(5_000, token).ConfigureAwait(false); return(PokeTradeResult.Success); } // We've somehow failed out of the Union Room -- can happen with connection error. if (!await IsUnionWork(UnionGamingOffset, token).ConfigureAwait(false)) { return(PokeTradeResult.TrainerTooSlow); } if (tradeCounter >= Hub.Config.Trade.TradeAnimationMaxDelaySeconds) { break; } } // If we don't detect a B1S1 change, the trade didn't go through in that time. return(PokeTradeResult.TrainerTooSlow); }
private async Task <PokeTradeResult> EndDuduTradeAsync(PokeTradeDetail <PK8> detail, PK8 pk, CancellationToken token) { await ExitDuduTrade(token).ConfigureAwait(false); detail.TradeFinished(this, pk); // Send results from separate thread; the bot doesn't need to wait for things to be calculated. #pragma warning disable 4014 Task.Run(() => ReplyWithZ3Results(detail, pk), token); #pragma warning restore 4014 Hub.Counts.AddCompletedDudu(); await Task.Delay(5_000, token).ConfigureAwait(false); return(PokeTradeResult.Success); }
public void StartTrade(PokeTradeBot b, PokeTradeDetail <PK8> detail, PokeTradeHub <PK8> hub) { try { if (CreateTradeStart) { GenerateBotConnection(b, detail); } if (CreateWaitedTime) { GenerateWaitedTime(detail.Time); } if (CreateEstimatedTime) { GenerateEstimatedTime(hub); } if (CreateUsersInQueue) { GenerateUsersInQueue(hub.Queues.Info.Count); } if (CreateOnDeck) { GenerateOnDeck(hub); } if (CreateOnDeck2) { GenerateOnDeck2(hub); } if (CreateUserList) { GenerateUserList(hub); } if (CreateCompletedTrades) { GenerateCompletedTrades(hub.Config.Counts); } if (CreateTradeStartSprite) { GenerateBotSprite(b, detail); } } catch (Exception e) { LogUtil.LogError(e.Message, nameof(StreamSettings)); } }
private string GetAltAccount(PokeTradeDetail <PK8> poke, string TrainerName) { if (Hub.Config.Discord.PingUserOnAltDetection == string.Empty) { return(""); } string invalid = new string(System.IO.Path.GetInvalidFileNameChars()) + new string(System.IO.Path.GetInvalidPathChars()); foreach (char c in invalid) { TrainerName = TrainerName.Replace(c.ToString(), ""); } string folderPath = @"AltDetection\"; string filePath = @"AltDetection\" + TrainerName + ".txt"; if (!System.IO.Directory.Exists(folderPath)) { System.IO.Directory.CreateDirectory(folderPath); } if (!System.IO.File.Exists(filePath)) { System.IO.File.Create(filePath).Close(); } List <string> content = System.IO.File.ReadAllLines(filePath).ToList(); var id = poke.DiscordUserId; if (content.Count == 0) { content.Add($"{id}"); } else if (content[0] != id.ToString()) { return($"{content[0]}"); } System.IO.File.WriteAllLines(filePath, content); return(""); }
private void ReplyWithSeedCheckResults(PokeTradeDetail <PK8> detail, PK8 result) { detail.SendNotification(this, "Calculating your seed(s)..."); if (result.IsShiny) { Log("The Pokémon is already shiny!"); // Do not bother checking for next shiny frame detail.SendNotification(this, "This Pokémon is already shiny! Raid seed calculation was not done."); if (DumpSetting.Dump && !string.IsNullOrEmpty(DumpSetting.DumpFolder)) { DumpPokemon(DumpSetting.DumpFolder, "seed", result); } detail.TradeFinished(this, result); return; } SeedChecker.CalculateAndNotify(result, detail, Hub.Config.SeedCheck, this); Log("Seed calculation completed."); }
private void ReplyWithZ3Results(PokeTradeDetail <PK8> detail, PK8 result) { detail.SendNotification(this, "Calculating your seed(s)..."); if (result.IsShiny) { Connection.Log("The Pokémon is already shiny!"); // Do not bother checking for next shiny frame detail.SendNotification(this, "This Pokémon is already shiny! Raid seed calculation was not done."); if (DumpSetting.Dump && !string.IsNullOrEmpty(DumpSetting.DumpFolder)) { DumpPokemon(DumpSetting.DumpFolder, "seed", result); } detail.TradeFinished(this, result); return; } var ec = result.EncryptionConstant; var pid = result.PID; var IVs = result.IVs.Length == 0 ? GetBlankIVTemplate() : PKX.ReorderSpeedLast((int[])result.IVs.Clone()); if (Hub.Config.Dudu.ShowAllZ3Results) { var matches = Z3Search.GetAllSeeds(ec, pid, IVs); foreach (var match in matches) { var lump = new PokeTradeSummary("Calculated Seed:", match); detail.SendNotification(this, lump); } } else { var match = Z3Search.GetFirstSeed(ec, pid, IVs); var lump = new PokeTradeSummary("Calculated Seed:", match); detail.SendNotification(this, lump); } Connection.Log("Seed calculation completed."); }
public void CalculateAndNotify(T pkm, PokeTradeDetail <T> detail, SeedCheckSettings settings, PokeTradeBot bot) { var ec = pkm.EncryptionConstant; var pid = pkm.PID; var IVs = pkm.IVs.Length == 0 ? GetBlankIVTemplate() : PKX.ReorderSpeedLast((int[])pkm.IVs.Clone()); if (settings.ShowAllZ3Results) { var matches = Z3Search.GetAllSeeds(ec, pid, IVs); foreach (var match in matches) { var lump = new PokeTradeSummary("Calculated Seed:", match); detail.SendNotification(bot, lump); } } else { var match = Z3Search.GetFirstSeed(ec, pid, IVs); var lump = new PokeTradeSummary("Calculated Seed:", match); detail.SendNotification(bot, lump); } }