Decompiled source of BetterCoreManagement v1.0.3

plugins/BetterCoreManagement.dll

Decompiled a year ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using BetterCoreManagement.Network;
using HarmonyLib;
using JetBrains.Annotations;
using Mirror;
using Mirror.RemoteCalls;
using UnityEngine;
using VLB;

[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: Guid("9C073AFD-FB22-4339-ABA1-95FB38E2F3EF")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyProduct("BetterCoreManagement")]
[assembly: AssemblyCompany("Vapok Gaming")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("BetterCoreManagement")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.0")]
[module: UnverifiableCode]
namespace BetterCoreManagement
{
	[BepInPlugin("com.vapok.BetterCoreManagement", "BetterCoreManagement", "1.0.3")]
	[BepInIncompatibility("com.equinox.VirtualCores")]
	public class BetterCoreManagement : BaseUnityPlugin
	{
		private const string MyGUID = "com.vapok.BetterCoreManagement";

		private const string PluginName = "BetterCoreManagement";

		private const string VersionString = "1.0.3";

		public static ManualLogSource Log = new ManualLogSource("BetterCoreManagement");

		private static BetterCoreManagement _instance;

		private static Harmony _harmony = new Harmony("com.vapok.BetterCoreManagement");

		private static Dictionary<CoreType, int> _virtualCoreCounts;

		private string _saveFolder = Path.Combine(Application.persistentDataPath, "BetterCoreManagement");

		public static BetterCoreManagement Instance => _instance;

		public static Dictionary<CoreType, int> VirtualCoreCounts => _virtualCoreCounts;

		private void Awake()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			_instance = this;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BetterCoreManagement [1.0.3] is loading...");
			Log = ((BaseUnityPlugin)this).Logger;
			Directory.CreateDirectory(_saveFolder);
			_virtualCoreCounts = new Dictionary<CoreType, int>();
			string[] names = Enum.GetNames(typeof(CoreType));
			for (int i = 0; i < names.Length; i++)
			{
				if (Enum.TryParse<CoreType>(names[i], out CoreType result) && !_virtualCoreCounts.ContainsKey(result))
				{
					_virtualCoreCounts.Add(result, 0);
				}
			}
			_harmony.PatchAll();
		}

		public void SaveVirtualCounts(string worldName)
		{
			if (_virtualCoreCounts != null)
			{
				string path = Path.Combine(_saveFolder, worldName + ".bin");
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				FileStream fileStream = File.Create(path);
				Log.LogDebug((object)("Saving Virtual Core Data to " + worldName + ".bin"));
				binaryFormatter.Serialize(fileStream, _virtualCoreCounts);
				fileStream.Close();
			}
		}

		public void LoadVirtualCounts(string worldName)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			string path = Path.Combine(_saveFolder, worldName + ".bin");
			if (!File.Exists(path))
			{
				return;
			}
			Log.LogDebug((object)("Loading Virtual Core Data from " + worldName + ".bin"));
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			FileStream fileStream = File.Open(path, FileMode.Open);
			Dictionary<CoreType, int> dictionary = binaryFormatter.Deserialize(fileStream) as Dictionary<CoreType, int>;
			fileStream.Close();
			if (dictionary == null)
			{
				return;
			}
			Log.LogDebug((object)"Loading Core Counts From File:");
			foreach (KeyValuePair<CoreType, int> item in dictionary)
			{
				Log.LogDebug((object)$"{item.Key} Core: {item.Value}");
				_virtualCoreCounts[item.Key] = item.Value;
			}
		}
	}
}
namespace BetterCoreManagement.Patches
{
	public static class TechTreeUIPatches
	{
		[HarmonyPatch(typeof(TechTreeUI), "RefreshCores")]
		public static class TechUIStartAddComponent
		{
			[UsedImplicitly]
			private static void Prefix(TechTreeUI __instance)
			{
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				List<CoreType> coreTypesToDisplay = Traverse.Create((object)__instance).Field("coreTypesToDisplay").GetValue() as List<CoreType>;
				if (coreTypesToDisplay != null)
				{
					foreach (KeyValuePair<CoreType, int> item in from coreCount in BetterCoreManagement.VirtualCoreCounts
						where coreCount.Value > 0
						where !coreTypesToDisplay.Contains(coreCount.Key)
						select coreCount)
					{
						coreTypesToDisplay.Add(item.Key);
					}
				}
				Traverse.Create((object)__instance).Field("coreTypesToDisplay").SetValue((object)coreTypesToDisplay);
			}

