Skip to content

Commit

Permalink
add auto cook #266
Browse files Browse the repository at this point in the history
  • Loading branch information
huiyadanli committed May 22, 2024
1 parent a801bb2 commit a84c94c
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 92 deletions.
6 changes: 6 additions & 0 deletions BetterGenshinImpact.Test/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,11 @@
Height="23"
Click="GenAvatarData"
Content="生成侧面头像数据集" />
<Button Canvas.Left="10"
Canvas.Top="190"
Width="100"
Height="23"
Click="AutoCookTestCase"
Content="自动烹饪图像测试" />
</Canvas>
</Window>
5 changes: 5 additions & 0 deletions BetterGenshinImpact.Test/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,9 @@ private void GenAvatarData(object sender, RoutedEventArgs e)
{
AvatarClassifyGen.GenAll();
}

private void AutoCookTestCase(object sender, RoutedEventArgs e)
{
AutoCookTest.Test();
}
}
17 changes: 17 additions & 0 deletions BetterGenshinImpact.Test/Simple/AutoCookTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using OpenCvSharp;

namespace BetterGenshinImpact.Test.Simple;

internal class AutoCookTest
{
public static void Test()
{
var img = new Mat(@"E:\HuiTask\更好的原神\自动烹饪\2.png");
Cv2.CvtColor(img, img, ColorConversionCodes.BGR2RGB);
var img2 = new Mat();
// Cv2.InRange(img, new Scalar(255, 192, 64), new Scalar(255, 192, 64), img2);
Cv2.InRange(img, new Scalar(255, 255, 192), new Scalar(255, 255, 192), img2);

Cv2.ImShow("img", img2);
}
}
6 changes: 6 additions & 0 deletions BetterGenshinImpact/BetterGenshinImpact.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,12 @@
<None Update="GameTask\Common\Element\Assets\1920x1080\submit_icon_exclamation.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\Common\Element\Assets\1920x1080\ui_left_top_cook_icon.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\Common\Element\Assets\1920x1080\ui_lt_cook_icon.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\Common\Element\Assets\1920x1080\yellow_track_point_28x.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
9 changes: 8 additions & 1 deletion BetterGenshinImpact/Core/Config/AllConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System;
using System.ComponentModel;
using System.Text.Json.Serialization;
using BetterGenshinImpact.GameTask.AutoCook;

namespace BetterGenshinImpact.Core.Config;

Expand Down Expand Up @@ -90,10 +91,15 @@ public partial class AllConfig : ObservableObject
public AutoFishingConfig AutoFishingConfig { get; set; } = new();

/// <summary>
/// 自动钓鱼配置
/// 快速传送配置
/// </summary>
public QuickTeleportConfig QuickTeleportConfig { get; set; } = new();

/// <summary>
/// 自动烹饪配置
/// </summary>
public AutoCookConfig AutoCookConfig { get; set; } = new();

/// <summary>
/// 自动打牌配置
/// </summary>
Expand Down Expand Up @@ -145,6 +151,7 @@ public void InitEvent()
AutoSkipConfig.PropertyChanged += OnAnyPropertyChanged;
AutoFishingConfig.PropertyChanged += OnAnyPropertyChanged;
QuickTeleportConfig.PropertyChanged += OnAnyPropertyChanged;
AutoCookConfig.PropertyChanged += OnAnyPropertyChanged;
MacroConfig.PropertyChanged += OnAnyPropertyChanged;
HotKeyConfig.PropertyChanged += OnAnyPropertyChanged;
AutoWoodConfig.PropertyChanged += OnAnyPropertyChanged;
Expand Down
54 changes: 54 additions & 0 deletions BetterGenshinImpact/GameTask/AutoCook/AutoCookTrigger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using System.Linq;

namespace BetterGenshinImpact.GameTask.AutoCook;

