ZeroLauncher/Manager/EngineManager.cs

297 lines
9.9 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.IO;
using System.Security.Cryptography;
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(AccountNew account)
{
return string.Format("{0}{1}{2}", account.ProviderId, account.ServerId, account.userName);
}
public static bool CreateGame(AccountNew account)
{
if (UpDateData.is_check == false)
{
MessageBox.Show("正在更新游戏数据请等待1-3秒喵。\n 请检查网络", "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
return true;
}
if (UpDateManager.state)
{
UpDateManager.DoUpdate();
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.OK, MessageBoxImage.Error);
break;
case 2:
MessageBox.Show("发生游戏服务错误==EMS。\n 请联系管理员喵", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
break;
default:
MessageBox.Show("发生未知错误==EMS。\n 请联系管理员喵", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
break;
}
return true;
}
try
{
mGame[key] = new SingleGame(account);
}catch (Exception _ex)
{
Trace.WriteLine("lalalala3");
UpDateManager.DoUpdate();
}
return true;
}
public static bool CreateGame(int memberId)
{
return CreateGame(AccountManager.AccountsList[memberId]);
}
public static int CheckGameState(AccountNew account)
{
var key = AccToKey(account);
if (mGame.ContainsKey(key)) { return mGame[key].mHandle; }
return -1;
}
public static short TurnGameSizeMini(AccountNew 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(AccountNew 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(AccountNew account)
{
var key = AccToKey(account);
if (!mGame.ContainsKey(key)) { return false; }
mGame[key].Send(StaticHandleS.CloseGame);
return true;
}
public static void OnGameExit(AccountNew account)
{
mGame.Remove(AccToKey(account));
}
public static bool CheckEmpy()
{
return mGame.Count == 0;
}
}
class SingleGame
{
Process process;
string? restartUrl;
public int mHandle;
public AccountNew? account;
string gameMode;
public SingleGame(AccountNew? acc, string mod = StaticHandleA.GameMode)
{
restartUrl = null;
account = acc;
gameMode = mod;
mHandle = 0;
process = EngineShell.CheckEngineSafe(gameMode);
process.OutputDataReceived += Handle;
process.ErrorDataReceived += Handle;
process.Exited += Process_Exited;
process.Start();
process.BeginOutputReadLine(); // 开始异步读取
}
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)
{
if (account == null) return;
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(" ", 2); // 切成两半
switch (lines[0])
{
case StaticHandleC.LoadDone:
if (gameMode == StaticHandleA.UpdateMode)
{
UpDateManager.DoUpdate1();
return;
}
Send($"{StaticHandleS.ShowWindow} {ServicesStaticInfo.ServicesName[account.ProviderId]}-{account.nickName}");
break;
case StaticHandleC.StartDone:
if (gameMode == StaticHandleA.UpdateMode)
{
UpDateManager.DoUpdate2();
return;
}
if (restartUrl == null)
{
Task.Run(async delegate
{
if (lines[1] == "True") await Task.Delay(5000);
LoginManager.DoLogin(this);
});
}
else
{
Send($"{StaticHandleS.GameSa} {restartUrl}");
restartUrl = null;
}
break;
case StaticHandleC.GameDone:
mHandle = int.Parse(lines[1]);
break;
case StaticHandleC.BrowserDone:
Trace.WriteLine($"尝试让游戏退出:{account.nickName}");
restartUrl = lines[1];
Send(StaticHandleS.CloseGame);
break;
case StaticHandleC.Version:
mHandle = int.Parse(lines[1]);
break;
case StaticHandleC.DownloadDone:
UpDateManager.OnDownLoadDone(lines[1]);
break;
case StaticHandleC.TakeVerify:
var args = lines[1].Split(' ');
_ = LoginManager.DoVerify(this, args[0], args[1]);
break;
default:
Trace.WriteLine($"from client:{e.Data}");
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 needShowTis = true;
static bool is_check = false;
const string engine_file = @"ZeroEngine.exe";
public static Process CheckEngineSafe(string mod)
{
bool is_first_luancher = EngineManager.CheckEmpy();
#region
if (mod == StaticHandleA.UpdateMode)
{
}
else 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 (CacheSha.GetE() != now_bit)
{
Trace.WriteLine("lalalala1");
throw new FileReadException("error esu0!");
}
is_check = true;
}
#endregion
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = engine_file,
Arguments = $"{StaticHandleA.GameMode} {needShowTis}",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
},
EnableRaisingEvents = true
};
if (needShowTis) needShowTis = false;
return process;
}
}
}