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) { 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(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); process.OutputDataReceived += 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) { //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: restartUrl = lines[1]; Send(StaticHandleS.CloseGame); break; case StaticHandleC.Version: mHandle = int.Parse(lines[1]); break; case StaticHandleC.DownloadDone: UpDateManager.OnDownLoadDone(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 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(); if (mod == StaticHandleA.UpdateMode) { if (DataStream.dataStream.ecs.Length > 10) { 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 (DataStream.dataStream.ecs != now_bit) { Trace.WriteLine("lalalala" + DataStream.dataStream.ecs); throw new FileReadException("error esu1!"); } } } 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!"); } if (DataStream.dataStream.ecs != now_bit) { DataStream.dataStream.ecs = now_bit; DataStream.write(); } is_check = true; } var process = new Process { StartInfo = new ProcessStartInfo { FileName = engine_file, Arguments = $"{StaticHandleA.GameMode} {needShowTis}", UseShellExecute = false, CreateNoWindow = true, RedirectStandardInput = true, RedirectStandardOutput = true }, EnableRaisingEvents = true }; if (needShowTis) needShowTis = false; return process; } } }