using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HQoL.Network; using HQoL.Patches; using HQoL.Util; using HarmonyLib; using Microsoft.CodeAnalysis; using OreoM.HQoL.73.NetcodePatcher; using TMPro; 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: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: AssemblyCompany("OreoM.HQoL.73")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.14.0")] [assembly: AssemblyInformationalVersion("1.0.14+5d32bbb500f65f5358744f7242f32ea01c4c13c6")] [assembly: AssemblyProduct("HQoL")] [assembly: AssemblyTitle("OreoM.HQoL.73")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.14.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 HQoL { [BepInPlugin("OreoM.HQoL.73", "HQoL", "1.0.14")] public class HQoL : BaseUnityPlugin { internal static SellModule sellModule = null; internal static HQoLConfig modConfig = null; internal static readonly FieldInfo? grabObjDeactivatedInfo = AccessTools.Field(typeof(GrabbableObject), "deactivated"); private const string UnityVersion = "2022.3.62"; public static HQoL Instance { get; private set; } = null; internal static ManualLogSource Logger { get; private set; } = null; internal static Harmony? Harmony { get; set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; if (!Application.unityVersion.StartsWith("2022.3.62", StringComparison.OrdinalIgnoreCase)) { Logger.LogInfo((object)"Skipping OreoM.HQoL.73, no patches will be loaded."); return; } sellModule = new SellModule(); modConfig = new HQoLConfig(((BaseUnityPlugin)this).Config); Patch(); NetcodePatch(); Logger.LogInfo((object)"OreoM.HQoL.73 v1.0.14 has loaded!"); } internal static void NetcodePatch() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { try { methodInfo.Invoke(null, null); } catch (Exception arg) { Logger.LogWarning((object)$"Netcode patch failed, but it's likely intended: {arg}"); } } } } } internal static void Patch() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("OreoM.HQoL.73"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Finished patching!"); } internal static void Unpatch() { Logger.LogDebug((object)"Unpatching..."); Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } Logger.LogDebug((object)"Finished unpatching!"); } } public class HQoLConfig { public HashSet storageException; public readonly ConfigEntry storageExceptionConfig; public HQoLConfig(ConfigFile cfg) { cfg.SaveOnConfigSet = false; storageExceptionConfig = cfg.Bind("General", "Dont store list", "Shotgun, Knife", "What items should not be stored automatically"); ClearOrphanedEntries(cfg); cfg.Save(); cfg.SaveOnConfigSet = true; storageException = new HashSet(from s in storageExceptionConfig.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim().ToLower()); } private static void ClearOrphanedEntries(ConfigFile cfg) { PropertyInfo propertyInfo = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries"); Dictionary dictionary = (Dictionary)propertyInfo.GetValue(cfg); dictionary.Clear(); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "OreoM.HQoL.73"; public const string PLUGIN_NAME = "HQoL"; public const string PLUGIN_VERSION = "1.0.14"; } } namespace HQoL.Util { internal class SellModule { public int sellValue; public List itemReferenceIndexToSell; public Dictionary itemTypesToSell; public SellModule() { itemTypesToSell = new Dictionary(); itemReferenceIndexToSell = new List(); } public bool FindItemsWithTotalValue(int value, bool useOvertime) { int num = value; int num2 = 0; int num3 = 10 * value; int profitQuota = TimeOfDay.Instance.profitQuota; int num4 = ((TimeOfDay.Instance.daysUntilDeadline == 0) ? (-1) : TimeOfDay.Instance.daysUntilDeadline); float companyBuyingRate = StartOfRound.Instance.companyBuyingRate; while (useOvertime) { int num5 = num; num = (num2 + num3) / 2; int num6 = Math.Max(((int)((float)num * companyBuyingRate) - profitQuota) / 5 + 15 * num4, 0); if ((int)((float)num * companyBuyingRate) + num6 >= value) { num3 = num; } else { num2 = num; } if ((int)((float)num * companyBuyingRate) + num6 == value) { break; } if (num5 == num) { num++; break; } } int num7 = num; int num8 = 0; foreach (ItemReference item in HQoLNetwork.Instance.netStorage) { num8 += item.value; } if (num7 > num8) { return FindAllItems(); } if (num7 < 1) { return false; } bool[,] array = new bool[num8 + 1, HQoLNetwork.Instance.netStorage.Count + 1]; for (int i = 0; i < num8 + 1; i++) { for (int j = 0; j < HQoLNetwork.Instance.netStorage.Count + 1; j++) { array[i, j] = false; } } array[0, 0] = true; for (int k = 0; k < num8 + 1; k++) { for (int l = 0; l < HQoLNetwork.Instance.netStorage.Count; l++) { if (k >= HQoLNetwork.Instance.netStorage[l].value) { array[k, l + 1] = array[k, l] || array[k - HQoLNetwork.Instance.netStorage[l].value, l]; } else { array[k, l + 1] = array[k, l]; } if (k >= num7 && array[k, HQoLNetwork.Instance.netStorage.Count]) { goto end_IL_020b; } } continue; end_IL_020b: break; } itemReferenceIndexToSell.Clear(); itemTypesToSell.Clear(); int m = num7; int num9; for (num9 = HQoLNetwork.Instance.netStorage.Count; !array[m, num9]; m++) { } sellValue = m; while (m != 0) { while (array[m, num9 - 1]) { num9--; } num9--; m -= HQoLNetwork.Instance.netStorage[num9].value; itemReferenceIndexToSell.Add(num9); Dictionary dictionary = itemTypesToSell; ItemReference itemReference = HQoLNetwork.Instance.netStorage[num9]; if (dictionary.ContainsKey(((object)(FixedString32Bytes)(ref itemReference.itemName)).ToString())) { Dictionary dictionary2 = itemTypesToSell; itemReference = HQoLNetwork.Instance.netStorage[num9]; dictionary2[((object)(FixedString32Bytes)(ref itemReference.itemName)).ToString()]++; } else { Dictionary dictionary3 = itemTypesToSell; itemReference = HQoLNetwork.Instance.netStorage[num9]; dictionary3[((object)(FixedString32Bytes)(ref itemReference.itemName)).ToString()] = 1; } } return true; } public bool FindAllItems() { sellValue = HQoLNetwork.Instance.totalStorageValue.Value; itemReferenceIndexToSell.Clear(); itemTypesToSell.Clear(); for (int i = 0; i < HQoLNetwork.Instance.netStorage.Count; i++) { itemReferenceIndexToSell.Add(i); Dictionary dictionary = itemTypesToSell; ItemReference itemReference = HQoLNetwork.Instance.netStorage[i]; if (dictionary.ContainsKey(((object)(FixedString32Bytes)(ref itemReference.itemName)).ToString())) { Dictionary dictionary2 = itemTypesToSell; itemReference = HQoLNetwork.Instance.netStorage[i]; dictionary2[((object)(FixedString32Bytes)(ref itemReference.itemName)).ToString()]++; } else { Dictionary dictionary3 = itemTypesToSell; itemReference = HQoLNetwork.Instance.netStorage[i]; dictionary3[((object)(FixedString32Bytes)(ref itemReference.itemName)).ToString()] = 1; } } return true; } public void ClearSellModule() { sellValue = 0; itemTypesToSell.Clear(); itemReferenceIndexToSell.Clear(); } } public struct ItemReference : INetworkSerializable, IEquatable { public FixedString32Bytes itemName; public int value; public unsafe void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0026: Unknown result type (might be due to invalid IL or missing references) ((BufferSerializer*)(&serializer))->SerializeValue(ref itemName, default(ForFixedStrings)); ((BufferSerializer*)(&serializer))->SerializeValue(ref value, default(ForPrimitives)); } public bool Equals(ItemReference other) { if ((ref itemName) == (ref other.itemName)) { return value == other.value; } return false; } } } namespace HQoL.Patches { [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatches { [HarmonyPatch("Start")] [HarmonyPostfix] private static void PostStart(GameNetworkManager __instance) { HQoLNetwork.CreateAndRegisterPrefab(); } [HarmonyPatch("Disconnect")] [HarmonyPrefix] private static void PreDisconnect(GameNetworkManager __instance) { bool flag = false; if (StartOfRoundPatches.hasChallengeFile) { flag = StartOfRoundPatches.isChallengeFileRef.Invoke(StartOfRound.Instance); } if (HQoLNetwork.Instance.storageHasBeenModified && __instance.isHostingGame && StartOfRound.Instance.inShipPhase && !flag) { try { List list = new List(); foreach (ItemReference item in HQoLNetwork.Instance.netStorage) { list.Add(item); } ES3.Save>("HQoL.ScrapList", list, GameNetworkManager.Instance.currentSaveFileName); HQoLNetwork.Instance.storageHasBeenModified = false; } catch (Exception arg) { HQoL.Logger.LogError((object)$"Error while trying to save game values when disconnecting as host: {arg}"); } } HQoLNetwork.DespawnNetworkHandler(); } private static void NewCodeFromV81() { ES3.DeleteKey("shipGrabbableItemIDs", GameNetworkManager.Instance.currentSaveFileName); ES3.DeleteKey("shipGrabbableItemPos", GameNetworkManager.Instance.currentSaveFileName); ES3.DeleteKey("shipScrapValues", GameNetworkManager.Instance.currentSaveFileName); ES3.DeleteKey("shipItemSaveData", GameNetworkManager.Instance.currentSaveFileName); } [HarmonyPatch("SaveItemsInShip")] [HarmonyTranspiler] private static IEnumerable TranspileSaveItemsInShip(IEnumerable codes) { //IL_0002: 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) //IL_0022: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(codes, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.PropertyGetter(typeof(List), "Count"), (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_I4_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Bgt, (object)null, (string)null) }); CodeInstruction[] array = (CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(GameNetworkManagerPatches), "NewCodeFromV81", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Ret, (object)null) }; val.Advance(6); if (val.Opcode != OpCodes.Ret) { HQoL.Logger.LogInfo((object)"0 item save bug already fix, this is likely v80+"); return codes; } List