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 mGame = new Dictionary(); //运行时才能决定是否执行内联 [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) { var key = AccToKey(account); if (mGame.ContainsKey(key)) { return false; } if (EngineCacheSha.errorCode != 0) { switch (EngineCacheSha.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 false; } try { mGame[key] = new SingleGame(account); }catch (Exception _ex) { MessageBox.Show("发生错误!\n如重复发生此错误,\n请重新下载登陆器文件或联系管理员。", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error); return false; } return true; } public static bool CreateGame(int memberId) { return CreateGame(AccountManager.accountsList[memberId]); } 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; public SingleGame(Account acc) { restartUrl = null; this.account = acc; mHandle = 0; process = EngineShell.CheckEngineSafe(); process.OutputDataReceived += Handle; process.Exited += Process_Exited; process.Start(); process.BeginOutputReadLine(); // 开始异步读取 } private void CreateProcess() { process = EngineShell.CheckEngineSafe(); 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 ( 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}"); _ = 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; } } 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() { if (!is_check && EngineManager.CheckEmpy()) { 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 = StaticHandleA.GameMode, UseShellExecute = false, CreateNoWindow = true, RedirectStandardInput = true, RedirectStandardOutput = true }, EnableRaisingEvents = true }; return process; } } }