Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Lone Company v1.2.1
Lone_Company.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyVersion("0.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 Lone_Company { [BepInPlugin("lone.company.Lone_Company", "Lone_Company", "1.2.1")] public class Plugin : BaseUnityPlugin { public const string Guid = "lone.company.Lone_Company"; public const string Name = "Lone_Company"; public const string Version = "1.2.1"; internal static ManualLogSource Log; internal static ConfigEntry<string> Mode; internal static ConfigEntry<string> Scaling; internal static ConfigEntry<float> ManualMultiplier; internal static ConfigEntry<string> EnemyAI; internal static int SpawnRound; private void Awake() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Mode = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Mode", "Value", new ConfigDescription("Value = multiplies how much scrap is worth.\nAmount = multiplies how much scrap spawns.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Value", "Amount" }), Array.Empty<object>())); Scaling = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Scaling", "Solo", new ConfigDescription("Manual = always use ManualMultiplier.\nAdaptive = ManualMultiplier divided by player count (min x1). Example: x4 = 1 player x4, 2 players x2, 4 players x1.\nSolo = use ManualMultiplier only when playing alone.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Manual", "Adaptive", "Solo" }), Array.Empty<object>())); ManualMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ManualMultiplier", 2f, new ConfigDescription("Your base multiplier. Adaptive spreads it across the player count.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 100f), Array.Empty<object>())); EnemyAI = ((BaseUnityPlugin)this).Config.Bind<string>("Enemy AI", "EnemyAI", "On", new ConfigDescription("On = enemy multiplayer stats and AI are retained (snareflea no retries/butler with more than 2 health)\nOff = enemy solo stats (nicer snareflea/2 hp butler)", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "On", "Off" }), Array.Empty<object>())); Harmony harmony = new Harmony("lone.company.Lone_Company"); Try("scrap patch", delegate { harmony.PatchAll(); }); Try("SID patch", delegate { SidFix.Apply(harmony); }); Try("enemy patch", delegate { EnemyAIPlayerCount.PatchAllEnemies(harmony); }); Log.LogInfo((object)("Lone_Company 1.2.1 loaded. Mode=" + Mode.Value + ", Scaling=" + Scaling.Value + ", EnemyAI=" + EnemyAI.Value)); } private static void Try(string what, Action a) { try { a(); } catch (Exception arg) { Log.LogError((object)$"Failed to apply {what}: {arg}"); } } internal static float GetMultiplier() { int totalPlayers = GameAccess.TotalPlayers; string value = Scaling.Value; string text = value; if (!(text == "Manual")) { if (text == "Solo") { return (totalPlayers == 1) ? ManualMultiplier.Value : 1f; } return Math.Max(1f, ManualMultiplier.Value / (float)totalPlayers); } return ManualMultiplier.Value; } } [HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")] internal static class SpawnScrapPatch { private static float savedValue; private static float savedAmount; private static bool applied; [HarmonyPrefix] private static void Prefix(RoundManager __instance) { applied = false; Plugin.SpawnRound++; try { if (!((NetworkBehaviour)__instance).IsHost) { return; } float multiplier = Plugin.GetMultiplier(); if (!(Math.Abs(multiplier - 1f) < 0.001f)) { savedValue = __instance.scrapValueMultiplier; savedAmount = __instance.scrapAmountMultiplier; if (Plugin.Mode.Value == "Value") { __instance.scrapValueMultiplier = savedValue * multiplier; } else { __instance.scrapAmountMultiplier = savedAmount * multiplier; } applied = true; Plugin.Log.LogInfo((object)$"{Plugin.Mode.Value} mode: x{multiplier:0.##} (value mult {savedValue:0.###} -> {__instance.scrapValueMultiplier:0.###}, amount mult {savedAmount:0.###} -> {__instance.scrapAmountMultiplier:0.###})"); } } catch (Exception ex) { Plugin.Log.LogError((object)("SpawnScrap prefix failed (level will load normally): " + ex)); } } [HarmonyFinalizer] private static void Finalizer(RoundManager __instance) { try { if (applied) { __instance.scrapValueMultiplier = savedValue; __instance.scrapAmountMultiplier = savedAmount; applied = false; } } catch (Exception ex) { Plugin.Log.LogError((object)("SpawnScrap finalizer failed: " + ex)); } } } internal static class EnemyAIPlayerCount { private static int depth; private static readonly HashSet<string> reported = new HashSet<string>(); internal static void Prefix(out bool __state) { __state = false; try { if (Plugin.EnemyAI.Value != "On") { return; } if (depth == 0) { if (GameAccess.ConnectedPlayers != 0) { return; } GameAccess.ConnectedPlayers = 1; } depth++; __state = true; } catch (Exception ex) { Plugin.Log.LogError((object)("Enemy AI prefix failed: " + ex.Message)); } } internal static void Finalizer(bool __state, Exception __exception, MethodBase __originalMethod) { if (__exception != null && __originalMethod != null) { string text = __originalMethod.DeclaringType?.Name + "." + __originalMethod.Name; if (reported.Add(text)) { Plugin.Log.LogWarning((object)("Enemy AI: exception inside " + text + " while multiplayer count was faked: " + __exception.GetType().Name + ": " + __exception.Message)); } } if (!__state) { return; } try { depth--; if (depth == 0) { GameAccess.ConnectedPlayers = 0; } } catch (Exception ex) { Plugin.Log.LogError((object)("Enemy AI finalizer failed: " + ex.Message)); } } internal static void PatchAllEnemies(Harmony harmony) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown HarmonyMethod val = new HarmonyMethod(typeof(EnemyAIPlayerCount).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)); HarmonyMethod val2 = new HarmonyMethod(typeof(EnemyAIPlayerCount).GetMethod("Finalizer", BindingFlags.Static | BindingFlags.NonPublic)); int num = 0; int num2 = 0; Type[] types = typeof(EnemyAI).Assembly.GetTypes(); foreach (Type type in types) { if ((type != typeof(EnemyAI) && !type.IsSubclassOf(typeof(EnemyAI))) || type.ContainsGenericParameters) { continue; } num++; MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.IsAbstract && !methodInfo.IsGenericMethod && !methodInfo.IsSpecialName && methodInfo.GetMethodBody() != null) { try { harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, val2, (HarmonyMethod)null); num2++; } catch (Exception ex) { Plugin.Log.LogDebug((object)("Skipped " + type.Name + "." + methodInfo.Name + ": " + ex.Message)); } } } } Plugin.Log.LogInfo((object)$"Enemy AI: hooked {num2} methods on {num} enemy types"); } } internal static class GameAccess { private static readonly Type RoundType = typeof(StartOfRound); private static FieldInfo instField; private static FieldInfo countField; private static PropertyInfo instProp; private static PropertyInfo countProp; private static bool resolved; internal static object Round { get { Resolve(); try { return (instProp != null) ? instProp.GetValue(null, null) : instField?.GetValue(null); } catch { return null; } } } internal static int ConnectedPlayers { get { Resolve(); object round = Round; if (round == null) { return -1; } try { return (int)((countProp != null) ? countProp.GetValue(round, null) : countField.GetValue(round)); } catch { return -1; } } set { Resolve(); object round = Round; if (round == null) { return; } try { if (countProp != null) { countProp.SetValue(round, value, null); } else { countField?.SetValue(round, value); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to set player count: " + ex.Message)); } } } internal static int TotalPlayers => (ConnectedPlayers < 0) ? 1 : (ConnectedPlayers + 1); private static void Resolve() { if (!resolved) { resolved = true; instProp = RoundType.GetProperty("Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); instField = RoundType.GetField("Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); countProp = RoundType.GetProperty("connectedPlayersAmount", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); countField = RoundType.GetField("connectedPlayersAmount", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if ((instProp == null && instField == null) || (countProp == null && countField == null)) { Plugin.Log.LogWarning((object)"Could not find StartOfRound.Instance / connectedPlayersAmount; player-count features disabled."); } } } } internal static class SidFix { private static int lastRound = -1; internal static void Apply(Harmony harmony) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(RoundManager), "SyncScrapValuesClientRpc", (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogWarning((object)"SID fix: SyncScrapValuesClientRpc not found, SID won't be multiplied."); } else { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(SidFix).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void Prefix(RoundManager __instance, object[] __args) { try { if (!((NetworkBehaviour)__instance).IsHost || Plugin.Mode.Value != "Value" || lastRound == Plugin.SpawnRound) { return; } object obj = AccessTools.Field(((object)__instance).GetType(), "__rpc_exec_stage")?.GetValue(__instance); if (obj != null && obj.ToString() == "Client") { return; } float multiplier = Plugin.GetMultiplier(); if (Math.Abs(multiplier - 1f) < 0.001f) { return; } Array array = __args[0] as Array; int[] array2 = __args[1] as int[]; if (array == null || array2 == null || array.Length < 3) { return; } string text = null; foreach (object item in array) { string text2 = ItemName(item); if (text2 == null) { return; } if (text == null) { text = text2; } else if (text2 != text) { return; } } lastRound = Plugin.SpawnRound; for (int i = 0; i < array2.Length; i++) { array2[i] = (int)Math.Round((float)array2[i] * multiplier); } Plugin.Log.LogInfo((object)$"Single item day ({text}): {array2.Length} items x{multiplier:0.##}"); } catch (Exception ex) { Plugin.Log.LogError((object)("SID fix failed (scrap will sync normally): " + ex.Message)); } } private static string ItemName(object netObjectRef) { object[] array = new object[2]; MethodInfo method = netObjectRef.GetType().GetMethod("TryGet"); if (method == null || !(bool)method.Invoke(netObjectRef, array)) { return null; } object obj = array[0]; Component val = (Component)((obj is Component) ? obj : null); Component val2 = ((val != null) ? val.GetComponent(typeof(GrabbableObject)) : null); if (val2 == null) { return null; } object obj2 = AccessTools.Field(((object)val2).GetType(), "itemProperties")?.GetValue(val2); return (obj2 == null) ? null : (AccessTools.Field(obj2.GetType(), "itemName")?.GetValue(obj2) as string); } } }