public override void Refresh() { int newTotal = MemoryTools.ReadInt(Handle, itemCount); if (newTotal != totalItems) { if (newTotal > totalItems) { // It's pretty common to acquire multiple items at once (such as an entire armor set). int pickupCount = newTotal - totalItems; AddItems(pickupCount); } // This means that items were lost (dropped, sold, etc.). else { // I'm fairly certain that only one item can be removed from the inventory at one time (via drop or // giving items to an NPC), but I'm not completely sure. A loop guarantees that the autosplitter's // internal inventory state remains correct. int dropCount = totalItems - newTotal; RemoveItems(dropCount); } totalItems = newTotal; } }
public override void SetItems(List <ItemId> itemIds) { SetItems(itemIds, DefaultSlots, DefaultSlots); IntPtr address = Start + (DefaultSlots - 1) * Step; if (OpenSlots.Count == 0) { return; } // Since the item count above isn't accurate (just a default value large enough to reasonably accommodate // most scenarios), fake slots at the end of the list must be removed in order for the initial state to be // correct. for (int i = 0; i < DefaultSlots; i++) { int rawId = MemoryTools.ReadInt(Handle, address); address -= Step; if (rawId == -1) { OpenSlots.RemoveLast(); TotalSlots--; } else { break; } } }
public override void Refresh() { IntPtr nextSlot = Start + (OpenSlots.Count > 0 ? OpenSlots.First.Value : TotalSlots) * Step; int value = MemoryTools.ReadInt(Handle, nextSlot); // Unlike the main inventory, there's no memory location that directly stores the number of items in the // bottomless box (or at least I wasn't able to find one). As such, item addition/removal must be detected // by checking slots directly. Also note that only one item can be put into the bottomless box at a time // (as opposed to picking up multiple items at once off the ground). if (value != -1) { AddItems(1); return; } LinkedListNode <int> slot = OpenSlots.First; // Since the bottomless box can't track count directly, all non-empty slots must be scanned each tick in // order to detect when one of them becomes empty. for (int i = 0; i < TotalSlots; i++) { if (slot != null && i == slot.Value) { slot = slot.Next; continue; } IntPtr address = Start + i * Step; value = MemoryTools.ReadInt(Handle, address); if (value == -1) { RemoveItems(1, address); return; } } }
protected override int ComputeRawId(IntPtr address) { return(MemoryTools.ReadInt(Handle, address)); }
public override void SetItems(List <ItemId> itemIds) { totalItems = MemoryTools.ReadInt(Handle, itemCount); SetItems(itemIds, totalItems); }
// Item trackers only know when their count changes (i.e. how many items were dropped). Since the bottomless // box scans its list in advance, the address of the removed item can be given directly. protected void RemoveItems(int count, IntPtr?knownAddress = null) { // Looping backwards allows the total slots to be decreased correctly if items were dropped // from the end of the array. int itemIndex = knownAddress != null ? ((int)knownAddress.Value - (int)Start) / step : TotalSlots - 1; IntPtr address = Start + itemIndex * step; for (int i = 0; i < count; i++) { LinkedListNode <int> openNode = OpenSlots.Last; while (itemIndex >= 0) { int rawId = MemoryTools.ReadInt(Handle, address); foreach (var list in tracker.Values) { int index = list.IndexOf(address); if (index >= 0) { list.RemoveAt(index); break; } } itemIndex--; address -= step; if (openNode != null && itemIndex < openNode.Value - 1) { openNode = openNode.Previous; } // Empty inventory slots have an ID of -1 (equivalent to 4B+ as an unsigned integer). if (rawId == -1) { // This check ensures that the same open slot isn't accidentally added twice. if (openNode != null && itemIndex + 1 == openNode.Value) { continue; } // Note that the index was already decremented above. if (itemIndex == TotalSlots - 2) { TotalSlots--; // This loop allows the tracked inventory to shrink as much as possible if there // are a series of open slots at the end. while (OpenSlots.Count > 0 && OpenSlots.Last.Value == TotalSlots - 1) { OpenSlots.RemoveLast(); TotalSlots--; } } else { OpenSlots.InsertSorted(itemIndex + 1); } break; } } } }