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);
}
}
}