using Archipelago.MultiClient.Net.Models; using ItemChanger.Modules; using System.Collections.Generic; namespace Archipelago.HollowKnight.IC.Modules; public class ArchipelagoRemoteItemCounterModule : Module { /// /// Full history of remote items received and saved by the client. Keys are player, location, item to finally reach a count. /// private readonly Dictionary>> savedItemCounts = new(); /// /// History of items seen when receiving from server. Keys are player, location, item to finally reach a count. /// private readonly Dictionary>> serverSeenItemCounts = new(); public override void Initialize() { } public override void Unload() { } /// /// Determines whether the specified item should be received from the server based on the current counts. Should be called before receiving the item. /// /// The item to evaluate for receiving from the server. /// /// if receiving the item would result in the server count exceeding the local saved count; /// otherwise, . /// public bool ShouldReceiveServerItem(ItemInfo item) { int currentSavedCount = EnsureCountExists(item.Player, item.LocationId, item.ItemId, savedItemCounts); int currentServerCount = EnsureCountExists(item.Player, item.LocationId, item.ItemId, serverSeenItemCounts); // if obtaining this item will have sent more items from the server than we have locally, we should receive the item. otherwise we should skip it. return currentServerCount + 1 > currentSavedCount; } /// /// Increments the server-side count for the specified item. /// /// The object representing the item whose count is to be incremented. This includes details /// such as the player, location, and item identifier. public void IncrementServerCountForItem(ItemInfo item) { EnsureCountExists(item.Player, item.LocationId, item.ItemId, serverSeenItemCounts); IncrementCurrentCountForItem(item.Player, item.LocationId, item.ItemId, serverSeenItemCounts); } /// /// Increments the saved count for a specific item at a given location for a specified player. /// /// The identifier of the player for whom the item's saved count is being incremented. /// The identifier of the location where the item is stored. /// The identifier of the item whose saved count is being incremented. public void IncrementSavedCountForItem(int player, long locationId, long itemId) { EnsureCountExists(player, locationId, itemId, savedItemCounts); IncrementCurrentCountForItem(player, locationId, itemId, savedItemCounts); } private static void IncrementCurrentCountForItem(int player, long locationId, long itemId, Dictionary>> itemCounts, int incrementBy = 1) { itemCounts[player][locationId][itemId] += incrementBy; } private static int EnsureCountExists(int player, long locationId, long itemId, Dictionary>> itemCounts) { if (!itemCounts.TryGetValue(player, out Dictionary> a)) { itemCounts[player] = a = new(); } if (!a.TryGetValue(locationId, out Dictionary b)) { a[locationId] = b = new(); } if (!b.TryGetValue(itemId, out int count)) { b[itemId] = count = 0; } return count; } }