Decompiled source of Ragnavik Server v1.0.13

plugins/RagnavikEpicMMOReloadGuard/RagnavikEpicMMOReloadGuard.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RagnavikEpicMMOReloadGuard")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1fd16b842eeaeee5d9fa2d497dd542180d98e7ce")]
[assembly: AssemblyProduct("RagnavikEpicMMOReloadGuard")]
[assembly: AssemblyTitle("RagnavikEpicMMOReloadGuard")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RagnavikEpicMMOReloadGuard
{
	internal static class JsonFolderFingerprint
	{
		internal static string Compute(string folder)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if (Directory.Exists(folder))
			{
				foreach (string item in Directory.GetFiles(folder, "*.json", SearchOption.AllDirectories).OrderBy<string, string>((string path) => path, StringComparer.Ordinal))
				{
					string s = item.Substring(folder.TrimEnd(Path.DirectorySeparatorChar).Length + 1);
					byte[] bytes = Encoding.UTF8.GetBytes(s);
					memoryStream.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
					memoryStream.Write(bytes, 0, bytes.Length);
					using FileStream fileStream = File.Open(item, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
					memoryStream.Write(BitConverter.GetBytes(fileStream.Length), 0, 8);
					fileStream.CopyTo(memoryStream);
				}
			}
			using SHA256 sHA = SHA256.Create();
			memoryStream.Position = 0L;
			return Convert.ToBase64String(sHA.ComputeHash(memoryStream));
		}
	}
	[BepInPlugin("LostKode.RagnavikEpicMMOReloadGuard", "Ragnavik EpicMMO Reload Guard", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class ReloadGuardPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "LostKode.RagnavikEpicMMOReloadGuard";

		private const float QuietSeconds = 1.5f;

		private static ReloadGuardPlugin? _instance;

		private static bool _allowOriginal;

		private static object? _epicMmoInstance;

		private static bool _pending;

		private static int _pendingEvents;

		private static float _lastEventAt;

		private Harmony? _harmony;

		private MethodInfo? _readJsonValues;

		private string? _folder;

		private string? _lastFingerprint;

		private void Awake()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				Type type = AccessTools.TypeByName("EpicMMOSystem.EpicMMOSystem");
				_readJsonValues = ((type == null) ? null : AccessTools.Method(type, "ReadJsonValues", (Type[])null, (Type[])null));
				if (_readJsonValues == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"EpicMMO 1.9.67 JSON watcher method was not found; guard is inactive.");
					return;
				}
				_folder = Path.Combine(Paths.ConfigPath, "EpicMMOSystem");
				_lastFingerprint = JsonFolderFingerprint.Compute(_folder);
				_instance = this;
				_harmony = new Harmony("LostKode.RagnavikEpicMMOReloadGuard");
				_harmony.Patch((MethodBase)_readJsonValues, new HarmonyMethod(typeof(ReloadGuardPlugin), "BeforeJsonReload", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"EpicMMO JSON reload guard is active on the dedicated server.");
			}
		}

		private static bool BeforeJsonReload(object __instance, FileSystemEventArgs __1)
		{
			if (_allowOriginal || (Object)(object)_instance == (Object)null)
			{
				return true;
			}
			if (__1 == null)
			{
				return false;
			}
			_epicMmoInstance = __instance;
			_lastEventAt = Time.realtimeSinceStartup;
			_pendingEvents++;
			_pending = true;
			return false;
		}

		private void Update()
		{
			if (!_pending || _folder == null || _readJsonValues == null || Time.realtimeSinceStartup - _lastEventAt < 1.5f)
			{
				return;
			}
			_pending = false;
			int pendingEvents = _pendingEvents;
			_pendingEvents = 0;
			string text;
			try
			{
				text = JsonFolderFingerprint.Compute(_folder);
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Cannot fingerprint EpicMMO JSON files; retrying: {arg}");
				_pending = true;
				_lastEventAt = Time.realtimeSinceStartup;
				return;
			}
			if (string.Equals(text, _lastFingerprint, StringComparison.Ordinal))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Ignored {pendingEvents} EpicMMO JSON metadata-only event(s).");
			}
			else
			{
				if (_epicMmoInstance == null)
				{
					return;
				}
				try
				{
					_allowOriginal = true;
					_readJsonValues.Invoke(_epicMmoInstance, new object[2]);
					_lastFingerprint = text;
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Coalesced {pendingEvents} EpicMMO JSON event(s) into one content reload.");
				}
				catch (Exception arg2)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"EpicMMO JSON reload failed; retrying: {arg2}");
					_pending = true;
					_lastEventAt = Time.realtimeSinceStartup;
				}
				finally
				{
					_allowOriginal = false;
				}
			}
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if (_instance == this)
			{
				_instance = null;
			}
			_pending = false;
			_pendingEvents = 0;
		}
	}
}