Files
better-genshin-impact/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs
FishmanTheMurloc 6d4f8b80e8 Feat/multi lan (#1336)
* 记录一次对hutaofisher的访谈,帮助开发者理解其算法

* 本地化HelloWorld

* .csproj取消windows版本号,此处导致了IDE在新建代码文件和自动生成代码时,默认命名空间丢失的问题。已知VisualStudio和ReSharper存在这个问题。

* 优化扩展方法写法,改为从localizer扩展;Converter优化写法,避免冲突;新增两种语言,待测试ocr效果

* Revert ".csproj取消windows版本号,此处导致了IDE在新建代码文件和自动生成代码时,默认命名空间丢失的问题。已知VisualStudio和ReSharper存在这个问题。"

This reverts commit 8bd7ee74c5.

* localizer改为由构造函数传入以支持单元测试;一个英语上钩的单元测试

* 传送任务支持英语游戏界面;本地化参数挪至OtherConfig类下,但界面位置暂不挪动,待定

* 调整resx位置风格,放在直接使用字符串的类下;一条龙合成树脂及领取每日奖励支持游戏内中英双语

* 删除无用碎片文件

* 删去两个不必要的Sdcb包引用

* Paddle服务类去掉分类模型;检测和识别新增支持繁中和法语,配有单元测试;因小语种识别效果不理想,使用正则匹配替换多处识别文本相等或包含判断;钓鱼、一条龙合成树脂及领取每日奖励支持游戏内繁中和法语;

* 检查今日奖励任务的多语言化;右侧联机的P图标检测区域宽度缩减,避免英语角色名被误识别成P

* AutoDomainTask的游戏多语言化,由于我的游戏账号无法测试,仅配一些测试用例

* 修复有3个Mizuki导致异常的bug,临时用拼音代替新角色英文名,并为该数据初始化方法添加单元测试

* 瓦雷莎删去别名“牛牛”,因荒泷一斗已占用此别名;别名加载和读取优化

* 加个锁避免单元测试中多线程初始化paddle崩溃
2025-03-28 11:00:08 +08:00

285 lines
9.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.Core.Recognition.OCR;
using BetterGenshinImpact.Core.Script;
using BetterGenshinImpact.GameTask;
using BetterGenshinImpact.Helpers;
using BetterGenshinImpact.Model;
using BetterGenshinImpact.Service.Interface;
using BetterGenshinImpact.View;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Fischless.GameCapture.BitBlt;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using BetterGenshinImpact.View.Windows;
using BetterGenshinImpact.ViewModel.Pages;
using DeviceId;
using Wpf.Ui;
using Wpf.Ui.Controls;
namespace BetterGenshinImpact.ViewModel;
public partial class MainWindowViewModel : ObservableObject, IViewModel
{
private readonly ILogger<MainWindowViewModel> _logger;
private readonly IConfigService _configService;
public string Title => $"BetterGI · 更好的原神 · {Global.Version}{(RuntimeHelper.IsDebug ? " · Dev" : string.Empty)}";
[ObservableProperty]
private bool _isVisible = true;
[ObservableProperty]
private WindowState _windowState = WindowState.Normal;
[ObservableProperty]
private WindowBackdropType _currentBackdropType = WindowBackdropType.Auto;
[ObservableProperty]
private bool _isWin11Later = OsVersionHelper.IsWindows11_OrGreater;
public AllConfig Config { get; set; }
public MainWindowViewModel(INavigationService navigationService, IConfigService configService)
{
_configService = configService;
Config = _configService.Get();
_logger = App.GetLogger<MainWindowViewModel>();
}
[RelayCommand]
private async Task OnActivated()
{
await ScriptRepoUpdater.Instance.ImportScriptFromClipboard();
}
[RelayCommand]
private void OnHide()
{
IsVisible = false;
}
[RelayCommand]
private void OnSwitchBackdrop()
{
if (!OsVersionHelper.IsWindows11_22523_OrGreater)
{
return; // win10 不支持切换主题
}
CurrentBackdropType = CurrentBackdropType switch
{
WindowBackdropType.Mica => WindowBackdropType.Acrylic,
WindowBackdropType.Acrylic => WindowBackdropType.Mica,
_ => WindowBackdropType.Acrylic
};
Config.CommonConfig.CurrentBackdropType = CurrentBackdropType;
if (Application.Current.MainWindow is MainWindow mainWindow)
{
mainWindow.Background = new SolidColorBrush(Color.FromArgb(100, 0, 0, 0));
WindowBackdrop.ApplyBackdrop(mainWindow, CurrentBackdropType);
}
}
[RelayCommand]
private void OnClosing(CancelEventArgs e)
{
if (Config.CommonConfig.ExitToTray)
{
e.Cancel = true;
OnHide();
}
}
[RelayCommand]
private async Task OnLoaded()
{
// 预热OCR
await OcrPreheating();
if (Environment.GetCommandLineArgs().Length > 1)
{
return;
}
// 自动处理目录配置
await Patch1();
// 首次运行
if (Config.CommonConfig.IsFirstRun)
{
// 自动初始化键位绑定
// InitKeyBinding();
Config.AutoFightConfig.TeamNames = ""; // 此配置以后无用
Config.CommonConfig.IsFirstRun = false;
}
// 版本是否运行过
if (Config.CommonConfig.RunForVersion != Global.Version)
{
ModifyFolderSecurity();
Config.CommonConfig.RunForVersion = Global.Version;
}
OnceRun();
// 检查更新
await App.GetService<IUpdateService>()!.CheckUpdateAsync(new UpdateOption());
// Win11下 BitBlt截图方式不可用需要关闭窗口优化功能
if (OsVersionHelper.IsWindows11_OrGreater && TaskContext.Instance().Config.AutoFixWin11BitBlt)
{
BitBltRegistryHelper.SetDirectXUserGlobalSettings();
}
// 更新仓库
ScriptRepoUpdater.Instance.AutoUpdate();
// 清理临时目录
TempManager.CleanUp();
}
private void ModifyFolderSecurity()
{
// 检查程序是否位于C盘
if (Global.StartUpPath.StartsWith(@"C:", StringComparison.OrdinalIgnoreCase))
{
// 修改文件夹权限
SecurityControlHelper.AllowFullFolderSecurity(Global.StartUpPath);
}
}
/*
private void InitKeyBinding()
{
try
{
var kbVm = App.GetService<KeyBindingsSettingsPageViewModel>();
if (kbVm != null)
{
kbVm.FetchFromRegistryCommand.Execute(null);
}
}
catch (Exception e)
{
_logger.LogError("首次运行自动初始化按键绑定异常:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
MessageBox.Error("读取原神键位并设置键位绑定数据时发生异常:" + e.Message + ",后续可以手动设置");
}
}
*/
/**
* 不同的安装目录处理
* 可能当前目录下存在 BetterGI 的文件,需要移动到新的目录
*/
private async Task Patch1()
{
var embeddedPath = Global.Absolute("BetterGI");
var embeddedUserPath = Global.Absolute("BetterGI/User");
var exePath = Global.Absolute("BetterGI/BetterGI.exe");
if (Directory.Exists(embeddedPath)
&& File.Exists(exePath)
&& Directory.Exists(embeddedUserPath)
)
{
var fileVersionInfo = FileVersionInfo.GetVersionInfo(exePath);
// 低版本才需要迁移
if (fileVersionInfo.FileVersion != null && !Global.IsNewVersion(fileVersionInfo.FileVersion))
{
var res = await MessageBox.ShowAsync("检测到旧的 BetterGI 配置,是否迁移配置并清理旧目录?", "BetterGI", System.Windows.MessageBoxButton.YesNo, MessageBoxImage.Question);
if (res == System.Windows.MessageBoxResult.Yes)
{
// 迁移配置,拷贝整个目录并覆盖
DirectoryHelper.CopyDirectory(embeddedUserPath, Global.Absolute("User"));
// 删除旧目录
DirectoryHelper.DeleteReadOnlyDirectory(embeddedPath);
await MessageBox.InformationAsync("迁移配置成功, 软件将自动退出,请手动重新启动 BetterGI");
Application.Current.Shutdown();
}
}
}
}
private async Task OcrPreheating()
{
try
{
await Task.Run(async () =>
{
try
{
string gameCultureInfoName = TaskContext.Instance().Config.OtherConfig.GameCultureInfoName;
await OcrFactory.ChangeCulture(gameCultureInfoName);
var s = OcrFactory.Paddle.Ocr(new Mat(Global.Absolute(@"Assets\Model\PaddleOCR\test_ocr.png"), ImreadModes.Grayscale));
Debug.WriteLine("PaddleOcr预热结果:" + s);
}
catch (Exception e)
{
Console.WriteLine(e);
_logger.LogError("PaddleOcr预热异常解决方案https://bettergi.com/faq.html" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
var innerException = e.InnerException;
if (innerException != null)
{
_logger.LogError("PaddleOcr预热内部异常解决方案https://bettergi.com/faq.html" + innerException.Source + "\r\n--" + Environment.NewLine + innerException.StackTrace + "\r\n---" + Environment.NewLine + innerException.Message);
throw innerException;
}
else
{
throw;
}
}
});
}
catch (Exception e)
{
MessageBox.Warning("PaddleOcr预热失败解决方案https://bettergi.com/faq.html" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
}
}
private void OnceRun()
{
string deviceId = "default";
try
{
deviceId = new DeviceIdBuilder()
.OnWindows(windows => windows
.AddMacAddressFromWmi(excludeWireless: true, excludeNonPhysical: true)
.AddProcessorId()
.AddMotherboardSerialNumber()
)
.ToString();
}
catch (Exception e)
{
_logger.LogDebug("获取设备ID异常" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
}
// 每个设备只运行一次
if (!Config.CommonConfig.OnceHadRunDeviceIdList.Contains(deviceId))
{
WelcomeDialog prompt = new WelcomeDialog
{
Owner = Application.Current.MainWindow
};
prompt.ShowDialog();
prompt.Focus();
Config.CommonConfig.OnceHadRunDeviceIdList.Add(deviceId);
_configService.Save();
}
}
}