From 455009c09c7a6b7b39bfd29218dc20eb59eba784 Mon Sep 17 00:00:00 2001 From: Dreathorian Date: Thu, 20 May 2021 15:17:38 +0200 Subject: [PATCH 1/2] 3.14 ready - added buyouts for resonators, incubators, fossils, splinters, scarabs etc. - fixed the item parse error so maps and uniques work again. - added a negative lower price range of up to -100 bc poe.ninja prices are weird - made the clipboard listener only listen for 100ms when right mouse was pushed to make it compatible poe awakened poe trade --- EasyBuyout/Hooks/MouseHook.cs | 58 ++++-- EasyBuyout/Item/Item.cs | 224 +++++++++++++------- EasyBuyout/Item/Key.cs | 230 +++++++++++++-------- EasyBuyout/MainWindow.xaml.cs | 23 ++- EasyBuyout/Prices/PriceManager.cs | 1 - EasyBuyout/Settings/Config.cs | 83 ++++---- EasyBuyout/Settings/SettingsWindow.xaml.cs | 4 +- 7 files changed, 400 insertions(+), 223 deletions(-) diff --git a/EasyBuyout/Hooks/MouseHook.cs b/EasyBuyout/Hooks/MouseHook.cs index 353e27a..df868ba 100644 --- a/EasyBuyout/Hooks/MouseHook.cs +++ b/EasyBuyout/Hooks/MouseHook.cs @@ -2,39 +2,55 @@ using System.Diagnostics; using System.Runtime.InteropServices; -namespace EasyBuyout { - public static class MouseHook { +namespace EasyBuyout +{ + public static class MouseHook + { private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); - public static event EventHandler MouseAction; - private static LowLevelMouseProc _proc = HookCallback; - private static IntPtr _hookID = IntPtr.Zero; - private const int WH_MOUSE_LL = 14; - public static void Start() { if (_hookID == IntPtr.Zero) _hookID = SetHook(_proc); } - public static void Stop() { UnhookWindowsHookEx(_hookID); } + public static event Action MouseAction; + private static LowLevelMouseProc _proc = HookCallback; + private static IntPtr _hookID = IntPtr.Zero; + private const int WH_MOUSE_LL = 14; - private static IntPtr SetHook(LowLevelMouseProc proc) { + public static void Start() + { + if (_hookID == IntPtr.Zero) _hookID = SetHook(_proc); + } + + public static void Stop() + { + UnhookWindowsHookEx(_hookID); + } + + private static IntPtr SetHook(LowLevelMouseProc proc) + { using (Process curProcess = Process.GetCurrentProcess()) - using (ProcessModule curModule = curProcess.MainModule) { - return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0); - } + using (ProcessModule curModule = curProcess.MainModule) + { + return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0); + } } private static IntPtr HookCallback( - int nCode, IntPtr wParam, IntPtr lParam) { - if (nCode >= 0 && MouseMessages.WM_RBUTTONDOWN == (MouseMessages)wParam) { - MouseAction?.Invoke(null, new EventArgs()); + int nCode, IntPtr wParam, IntPtr lParam) + { + if (nCode >= 0 && MouseMessages.WM_RBUTTONDOWN == (MouseMessages) wParam) + { + MouseAction?.Invoke(); } + return CallNextHookEx(_hookID, nCode, wParam, lParam); } - private enum MouseMessages { + private enum MouseMessages + { WM_LBUTTONDOWN = 0x0201, - WM_LBUTTONUP = 0x0202, - WM_MOUSEMOVE = 0x0200, - WM_MOUSEWHEEL = 0x020A, + WM_LBUTTONUP = 0x0202, + WM_MOUSEMOVE = 0x0200, + WM_MOUSEWHEEL = 0x020A, WM_RBUTTONDOWN = 0x0204, - WM_RBUTTONUP = 0x0205 + WM_RBUTTONUP = 0x0205 } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] @@ -50,4 +66,4 @@ private enum MouseMessages { [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); } -} +} \ No newline at end of file diff --git a/EasyBuyout/Item/Item.cs b/EasyBuyout/Item/Item.cs index a09ddc9..9150f0d 100644 --- a/EasyBuyout/Item/Item.cs +++ b/EasyBuyout/Item/Item.cs @@ -3,17 +3,20 @@ using System.Linq; using System.Text.RegularExpressions; -namespace EasyBuyout.Item { - public class Item { +namespace EasyBuyout.Item +{ + public class Item + { public readonly List Errors = new List(); - public volatile bool Discard; - public readonly Key Key = new Key(); + public volatile bool Discard; + public readonly Key Key = new Key(); /// /// Default constructor /// /// Copied item data string - public Item(string rawInput) { + public Item(string rawInput) + { var splitRaw = SplitRawInput(rawInput); // If any errors occured in split method if (Discard) return; @@ -30,9 +33,11 @@ public Item(string rawInput) { /// Converts input into an array, replaces newlines with delimiters, splits groups /// /// Formatted list of item data groups - private string[] SplitRawInput(string rawInput) { + private string[] SplitRawInput(string rawInput) + { // All Ctrl+C'd item data must contain "--------" or "Rarity:" - if (!rawInput.Contains("--------") || !rawInput.Contains("Rarity: ")) { + if (!rawInput.Contains("--------") || !rawInput.Contains("Rarity: ")) + { Errors.Add("Clipboard contents did not match Ctrl+C'd item data pattern"); Discard = true; return null; @@ -71,14 +76,17 @@ private string[] SplitRawInput(string rawInput) { var splitRaw = formattedRaw.Split(new[] {"|::|"}, StringSplitOptions.None); // Check validity of item data - foreach (var line in splitRaw) { - if (line.StartsWith("Unidentified")) { + foreach (var line in splitRaw) + { + if (line.StartsWith("Unidentified")) + { Errors.Add("Item is unidentified"); Discard = true; break; } - if (line.StartsWith("Note: ")) { + if (line.StartsWith("Note: ")) + { Errors.Add("Cannot add buyout notes to items that already have them"); Discard = true; break; @@ -91,25 +99,37 @@ private string[] SplitRawInput(string rawInput) { /// /// Checks what data is present and then calls specific parse methods /// - public void ParseItemData(string[] splitRaw) { + public void ParseItemData(string[] splitRaw) + { // Find name, type and rarity - var nameLine = splitRaw[0].Split('|'); - var rarity = TrimProperty(nameLine[0]); + var nameLine = splitRaw[0].Split('|'); + var itemClass = TrimProperty(nameLine[0]); + var rarity = TrimProperty(nameLine[1]); - Key.Name = nameLine[1]; - Key.TypeLine = nameLine.Length > 2 ? nameLine[2] : null; + Key.Name = nameLine[2]; + Key.TypeLine = nameLine.Length > 3 ? nameLine[3] : null; - if (rarity.Equals("Rare")) { - Key.Name = Key.TypeLine; + if (rarity.Equals("Rare")) + { + Key.Name = Key.TypeLine; Key.TypeLine = null; } // Find item's frame type Key.FrameType = Parse_FrameType(splitRaw, rarity); + + if (itemClass.Equals("Maps")) + { + var itemInfo = splitRaw[1].Split('|'); + Key.MapTier = int.Parse(TrimProperty(itemInfo[0])); + return; + + } // If any errors occured in parse function if (Discard) return; - switch (Key.FrameType) { + switch (Key.FrameType) + { case 3: // Find largest link group, if present Key.Links = ParseSockets(splitRaw); @@ -122,50 +142,66 @@ public void ParseItemData(string[] splitRaw) { } } + private static string GetItemClass(string classSubString) + { + var index = classSubString.IndexOf(':'); + return classSubString.Substring(index, classSubString.Length - index); + } + /// /// Extract frame type from item data /// /// /// /// - private int Parse_FrameType(string[] splitRaw, string rarity) { - if (rarity == null) { + private int Parse_FrameType(string[] splitRaw, string rarity) + { + if (rarity == null) + { // Shouldn't run Discard = true; Errors.Add("Invalid rarity"); } - switch (rarity) { + switch (rarity) + { case "Unique": return 3; case "Gem": return 4; case "Currency": return 5; + case "Fragment": + return 0; case "Divination Card": return 6; } // Loop through lines checking for specific strings - foreach (var line in splitRaw) { - if (line.Contains("Right-click to add this prophecy")) { + foreach (var line in splitRaw) + { + if (line.Contains("Right-click to add this prophecy")) + { // Prophecy return 8; } - if (line.Contains("Travel to this Map by using it in")) { + if (line.Contains("Travel to this Map by using it in")) + { // Standardized maps return 0; } - if (line.Equals("Relic Unique")) { + if (line.Equals("Relic Unique")) + { // Relics return 9; } } // If other methods failed use frame type 0 - switch (rarity) { + switch (rarity) + { case "Normal": case "Magic": case "Rare": @@ -187,7 +223,8 @@ private int Parse_FrameType(string[] splitRaw, string rarity) { /// /// /// Socket count (5 or 6) or null - private static int? ParseSockets(string[] splitRaw) { + private static int? ParseSockets(string[] splitRaw) + { // Find what line index socket data is under var lineIndex = FindIndexOf("Sockets:", splitRaw); @@ -198,11 +235,12 @@ private int Parse_FrameType(string[] splitRaw, string rarity) { var socketData = TrimProperty(splitRaw[lineIndex]); // Create array for counting link groups - int[] links = {1, 1, 1, 1, 1}; - var counter = 0; + int[] links = {1, 1, 1, 1, 1}; + var counter = 0; // Count links - for (var i = 1; i < socketData.Length; i += 2) { + for (var i = 1; i < socketData.Length; i += 2) + { if (socketData[i] == '-') links[counter]++; else @@ -220,7 +258,8 @@ private int Parse_FrameType(string[] splitRaw, string rarity) { /// As some specific items have multiple variants, distinguish them /// /// Variant string or null if none - private static string ParseVariant(string[] splitRaw, string name) { + private static string ParseVariant(string[] splitRaw, string name) + { // Find what line index "Item Level:" is under var exModIndex = FindIndexOf("Item Level:", splitRaw); @@ -231,13 +270,15 @@ private static string ParseVariant(string[] splitRaw, string name) { var explicitMods = splitRaw[exModIndex + 1].Split('|'); // Check variation - switch (name) { + switch (name) + { case "Atziri's Splendour": // Take the first explicit mod and replace variables with constants var genericMod = string.Join("#", Regex.Split(explicitMods[0], @"\d+")); // Compare the first generic explicit mod to the preset definitions - switch (genericMod) { + switch (genericMod) + { case "#% increased Armour, Evasion and Energy Shield": return "ar/ev/es"; case "#% increased Armour and Energy Shield": @@ -257,7 +298,8 @@ private static string ParseVariant(string[] splitRaw, string name) { break; case "Vessel of Vinktar": - foreach (var mod in explicitMods) { + foreach (var mod in explicitMods) + { if (mod.Contains("to Spells")) return "spells"; if (mod.Contains("to Attacks")) return "attacks"; if (mod.Contains("Penetrates")) return "penetration"; @@ -270,7 +312,8 @@ private static string ParseVariant(string[] splitRaw, string name) { // Explicit mods for Doryani's Invitation are located 2 lines under the "Item Level:" line explicitMods = splitRaw[exModIndex + 2].Split('|'); - foreach (var mod in explicitMods) { + foreach (var mod in explicitMods) + { if (mod.Contains("Lightning Damage")) return "lightning"; if (mod.Contains("Physical Damage")) return "physical"; if (mod.Contains("Fire Damage")) return "fire"; @@ -280,7 +323,8 @@ private static string ParseVariant(string[] splitRaw, string name) { break; case "Yriel's Fostering": - foreach (var mod in explicitMods) { + foreach (var mod in explicitMods) + { if (mod.Contains("Chaos Damage")) return "snake"; if (mod.Contains("Physical Damage")) return "ursa"; if (mod.Contains("Attack and Movement")) return "rhoa"; @@ -290,15 +334,18 @@ private static string ParseVariant(string[] splitRaw, string name) { case "Volkuur's Guidance": // Figure out on what line explicit mods are located (due to enchantments) - for (int i = exModIndex; i < splitRaw.Length; i++) { - if (splitRaw[i].Contains("to maximum Life")) { + for (int i = exModIndex; i < splitRaw.Length; i++) + { + if (splitRaw[i].Contains("to maximum Life")) + { explicitMods = splitRaw[i].Split('|'); break; } } // Figure out item variant - foreach (var mod in explicitMods) { + foreach (var mod in explicitMods) + { if (mod.Contains("Lightning Damage")) return "lightning"; if (mod.Contains("Fire Damage")) return "fire"; if (mod.Contains("Cold Damage")) return "cold"; @@ -310,7 +357,8 @@ private static string ParseVariant(string[] splitRaw, string name) { // Explicit mods for Impresence are located 2 lines under the "Item Level:" line explicitMods = splitRaw[exModIndex + 2].Split('|'); - foreach (var mod in explicitMods) { + foreach (var mod in explicitMods) + { if (mod.Contains("Lightning Damage")) return "lightning"; if (mod.Contains("Physical Damage")) return "physical"; if (mod.Contains("Chaos Damage")) return "chaos"; @@ -327,15 +375,18 @@ private static string ParseVariant(string[] splitRaw, string name) { case "Command of the Pit": case "Hale Negator": // Figure out on what line explicit mods are located (due to enchantments) - for (int i = exModIndex; i < splitRaw.Length; i++) { - if (splitRaw[i].Contains("Abyssal Socket")) { + for (int i = exModIndex; i < splitRaw.Length; i++) + { + if (splitRaw[i].Contains("Abyssal Socket")) + { explicitMods = splitRaw[i].Split('|'); break; } } // Check how many abyssal sockets the item has - switch (explicitMods[0]) { + switch (explicitMods[0]) + { case "Has 2 Abyssal Sockets": return "2 sockets"; case "Has 1 Abyssal Socket": @@ -346,11 +397,14 @@ private static string ParseVariant(string[] splitRaw, string name) { case "The Beachhead": // Find the line that contains map tier info (e.g "Map Tier: 15") - foreach (var line in splitRaw) { + foreach (var line in splitRaw) + { var subLine = line.Split('|'); - foreach (var prop in subLine) { - if (prop.StartsWith("Map Tier: ")) { + foreach (var prop in subLine) + { + if (prop.StartsWith("Map Tier: ")) + { // Return tier info (e.g "15") return prop.Substring(prop.IndexOf(' ', prop.IndexOf(' ') + 1) + 1); } @@ -363,7 +417,8 @@ private static string ParseVariant(string[] splitRaw, string name) { // Explicit mods for Combat Focus are located 2 lines under the "Item Level:" line explicitMods = splitRaw[exModIndex + 2].Split('|'); - foreach (var mod in explicitMods) { + foreach (var mod in explicitMods) + { if (mod.Contains("choose Lightning")) return "lightning"; if (mod.Contains("choose Cold")) return "cold"; if (mod.Contains("choose Fire")) return "fire"; @@ -379,24 +434,30 @@ private static string ParseVariant(string[] splitRaw, string name) { /// /// Extracts gem information from item data /// - private void ParseGemData(string[] splitRaw, string name) { - var pattern = new Regex(@"\d+"); - int? level = null; - int quality = 0; + private void ParseGemData(string[] splitRaw, string name) + { + var pattern = new Regex(@"\d+"); + int? level = null; + int quality = 0; // Second line will contain gem data var gemLines = splitRaw[1].Split('|'); // Find gem level and quality - foreach (var line in gemLines) { - if (line.Contains("Level:")) { + foreach (var line in gemLines) + { + if (line.Contains("Level:")) + { level = int.Parse(pattern.Match(line).Value); - } else if (line.Contains("Quality:")) { + } + else if (line.Contains("Quality:")) + { quality = int.Parse(pattern.Match(line).Value); } } - if (level == null) { + if (level == null) + { Discard = true; Errors.Add("Couldn't extract gem data"); return; @@ -406,40 +467,55 @@ private void ParseGemData(string[] splitRaw, string name) { var corrupted = splitRaw[splitRaw.Length - 1].Contains("Corrupted"); // Special gems have special needs - if (name.Contains("Empower") || name.Contains("Enlighten") || name.Contains("Enhance")) { + if (name.Contains("Empower") || name.Contains("Enlighten") || name.Contains("Enhance")) + { quality = quality < 10 ? 0 : 20; // Quality doesn't matter for lvl 3 and 4 if (level > 2) quality = 0; - } else { + } + else + { // Logically speaking, a lvl 17 gem is closer to lvl1 in terms of value compared to lvl20 - if (level < 18) { + if (level < 18) + { level = 1; - } else if (level < 21) { + } + else if (level < 21) + { level = 20; } - if (quality < 17) { + if (quality < 17) + { quality = 0; - } else if (quality < 22) { + } + else if (quality < 22) + { quality = 20; - } else { + } + else + { quality = 23; } // Gets rid of specific gems (lvl:1 quality:23-> lvl:1 quality:20) - if (level < 20 && quality > 20) { + if (level < 20 && quality > 20) + { quality = 20; } - if (level > 20 || quality > 20) { + if (level > 20 || quality > 20) + { corrupted = true; - } else if (name.Contains("Vaal")) { + } + else if (name.Contains("Vaal")) + { corrupted = true; } } - Key.GemLevel = level; - Key.GemQuality = quality; + Key.GemLevel = level; + Key.GemQuality = quality; Key.GemCorrupted = corrupted; } @@ -453,9 +529,12 @@ private void ParseGemData(string[] splitRaw, string name) { /// String to search for /// Array to search it in /// - private static int FindIndexOf(string needle, string[] haystack) { - for (int i = 0; i < haystack.Length; i++) { - if (haystack[i].StartsWith(needle)) { + private static int FindIndexOf(string needle, string[] haystack) + { + for (int i = 0; i < haystack.Length; i++) + { + if (haystack[i].StartsWith(needle)) + { return i; } } @@ -468,8 +547,9 @@ private static int FindIndexOf(string needle, string[] haystack) { /// /// "Sockets: B - B B " /// "B - B B" - private static string TrimProperty(string str) { - var index = str.IndexOf(' ') + 1; + private static string TrimProperty(string str) + { + var index = str.IndexOf(':') + 2; return str.Substring(index, str.Length - index).Trim(); } } diff --git a/EasyBuyout/Item/Key.cs b/EasyBuyout/Item/Key.cs index cd8983c..9c2cd4b 100644 --- a/EasyBuyout/Item/Key.cs +++ b/EasyBuyout/Item/Key.cs @@ -1,14 +1,19 @@ using System; +using System.Linq; using System.Text; using EasyBuyout.Prices; -namespace EasyBuyout.Item { - public class Key { +namespace EasyBuyout.Item +{ + public class Key + { public string Name, TypeLine, Variation; - public int FrameType; - public int? Links, MapTier, GemLevel, GemQuality; - public bool? GemCorrupted; + public int FrameType; + public int? Links, MapTier, GemLevel, GemQuality; + public bool? GemCorrupted; + + private static string[] SimplifiedCurrencies = {"Oil", "Essence", "DeliriumOrb"}; public Key() { } /// @@ -16,42 +21,57 @@ public Key() { } /// /// /// - public Key(string category, PoeNinjaEntry entry) { - // Currency is handled in a different API format - if (category.Equals("Currency")) { - Name = entry.currencyTypeName; + public Key(string category, PoeNinjaEntry entry) + { + // Currency is handled in a different API format, yeah bc it's retarded -.- + if (category.Equals("Currency")) + { + Name = entry.currencyTypeName; FrameType = 5; return; } + foreach (var s in SimplifiedCurrencies) + if (s == category) + { + Name = entry.name; + FrameType = 5; + return; + } // Fragments are handled in a different API format - if (category.Equals("Fragment")) { - Name = entry.currencyTypeName; - FrameType = 0; + if (category.Equals("Fragment")) + { + Name = entry.currencyTypeName; + FrameType = entry.currencyTypeName.Contains("Splinter") ? 5 : 0; return; } - Name = entry.name; - TypeLine = entry.baseType; + + Name = entry.name; + TypeLine = entry.baseType; FrameType = entry.itemClass; - Links = entry.links; - MapTier = entry.mapTier; - GemLevel = entry.gemLevel; - GemQuality = entry.gemQuality; + Links = entry.links; + MapTier = entry.mapTier; + GemLevel = entry.gemLevel; + GemQuality = entry.gemQuality; GemCorrupted = entry.corrupted; - Variation = entry.variant; + Variation = entry.variant; // For gems - if (FrameType == 4) { + if (FrameType == 4) + { // Gems have variants? Variation = null; } // For non-maps - if (MapTier == 0) { + if (MapTier == 0) + { MapTier = null; - } else if (FrameType != 3) { + } + else if (FrameType != 3) + { // Maps have random frametypes FrameType = 0; // Can't determine map series from item data so map variation is unusable for us @@ -59,25 +79,29 @@ public Key(string category, PoeNinjaEntry entry) { } // For items with variations - if (Variation != null) { + if (Variation != null) + { Variation = FixPoeNinjaVariant(Name, Variation); } // For non- 6L and 5L - if (Links == 0) { + if (Links == 0) + { Links = null; } // For non-gems - if (FrameType != 4) { - GemLevel = null; - GemQuality = null; + if (FrameType != 4) + { + GemLevel = null; + GemQuality = null; GemCorrupted = null; } // For normal maps - if (MapTier == 0 && FrameType == 0) { + if (MapTier == 0 && FrameType == 0) + { // Name is type line for some reason TypeLine = null; // Variant refers to map type @@ -85,41 +109,47 @@ public Key(string category, PoeNinjaEntry entry) { } } - private string FixPoeNinjaVariant(string name, string variant) { - if (variant == null) { + private string FixPoeNinjaVariant(string name, string variant) + { + if (variant == null) + { return null; } - switch (name) { + switch (name) + { case "Atziri's Splendour": - switch (variant) { - case "Armour/ES": return "ar/es"; - case "ES": return "es"; - case "Armour/Evasion": return "ar/ev"; - case "Armour/ES/Life": return "ar/es/li"; - case "Evasion/ES": return "ev/es"; + switch (variant) + { + case "Armour/ES": return "ar/es"; + case "ES": return "es"; + case "Armour/Evasion": return "ar/ev"; + case "Armour/ES/Life": return "ar/es/li"; + case "Evasion/ES": return "ev/es"; case "Armour/Evasion/ES": return "ar/ev/es"; - case "Evasion": return "ev"; - case "Evasion/ES/Life": return "ev/es/li"; - case "Armour": return "ar"; + case "Evasion": return "ev"; + case "Evasion/ES/Life": return "ev/es/li"; + case "Armour": return "ar"; } break; case "Yriel's Fostering": - switch (variant) { + switch (variant) + { case "Bleeding": return "ursa"; - case "Poison": return "snake"; - case "Maim": return "rhoa"; + case "Poison": return "snake"; + case "Maim": return "rhoa"; } break; case "Volkuur's Guidance": - switch (variant) { + switch (variant) + { case "Lightning": return "lightning"; - case "Fire": return "fire"; - case "Cold": return "cold"; + case "Fire": return "fire"; + case "Cold": return "cold"; } break; @@ -130,40 +160,44 @@ private string FixPoeNinjaVariant(string name, string variant) { case "Tombfist": case "Command of the Pit": case "Hale Negator": - switch (variant) { + switch (variant) + { case "2 Jewels": return "2 sockets"; - case "1 Jewel": return "1 socket"; + case "1 Jewel": return "1 socket"; } break; case "Vessel of Vinktar": - switch (variant) { + switch (variant) + { case "Added Attacks": return "attacks"; - case "Added Spells": return "spells"; - case "Penetration": return "penetration"; - case "Conversion": return "conversion"; + case "Added Spells": return "spells"; + case "Penetration": return "penetration"; + case "Conversion": return "conversion"; } break; case "Doryani's Invitation": - switch (variant) { + switch (variant) + { case null: // Bug on poe.ninja's end case "Physical": return "physical"; - case "Fire": return "fire"; - case "Cold": return "cold"; + case "Fire": return "fire"; + case "Cold": return "cold"; case "Lightning": return "lightning"; } break; case "Impresence": - switch (variant) { - case "Chaos": return "chaos"; - case "Physical": return "physical"; - case "Fire": return "fire"; - case "Cold": return "cold"; + switch (variant) + { + case "Chaos": return "chaos"; + case "Physical": return "physical"; + case "Fire": return "fire"; + case "Cold": return "cold"; case "Lightning": return "lightning"; } @@ -178,61 +212,74 @@ private string FixPoeNinjaVariant(string name, string variant) { return null; } - public override bool Equals(object obj) { - if (obj == null) { + public override bool Equals(object obj) + { + if (obj == null) + { return false; } - if (typeof(Key) != obj.GetType()) { + if (typeof(Key) != obj.GetType()) + { return false; } var other = (Key) obj; - if (FrameType != other.FrameType) { + if (FrameType != other.FrameType) + { return false; } - if (!Name?.Equals(other.Name) ?? (other.Name != null)) { + if (!Name?.Equals(other.Name) ?? (other.Name != null)) + { return false; } - if (!TypeLine?.Equals(other.TypeLine) ?? (other.TypeLine != null)) { + if (!TypeLine?.Equals(other.TypeLine) ?? (other.TypeLine != null)) + { return false; } - if (!Variation?.Equals(other.Variation) ?? (other.Variation != null)) { + if (!Variation?.Equals(other.Variation) ?? (other.Variation != null)) + { return false; } - if (!Links?.Equals(other.Links) ?? (other.Links != null)) { + if (!Links?.Equals(other.Links) ?? (other.Links != null)) + { return false; } - if (!GemLevel?.Equals(other.GemLevel) ?? (other.GemLevel != null)) { + if (!GemLevel?.Equals(other.GemLevel) ?? (other.GemLevel != null)) + { return false; } - if (!GemQuality?.Equals(other.GemQuality) ?? (other.GemQuality != null)) { + if (!GemQuality?.Equals(other.GemQuality) ?? (other.GemQuality != null)) + { return false; } - if (!MapTier?.Equals(other.MapTier) ?? (other.MapTier != null)) { + if (!MapTier?.Equals(other.MapTier) ?? (other.MapTier != null)) + { return false; } - if (!GemCorrupted?.Equals(other.GemCorrupted) ?? (other.GemCorrupted != null)) { + if (!GemCorrupted?.Equals(other.GemCorrupted) ?? (other.GemCorrupted != null)) + { return false; } return true; } - public override int GetHashCode() { + public override int GetHashCode() + { var hash = 3; - hash = 53 * hash + (Name?.GetHashCode() ?? 0); - hash = 53 * hash + (TypeLine?.GetHashCode() ?? 0); + hash = 53 * hash + (Name?.GetHashCode() ?? 0); + hash = 53 * hash + (TypeLine?.GetHashCode() ?? 0); hash = 53 * hash + (Variation?.GetHashCode() ?? 0); hash = 53 * hash + (Links.GetHashCode()); hash = 53 * hash + (GemLevel.GetHashCode()); @@ -244,54 +291,65 @@ public override int GetHashCode() { return hash; } - public override string ToString() { + public override string ToString() + { var builder = new StringBuilder(); builder.Append($"{Name}"); - if (TypeLine != null) { + if (TypeLine != null) + { builder.Append($", {TypeLine}"); } - if (Variation != null) { + if (Variation != null) + { builder.Append($" ({Variation})"); } return builder.ToString(); } - public string ToFullString() { + public string ToFullString() + { var builder = new StringBuilder(); builder.Append($"name:'{Name}'"); - if (TypeLine != null) { + if (TypeLine != null) + { builder.Append($",type:'{TypeLine}'"); } builder.Append($",frame:'{FrameType}'"); - if (Variation != null) { + if (Variation != null) + { builder.Append($",var:'{Variation}'"); } - if (Links != null) { + if (Links != null) + { builder.Append($",links:'{Links}'"); } - if (MapTier != null) { + if (MapTier != null) + { builder.Append($",tier:'{MapTier}'"); } - if (GemLevel != null) { + if (GemLevel != null) + { builder.Append($",lvl:'{GemLevel}'"); } - if (GemQuality != null) { + if (GemQuality != null) + { builder.Append($",quality:'{GemQuality}'"); } - if (GemCorrupted != null) { + if (GemCorrupted != null) + { builder.Append($",corrupted:'{GemCorrupted}'"); } diff --git a/EasyBuyout/MainWindow.xaml.cs b/EasyBuyout/MainWindow.xaml.cs index f2bcd8f..16cd83f 100644 --- a/EasyBuyout/MainWindow.xaml.cs +++ b/EasyBuyout/MainWindow.xaml.cs @@ -73,6 +73,7 @@ public MainWindow() { }); } + private bool _checkActive = false; //----------------------------------------------------------------------------------------------------------- // External event handlers //----------------------------------------------------------------------------------------------------------- @@ -82,12 +83,15 @@ public MainWindow() { /// /// /// - private void Event_mouse(object sender, EventArgs e) { + private void Event_mouse() { // Do not run if user has not pressed run button if (!_config.FlagRun) { return; } + _checkActive = true; + Task.Delay(100).ContinueWith(t => _checkActive = false); + // Send Ctrl+C on mouse click KeyEmulator.SendCtrlC(); } @@ -97,7 +101,7 @@ private void Event_mouse(object sender, EventArgs e) { /// private void Event_clipboard(object sender, EventArgs e) { // Do not run if user has not pressed run button - if (!_config.FlagRun) { + if (!_config.FlagRun || !_checkActive) { return; } @@ -111,7 +115,16 @@ private void Event_clipboard(object sender, EventArgs e) { Thread.Sleep(_config.ClipboardWriteDelay); // Get clipboard contents - var clipboardString = Clipboard.GetText(); + var clipboardString = string.Empty; + try + { + clipboardString = Clipboard.GetText(); + } + catch (Exception exception) + { + //awakened poe trade came first. probably should check if right mouse has been pressed shortly before to prevent this kind of fetching + //Log(exception.ToString()); + } // This event handles *all* clipboard events if (clipboardString.StartsWith("~")) { @@ -130,7 +143,7 @@ private void ClipBoard_ItemParseTask(string clipboardString) { // If the item was shite, discard it if (item.Discard) { - System.Media.SystemSounds.Asterisk.Play(); + //System.Media.SystemSounds.Asterisk.Play(); foreach (var error in item.Errors) { Log(error, Flair.Error); @@ -154,7 +167,7 @@ private void ClipBoard_ItemParseTask(string clipboardString) { } double price; - if (_config.LowerPricePercentage > 0) { + if (_config.LowerPricePercentage > -100) { price = (entry.Value * (100 - _config.LowerPricePercentage)) / 100.0; } else { price = entry.Value; diff --git a/EasyBuyout/Prices/PriceManager.cs b/EasyBuyout/Prices/PriceManager.cs index be77b8b..d4741db 100644 --- a/EasyBuyout/Prices/PriceManager.cs +++ b/EasyBuyout/Prices/PriceManager.cs @@ -70,7 +70,6 @@ public void Download() { Console.WriteLine($"Duplicate key for {key}"); continue; } - _entryMap.Add(new Key(category, line), new Entry(line.GetValue(), line.count)); } } catch (Exception ex) { diff --git a/EasyBuyout/Settings/Config.cs b/EasyBuyout/Settings/Config.cs index 3374ebd..0ccabd5 100644 --- a/EasyBuyout/Settings/Config.cs +++ b/EasyBuyout/Settings/Config.cs @@ -1,59 +1,70 @@ using System.Collections.Generic; using EasyBuyout.Settings.Source; -namespace EasyBuyout.Settings { - public class Config { +namespace EasyBuyout.Settings +{ + public class Config + { //----------------------------------------------------------------------------------------------------------- // Readonly //----------------------------------------------------------------------------------------------------------- public readonly SourceSite Source; - public readonly string ProgramTitle = "EasyBuyout"; - public readonly string ProgramVersion = "v1.1.2"; + public readonly string ProgramTitle = "EasyBuyout"; + public readonly string ProgramVersion = "v1.1.2"; - public readonly string LeagueApiUrl = "https://www.pathofexile.com/api/trade/data/leagues"; + public readonly string LeagueApiUrl = "https://www.pathofexile.com/api/trade/data/leagues"; public readonly string ManualLeagueDisplay = ""; - public readonly string GithubReleaseApi = "https://api.github.com/repos/siegrest/EasyBuyout/releases"; - public readonly int LiveUpdateDelayMs = 600000; // Update prices every x milliseconds + public readonly string GithubReleaseApi = "https://api.github.com/repos/siegrest/EasyBuyout/releases"; + public readonly int LiveUpdateDelayMs = 600000; // Update prices every x milliseconds //----------------------------------------------------------------------------------------------------------- // Dynamic //----------------------------------------------------------------------------------------------------------- - public string NotePrefix { get; set; } = "~b/o"; - public string SelectedLeague { get; set; } - public int LowerPricePercentage { get; set; } = 0; - public int PasteDelay { get; set; } = 120; - public int ClipboardWriteDelay { get; set; } = 4; - public int PricePrecision { get; set; } = 1; + public string NotePrefix { get; set; } = "~b/o"; + public string SelectedLeague { get; set; } + public int LowerPricePercentage { get; set; } = 0; + public int PasteDelay { get; set; } = 120; + public int ClipboardWriteDelay { get; set; } = 4; + public int PricePrecision { get; set; } = 1; - public bool FlagSendNote { get; set; } = true; - public bool FlagSendEnter { get; set; } = false; + public bool FlagSendNote { get; set; } = true; + public bool FlagSendEnter { get; set; } = false; public bool FlagShowOverlay { get; set; } = false; - public bool FlagLiveUpdate { get; set; } = true; - public bool FlagRun { get; set; } = false; + public bool FlagLiveUpdate { get; set; } = true; + public bool FlagRun { get; set; } = false; - public Config() { + public Config() + { // Initialize data sources - Source = new SourceSite() { - Name = "Poe.Ninja", - SourceApis = new List() { - new SourceApi() { - Display = "Currency", - Url = "https://poe.ninja/api/data/currencyoverview?league={league}&type={category}", - Categories = new List() { - "Currency", "Fragment" - } - }, - new SourceApi() { - Display = "Items", - Url = "https://poe.ninja/api/data/itemoverview?league={league}&type={category}", - Categories = new List() { - "UniqueArmour", "Essence", "DivinationCard", "Prophecy", "UniqueMap", - "Map", "UniqueJewel", "UniqueFlask", "UniqueWeapon", "UniqueAccessory", "SkillGem" - } + Source = new SourceSite() + { + Name = "Poe.Ninja", + SourceApis = new List() + { + new SourceApi() + { + Display = "Currency", + Url = "https://poe.ninja/api/data/currencyoverview?league={league}&type={category}", + Categories = new List() + { + "Currency", "Fragment" + } + }, + new SourceApi() + { + Display = "Items", + Url = "https://poe.ninja/api/data/itemoverview?league={league}&type={category}", + Categories = new List() + { + "Resonator", "Incubator", "UniqueMap", "Essence", "Scarab", "Fossil", "Oil", "DeliriumOrb", + "DivinationCard", "Prophecy", + "Map", "UniqueArmour", "UniqueJewel", "UniqueFlask", "UniqueWeapon", + "UniqueAccessory", "SkillGem" + } + } } - } }; } } diff --git a/EasyBuyout/Settings/SettingsWindow.xaml.cs b/EasyBuyout/Settings/SettingsWindow.xaml.cs index fd2180c..ef18189 100644 --- a/EasyBuyout/Settings/SettingsWindow.xaml.cs +++ b/EasyBuyout/Settings/SettingsWindow.xaml.cs @@ -92,8 +92,8 @@ private void Button_Apply_Click(object sender, RoutedEventArgs e) { // Lower price % box int.TryParse(TextBox_LowerPrice.Text, out var newLowerPercentage); if (newLowerPercentage != _config.LowerPricePercentage) { - if (newLowerPercentage < 0 || newLowerPercentage > 100) { - _log("Invalid input - percentage (allowed: 0 - 100)", MainWindow.Flair.Warn); + if (newLowerPercentage < -100 || newLowerPercentage > 100) { + _log("Invalid input - percentage (allowed: -100 - 100)", MainWindow.Flair.Warn); TextBox_LowerPrice.Text = _config.LowerPricePercentage.ToString(); } else { _log($"Changed percentage {_config.LowerPricePercentage} -> {newLowerPercentage}", From 6ff895f2a5a8aaacea47f0d748c013757a259c8f Mon Sep 17 00:00:00 2001 From: Dreathorian Date: Sun, 23 May 2021 17:20:41 +0200 Subject: [PATCH 2/2] Added auto download and config serialization Added auto download and config serialization (save configs) for some reason nuget server wasnt reachable so I couldn't just json serialize it... whatever, easy fix --- EasyBuyout/App.config | 6 +- EasyBuyout/EasyBuyout.csproj | 3 +- EasyBuyout/MainWindow.xaml | 5 +- EasyBuyout/MainWindow.xaml.cs | 219 ++++++++++++-------- EasyBuyout/Properties/Resources.Designer.cs | 2 +- EasyBuyout/Properties/Settings.Designer.cs | 2 +- EasyBuyout/Settings/Config.cs | 151 ++++++++++++-- EasyBuyout/Settings/SettingsWindow.xaml.cs | 11 +- 8 files changed, 283 insertions(+), 116 deletions(-) diff --git a/EasyBuyout/App.config b/EasyBuyout/App.config index 731f6de..d1428ad 100644 --- a/EasyBuyout/App.config +++ b/EasyBuyout/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/EasyBuyout/EasyBuyout.csproj b/EasyBuyout/EasyBuyout.csproj index 01f7671..38df9e0 100644 --- a/EasyBuyout/EasyBuyout.csproj +++ b/EasyBuyout/EasyBuyout.csproj @@ -8,11 +8,12 @@ WinExe EasyBuyout EasyBuyout - v4.6.1 + v4.5 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 true + AnyCPU diff --git a/EasyBuyout/MainWindow.xaml b/EasyBuyout/MainWindow.xaml index a6cf51f..aded609 100644 --- a/EasyBuyout/MainWindow.xaml +++ b/EasyBuyout/MainWindow.xaml @@ -7,9 +7,8 @@ mc:Ignorable="d" WindowStartupLocation="CenterScreen" Margin="0" Padding="0" Closing="Window_Closing" MinWidth="598" MinHeight="281" SizeToContent="WidthAndHeight" Loaded="Window_Loaded"> -