			private static int UpdateTotalCores(int totalCores, int coreIndex)
			{
				return totalCores + BetterCoreManagement.VirtualCoreCounts[(CoreType)coreIndex];
			}

			[UsedImplicitly]
			public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator)
			{
				List<CodeInstruction> instrs = instructions.ToList();
				int counter = 0;
				bool patchedRefreshCoresMethod = false;
				int i = 0;
				while (i < instrs.Count)
				{
					if (i > 6 && instrs[i].opcode == OpCodes.Stloc_S && instrs[i - 1].opcode == OpCodes.Callvirt && instrs[i - 2].opcode == OpCodes.Ldloc_S && instrs[i - 3].opcode == OpCodes.Ldloc_0)
					{
						yield return LogMessage(instrs[i]);
						counter++;
						yield return LogMessage(new CodeInstruction(OpCodes.Ldloc_S, instrs[i].operand));
						counter++;
						yield return LogMessage(new CodeInstruction(OpCodes.Ldloc_S, instrs[i - 2].operand));
						counter++;
						yield return LogMessage(new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(TechUIStartAddComponent), "UpdateTotalCores", (Type[])null, (Type[])null)));
						counter++;
						yield return LogMessage(new CodeInstruction(OpCodes.Stloc_S, instrs[i].operand));
						counter++;
						patchedRefreshCoresMethod = true;
					}
					else
					{
						yield return LogMessage(instrs[i]);
						counter++;
					}
					int num = i + 1;
					i = num;
				}
				if (!patchedRefreshCoresMethod)
				{
					BetterCoreManagement.Log.LogError((object)"TechTreeUI.RefreshCores Transpiler Failed To Patch");
					BetterCoreManagement.Log.LogError((object)"Please inform Mod Author.");
					Thread.Sleep(5000);
				}
				CodeInstruction LogMessage(CodeInstruction instruction)
				{
					BetterCoreManagement.Log.LogDebug((object)$"IL_{counter}: Opcode: {instruction.opcode} Operand: {instruction.operand}");
					return instruction;
				}
			}
		}
	}
	public static class MemoryTreePatches
	{
		[HarmonyPatch(typeof(MemoryTreeMachineList), "UpdateAll")]
		public static class MemoryTreeMachineListUpdateAllChanges
		{
			[UsedImplicitly]
			public static void Postfix(MemoryTreeMachineList __instance)
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Invalid comparison between Unknown and I4
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: 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_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				if (((MachineInstanceList<MemoryTreeInstance, MemoryTreeDefinition>)(object)__instance).curCount < 1)
				{
					return;
				}
				int num = default(int);
				ResearchCoreDefinition val = default(ResearchCoreDefinition);
				int num2 = default(int);
				for (int i = 0; i < ((MachineInstanceList<MemoryTreeInstance, MemoryTreeDefinition>)(object)__instance).curCount; i++)
				{
					if (((MachineInstanceList<MemoryTreeInstance, MemoryTreeDefinition>)(object)__instance).myArray[i].pendingCoreCount < 1 && (int)((MemoryTreeInstance)(ref ((MachineInstanceList<MemoryTreeInstance, MemoryTreeDefinition>)(object)__instance).myArray[i])).GetErrorState() == 1 && ((MemoryTreeInstance)(ref ((MachineInstanceList<MemoryTreeInstance, MemoryTreeDefinition>)(object)__instance).myArray[i])).FindCoreInInventory(ref num, ref val))
					{
						BetterCoreManagement.VirtualCoreCounts[val.coreType]++;
						BetterCoreManagement.Log.LogDebug((object)$"Adding 1 {val.coreType} Research Core Virtually");
						((Inventory)(ref ((MemoryTreeInstance)(ref ((MachineInstanceList<MemoryTreeInstance, MemoryTreeDefinition>)(object)__instance).myArray[i])).GetInputInventory())).RemoveResourcesFromSlot(num, ref num2, 1, false);
					}
				}
			}
		}
	}
	public static class NetworkIdentityPatches
	{
		[HarmonyPatch(typeof(NetworkIdentity), "Awake")]
		public static class NetworkIdentityAwakeChanges
		{
			[UsedImplicitly]
			public static void Prefix(NetworkIdentity __instance)
			{
				Utils.GetOrAddComponent<CoreNetwork>((MonoBehaviour)(object)__instance);
			}
		}
	}
	public static class SaveStatePatches
	{
		[HarmonyPatch(typeof(SaveState), "LoadFileData", new Type[]
		{
			typeof(SaveMetadata),
			typeof(string)
		})]
		public static class SaveStateLoadFileData
		{
			public static void Postfix(SaveState __instance, SaveMetadata saveMetadata)
			{
				BetterCoreManagement.Instance.LoadVirtualCounts(saveMetadata.worldName);
			}
		}

		[HarmonyPatch(typeof(SaveState), "SaveToFile")]
		public static class SaveStateSaveToFile
		{
			[UsedImplicitly]
			public static void Postfix(SaveState __instance)
			{
				if (__instance != null && __instance.metadata?.worldName != null)
				{
					BetterCoreManagement.Instance.SaveVirtualCounts(__instance.metadata.worldName);
				}
			}
		}
	}
	public static class TechTreeStatePatches
	{
		[HarmonyPatch(typeof(TechTreeState), "NumCoresOfTypePlaced")]
		public static class TechTreeStateNumCoresOfTypePlacedChanges
		{
			[UsedImplicitly]
			public static void Postfix(TechTreeState __instance, int typeIndex, ref int __result)
			{
				for (int i = 0; i < BetterCoreManagement.VirtualCoreCounts.Count; i++)
				{
					if (BetterCoreManagement.VirtualCoreCounts[(CoreType)i] > 0 && i >= __instance.totalResearchCores.Count)
					{
						while (i >= __instance.totalResearchCores.Count)
						{
							__instance.totalResearchCores.Add(0);
						}
					}
				}
				int num = 0;
				if (__instance.totalResearchCores.Count <= typeIndex)
				{
					for (int j = 0; j < typeIndex - __instance.totalResearchCores.Count; j++)
					{
						__instance.totalResearchCores.Add(0);
					}
				}
				else
				{
					num = __instance.totalResearchCores[typeIndex] + BetterCoreManagement.VirtualCoreCounts[(CoreType)typeIndex];
				}
				__result = num;
			}
		}
	}
}
namespace BetterCoreManagement.Network
{
	public class CoreNetwork : NetworkBehaviour
	{
		[SyncVar]
		public string NetworkID;

