feat: async inventory processing

TODO: Do !!NOT!! process containers twice!
This commit is contained in:
Yui 2024-11-06 17:45:58 -03:00
parent fa0821686b
commit a86213d3a6
Signed by: yui
GPG Key ID: F368D23A0ABA04B4
2 changed files with 45 additions and 12 deletions

View File

@ -16,7 +16,8 @@ namespace LootValueEX.Extensions
/// <param name="item">The item to check.</param> /// <param name="item">The item to check.</param>
/// <returns>True if the item has been examined, false otherwise.</returns> /// <returns>True if the item has been examined, false otherwise.</returns>
internal static bool IsExamined(this Item? item) => item != null && ClientAppUtils.GetMainApp().GetClientBackEndSession().Profile.Examined(item); internal static bool IsExamined(this Item? item) => item != null && ClientAppUtils.GetMainApp().GetClientBackEndSession().Profile.Examined(item);
internal static string PrehashTemplate(this Item? item) => string.Format("{0}|{1}|{2}", item?.TemplateId, item.GetDurability(), item.GetUses());
/// <summary> /// <summary>
/// Retrieves the value of a specific attribute from an item. /// Retrieves the value of a specific attribute from an item.
/// </summary> /// </summary>
@ -39,27 +40,28 @@ namespace LootValueEX.Extensions
/// <summary> /// <summary>
/// Generates a custom hash for the given item. /// Generates a custom hash for the given item.
/// ///
/// This function takes an optional Item as a parameter and returns its custom hash. /// This function takes an optional Item as a parameter and returns its custom hash.
/// If the item is null, it returns an empty string. The custom hash is determined by the item's template, durability, and uses. /// If the item is null, it returns an empty string. The custom hash is determined by the item's template, durability, and uses.
/// </summary> /// </summary>
/// <param name="item">The item to retrieve the custom hash for.</param> /// <param name="item">The item to retrieve the custom hash for.</param>
/// <returns>The custom hash of the item, or an empty string if the item is null.</returns> /// <returns>The custom hash of the item, or an empty string if the item is null.</returns>
internal static string GetCustomHash(this Item? item) internal static async Task<string> GetCustomHashAsync(this Item? item)
{ {
if (item == null) if (item == null)
return string.Empty; return string.Empty;
StringBuilder prehashString = new StringBuilder(); StringBuilder prehashString = new StringBuilder();
item.GetAllItems().Where(prop => !prop.Equals(item)).ExecuteForEach(prop => prehashString.Append(prop.GetCustomHash()));
item.GetAllItems().Where(i => !i.Equals(item)).DoMap(i => prehashString.Append(i.PrehashTemplate()));
if (item.Template.Equals(typeof(MagazineTemplate))) if (item.Template.Equals(typeof(MagazineTemplate)))
{ {
MagazineTemplate magTemplate = (MagazineTemplate)item.Template; MagazineTemplate magTemplate = (MagazineTemplate)item.Template;
magTemplate.Cartridges.ExecuteForEach(prop => prop.Items.ExecuteForEach(ammo => prehashString.Append(ammo.GetCustomHash()))); magTemplate.Cartridges.DoMap(s => s.Items.DoMap(i => prehashString.Append(i.PrehashTemplate())));
} }
string itemHashTemplate = string.Format("{0}|{1}|{2}|{3}", prehashString.ToString(), item.TemplateId, item.GetDurability(), item.GetUses()); prehashString.Append(item.PrehashTemplate());
return Utils.HashingUtils.ConvertToSha256(itemHashTemplate); return await Task.Run(() => Utils.HashingUtils.ConvertToSha256(prehashString.ToString()));
} }
internal static string GetCustomHash(this Item? item) => Task.Run(() => item?.GetCustomHashAsync()).Result ?? string.Empty;
#if DEBUG #if DEBUG
internal static string AttributesToString(this Item? item) internal static string AttributesToString(this Item? item)
{ {

View File

@ -1,4 +1,5 @@
using System.Reflection; using System.Diagnostics;
using System.Reflection;
using EFT; using EFT;
using EFT.HealthSystem; using EFT.HealthSystem;
using EFT.UI; using EFT.UI;
@ -14,10 +15,40 @@ namespace LootValueEX.Patches.Screens
[PatchPostfix] [PatchPostfix]
private static void PatchPostfix(ref Profile ___profile_0, ref LootItemClass ___lootItemClass) private static void PatchPostfix(ref Profile ___profile_0, ref LootItemClass ___lootItemClass)
{ {
___profile_0.Inventory.GetPlayerItems(EFT.InventoryLogic.EPlayerItems.Equipment).ExecuteForEach(item => Plugin.Log.LogDebug($"{item.LocalizedName()} ({item.TemplateId}): {item.GetCustomHash()}")); Profile profile = ___profile_0;
TaskCompletionSource<bool> tcsInventory = new();
CancellationTokenSource ctsInventory = new CancellationTokenSource(5000);
Task<bool> taskInventory = tcsInventory.Task;
Task.Factory.StartNew(async () =>
{
Stopwatch sw = Stopwatch.StartNew();
foreach(EFT.InventoryLogic.Item item in profile.Inventory.GetPlayerItems(EFT.InventoryLogic.EPlayerItems.Equipment))
{
Plugin.Log.LogDebug($"Equip Process: {item.LocalizedName()} ({item.TemplateId}): {await item.GetCustomHashAsync()}");
}
sw.Stop();
Plugin.Log.LogDebug($"Equipment processing finished in {sw.ElapsedMilliseconds}ms");
tcsInventory.SetResult(true);
}, ctsInventory.Token);
if(___lootItemClass != null) if(___lootItemClass != null)
___lootItemClass.GetAllItems().ExecuteForEach(item => Plugin.Log.LogDebug($"{item.LocalizedName()} ({item.TemplateId}): {item.GetCustomHash()}")); {
LootItemClass lootItemClass = ___lootItemClass;
TaskCompletionSource<bool> tcsLoot = new();
CancellationTokenSource ctsLoot = new CancellationTokenSource(5000);
Task<bool> taskLoot = tcsLoot.Task;
Task.Factory.StartNew(async () =>
{
Stopwatch sw = Stopwatch.StartNew();
foreach (EFT.InventoryLogic.Item item in lootItemClass.GetAllItems())
{
Plugin.Log.LogDebug($"LootItemClass process: {item.LocalizedName()} ({item.TemplateId}): {await item.GetCustomHashAsync()}");
}
Plugin.Log.LogDebug($"LootItemClass processing finished in {sw.ElapsedMilliseconds}ms");
tcsLoot.SetResult(true);
}, ctsLoot.Token);
}
} }
} }
} }