ZeroLauncher/Manager/EngineManager.cs
2024-03-11 10:57:12 +08:00

274 lines
9.2 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 System.Diagnostics;
using System.Windows;
using Zerolauncher.Defender;
namespace Zerolauncher.Manager
{
internal class EngineManager
{
private static Dictionary<string, SingleGame> mGame = new Dictionary<string, SingleGame>();
//运行时才能决定是否执行内联
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
private static string AccToKey(Account account)
{
return string.Format("{0}{1}{2}", account.providerId, account.serverId, account.userName);
}
public static bool CreateGame(Account account, out bool showDialog)
{
showDialog = false;
if (UpDateData.is_check == false)
{
MessageBox.Show("正在更新数据请等待1-3秒。\n 请检查网络", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
return true;
}
if (UpDateData.state)
{
showDialog = true;
return true;
}
var key = AccToKey(account);
if (mGame.ContainsKey(key)) { return false; }
if (CacheSha.errorCode != 0) {
switch (CacheSha.errorCode)
{
case 1:
MessageBox.Show("发生网络错误==EMS。\n 请检查网络", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error);
break;
case 2:
MessageBox.Show("发生游戏服务错误==EMS。\n 请联系管理员", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error);
break;
default:
MessageBox.Show("发生未知错误==EMS。\n 请联系管理员", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error);
break;
}
return true;
}
try
{
mGame[key] = new SingleGame(account);
}catch (Exception _ex)
{
MessageBox.Show("发生错误!\n如重复发生此错误\n请重新下载大厅文件或联系管理员。", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error);
}
return true;
}
public static bool CreateGame(int memberId, out bool showDialog)
{
return CreateGame(AccountManager.accountsList[memberId], out showDialog);
}
public static int CheckGameState(Account account)
{
var key = AccToKey(account);
if (mGame.ContainsKey(key)) { return mGame[key].mHandle; }
return -1;
}
public static short TurnGameSizeMini(Account account)
{
var key = AccToKey(account);
if (mGame.ContainsKey(key))
{
var game = mGame[key];
if (game.mHandle != 0)
{
game.Send(StaticHandleS.MiniSize);
return 2;
}
return 1;
}
return 0;
}
public static short TurnGameSizeNormal(Account account)
{
var key = AccToKey(account);
if (mGame.ContainsKey(key))
{
var game = mGame[key];
if (game.mHandle != 0)
{
game.Send(StaticHandleS.NormalSize);
return 2;
}
return 1;
}
return 0;
}
public static bool ExitGame(Account account)
{
var key = AccToKey(account);
if (!mGame.ContainsKey(key)) { return false; }
mGame[key].Send(StaticHandleS.CloseGame);
return true;
}
public static void OnGameExit(Account account)
{
mGame.Remove(AccToKey(account));
}
public static bool CheckEmpy()
{
return mGame.Count == 0;
}
}
class SingleGame
{
Process process;
string? restartUrl;
public int mHandle;
public Account? account;
string gameMode;
public SingleGame(Account? acc, string mod = StaticHandleA.GameMode)
{
restartUrl = null;
account = acc;
gameMode = mod;
mHandle = 0;
process = EngineShell.CheckEngineSafe(gameMode);
if (gameMode != StaticHandleA.UpdateMode)
{
process.OutputDataReceived += Handle;
process.Exited += Process_Exited;
}
process.Start();
if (gameMode != StaticHandleA.UpdateMode)
{
process.BeginOutputReadLine(); // 开始异步读取
if (gameMode == StaticHandleA.Version)
{
process.WaitForExit();
}
}
}
private void CreateProcess()
{
process = EngineShell.CheckEngineSafe(gameMode);
process.OutputDataReceived += Handle;
process.Exited += Process_Exited;
process.Start();
process.BeginOutputReadLine(); // 开始异步读取
}
private void Process_Exited(object? sender, EventArgs e)
{
//Trace.WriteLine(
// $"Exit time : {process.ExitTime}\n" +
// $"Exit code : {process.ExitCode}\n" +
// $"Elapsed time : {Math.Round((process.ExitTime - process.StartTime).TotalMilliseconds)}");
//Trace.WriteLine($"进程已退出:{account.nickName}");
if (gameMode != StaticHandleA.GameMode) return;
if ( restartUrl == null)
{
EngineManager.OnGameExit(account);
return;
}
CreateProcess();
}
private void Handle(object sender, DataReceivedEventArgs e)
{
var lines = e.Data == null? [""] : e.Data.Split(" ");
switch (lines[0])
{
case StaticHandleC.StartDone:
if(restartUrl == null)
{
Send($"{StaticHandleS.ShowWindow} {ServicesStaticInfo.ServicesName[account.providerId]}-{account.nickName}");
Task.Run(async delegate
{
if (lines[1] == "True") await Task.Delay(5000);
_ =LoginManager.DoLogin(this);
});
}
else
{
Send($"{StaticHandleS.ShowWindow} {ServicesStaticInfo.ServicesName[account.providerId]}-{account.nickName}");
Send($"{StaticHandleS.GameSa} {restartUrl}");
restartUrl = null;
}
break;
case StaticHandleC.GameDone:
mHandle = int.Parse(lines[1]);
break;
case StaticHandleC.BrowserDone:
restartUrl = lines[1];
Send(StaticHandleS.CloseGame);
break;
case StaticHandleC.Version:
mHandle = int.Parse(lines[1]);
break;
}
}
public bool Send(string msg)
{
if(process.HasExited) { return false; }
process.StandardInput.WriteLine(msg);
return true;
}
}
public class FileReadException : Exception
{
public FileReadException(string message) : base(message)
{
}
}
class EngineShell
{
static bool is_check = false;
const string engine_file = @"ZeroEngine.exe";
public static Process CheckEngineSafe(string mod)
{
bool is_first_luancher = EngineManager.CheckEmpy();
//if (!is_check && is_first_luancher)
//{
// string? now_bit;
// using (SHA256 sha256 = SHA256.Create())
// {
// using (FileStream fileStream = File.OpenRead(engine_file))
// {
// byte[] hashBytes = sha256.ComputeHash(fileStream);
// now_bit = BitConverter.ToString(hashBytes).Replace("-", string.Empty);
// }
// }
// if (EngineCacheSha.Get() != now_bit)
// {
// throw new FileReadException("无法读取文件内容");
// }
// is_check = true;
//}
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = engine_file,
Arguments = $"{mod} {is_first_luancher}",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true
},
EnableRaisingEvents = true
};
return process;
}
}
}