		public PlatformUserId playerID;

		private HashSet<NetworkConnection> _clients = new HashSet<NetworkConnection>();

		private NetworkedPlayer _player => Player.instance.networkedPlayer;

		public string NetworkNetworkID
		{
			get
			{
				return NetworkID;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<string>(value, ref NetworkID))
				{
					_ = NetworkID;
					((NetworkBehaviour)this).SetSyncVar<string>(value, ref NetworkID, 1uL);
				}
			}
		}

		protected override bool SerializeSyncVars(NetworkWriter writer, bool forceAll)
		{
			bool result = ((NetworkBehaviour)this).SerializeSyncVars(writer, forceAll);
			if (forceAll)
			{
				NetworkWriterExtensions.WriteString(writer, NetworkID);
				return true;
			}
			NetworkWriterExtensions.WriteULong(writer, ((NetworkBehaviour)this).syncVarDirtyBits);
			if ((((NetworkBehaviour)this).syncVarDirtyBits & 1) != 0L)
			{
				NetworkWriterExtensions.WriteString(writer, NetworkID);
				result = true;
			}
			return result;
		}

		protected override void DeserializeSyncVars(NetworkReader reader, bool initialState)
		{
			((NetworkBehaviour)this).DeserializeSyncVars(reader, initialState);
			if (initialState)
			{
				_ = NetworkID;
				NetworkNetworkID = NetworkReaderExtensions.ReadString(reader);
			}
			else if ((NetworkReaderExtensions.ReadULong(reader) & 1) != 0L)
			{
				_ = NetworkID;
				NetworkNetworkID = NetworkReaderExtensions.ReadString(reader);
			}
		}

