Decompiled source of Random Interiors Normal Seeds v1.0.0

plugins/RandomInteriorsNormalSeeds/RandomInteriorsNormalSeeds.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
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("RandomInteriorsNormalSeeds")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RandomInteriorsNormalSeeds")]
[assembly: AssemblyTitle("RandomInteriorsNormalSeeds")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RandomInteriorsNormalSeeds
{
	[BepInPlugin("local.RandomInteriorsNormalSeeds", "Random Interiors Normal Seeds", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__Receive;
		}

		public const string Guid = "local.RandomInteriorsNormalSeeds";

		private const string RandomInteriorsGuid = "Hibyhii.RandomInteriors";

		private const string Message = "local.RandomInteriorsNormalSeeds.Selection.v1";

		private static Plugin Self;

		private Harmony harmony;

		private static MethodInfo compute;

		private static FieldInfo mapSeed;

		private static PropertyInfo startInstance;

		private CustomMessagingManager messaging;

		private bool active;

		private void Awake()
		{
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			Self = this;
			try
			{
				Assembly assembly = ((object)Chainloader.PluginInfos["Hibyhii.RandomInteriors"].Instance).GetType().Assembly;
				Type type = assembly.GetType("Hibyhii.RandomInteriors.SelectionManager", throwOnError: true);
				MethodInfo target = Require(type, "EncodeSeed", typeof(int), typeof(int));
				MethodInfo target2 = Require(type, "IsEncodedSeed", typeof(int));
				MethodInfo target3 = Require(type, "DecodeInteriorId", typeof(int));
				Type type2 = AccessTools.TypeByName("RoundManager");
				Type type3 = AccessTools.TypeByName("StartOfRound");
				if (type2 == null || type3 == null)
				{
					throw new MissingMemberException("Game round types were not found.");
				}
				compute = Require(type, "TryComputeAndStoreHostSelection", type2, typeof(int), typeof(int).MakeByRefType(), typeof(int).MakeByRefType());
				mapSeed = AccessTools.Field(type3, "randomMapSeed");
				startInstance = AccessTools.Property(type3, "Instance");
				if (mapSeed == null || startInstance == null)
				{
					throw new MissingMemberException("StartOfRound seed accessors were not found.");
				}
				MethodInfo target4 = Require(type3, "ChooseNewRandomMapSeed");
				MethodInfo target5 = Require(type2, "GenerateNewLevelClientRpc", typeof(int), typeof(int));
				MethodInfo methodInfo = AccessTools.Method(AccessTools.TypeByName("GameNetworkManager"), "Disconnect", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					throw new MissingMethodException("GameNetworkManager.Disconnect");
				}
				harmony = new Harmony("local.RandomInteriorsNormalSeeds");
				Patch(target, "Encode");
				Patch(target2, "IsEncoded");
				Patch(target3, "Decode");
				Patch(target4, "BeforeChoose");
				Patch(target5, "BeforeRpc");
				Patch(methodInfo, "Disconnect");
				active = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Normal seed compatibility enabled. Install this fix on EVERY player. Random Interiors assembly: " + assembly.GetName().Version));
			}
			catch (Exception ex)
			{
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				((BaseUnityPlugin)this).Logger.LogError((object)("Unsupported Random Interiors/game version; no seed changes were applied. " + ex));
			}
		}

		private static MethodInfo Require(Type type, string name, params Type[] args)
		{
			MethodInfo methodInfo = AccessTools.Method(type, name, args, (Type[])null);
			if (methodInfo == null)
			{
				throw new MissingMethodException(type.FullName, name);
			}
			return methodInfo;
		}

		private void Patch(MethodInfo target, string prefix)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			harmony.Patch((MethodBase)target, new HarmonyMethod(AccessTools.Method(typeof(Plugin), prefix, (Type[])null, (Type[])null))
			{
				priority = 800
			}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private void Update()
		{
			if (active)
			{
				RegisterMessages();
			}
		}

		private void RegisterMessages()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			CustomMessagingManager val = (((Object)(object)singleton == (Object)null) ? null : singleton.CustomMessagingManager);
			if (val == messaging)
			{
				return;
			}
			if (messaging != null)
			{
				messaging.UnregisterNamedMessageHandler("local.RandomInteriorsNormalSeeds.Selection.v1");
			}
			messaging = val;
			SeedSelections.Clear();
			if (messaging != null)
			{
				CustomMessagingManager obj = messaging;
				object obj2 = <>O.<0>__Receive;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val2 = Receive;
					<>O.<0>__Receive = val2;
					obj2 = (object)val2;
				}
				obj.RegisterNamedMessageHandler("local.RandomInteriorsNormalSeeds.Selection.v1", (HandleNamedMessageDelegate)obj2);
			}
		}

		private static bool Encode(int __0, int __1, ref int __result)
		{
			__result = SeedSelections.Remember(__0, __1);
			return false;
		}

		private static bool IsEncoded(int __0, ref bool __result)
		{
			__result = SeedSelections.Contains(__0);
			return false;
		}

		private static bool Decode(int __0, ref int __result)
		{
			__result = SeedSelections.Decode(__0);
			return false;
		}

		private static void BeforeChoose()
		{
			Self.RegisterMessages();
			SeedSelections.Clear();
		}

		private unsafe static void BeforeRpc(object __instance, ref int __0, int __1)
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			Self.RegisterMessages();
			NetworkManager network = NetworkManager.Singleton;
			if ((Object)(object)network == (Object)null || !network.IsServer)
			{
				return;
			}
			if (__0 <= 0)
			{
				int num = __0;
				__0 = Random.Range(1, 100000000);
				object value = startInstance.GetValue(null, null);
				if (value != null)
				{
					mapSeed.SetValue(value, __0);
				}
				((BaseUnityPlugin)Self).Logger.LogInfo((object)("Replaced legacy non-positive seed " + num + " with " + __0));
			}
			if (!SeedSelections.Contains(__0))
			{
				object[] parameters = new object[4] { __instance, __0, __0, -1 };
				compute.Invoke(null, parameters);
			}
			int num2 = (SeedSelections.Contains(__0) ? SeedSelections.Decode(__0) : (-1));
			if (Self.messaging == null)
			{
				throw new InvalidOperationException("Interior synchronization is not ready.");
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref __0, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref __1, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num2, default(ForPrimitives));
				ulong[] array = network.ConnectedClientsIds.Where((ulong id) => id != network.LocalClientId).ToArray();
				if (array.Length != 0)
				{
					Self.messaging.SendNamedMessage("local.RandomInteriorsNormalSeeds.Selection.v1", (IReadOnlyList<ulong>)array, val, (NetworkDelivery)4);
				}
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
			((BaseUnityPlugin)Self).Logger.LogDebug((object)("Synchronized seed " + __0 + ", moon " + __1 + ", interior " + num2));
		}

		private static void Receive(ulong sender, FastBufferReader reader)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || singleton.IsServer || sender != 0L)
			{
				return;
			}
			if (!((FastBufferReader)(ref reader)).TryBeginRead(12))
			{
				((BaseUnityPlugin)Self).Logger.LogError((object)"Rejected truncated interior selection message.");
				return;
			}
			int num = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
			int num2 = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num2, default(ForPrimitives));
			int num3 = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num3, default(ForPrimitives));
			if (num <= 0 || num3 < -1 || num3 > 4095)
			{
				((BaseUnityPlugin)Self).Logger.LogError((object)"Rejected invalid interior selection message.");
				return;
			}
			SeedSelections.Clear();
			if (num3 >= 0)
			{
				SeedSelections.Remember(num, num3);
			}
			((BaseUnityPlugin)Self).Logger.LogDebug((object)("Received seed " + num + ", moon " + num2 + ", interior " + num3));
		}

		private static void Disconnect()
		{
			SeedSelections.Clear();
		}

		private void OnDestroy()
		{
			if (messaging != null)
			{
				messaging.UnregisterNamedMessageHandler("local.RandomInteriorsNormalSeeds.Selection.v1");
			}
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			SeedSelections.Clear();
		}
	}
	internal static class SeedSelections
	{
		private static readonly Dictionary<int, int> Values = new Dictionary<int, int>();

		internal static int Remember(int seed, int interior)
		{
			if (seed <= 0)
			{
				throw new ArgumentOutOfRangeException("seed");
			}
			if (interior < 0 || interior > 4095)
			{
				throw new ArgumentOutOfRangeException("interior");
			}
			if (Values.Count >= 64 && !Values.ContainsKey(seed))
			{
				Values.Clear();
			}
			Values[seed] = interior;
			return seed;
		}

		internal static bool Contains(int seed)
		{
			return Values.ContainsKey(seed);
		}

		internal static int Decode(int seed)
		{
			return Values[seed];
		}

		internal static void Clear()
		{
			Values.Clear();
		}
	}
}