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 FriendScrapStatues v1.0.5
FriendScrapStatues.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using LethalLib.Modules; using Microsoft.CodeAnalysis; 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: AssemblyCompany("FriendScrapStatues")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9f7cf52b5b2a1d26ef731d2280a3b36f642606d6")] [assembly: AssemblyProduct("FriendScrapStatues")] [assembly: AssemblyTitle("FriendScrapStatues")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 FriendScrapStatues { [HarmonyPatch(typeof(GrabbableObject), "LateUpdate")] internal static class HoldUprightPatch { private static void Postfix(GrabbableObject __instance) { //IL_0071: 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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (__instance.isHeld && !((Object)(object)__instance.parentObject == (Object)null) && !((Object)(object)__instance.playerHeldBy == (Object)null)) { ScrapDefinition scrapDefinition = ScrapDefinition.All.FirstOrDefault((ScrapDefinition d) => d.HoldUpright && (Object)(object)d.Item == (Object)(object)__instance.itemProperties); if (scrapDefinition != null) { Quaternion rotation = ((Component)__instance.playerHeldBy.gameplayCamera).transform.rotation; ((Component)__instance).transform.rotation = rotation * Quaternion.Euler(0f, scrapDefinition.HeldYaw, 0f); } } } } internal static class ItemFactory { [HarmonyPatch(typeof(GameNetworkManager), "Start")] private static class GameNetworkManagerStartPatch { private static void Postfix() { CreateAll(); } } private const string TemplateItemName = "Big bolt"; private const float GameFloorLift = 0.04f; private static GameObject? _templateHolder; private static void CreateAll() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown if ((Object)(object)_templateHolder != (Object)null) { return; } NetworkManager singleton = NetworkManager.Singleton; GrabbableObject val = singleton.NetworkConfig.Prefabs.Prefabs.Select((NetworkPrefab p) => (!((Object)(object)p.Prefab != (Object)null)) ? null : p.Prefab.GetComponent<GrabbableObject>()).FirstOrDefault((Func<GrabbableObject, bool>)((GrabbableObject g) => (Object)(object)g != (Object)null && (Object)(object)g.itemProperties != (Object)null && g.itemProperties.itemName == "Big bolt")); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Could not find the vanilla 'Big bolt' to copy. No scrap was added."); return; } _templateHolder = new GameObject("FriendScrapStatues_Templates"); _templateHolder.SetActive(false); ((Object)_templateHolder).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)_templateHolder); ScrapDefinition[] all = ScrapDefinition.All; foreach (ScrapDefinition scrapDefinition in all) { try { Item val2 = Build(scrapDefinition, val); singleton.AddNetworkPrefab(val2.spawnPrefab); Items.RegisterScrap(val2, 1, (LevelTypes)(-1)); scrapDefinition.Item = val2; Plugin.Log.LogInfo((object)("Added scrap '" + scrapDefinition.Name + "'.")); } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to build '{scrapDefinition.Name}': {arg}"); } } } private static Item Build(ScrapDefinition def, GrabbableObject template) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Unknown result type (might be due to invalid IL or missing references) AssetBundle bundle = Plugin.Bundle; MeshFilter componentInChildren = (bundle.LoadAsset<GameObject>(def.AssetName) ?? throw new Exception("model '" + def.AssetName + "' is not in the asset bundle")).GetComponentInChildren<MeshFilter>(); Mesh val = ((componentInChildren != null) ? componentInChildren.sharedMesh : null) ?? throw new Exception("model '" + def.AssetName + "' has no mesh"); Texture2D val2 = bundle.LoadAsset<Texture2D>(def.TextureName) ?? throw new Exception("texture '" + def.TextureName + "' is not in the asset bundle"); GameObject val3 = Object.Instantiate<GameObject>(((Component)template).gameObject, _templateHolder.transform); ((Object)val3).name = def.AssetName; val3.transform.localScale = Vector3.one; byte[] value = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("theOhmbrewer.FriendScrapStatues" + def.AssetName)); AccessTools.Field(typeof(NetworkObject), "GlobalObjectIdHash").SetValue(val3.GetComponent<NetworkObject>(), BitConverter.ToUInt32(value, 0)); Material val4 = new Material(((Renderer)val3.GetComponentInChildren<MeshRenderer>()).sharedMaterial) { name = def.AssetName }; val4.SetColor("_BaseColor", Color.white); val4.SetTexture("_BaseColorMap", (Texture)(object)val2); val4.mainTexture = (Texture)(object)val2; val4.SetFloat("_Metallic", 0f); val4.SetFloat("_Smoothness", 0.2f); val4.SetTexture("_NormalMap", (Texture)null); val4.SetTexture("_MaskMap", (Texture)null); val4.DisableKeyword("_NORMALMAP"); val4.DisableKeyword("_MASKMAP"); LODGroup[] componentsInChildren = val3.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } MeshRenderer[] componentsInChildren2 = val3.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer obj in componentsInChildren2) { MeshFilter component = ((Component)obj).GetComponent<MeshFilter>(); Object.DestroyImmediate((Object)(object)obj); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } } Bounds bounds = val.bounds; float num = def.SizeMeters / Mathf.Max(new float[3] { ((Bounds)(ref bounds)).size.x, ((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z }); GameObject val5 = new GameObject("Model") { layer = val3.layer }; val5.transform.SetParent(val3.transform, false); val5.transform.localScale = Vector3.one * num; val5.transform.localPosition = -((Bounds)(ref bounds)).center * num; val5.AddComponent<MeshFilter>().sharedMesh = val; MeshRenderer val6 = val5.AddComponent<MeshRenderer>(); ((Renderer)val6).sharedMaterial = val4; BoxCollider component2 = val3.GetComponent<BoxCollider>(); if ((Object)(object)component2 != (Object)null) { component2.center = Vector3.zero; component2.size = Vector3.Max(((Bounds)(ref bounds)).size * num, Vector3.one * 0.1f); } Item val7 = Object.Instantiate<Item>(template.itemProperties); ((Object)val7).name = def.AssetName; val7.itemName = def.Name; val7.spawnPrefab = val3; val7.isScrap = true; val7.twoHanded = false; val7.isConductiveMetal = def.Conductive; val7.weight = 1f + def.Pounds / 105f; SpawnOddsPatch.SetValueRange(def, val7, 0.4f); val7.restingRotation = Vector3.zero; val7.verticalOffset = Mathf.Max(0f, ((Bounds)(ref bounds)).size.y * num / 2f - 0.04f); AudioClip val8 = LoadSound(def.GrabSound); if ((Object)(object)val8 != (Object)null) { val7.grabSFX = val8; } AudioClip val9 = LoadSound(def.DropSound); if ((Object)(object)val9 != (Object)null) { val7.dropSFX = val9; } GrabbableObject component3 = val3.GetComponent<GrabbableObject>(); component3.itemProperties = val7; component3.mainObjectRenderer = val6; ScanNodeProperties componentInChildren2 = val3.GetComponentInChildren<ScanNodeProperties>(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.headerText = def.Name; ((Component)componentInChildren2).transform.localPosition = Vector3.zero; } return val7; } private static AudioClip? LoadSound(string name) { if (string.IsNullOrEmpty(name)) { return null; } AudioClip obj = Plugin.Bundle.LoadAsset<AudioClip>(name); if ((Object)(object)obj == (Object)null) { Plugin.Log.LogWarning((object)("Sound '" + name + "' is not in the asset bundle; using the default.")); } return obj; } } [BepInPlugin("theOhmbrewer.FriendScrapStatues", "FriendScrapStatues", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private const string BundleFileName = "friendscrapstatues"; internal static ManualLogSource Log; internal static AssetBundle Bundle; private void Awake() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "friendscrapstatues"); Bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)Bundle == (Object)null) { Log.LogError((object)("Could not load asset bundle at " + text + ". The mod will not add any scrap.")); return; } new Harmony("theOhmbrewer.FriendScrapStatues").PatchAll(); Log.LogInfo((object)"FriendScrapStatues 1.0.0 loaded."); } } internal class ScrapDefinition { internal static readonly ScrapDefinition[] All = new ScrapDefinition[2] { new ScrapDefinition { Name = "Dez Statue", AssetName = "dezstatue", TextureName = "dezstatuetexture", MinCredits = 150, MaxCredits = 210, Pounds = 5f, AverageDaysBetween = 6.6666665f, Conductive = false, SizeMeters = 0.6f, HoldUpright = true }, new ScrapDefinition { Name = "Nano Orb", AssetName = "nanoorb", TextureName = "nanoorbtexture", MinCredits = 160, MaxCredits = 220, Pounds = 7f, AverageDaysBetween = 20f, Conductive = true, SizeMeters = 0.35f } }; public string Name = ""; public string AssetName = ""; public string TextureName = ""; public string GrabSound = ""; public string DropSound = ""; public int MinCredits; public int MaxCredits; public float Pounds; public float AverageDaysBetween; public bool Conductive; public float SizeMeters; public bool HoldUpright; public float HeldYaw = 180f; public Item? Item; } [HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")] internal static class SpawnOddsPatch { private const int Precision = 100; private static readonly Dictionary<SpawnableItemWithRarity, int> OriginalRarities = new Dictionary<SpawnableItemWithRarity, int>(); private static void Prefix(RoundManager __instance) { RestoreRarities(); SelectableLevel currentLevel = __instance.currentLevel; if ((Object)(object)currentLevel == (Object)null) { return; } List<(SpawnableItemWithRarity entry, ScrapDefinition def)> ours = (from entry in currentLevel.spawnableScrap select (entry: entry, def: ScrapDefinition.All.FirstOrDefault((ScrapDefinition d) => (Object)(object)d.Item != (Object)null && (Object)(object)d.Item == (Object)(object)entry.spawnableItem)) into x where x.def != null select x).ToList(); if (ours.Count == 0) { return; } float usualScrapCount = (float)(currentLevel.minScrap + currentLevel.maxScrap - 1) / 2f * __instance.scrapAmountMultiplier; int num = currentLevel.spawnableScrap.Where((SpawnableItemWithRarity e) => ours.All(((SpawnableItemWithRarity entry, ScrapDefinition def) o) => o.entry != e)).Sum((SpawnableItemWithRarity e) => e.rarity) * 100; if (usualScrapCount <= 0f || num <= 0) { return; } Dictionary<SpawnableItemWithRarity, float> dictionary = ours.ToDictionary(((SpawnableItemWithRarity entry, ScrapDefinition def) o) => o.entry, ((SpawnableItemWithRarity entry, ScrapDefinition def) o) => 1f / (o.def.AverageDaysBetween * usualScrapCount)); float num2 = dictionary.Values.Sum(); if (num2 >= 1f) { return; } foreach (SpawnableItemWithRarity item5 in currentLevel.spawnableScrap) { OriginalRarities[item5] = item5.rarity; item5.rarity *= 100; } float num3 = (float)num / (1f - num2); foreach (var item6 in ours) { SpawnableItemWithRarity item = item6.entry; ScrapDefinition item2 = item6.def; item.rarity = Mathf.Max(1, Mathf.RoundToInt(dictionary[item] * num3)); SetValueRange(item2, item2.Item, __instance.scrapValueMultiplier); } int num4 = num + ours.Sum(((SpawnableItemWithRarity entry, ScrapDefinition def) o) => o.entry.rarity); foreach (var item7 in ours) { SpawnableItemWithRarity item3 = item7.entry; ScrapDefinition item4 = item7.def; float num5 = (float)item3.rarity / (float)num4; Plugin.Log.LogInfo((object)($"{currentLevel.PlanetName}: {item4.Name} {100f * num5:0.000}% per scrap, ~{usualScrapCount:0.#} scrap/day " + $"= one every {1f / (num5 * usualScrapCount):0.0} days (target {item4.AverageDaysBetween:0.0}).")); } } private static void Postfix() { RestoreRarities(); } private static void RestoreRarities() { foreach (KeyValuePair<SpawnableItemWithRarity, int> originalRarity in OriginalRarities) { originalRarity.Key.rarity = originalRarity.Value; } OriginalRarities.Clear(); } internal static void SetValueRange(ScrapDefinition def, Item item, float multiplier) { if (!(multiplier <= 0f)) { item.minValue = Mathf.CeilToInt((float)def.MinCredits / multiplier); item.maxValue = Mathf.FloorToInt((float)def.MaxCredits / multiplier) + 1; } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "theOhmbrewer.FriendScrapStatues"; public const string PLUGIN_NAME = "FriendScrapStatues"; public const string PLUGIN_VERSION = "1.0.0"; } }