		static CoreNetwork()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			RemoteCallHelper.RegisterCommandDelegate(typeof(CoreNetwork), "RequestCoreCount", new CmdDelegate(InvokeUserCode_RequestCoreCount), true);
			RemoteCallHelper.RegisterRpcDelegate(typeof(CoreNetwork), "LoadCoreCountFromServer", new CmdDelegate(InvokeUserCode_LoadCoreCountFromServer));
		}

		private static void InvokeUserCode_RequestCoreCount(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection)
		{
			if (!NetworkServer.active)
			{
				BetterCoreManagement.Log.LogError((object)"Command RequestCoreCount called on client.");
			}
			else
			{
				((CoreNetwork)(object)obj).UserCode_RequestCoreCount(senderConnection);
			}
		}

		protected static void InvokeUserCode_LoadCoreCountFromServer(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection)
		{
			if (!NetworkClient.active)
			{
				BetterCoreManagement.Log.LogError((object)"TargetRPC LoadCoreCountFromServer called on server.");
			}
			else
			{
				((CoreNetwork)(object)obj).UserCode_LoadCoreCountFromServer(NetworkClient.connection, NetworkReaderExtensions.ReadList<int>(reader), NetworkReaderExtensions.ReadList<int>(reader));
			}
		}

		private void Awake()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			base.syncMode = (SyncMode)1;
		}

		public override void OnStartClient()
		{
			if (((NetworkBehaviour)this).connectionToClient != null)
			{
				_clients.Add(((NetworkBehaviour)this).connectionToClient);
			}
		}

		public override void OnStartLocalPlayer()
		{
			BetterCoreManagement.Log.LogDebug((object)$"OnStartLocalPlayer() for Network ID {((NetworkBehaviour)this).netId}");
			RequestCoreCount();
			((MonoBehaviour)this).InvokeRepeating("InvokeRequestCoreCount", 300f, 300f);
		}

		public override void OnStartServer()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)this).connectionToClient != null)
			{
				BetterCoreManagement.Log.LogDebug((object)$"OnStartServer() for Network ID {((NetworkBehaviour)this).netId}");
				if (!((NetworkBehaviour)this).hasAuthority)
				{
					NetworkNetworkID = (string)((NetworkBehaviour)this).connectionToClient.authenticationData;
					playerID = Platform.mgr.ClientIdFromString(NetworkID);
					BetterCoreManagement.Log.LogDebug((object)$"No Authority for Network ID {((NetworkBehaviour)this).netId} / Player ID {playerID}");
				}
				else
				{
					NetworkNetworkID = "host";
					playerID = Platform.mgr.LocalPlayerId();
					BetterCoreManagement.Log.LogDebug((object)$"Has Authority for Network ID {((NetworkBehaviour)this).netId} / Player ID {playerID}");
				}
			}
		}

		public override void OnStopClient()
		{
			if (((NetworkBehaviour)this).connectionToClient != null)
			{
				BetterCoreManagement.Log.LogDebug((object)$"OnStopClient() for Network ID {((NetworkBehaviour)this).netId}");
				((MonoBehaviour)this).CancelInvoke("RequestCoreCount");
				_clients.Remove(((NetworkBehaviour)this).connectionToClient);
			}
		}

		private void InvokeRequestCoreCount()
		{
			RequestCoreCount();
		}

		[Command]
		public void RequestCoreCount(NetworkConnectionToClient sender = null)
		{
			if (!((NetworkBehaviour)this).isServer)
			{
				BetterCoreManagement.Log.LogDebug((object)"Requesting Core Count");
				PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
				((NetworkBehaviour)this).SendCommandInternal(typeof(CoreNetwork), "RequestCoreCount", (NetworkWriter)(object)writer, 0, true);
				NetworkWriterPool.Recycle(writer);
			}
		}

		[TargetRpc]
		public void LoadCoreCountFromServer(NetworkConnection connection)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected I4, but got Unknown
			BetterCoreManagement.Log.LogDebug((object)"Core Count Requested by NetworkedPlayer");
			PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
			List<int> list = new List<int>();
			List<int> list2 = new List<int>();
			foreach (KeyValuePair<CoreType, int> virtualCoreCount in BetterCoreManagement.VirtualCoreCounts)
			{
				list.Add((int)virtualCoreCount.Key);
				list2.Add(virtualCoreCount.Value);
			}
			NetworkWriterExtensions.WriteList<int>((NetworkWriter)(object)writer, list);
			NetworkWriterExtensions.WriteList<int>((NetworkWriter)(object)writer, list2);
			((NetworkBehaviour)this).SendTargetRPCInternal(connection, typeof(CoreNetwork), "LoadCoreCountFromServer", (NetworkWriter)(object)writer, 0);
			NetworkWriterPool.Recycle(writer);
		}

		private void UserCode_RequestCoreCount(NetworkConnectionToClient sender)
		{
			((MonoBehaviour)this).StartCoroutine(PackageCoreCount(sender));
		}

		private void UserCode_LoadCoreCountFromServer(NetworkConnection connection, List<int> keyList, List<int> valueList)
		{
			BetterCoreManagement.Log.LogDebug((object)"Core Count Received by Host/Server");
			for (int i = 0; i < keyList.Count; i++)
			{
				BetterCoreManagement.VirtualCoreCounts[(CoreType)keyList[i]] = valueList[i];
			}
		}

		private IEnumerator PackageCoreCount(NetworkConnectionToClient sender)
		{
			while (SaveState.isSaving)
			{
				yield return null;
			}
			LoadCoreCountFromServer((NetworkConnection)(object)sender);
		}
	}
}