Decompiled source of Ephemeral Coins Multiplayer Patch v1.0.1

TheEphemeralCoinsMultiplayerPatch.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using On.RoR2;
using ProperSave;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.Utils;
using RoR2;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;

[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("TheEphemeralCoinsMultiplayerPatch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+34c48a2bac01ab92d5a7d4b2a16bb0164d553963")]
[assembly: AssemblyProduct("TheEphemeralCoinsMultiplayerPatch")]
[assembly: AssemblyTitle("TheEphemeralCoinsMultiplayerPatch")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 EphemeralCoinsMultiplayerPatch
{
	internal static class CoinStoragePatch
	{
		private static Type _ephemeralType;

		private static Type _hooksType;

		private static object _ephemeralInstance;

		private static PropertyInfo _artifactEnabledProp;

		private static FieldInfo _coinCountsField;

		private static MethodInfo _delayedStartingCoins;

		public static void Apply(Harmony harmony)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			_ephemeralType = AccessTools.TypeByName("EphemeralCoins.EphemeralCoins") ?? throw new InvalidOperationException("Could not find EphemeralCoins.EphemeralCoins");
			_hooksType = AccessTools.TypeByName("EphemeralCoins.Hooks") ?? throw new InvalidOperationException("Could not find EphemeralCoins.Hooks");
			_ephemeralInstance = AccessTools.Field(_ephemeralType, "instance")?.GetValue(null) ?? throw new InvalidOperationException("EphemeralCoins.instance was null");
			_artifactEnabledProp = AccessTools.Property(_ephemeralType, "artifactEnabled");
			_coinCountsField = AccessTools.Field(_ephemeralType, "coinCounts");
			_delayedStartingCoins = AccessTools.Method(_ephemeralType, "DelayedStartingLunarCoins", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)AccessTools.Method(_ephemeralType, "SetupCoinStorage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(CoinStoragePatch), "SetupCoinStoragePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(_ephemeralType, "giveCoinsToUser", (Type[])null, (Type[])null), new HarmonyMethod(typeof(CoinStoragePatch), "GiveCoinsPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(_ephemeralType, "takeCoinsFromUser", (Type[])null, (Type[])null), new HarmonyMethod(typeof(CoinStoragePatch), "TakeCoinsPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(_ephemeralType, "getCoinsFromUser", (Type[])null, (Type[])null), new HarmonyMethod(typeof(CoinStoragePatch), "GetCoinsPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(_hooksType, "Run_Start", (Type[])null, (Type[])null), new HarmonyMethod(typeof(CoinStoragePatch), "HooksRunStartPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static bool ArtifactEnabled()
		{
			if (_artifactEnabledProp != null)
			{
				return (bool)_artifactEnabledProp.GetValue(_ephemeralInstance);
			}
			return false;
		}

		public static void ApplySyncedPlayer(NetworkUserId userId, string name, uint count)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			PatchedCoinEntry patchedCoinEntry = FindEntry(userId, name) ?? EnsureEntry(userId, name, syncToClients: false);
			patchedCoinEntry.userId = userId;
			if (!string.IsNullOrEmpty(name))
			{
				patchedCoinEntry.name = name;
			}
			patchedCoinEntry.ephemeralCoinCount = count;
			TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)("Sync coin entry: " + (patchedCoinEntry.name ?? "?") + " -> " + count));
		}

		public static void SyncAllEntriesToClients()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			foreach (PatchedCoinEntry entry in PatchCoinState.Entries)
			{
				if (entry != null)
				{
					NetMessageExtensions.Send((INetMessage)(object)new SyncPatchedCoinStorage(entry.userId, entry.name, entry.ephemeralCoinCount), (NetworkDestination)1);
				}
			}
		}

		private static PatchedCoinEntry FindEntry(NetworkUserId userId, string name)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			foreach (PatchedCoinEntry entry in PatchCoinState.Entries)
			{
				if (entry != null && ((NetworkUserId)(ref entry.userId)).Equals(userId))
				{
					return entry;
				}
			}
			if (!string.IsNullOrEmpty(name))
			{
				foreach (PatchedCoinEntry entry2 in PatchCoinState.Entries)
				{
					if (entry2 != null && string.Equals(entry2.name, name, StringComparison.Ordinal))
					{
						return entry2;
					}
				}
			}
			return null;
		}

		private static PatchedCoinEntry FindEntry(NetworkUser user)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)user == (Object)null)
			{
				return null;
			}
			return FindEntry(user.id, user.userName);
		}

		private static PatchedCoinEntry EnsureEntry(NetworkUser user, bool syncToClients)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)user == (Object)null)
			{
				return null;
			}
			PatchedCoinEntry patchedCoinEntry = FindEntry(user);
			if (patchedCoinEntry != null)
			{
				patchedCoinEntry.userId = user.id;
				if (string.IsNullOrEmpty(patchedCoinEntry.name))
				{
					patchedCoinEntry.name = user.userName;
				}
				return patchedCoinEntry;
			}
			return EnsureEntry(user.id, user.userName, syncToClients);
		}

		private static PatchedCoinEntry EnsureEntry(NetworkUserId userId, string name, bool syncToClients)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			PatchedCoinEntry patchedCoinEntry = FindEntry(userId, name);
			if (patchedCoinEntry != null)
			{
				patchedCoinEntry.userId = userId;
				if (string.IsNullOrEmpty(patchedCoinEntry.name))
				{
					patchedCoinEntry.name = name;
				}
				return patchedCoinEntry;
			}
			PatchedCoinEntry patchedCoinEntry2 = new PatchedCoinEntry
			{
				userId = userId,
				name = name,
				ephemeralCoinCount = 0u
			};
			PatchCoinState.Entries.Add(patchedCoinEntry2);
			if (syncToClients && NetworkServer.active)
			{
				NetMessageExtensions.Send((INetMessage)(object)new SyncPatchedCoinStorage(patchedCoinEntry2.userId, patchedCoinEntry2.name, patchedCoinEntry2.ephemeralCoinCount), (NetworkDestination)1);
			}
			return patchedCoinEntry2;
		}

		private static void SetupPatchedStorage(bool newRun)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (newRun)
			{
				PatchCoinState.Entries.Clear();
				ProperSavePatch.ClearRestoredFlag();
			}
			if (newRun && _coinCountsField != null && _coinCountsField.GetValue(_ephemeralInstance) is IList list)
			{
				list.Clear();
			}
			foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
			{
				if ((Object)(object)readOnlyInstances == (Object)null)
				{
					continue;
				}
				PatchedCoinEntry patchedCoinEntry = FindEntry(readOnlyInstances);
				if (patchedCoinEntry != null)
				{
					patchedCoinEntry.userId = readOnlyInstances.id;
					if (string.IsNullOrEmpty(patchedCoinEntry.name))
					{
						patchedCoinEntry.name = readOnlyInstances.userName;
					}
				}
				else
				{
					EnsureEntry(readOnlyInstances, syncToClients: true);
					TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)(readOnlyInstances.userName + " added to patched CoinStorage."));
				}
			}
			SyncAllEntriesToClients();
		}

		private static bool SetupCoinStoragePrefix(bool NewRun)
		{
			SetupPatchedStorage(NewRun);
			TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)"Patched SetupCoinStorage finished.");
			return false;
		}

		private static bool GiveCoinsPrefix(NetworkUser user, uint count)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (ProperSavePatch.IsLoading())
			{
				return false;
			}
			PatchedCoinEntry patchedCoinEntry = EnsureEntry(user, syncToClients: false);
			if (patchedCoinEntry == null)
			{
				return false;
			}
			patchedCoinEntry.ephemeralCoinCount += count;
			if (NetworkServer.active)
			{
				NetMessageExtensions.Send((INetMessage)(object)new SyncPatchedCoinStorage(patchedCoinEntry.userId, patchedCoinEntry.name, patchedCoinEntry.ephemeralCoinCount), (NetworkDestination)1);
			}
			TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)("giveCoinsToUser: " + user.userName + " " + count + " -> " + patchedCoinEntry.ephemeralCoinCount));
			return false;
		}

		private static bool TakeCoinsPrefix(NetworkUser user, uint count)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (ProperSavePatch.IsLoading())
			{
				return false;
			}
			PatchedCoinEntry patchedCoinEntry = EnsureEntry(user, syncToClients: false);
			if (patchedCoinEntry == null)
			{
				return false;
			}
			if (count > patchedCoinEntry.ephemeralCoinCount)
			{
				patchedCoinEntry.ephemeralCoinCount = 0u;
			}
			else
			{
				patchedCoinEntry.ephemeralCoinCount -= count;
			}
			if (NetworkServer.active)
			{
				NetMessageExtensions.Send((INetMessage)(object)new SyncPatchedCoinStorage(patchedCoinEntry.userId, patchedCoinEntry.name, patchedCoinEntry.ephemeralCoinCount), (NetworkDestination)1);
			}
			TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)("takeCoinsFromUser: " + user.userName + " " + count + " -> " + patchedCoinEntry.ephemeralCoinCount));
			return false;
		}

		private static bool GetCoinsPrefix(NetworkUser user, ref uint __result)
		{
			__result = 0u;
			if ((Object)(object)Run.instance == (Object)null || (Object)(object)user == (Object)null)
			{
				return false;
			}
			PatchedCoinEntry patchedCoinEntry = FindEntry(user);
			if (patchedCoinEntry != null)
			{
				__result = patchedCoinEntry.ephemeralCoinCount;
			}
			return false;
		}

		private static bool HooksRunStartPrefix(orig_Start orig, Run self)
		{
			orig.Invoke(self);
			if (ArtifactEnabled())
			{
				SpawnPrefabPatch.SafePrefabSetup(set: true);
			}
			if (NetworkServer.active && ArtifactEnabled())
			{
				bool num = !ProperSavePatch.IsLoading() && !ProperSavePatch.ShouldPreserveRestoredCoins;
				if (num)
				{
					ProperSavePatch.ClearRestoredFlag();
					PatchCoinState.Entries.Clear();
				}
				SetupPatchedStorage(num);
				if (num && _delayedStartingCoins != null)
				{
					object ephemeralInstance = _ephemeralInstance;
					MonoBehaviour val = (MonoBehaviour)((ephemeralInstance is MonoBehaviour) ? ephemeralInstance : null);
					if (val != null)
					{
						val.StartCoroutine((IEnumerator)_delayedStartingCoins.Invoke(_ephemeralInstance, null));
					}
				}
			}
			return false;
		}
	}
	internal static class CostTypePatch
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static IsAffordableDelegate <>9__5_0;

			internal bool <ApplyAffordabilityFix>b__5_0(CostTypeDef costTypeDef, IsAffordableContext context)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				NetworkUser val = Util.LookUpBodyNetworkUser(((Component)context.activator).gameObject);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return false;
				}
				if (ArtifactEnabled())
				{
					return GetCoins(val) >= context.cost;
				}
				return val.lunarCoins >= context.cost;
			}
		}

		private static object _ephemeralInstance;

		private static PropertyInfo _artifactEnabledProp;

		public static void Apply()
		{
			Type type = AccessTools.TypeByName("EphemeralCoins.EphemeralCoins");
			_ephemeralInstance = AccessTools.Field(type, "instance").GetValue(null);
			_artifactEnabledProp = AccessTools.Property(type, "artifactEnabled");
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(ApplyAffordabilityFix));
		}

		private static bool ArtifactEnabled()
		{
			if (_artifactEnabledProp != null)
			{
				return (bool)_artifactEnabledProp.GetValue(_ephemeralInstance);
			}
			return false;
		}

		private static uint GetCoins(NetworkUser user)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)user == (Object)null)
			{
				return 0u;
			}
			foreach (PatchedCoinEntry entry in PatchCoinState.Entries)
			{
				if (entry != null && ((NetworkUserId)(ref entry.userId)).Equals(user.id))
				{
					return entry.ephemeralCoinCount;
				}
			}
			string userName = user.userName;
			if (!string.IsNullOrEmpty(userName))
			{
				foreach (PatchedCoinEntry entry2 in PatchCoinState.Entries)
				{
					if (entry2 != null && string.Equals(entry2.name, userName, StringComparison.Ordinal))
					{
						return entry2.ephemeralCoinCount;
					}
				}
			}
			return 0u;
		}

		private static void ApplyAffordabilityFix()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			try
			{
				CostTypeDef costTypeDef = CostTypeCatalog.GetCostTypeDef((CostTypeIndex)3);
				if (costTypeDef == null)
				{
					TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)"LunarCoin CostTypeDef missing; shop affordability patch skipped.");
					return;
				}
				object obj = <>c.<>9__5_0;
				if (obj == null)
				{
					IsAffordableDelegate val = delegate(CostTypeDef val3, IsAffordableContext context)
					{
						//IL_0000: Unknown result type (might be due to invalid IL or missing references)
						//IL_003d: Unknown result type (might be due to invalid IL or missing references)
						//IL_0029: Unknown result type (might be due to invalid IL or missing references)
						NetworkUser val2 = Util.LookUpBodyNetworkUser(((Component)context.activator).gameObject);
						if (!Object.op_Implicit((Object)(object)val2))
						{
							return false;
						}
						return ArtifactEnabled() ? (GetCoins(val2) >= context.cost) : (val2.lunarCoins >= context.cost);
					};
					<>c.<>9__5_0 = val;
					obj = (object)val;
				}
				costTypeDef.isAffordable = (IsAffordableDelegate)obj;
				TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)"Patched LunarCoin isAffordable delegate.");
			}
			catch (Exception ex)
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogError((object)("Failed to patch LunarCoin affordability (load will continue): " + ex));
			}
		}
	}
	internal static class HooksInitPatch
	{
		public static void Apply(Harmony harmony)
		{
		}
	}
	internal static class NetworkUserIdAccess
	{
		private static readonly FieldInfo ValueField = AccessTools.Field(typeof(NetworkUserId), "value");

		private static readonly FieldInfo StrValueField = AccessTools.Field(typeof(NetworkUserId), "strValue");

		private static readonly FieldInfo SubIdField = AccessTools.Field(typeof(NetworkUserId), "subId");

		private static readonly PropertyInfo ValueProp = AccessTools.Property(typeof(NetworkUserId), "value");

		private static readonly PropertyInfo StrValueProp = AccessTools.Property(typeof(NetworkUserId), "strValue");

		private static readonly PropertyInfo SubIdProp = AccessTools.Property(typeof(NetworkUserId), "subId");

		public static ulong GetValue(NetworkUserId id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			object obj = id;
			if (ValueField != null)
			{
				return (ulong)ValueField.GetValue(obj);
			}
			if (ValueProp != null)
			{
				return (ulong)ValueProp.GetValue(obj);
			}
			return 0uL;
		}

		public static string GetStrValue(NetworkUserId id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			object obj = id;
			if (StrValueField != null)
			{
				return StrValueField.GetValue(obj) as string;
			}
			if (StrValueProp != null)
			{
				return StrValueProp.GetValue(obj) as string;
			}
			return null;
		}

		public static byte GetSubId(NetworkUserId id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			object obj = id;
			if (SubIdField != null)
			{
				return (byte)SubIdField.GetValue(obj);
			}
			if (SubIdProp != null)
			{
				return (byte)SubIdProp.GetValue(obj);
			}
			return 0;
		}
	}
	internal static class ProperSavePatch
	{
		[Serializable]
		public class EphemeralCoinSaveEntry
		{
			public ulong idValue;

			public string idStr;

			public byte idSub;

			public string name;

			public uint count;
		}

		public const string SaveDataKey = "EphemeralCoins.coinCounts";

		private static List<EphemeralCoinSaveEntry> _lastRestored;

		private static int _preserveLoadId;

		private static int _loadId;

		private static int _delayedReapplyLoadId;

		private static bool _hooksInstalled;

		public static bool RestoredFromSave { get; private set; }

		internal static bool ShouldPreserveRestoredCoins
		{
			get
			{
				if (_preserveLoadId != 0 && _preserveLoadId == _loadId)
				{
					return _lastRestored != null;
				}
				return false;
			}
		}

		public static void Apply()
		{
			if (!Chainloader.PluginInfos.ContainsKey("com.KingEnderBrine.ProperSave"))
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)"ProperSave not installed; coin save/load skipped.");
			}
			else
			{
				Setup();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void Setup()
		{
			if (!_hooksInstalled)
			{
				_hooksInstalled = true;
				SaveFile.OnGatherSaveData += OnGatherSaveData;
				Loading.OnLoadingEnded += OnLoadingEnded;
				Stage.onStageStartGlobal += OnStageStartGlobal;
				Run.onRunDestroyGlobal += OnRunDestroyGlobal;
				TheEphemeralCoinsMultiplayerPatch.Log.LogInfo((object)"ProperSave compatibility enabled (ephemeral coin save/load).");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static bool IsLoading()
		{
			try
			{
				return Loading.IsLoading;
			}
			catch
			{
				return false;
			}
		}

		private static void OnRunDestroyGlobal(Run run)
		{
			ClearRestoredFlag();
			PatchCoinState.Entries.Clear();
			TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)"ProperSave: cleared coin state on run destroy.");
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void OnGatherSaveData(Dictionary<string, object> dict)
		{
			if (ShouldPreserveRestoredCoins)
			{
				ApplySavedEntries(_lastRestored, fromSnapshotReapply: true);
			}
			EndPreserveWindow();
			List<EphemeralCoinSaveEntry> list = new List<EphemeralCoinSaveEntry>();
			foreach (PatchedCoinEntry entry in PatchCoinState.Entries)
			{
				if (entry != null)
				{
					list.Add(CloneEntry(entry));
				}
			}
			dict["EphemeralCoins.coinCounts"] = list;
			TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)("ProperSave: gathered " + list.Count + " ephemeral coin entries."));
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void OnLoadingEnded(SaveFile save)
		{
			if (save == null)
			{
				return;
			}
			try
			{
				List<EphemeralCoinSaveEntry> list = save.TryGetModdedData<List<EphemeralCoinSaveEntry>>("EphemeralCoins.coinCounts");
				if (list == null)
				{
					TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)"ProperSave: no ephemeral coin data in save (starting at 0).");
					return;
				}
				_loadId++;
				_preserveLoadId = _loadId;
				_delayedReapplyLoadId = _loadId;
				_lastRestored = CloneList(list);
				ApplySavedEntries(_lastRestored);
				StartPostLoadReapplyCoroutine(_loadId);
			}
			catch (Exception ex)
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)("ProperSave: failed to restore ephemeral coins: " + ex));
			}
		}

		private static void OnStageStartGlobal(Stage stage)
		{
			if (ShouldPreserveRestoredCoins)
			{
				ApplySavedEntries(_lastRestored, fromSnapshotReapply: true);
			}
		}

		private static void StartPostLoadReapplyCoroutine(int loadId)
		{
			MonoBehaviour instance = (MonoBehaviour)(object)TheEphemeralCoinsMultiplayerPatch.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				instance.StartCoroutine(PostLoadReapplyCoroutine(loadId));
			}
		}

		private static IEnumerator PostLoadReapplyCoroutine(int loadId)
		{
			yield return (object)new WaitForSeconds(1f);
			if (loadId == _delayedReapplyLoadId && _lastRestored != null)
			{
				ApplySavedEntries(_lastRestored, fromSnapshotReapply: true);
				TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)"ProperSave: re-applied ephemeral coin snapshot after load settle.");
				if (_preserveLoadId == 0)
				{
					_lastRestored = null;
				}
			}
		}

		private static void EndPreserveWindow()
		{
			_preserveLoadId = 0;
		}

		internal static void ApplySavedEntries(List<EphemeralCoinSaveEntry> saved, bool fromSnapshotReapply = false)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			PatchCoinState.Entries.Clear();
			if (saved == null)
			{
				RestoredFromSave = false;
				return;
			}
			foreach (EphemeralCoinSaveEntry item2 in saved)
			{
				if (item2 != null)
				{
					NetworkUserId userId = ((!string.IsNullOrEmpty(item2.idStr)) ? NetworkUserId.FromIp(item2.idStr, item2.idSub) : NetworkUserId.FromId(item2.idValue, item2.idSub));
					PatchedCoinEntry item = new PatchedCoinEntry
					{
						userId = userId,
						name = item2.name,
						ephemeralCoinCount = item2.count
					};
					PatchCoinState.Entries.Add(item);
				}
			}
			RestoredFromSave = true;
			if (NetworkServer.active)
			{
				foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
				{
					if ((Object)(object)readOnlyInstances == (Object)null)
					{
						continue;
					}
					foreach (PatchedCoinEntry entry in PatchCoinState.Entries)
					{
						if (entry != null && (((NetworkUserId)(ref entry.userId)).Equals(readOnlyInstances.id) || (!string.IsNullOrEmpty(entry.name) && string.Equals(entry.name, readOnlyInstances.userName, StringComparison.Ordinal))))
						{
							entry.userId = readOnlyInstances.id;
							entry.name = readOnlyInstances.userName;
							break;
						}
					}
				}
				CoinStoragePatch.SyncAllEntriesToClients();
			}
			if (!fromSnapshotReapply)
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogInfo((object)("ProperSave: restored " + PatchCoinState.Entries.Count + " ephemeral coin entr" + ((PatchCoinState.Entries.Count == 1) ? "y" : "ies") + "."));
			}
		}

		internal static void ClearRestoredFlag()
		{
			_loadId++;
			_preserveLoadId = 0;
			_delayedReapplyLoadId = 0;
			_lastRestored = null;
			RestoredFromSave = false;
		}

		private static EphemeralCoinSaveEntry CloneEntry(PatchedCoinEntry player)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			return new EphemeralCoinSaveEntry
			{
				idValue = NetworkUserIdAccess.GetValue(player.userId),
				idStr = (NetworkUserIdAccess.GetStrValue(player.userId) ?? ""),
				idSub = NetworkUserIdAccess.GetSubId(player.userId),
				name = player.name,
				count = player.ephemeralCoinCount
			};
		}

		private static List<EphemeralCoinSaveEntry> CloneList(List<EphemeralCoinSaveEntry> source)
		{
			List<EphemeralCoinSaveEntry> list = new List<EphemeralCoinSaveEntry>(source.Count);
			foreach (EphemeralCoinSaveEntry item in source)
			{
				if (item != null)
				{
					list.Add(new EphemeralCoinSaveEntry
					{
						idValue = item.idValue,
						idStr = item.idStr,
						idSub = item.idSub,
						name = item.name,
						count = item.count
					});
				}
			}
			return list;
		}
	}
	internal static class SpawnPrefabPatch
	{
		private static readonly string[] LunarInteractables = new string[5] { "RoR2/Base/Interactables/LunarRecycler/LunarRecycler.prefab", "RoR2/Base/Interactables/LunarChest/LunarChest.prefab", "RoR2/Base/Interactables/LunarShopTerminal/LunarShopTerminal.prefab", "RoR2/Base/Scenes/bazaar/SeerStation.prefab", "RoR2/Base/Scenes/moon/Natural/Prefabs/FrogInteractable.prefab" };

		private static readonly string[] PickupLunarCoinKeys = new string[2] { "RoR2/Base/LunarCoin/PickupLunarCoin.prefab", "RoR2/Base/MiscPickups/LunarCoin/PickupLunarCoin.prefab" };

		private static readonly string[] LunarCoinMeshKeys = new string[2] { "RoR2/Base/Common/VFX/mdlLunarCoin.fbx", "RoR2/Base/Common/VFX/Coins/mdlLunarCoin.fbx" };

		private static readonly string[] LunarCoinWithHoleMeshKeys = new string[2] { "RoR2/Base/Common/VFX/mdlLunarCoinWithHole.fbx", "RoR2/Base/Common/VFX/Coins/mdlLunarCoinWithHole.fbx" };

		private static readonly string[] LunarCoinPlaceholderMatKeys = new string[2] { "RoR2/Base/Common/VFX/matLunarCoinPlaceholder.mat", "RoR2/Base/Common/VFX/Coins/matLunarCoinPlaceholder.mat" };

		private static Type _artifactManagerType;

		private static Type _assetsType;

		private static Type _bepConfigType;

		private static FieldInfo _frogMaxPetsField;

		public static void Apply(Harmony harmony)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			_artifactManagerType = AccessTools.TypeByName("EphemeralCoins.NewMoonArtifactManager") ?? throw new InvalidOperationException("Could not find NewMoonArtifactManager");
			_assetsType = AccessTools.TypeByName("EphemeralCoins.Assets");
			_bepConfigType = AccessTools.TypeByName("EphemeralCoins.BepConfig");
			_frogMaxPetsField = AccessTools.Field(typeof(FrogController), "maxPets");
			MethodInfo methodInfo = AccessTools.Method(_artifactManagerType, "PrefabSetup", new Type[1] { typeof(bool) }, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(_artifactManagerType, "Run_Start", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(SpawnPrefabPatch), "ArtifactRunStartPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(SpawnPrefabPatch), "PrefabSetupPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static bool ArtifactRunStartPrefix(orig_Start orig, Run self)
		{
			orig.Invoke(self);
			SafePrefabSetup(set: true);
			return false;
		}

		private static bool PrefabSetupPrefix(bool set)
		{
			SafePrefabSetup(set);
			return false;
		}

		internal static void SafePrefabSetup(bool set)
		{
			try
			{
				ApplyCoinVisuals(set);
			}
			catch (Exception ex)
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogError((object)("Patched PrefabSetup coin visuals failed (run init will continue): " + ex));
			}
			try
			{
				ApplyInteractableCosts();
			}
			catch (Exception ex2)
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogError((object)("Patched PrefabSetup interactable costs failed (run init will continue): " + ex2));
			}
		}

		private static void ApplyCoinVisuals(bool set)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			TheEphemeralCoinsMultiplayerPatch.Log.LogInfo((object)("Patched PrefabSetup coin visuals " + set));
			PickupDef lunarCoinPickupDef = GetLunarCoinPickupDef();
			if (lunarCoinPickupDef == null)
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)"Patched PrefabSetup: LunarCoin.Coin0 pickup def not ready yet; will retry on run start.");
			}
			else
			{
				lunarCoinPickupDef.nameToken = (set ? "Ephemeral Coin" : "PICKUP_LUNAR_COIN");
				lunarCoinPickupDef.interactContextToken = (set ? "Pick up Ephemeral Coin" : "LUNAR_COIN_PICKUP_CONTEXT");
				lunarCoinPickupDef.baseColor = Color32.op_Implicit(set ? new Color32((byte)96, (byte)254, byte.MaxValue, byte.MaxValue) : new Color32((byte)48, (byte)127, byte.MaxValue, byte.MaxValue));
				lunarCoinPickupDef.darkColor = Color32.op_Implicit(set ? new Color32((byte)152, (byte)168, byte.MaxValue, byte.MaxValue) : new Color32((byte)76, (byte)84, (byte)144, byte.MaxValue));
			}
			Mesh val = LoadCoinMesh(set ? LunarCoinMeshKeys : LunarCoinWithHoleMeshKeys);
			Material val2 = (set ? LoadBundleMaterial("matEphemeralCoin") : LoadFirstAddressable<Material>(LunarCoinPlaceholderMatKeys));
			if (!Object.op_Implicit((Object)(object)val))
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)"Patched PrefabSetup: failed to load replacement lunar coin mesh.");
			}
			if (!Object.op_Implicit((Object)(object)val2))
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)"Patched PrefabSetup: failed to load lunar coin material.");
			}
			int num = 0;
			foreach (GameObject item in EnumerateCoinPrefabs(lunarCoinPickupDef))
			{
				if (TryApplyMeshAndMaterial(item, val, val2))
				{
					num++;
				}
			}
			if (num == 0)
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)"Patched PrefabSetup: could not apply mesh/material to any lunar coin prefab.");
			}
			else
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogInfo((object)("Patched PrefabSetup: applied coin mesh/material to " + num + " prefab(s)."));
			}
		}

		private static PickupDef GetLunarCoinPickupDef()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			PickupIndex val = PickupCatalog.FindPickupIndex("LunarCoin.Coin0");
			PickupDef pickupDef = PickupCatalog.GetPickupDef(val);
			if (pickupDef != null)
			{
				return pickupDef;
			}
			object? obj = AccessTools.PropertyGetter(typeof(PickupIndex), "pickupDef")?.Invoke(val, null);
			return (PickupDef)((obj is PickupDef) ? obj : null);
		}

		private static IEnumerable<GameObject> EnumerateCoinPrefabs(PickupDef coinDef)
		{
			HashSet<int> seen = new HashSet<int>();
			GameObject val = ((coinDef != null) ? GetDisplayPrefab(coinDef) : null);
			if (Object.op_Implicit((Object)(object)val) && seen.Add(((Object)val).GetInstanceID()))
			{
				yield return val;
			}
			string[] pickupLunarCoinKeys = PickupLunarCoinKeys;
			for (int i = 0; i < pickupLunarCoinKeys.Length; i++)
			{
				GameObject val2 = LoadAddressable<GameObject>(pickupLunarCoinKeys[i]);
				if (Object.op_Implicit((Object)(object)val2) && seen.Add(((Object)val2).GetInstanceID()))
				{
					yield return val2;
				}
			}
		}

		private static GameObject GetDisplayPrefab(PickupDef coinDef)
		{
			if (coinDef == null)
			{
				return null;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(PickupDef), "displayPrefab");
			if (fieldInfo != null)
			{
				object? value = fieldInfo.GetValue(coinDef);
				return (GameObject)((value is GameObject) ? value : null);
			}
			object? obj = AccessTools.Property(typeof(PickupDef), "displayPrefab")?.GetValue(coinDef);
			return (GameObject)((obj is GameObject) ? obj : null);
		}

		private static bool TryApplyMeshAndMaterial(GameObject theCoin, Mesh replacementMesh, Material replacementMat)
		{
			Transform val = FindCoinMesh(theCoin);
			if (!Object.op_Implicit((Object)(object)theCoin) || !Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			bool result = false;
			MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
			MeshRenderer component2 = ((Component)val).GetComponent<MeshRenderer>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)replacementMesh))
			{
				component.sharedMesh = replacementMesh;
				component.mesh = replacementMesh;
				result = true;
			}
			if (Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)replacementMat))
			{
				((Renderer)component2).sharedMaterial = replacementMat;
				((Renderer)component2).material = replacementMat;
				result = true;
			}
			return result;
		}

		private static void ApplyInteractableCosts()
		{
			string[] lunarInteractables = LunarInteractables;
			foreach (string text in lunarInteractables)
			{
				try
				{
					ApplyInteractableCost(text);
				}
				catch (Exception ex)
				{
					TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)("Patched PrefabSetup: interactable update failed for " + text + ": " + ex.Message));
				}
			}
		}

		private static void ApplyInteractableCost(string path)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = LoadAddressable<GameObject>(path);
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = LoadAddressable<GameObject>(path.Replace("RoR2/Base/Interactables/", "RoR2/Base/").Replace("RoR2/Base/Scenes/bazaar/", "RoR2/Base/bazaar/").Replace("RoR2/Base/Scenes/moon/Natural/Prefabs/", "RoR2/Base/moon/"));
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)("Patched PrefabSetup: failed to load lunarInteractable " + path));
				return;
			}
			int num = ResolveCost(((Object)val).name);
			PurchaseInteraction component = val.GetComponent<PurchaseInteraction>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			component.cost = num;
			if (num == 0)
			{
				component.costType = (CostTypeIndex)0;
			}
			if (((Object)val).name == "FrogInteractable")
			{
				FrogController component2 = val.GetComponent<FrogController>();
				if ((Object)(object)component2 != (Object)null && _frogMaxPetsField != null)
				{
					_frogMaxPetsField.SetValue(component2, (int)GetConfigFloat("FrogPets", 1f));
				}
			}
		}

		private static Mesh LoadCoinMesh(string[] keys)
		{
			Mesh val = LoadFirstAddressable<Mesh>(keys);
			if (Object.op_Implicit((Object)(object)val))
			{
				return val;
			}
			GameObject val2 = LoadFirstAddressable<GameObject>(keys);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return null;
			}
			MeshFilter component = val2.GetComponent<MeshFilter>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sharedMesh))
			{
				return component.sharedMesh;
			}
			component = val2.GetComponentInChildren<MeshFilter>(true);
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			return component.sharedMesh;
		}

		private static int ResolveCost(string prefabName)
		{
			return prefabName switch
			{
				"LunarRecycler" => (int)GetConfigFloat("RerollCost", 0f), 
				"LunarChest" => (int)GetConfigFloat("PodCost", 0f), 
				"LunarShopTerminal" => (int)GetConfigFloat("ShopCost", 1f), 
				"SeerStation" => (int)GetConfigFloat("SeerCost", 1f), 
				"FrogInteractable" => (int)GetConfigFloat("FrogCost", 0f), 
				_ => 0, 
			};
		}

		private static float GetConfigFloat(string fieldName, float fallback)
		{
			if (_bepConfigType == null)
			{
				return fallback;
			}
			object obj = AccessTools.Field(_bepConfigType, fieldName)?.GetValue(null);
			if (obj == null)
			{
				return fallback;
			}
			PropertyInfo propertyInfo = AccessTools.Property(obj.GetType(), "Value");
			if (propertyInfo == null)
			{
				return fallback;
			}
			object value = propertyInfo.GetValue(obj);
			if (value is float)
			{
				return (float)value;
			}
			if (value is int num)
			{
				return num;
			}
			return fallback;
		}

		private static Material LoadBundleMaterial(string assetName)
		{
			if (_assetsType == null)
			{
				return null;
			}
			object? obj = AccessTools.Field(_assetsType, "mainBundle")?.GetValue(null);
			AssetBundle val = (AssetBundle)((obj is AssetBundle) ? obj : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogWarning((object)"Patched PrefabSetup: EphemeralCoins.Assets.mainBundle is null.");
				return null;
			}
			return val.LoadAsset<Material>(assetName);
		}

		private static T LoadAddressable<T>(string key) where T : Object
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return Addressables.LoadAssetAsync<T>((object)key).WaitForCompletion();
			}
			catch (Exception ex)
			{
				TheEphemeralCoinsMultiplayerPatch.Log.LogDebug((object)("Patched PrefabSetup: Addressables key failed (" + key + "): " + ex.Message));
				return default(T);
			}
		}

		private static T LoadFirstAddressable<T>(params string[] keys) where T : Object
		{
			for (int i = 0; i < keys.Length; i++)
			{
				T val = LoadAddressable<T>(keys[i]);
				if (Object.op_Implicit((Object)(object)val))
				{
					return val;
				}
			}
			return default(T);
		}

		private static Transform FindCoinMesh(GameObject coinPrefab)
		{
			if (!Object.op_Implicit((Object)(object)coinPrefab))
			{
				return null;
			}
			Transform val = coinPrefab.transform.Find("Coin5Mesh");
			if (Object.op_Implicit((Object)(object)val))
			{
				return val;
			}
			val = coinPrefab.transform.Find("LunarCoinMesh");
			if (Object.op_Implicit((Object)(object)val))
			{
				return val;
			}
			MeshFilter componentInChildren = coinPrefab.GetComponentInChildren<MeshFilter>(true);
			if (!Object.op_Implicit((Object)(object)componentInChildren))
			{
				return null;
			}
			return ((Component)componentInChildren).transform;
		}
	}
	public class SyncPatchedCoinStorage : INetMessage, ISerializableObject
	{
		public NetworkUserId userId;

		public string name;

		public uint ephemeralCoinCount;

		public SyncPatchedCoinStorage()
		{
		}

		public SyncPatchedCoinStorage(NetworkUserId userId, string name, uint ephemeralCoinCount)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			this.userId = userId;
			this.name = name;
			this.ephemeralCoinCount = ephemeralCoinCount;
		}

		public void Serialize(NetworkWriter writer)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			writer.WritePackedUInt64(NetworkUserIdAccess.GetValue(userId));
			writer.Write(NetworkUserIdAccess.GetStrValue(userId) ?? "");
			writer.Write(NetworkUserIdAccess.GetSubId(userId));
			writer.Write(name ?? "");
			writer.WritePackedUInt32(ephemeralCoinCount);
		}

		public void Deserialize(NetworkReader reader)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			ulong num = reader.ReadPackedUInt64();
			string text = reader.ReadString();
			byte b = reader.ReadByte();
			userId = ((!string.IsNullOrEmpty(text)) ? NetworkUserId.FromIp(text, b) : NetworkUserId.FromId(num, b));
			name = reader.ReadString();
			ephemeralCoinCount = reader.ReadPackedUInt32();
		}

		public void OnReceived()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				CoinStoragePatch.ApplySyncedPlayer(userId, name, ephemeralCoinCount);
			}
		}
	}
	internal class PatchedCoinEntry
	{
		public NetworkUserId userId;

		public string name;

		public uint ephemeralCoinCount;
	}
	internal static class PatchCoinState
	{
		internal static readonly List<PatchedCoinEntry> Entries = new List<PatchedCoinEntry>();
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.willcola.EphemeralCoinsMultiplayerPatch", "Ephemeral_Coins_Multiplayer_Patch", "1.0.1")]
	public class TheEphemeralCoinsMultiplayerPatch : BaseUnityPlugin
	{
		public const string PluginGuid = "com.willcola.EphemeralCoinsMultiplayerPatch";

		public const string PluginName = "Ephemeral_Coins_Multiplayer_Patch";

		public const string PluginVersion = "1.0.1";

		public const string EphemeralCoinsGuid = "com.Varna.EphemeralCoins";

		public static readonly Version TargetedEphemeralCoinsVersion = new Version(2, 3, 7);

		internal static TheEphemeralCoinsMultiplayerPatch Instance { get; private set; }

		internal static Harmony Harmony { get; private set; }

		internal static bool PatchesApplied { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony = new Harmony("com.willcola.EphemeralCoinsMultiplayerPatch");
			if (!TryGetEphemeralCoinsVersion(out var version))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Ephemeral Coins is required but was not found. Patch not applied.");
				return;
			}
			if (version > TargetedEphemeralCoinsVersion)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Ephemeral Coins {version} is newer than targeted {TargetedEphemeralCoinsVersion}. Patch idle.");
				return;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Ephemeral Coins {version} detected (<= {TargetedEphemeralCoinsVersion}). Applying multiplayer patch.");
			try
			{
				NetworkingAPI.RegisterMessageType<SyncPatchedCoinStorage>();
				CoinStoragePatch.Apply(Harmony);
				SpawnPrefabPatch.Apply(Harmony);
				HooksInitPatch.Apply(Harmony);
				CostTypePatch.Apply();
				ProperSavePatch.Apply();
				PatchesApplied = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Ephemeral Coins Multiplayer Patch applied.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to apply Ephemeral Coins Multiplayer Patch: " + ex));
			}
		}

		private static bool TryGetEphemeralCoinsVersion(out Version version)
		{
			version = null;
			if (!Chainloader.PluginInfos.TryGetValue("com.Varna.EphemeralCoins", out var value) || ((value != null) ? value.Metadata : null) == null)
			{
				return false;
			}
			version = value.Metadata.Version;
			return version != null;
		}
	}
}