219 lines
7.6 KiB
C#
219 lines
7.6 KiB
C#
using System.Collections.ObjectModel;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using Poe2Trade.Bot;
|
|
using Poe2Trade.Core;
|
|
using Poe2Trade.Inventory;
|
|
using Serilog;
|
|
|
|
namespace Poe2Trade.Ui.ViewModels;
|
|
|
|
public partial class SettingsViewModel : ObservableObject
|
|
{
|
|
private readonly BotOrchestrator _bot;
|
|
|
|
[ObservableProperty] private string _poe2LogPath = "";
|
|
[ObservableProperty] private string _windowTitle = "";
|
|
[ObservableProperty] private decimal? _travelTimeoutMs = 15000;
|
|
[ObservableProperty] private decimal? _stashScanTimeoutMs = 10000;
|
|
[ObservableProperty] private decimal? _waitForMoreItemsMs = 20000;
|
|
[ObservableProperty] private decimal? _betweenTradesDelayMs = 5000;
|
|
[ObservableProperty] private bool _headless = true;
|
|
[ObservableProperty] private bool _showHudDebug;
|
|
[ObservableProperty] private string _ocrEngine = "WinOCR";
|
|
[ObservableProperty] private bool _isSaved;
|
|
[ObservableProperty] private string _calibrationStatus = "";
|
|
[ObservableProperty] private string _stashCalibratedAt = "";
|
|
[ObservableProperty] private string _shopCalibratedAt = "";
|
|
|
|
public static string[] OcrEngineOptions { get; } = ["WinOCR", "OneOCR", "EasyOCR"];
|
|
|
|
public ObservableCollection<StashTabViewModel> StashTabs { get; } = [];
|
|
public ObservableCollection<StashTabViewModel> ShopTabs { get; } = [];
|
|
|
|
public SettingsViewModel(BotOrchestrator bot)
|
|
{
|
|
_bot = bot;
|
|
LoadFromConfig();
|
|
LoadTabs();
|
|
}
|
|
|
|
private void LoadFromConfig()
|
|
{
|
|
var s = _bot.Store.Settings;
|
|
Poe2LogPath = s.Poe2LogPath;
|
|
WindowTitle = s.Poe2WindowTitle;
|
|
TravelTimeoutMs = s.TravelTimeoutMs;
|
|
StashScanTimeoutMs = s.StashScanTimeoutMs;
|
|
WaitForMoreItemsMs = s.WaitForMoreItemsMs;
|
|
BetweenTradesDelayMs = s.BetweenTradesDelayMs;
|
|
Headless = s.Headless;
|
|
ShowHudDebug = s.ShowHudDebug;
|
|
OcrEngine = s.OcrEngine;
|
|
}
|
|
|
|
private void LoadTabs()
|
|
{
|
|
var s = _bot.Store.Settings;
|
|
|
|
StashTabs.Clear();
|
|
if (s.StashCalibration != null)
|
|
{
|
|
foreach (var tab in s.StashCalibration.Tabs)
|
|
StashTabs.Add(new StashTabViewModel(tab));
|
|
StashCalibratedAt = FormatTimestamp(s.StashCalibration.CalibratedAt);
|
|
}
|
|
else
|
|
{
|
|
StashCalibratedAt = "Not calibrated";
|
|
}
|
|
|
|
ShopTabs.Clear();
|
|
if (s.ShopCalibration != null)
|
|
{
|
|
foreach (var tab in s.ShopCalibration.Tabs)
|
|
ShopTabs.Add(new StashTabViewModel(tab));
|
|
ShopCalibratedAt = FormatTimestamp(s.ShopCalibration.CalibratedAt);
|
|
}
|
|
else
|
|
{
|
|
ShopCalibratedAt = "Not calibrated";
|
|
}
|
|
}
|
|
|
|
private static string FormatTimestamp(long unixMs)
|
|
{
|
|
if (unixMs == 0) return "Not calibrated";
|
|
var dt = DateTimeOffset.FromUnixTimeMilliseconds(unixMs).LocalDateTime;
|
|
return dt.ToString("yyyy-MM-dd HH:mm");
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void SaveSettings()
|
|
{
|
|
_bot.Store.UpdateSettings(s =>
|
|
{
|
|
s.Poe2LogPath = Poe2LogPath;
|
|
s.Poe2WindowTitle = WindowTitle;
|
|
s.TravelTimeoutMs = (int)(TravelTimeoutMs ?? 15000);
|
|
s.StashScanTimeoutMs = (int)(StashScanTimeoutMs ?? 10000);
|
|
s.WaitForMoreItemsMs = (int)(WaitForMoreItemsMs ?? 20000);
|
|
s.BetweenTradesDelayMs = (int)(BetweenTradesDelayMs ?? 5000);
|
|
s.Headless = Headless;
|
|
s.ShowHudDebug = ShowHudDebug;
|
|
s.OcrEngine = OcrEngine;
|
|
});
|
|
|
|
IsSaved = true;
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void SaveTabs()
|
|
{
|
|
_bot.Store.UpdateSettings(s =>
|
|
{
|
|
// Models are already updated via write-through in StashTabViewModel
|
|
// Just trigger a save
|
|
if (s.StashCalibration != null)
|
|
s.StashCalibration = s.StashCalibration;
|
|
if (s.ShopCalibration != null)
|
|
s.ShopCalibration = s.ShopCalibration;
|
|
});
|
|
|
|
CalibrationStatus = "Tabs saved!";
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task CalibrateStash()
|
|
{
|
|
try
|
|
{
|
|
var calibrator = new StashCalibrator(_bot.Screen, _bot.Game);
|
|
CalibrationStatus = "Calibrating stash...";
|
|
|
|
await _bot.Game.FocusGame();
|
|
await Helpers.RandomDelay(150, 300);
|
|
|
|
var pos = await _bot.Inventory.FindAndClickNameplate("STASH");
|
|
if (!pos.HasValue)
|
|
{
|
|
CalibrationStatus = "STASH not found. Stand near your stash.";
|
|
return;
|
|
}
|
|
await Helpers.RandomDelay(300, 500);
|
|
|
|
var cal = await calibrator.CalibrateOpenPanel();
|
|
|
|
await _bot.Game.PressEscape();
|
|
await Helpers.RandomDelay(200, 400);
|
|
|
|
_bot.Store.UpdateSettings(s => s.StashCalibration = cal);
|
|
LoadTabs();
|
|
CalibrationStatus = $"Stash calibrated — {cal.Tabs.Count} tabs found.";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
CalibrationStatus = $"Stash calibration failed: {ex.Message}";
|
|
Log.Error(ex, "Stash calibration failed");
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task CalibrateShop()
|
|
{
|
|
try
|
|
{
|
|
var calibrator = new StashCalibrator(_bot.Screen, _bot.Game);
|
|
CalibrationStatus = "Calibrating shop...";
|
|
|
|
await _bot.Game.FocusGame();
|
|
await Helpers.RandomDelay(150, 300);
|
|
|
|
var pos = await _bot.Inventory.FindAndClickNameplate("ANGE");
|
|
if (!pos.HasValue)
|
|
{
|
|
CalibrationStatus = "ANGE not found. Stand near the vendor.";
|
|
return;
|
|
}
|
|
await Helpers.RandomDelay(800, 1200);
|
|
|
|
// ANGE opens a dialog — click "Manage Shop"
|
|
var dialogRegion = new Region(pos.Value.X, pos.Value.Y, 460, 600);
|
|
var managePos = await _bot.Screen.FindTextInRegion(dialogRegion, "Manage");
|
|
if (managePos.HasValue)
|
|
{
|
|
await _bot.Game.LeftClickAt(managePos.Value.X, managePos.Value.Y);
|
|
await Helpers.RandomDelay(300, 500);
|
|
}
|
|
else
|
|
{
|
|
Log.Warning("'Manage Shop' not found in dialog region, saving debug capture");
|
|
await _bot.Screen.SaveRegion(dialogRegion, "debug/calibrate-dialog.png");
|
|
}
|
|
|
|
var cal = await calibrator.CalibrateOpenPanel(firstFolderOnly: true);
|
|
|
|
await _bot.Game.PressEscape();
|
|
await Helpers.RandomDelay(200, 400);
|
|
|
|
_bot.Store.UpdateSettings(s => s.ShopCalibration = cal);
|
|
LoadTabs();
|
|
CalibrationStatus = $"Shop calibrated — {cal.Tabs.Count} tabs found.";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
CalibrationStatus = $"Shop calibration failed: {ex.Message}";
|
|
Log.Error(ex, "Shop calibration failed");
|
|
}
|
|
}
|
|
|
|
partial void OnPoe2LogPathChanged(string value) => IsSaved = false;
|
|
partial void OnWindowTitleChanged(string value) => IsSaved = false;
|
|
partial void OnTravelTimeoutMsChanged(decimal? value) => IsSaved = false;
|
|
partial void OnStashScanTimeoutMsChanged(decimal? value) => IsSaved = false;
|
|
partial void OnWaitForMoreItemsMsChanged(decimal? value) => IsSaved = false;
|
|
partial void OnBetweenTradesDelayMsChanged(decimal? value) => IsSaved = false;
|
|
partial void OnHeadlessChanged(bool value) => IsSaved = false;
|
|
partial void OnShowHudDebugChanged(bool value) => IsSaved = false;
|
|
partial void OnOcrEngineChanged(string value) => IsSaved = false;
|
|
}
|