private static async Task <bool> DepositLoop(int index) { string name = ItemSortStatus.GetByIndex(index).Name; if (ItemSortStatus.GetByIndex(ItemSortStatus.PlayerInventoryIndex).AllBelong()) { LogCritical($"We tried depositing to {name} but everything in the Player Inventory belongs there...?"); return(false); } if (BagsFreeSlotCount(index) == 0) { LogCritical($"We tried depositing to {name} but their inventory was full!"); return(false); } Log($"Depositing items to {name}..."); var moveCount = 0; foreach (BagSlot bagSlot in GeneralFunctions.MainBagsFilledSlots()) { if (BagsFreeSlotCount(index) == 0) { LogCritical($"Stopping deposits to {name} because their inventory is full!"); return(false); } var sortInfo = ItemSortStatus.GetSortInfo(bagSlot.TrueItemId); if (sortInfo.SortStatus(index) == SortStatus.BelongsInIndex) { bool moveResult; if (index == ItemSortStatus.SaddlebagInventoryIndex) { moveResult = await bagSlot.TryAddToSaddlebag(bagSlot.Count, AutoRetainerSortSettings.Instance.ItemMoveWaitMs); } else { moveResult = await bagSlot.TryEntrustToRetainer(bagSlot.Count, AutoRetainerSortSettings.Instance.ItemMoveWaitMs); } if (moveResult) { LogSuccess($"Deposited {sortInfo.Name}."); if (sortInfo.ItemInfo.Unique) { ItemSortStatus.PlayerInventoryUniques.Remove(sortInfo.TrueItemId); ItemSortStatus.TryingToMoveUniques.Remove(sortInfo.TrueItemId); } moveCount++; } else { LogCritical($"Something went wrong with depositing {sortInfo.Name}, it's still in the same slot!"); } } } return(moveCount > 0); }
public static async Task CombineStacks(IEnumerable <BagSlot> bagSlotsEnumerable) { var bagSlots = bagSlotsEnumerable.ToArray(); if (!bagSlots.Any()) { return; } var groupedSlots = bagSlots .Where(x => x.IsValid && x.IsFilled && (x.Item?.StackSize ?? 0) > 1) .GroupBy(x => x.TrueItemId) .Where(x => x.Count(slot => slot.Count < slot.Item.StackSize) > 1); foreach (var slotGrouping in groupedSlots) { if (slotGrouping.Key > ItemSortInfo.CollectableOffset) { continue; } LogSuccess($"Combining stacks of {ItemSortStatus.GetSortInfo(slotGrouping.Key).Name}"); var bagSlotArray = slotGrouping.OrderByDescending(x => x.Count).ToArray(); int moveToIndex = Array.FindIndex(bagSlotArray, x => x.Count < x.Item.StackSize); if (moveToIndex < 0) { continue; } for (int i = bagSlotArray.Length - 1; i > moveToIndex; i--) { var moveFromSlot = bagSlotArray[i]; if (moveFromSlot == null || !moveFromSlot.IsValid || !moveFromSlot.IsFilled) { continue; } uint curCount = bagSlotArray[moveToIndex].Count; bool result = moveFromSlot.Move(bagSlotArray[moveToIndex]); if (result) { await Coroutine.Wait(3000, () => curCount != bagSlotArray[moveToIndex].Count); } await Coroutine.Yield(); BagSlot curMoveTo = bagSlotArray[moveToIndex]; if (curMoveTo.Count >= curMoveTo.Item.StackSize) { moveToIndex = Array.FindIndex(bagSlotArray, x => x.IsValid && x.IsFilled && x.Count < x.Item.StackSize); } } } }
private void AddNewItem_Click(object sender, EventArgs e) { var toAddIds = new HashSet <uint>(); using (AddNewItemForm newItemForm = new AddNewItemForm()) { DialogResult dr = newItemForm.ShowDialog(this); if (dr != DialogResult.OK) { return; } SearchResult selectedItem = newItemForm.SelectedSearchResult; if (selectedItem == null || selectedItem.RawItemId == 0) { return; } if (newItemForm.ModifierNone) { toAddIds.Add(selectedItem.RawItemId); } else if (newItemForm.ModifierHQ) { toAddIds.Add(selectedItem.RawItemId + QualityOffset); } else if (newItemForm.ModifierCollectable) { toAddIds.Add(selectedItem.RawItemId + CollectableOffset); } else { return; } if (newItemForm.IncludeHQ) { toAddIds.Add(selectedItem.RawItemId + QualityOffset); } if (newItemForm.IncludeCollectable) { toAddIds.Add(selectedItem.RawItemId + CollectableOffset); } } foreach (uint toAddId in toAddIds) { ItemSortInfo sortInfo = ItemSortStatus.GetSortInfo(toAddId); var shouldAdd = true; foreach (var indexInfoPair in AutoRetainerSortSettings.Instance.InventoryOptions) { if (indexInfoPair.Key == _index) { continue; } if (!indexInfoPair.Value.ContainsItem(sortInfo)) { continue; } if (sortInfo.ItemInfo.Unique) { continue; } DialogResult dr = MessageBox.Show( string.Format(Strings.AddNewItem_AlreadyExists_Warning, indexInfoPair.Value.Name, sortInfo.Name, indexInfoPair.Value.Name, _sortInfo.Name), Strings.WarningCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (dr == DialogResult.Yes) { indexInfoPair.Value.SpecificItems.Remove(sortInfo); } else { shouldAdd = false; break; } } if (!shouldAdd) { continue; } AutoRetainerSort.LogSuccess($"Added {sortInfo.Name} to {_sortInfo.Name}!"); _bsItems.Add(sortInfo); } AutoRetainerSortSettings.Instance.Save(); }
public static void PopulateSettings(string settingsPath) { if (string.IsNullOrEmpty(settingsPath)) { AutoRetainerSort.LogCritical("Provided Lisbeth settings path is invalid!"); return; } JObject settingsJObject = GetJObject(settingsPath); LisbethRetainerRules knownRules = new LisbethRetainerRules(settingsJObject); foreach (var indexInfoPair in AutoRetainerSortSettings.Instance.InventoryOptions) { if (!knownRules.RulesByIndex.ContainsKey(indexInfoPair.Key)) { continue; } var ruleList = knownRules.RulesByIndex[indexInfoPair.Key]; foreach (uint itemId in indexInfoPair.Value.SpecificItems.Select(x => x.RawItemId).Distinct()) { ruleList.Add(new LisbethRetainerRules.ItemRule(itemId)); } } foreach (CachedInventory cachedInventory in ItemSortStatus.GetAllInventories()) { if (!knownRules.RulesByIndex.ContainsKey(cachedInventory.Index)) { continue; } var ruleList = knownRules.RulesByIndex[cachedInventory.Index]; foreach (ItemSortInfo sortInfo in cachedInventory.ItemCounts.Select(x => ItemSortStatus.GetSortInfo(x.Key)).Distinct()) { if (sortInfo.ItemInfo.Unique || sortInfo.ItemInfo.StackSize <= 1) { continue; } ruleList.Add(new LisbethRetainerRules.ItemRule(sortInfo.RawItemId)); } } SetRules(settingsJObject, knownRules); using (StreamWriter outputFile = new StreamWriter(settingsPath, false)) { outputFile.Write(JsonConvert.SerializeObject(settingsJObject, Formatting.None)); } }
private void AutoSetup_Click(object sender, EventArgs e) { if (!AutoRetainerSortSettings.Instance.InventoryOptions.ContainsKey(ItemSortStatus.PlayerInventoryIndex)) { DialogResult dr = MessageBox.Show( "It looks like you don't have the player inventory added to the indexes... somehow. Do you want me to re-add that for you?", "Um.", MessageBoxButtons.YesNo, MessageBoxIcon.Warning ); if (dr == DialogResult.Yes) { AutoRetainerSortSettings.Instance.InventoryOptions.Add(ItemSortStatus.PlayerInventoryIndex, new InventorySortInfo("Player Inventory")); } } if (!AutoRetainerSortSettings.Instance.InventoryOptions.ContainsKey(ItemSortStatus.SaddlebagInventoryIndex)) { DialogResult dr = MessageBox.Show( "It looks like you don't have the chocobo saddlebag added to the indexes. Do you want me to re-add that for you?", "Hey Listen!", MessageBoxButtons.YesNo, MessageBoxIcon.Information ); if (dr == DialogResult.Yes) { AutoRetainerSortSettings.Instance.InventoryOptions.Add(ItemSortStatus.SaddlebagInventoryIndex, new InventorySortInfo("Chocobo Saddlebag")); } } MessageBox.Show( Strings.AutoSetup_CacheAdvice, "Careful!", MessageBoxButtons.OK, MessageBoxIcon.Information); DialogResult warningResult = MessageBox.Show( Strings.AutoSetup_OverwriteWarning, "Warning!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (warningResult == DialogResult.No) { return; } bool conflictUnsorted = MessageBox.Show( Strings.AutoSetup_ConflictQuestion, "Conflict?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes; var newInventorySetup = AutoRetainerSortSettings.Instance.InventoryOptions; foreach (InventorySortInfo inventorySortInfo in newInventorySetup.Values) { inventorySortInfo.SortTypes.Clear(); } var orderedRetainerList = RetainerList.Instance.OrderedRetainerList; for (var i = 0; i < orderedRetainerList.Length; i++) { if (newInventorySetup.ContainsKey(i)) { continue; } RetainerInfo retInfo = orderedRetainerList[i]; if (!retInfo.Active) { continue; } newInventorySetup.Add(i, new InventorySortInfo(retInfo.Name)); } AutoRetainerSortSettings.Instance.InventoryOptions = newInventorySetup; ItemSortStatus.UpdateFromCache(orderedRetainerList); var sortTypeCounts = new Dictionary <SortType, Dictionary <int, int> >(); foreach (SortType sortType in Enum.GetValues(typeof(SortType)).Cast <SortType>()) { sortTypeCounts[sortType] = new Dictionary <int, int>(); } foreach (CachedInventory cachedInventory in ItemSortStatus.GetAllInventories()) { foreach (SortType sortType in cachedInventory.ItemCounts.Select(x => ItemSortStatus.GetSortInfo(x.Key).SortType)) { var indexCountDic = sortTypeCounts[sortType]; if (indexCountDic.ContainsKey(cachedInventory.Index)) { indexCountDic[cachedInventory.Index]++; } else { indexCountDic.Add(cachedInventory.Index, 1); } } } foreach (var typeDicPair in sortTypeCounts) { SortType sortType = typeDicPair.Key; int indexCount = typeDicPair.Value.Keys.Count; if (indexCount == 0) { continue; } if (indexCount > 1 && conflictUnsorted) { continue; } int desiredIndex = typeDicPair.Value.OrderByDescending(x => x.Value).First().Key; AutoRetainerSortSettings.Instance.InventoryOptions[desiredIndex].SortTypes.Add(new SortTypeWithCount(sortType)); } ResetBindingSource(); AutoRetainerSortSettings.Instance.Save(); AutoRetainerSort.LogSuccess("Auto-Setup done!"); }
private async Task <bool> Run() { if (AutoRetainerSortSettings.Instance.InventoryOptions.Count == 0) { LogCritical("You don't have any inventories (or sorting rules for them) added yet! Go check the settings?"); TreeRoot.Stop("No sort settings."); return(false); } if (!ItemSortStatus.AnyRulesExist()) { LogCritical("You don't have any sorting rules set up... maybe go hit the Auto-Setup button?"); TreeRoot.Stop("No sort settings."); return(false); } LogCritical($"The journey begins! {Strings.AutoSetup_CacheAdvice}"); await GeneralFunctions.StopBusy(true, true, false); var retData = await HelperFunctions.GetOrderedRetainerArray(true); if (retData.Length == 0) { LogCritical("No retainers. Exiting."); TreeRoot.Stop("No retainer data found."); return(false); } foreach (var pair in AutoRetainerSortSettings.Instance.InventoryOptions) { if (pair.Key < 0) { continue; } if (pair.Key >= retData.Length) { LogCritical($"{pair.Value.Name}'s index of {pair.Key.ToString()} doesn't exist in retainer data."); TreeRoot.Stop("Invalid index."); return(false); } if (!retData[pair.Key].Active) { LogCritical($"{pair.Value.Name} isn't an active retainer!"); TreeRoot.Stop("Retainer inactive."); return(false); } } ItemSortStatus.ItemSortInfoCache.Clear(); await ItemFinder.FlashSaddlebags(); ItemSortStatus.UpdateFromCache(retData); if (AutoRetainerSortSettings.Instance.PrintMoves) { alreadyPrintedUniques.Clear(); foreach (CachedInventory cachedInventory in ItemSortStatus.GetAllInventories()) { PrintMoves(cachedInventory.Index); } } while (ItemSortStatus.AnyUnsorted()) { if (ItemSortStatus.FilledAndSortedInventories.Contains(ItemSortStatus.PlayerInventoryIndex)) { LogCritical("Everything currently in the player's inventory belongs there, but it's full! Can't move items like this. I quit."); break; } await DepositFromPlayer(); await RetrieveFromInventories(); await Coroutine.Sleep(250); ItemSortStatus.UpdateFromCache(retData); await Coroutine.Sleep(250); } foreach (CachedInventory cachedInventory in ItemSortStatus.GetAllInventories()) { foreach (ItemSortInfo sortInfo in cachedInventory.ItemCounts.Select(x => ItemSortStatus.GetSortInfo(x.Key))) { int[] localIndexCache = sortInfo.MatchingIndexes.ToArray(); if (localIndexCache.Length == 0) { continue; } if (sortInfo.SortStatus(cachedInventory.Index) == SortStatus.MoveButUnable) { if (ItemSortStatus.FilledAndSortedInventories.Contains(cachedInventory.Index) || (cachedInventory.FreeSlots == 0 && cachedInventory.AllBelong())) { LogCritical($"We want to move {sortInfo.Name} to {ItemSortStatus.GetByIndex(localIndexCache[0]).Name} but it's full and everything there belongs. Too bad!"); } else if (sortInfo.ItemInfo.Unique) { if (localIndexCache.Length == 1) { LogCritical($"We want to move {sortInfo.Name} to {ItemSortStatus.GetByIndex(localIndexCache[0]).Name} but it's unique and that inventory already has one. Too bad!"); } else { LogCritical($"We want to move {sortInfo.Name} but it's unique and all inventories set for it already have one. Too bad!"); } } else { LogCritical($"We want to move {sortInfo.Name} to {ItemSortStatus.GetByIndex(localIndexCache[0]).Name} " + $"but it can't be moved there for... some reason. IndexStatus: {sortInfo.IndexStatus(cachedInventory.Index).ToString()}"); } } } } await GeneralFunctions.ExitRetainer(true); if (AutoRetainerSortSettings.Instance.AutoGenLisbeth) { string lisbethSettingsPath = LisbethRuleGenerator.GetSettingsPath(); if (!string.IsNullOrEmpty(lisbethSettingsPath)) { LisbethRuleGenerator.PopulateSettings(lisbethSettingsPath); LogSuccess("Auto-populated Lisbeth's retainer item rules!"); MessageBox.Show( Strings.LisbethRules_RestartRB, "Just Letting You Know...", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { LogCritical("Couldn't find Lisbeth settings path! We won't auto-generate retainer rules."); } } TreeRoot.Stop("Done sorting inventories."); return(false); }
private static async Task <bool> RetrieveLoop(int index) { string name = ItemSortStatus.GetByIndex(index).Name; if (ItemSortStatus.GetByIndex(index).AllBelong()) { LogCritical($"We tried to retrieve items from {name} but everything in their inventory already belongs there...?"); return(false); } if (InventoryManager.FreeSlots == 0) { LogCritical($"We tried to retrieve items from {name} but our player inventory is full!"); return(false); } Log($"Retrieving items from {name}..."); var movedCount = 0; foreach (BagSlot bagSlot in InventoryManager.GetBagsByInventoryBagId(BagIdsByIndex(index)).SelectMany(x => x.FilledSlots)) { if (InventoryManager.FreeSlots == 0) { LogCritical($"Stopping retrievals from {name} because our player inventory is full!"); return(false); } var sortInfo = ItemSortStatus.GetSortInfo(bagSlot.TrueItemId); if (sortInfo.ItemInfo.Unique && InventoryManager.FilledSlots.Any(x => x.TrueItemId == sortInfo.TrueItemId)) { continue; } if (sortInfo.SortStatus(index) == SortStatus.Move) { bool moveResult; if (index == ItemSortStatus.SaddlebagInventoryIndex) { moveResult = await bagSlot.TryRemoveFromSaddlebag(bagSlot.Count, AutoRetainerSortSettings.Instance.ItemMoveWaitMs); } else { moveResult = await bagSlot.TryRetrieveFromRetainer(bagSlot.Count, AutoRetainerSortSettings.Instance.ItemMoveWaitMs); } if (moveResult) { string belongsInName = ItemSortStatus.GetByIndex(sortInfo.MatchingIndexes[0]).Name; if (sortInfo.ItemInfo.Unique) { var localIndexCache = sortInfo.MatchingIndexes.ToArray(); for (int i = 0; i < localIndexCache.Length; i++) { var cachedInventory = ItemSortStatus.GetByIndex(localIndexCache[i]); if (cachedInventory.ItemCounts.ContainsKey(sortInfo.TrueItemId)) { continue; } belongsInName = cachedInventory.Name; break; } } LogSuccess($"Retrieved {sortInfo.Name}. It belongs in {belongsInName}."); if (sortInfo.ItemInfo.Unique) { ItemSortStatus.PlayerInventoryUniques.Add(sortInfo.TrueItemId); ItemSortStatus.TryingToMoveUniques.Remove(sortInfo.TrueItemId); } movedCount++; } else { LogCritical($"Something went wrong with retrieving {sortInfo.Name}, it's still in the same slot!"); } } } return(movedCount > 0); }
private static void PrintMoves(int index) { foreach (ItemSortInfo sortInfo in ItemSortStatus.GetByIndex(index).ItemCounts.Select(x => ItemSortStatus.GetSortInfo(x.Key))) { if (sortInfo.SortStatus(index) != SortStatus.Move) { continue; } if (alreadyPrintedUniques.Contains(sortInfo.TrueItemId)) { continue; } if (sortInfo.ItemInfo.Unique) { alreadyPrintedUniques.Add(sortInfo.TrueItemId); } int[] localIndexCache = sortInfo.MatchingIndexes.ToArray(); StringBuilder sb = new StringBuilder(); sb.Append($"We want to move {sortInfo.Name} from {ItemSortStatus.GetByIndex(index).Name}"); bool isFull = localIndexCache.All(x => ItemSortStatus.FilledAndSortedInventories.Contains(x)); if (sortInfo.ItemInfo.Unique) { var uniqueNoSpace = true; for (int i = 0; i < localIndexCache.Length; i++) { if (ItemSortStatus.GetByIndex(localIndexCache[i]).ItemCounts.ContainsKey(sortInfo.TrueItemId)) { continue; } sb.Append($" to {ItemSortStatus.GetByIndex(localIndexCache[i]).Name}"); uniqueNoSpace = false; break; } isFull = uniqueNoSpace; } else { sb.Append($" to {ItemSortStatus.GetByIndex(localIndexCache[0]).Name}"); } if (sortInfo.ItemInfo.Unique && isFull) { sb.Append("... but it's unique and there's no available space."); } else if (isFull) { sb.Append("... but it's full."); } else { sb.Append("."); } if (isFull) { LogCritical(sb.ToString()); } else { Log(sb.ToString()); } } }