public class AutoCookTrigger : ITaskTrigger
{
private readonly ILogger<AutoCookTrigger> _logger = App.GetLogger<AutoCookTrigger>();

public string Name => "自动烹饪";
public bool IsEnabled { get; set; }
public int Priority => 50;
public bool IsExclusive { get; set; }

public void Init()
{
IsEnabled = TaskContext.Instance().Config.AutoCookConfig.Enabled;
IsExclusive = false;
}

public void OnCapture(CaptureContent content)
{
// 判断是否处于烹饪界面
IsExclusive = false;
content.CaptureRectArea.Find(ElementAssets.Instance.UiLeftTopCookIcon, foundRectArea =>
{
IsExclusive = true;
var captureRect = TaskContext.Instance().SystemInfo.ScaleMax1080PCaptureRect;
using var region = content.CaptureRectArea.DeriveCrop(0, captureRect.Height / 2, captureRect.Width, captureRect.Height / 2);
var perfectBarRects = ContoursHelper.FindSpecifyColorRects(region.SrcMat, new Scalar(255, 192, 64), 0, 8);
if (perfectBarRects.Count >= 2)
{
// 点击烹饪按钮
var btnList = ContoursHelper.FindSpecifyColorRects(region.SrcMat, new Scalar(255, 255, 192), 12, 12);
if (btnList.Count >= 1)
{
if (btnList.Count > 1)
{
_logger.LogWarning("自动烹饪:{Text}", "识别到多个结束烹饪按钮");
btnList = [.. btnList.OrderByDescending(r => r.Width)];
}
var btn = btnList[0];
var x = btn.X + btn.Width / 2;
var y = btn.Y + btn.Height / 2;
region.ClickTo(x, y);
_logger.LogInformation("自动烹饪:{Text}", "点击结束按钮");
}
}
});
}
}
17 changes: 17 additions & 0 deletions BetterGenshinImpact/GameTask/AutoCook/AutoPickConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;

namespace BetterGenshinImpact.GameTask.AutoCook;

/// <summary>
///自动烹饪配置
/// </summary>
[Serializable]
public partial class AutoCookConfig : ObservableObject
{
/// <summary>
/// 触发器是否启用
/// </summary>
[ObservableProperty]
private bool _enabled = false;
}
4 changes: 0 additions & 4 deletions BetterGenshinImpact/GameTask/AutoPick/AutoPickConfig.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BetterGenshinImpact.GameTask.AutoPick
{
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class ElementAssets : BaseAssets<ElementAssets>
public RecognitionObject PaimonMenuRo;
public RecognitionObject BlueTrackPoint;

public RecognitionObject UiLeftTopCookIcon;

private ElementAssets()
{
// 按钮
Expand Down Expand Up @@ -83,5 +85,15 @@ private ElementAssets()
Threshold = 0.6,
DrawOnWindow = true
}.InitTemplate();

// 左上角UI元素
UiLeftTopCookIcon = new RecognitionObject
{
Name = "UiLeftTopCookIcon",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage(@"Common\Element", "ui_left_top_cook_icon.png"),
RegionOfInterest = new Rect(0, 0, (int)(150 * AssetScale), (int)(120 * AssetScale)),
DrawOnWindow = false
}.InitTemplate();
}
}
173 changes: 87 additions & 86 deletions BetterGenshinImpact/GameTask/GameTaskManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,110 +20,111 @@
using BetterGenshinImpact.GameTask.QuickTeleport.Assets;
using BetterGenshinImpact.View.Drawable;

namespace BetterGenshinImpact.GameTask
namespace BetterGenshinImpact.GameTask;

