Use harmony instead of custom patcher

Cleanup code from decompiler
This commit is contained in:
2024-11-06 10:15:39 -05:00
parent c05d904954
commit c249c8b660
6 changed files with 168 additions and 412 deletions

View File

@@ -1,8 +1,7 @@
using System;
using System.Diagnostics;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using ClientPlugin;
using HarmonyLib;
using Sandbox;
using Sandbox.Engine.Multiplayer;
using Sandbox.Engine.Networking;
@@ -17,189 +16,160 @@ using VRage.GameServices;
using VRage.Plugins;
using VRage.Utils;
namespace TimeoutFixPlugin
namespace TimeoutFix;
public class TimeoutFix : IPlugin
{
public class TimeoutFix : IPlugin, IDisposable
private const string Version = "v2.2";
private static readonly MethodInfo Target = typeof(MyJoinGameHelper).GetMethod(nameof(DownloadWorld), BindingFlags.Static | BindingFlags.NonPublic);
private static readonly MethodInfo Patch = typeof(TimeoutFix).GetMethod(nameof(DownloadWorld), BindingFlags.Static | BindingFlags.NonPublic);
private static readonly MethodInfo ReceiveTarget = typeof(MyJoinGameHelper).GetMethod(nameof(WorldReceived), BindingFlags.Static | BindingFlags.Public);
private static readonly MethodInfo ReceivePatch = typeof(TimeoutFix).GetMethod(nameof(WorldReceived), BindingFlags.Static | BindingFlags.NonPublic);
private static readonly FieldInfo ProgressField = typeof(MyJoinGameHelper).GetField("m_progress", BindingFlags.Static | BindingFlags.NonPublic);
private static bool _worldReceived;
private static MyGuiScreenProgressBase Progress
{
private static MyGuiScreenProgressBase m_progress
get => (MyGuiScreenProgressBase)ProgressField.GetValue(null);
set => ProgressField.SetValue(null, value);
}
public void Dispose()
{
}
public void Init(object gameInstance)
{
var harmony = new Harmony(nameof(TimeoutFix));
harmony.Patch(Target, new HarmonyMethod(Patch));
harmony.Patch(ReceiveTarget, new HarmonyMethod(ReceivePatch));
}
public void Update()
{
}
private static bool DownloadWorld(MyGuiScreenProgress progress, MyMultiplayerBase multiplayer)
{
_worldReceived = false;
if (progress.Text != null)
{
get
progress.Text.Clear();
progress.Text.Append(MyTexts.Get(MyCommonTexts.MultiplayerStateConnectingToServer));
}
MyLog.Default.WriteLine($"World requested: Timeout fix {Version}");
var worldRequestTime = Stopwatch.StartNew();
var serverId = multiplayer.GetOwner();
var connected = false;
progress.Tick += delegate
{
var myP2PSessionState = default(MyP2PSessionState);
MyGameService.Peer2Peer.GetSessionState(multiplayer.ServerId, ref myP2PSessionState);
if (!connected && myP2PSessionState.ConnectionActive)
{
return (MyGuiScreenProgressBase)((MyGuiScreenProgressBase)TimeoutFix._progressField.GetValue(null));
MyLog.Default.WriteLine("World requested - connection alive");
connected = true;
if (progress.Text != null)
{
progress.Text.Clear();
progress.Text.AppendLine("Using Rexxar's fixed join code v2.2! :D");
progress.Text.Append(MyTexts.Get(MyCommonTexts.MultiplayerStateWaitingForServer));
}
}
set
if (connected && !myP2PSessionState.ConnectionActive)
{
TimeoutFix._progressField.SetValue(null, value);
MyLog.Default.WriteLine("World request - connection dropped");
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplaterJoin_ServerIsNotResponding, default, MyMessageBoxStyleEnum.Error);
MySessionLoader.UnloadAndExitToMenu();
}
}
public void Dispose()
{
}
public void Init(object gameInstance)
{
MethodUtil.ReplaceMethod(TimeoutFix._patch, TimeoutFix._target);
MethodUtil.ReplaceMethod(TimeoutFix._receivePatch, TimeoutFix._receiveTarget);
}
public void Update()
{
}
private static void DownloadWorld(MyGuiScreenProgress progress, MyMultiplayerBase multiplayer)
{
TimeoutFix._worldReceived = false;
bool flag = progress.Text != null;
if (flag)
var progressScreenOnTop = MyScreenManager.IsScreenOnTop(progress);
if (serverId != multiplayer.GetOwner())
{
progress.Text.Clear();
progress.Text.Append(MyTexts.Get(MyCommonTexts.MultiplayerStateConnectingToServer));
}
MyLog.Default.WriteLine("World requested: Timeout fix v2.2");
Stopwatch worldRequestTime = Stopwatch.StartNew();
ulong serverId = multiplayer.GetOwner();
bool connected = false;
progress.Tick += delegate
{
MyP2PSessionState myP2PSessionState = default(MyP2PSessionState);
MyGameService.Peer2Peer.GetSessionState(multiplayer.ServerId, ref myP2PSessionState);
bool flag2 = !connected && myP2PSessionState.ConnectionActive;
if (flag2)
{
MyLog.Default.WriteLine("World requested - connection alive");
connected = true;
bool flag3 = progress.Text != null;
if (flag3)
{
progress.Text.Clear();
progress.Text.AppendLine("Using Rexxar's fixed join code v2.2! :D");
progress.Text.Append(MyTexts.Get(MyCommonTexts.MultiplayerStateWaitingForServer));
}
}
bool flag4 = connected && !myP2PSessionState.ConnectionActive;
if (flag4)
{
MyLog.Default.WriteLine("World request - connection dropped");
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplaterJoin_ServerIsNotResponding, default(MyStringId), MyMessageBoxStyleEnum.Error);
MySessionLoader.UnloadAndExitToMenu();
}
bool flag5 = MyScreenManager.IsScreenOnTop((MyGuiScreenBase)progress);
bool flag6 = serverId != multiplayer.GetOwner();
if (flag6)
{
MyLog.Default.WriteLine(string.Format("World requested - failed, server changed: Expected {0} got {1}", serverId, multiplayer.GetOwner()));
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplayerErrorServerHasLeft, default(MyStringId), MyMessageBoxStyleEnum.Error);
multiplayer.Dispose();
}
bool flag7 = MyScreenManager.IsScreenOfTypeOpen(typeof(MyGuiScreenDownloadMods));
bool flag8 = !flag7 && flag5 && !worldRequestTime.IsRunning;
if (flag8)
{
worldRequestTime.Start();
}
else
{
bool flag9 = flag7 || (!flag5 && worldRequestTime.IsRunning);
if (flag9)
{
worldRequestTime.Stop();
}
}
bool flag10 = flag7 && progress.Visible;
if (flag10)
{
progress.HideScreen();
}
else
{
bool flag11 = !flag7 && !progress.Visible;
if (flag11)
{
progress.UnhideScreen();
}
}
bool flag12 = !TimeoutFix._worldReceived && worldRequestTime.IsRunning && (float)(worldRequestTime.ElapsedTicks / Stopwatch.Frequency) > 120f;
if (flag12)
{
MyLog.Default.WriteLine("World requested - failed, timeout reached");
MyLog.Default.WriteLine(string.Format("Elapsed : {0:N2}", worldRequestTime.ElapsedTicks / Stopwatch.Frequency));
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplaterJoin_ServerIsNotResponding, default(MyStringId), MyMessageBoxStyleEnum.Error);
MySessionLoader.UnloadAndExitToMenu();
}
};
multiplayer.DownloadWorld(MyFinalBuildConstants.APP_VERSION.Version);
}
private static void CheckDx11AndJoin(MyObjectBuilder_World world, MyMultiplayerBase multiplayer)
{
bool scenario = multiplayer.Scenario;
if (scenario)
{
MySessionLoader.LoadMultiplayerScenarioWorld(world, multiplayer);
}
else
{
MySessionLoader.LoadMultiplayerSession(world, multiplayer);
}
}
private static void WorldReceived(MyObjectBuilder_World world, MyMultiplayerBase multiplayer)
{
bool flag = world == null;
if (flag)
{
MyLog.Default.WriteLine("World requested - failed, version mismatch");
TimeoutFix.m_progress.Cancel();
TimeoutFix.m_progress = null;
MyGuiSandbox.Show(MyCommonTexts.MultiplayerErrorAppVersionMismatch, default(MyStringId), MyMessageBoxStyleEnum.Error);
MyLog.Default.WriteLine(string.Format("World requested - failed, server changed: Expected {0} got {1}", serverId, multiplayer.GetOwner()));
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplayerErrorServerHasLeft, default, MyMessageBoxStyleEnum.Error);
multiplayer.Dispose();
}
var downloadScreenOpen = MyScreenManager.IsScreenOfTypeOpen(typeof(MyGuiScreenDownloadMods));
if (!downloadScreenOpen && progressScreenOnTop && !worldRequestTime.IsRunning)
{
worldRequestTime.Start();
}
else
{
TimeoutFix._worldReceived = true;
MyLog.Default.WriteLine("World requested - world data received");
bool flag2;
if (world == null)
{
flag2 = null != null;
}
else
{
MyObjectBuilder_Checkpoint checkpoint = world.Checkpoint;
flag2 = ((checkpoint != null) ? checkpoint.Settings : null) != null;
}
bool flag3 = flag2 && !MySandboxGame.Config.ExperimentalMode;
if (flag3)
{
MySessionLoader.UnloadAndExitToMenu();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendFormat(MyCommonTexts.DialogTextJoinWorldFailed, MyTexts.GetString(MyCommonTexts.MultiplayerErrorExperimental));
MyGuiSandbox.AddScreen((MyGuiScreenBase)MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, stringBuilder, MyTexts.Get(MyCommonTexts.MessageBoxCaptionError), null, null, null, null, null, 0, MyGuiScreenMessageBox.ResultEnum.YES, true, null, true, null, true, false, null));
}
else
{
TimeoutFix.m_progress = null;
TimeoutFix.CheckDx11AndJoin(world, multiplayer);
}
if (downloadScreenOpen || !progressScreenOnTop && worldRequestTime.IsRunning)
worldRequestTime.Stop();
}
if (downloadScreenOpen && progress.Visible)
{
progress.HideScreen();
}
else
{
if (!downloadScreenOpen && !progress.Visible)
progress.UnhideScreen();
}
if (!_worldReceived && worldRequestTime.IsRunning && worldRequestTime.ElapsedTicks / Stopwatch.Frequency > 120f)
{
MyLog.Default.WriteLine("World requested - failed, timeout reached");
MyLog.Default.WriteLine(string.Format("Elapsed : {0:N2}", worldRequestTime.ElapsedTicks / Stopwatch.Frequency));
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplaterJoin_ServerIsNotResponding, default, MyMessageBoxStyleEnum.Error);
MySessionLoader.UnloadAndExitToMenu();
}
};
multiplayer.DownloadWorld(MyFinalBuildConstants.APP_VERSION.Version);
return false;
}
private static void CheckDx11AndJoin(MyObjectBuilder_World world, MyMultiplayerBase multiplayer)
{
if (multiplayer.Scenario)
MySessionLoader.LoadMultiplayerScenarioWorld(world, multiplayer);
else
MySessionLoader.LoadMultiplayerSession(world, multiplayer);
}
private static bool WorldReceived(MyObjectBuilder_World world, MyMultiplayerBase multiplayer)
{
if (world == null)
{
MyLog.Default.WriteLine("World requested - failed, version mismatch");
Progress.Cancel();
Progress = null;
MyGuiSandbox.Show(MyCommonTexts.MultiplayerErrorAppVersionMismatch, default, MyMessageBoxStyleEnum.Error);
multiplayer.Dispose();
}
else
{
_worldReceived = true;
MyLog.Default.WriteLine("World requested - world data received");
if (world.Checkpoint?.Settings != null && !MySandboxGame.Config.ExperimentalMode)
{
MySessionLoader.UnloadAndExitToMenu();
var stringBuilder = new StringBuilder();
stringBuilder.AppendFormat(MyCommonTexts.DialogTextJoinWorldFailed, MyTexts.GetString(MyCommonTexts.MultiplayerErrorExperimental));
MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, stringBuilder, MyTexts.Get(MyCommonTexts.MessageBoxCaptionError), null, null, null, null, null, 0, MyGuiScreenMessageBox.ResultEnum.YES, true, null, true, null, true, false, null));
}
else
{
Progress = null;
CheckDx11AndJoin(world, multiplayer);
}
}
private static MethodInfo _target = typeof(MyJoinGameHelper).GetMethod("DownloadWorld", BindingFlags.Static | BindingFlags.NonPublic);
private static MethodInfo _patch = typeof(TimeoutFix).GetMethod("DownloadWorld", BindingFlags.Static | BindingFlags.NonPublic);
private static MethodInfo _receiveTarget = typeof(MyJoinGameHelper).GetMethod("WorldReceived", BindingFlags.Static | BindingFlags.Public);
private static MethodInfo _receivePatch = typeof(TimeoutFix).GetMethod("WorldReceived", BindingFlags.Static | BindingFlags.NonPublic);
private static bool _worldReceived;
private static readonly FieldInfo _progressField = typeof(MyJoinGameHelper).GetField("m_progress", BindingFlags.Static | BindingFlags.NonPublic);
private const string VERSION = "v2.2";
return false;
}
}