private async Task SwipeDown(AndroidConnector android) { await Task.Delay(250); await android.Swipe(1160, 860, 1160, -350, 1000); await Task.Delay(250); await android.Tap(530, 845); // against overlay await Task.Delay(500); }
private async Task <bool> NextPage(AndroidConnector android) { using (var image = Image.Load <Rgba32>("shopitems.png")) { var maxPageImage = image.Clone(ctx => ctx.Crop(new Rectangle(763, 956, 39, 52))); int maxPage = -1; //TODO: cache these foreach (var file in Directory.GetFiles("data/pagenumbers/total")) { using (var pageImage = Image.Load <Rgba32>(file)) if (IsSame(pageImage, maxPageImage)) { maxPage = int.Parse(Path.GetFileNameWithoutExtension(file), CultureInfo.InvariantCulture); } } if (maxPage == -1) { maxPageImage.Save($"unknown/maxpage{Directory.GetFiles("unknown").Length}.png"); } var curPageImage = image.Clone(ctx => ctx.Crop(new Rectangle(700, 962, 63, 44))); int curPage = -1; //TODO: cache these foreach (var file in Directory.GetFiles("data/pagenumbers/current")) { using (var pageImage = Image.Load <Rgba32>(file)) if (IsSame(pageImage, curPageImage)) { curPage = int.Parse(Path.GetFileNameWithoutExtension(file), CultureInfo.InvariantCulture); } } if (curPage == -1) { curPageImage.Save($"unknown/curpage{Directory.GetFiles("unknown").Length}.png"); } if (curPage < maxPage) { await android.Tap(944, 982); await Task.Delay(500); // wait for next page to load return(false); } } return(true); }
public async Task <bool> IsExchangeOpen(AndroidConnector android) { await android.Screenshot("isExchangeOpen.png"); using (var image = Image.Load <Rgba32>("isExchangeOpen.png")) { using (var cmp = Image.Load <Rgba32>("data/search.png")) if (ImageDistance(image.Clone(ctx => ctx.Crop(new Rectangle(223, 200, 268, 63))), cmp) < 10) { return(true); } using (var cmp = Image.Load <Rgba32>("data/search2.png")) if (ImageDistance(image.Clone(ctx => ctx.Crop(new Rectangle(1356, 235, 117, 55))), cmp) < 10) { return(true); } return(false); } }
static void Main(string[] args) { string hostname = "10.10.0.32:1234"; if (args.Length > 0) { hostname = args[0]; } Application.Init(); var top = Application.Top; top.Add(log = new LogWindow()); top.Add(status = new StatusWindow()); top.Add(controls = new ControlsWindow()); var menu = new MenuBar(new MenuBarItem[] { new MenuBarItem("_File", new MenuItem [] { new MenuItem("_New", "", null), new MenuItem("_Close", "", null), new MenuItem("_Quit", "", null) }), new MenuBarItem("_Edit", new MenuItem [] { new MenuItem("_Copy", "", null), new MenuItem("C_ut", "", null), new MenuItem("_Paste", "", null) }) }); top.Add(menu); androidConnection = new AndroidConnector(hostname); using (scanner = new Scanner()) { Task.Run(RunScanner); Application.Run(); } }
public async Task <List <ScanResultEquip> > ScanEquip(AndroidConnector android, ScanInfo scanInfo) { List <ScanResultEquip> result = new List <ScanResultEquip>(); if (scanInfo.RealName.Contains("[1]")) { scanInfo.Slots = 1; } if (scanInfo.RealName.Contains("[2]")) { scanInfo.Slots = 2; } if (scanInfo.SearchName.Contains("[")) { scanInfo.SearchName = scanInfo.SearchName.Substring(0, scanInfo.SearchName.IndexOf("[")).Trim(); } scanInfo.Equip = true; Program.status.SetSubStatus("Opening search window"); await CloseSearch(android); await ClickSearchButton(android); await ClickSearchBox(android); await android.Text(scanInfo.SearchName); await ClickSearchWindowSearchButton(android); //to close text input await ClickSearchWindowSearchButton(android); Program.status.SetSubStatus("Scanning search result"); await android.Screenshot("searchresult.png"); using (var image = Image.Load <Rgba32>("searchresult.png")) using (var cmp = Image.Load <Rgba32>("data/bigerror.png")) if (ImageDistance(image.Clone(c => c.Crop(new Rectangle(650, 150, 700, 200))), cmp) < 100) { Program.Restart = true; return(null); } List <int> indices = FindSearchResult("searchresult.png", scanInfo); if (indices.Count == 1 && indices[0] == -1) { await android.Swipe(1100, 863, 1100, 355, 200); await Task.Delay(500); await android.Screenshot("searchresult.png"); indices = FindSearchResult("searchresult.png", scanInfo); } await Task.Delay(500); if (indices.Count == 0) { //TODO: do something with item0.png - item9.png Program.status.SetSubStatus("- Error, could not find item"); await CloseSearch(android); return(new List <ScanResultEquip>() { ScanResult.BuildError <ScanResultEquip>(scanInfo) }); } if (indices[0] != scanInfo.SearchIndex) { if (scanInfo.SearchIndex != -1) { Program.log.Log(scanInfo.RealName, "Warning, search index not correct"); } scanInfo.SearchIndex = indices[0]; } for (int i = 0; i < indices.Count; i++) { await ClickSearchWindowIndex(android, indices[i]); await Task.Delay(2500); Program.status.SetSubStatus("Checking for sales"); await android.Screenshot("shopitems.png"); using (var image = Image.Load <Rgba32>("shopitems.png")) image.Clone(ctx => ctx.Crop(new Rectangle(975, 505, 368, 64))).Save($"nosale.png"); bool onSale = true; if (GetTextFromImage("nosale.png").ToLower().Contains("currently")) { onSale = false; Program.log.Log(scanInfo.RealName, "Currently not for sale"); if (i + 1 >= indices.Count) { return new List <ScanResultEquip>() { new ScanResultEquip() { Found = false, ScanInfo = scanInfo } } } ; } if (onSale) { var images = new List <Image <Rgba32> >(); int subPage = 0; while (!Program.CancelScan) { Program.log.Log(scanInfo.RealName, "Scanning page " + subPage); int foundResults = images.Count; bool done = await ScanPage(images, android, scanInfo, result); if (foundResults == images.Count) { Program.log.Log(scanInfo.RealName, "No new items found in last sweep, done"); break; } if (subPage % 2 == 0) { await SwipeDown(android); } else if (await NextPage(android)) { break; } await android.Screenshot("shopitems.png"); subPage++; } Program.status.SetSubStatus("done scanning"); foreach (var img in images) { img.Dispose(); } return(result); } //this should not happen scanInfo.Message = ""; Console.WriteLine("Item does not match, or not found on exchange with multiple items, trying to rescan it"); await CloseSearch(android); await ClickSearchButton(android); await ClickSearchBox(android); await android.Text(scanInfo.SearchName); await ClickSearchWindowSearchButton(android); //to close text input await ClickSearchWindowSearchButton(android); } return(null); }
public async Task RestartRo(AndroidConnector android) { Program.status.SetSubStatus("Stopping RO"); await android.StopRo(); await Task.Delay(1000); Program.status.SetSubStatus("Starting RO"); await android.StartRo(); await Task.Delay(30000); Program.status.SetSubStatus("Scanning if logged in"); //TODO: check for google/facebook popup for (int i = 0; i < 25; i++) { await android.Screenshot("login.png"); using (var image = Image.Load <Rgba32>("login.png")) image.Clone(ctx => ctx.Crop(new Rectangle(855, 585, 215, 55))).Save($"servername.png"); string servername = GetTextFromImage("servername.png"); Console.WriteLine(servername); if (servername.ToLower() == "eternal love") { break; } await Task.Delay(5000); if (i == 24) { Program.status.SetSubStatus("Unable to login"); return; } } Program.status.SetSubStatus("Tapping Login"); await android.Tap(500, 500); //login tap await Task.Delay(10000); for (int i = 0; i < 25; i++) { await android.Screenshot("charselect.png"); using (var image = Image.Load <Rgba32>("charselect.png")) using (var cmp = Image.Load <Rgba32>("data/startbutton.png")) if (IsSame(image.Clone(ctx => ctx.Crop(new Rectangle(1518, 943, 243, 67))), cmp)) { break; } await Task.Delay(2000); if (i == 24) { Program.status.SetSubStatus("Unable to select character"); return; } } Program.status.SetSubStatus("Selecting char"); await android.Tap(1624, 975); //select char button await Task.Delay(30000); Program.status.SetSubStatus("Closing stupid ninja popup"); await android.Tap(1893, 50); // await Task.Delay(1000); Program.status.SetSubStatus("Closing event popup"); await android.Tap(1400, 133); //close event popup await android.Tap(1495, 111); //close anotherpopup }
public async Task <ScanResultEquip> ParseResultWindowEquip(string fileName, ScanInfo scanInfo, AndroidConnector android) { ScanResultEquip exchangeInfo = new ScanResultEquip() { Found = true, ScanInfo = scanInfo }; using (var image = Image.Load <Rgba32>(fileName)) { image.Clone(ctx => ctx.Crop(new Rectangle(996, 159, 549, 66))).Save($"itemname.png"); string itemName = GetTextFromImage("itemname.png"); if (itemName.ToLower() != scanInfo.RealName.ToLower()) { scanInfo.Message = $"Something is wrong, names do NOT match. Expected {scanInfo.RealName.ToLower()} but got {itemName.ToLower()}"; return(ScanResult.BuildError <ScanResultEquip>(scanInfo)); } exchangeInfo.Price = int.Parse(GetPriceEquip(image), CultureInfo.InvariantCulture); exchangeInfo.SnapTime = GetSnapTime(image); int i = 0; //scan for multiple items bool enchanted = false; bool foundRefine = false; while (!Program.CancelScan) { using (var image2 = Image.Load <Rgba32>(fileName)) image2.Clone(ctx => ctx.Crop(new Rectangle(383, 261, 553, 453))).Save($"enchant{i}.png"); string hasEnchant = GetTextFromImage($"enchant{i}.png"); Console.WriteLine($"- Text Read: \n\n{hasEnchant}\n\n"); if (hasEnchant.ToLower().Contains("refine ") && !foundRefine && !enchanted && hasEnchant.ToLower().IndexOf("refine ") != hasEnchant.ToLower().IndexOf("refine +6 effective")) { string refine = hasEnchant.ToLower(); refine = refine.Replace("\r\n", "\n"); while (refine.Contains("\n\n")) { refine = refine.Replace("\n\n", "\n"); } refine = refine.Substring(refine.IndexOf("\nrefine ") + 8).Trim(); if (refine.IndexOf("\n") > 0) { refine = refine.Substring(0, refine.IndexOf("\n")).Trim(); } Console.WriteLine(refine); int refineLevel = 0; if (refine.Contains("/")) { try { refineLevel = int.Parse(refine.Substring(0, refine.IndexOf("/"))); foundRefine = true; } catch (FormatException e) { scanInfo.Message = "Something is wrong, error parsing refine level: " + refine; Console.WriteLine(e); return(ScanResult.BuildError <ScanResultEquip>(scanInfo)); } } if (refine.Contains("atk+")) { int atk = int.Parse(refine.Substring(refine.IndexOf("atk+") + 4)); foundRefine = true; //TODO: check if atk matches refineLevel } exchangeInfo.RefinementLevel = refineLevel; } if (hasEnchant.ToLower().Contains("enchanted")) { enchanted = true; } if (hasEnchant.ToLower().Contains("equipment upgrade")) { if (enchanted) { MemoryStream ms = new MemoryStream(); var jpegEncoder = new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder { Quality = 10 }; using (var image2 = Image.Load <Rgba32>($"enchant{i}.png")) image2.Clone(ctx => ctx.Resize(new ResizeOptions { Size = image2.Size() / 2 })).SaveAsJpeg(ms, jpegEncoder); exchangeInfo.EnchantmentImage = System.Convert.ToBase64String(ms.GetBuffer()); if (!hasEnchant.ToLower().Contains("enchanted")) { Console.WriteLine("Scrolled too far"); exchangeInfo.Enchantments = new List <string>() { "scrolled too far" }; break; } hasEnchant = hasEnchant.ToLower(); hasEnchant = hasEnchant.Replace("\r\n", "\n"); while (hasEnchant.Contains("\n\n")) { hasEnchant = hasEnchant.Replace("\n\n", "\n"); } hasEnchant = hasEnchant.Substring(hasEnchant.IndexOf("enchanted attribute:") + 20).Trim(); hasEnchant = hasEnchant.Substring(0, hasEnchant.IndexOf("equipment upgrade")).Trim(); hasEnchant = hasEnchant.Replace("mapr ", "maxhp "); exchangeInfo.Enchantments = hasEnchant.Split("\n", 4).ToList(); } break; } if (hasEnchant.ToLower().Contains("exchange price")) { Console.WriteLine("Scrolled wayyyyyy too far"); break; } await android.Swipe(555, 500, 555, 300, 500); await Task.Delay(100); await android.Tap(1500, 960); await android.Screenshot(fileName); i++; } exchangeInfo.Found = true; } return(exchangeInfo); }
public ScanResultItem ParseResultWindowRareItem(string fileName, ScanInfo scanInfo, AndroidConnector android) { ScanResultItem exchangeInfo = new ScanResultItem() { Found = true, ScanInfo = scanInfo }; using (var image = Image.Load <Rgba32>(fileName)) { image.Clone(ctx => ctx.Crop(new Rectangle(996, 159, 549, 66))).Save($"itemname.png"); string itemName = GetTextFromImage("itemname.png"); if ( (!scanInfo.RealName.Contains("★") && itemName.ToLower() != scanInfo.RealName.ToLower()) || (scanInfo.RealName.Contains("★") && !itemName.Contains("*") && itemName.ToLower() != "andrei card" && itemName.ToLower() != "zipper beartcard" && itemName.ToLower() != "archer skeletontcard" ) ) { if (scanInfo.RealName.Contains("★")) { Console.WriteLine("Star card not found"); } scanInfo.Message = "Something is wrong, names do NOT match"; return(ScanResult.BuildError <ScanResultItem>(scanInfo)); } exchangeInfo.Price = int.Parse(GetPrice(image), CultureInfo.InvariantCulture); string amount = GetAmount(image); if (amount == "") { scanInfo.Message = "Could not find the right amount"; return(ScanResult.BuildError <ScanResultItem>(scanInfo)); } exchangeInfo.Amount = int.Parse(amount, CultureInfo.InvariantCulture); exchangeInfo.SnapTime = GetSnapTime(image); exchangeInfo.Found = true; } return(exchangeInfo); }
public async Task <ScanResultItem> ScanRareItem(AndroidConnector android, ScanInfo scanInfo) { Console.WriteLine("- Opening search window"); await CloseSearch(android); await ClickSearchButton(android); await ClickSearchBox(android); string itemName = scanInfo.SearchName; if (itemName.Contains("★")) { itemName = itemName.Substring(0, itemName.IndexOf("★")).Trim(); } await android.Text(itemName); await ClickSearchWindowSearchButton(android); //to close text input await ClickSearchWindowSearchButton(android); Console.WriteLine("- Scanning search result"); await android.Screenshot("searchresult.png"); List <int> indices = FindSearchResult("searchresult.png", scanInfo); if (indices.Count == 0) { //TODO: do something with item0.png - item9.png Console.WriteLine("- Error, could not find item"); await CloseSearch(android); return(ScanResult.BuildError <ScanResultItem>(scanInfo)); } if (indices[0] != scanInfo.SearchIndex) { if (scanInfo.SearchIndex != -1) { Console.WriteLine("- Warning, search index not correct"); } scanInfo.SearchIndex = indices[0]; } for (int i = 0; i < indices.Count; i++) { await ClickSearchWindowIndex(android, indices[i]); await Task.Delay(1500); // the UI needs some time to load the card Console.WriteLine("- Checking if any items are on sale"); await android.Screenshot("shopitems.png"); using (var image = Image.Load <Rgba32>("shopitems.png")) image.Clone(ctx => ctx.Crop(new Rectangle(975, 505, 368, 64))).Save($"nosale.png"); bool nosale = false; if (GetTextFromImage("nosale.png").ToLower().Contains("currently")) { nosale = true; Console.WriteLine("- No items currently on sale"); if (i + 1 >= indices.Count) { return new ScanResultItem() { Found = false, ScanInfo = scanInfo } } ; } if (!nosale) { await ClickShopItem(android, 0); // these items should only give 1 item result await ClickShopBuyButton(android); await Task.Delay(1500); // the UI needs some time to load the card Console.WriteLine("- Scanning item"); await android.Screenshot("shopresult.png"); await ClickShopCloseItem(android); ScanResultItem priceInfo = ParseResultWindowRareItem("shopresult.png", scanInfo, android); if (!priceInfo.Error || i + 1 >= indices.Count) { priceInfo.Error = false; return(priceInfo); } } scanInfo.Message = ""; Console.WriteLine("Item does not match, or not found on exchange with multiple items, trying to rescan it"); await CloseSearch(android); await ClickSearchButton(android); await ClickSearchBox(android); await android.Text(itemName); await ClickSearchWindowSearchButton(android); //to close text input await ClickSearchWindowSearchButton(android); } return(null); } }
private async Task ClickShopItem(AndroidConnector android, int index, int offsety = 0) { await android.Tap(800 + (index % 2) * 600, offsety + 302 + 180 *(index / 2)); }
private async Task ClickSearchWindowIndex(AndroidConnector android, int index) { await android.Tap(SearchResultPositions[index].X + 155, SearchResultPositions[index].Y + 44); }
private async Task ClickSearchWindowSearchButton(AndroidConnector android) { await android.Tap(1400, 260); }
private async Task ClickSearchBox(AndroidConnector android) { await android.Tap(800, 270); }
private async Task CloseSearch(AndroidConnector android) { await android.Tap(1467, 187); }
private async Task ClickSearchButton(AndroidConnector android) { await android.Tap(300, 200); }
private async Task <bool> ScanPage(List <Image <Rgba32> > images, AndroidConnector android, ScanInfo scanInfo, List <ScanResultEquip> result) { string codename = scanInfo.RealName.ToLower(); codename = codename.Replace(" ", "_"); codename = codename.Replace("[1]", "1s"); codename = codename.Replace("[2]", "2s"); using (var image = Image.Load <Rgba32>("shopitems.png")) { //first, look for the top blue line of the item box (RGB(171, 210, 243) if not scrolled half a pixel) int starty = FindFirstResult(image); Program.log.Log(scanInfo.RealName, $"Item list starting at {starty}"); await ClickShopItem(android, 0, starty - 230); //go through all 8 pictures for (int ii = 0; ii < 8; ii++) { int newstarty = FindFirstResult(image); if (newstarty != starty) { Program.log.Log(scanInfo.RealName, $"Scrolled a bit, adjusting"); starty = newstarty; } if (starty + 180 * (ii / 2) + 132 > 902) { continue; } //make a capture of the item, so we don't scan items twice var subImage = image.Clone(ctx => ctx.Crop(new Rectangle(595 + 600 * (ii % 2), starty + 180 * (ii / 2), 400, 132))); if (TestIfScanned(subImage, images)) { Program.log.Log(scanInfo.RealName, $"Item {ii} already scanned, skipping"); continue; } images.Add(subImage); subImage.Save($"unknown/unknown{Directory.GetFiles("unknown").Length}.png"); //click it as visualisation await ClickShopItem(android, ii, starty - 230); //check if item has multiple on sale. If it does, we don't have to scan it because it won't have an enchantment var rect = new Rectangle(694 + 600 * (ii % 2), starty + 103 + 180 * (ii / 2), 33, 28); using (var amountImage = image.Clone(ctx => ctx.Crop(rect))) { //image.Clone(ctx => ctx.Crop(rect)).Save($"unknown/unknown{Directory.GetFiles("unknown").Length}.png"); if (!File.Exists($"data/equip_br/{codename}.png")) { if (!Directory.Exists($"data/equip_br/{codename}")) { Directory.CreateDirectory($"data/equip_br/{codename}"); } amountImage.Save($"data/equip_br/{codename}/{Directory.GetFiles($"data/equip_br/{codename}/").Length}.png"); } else { using (var noamount = Image.Load <Rgba32>($"data/equip_br/{codename}.png")) { int dist = ImageDistance(amountImage, noamount); if (dist > 100) { Program.log.Log(scanInfo.RealName, $"Item {ii} has an amount, not scanning. Distance {dist}"); Console.WriteLine($"- Item {ii} has an amount, not scanning! Distance {dist}"); continue; } } } } //scan item for price and enchantments await Task.Delay(100); Console.WriteLine($"- Scanning item {ii}"); await ClickShopBuyButton(android); await Task.Delay(1000); Console.WriteLine("- Scanning item"); await android.Screenshot("shopresult.png"); ScanResultEquip priceInfo = await ParseResultWindowEquip("shopresult.png", scanInfo, android); result.Add(priceInfo); await Task.Delay(100); await ClickShopCloseItem(android); if (priceInfo.Error) //if error, last one is found { return(true); } } } return(false); }
private async Task ClickShopBuyButton(AndroidConnector android) { await android.Tap(1600, 984); }
private async Task ClickShopCloseItem(AndroidConnector android) { await android.Tap(525, 900); }
public async Task OpenExchange(AndroidConnector android, int map) { await android.Tap(1800, 160); //open minimap await Task.Delay(500); await android.Screenshot("minimap.png"); using (var image = Image.Load <Rgba32>("minimap.png")) image.Clone(ctx => ctx.Crop(new Rectangle(1309, 175, 523, 60))).Save($"mapname.png"); string mapname = GetTextFromImage("mapname.png").ToLower(); await android.Tap(1325, 861); //click world button await Task.Delay(1500); if (mapname == "prontera south gate") { await android.Tap(1100, 700); //click map await Task.Delay(1500); await android.Tap(700, 665); //click big cat man } else if (mapname == "prontera") { await android.Tap(1100, 600); //click map await Task.Delay(1500); await android.Tap(700, 831); //click big cat man } else if (mapname == "morroc") { await android.Tap(1000, 800); //click map await Task.Delay(1500); await android.Tap(700, 782); //click big cat man } else if (mapname == "geffen") { await android.Tap(900, 600); //click map await Task.Delay(1500); await android.Tap(700, 718); //click big cat man } } else if (mapname == "payon") { await android.Tap(1300, 800); //click map await Task.Delay(1500); await android.Tap(700, 716); //click big cat man } else if (mapname == "izlude island") { await android.Tap(1200, 700); //click map await Task.Delay(1500); await android.Tap(700, 432); //click big cat man } else { Program.status.SetSubStatus("Player is at unknown map: " + mapname); } Program.status.SetSubStatus("Waiting for exchange popup"); await Task.Delay(1000); //wait for buy button to appear while (true) { await android.Screenshot("exchange.png"); using (var image = Image.Load <Rgba32>("exchange.png")) using (var cmp = Image.Load <Rgba32>("data/exchange.png")) if (IsSame(image.Clone(ctx => ctx.Crop(new Rectangle(1525, 683, 329, 54))), cmp)) { break; } await Task.Delay(2000); } Program.status.SetSubStatus("Exchange opened, done"); await android.Tap(1660, 705); }