mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-04-23 22:10:00 +08:00
177 lines
6.4 KiB
C#
177 lines
6.4 KiB
C#
using BetterGenshinImpact.Core.Recorder.Model;
|
|
using BetterGenshinImpact.Core.Simulator;
|
|
using BetterGenshinImpact.GameTask;
|
|
using BetterGenshinImpact.GameTask.Common;
|
|
using BetterGenshinImpact.GameTask.Common.Map;
|
|
using BetterGenshinImpact.Helpers;
|
|
using Microsoft.Extensions.Logging;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Text.Json;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using Vanara.PInvoke;
|
|
using Wpf.Ui.Violeta.Controls;
|
|
|
|
namespace BetterGenshinImpact.Core.Recorder;
|
|
|
|
public class KeyMouseMacroPlayer
|
|
{
|
|
public static async Task PlayMacro(string macro, CancellationToken ct, bool withDelay = true)
|
|
{
|
|
if (!TaskContext.Instance().IsInitialized)
|
|
{
|
|
Toast.Warning("请先在启动页,启动截图器再使用本功能");
|
|
return;
|
|
}
|
|
|
|
var script = JsonSerializer.Deserialize<KeyMouseScript>(macro, KeyMouseRecorder.JsonOptions) ?? throw new Exception("Failed to deserialize macro");
|
|
script.Adapt(TaskContext.Instance().SystemInfo.CaptureAreaRect);
|
|
SystemControl.ActivateWindow();
|
|
|
|
if (withDelay)
|
|
{
|
|
for (var i = 3; i >= 1; i--)
|
|
{
|
|
TaskControl.Logger.LogInformation("{Sec}秒后进行重放...", i);
|
|
await Task.Delay(1000, ct);
|
|
}
|
|
|
|
TaskControl.Logger.LogInformation("开始重放");
|
|
}
|
|
|
|
await PlayMacro(script.MacroEvents, ct);
|
|
}
|
|
|
|
public static async Task PlayMacro(List<MacroEvent> macroEvents, CancellationToken ct)
|
|
{
|
|
WorkingArea = PrimaryScreen.WorkingArea;
|
|
var startTime = DateTime.UtcNow;
|
|
foreach (var e in macroEvents)
|
|
{
|
|
var timeToWait = (int)(e.Time - (DateTime.UtcNow - startTime).TotalMilliseconds);
|
|
if (timeToWait < 0)
|
|
{
|
|
TaskControl.Logger.LogWarning("无法原速重放事件{Event},落后{TimeToWait}ms", e.Type.ToString(), -timeToWait);
|
|
}
|
|
else
|
|
{
|
|
await Task.Delay(timeToWait, ct);
|
|
}
|
|
switch (e.Type)
|
|
{
|
|
case MacroEventType.KeyDown:
|
|
Simulation.SendInput.Keyboard.KeyDown((User32.VK)e.KeyCode!);
|
|
break;
|
|
|
|
case MacroEventType.KeyUp:
|
|
Simulation.SendInput.Keyboard.KeyUp((User32.VK)e.KeyCode!);
|
|
break;
|
|
|
|
case MacroEventType.MouseDown:
|
|
var buttonMouseDown = Enum.Parse<MouseButtons>(e.MouseButton!);
|
|
var xMouseDown = ToVirtualDesktopX(e.MouseX);
|
|
var yMouseDown = ToVirtualDesktopY(e.MouseY);
|
|
switch (buttonMouseDown)
|
|
{
|
|
case MouseButtons.Left:
|
|
Simulation.SendInput.Mouse.MoveMouseTo(xMouseDown, yMouseDown).LeftButtonDown();
|
|
break;
|
|
|
|
case MouseButtons.Right:
|
|
Simulation.SendInput.Mouse.MoveMouseTo(xMouseDown, yMouseDown).RightButtonDown();
|
|
break;
|
|
|
|
case MouseButtons.Middle:
|
|
Simulation.SendInput.Mouse.MoveMouseTo(xMouseDown, yMouseDown).MiddleButtonDown();
|
|
break;
|
|
|
|
case MouseButtons.None:
|
|
break;
|
|
|
|
case MouseButtons.XButton1:
|
|
break;
|
|
|
|
case MouseButtons.XButton2:
|
|
break;
|
|
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
break;
|
|
|
|
case MacroEventType.MouseUp:
|
|
var buttonMouseUp = Enum.Parse<MouseButtons>(e.MouseButton!);
|
|
var xMouseUp = ToVirtualDesktopX(e.MouseX);
|
|
var yMouseUp = ToVirtualDesktopY(e.MouseY);
|
|
switch (buttonMouseUp)
|
|
{
|
|
case MouseButtons.Left:
|
|
Simulation.SendInput.Mouse.MoveMouseTo(xMouseUp, yMouseUp).LeftButtonUp();
|
|
break;
|
|
|
|
case MouseButtons.Right:
|
|
Simulation.SendInput.Mouse.MoveMouseTo(xMouseUp, yMouseUp).RightButtonUp();
|
|
break;
|
|
|
|
case MouseButtons.Middle:
|
|
Simulation.SendInput.Mouse.MoveMouseTo(xMouseUp, yMouseUp).MiddleButtonUp();
|
|
break;
|
|
|
|
case MouseButtons.None:
|
|
break;
|
|
|
|
case MouseButtons.XButton1:
|
|
break;
|
|
|
|
case MouseButtons.XButton2:
|
|
break;
|
|
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
break;
|
|
|
|
case MacroEventType.MouseMoveTo:
|
|
Simulation.SendInput.Mouse.MoveMouseTo(ToVirtualDesktopX(e.MouseX), ToVirtualDesktopY(e.MouseY));
|
|
break;
|
|
|
|
case MacroEventType.MouseMoveBy:
|
|
if (e.CameraOrientation != null)
|
|
{
|
|
var cao = CameraOrientation.Compute(TaskControl.CaptureToRectArea().SrcGreyMat);
|
|
var diff = (cao - (int)e.CameraOrientation + 180) % 360 - 180;
|
|
diff += diff < -180 ? 360 : 0;
|
|
//过滤一下特别大的角度偏差
|
|
if (diff != 0 && diff < 8 && diff > -8)
|
|
{
|
|
TaskControl.Logger.LogWarning("视角重放偏差{diff}°,尝试修正", diff);
|
|
e.MouseX -= diff;
|
|
}
|
|
}
|
|
Simulation.SendInput.Mouse.MoveMouseBy(e.MouseX, e.MouseY);
|
|
break;
|
|
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
}
|
|
|
|
public static Size WorkingArea;
|
|
|
|
public static double ToVirtualDesktopX(int x)
|
|
{
|
|
return x * 65535 * 1d / WorkingArea.Width;
|
|
}
|
|
|
|
public static double ToVirtualDesktopY(int y)
|
|
{
|
|
return y * 65535 * 1d / WorkingArea.Height;
|
|
}
|
|
}
|