Please disclose if your mod was created primarily 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 TooMuchScrap v1.4.1
TooMuchScrap.dll
Decompiled 3 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TooMuchScrap; 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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TooMuchScrap")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.5.1.0")] [assembly: AssemblyInformationalVersion("1.5.1+12af77b795bbdcb35d0fd8236c459f1ae76a7a77")] [assembly: AssemblyProduct("TooMuchScrap")] [assembly: AssemblyTitle("TooMuchScrap")] [assembly: AssemblyVersion("1.5.1.0")] 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; } } } [HarmonyPatch(typeof(HUDManager))] internal class MergeCommandPatch { [HarmonyPatch("AddTextToChatOnServer")] [HarmonyPrefix] public static bool AddTextToChatOnServer_Prefix(HUDManager __instance, ref string chatMessage) { Match match = Regex.Match(chatMessage, "^" + global::TooMuchScrap.TooMuchScrap.PrefixChar.Value + "merge(?:\\s+(-?\\d+))?$"); if (match.Success) { global::TooMuchScrap.TooMuchScrap.ReloadConfig(); string error; int num = MergeClass.Merge(out error); if (num >= 0) { __instance.AddTextToChatOnServer($"[TMS] Total scrap removed: {num}", -1); return false; } __instance.AddTextToChatOnServer("[TMS] " + error, -1); return false; } return true; } } [HarmonyPatch(typeof(Terminal))] internal class TerminalMergePatch { [HarmonyPatch("ParsePlayerSentence")] [HarmonyPostfix] public static void ParsePlayerSentence_Postfix(ref Terminal __instance, ref TerminalNode __result) { string text = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded).ToLower().Trim(); if (text == "merge") { global::TooMuchScrap.TooMuchScrap.ReloadConfig(); string error; int num = MergeClass.Merge(out error); TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>(); val.clearPreviousText = true; if (num >= 0) { val.displayText = $"[TMS] Merge successful. Total scrap removed: {num}\n\n"; } else { val.displayText = "[TMS] Error: " + error + "\n\n"; } __result = val; } } } [HarmonyPatch(typeof(StartOfRound))] internal class AutoMergePatch { [HarmonyPatch("SetShipReadyToLand")] [HarmonyPostfix] public static void SetShipReadyToLand_Postfix(StartOfRound __instance) { global::TooMuchScrap.TooMuchScrap.ReloadConfig(); if (global::TooMuchScrap.TooMuchScrap.AutoMerge.Value) { string error; int num = MergeClass.Merge(out error); if (num > 0) { HUDManager.Instance.AddTextToChatOnServer($"[TMS] Auto-merge complete. Total scrap removed: {num}", -1); } } } } namespace TooMuchScrap { public static class MergeClass { public static int Merge(out string? error) { error = null; if (!IsHost(out error)) { return -1; } if (TooMuchScrap.CompanyOnly.Value && !IsInCompanyBuilding(out error)) { return -1; } HashSet<string> mergeableItems = TooMuchScrap.GetMergeableItems(); GrabbableObject[] scrapInShip = GetScrapInShip(); return MergeAllScrap(scrapInShip, mergeableItems); } private static bool IsInCompanyBuilding(out string? error) { if (RoundManager.Instance.currentLevel.sceneName != "CompanyBuilding") { error = "The /merge command can only be used in the Company Building. (You can change this in the config)"; return false; } error = null; return true; } private static bool IsHost(out string? error) { if (!((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost) { error = "Only the host can execute the /merge command to ensure proper networking."; return false; } error = null; return true; } private static GrabbableObject[] GetScrapInShip() { return (from x in Object.FindObjectsByType<GrabbableObject>((FindObjectsSortMode)0) where (Object)(object)x != (Object)null && x.itemProperties.isScrap && x.isInShipRoom select x).ToArray(); } private static int MergeAllScrap(GrabbableObject[] scrapInShip, HashSet<string> mergeableItems) { HashSet<int> hashSet = new HashSet<int>(); int num = 0; foreach (GrabbableObject val in scrapInShip) { if (!((Object)(object)val == (Object)null) && !hashSet.Contains(((Object)val).GetInstanceID())) { string item = ((Object)val).name.Replace("(Clone)", ""); if (mergeableItems.Contains(item)) { int num2 = MergeNearbyScrap(val, mergeableItems, hashSet); num += num2; } } } return num; } private static int MergeNearbyScrap(GrabbableObject source, HashSet<string> mergeableItems, HashSet<int> processed) { //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) GrabbableObject source2 = source; int num = 0; int instanceID = ((Object)source2).GetInstanceID(); GrabbableObject[] array = FindMergeCandidates(source2); if (array.Length < 2) { return 0; } GrabbableObject[] array2 = array.Where((GrabbableObject x) => Vector3.Distance(((Component)x).transform.position, ((Component)source2).transform.position) < TooMuchScrap.MergeDistance.Value).ToArray(); if (array2.Length < 2) { return 0; } List<GrabbableObject> list = array2.OrderBy((GrabbableObject x) => x.scrapValue).ToList(); int num2 = source2.scrapValue; List<GrabbableObject> list2 = new List<GrabbableObject> { source2 }; foreach (GrabbableObject item in list) { if (!((Object)(object)item == (Object)null) && !processed.Contains(((Object)item).GetInstanceID()) && ((Object)item).GetInstanceID() != instanceID && (TooMuchScrap.MaxMergeValue.Value == -1f || !((float)(num2 + item.scrapValue) > TooMuchScrap.MaxMergeValue.Value))) { num2 += item.scrapValue; list2.Add(item); } } source2.SetScrapValue(num2); RoundManager.Instance.SyncScrapValuesClientRpc((NetworkObjectReference[])(object)new NetworkObjectReference[1] { NetworkObjectReference.op_Implicit(((Component)source2).GetComponent<NetworkObject>()) }, new int[1] { num2 }); foreach (GrabbableObject item2 in list2.Where((GrabbableObject x) => (Object)(object)x != (Object)(object)source2)) { if (!((Object)(object)item2 == (Object)null)) { processed.Add(((Object)item2).GetInstanceID()); Object.Destroy((Object)(object)((Component)item2).gameObject); num++; } } processed.Add(instanceID); return num; } private static GrabbableObject[] FindMergeCandidates(GrabbableObject source) { GrabbableObject source2 = source; return (from x in Object.FindObjectsByType<GrabbableObject>((FindObjectsSortMode)0) where (Object)(object)x != (Object)null && x.isInShipRoom && x.itemProperties.isScrap && ((Object)x).name == ((Object)source2).name && !x.isHeld select x).ToArray(); } } [BepInPlugin("abu.TooMuchScrap", "TooMuchScrap", "1.4.1")] public class TooMuchScrap : BaseUnityPlugin { public const string PluginGUID = "abu.TooMuchScrap"; public const string PluginAuthor = "abu"; public const string PluginName = "TooMuchScrap"; public const string PluginVersion = "1.4.1"; private static HashSet<string>? _mergeableItemsCache; public static TooMuchScrap Instance; public static ConfigEntry<float> MergeDistance { get; private set; } public static ConfigEntry<float> MaxMergeValue { get; private set; } public static ConfigEntry<string> MergeableItems { get; private set; } public static ConfigEntry<string> PrefixChar { get; private set; } public static ConfigEntry<bool> CompanyOnly { get; private set; } public static ConfigEntry<bool> AutoMerge { get; private set; } private void Awake() { Instance = this; Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); MergeDistance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MergeDistance", 5f, "Maximum distance at which scrap will merge."); MaxMergeValue = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxMergeValue", 200f, "Maximum merged scrap value."); MergeableItems = ((BaseUnityPlugin)this).Config.Bind<string>("General", "MergeableItems", "HeartContainer,SeveredHandLOD0,SeveredFootLOD0,SeveredThighLOD0,Bone,RibcageBone,Ear,Tongue", "Comma-separated list of item names that can be merged."); PrefixChar = ((BaseUnityPlugin)this).Config.Bind<string>("General", "PrefixChar", "/", "Character that prefixes chat commands."); CompanyOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "CompanyOnly", false, "Only allow merging of scrap at the company building."); AutoMerge = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoMerge", false, "Automatically merge scrap when going in orbit."); } public static HashSet<string> GetMergeableItems() { if (_mergeableItemsCache == null || string.IsNullOrWhiteSpace(MergeableItems?.Value)) { _mergeableItemsCache = new HashSet<string>(); if (!string.IsNullOrWhiteSpace(MergeableItems?.Value)) { string[] array = MergeableItems.Value.Split(','); foreach (string text in array) { string text2 = text.Trim(); if (!string.IsNullOrWhiteSpace(text2)) { _mergeableItemsCache.Add(text2); } } } } return _mergeableItemsCache; } public static void ClearCache() { _mergeableItemsCache = null; } public static void ReloadConfig() { ((BaseUnityPlugin)Instance).Config.Reload(); ClearCache(); } } public static class PluginInfo { public const string PLUGIN_GUID = "TooMuchScrap"; public const string PLUGIN_NAME = "TooMuchScrap"; public const string PLUGIN_VERSION = "1.5.1"; } }