switched to new way

This commit is contained in:
Boki 2026-02-13 01:12:51 -05:00
parent f22d182c8f
commit 4a65c8e17b
96 changed files with 4991 additions and 10025 deletions

View file

@ -0,0 +1,260 @@
using Poe2Trade.Core;
using Poe2Trade.Game;
using Poe2Trade.GameLog;
using Poe2Trade.Screen;
using Serilog;
namespace Poe2Trade.Inventory;
public class InventoryManager
{
private static readonly string SalvageTemplate = Path.Combine("assets", "salvage.png");
public InventoryTracker Tracker { get; } = new();
private bool _atOwnHideout = true;
private string _sellerAccount = "";
private readonly GameController _game;
private readonly ScreenReader _screen;
private readonly ClientLogWatcher _logWatcher;
private readonly AppConfig _config;
public bool IsAtOwnHideout => _atOwnHideout;
public string SellerAccount => _sellerAccount;
public InventoryManager(GameController game, ScreenReader screen, ClientLogWatcher logWatcher, AppConfig config)
{
_game = game;
_screen = screen;
_logWatcher = logWatcher;
_config = config;
}
public void SetLocation(bool atHome, string? seller = null)
{
_atOwnHideout = atHome;
_sellerAccount = seller ?? "";
}
public async Task ScanInventory(PostAction defaultAction = PostAction.Stash)
{
Log.Information("Scanning inventory...");
await _game.FocusGame();
await Helpers.Sleep(300);
await _game.OpenInventory();
var result = await _screen.Grid.Scan("inventory");
var cells = new bool[5, 12];
foreach (var cell in result.Occupied)
{
if (cell.Row < 5 && cell.Col < 12)
cells[cell.Row, cell.Col] = true;
}
Tracker.InitFromScan(cells, result.Items, defaultAction);
await _game.PressEscape();
await Helpers.Sleep(300);
}
public async Task ClearToStash()
{
Log.Information("Checking inventory for leftover items...");
await ScanInventory(PostAction.Stash);
if (Tracker.GetItems().Count == 0)
{
Log.Information("Inventory empty, nothing to clear");
return;
}
Log.Information("Found {Count} leftover items, depositing to stash", Tracker.GetItems().Count);
await DepositItemsToStash(Tracker.GetItems());
Tracker.Clear();
Log.Information("Inventory cleared to stash");
}
public async Task<bool> EnsureAtOwnHideout()
{
if (_atOwnHideout)
{
Log.Information("Already at own hideout");
return true;
}
await _game.FocusGame();
await Helpers.Sleep(300);
var arrived = await WaitForAreaTransition(_config.TravelTimeoutMs, () => _game.GoToHideout());
if (!arrived)
{
Log.Error("Timed out going to own hideout");
return false;
}
await Helpers.Sleep(1500);
_atOwnHideout = true;
_sellerAccount = "";
return true;
}
public async Task DepositItemsToStash(List<PlacedItem> items)
{
if (items.Count == 0) return;
var stashPos = await FindAndClickNameplate("Stash");
if (stashPos == null)
{
Log.Error("Could not find Stash nameplate");
return;
}
await Helpers.Sleep(1000);
var inventoryLayout = GridLayouts.Inventory;
Log.Information("Depositing {Count} items to stash", items.Count);
await _game.HoldCtrl();
foreach (var item in items)
{
var center = _screen.Grid.GetCellCenter(inventoryLayout, item.Row, item.Col);
await _game.LeftClickAt(center.X, center.Y);
await Helpers.Sleep(150);
}
await _game.ReleaseCtrl();
await Helpers.Sleep(500);
await _game.PressEscape();
await Helpers.Sleep(500);
Log.Information("Items deposited to stash");
}
public async Task<bool> SalvageItems(List<PlacedItem> items)
{
if (items.Count == 0) return true;
var nameplate = await FindAndClickNameplate("SALVAGE BENCH");
if (nameplate == null)
{
Log.Error("Could not find Salvage nameplate");
return false;
}
await Helpers.Sleep(1000);
var salvageBtn = await _screen.TemplateMatch(SalvageTemplate);
if (salvageBtn != null)
{
await _game.LeftClickAt(salvageBtn.X, salvageBtn.Y);
await Helpers.Sleep(500);
}
else
{
Log.Warning("Could not find salvage button via template match");
}
var inventoryLayout = GridLayouts.Inventory;
Log.Information("Salvaging {Count} inventory items", items.Count);
await _game.HoldCtrl();
foreach (var item in items)
{
var center = _screen.Grid.GetCellCenter(inventoryLayout, item.Row, item.Col);
await _game.LeftClickAt(center.X, center.Y);
await Helpers.Sleep(150);
}
await _game.ReleaseCtrl();
await Helpers.Sleep(500);
await _game.PressEscape();
await Helpers.Sleep(500);
return true;
}
public async Task ProcessInventory()
{
try
{
var home = await EnsureAtOwnHideout();
if (!home)
{
Log.Error("Cannot process inventory: failed to reach hideout");
return;
}
if (Tracker.HasItemsWithAction(PostAction.Salvage))
{
var salvageItems = Tracker.GetItemsByAction(PostAction.Salvage);
if (await SalvageItems(salvageItems))
Tracker.RemoveItemsByAction(PostAction.Salvage);
else
Log.Warning("Salvage failed, depositing all to stash");
}
await ScanInventory(PostAction.Stash);
var allItems = Tracker.GetItems();
if (allItems.Count > 0)
await DepositItemsToStash(allItems);
Tracker.Clear();
Log.Information("Inventory processing complete");
}
catch (Exception ex)
{
Log.Error(ex, "Inventory processing failed");
try { await _game.PressEscape(); await Helpers.Sleep(300); } catch { }
Tracker.Clear();
}
}
public async Task<(int X, int Y)?> FindAndClickNameplate(string name, int maxRetries = 3, int retryDelayMs = 1000)
{
for (var attempt = 1; attempt <= maxRetries; attempt++)
{
Log.Information("Searching for nameplate '{Name}' (attempt {Attempt}/{Max})", name, attempt, maxRetries);
var pos = await _screen.FindTextOnScreen(name, fuzzy: true);
if (pos.HasValue)
{
Log.Information("Clicking nameplate '{Name}' at ({X},{Y})", name, pos.Value.X, pos.Value.Y);
await _game.LeftClickAt(pos.Value.X, pos.Value.Y);
return pos;
}
if (attempt < maxRetries)
await Helpers.Sleep(retryDelayMs);
}
Log.Warning("Nameplate '{Name}' not found after {Max} retries", name, maxRetries);
return null;
}
public async Task<bool> WaitForAreaTransition(int timeoutMs, Func<Task>? triggerAction = null)
{
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
using var cts = new CancellationTokenSource(timeoutMs);
cts.Token.Register(() => tcs.TrySetResult(false));
void Handler(string _) => tcs.TrySetResult(true);
_logWatcher.AreaEntered += Handler;
try
{
if (triggerAction != null)
{
try { await triggerAction(); }
catch
{
tcs.TrySetResult(false);
}
}
return await tcs.Task;
}
finally
{
_logWatcher.AreaEntered -= Handler;
}
}
public (bool[,] Grid, List<PlacedItem> Items, int Free) GetInventoryState()
{
return (Tracker.GetGrid(), Tracker.GetItems(), Tracker.FreeCells);
}
}