Files
PCL2/pcl2_full/Plain Craft Launcher 2/ModWatcher.cs
1989-06-04 00:00:04 +09:00

619 lines
20 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 Microsoft.VisualBasic.CompilerServices;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace PCL
{
// Token: 0x02000060 RID: 96
[StandardModule]
public sealed class ModWatcher
{
// Token: 0x0600029A RID: 666 RVA: 0x00003A5E File Offset: 0x00001C5E
// Note: this type is marked as 'beforefieldinit'.
static ModWatcher()
{
ModWatcher.m_TestsVal = new List<ModWatcher.Watcher>();
ModWatcher.broadcasterVal = false;
ModWatcher.m_FieldVal = false;
}
// Token: 0x0600029B RID: 667 RVA: 0x0001A238 File Offset: 0x00018438
private static void WatcherStateChanged()
{
bool flag = false;
bool hasMinecraftCrashed = false;
try
{
foreach (ModWatcher.Watcher watcher in ModWatcher.m_TestsVal)
{
if (watcher.State != ModWatcher.Watcher.MinecraftState.Loading)
{
if (watcher.State != ModWatcher.Watcher.MinecraftState.Running)
{
if (watcher.State == ModWatcher.Watcher.MinecraftState.Crashed)
{
hasMinecraftCrashed = true;
continue;
}
continue;
}
}
flag = true;
break;
}
}
finally
{
List<ModWatcher.Watcher>.Enumerator enumerator;
((IDisposable)enumerator).Dispose();
}
if (ModWatcher.broadcasterVal != flag)
{
ModWatcher.broadcasterVal = flag;
if (ModWatcher.broadcasterVal)
{
ModWatcher.MinecraftStart();
return;
}
ModWatcher.MinecraftStop(hasMinecraftCrashed);
}
}
// Token: 0x0600029C RID: 668 RVA: 0x00003A76 File Offset: 0x00001C76
private static void MinecraftStart()
{
ModLaunch.McLaunchLog("[全局] 出现运行中的 Minecraft");
ModWatcher.m_FieldVal = true;
ModMain.m_GetterFilter.BtnExtraShutdown.ShowRefresh();
}
// Token: 0x0600029D RID: 669 RVA: 0x0001A2CC File Offset: 0x000184CC
private static void MinecraftStop(bool HasMinecraftCrashed)
{
ModLaunch.McLaunchLog("[全局] 已无运行中的 Minecraft");
ModWatcher.m_FieldVal = false;
ModMain.m_GetterFilter.BtnExtraShutdown.ShowRefresh();
if (Conversions.ToBoolean(ModBase._BaseRule.Get("UiMusicStop", null)))
{
ModBase.RunInUi((ModWatcher._Closure$__.$I6-0 == null) ? (ModWatcher._Closure$__.$I6-0 = delegate()
{
if (ModMusic.MusicResume())
{
ModBase.Log("[Music] 已根据设置,在结束后开始音乐播放", ModBase.LogLevel.Normal, "出现错误");
}
}) : ModWatcher._Closure$__.$I6-0, false);
}
else if (Conversions.ToBoolean(ModBase._BaseRule.Get("UiMusicStart", null)))
{
ModBase.RunInUi((ModWatcher._Closure$__.$I6-1 == null) ? (ModWatcher._Closure$__.$I6-1 = delegate()
{
if (ModMusic.MusicPause())
{
ModBase.Log("[Music] 已根据设置,在结束后暂停音乐播放", ModBase.LogLevel.Normal, "出现错误");
}
}) : ModWatcher._Closure$__.$I6-1, false);
}
object left = ModBase._BaseRule.Get("LaunchArgumentVisible", null);
if (!Operators.ConditionalCompareObjectEqual(left, 2, true))
{
if (Operators.ConditionalCompareObjectEqual(left, 3, true))
{
ModBase.RunInUi((ModWatcher._Closure$__.$I6-4 == null) ? (ModWatcher._Closure$__.$I6-4 = delegate()
{
ModMain.m_GetterFilter.Hidden = false;
}) : ModWatcher._Closure$__.$I6-4, false);
}
return;
}
if (HasMinecraftCrashed)
{
ModBase.RunInUi((ModWatcher._Closure$__.$I6-2 == null) ? (ModWatcher._Closure$__.$I6-2 = delegate()
{
ModMain.m_GetterFilter.Hidden = false;
}) : ModWatcher._Closure$__.$I6-2, false);
return;
}
ModBase.RunInUi((ModWatcher._Closure$__.$I6-3 == null) ? (ModWatcher._Closure$__.$I6-3 = delegate()
{
ModMain.m_GetterFilter.EndProgram(false);
}) : ModWatcher._Closure$__.$I6-3, false);
}
// Token: 0x04000148 RID: 328
public static List<ModWatcher.Watcher> m_TestsVal;
// Token: 0x04000149 RID: 329
private static bool broadcasterVal;
// Token: 0x0400014A RID: 330
public static bool m_FieldVal;
// Token: 0x02000061 RID: 97
public class Watcher
{
// Token: 0x0600029E RID: 670 RVA: 0x0001A430 File Offset: 0x00018630
public Watcher(ModLoader.LoaderTask<Process, int> Loader, ModMinecraft.McVersion Version, string WindowTitle)
{
ModWatcher.Watcher._Closure$__5-0 CS$<>8__locals1 = new ModWatcher.Watcher._Closure$__5-0(CS$<>8__locals1);
CS$<>8__locals1.$VB$Local_Loader = Loader;
CS$<>8__locals1.$VB$Local_WindowTitle = WindowTitle;
base..ctor();
CS$<>8__locals1.$VB$Me = this;
this.m_AttributeRule = "";
this.advisorRule = ModWatcher.Watcher.MinecraftState.Loading;
this._StrategyRule = new List<string>(0x3E8);
this.m_WrapperRule = RuntimeHelpers.GetObjectValue(new object());
this.m_WriterRule = new Queue<string>();
this._ExporterRule = 0;
this.recordRule = false;
this.m_GetterRule = false;
this._RoleRule = CS$<>8__locals1.$VB$Local_Loader;
this.registryRule = Version;
this.m_AttributeRule = CS$<>8__locals1.$VB$Local_WindowTitle;
this._ValueRule = CS$<>8__locals1.$VB$Local_Loader.Input.Id;
this.WatcherLog("开始 Minecraft 日志监控");
if (Operators.CompareString(this.m_AttributeRule, "", true) != 0)
{
this.WatcherLog("要求窗口标题:" + CS$<>8__locals1.$VB$Local_WindowTitle);
}
List<ModWatcher.Watcher> list = new List<ModWatcher.Watcher>();
try
{
foreach (ModWatcher.Watcher watcher in ModWatcher.m_TestsVal)
{
if (watcher.State != ModWatcher.Watcher.MinecraftState.Crashed && watcher.State != ModWatcher.Watcher.MinecraftState.Ended)
{
list.Add(watcher);
}
}
}
finally
{
List<ModWatcher.Watcher>.Enumerator enumerator;
((IDisposable)enumerator).Dispose();
}
list.Add(this);
ModWatcher.m_TestsVal = list;
ModWatcher.WatcherStateChanged();
this.comparatorRule = CS$<>8__locals1.$VB$Local_Loader.Input;
this.comparatorRule.BeginOutputReadLine();
this.comparatorRule.BeginErrorReadLine();
this.comparatorRule.OutputDataReceived += this.LogReceived;
this.comparatorRule.ErrorDataReceived += this.LogReceived;
ModBase.RunInNewThread(checked(delegate
{
try
{
CS$<>8__locals1.$VB$Me._InvocationRule = CS$<>8__locals1.$VB$Me.GetAllMinecraftWindowHandle(false).Keys.ToList<IntPtr>();
while (CS$<>8__locals1.$VB$Me.State != ModWatcher.Watcher.MinecraftState.Ended && CS$<>8__locals1.$VB$Me.State != ModWatcher.Watcher.MinecraftState.Crashed)
{
if (CS$<>8__locals1.$VB$Local_Loader.State == ModBase.LoadState.Aborted)
{
break;
}
CS$<>8__locals1.$VB$Me.TimerWindow();
CS$<>8__locals1.$VB$Me.TimerLog();
if (CS$<>8__locals1.$VB$Me.State == ModWatcher.Watcher.MinecraftState.Loading)
{
CS$<>8__locals1.$VB$Me.ProgressUpdate();
}
int num = 1;
do
{
if (CS$<>8__locals1.$VB$Me.m_GetterRule && Operators.CompareString(CS$<>8__locals1.$VB$Local_WindowTitle, "", true) != 0 && CS$<>8__locals1.$VB$Me.State == ModWatcher.Watcher.MinecraftState.Running && !CS$<>8__locals1.$VB$Me.comparatorRule.HasExited)
{
string text = CS$<>8__locals1.$VB$Local_WindowTitle.Replace("{time}", DateTime.Now.ToShortTimeString());
int hWnd = (int)CS$<>8__locals1.$VB$Me.interceptorRule;
string text2 = new string(text.ToCharArray());
ModWatcher.Watcher.SetWindowTextA(hWnd, ref text2);
}
Thread.Sleep(0x40);
num++;
}
while (num <= 3);
}
CS$<>8__locals1.$VB$Me.WatcherLog("Minecraft 日志监控已退出");
}
catch (Exception ex)
{
ModBase.Log(ex, "Minecraft 日志监控主循环出错", ModBase.LogLevel.Feedback, "出现错误");
CS$<>8__locals1.$VB$Me.State = ModWatcher.Watcher.MinecraftState.Ended;
}
}), "Minecraft Watcher PID " + Conversions.ToString(this._ValueRule), ThreadPriority.Normal);
}
// Token: 0x1700005C RID: 92
// (get) Token: 0x0600029F RID: 671 RVA: 0x00003A97 File Offset: 0x00001C97
// (set) Token: 0x060002A0 RID: 672 RVA: 0x00003A9F File Offset: 0x00001C9F
public ModWatcher.Watcher.MinecraftState State
{
get
{
return this.advisorRule;
}
set
{
if (this.advisorRule != value)
{
this.advisorRule = value;
ModWatcher.WatcherStateChanged();
}
}
}
// Token: 0x060002A1 RID: 673 RVA: 0x0001A608 File Offset: 0x00018808
private void LogReceived(object sender, DataReceivedEventArgs e)
{
object wrapperRule = this.m_WrapperRule;
ObjectFlowControl.CheckForSyncLockOnValueType(wrapperRule);
lock (wrapperRule)
{
this._StrategyRule.Add(e.Data);
}
}
// Token: 0x060002A2 RID: 674 RVA: 0x0001A65C File Offset: 0x0001885C
private void TimerLog()
{
try
{
List<string> list = new List<string>();
object wrapperRule = this.m_WrapperRule;
ObjectFlowControl.CheckForSyncLockOnValueType(wrapperRule);
lock (wrapperRule)
{
if (this._StrategyRule.Count == 0)
{
return;
}
list = this._StrategyRule;
this._StrategyRule = new List<string>(0x3E8);
}
try
{
foreach (string text in list)
{
this.GameLog(text);
}
}
finally
{
List<string>.Enumerator enumerator;
((IDisposable)enumerator).Dispose();
}
if (this.comparatorRule.HasExited)
{
this.WatcherLog("Minecraft 已退出,返回值:" + Conversions.ToString(this.comparatorRule.ExitCode));
if (this.State == ModWatcher.Watcher.MinecraftState.Loading)
{
this.WatcherLog("Minecraft 尚未加载完成,可能已崩溃");
this.Crashed();
}
else if (this.comparatorRule.ExitCode != 0 && this.State == ModWatcher.Watcher.MinecraftState.Running && this.registryRule.m_RulesAlgo.Year >= 0x7DC)
{
this.WatcherLog("Minecraft 返回值异常,可能已崩溃");
this.Crashed();
}
else
{
this.State = ModWatcher.Watcher.MinecraftState.Ended;
}
}
}
catch (Exception ex)
{
ModBase.Log(ex, "输出 Minecraft 日志失败", ModBase.LogLevel.Feedback, "出现错误");
}
}
// Token: 0x060002A3 RID: 675 RVA: 0x0001A7F0 File Offset: 0x000189F0
private void GameLog(string Text)
{
if (Text != null)
{
Text = Text.Replace("\r\n", "\r").Replace("\n", "\r").Replace("\r", "\r\n");
this.m_WriterRule.Enqueue(Text);
if (this.m_WriterRule.Count >= 0xC9)
{
this.m_WriterRule.Dequeue();
}
if (this._ExporterRule < 1)
{
this.WatcherLog("日志 1/5已出现日志输出");
this._ExporterRule = 1;
}
if (this._ExporterRule < 2 && Text.Contains("Setting user:"))
{
this.WatcherLog("日志 2/5游戏用户已设置");
this._ExporterRule = 2;
}
else if (this._ExporterRule < 3 && Text.ToLower().Contains("lwjgl version"))
{
this.WatcherLog("日志 3/5LWJGL 版本已确认");
this._ExporterRule = 3;
}
else if (this._ExporterRule < 4 && (Text.Contains("OpenAL initialized") || Text.Contains("Starting up SoundSystem")))
{
this.WatcherLog("日志 4/5OpenAL 已加载");
this._ExporterRule = 4;
}
else if (this._ExporterRule < 5 && ((Text.Contains("Created") && Text.Contains("textures") && Text.Contains("-atlas")) || Text.Contains("Found animation info")))
{
this.WatcherLog("日志 5/5材质已加载");
this._ExporterRule = 5;
}
if (!Text.Contains("[CHAT]"))
{
if (Text.Contains("Someone is closing me!"))
{
this.WatcherLog("识别为关闭的 Log" + Text);
this.State = ModWatcher.Watcher.MinecraftState.Ended;
return;
}
if (Text.Contains("Game crashed! Crash report saved to:") || Text.Contains("This crash report has been saved to:"))
{
this.WatcherLog("识别为崩溃的 Log" + Text);
this.Crashed();
return;
}
if (Text.Contains("Could not save crash report to"))
{
this.WatcherLog("识别为崩溃的 Log" + Text);
this.Crashed();
return;
}
if (Text.Contains("/ERROR]: Unable to launch") || Text.Contains("An exception was thrown, the game will display an error screen and halt."))
{
this.WatcherLog("识别为崩溃的 Log" + Text);
this.Crashed();
}
}
}
}
// Token: 0x060002A4 RID: 676 RVA: 0x00003AB6 File Offset: 0x00001CB6
private void WatcherLog(string Text)
{
ModLaunch.McLaunchLog("[" + Conversions.ToString(this._ValueRule) + "] " + Text);
}
// Token: 0x060002A5 RID: 677 RVA: 0x0001AA20 File Offset: 0x00018C20
private void ProgressUpdate()
{
double progress;
if (!this.recordRule)
{
if (this._ExporterRule != 5)
{
progress = (double)Math.Min(this._ExporterRule, 3) / 3.0 * 0.9;
goto IL_53;
}
}
progress = 0.95;
this.WatcherLog("Minecraft 加载已完成");
this.State = ModWatcher.Watcher.MinecraftState.Running;
IL_53:
this._RoleRule.Progress = progress;
}
// Token: 0x060002A6 RID: 678 RVA: 0x0001AA8C File Offset: 0x00018C8C
private void TimerWindow()
{
try
{
if (!this.comparatorRule.HasExited)
{
if (!this.m_GetterRule)
{
Dictionary<IntPtr, bool> allMinecraftWindowHandle = this.GetAllMinecraftWindowHandle(true);
try
{
foreach (IntPtr key in this._InvocationRule)
{
if (allMinecraftWindowHandle.ContainsKey(key))
{
allMinecraftWindowHandle.Remove(key);
}
}
}
finally
{
List<IntPtr>.Enumerator enumerator;
((IDisposable)enumerator).Dispose();
}
if (allMinecraftWindowHandle.Count != 0)
{
if (allMinecraftWindowHandle.Values.ElementAtOrDefault(0))
{
this.interceptorRule = allMinecraftWindowHandle.Keys.ElementAtOrDefault(0);
this.WatcherLog("Minecraft 窗口已加载:" + Conversions.ToString(this.interceptorRule.ToInt64()));
this.m_GetterRule = true;
Thread.Sleep(0xBB8);
if (Operators.ConditionalCompareObjectEqual(ModBase._BaseRule.Get("LaunchArgumentWindowType", null), 4, true))
{
ModWatcher.Watcher.ShowWindow(this.interceptorRule, 3U);
}
}
else if (!this.recordRule)
{
this.WatcherLog("FML 窗口已加载:" + Conversions.ToString(allMinecraftWindowHandle.Keys.ElementAtOrDefault(0).ToInt64()));
}
this.recordRule = true;
}
}
}
}
catch (Exception ex)
{
ModBase.Log(ex, "检查 Minecraft 窗口失败", ModBase.LogLevel.Feedback, "出现错误");
}
}
// Token: 0x060002A7 RID: 679 RVA: 0x00003AD8 File Offset: 0x00001CD8
private Dictionary<IntPtr, bool> GetAllMinecraftWindowHandle(bool CanUseFml)
{
Dictionary<IntPtr, bool> AllList = new Dictionary<IntPtr, bool>();
ModWatcher.Watcher.EnumWindows(delegate(IntPtr hwnd, int lParam)
{
StringBuilder stringBuilder = new StringBuilder(0x200);
ModWatcher.Watcher.GetClassNameA((int)hwnd, stringBuilder, stringBuilder.Capacity);
string left = stringBuilder.ToString();
if (Operators.CompareString(left, "GLFW30", true) == 0 || Operators.CompareString(left, "LWJGL", true) == 0 || Operators.CompareString(left, "SunAwtFrame", true) == 0)
{
stringBuilder = new StringBuilder(0x200);
ModWatcher.Watcher.GetWindowTextA((int)hwnd, stringBuilder, stringBuilder.Capacity);
string text = stringBuilder.ToString();
if (CanUseFml && text.StartsWith("FML"))
{
AllList.Add(hwnd, false);
return;
}
if (!text.StartsWith("GLFW") && Operators.CompareString(text, "PopupMessageWindow", true) != 0)
{
AllList.Add(hwnd, true);
}
}
}, 0);
return AllList;
}
// Token: 0x060002A8 RID: 680
[DllImport("user32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool EnumWindows(ModWatcher.Watcher.EnumWindowsSub hWnd, int lParam);
// Token: 0x060002A9 RID: 681
[DllImport("user32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern int GetClassNameA(int hWnd, StringBuilder str, int maxCount);
// Token: 0x060002AA RID: 682
[DllImport("user32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern int GetWindowTextA(int hWnd, StringBuilder str, int maxCount);
// Token: 0x060002AB RID: 683
[DllImport("user32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool SetWindowTextA(int hWnd, [MarshalAs(UnmanagedType.VBByRefStr)] ref string str);
// Token: 0x060002AC RID: 684
[DllImport("user32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool ShowWindow(IntPtr hWnd, uint cmdWindow);
// Token: 0x060002AD RID: 685 RVA: 0x0001AC18 File Offset: 0x00018E18
private void Crashed()
{
if (this.State != ModWatcher.Watcher.MinecraftState.Crashed && this.State != ModWatcher.Watcher.MinecraftState.Ended)
{
this.State = ModWatcher.Watcher.MinecraftState.Crashed;
this.WatcherLog("Minecraft 已崩溃,将在 2 秒后开始崩溃分析");
ModMain.Hint("检测到 Minecraft 出现错误,错误分析已开始……", ModMain.HintType.Info, true);
ModBase.RunInNewThread(delegate
{
try
{
Thread.Sleep(0x7D0);
this.WatcherLog("崩溃分析开始");
ModCrash.CrashAnalyzer crashAnalyzer = new ModCrash.CrashAnalyzer(this._ValueRule);
crashAnalyzer.Collect(this.registryRule.ManageExpression(), this.m_WriterRule.ToList<string>());
crashAnalyzer.Prepare();
crashAnalyzer.Analyze(this.registryRule);
crashAnalyzer.Output(false, new List<string>
{
this.registryRule.Path + this.registryRule.Name + ".json",
ModBase.Path + "PCL\\Log1.txt",
ModBase.Path + "PCL\\LatestLaunch.bat"
});
}
catch (Exception ex)
{
ModBase.Log(ex, "崩溃分析失败", ModBase.LogLevel.Feedback, "出现错误");
}
}, "Crash Analyzer", ThreadPriority.Normal);
}
}
// Token: 0x060002AE RID: 686 RVA: 0x0001AC70 File Offset: 0x00018E70
public void Kill()
{
this.State = ModWatcher.Watcher.MinecraftState.Ended;
this.WatcherLog("尝试强制结束 Minecraft 进程");
try
{
if (!this.comparatorRule.HasExited)
{
this.comparatorRule.Kill();
}
this.WatcherLog("已强制结束 Minecraft 进程");
}
catch (Exception ex)
{
ModBase.Log(ex, "强制结束 Minecraft 进程失败", ModBase.LogLevel.Hint, "出现错误");
}
}
// Token: 0x0400014B RID: 331
public Process comparatorRule;
// Token: 0x0400014C RID: 332
public ModMinecraft.McVersion registryRule;
// Token: 0x0400014D RID: 333
private string m_AttributeRule;
// Token: 0x0400014E RID: 334
private int _ValueRule;
// Token: 0x0400014F RID: 335
public ModLoader.LoaderTask<Process, int> _RoleRule;
// Token: 0x04000150 RID: 336
private ModWatcher.Watcher.MinecraftState advisorRule;
// Token: 0x04000151 RID: 337
public List<string> _StrategyRule;
// Token: 0x04000152 RID: 338
private readonly object m_WrapperRule;
// Token: 0x04000153 RID: 339
public Queue<string> m_WriterRule;
// Token: 0x04000154 RID: 340
private int _ExporterRule;
// Token: 0x04000155 RID: 341
private bool recordRule;
// Token: 0x04000156 RID: 342
private bool m_GetterRule;
// Token: 0x04000157 RID: 343
private IntPtr interceptorRule;
// Token: 0x04000158 RID: 344
private List<IntPtr> _InvocationRule;
// Token: 0x02000062 RID: 98
public enum MinecraftState
{
// Token: 0x0400015A RID: 346
Loading,
// Token: 0x0400015B RID: 347
Running,
// Token: 0x0400015C RID: 348
Crashed,
// Token: 0x0400015D RID: 349
Ended
}
// Token: 0x02000063 RID: 99
// (Invoke) Token: 0x060002B3 RID: 691
private delegate void EnumWindowsSub(IntPtr hwnd, int lParam);
}
}
}