using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JXHelper.Config;
using JXHelper.Platform;
namespace JXHelper.Core;
///
/// Động cơ tuần tra bãi luyện theo chuỗi tọa độ Waypoints (INV-BG-INPUT-NO-HIJACK).
/// Vừa di chuyển theo lộ trình vừa hỗ trợ quét quái trên đường.
///
public class PatrolEngine : IDisposable
{
private CancellationTokenSource? _cts;
private Task? _loopTask;
public bool IsPaused { get; set; }
public event Action? OnLog;
public void Start(IntPtr hWnd, BotConfig config)
{
Stop();
if (!config.PatrolEnabled) return;
var waypoints = ParseWaypoints(config.WaypointsData);
if (waypoints.Count == 0) return;
_cts = new CancellationTokenSource();
var ct = _cts.Token;
_loopTask = Task.Run(() => PatrolLoopAsync(hWnd, config, waypoints, ct), ct);
}
public void Stop()
{
_cts?.Cancel();
_cts?.Dispose();
_cts = null;
_loopTask = null;
}
private async Task PatrolLoopAsync(IntPtr hWnd, BotConfig config, List waypoints, CancellationToken ct)
{
int currentIndex = 0;
while (!ct.IsCancellationRequested && NativeMethods.IsWindow(hWnd))
{
try
{
if (IsPaused || waypoints.Count == 0)
{
await Task.Delay(500, ct);
continue;
}
var pt = waypoints[currentIndex];
OnLog?.Invoke($"[TUẦN TRA] Di chuyển đến Waypoint {currentIndex + 1}/{waypoints.Count}: ({pt.X}, {pt.Y})");
// Click chuột trái vào tọa độ mặt đất trong game để di chuyển
await BackgroundInput.SendLeftClickAsync(hWnd, pt.X, pt.Y);
// Chờ nhân vật di chuyển
int intervalMs = Math.Max(2000, config.PatrolIntervalSeconds * 1000);
await Task.Delay(intervalMs, ct);
currentIndex = (currentIndex + 1) % waypoints.Count;
}
catch (OperationCanceledException)
{
break;
}
catch (Exception ex)
{
OnLog?.Invoke($"[LỖI TUẦN TRA] {ex.Message}");
await Task.Delay(2000, ct);
}
}
}
public static List ParseWaypoints(string? data)
{
var list = new List();
if (string.IsNullOrWhiteSpace(data)) return list;
var parts = data.Split(';', StringSplitOptions.RemoveEmptyEntries);
foreach (var p in parts)
{
var coords = p.Split(',', StringSplitOptions.RemoveEmptyEntries);
if (coords.Length == 2 && int.TryParse(coords[0].Trim(), out int x) && int.TryParse(coords[1].Trim(), out int y))
{
list.Add(new Point(x, y));
}
}
return list;
}
public static string FormatWaypoints(IEnumerable points)
{
return string.Join(";", points.Select(p => $"{p.X},{p.Y}"));
}
public void Dispose()
{
Stop();
}
}