test
This commit is contained in:
parent
53641fc8e7
commit
657d307485
28 changed files with 2045 additions and 161 deletions
|
|
@ -47,9 +47,11 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
public FrameSaver FrameSaver { get; }
|
||||
public LootDebugDetector LootDebugDetector { get; }
|
||||
public KulemakExecutor KulemakExecutor { get; }
|
||||
public AtlasExecutor AtlasExecutor { get; }
|
||||
public volatile bool ShowYoloOverlay = true;
|
||||
public volatile bool ShowFightPositionOverlay = true;
|
||||
private readonly Dictionary<string, ScrapExecutor> _scrapExecutors = new();
|
||||
private readonly Dictionary<string, DiamondExecutor> _diamondExecutors = new();
|
||||
|
||||
// Events
|
||||
public event Action? StatusUpdated;
|
||||
|
|
@ -94,6 +96,7 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
enemyDetector: EnemyDetector);
|
||||
|
||||
KulemakExecutor = new KulemakExecutor(game, screen, inventory, logWatcher, store.Settings, BossDetector, HudReader, Navigation);
|
||||
AtlasExecutor = new AtlasExecutor(game, screen, inventory, store.Settings, pipelineService.Pipeline);
|
||||
|
||||
logWatcher.AreaEntered += area =>
|
||||
{
|
||||
|
|
@ -144,6 +147,31 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
}
|
||||
}
|
||||
|
||||
public async Task EmergencyStop()
|
||||
{
|
||||
Log.Warning("EMERGENCY STOP triggered");
|
||||
_paused = true;
|
||||
Store.SetPaused(true);
|
||||
|
||||
// Stop all trade executors
|
||||
foreach (var exec in _scrapExecutors.Values)
|
||||
await exec.Stop();
|
||||
_scrapExecutors.Clear();
|
||||
|
||||
foreach (var exec in _diamondExecutors.Values)
|
||||
await exec.Stop();
|
||||
_diamondExecutors.Clear();
|
||||
|
||||
TradeQueue.Clear();
|
||||
|
||||
// Stop navigation and mapping
|
||||
await Navigation.Stop();
|
||||
KulemakExecutor.Stop();
|
||||
|
||||
State = "Stopped (END)";
|
||||
StatusUpdated?.Invoke();
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
_paused = true;
|
||||
|
|
@ -185,6 +213,29 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
_ = DeactivateLink(id);
|
||||
}
|
||||
|
||||
public void ChangeLinkMode(string id, LinkMode newMode)
|
||||
{
|
||||
var link = Links.UpdateMode(id, newMode);
|
||||
if (link == null) return;
|
||||
StatusUpdated?.Invoke();
|
||||
|
||||
if (!_started || !link.Active) return;
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await DeactivateLink(id);
|
||||
await ActivateLink(link);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to change link mode: {Id} → {Mode}", id, newMode);
|
||||
Emit("error", $"Failed to switch mode: {link.Name}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public BotStatus GetStatus() => new()
|
||||
{
|
||||
Paused = _paused,
|
||||
|
|
@ -211,6 +262,14 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
return;
|
||||
}
|
||||
}
|
||||
foreach (var diamondExec in _diamondExecutors.Values)
|
||||
{
|
||||
if (diamondExec.State != DiamondState.Idle && diamondExec.State != DiamondState.WaitingForListings)
|
||||
{
|
||||
State = diamondExec.State.ToString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (KulemakExecutor.State != MappingState.Idle)
|
||||
{
|
||||
State = KulemakExecutor.State.ToString();
|
||||
|
|
@ -273,6 +332,10 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
await Inventory.ClearToStash();
|
||||
Emit("info", "Inventory cleared");
|
||||
|
||||
// Wire trade monitor events before activating links to avoid race
|
||||
TradeMonitor.NewListings += OnNewListings;
|
||||
TradeMonitor.DiamondListings += OnDiamondListings;
|
||||
|
||||
// Load links
|
||||
var allUrls = new HashSet<string>(cliUrls);
|
||||
foreach (var l in Store.Settings.Links)
|
||||
|
|
@ -287,9 +350,6 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
Emit("info", $"Loaded (inactive): {link.Name}");
|
||||
}
|
||||
|
||||
// Wire trade monitor events
|
||||
TradeMonitor.NewListings += OnNewListings;
|
||||
|
||||
Emit("info", $"Loaded {allUrls.Count} trade link(s)");
|
||||
Log.Information("Bot started");
|
||||
}
|
||||
|
|
@ -360,6 +420,8 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
Log.Information("Shutting down bot...");
|
||||
foreach (var exec in _scrapExecutors.Values)
|
||||
await exec.Stop();
|
||||
foreach (var exec in _diamondExecutors.Values)
|
||||
await exec.Stop();
|
||||
EnemyDetector.Dispose();
|
||||
Screen.Dispose();
|
||||
await TradeMonitor.DisposeAsync();
|
||||
|
|
@ -367,25 +429,46 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
PipelineService.Dispose();
|
||||
}
|
||||
|
||||
private void OnNewListings(string searchId, List<string> itemIds)
|
||||
private void OnNewListings(string searchId, List<TradeItem> items)
|
||||
{
|
||||
if (_paused)
|
||||
{
|
||||
Emit("warn", $"New listings ({itemIds.Count}) skipped - bot paused");
|
||||
Emit("warn", $"New listings ({items.Count}) skipped - bot paused");
|
||||
return;
|
||||
}
|
||||
if (!Links.IsActive(searchId))
|
||||
{
|
||||
Emit("warn", $"New listings ({items.Count}) skipped - link {searchId} inactive");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Information("New listings: {SearchId} ({Count} items)", searchId, items.Count);
|
||||
Emit("info", $"New listings: {items.Count} items from {searchId}");
|
||||
|
||||
TradeQueue.Enqueue(new TradeInfo(
|
||||
SearchId: searchId,
|
||||
Items: items,
|
||||
Timestamp: DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
||||
));
|
||||
}
|
||||
|
||||
private void OnDiamondListings(string searchId, List<PricedTradeItem> items)
|
||||
{
|
||||
if (_paused)
|
||||
{
|
||||
Emit("warn", $"Diamond listings ({items.Count}) skipped - bot paused");
|
||||
return;
|
||||
}
|
||||
if (!Links.IsActive(searchId)) return;
|
||||
|
||||
Log.Information("New listings: {SearchId} ({Count} items)", searchId, itemIds.Count);
|
||||
Emit("info", $"New listings: {itemIds.Count} items from {searchId}");
|
||||
foreach (var item in items)
|
||||
{
|
||||
var display = DiamondSettings.KnownDiamonds.GetValueOrDefault(item.Name, item.Name);
|
||||
Emit("info", $"Diamond: {display} @ {item.PriceAmount} {item.PriceCurrency}");
|
||||
}
|
||||
|
||||
TradeQueue.Enqueue(new TradeInfo(
|
||||
SearchId: searchId,
|
||||
ItemIds: itemIds,
|
||||
WhisperText: "",
|
||||
Timestamp: DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
|
||||
TradeUrl: ""
|
||||
));
|
||||
if (_diamondExecutors.TryGetValue(searchId, out var exec))
|
||||
exec.EnqueueItems(items);
|
||||
}
|
||||
|
||||
private async Task ActivateLink(TradeLink link)
|
||||
|
|
@ -412,6 +495,29 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
}
|
||||
});
|
||||
}
|
||||
else if (link.Mode == LinkMode.Diamond)
|
||||
{
|
||||
var searchId = TradeMonitor.ExtractSearchId(link.Url);
|
||||
var diamondExec = new DiamondExecutor(searchId, Game, Screen, TradeMonitor, Inventory, Config);
|
||||
diamondExec.StateChanged += _ => UpdateExecutorState();
|
||||
diamondExec.ItemBought += () => { Interlocked.Increment(ref _tradesCompleted); StatusUpdated?.Invoke(); };
|
||||
diamondExec.ItemFailed += () => { Interlocked.Increment(ref _tradesFailed); StatusUpdated?.Invoke(); };
|
||||
_diamondExecutors[searchId] = diamondExec;
|
||||
|
||||
await TradeMonitor.AddDiamondSearch(link.Url);
|
||||
Emit("info", $"Diamond search started: {link.Name}");
|
||||
StatusUpdated?.Invoke();
|
||||
|
||||
_ = diamondExec.RunLoop().ContinueWith(t =>
|
||||
{
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
Log.Error(t.Exception!, "Diamond loop error: {LinkId}", link.Id);
|
||||
Emit("error", $"Diamond loop failed: {link.Name}");
|
||||
_diamondExecutors.Remove(searchId);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await TradeMonitor.AddSearch(link.Url);
|
||||
|
|
@ -433,6 +539,14 @@ public class BotOrchestrator : IAsyncDisposable
|
|||
await scrapExec.Stop();
|
||||
_scrapExecutors.Remove(id);
|
||||
}
|
||||
|
||||
// Diamond executors are keyed by searchId, not link id — but they're the same
|
||||
if (_diamondExecutors.TryGetValue(id, out var diamondExec))
|
||||
{
|
||||
await diamondExec.Stop();
|
||||
_diamondExecutors.Remove(id);
|
||||
}
|
||||
|
||||
await TradeMonitor.PauseSearch(id);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue