//
// MaaWpfGui - A part of the MaaCoreArknights project
// Copyright (C) 2021 MistEO and Contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using MaaWpfGui.Helper;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Stylet;
using StyletIoC;
namespace MaaWpfGui
{
///
/// The view model of task queue.
///
public class TaskQueueViewModel : Screen
{
private readonly IWindowManager _windowManager;
private readonly IContainer _container;
///
/// Gets or sets the view models of task items.
///
public ObservableCollection TaskItemViewModels { get; set; }
///
/// 实时更新任务顺序
///
public void TaskItemSelectionChanged()
{
int index = 0;
foreach (var item in TaskItemViewModels)
{
ViewStatusStorage.Set("TaskQueue.Order." + item.OriginalName, index.ToString());
++index;
}
}
///
/// Gets or sets the view models of log items.
///
public ObservableCollection LogItemViewModels { get; set; }
private string _actionAfterCompleted = ViewStatusStorage.Get("MainFunction.ActionAfterCompleted", ActionType.DoNothing.ToString());
///
/// Gets or sets the list of the actions after completion.
///
public List> ActionAfterCompletedList { get; set; }
///
/// Gets or sets the action after completion.
///
public ActionType ActionAfterCompleted
{
get
{
if (Enum.TryParse(_actionAfterCompleted, out ActionType action))
{
return action;
}
return ActionType.DoNothing;
}
set
{
string storeValue = value.ToString();
SetAndNotify(ref _actionAfterCompleted, storeValue);
ViewStatusStorage.Set("MainFunction.ActionAfterCompleted", storeValue);
}
}
///
/// Initializes a new instance of the class.
///
/// The IoC container.
/// The window manager.
public TaskQueueViewModel(IContainer container, IWindowManager windowManager)
{
_container = container;
_windowManager = windowManager;
DisplayName = Localization.GetString("Farming");
LogItemViewModels = new ObservableCollection();
InitializeItems();
InitTimer();
var trayIcon = _container.Get();
trayIcon.SetTaskQueueViewModel(this);
}
/*
public void ShowButton()
{
Visible = Visibility.Visible;
Hibernate = true;
}
private Visibility _visible = Visibility.Collapsed;
public Visibility Visible
{
get => _visible;
set => SetAndNotify(ref _visible, value);
}
*/
private readonly System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();
private void InitTimer()
{
_timer.Enabled = true;
_timer.Interval = 1000 * 50;
_timer.Tick += Timer1_Elapsed;
_timer.Start();
}
private void Timer1_Elapsed(object sender, EventArgs e)
{
if (NeedToUpdateDatePrompt())
{
UpdateDatePrompt();
UpdateStageList(false);
}
refreshCustomInfrastPlanIndexByPeriod();
if (!Idle)
{
return;
}
int intMinute = DateTime.Now.Minute;
int intHour = DateTime.Now.Hour;
var settings = _container.Get();
if ((settings.Timer1 && settings.Timer1Hour == intHour && settings.Timer1Min == intMinute) ||
(settings.Timer2 && settings.Timer2Hour == intHour && settings.Timer2Min == intMinute) ||
(settings.Timer3 && settings.Timer3Hour == intHour && settings.Timer3Min == intMinute) ||
(settings.Timer4 && settings.Timer4Hour == intHour && settings.Timer4Min == intMinute) ||
(settings.Timer5 && settings.Timer5Hour == intHour && settings.Timer5Min == intMinute) ||
(settings.Timer6 && settings.Timer6Hour == intHour && settings.Timer6Min == intMinute) ||
(settings.Timer7 && settings.Timer7Hour == intHour && settings.Timer7Min == intMinute) ||
(settings.Timer8 && settings.Timer8Hour == intHour && settings.Timer8Min == intMinute))
{
LinkStart();
}
}
///
/// Initializes items.
///
public void InitializeItems()
{
string[] task_list = new string[]
{
"WakeUp",
"Recruiting",
"Base",
"Combat",
"Mall",
"Mission",
"AutoRoguelike",
};
ActionAfterCompletedList = new List>
{
new GenericCombData { Display = Localization.GetString("DoNothing"), Value = ActionType.DoNothing },
new GenericCombData { Display = Localization.GetString("ExitArknights"), Value = ActionType.StopGame },
new GenericCombData { Display = Localization.GetString("ExitEmulator"), Value = ActionType.ExitEmulator },
new GenericCombData { Display = Localization.GetString("ExitSelf"), Value = ActionType.ExitSelf },
new GenericCombData { Display = Localization.GetString("ExitEmulatorAndSelf"), Value = ActionType.ExitEmulatorAndSelf },
// new GenericCombData{ Display="待机",Value=ActionTypeAfterCompleted.Suspend },
new GenericCombData { Display = Localization.GetString("ExitEmulatorAndSelfAndHibernate"), Value = ActionType.ExitEmulatorAndSelfAndHibernate },
new GenericCombData { Display = Localization.GetString("Hibernate"), Value = ActionType.Hibernate },
new GenericCombData { Display = Localization.GetString("Shutdown"), Value = ActionType.Shutdown },
};
var temp_order_list = new List(new DragItemViewModel[task_list.Length]);
var non_order_list = new List();
for (int i = 0; i != task_list.Length; ++i)
{
var task = task_list[i];
int order;
bool parsed = int.TryParse(ViewStatusStorage.Get("TaskQueue.Order." + task, "-1"), out order);
var vm = new DragItemViewModel(Localization.GetString(task), task, "TaskQueue.");
if (!parsed || order < 0 || order >= temp_order_list.Count)
{
non_order_list.Add(vm);
}
else
{
temp_order_list[order] = vm;
}
}
foreach (var new_vm in non_order_list)
{
int i = 0;
while (temp_order_list[i] != null)
{
++i;
}
temp_order_list[i] = new_vm;
}
TaskItemViewModels = new ObservableCollection(temp_order_list);
_stageManager = new StageManager();
RemainingSanityStageList = new ObservableCollection(_stageManager.GetStageList());
// It's Cur/Last option
RemainingSanityStageList[0] = new CombData { Display = Localization.GetString("NoUse"), Value = string.Empty };
InitDrops();
NeedToUpdateDatePrompt();
UpdateDatePrompt();
UpdateStageList(true);
RefreshCustonInfrastPlan();
}
private StageManager _stageManager;
private DayOfWeek _curDayOfWeek;
///
/// Determine whether the specified stage is open
///
/// stage name
/// Whether the specified stage is open
private bool IsStageOpen(string name)
{
return _stageManager.IsStageOpen(name, _curDayOfWeek);
}
///
/// Updates stage list.
///
/// Whether or not to update the stage list for selection forcely
public void UpdateStageList(bool forceUpdate)
{
var settingsModel = _container.Get();
if (settingsModel.HideUnavailableStage)
{
// update available stage list
var stage1 = Stage1;
StageList = new ObservableCollection(_stageManager.GetStageList(_curDayOfWeek));
// reset closed stage1 to "Last/Current"
if (!CustomStageCode &&
(stage1 == null || !_stageManager.IsStageOpen(stage1, _curDayOfWeek)))
{
Stage1 = string.Empty;
}
}
else
{
// initializing or settings changing, update stage list forcely
if (forceUpdate)
{
var stage1 = Stage1;
var stage2 = Stage2;
var stage3 = Stage3;
StageList = new ObservableCollection(_stageManager.GetStageList());
// reset closed stages to "Last/Current"
if (!CustomStageCode && !StageList.Any(x => x.Value == stage1))
{
Stage1 = string.Empty;
}
if (!CustomStageCode && !StageList.Any(x => x.Value == stage2))
{
Stage2 = string.Empty;
}
if (!CustomStageCode && !StageList.Any(x => x.Value == stage3))
{
Stage3 = string.Empty;
}
}
else
{
// do nothing
}
}
var remainingSanityStage = RemainingSanityStage;
RemainingSanityStageList = new ObservableCollection(_stageManager.GetStageList());
RemainingSanityStageList[0] = new CombData { Display = Localization.GetString("NoUse"), Value = string.Empty };
if (!CustomStageCode && !RemainingSanityStageList.Any(x => x.Value == remainingSanityStage))
{
RemainingSanityStage = string.Empty;
}
}
private bool NeedToUpdateDatePrompt()
{
var now = Utils.GetYJTimeNow();
var hour = now.Hour;
var min = now.Minute;
// yj历的16点
if (min == 0 && hour == 12)
{
return true;
}
else
{
if (_curDayOfWeek == now.DayOfWeek)
{
return false;
}
else
{
_curDayOfWeek = now.DayOfWeek;
return true;
}
}
}
///
/// Updates date prompt.
///
public void UpdateDatePrompt()
{
var builder = new StringBuilder(Localization.GetString("TodaysStageTip") + "\n");
// Closed activity stages
var stages = new[] { Stage1, Stage2, Stage3 };
foreach (var stage in stages)
{
if (_stageManager.GetStageInfo(stage)?.IsActivityClosed() == true)
{
builder.Append(stage).Append(": ").AppendLine(Localization.GetString("ClosedStage"));
break;
}
}
// Open stages today
var openStages = _stageManager.GetStageTips(_curDayOfWeek);
if (!string.IsNullOrEmpty(openStages))
{
builder.Append(openStages);
}
var prompt = builder.ToString();
if (StagesOfToday == prompt)
{
return;
}
StagesOfToday = prompt;
}
private string _stagesOfToday = string.Empty;
///
/// Gets or sets the stages of today.
///
public string StagesOfToday
{
get => _stagesOfToday;
set => SetAndNotify(ref _stagesOfToday, value);
}
///
/// Adds log.
///
/// The content.
/// The font color.
/// The font weight.
public void AddLog(string content, string color = UILogColor.Trace, string weight = "Regular")
{
var log = new LogItemViewModel(content, color, weight);
LogItemViewModels.Add(log);
Logger.Info(content);
}
///
/// Clears log.
///
public void ClearLog()
{
LogItemViewModels.Clear();
Logger.Info("\n");
}
///
/// Selects all.
///
public void SelectedAll()
{
foreach (var item in TaskItemViewModels)
{
if (item.OriginalName == "AutoRoguelike")
{
continue;
}
item.IsChecked = true;
}
}
private bool _inverseMode = Convert.ToBoolean(ViewStatusStorage.Get("MainFunction.InverseMode", bool.FalseString));
///
/// Gets or sets a value indicating whether to use inverse mode.
///
public bool InverseMode
{
get => _inverseMode;
set
{
SetAndNotify(ref _inverseMode, value);
InverseShowText = value ? Localization.GetString("Inverse") : Localization.GetString("Clear");
InverseMenuText = value ? Localization.GetString("Clear") : Localization.GetString("Inverse");
ViewStatusStorage.Set("MainFunction.InverseMode", value.ToString());
}
}
///
/// The width of "Select All" when both.
///
public const int SelectedAllWidthWhenBoth = 80;
private int _selectedAllWidth =
ViewStatusStorage.Get("GUI.InverseClearMode", "Clear") == "ClearInverse" ? SelectedAllWidthWhenBoth : 85;
///
/// Gets or sets the width of "Select All".
///
public int SelectedAllWidth
{
get => _selectedAllWidth;
set => SetAndNotify(ref _selectedAllWidth, value);
}
private int _inverseSelectedWidth = 90;
///
/// Gets or sets the width of "Select inversely".
///
public int InverseSelectedWidth
{
get => _inverseSelectedWidth;
set => SetAndNotify(ref _inverseSelectedWidth, value);
}
private bool _showInverse = ViewStatusStorage.Get("GUI.InverseClearMode", "Clear") == "ClearInverse";
///
/// Gets or sets a value indicating whether "Select inversely" is visible.
///
public bool ShowInverse
{
get => _showInverse;
set => SetAndNotify(ref _showInverse, value);
}
private string _inverseShowText = Convert.ToBoolean(ViewStatusStorage.Get("MainFunction.InverseMode", bool.FalseString)) ? Localization.GetString("Inverse") : Localization.GetString("Clear");
///
/// Gets or sets the text to be displayed for "Select inversely".
///
public string InverseShowText
{
get => _inverseShowText;
set => SetAndNotify(ref _inverseShowText, value);
}
private string _inverseMenuText = Convert.ToBoolean(ViewStatusStorage.Get("MainFunction.InverseMode", bool.FalseString)) ? Localization.GetString("Clear") : Localization.GetString("Inverse");
///
/// Gets or sets the text of inversion menu.
///
public string InverseMenuText
{
get => _inverseMenuText;
set => SetAndNotify(ref _inverseMenuText, value);
}
///
/// Changes inversion mode.
///
public void ChangeInverseMode()
{
InverseMode = !InverseMode;
}
///
/// Selects inversely.
///
public void InverseSelected()
{
if (_inverseMode)
{
foreach (var item in TaskItemViewModels)
{
if (item.OriginalName == "AutoRoguelike")
{
item.IsChecked = false;
continue;
}
item.IsChecked = !item.IsChecked;
}
}
else
{
foreach (var item in TaskItemViewModels)
{
item.IsChecked = false;
}
}
}
///
/// Starts.
///
public async void LinkStart()
{
if (Idle == false)
{
return;
}
Idle = false;
// 虽然更改时已经保存过了,不过保险起见还是在点击开始之后再保存一次任务及基建列表
TaskItemSelectionChanged();
_container.Get().InfrastOrderSelectionChanged();
ClearLog();
AddLog(Localization.GetString("ConnectingToEmulator"));
var asstProxy = _container.Get();
string errMsg = string.Empty;
var task = Task.Run(() =>
{
return asstProxy.AsstConnect(ref errMsg);
});
bool caught = await task;
// 一般是点了“停止”按钮了
if (Stopping)
{
SetStopped();
return;
}
if (!caught)
{
AddLog(errMsg, UILogColor.Error);
AddLog(Localization.GetString("ConnectFailed") + "\n" + Localization.GetString("TryToStartEmulator"));
var settingsModel = _container.Get();
var subtask = Task.Run(() =>
{
settingsModel.TryToStartEmulator(true);
});
await subtask;
task = Task.Run(() =>
{
return asstProxy.AsstConnect(ref errMsg);
});
caught = await task;
if (!caught)
{
AddLog(errMsg, UILogColor.Error);
Idle = true;
SetStopped();
return;
}
}
// 一般是点了“停止”按钮了
if (Stopping)
{
SetStopped();
return;
}
bool ret = true;
// 直接遍历TaskItemViewModels里面的内容,是排序后的
int count = 0;
foreach (var item in TaskItemViewModels)
{
if (item.IsChecked == false)
{
continue;
}
++count;
if (item.OriginalName == "Base")
{
ret &= appendInfrast();
}
else if (item.OriginalName == "WakeUp")
{
ret &= appendStart();
}
else if (item.OriginalName == "Combat")
{
ret &= appendFight();
}
else if (item.OriginalName == "Recruiting")
{
ret &= appendRecruit();
}
else if (item.OriginalName == "Mall")
{
ret &= appendMall();
}
else if (item.OriginalName == "Mission")
{
ret &= asstProxy.AsstAppendAward();
}
else if (item.OriginalName == "AutoRoguelike")
{
ret &= appendRoguelike();
}
else
{
--count;
// TODO 报错
}
}
if (count == 0)
{
AddLog(Localization.GetString("UnselectedTask"));
Idle = true;
SetStopped();
return;
}
// 一般是点了“停止”按钮了
if (Stopping)
{
SetStopped();
return;
}
ret &= asstProxy.AsstStart();
if (ret)
{
AddLog(Localization.GetString("Running"));
var settingsModel = _container.Get();
if (!settingsModel.AdbReplaced && !settingsModel.IsAdbTouchMode())
{
AddLog(Localization.GetString("AdbReplacementTips"), UILogColor.Info);
}
}
else
{
AddLog(Localization.GetString("UnknownErrorOccurs"));
}
}
///
/// Stops.
///
public async void Stop()
{
Stopping = true;
AddLog(Localization.GetString("Stopping"));
var task = Task.Run(() =>
{
return _container.Get().AsstStop();
});
await task;
}
public void SetStopped()
{
if (!Idle || Stopping)
{
AddLog(Localization.GetString("Stopped"));
}
Stopping = false;
Idle = true;
}
private bool appendStart()
{
var settings = _container.Get();
var asstProxy = _container.Get();
var mode = settings.ClientType;
var enable = mode.Length != 0;
return asstProxy.AsstAppendStartUp(mode, enable);
}
private bool appendFight()
{
int medicine = 0;
if (UseMedicine)
{
if (!int.TryParse(MedicineNumber, out medicine))
{
medicine = 0;
}
}
int stone = 0;
if (UseStone)
{
if (!int.TryParse(StoneNumber, out stone))
{
stone = 0;
}
}
int times = int.MaxValue;
if (HasTimesLimited)
{
if (!int.TryParse(MaxTimes, out times))
{
times = 0;
}
}
int drops_quantity = 0;
if (IsSpecifiedDrops)
{
if (!int.TryParse(DropsQuantity, out drops_quantity))
{
drops_quantity = 0;
}
}
var asstProxy = _container.Get();
bool mainFightRet = asstProxy.AsstAppendFight(Stage, medicine, stone, times, DropsItemId, drops_quantity);
if (!mainFightRet || RemainingSanityStage == string.Empty)
{
return mainFightRet;
}
return asstProxy.AsstAppendFight(RemainingSanityStage, 0, 0, int.MaxValue, string.Empty, 0, false);
}
///
/// Sets parameters.
///
public void SetFightParams()
{
int medicine = 0;
if (UseMedicine)
{
if (!int.TryParse(MedicineNumber, out medicine))
{
medicine = 0;
}
}
int stone = 0;
if (UseStone)
{
if (!int.TryParse(StoneNumber, out stone))
{
stone = 0;
}
}
int times = int.MaxValue;
if (HasTimesLimited)
{
if (!int.TryParse(MaxTimes, out times))
{
times = 0;
}
}
int drops_quantity = 0;
if (IsSpecifiedDrops)
{
if (!int.TryParse(DropsQuantity, out drops_quantity))
{
drops_quantity = 0;
}
}
var asstProxy = _container.Get();
asstProxy.AsstSetFightTaskParams(Stage, medicine, stone, times, DropsItemId, drops_quantity);
}
public void SetFightRemainingSanityParams()
{
var asstProxy = _container.Get();
asstProxy.AsstSetFightTaskParams(RemainingSanityStage, 0, 0, int.MaxValue, string.Empty, 0, false);
}
public void SetInfrastParams()
{
var settings = _container.Get();
var order = settings.GetInfrastOrderList();
var asstProxy = _container.Get();
asstProxy.AsstSetInfrastTaskParams(order.ToArray(), settings.UsesOfDrones, settings.DormThreshold / 100.0, settings.DormFilterNotStationedEnabled, settings.DormTrustEnabled, settings.OriginiumShardAutoReplenishment,
settings.CustomInfrastEnabled, settings.CustomInfrastFile, CustomInfrastPlanIndex);
}
private bool appendInfrast()
{
var settings = _container.Get();
var order = settings.GetInfrastOrderList();
var asstProxy = _container.Get();
return asstProxy.AsstAppendInfrast(order.ToArray(), settings.UsesOfDrones, settings.DormThreshold / 100.0, settings.DormFilterNotStationedEnabled, settings.DormTrustEnabled, settings.OriginiumShardAutoReplenishment,
settings.CustomInfrastEnabled, settings.CustomInfrastFile, CustomInfrastPlanIndex);
}
private bool appendMall()
{
var settings = _container.Get();
var asstProxy = _container.Get();
var buy_first = settings.CreditFirstList.Split(new char[] { ';', ';' });
var black_list = settings.CreditBlackList.Split(new char[] { ';', ';' });
for (var i = 0; i < buy_first.Length; ++i)
{
buy_first[i] = buy_first[i].Trim();
}
for (var i = 0; i < black_list.Length; ++i)
{
black_list[i] = black_list[i].Trim();
}
return asstProxy.AsstAppendMall(settings.CreditFightTaskEnabled, settings.CreditShopping, buy_first, black_list, settings.CreditForceShoppingIfCreditFull);
}
private bool appendRecruit()
{
// for debug
var settings = _container.Get();
int max_times;
if (!int.TryParse(settings.RecruitMaxTimes, out max_times))
{
max_times = 0;
}
var reqList = new List();
var cfmList = new List();
if (settings.ChooseLevel3)
{
cfmList.Add(3);
}
if (settings.ChooseLevel4)
{
reqList.Add(4);
cfmList.Add(4);
}
if (settings.ChooseLevel5)
{
reqList.Add(5);
cfmList.Add(5);
}
var asstProxy = _container.Get();
return asstProxy.AsstAppendRecruit(
max_times, reqList.ToArray(), cfmList.ToArray(),
settings.RefreshLevel3, settings.UseExpedited,
settings.NotChooseLevel1, settings.IsLevel3UseShortTime);
}
private bool appendRoguelike()
{
var settings = _container.Get();
int.TryParse(settings.RoguelikeMode, out var mode);
var asstProxy = _container.Get();
return asstProxy.AsstAppendRoguelike(
mode, settings.RoguelikeStartsCount,
settings.RoguelikeInvestmentEnabled, settings.RoguelikeInvestsCount, settings.RoguelikeStopWhenInvestmentFull,
settings.RoguelikeSquad, settings.RoguelikeRoles, settings.RoguelikeCoreChar, settings.RoguelikeUseSupportUnit,
settings.RoguelikeEnableNonfriendSupport, settings.RoguelikeTheme);
}
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
private static extern int GetWindowThreadProcessId(IntPtr hwnd, out int id);
///
/// Kills emulator by Window hwnd.
///
/// Whether the operation is successful.
public bool KillEumlatorbyWindow()
{
IntPtr hwnd;
int pid = 0;
var windowname = new[]
{
"明日方舟",
"夜神模拟器",
"逍遥模拟器",
"雷电模拟器(64)",
"雷电模拟器",
"明日方舟 - MuMu模拟器",
"BlueStacks App Player",
"BlueStacks",
};
foreach (string i in windowname)
{
hwnd = FindWindow(null, i);
if (hwnd != IntPtr.Zero)
{
GetWindowThreadProcessId(hwnd, out pid);
break;
}
}
do
{
if (pid == 0)
{
break;
}
Process emulator;
try
{
emulator = Process.GetProcessById(pid);
emulator.CloseMainWindow();
}
catch
{
break;
}
if (emulator.HasExited)
{
break;
}
try
{
emulator.Kill();
}
catch
{
break;
}
// 尽管已经成功 CloseMainWindow(),再次尝试 killEmulator()
// Refer to https://github.com/MaaAssistantArknights/MaaAssistantArknights/pull/1878
KillEmulator();
// 已经成功 CloseMainWindow(),所以不管 killEmulator() 的结果如何,都返回 true
return true;
}
while (false);
return KillEmulator();
}
///
/// Kills emulator.
///
/// Whether the operation is successful.
public bool KillEmulator()
{
int pid = 0;
string port;
string address = ViewStatusStorage.Get("Connect.Address", string.Empty);
if (address.StartsWith("127"))
{
port = address.Substring(10);
}
else
{
port = "5555";
}
string portCmd = "netstat -ano|findstr \"" + port + "\"";
Process checkCmd = new Process();
checkCmd.StartInfo.FileName = "cmd.exe";
checkCmd.StartInfo.UseShellExecute = false;
checkCmd.StartInfo.RedirectStandardInput = true;
checkCmd.StartInfo.RedirectStandardOutput = true;
checkCmd.StartInfo.RedirectStandardError = true;
checkCmd.StartInfo.CreateNoWindow = true;
try
{
checkCmd.Start();
}
catch
{
checkCmd.Close();
return false;
}
checkCmd.StandardInput.WriteLine(portCmd);
checkCmd.StandardInput.WriteLine("exit");
Regex reg = new Regex("\\s+", RegexOptions.Compiled);
string line;
while (true)
{
line = checkCmd.StandardOutput.ReadLine();
try
{
line = line.Trim();
}
catch
{
break;
}
if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
{
line = reg.Replace(line, ",");
string[] arr = line.Split(',');
if (!Convert.ToBoolean(string.Compare(arr[1], address, StringComparison.Ordinal)) || !Convert.ToBoolean(string.Compare(arr[1], "[::]:" + port, StringComparison.Ordinal)) || !Convert.ToBoolean(string.Compare(arr[1], "0.0.0.0:" + port, StringComparison.Ordinal)))
{
pid = int.Parse(arr[4]);
break;
}
}
}
if (pid == 0)
{
return false;
}
try
{
Process emulator = Process.GetProcessById(pid);
emulator.Kill();
}
catch
{
return false;
}
return true;
}
///
/// The action type.
///
public enum ActionType
{
///
/// Does nothing.
///
DoNothing,
///
/// Stops game.
///
StopGame,
///
/// Exits MAA.
///
ExitSelf,
///
/// Exits emulator.
///
ExitEmulator,
///
/// Exits MAA and emulator.
///
ExitEmulatorAndSelf,
///
/// Computer suspends.
///
Suspend,
///
/// Computer hibernates.
///
Hibernate,
///
/// Exits MAA and emulator and computer hibernates.
///
ExitEmulatorAndSelfAndHibernate,
///
/// Computer shutdown.
///
Shutdown,
}
///
/// Checks after completion.
///
public void CheckAfterCompleted()
{
switch (ActionAfterCompleted)
{
case ActionType.DoNothing:
break;
case ActionType.StopGame:
var asstProxy = _container.Get();
if (!asstProxy.AsstStartCloseDown())
{
AddLog(Localization.GetString("CloseArknightsFailed"), UILogColor.Error);
}
break;
case ActionType.ExitSelf:
// Shutdown 会调用 OnExit 但 Exit 不会
Application.Current.Shutdown();
// Environment.Exit(0);
break;
case ActionType.ExitEmulator:
if (!KillEumlatorbyWindow())
{
AddLog(Localization.GetString("ExitEmulatorFailed"), UILogColor.Error);
}
break;
case ActionType.ExitEmulatorAndSelf:
if (!KillEumlatorbyWindow())
{
AddLog(Localization.GetString("ExitEmulatorFailed"), UILogColor.Error);
}
// Shutdown 会调用 OnExit 但 Exit 不会
Application.Current.Shutdown();
// Environment.Exit(0);
break;
case ActionType.Shutdown:
Process.Start("shutdown.exe", "-s -t 60");
// 关机询问
var shutdownResult = _windowManager.ShowMessageBox(Localization.GetString("AboutToShutdown"), Localization.GetString("ShutdownPrompt"), MessageBoxButton.OK, MessageBoxImage.Question);
if (shutdownResult == MessageBoxResult.OK)
{
Process.Start("shutdown.exe", "-a");
}
break;
case ActionType.Suspend:
Process.Start("powercfg", "-h off");
Process.Start("rundll32.exe", "powrprof.dll,SetSuspendState 0,1,0");
Process.Start("powercfg", "-h on");
break;
case ActionType.Hibernate:
// 休眠提示
AddLog(Localization.GetString("HibernatePrompt"), UILogColor.Error);
// 休眠不能加时间参数,https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues/1133
Process.Start("shutdown.exe", "-h");
break;
case ActionType.ExitEmulatorAndSelfAndHibernate:
if (!KillEumlatorbyWindow())
{
AddLog(Localization.GetString("ExitEmulatorFailed"), UILogColor.Error);
}
// 休眠提示
AddLog(Localization.GetString("HibernatePrompt"), UILogColor.Error);
// 休眠不能加时间参数,https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues/1133
Process.Start("shutdown.exe", "-h");
// Shutdown 会调用 OnExit 但 Exit 不会
Application.Current.Shutdown();
// Environment.Exit(0);
break;
default:
break;
}
}
///
/// Gets a value indicating whether it is initialized.
///
public bool Inited { get; private set; } = false;
///
/// Sets it initialized.
///
public void SetInited()
{
Inited = true;
NotifyOfPropertyChange("Inited");
}
private bool _idle = false;
///
/// Gets or sets a value indicating whether it is idle.
///
public bool Idle
{
get => _idle;
set
{
SetAndNotify(ref _idle, value);
var settings = _container.Get();
settings.Idle = value;
if (value)
{
FightTaskRunning = false;
InfrastTaskRunning = false;
}
}
}
private bool _stopping = false;
///
/// Gets or sets a value indicating whether `stop` is awaiting.
///
public bool Stopping
{
get => _stopping;
set => SetAndNotify(ref _stopping, value);
}
private bool _fightTaskRunning = false;
///
/// Gets or sets a value indicating whether the battle task is running.
///
public bool FightTaskRunning
{
get => _fightTaskRunning;
set => SetAndNotify(ref _fightTaskRunning, value);
}
private bool _infrastTaskRunning = false;
public bool InfrastTaskRunning
{
get => _infrastTaskRunning;
set => SetAndNotify(ref _infrastTaskRunning, value);
}
/*
private bool _shutdown = false;
public bool Shutdown
{
get => return _shutdown;
set
{
SetAndNotify(ref _shutdown, value);
if (value)
{
Hibernate = false;
Suspend = false;
}
}
}
private bool _hibernate = false; // 休眠
public bool Hibernate
{
get => return _hibernate;
set
{
SetAndNotify(ref _hibernate, value);
if (value)
{
Shutdown = false;
Suspend = false;
}
}
}
private bool _suspend = false; // 待机
public bool Suspend
{
get => return _suspend;
set
{
SetAndNotify(ref _suspend, value);
if (value)
{
Shutdown = false;
Hibernate = false;
}
}
}
*/
private ObservableCollection _stageList = new ObservableCollection();
///
/// Gets or sets the list of stages.
///
public ObservableCollection StageList
{
get => _stageList;
set => SetAndNotify(ref _stageList, value);
}
public ObservableCollection RemainingSanityStageList { get; set; } = new ObservableCollection();
///
/// Gets the stage.
///
public string Stage
{
get
{
var settingsModel = _container.Get();
if (CustomStageCode)
{
return Stage1;
}
if (settingsModel.UseAlternateStage)
{
if (IsStageOpen(Stage1))
{
return Stage1;
}
if (IsStageOpen(Stage2))
{
return Stage2;
}
if (IsStageOpen(Stage3))
{
return Stage3;
}
}
return Stage1;
}
}
private string _stage1 = ViewStatusStorage.Get("MainFunction.Stage1", string.Empty);
///
/// Gets or sets the stage1.
///
public string Stage1
{
get => _stage1;
set
{
SetAndNotify(ref _stage1, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.Stage1", value);
UpdateDatePrompt();
}
}
private string _stage2 = ViewStatusStorage.Get("MainFunction.Stage2", string.Empty);
///
/// Gets or sets the stage2.
///
public string Stage2
{
get => _stage2;
set
{
SetAndNotify(ref _stage2, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.Stage2", value);
UpdateDatePrompt();
}
}
private string _stage3 = ViewStatusStorage.Get("MainFunction.Stage3", string.Empty);
///
/// Gets or sets the stage2.
///
public string Stage3
{
get => _stage3;
set
{
SetAndNotify(ref _stage3, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.Stage3", value);
UpdateDatePrompt();
}
}
private bool _alternateStageDisplay = !Convert.ToBoolean(ViewStatusStorage.Get("GUI.CustomStageCode", bool.FalseString))
&& Convert.ToBoolean(ViewStatusStorage.Get("GUI.UseAlternateStage", bool.FalseString));
///
/// Gets or sets a value indicating whether to use alternate stage.
///
public bool AlternateStageDisplay
{
get => _alternateStageDisplay;
set => SetAndNotify(ref _alternateStageDisplay, value);
}
private bool _customStageCode = Convert.ToBoolean(ViewStatusStorage.Get("GUI.CustomStageCode", bool.FalseString));
///
/// Gets or sets a value indicating whether to use custom stage code.
///
public bool CustomStageCode
{
get => _customStageCode;
set
{
SetAndNotify(ref _customStageCode, value);
var settingsModel = _container.Get();
AlternateStageDisplay = !value && settingsModel.UseAlternateStage;
}
}
private string _remainingSanityStage = ViewStatusStorage.Get("Fight.RemainingSanityStage", string.Empty);
public string RemainingSanityStage
{
get
{
if (!IsStageOpen(_remainingSanityStage))
{
return string.Empty;
}
return _remainingSanityStage;
}
set
{
SetAndNotify(ref _remainingSanityStage, value);
SetFightRemainingSanityParams();
ViewStatusStorage.Set("Fight.RemainingSanityStage", value);
}
}
private bool _customInfrastEnabled = Convert.ToBoolean(ViewStatusStorage.Get("Infrast.CustomInfrastEnabled", bool.FalseString));
public bool CustomInfrastEnabled
{
get => _customInfrastEnabled;
set
{
SetAndNotify(ref _customInfrastEnabled, value);
RefreshCustonInfrastPlan();
}
}
private int _customInfrastPlanIndex = Convert.ToInt32(ViewStatusStorage.Get("Infrast.CustomInfrastPlanIndex", "0"));
public int CustomInfrastPlanIndex
{
get => _customInfrastPlanIndex;
set
{
if (value != _customInfrastPlanIndex)
{
var plan = CustomInfrastPlanInfoList[value];
AddLog(plan.Name, UILogColor.Message);
foreach (var period in plan.PeriodList)
{
AddLog(string.Format("[ {0:D2}:{1:D2} - {2:D2}:{3:D2} ]",
period.BeginHour, period.BeginMinute,
period.EndHour, period.EndMinute));
}
if (plan.Description != string.Empty)
{
AddLog(plan.Description);
}
}
SetAndNotify(ref _customInfrastPlanIndex, value);
SetInfrastParams();
ViewStatusStorage.Set("Infrast.CustomInfrastPlanIndex", value.ToString());
}
}
public ObservableCollection> CustomInfrastPlanList { get; set; } = new ObservableCollection>();
public struct CustomInfrastPlanInfo
{
public int Index;
public string Name;
public string Description;
public string DescriptionPost;
// 有效时间段
public struct Period
{
public int BeginHour;
public int BeginMinute;
public int EndHour;
public int EndMinute;
}
public List PeriodList;
}
public List CustomInfrastPlanInfoList { get; set; } = new List();
private bool _customInfrastPlanHasPeriod = false;
public void RefreshCustonInfrastPlan()
{
CustomInfrastPlanInfoList.Clear();
CustomInfrastPlanList.Clear();
_customInfrastPlanHasPeriod = false;
if (!CustomInfrastEnabled)
{
return;
}
var settingsModel = _container.Get();
if (!File.Exists(settingsModel.CustomInfrastFile))
{
return;
}
try
{
string jsonStr = File.ReadAllText(settingsModel.CustomInfrastFile);
var root = (JObject)JsonConvert.DeserializeObject(jsonStr);
if (root.ContainsKey("title"))
{
AddLog(Localization.GetString("CustomInfrastTitle"), UILogColor.Message);
AddLog(root["title"].ToString(), UILogColor.Info);
if (root.ContainsKey("description"))
{
AddLog(root["description"].ToString());
}
}
var plan_list = (JArray)root["plans"];
for (int i = 0; i < plan_list.Count; ++i)
{
var plan = (JObject)plan_list[i];
string display = plan.ContainsKey("name") ? plan["name"].ToString() : ("Plan " + ((char)('A' + i)).ToString());
CustomInfrastPlanList.Add(new GenericCombData { Display = display, Value = i });
string desc = plan.ContainsKey("description") ? plan["description"].ToString() : string.Empty;
string descPost = plan.ContainsKey("description_post") ? plan["description_post"].ToString() : string.Empty;
AddLog(display, UILogColor.Message);
var periodList = new List();
if (plan.ContainsKey("period"))
{
var periodArray = (JArray)plan["period"];
foreach (var periodJson in periodArray)
{
var period = default(CustomInfrastPlanInfo.Period);
string beginTime = periodJson[0].ToString();
var beginSplited = beginTime.Split(':');
period.BeginHour = int.Parse(beginSplited[0]);
period.BeginMinute = int.Parse(beginSplited[1]);
string endTime = periodJson[1].ToString();
var endSplited = endTime.Split(':');
period.EndHour = int.Parse(endSplited[0]);
period.EndMinute = int.Parse(endSplited[1]);
periodList.Add(period);
AddLog(string.Format("[ {0:D2}:{1:D2} - {2:D2}:{3:D2} ]",
period.BeginHour, period.BeginMinute,
period.EndHour, period.EndMinute));
}
if (periodList.Count != 0)
{
_customInfrastPlanHasPeriod = true;
}
}
if (desc != string.Empty)
{
AddLog(desc);
}
if (descPost != string.Empty)
{
AddLog(descPost);
}
CustomInfrastPlanInfoList.Add(new CustomInfrastPlanInfo
{
Index = i,
Name = display,
Description = desc,
DescriptionPost = descPost,
PeriodList = periodList,
});
}
}
catch (Exception)
{
AddLog(Localization.GetString("CustomInfrastFileParseFailed"), UILogColor.Error);
return;
}
refreshCustomInfrastPlanIndexByPeriod();
}
private void refreshCustomInfrastPlanIndexByPeriod()
{
if (!CustomInfrastEnabled || !_customInfrastPlanHasPeriod || InfrastTaskRunning)
{
return;
}
bool timeLess(int lHour, int lMin, int rHour, int rMin)
{
return (lHour != rHour) ? (lHour < rHour) : (lMin <= rMin);
}
var now = DateTime.Now;
foreach (var plan in CustomInfrastPlanInfoList)
{
foreach (var period in plan.PeriodList)
{
if (timeLess(period.BeginHour, period.BeginMinute, now.Hour, now.Minute) &&
timeLess(now.Hour, now.Minute, period.EndHour, period.EndMinute))
{
CustomInfrastPlanIndex = plan.Index;
return;
}
}
}
}
public void IncreaseCustomInfrastPlanIndex()
{
if (!CustomInfrastEnabled || _customInfrastPlanHasPeriod)
{
return;
}
AddLog(Localization.GetString("CustomInfrastPlanIndexAutoSwitch"), UILogColor.Message);
var prePlanPostDesc = CustomInfrastPlanInfoList[CustomInfrastPlanIndex].DescriptionPost;
if (prePlanPostDesc != string.Empty)
{
AddLog(prePlanPostDesc);
}
if (CustomInfrastPlanIndex >= CustomInfrastPlanList.Count - 1)
{
CustomInfrastPlanIndex = 0;
}
else
{
++CustomInfrastPlanIndex;
}
}
private bool _useMedicine = Convert.ToBoolean(ViewStatusStorage.Get("MainFunction.UseMedicine", bool.FalseString));
///
/// Gets or sets a value indicating whether to use medicine.
///
public bool UseMedicine
{
get => _useMedicine;
set
{
SetAndNotify(ref _useMedicine, value);
if (!value)
{
UseStone = false;
}
SetFightParams();
ViewStatusStorage.Set("MainFunction.UseMedicine", value.ToString());
}
}
private string _medicineNumber = ViewStatusStorage.Get("MainFunction.UseMedicine.Quantity", "999");
///
/// Gets or sets the amount of medicine used.
///
public string MedicineNumber
{
get => _medicineNumber;
set
{
SetAndNotify(ref _medicineNumber, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.UseMedicine.Quantity", MedicineNumber);
}
}
private bool _useStone;
///
/// Gets or sets a value indicating whether to use originiums.
///
public bool UseStone
{
get => _useStone;
set
{
SetAndNotify(ref _useStone, value);
if (value)
{
UseMedicine = true;
}
SetFightParams();
}
}
private string _stoneNumber = ViewStatusStorage.Get("MainFunction.UseStone.Quantity", "0");
///
/// Gets or sets the amount of originiums used.
///
public string StoneNumber
{
get => _stoneNumber;
set
{
SetAndNotify(ref _stoneNumber, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.UseStone.Quantity", StoneNumber);
}
}
private bool _hasTimesLimited;
///
/// Gets or sets a value indicating whether the number of times is limited.
///
public bool HasTimesLimited
{
get => _hasTimesLimited;
set
{
SetAndNotify(ref _hasTimesLimited, value);
SetFightParams();
}
}
private string _maxTimes = ViewStatusStorage.Get("MainFunction.TimesLimited.Quantity", "5");
///
/// Gets or sets the max number of times.
///
public string MaxTimes
{
get => _maxTimes;
set
{
SetAndNotify(ref _maxTimes, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.TimesLimited.Quantity", MaxTimes);
}
}
#region Drops
private bool _isSpecifiedDrops = Convert.ToBoolean(ViewStatusStorage.Get("MainFunction.Drops.Enable", bool.FalseString));
///
/// Gets or sets a value indicating whether the drops are specified.
///
public bool IsSpecifiedDrops
{
get => _isSpecifiedDrops;
set
{
SetAndNotify(ref _isSpecifiedDrops, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.Drops.Enable", value.ToString());
}
}
private static readonly string _DropsFilename = Environment.CurrentDirectory + "\\resource\\item_index.json";
///
/// Gets or sets the list of all drops.
///
public List AllDrops { get; set; } = new List();
private void InitDrops()
{
string jsonStr = File.ReadAllText(_DropsFilename);
var reader = (JObject)JsonConvert.DeserializeObject(jsonStr);
foreach (var item in reader)
{
var val = item.Key;
// 不是数字的东西都是正常关卡不会掉的(大概吧)
if (!int.TryParse(val, out _))
{
continue;
}
var dis = item.Value["name"].ToString();
if (dis.EndsWith("双芯片") || dis.EndsWith("寻访凭证") || dis.EndsWith("加固建材")
|| dis.EndsWith("许可") || dis == "资质凭证" || dis == "高级凭证" || dis == "演习券"
|| dis.Contains("源石") || dis == "D32钢" || dis == "双极纳米片" || dis == "聚合剂"
|| dis == "晶体电子单元" || dis == "龙骨" || dis == "芯片助剂")
{
continue;
}
AllDrops.Add(new CombData { Display = dis, Value = val });
}
AllDrops.Sort((a, b) =>
{
return string.Compare(a.Value, b.Value, StringComparison.Ordinal);
});
DropsList = new ObservableCollection(AllDrops);
}
///
/// Gets or sets the list of drops.
///
public ObservableCollection DropsList { get; set; }
private string _dropsItemId = ViewStatusStorage.Get("MainFunction.Drops.ItemId", string.Empty);
///
/// Gets or sets the item ID of drops.
///
public string DropsItemId
{
get => _dropsItemId;
set
{
SetAndNotify(ref _dropsItemId, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.Drops.ItemId", DropsItemId);
}
}
private string _dropsItemName = ViewStatusStorage.Get("MainFunction.Drops.ItemName", Localization.GetString("NotSelected"));
///
/// Gets or sets the item Name of drops.
///
public string DropsItemName
{
get => _dropsItemName;
set
{
SetAndNotify(ref _dropsItemName, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.Drops.ItemName", DropsItemName);
}
}
public void DropsListDropDownClosed()
{
foreach (var item in DropsList)
{
if (DropsItemName == item.Display)
{
DropsItemId = item.Value;
if (DropsItemName != item.Display || DropsItemId != item.Value)
{
DropsItemName = Localization.GetString("NotSelected");
}
return;
}
}
DropsItemName = Localization.GetString("NotSelected");
}
private string _dropsQuantity = ViewStatusStorage.Get("MainFunction.Drops.Quantity", "5");
///
/// Gets or sets the quantity of drops.
///
public string DropsQuantity
{
get => _dropsQuantity;
set
{
SetAndNotify(ref _dropsQuantity, value);
SetFightParams();
ViewStatusStorage.Set("MainFunction.Drops.Quantity", DropsQuantity);
}
}
///
/// DropsList ComboBox loaded
///
/// Event sender
/// Event args
public void DropsList_Loaded(object sender, EventArgs e)
{
(sender as ComboBox)?.MakeComboBoxSearchable();
}
#endregion Drops
}
}