internal class GameTaskManager
{
internal class GameTaskManager
{
public static Dictionary<string, ITaskTrigger>? TriggerDictionary { get; set; }
public static Dictionary<string, ITaskTrigger>? TriggerDictionary { get; set; }

/// <summary>
/// 一定要在任务上下文初始化完毕后使用
/// </summary>
/// <returns></returns>
public static List<ITaskTrigger> LoadTriggers()
/// <summary>
/// 一定要在任务上下文初始化完毕后使用
/// </summary>
/// <returns></returns>
public static List<ITaskTrigger> LoadTriggers()
{
ReloadAssets();
TriggerDictionary = new Dictionary<string, ITaskTrigger>()
{
ReloadAssets();
TriggerDictionary = new Dictionary<string, ITaskTrigger>()
{
{ "RecognitionTest", new TestTrigger() },
{ "GameLoading", new GameLoadingTrigger() },
{ "AutoPick", new AutoPick.AutoPickTrigger() },
{ "QuickTeleport", new QuickTeleport.QuickTeleportTrigger() },
{ "AutoSkip", new AutoSkip.AutoSkipTrigger() },
{ "AutoFishing", new AutoFishing.AutoFishingTrigger() }
};
{ "RecognitionTest", new TestTrigger() },
{ "GameLoading", new GameLoadingTrigger() },
{ "AutoPick", new AutoPick.AutoPickTrigger() },
{ "QuickTeleport", new QuickTeleport.QuickTeleportTrigger() },
{ "AutoSkip", new AutoSkip.AutoSkipTrigger() },
{ "AutoFishing", new AutoFishing.AutoFishingTrigger() },
{ "AutoCook", new AutoCook.AutoCookTrigger() }
};

var loadedTriggers = TriggerDictionary.Values.ToList();
var loadedTriggers = TriggerDictionary.Values.ToList();

loadedTriggers.ForEach(i => i.Init());
loadedTriggers.ForEach(i => i.Init());

loadedTriggers = loadedTriggers.OrderByDescending(i => i.Priority).ToList();
return loadedTriggers;
}
loadedTriggers = loadedTriggers.OrderByDescending(i => i.Priority).ToList();
return loadedTriggers;
}

public static void RefreshTriggerConfigs()
public static void RefreshTriggerConfigs()
{
if (TriggerDictionary is { Count: > 0 })
{
if (TriggerDictionary is { Count: > 0 })
TriggerDictionary["AutoPick"].IsEnabled = TaskContext.Instance().Config.AutoPickConfig.Enabled;
// 用于刷新AutoPick的黑白名单
TriggerDictionary["AutoPick"].Init();
TriggerDictionary["AutoSkip"].IsEnabled = TaskContext.Instance().Config.AutoSkipConfig.Enabled;
TriggerDictionary["AutoFishing"].IsEnabled = TaskContext.Instance().Config.AutoFishingConfig.Enabled;
// 钓鱼有很多变量要初始化,直接重新newZA
if (TriggerDictionary["AutoFishing"].IsEnabled == false)
{
TriggerDictionary["AutoPick"].IsEnabled = TaskContext.Instance().Config.AutoPickConfig.Enabled;
// 用于刷新AutoPick的黑白名单
TriggerDictionary["AutoPick"].Init();
TriggerDictionary["AutoSkip"].IsEnabled = TaskContext.Instance().Config.AutoSkipConfig.Enabled;
TriggerDictionary["AutoFishing"].IsEnabled = TaskContext.Instance().Config.AutoFishingConfig.Enabled;
// 钓鱼有很多变量要初始化,直接重新newZA
if (TriggerDictionary["AutoFishing"].IsEnabled == false)
{
TriggerDictionary["AutoFishing"].Init();
}
TriggerDictionary["QuickTeleport"].IsEnabled = TaskContext.Instance().Config.QuickTeleportConfig.Enabled;
TriggerDictionary["GameLoading"].Init();
// 清理画布
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<object>(new object(), "RemoveAllButton", new object(), ""));
VisionContext.Instance().DrawContent.ClearAll();
TriggerDictionary["AutoFishing"].Init();
}
ReloadAssets();
TriggerDictionary["QuickTeleport"].IsEnabled = TaskContext.Instance().Config.QuickTeleportConfig.Enabled;
TriggerDictionary["GameLoading"].Init();
TriggerDictionary["AutoCook"].Init();
// 清理画布
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<object>(new object(), "RemoveAllButton", new object(), ""));
VisionContext.Instance().DrawContent.ClearAll();
}
ReloadAssets();
}

public static void ReloadAssets()
{
AutoPickAssets.DestroyInstance();
AutoSkipAssets.DestroyInstance();
AutoFishingAssets.DestroyInstance();
QuickTeleportAssets.DestroyInstance();
AutoWoodAssets.DestroyInstance();
AutoGeniusInvokationAssets.DestroyInstance();
AutoFightAssets.DestroyInstance();
ElementAssets.DestroyInstance();
QuickSereniteaPotAssets.DestroyInstance();
GameLoadingAssets.DestroyInstance();
}

public static void ReloadAssets()
/// <summary>
/// 获取素材图片并缩放
/// todo 支持多语言
/// </summary>
/// <param name="featName">任务名称</param>
/// <param name="assertName">素材文件名</param>
/// <param name="flags"></param>
/// <returns></returns>
/// <exception cref="FileNotFoundException"></exception>
public static Mat LoadAssetImage(string featName, string assertName, ImreadModes flags = ImreadModes.Color)
{
var info = TaskContext.Instance().SystemInfo;
var assetsFolder = Global.Absolute($@"GameTask\{featName}\Assets\{info.GameScreenSize.Width}x{info.GameScreenSize.Height}");
if (!Directory.Exists(assetsFolder))
{
AutoPickAssets.DestroyInstance();
AutoSkipAssets.DestroyInstance();
AutoFishingAssets.DestroyInstance();
QuickTeleportAssets.DestroyInstance();
AutoWoodAssets.DestroyInstance();
AutoGeniusInvokationAssets.DestroyInstance();
AutoFightAssets.DestroyInstance();
ElementAssets.DestroyInstance();
QuickSereniteaPotAssets.DestroyInstance();
GameLoadingAssets.DestroyInstance();
assetsFolder = Global.Absolute($@"GameTask\{featName}\Assets\1920x1080");
}

/// <summary>
/// 获取素材图片并缩放
/// todo 支持多语言
/// </summary>
/// <param name="featName">任务名称</param>
/// <param name="assertName">素材文件名</param>
/// <param name="flags"></param>
/// <returns></returns>
/// <exception cref="FileNotFoundException"></exception>
public static Mat LoadAssetImage(string featName, string assertName, ImreadModes flags = ImreadModes.Color)
if (!Directory.Exists(assetsFolder))
{
var info = TaskContext.Instance().SystemInfo;
var assetsFolder = Global.Absolute($@"GameTask\{featName}\Assets\{info.GameScreenSize.Width}x{info.GameScreenSize.Height}");
if (!Directory.Exists(assetsFolder))
{
assetsFolder = Global.Absolute($@"GameTask\{featName}\Assets\1920x1080");
}

if (!Directory.Exists(assetsFolder))
{
throw new FileNotFoundException($"未找到{featName}的素材文件夹");
}

var filePath = Path.Combine(assetsFolder, assertName);
if (!File.Exists(filePath))
{
throw new FileNotFoundException($"未找到{featName}中的{assertName}文件");
}
throw new FileNotFoundException($"未找到{featName}的素材文件夹");
}

var mat = Mat.FromStream(File.OpenRead(filePath), flags);
if (info.GameScreenSize.Width != 1920)
{
mat = ResizeHelper.Resize(mat, info.AssetScale);
}
var filePath = Path.Combine(assetsFolder, assertName);
if (!File.Exists(filePath))
{
throw new FileNotFoundException($"未找到{featName}中的{assertName}文件");
}

return mat;
var mat = Mat.FromStream(File.OpenRead(filePath), flags);
if (info.GameScreenSize.Width != 1920)
{
mat = ResizeHelper.Resize(mat, info.AssetScale);
}

return mat;
}
}
Loading

0 comments on commit a84c94c

Please sign in to comment.