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 JaundiceJoeScrap v1.0.0
LethalModTemplate.dll
Decompiled 2 months 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.Text; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [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("LethalModTemplate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A starter Lethal Company mod that adds a new scrap item.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalModTemplate")] [assembly: AssemblyTitle("LethalModTemplate")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 LethalModTemplate { [HarmonyPatch] internal static class CustomScrap { private const string DisplayName = "Lucky Cushion"; private const string BaseItemName = "Whoopie cushion"; private const int MinValue = 60; private const int MaxValue = 120; private const int SpawnWeight = 20; private const float WeightKilograms = 0.5f; private static Item _customItem; private static bool _attemptedBuild; [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void OnStartOfRoundAwake(StartOfRound __instance) { if (_attemptedBuild) { return; } _attemptedBuild = true; Item val = __instance.allItemsList?.itemsList?.FirstOrDefault((Func<Item, bool>)((Item i) => (Object)(object)i != (Object)null && i.itemName == "Whoopie cushion")); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogWarning((object)"Couldn't find base item 'Whoopie cushion' to clone. Try a different BaseItemName (check StartOfRound.allItemsList in a logger)."); return; } Item val2 = Object.Instantiate<Item>(val); ((Object)val2).name = "Lucky Cushion"; val2.itemName = "Lucky Cushion"; val2.minValue = 60; val2.maxValue = 120; val2.weight = 1.005f; val2.isScrap = true; val2.canBeGrabbedBeforeGameStart = false; if ((Object)(object)val2.spawnPrefab != (Object)null) { _customItem = val2; __instance.allItemsList.itemsList.Add(val2); Plugin.Logger.LogInfo((object)"Registered custom scrap 'Lucky Cushion' cloned from 'Whoopie cushion'."); } else { Plugin.Logger.LogWarning((object)"Base item 'Whoopie cushion' had no spawnPrefab. Skipping registration."); } } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPrefix] private static void OnGenerateNewLevel(RoundManager __instance) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if (!((Object)(object)_customItem == (Object)null)) { SelectableLevel currentLevel = __instance.currentLevel; if (!((Object)(object)currentLevel == (Object)null) && currentLevel.spawnableScrap != null && !currentLevel.spawnableScrap.Any((SpawnableItemWithRarity s) => (Object)(object)s.spawnableItem == (Object)(object)_customItem)) { currentLevel.spawnableScrap.Add(new SpawnableItemWithRarity(_customItem, 20)); Plugin.Logger.LogInfo((object)string.Format("Added '{0}' to scrap pool on level '{1}' (weight {2}).", "Lucky Cushion", currentLevel.PlanetName, 20)); } } } } [HarmonyPatch] internal static class DevSpawnInputHook { private static int _tick; [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PollDevSpawn() { _tick++; if (_tick % 300 == 0) { Plugin.Logger.LogInfo((object)($"Heartbeat (PlayerControllerB.Update): tick={_tick}, " + $"Keyboard.current={Keyboard.current != null}")); } DevSpawn.CheckInput(); } } internal static class DevSpawn { public static readonly KeyCode SpawnKey = (KeyCode)92; public static readonly Key SpawnKeyNew = (Key)10; private static int _rotationIndex; private static int _lastSpawnFrame = -1; private static bool _wasHeldLastFrame; public static void CheckInput() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) bool flag = false; Keyboard current = Keyboard.current; if (current != null) { flag = ((ButtonControl)current[SpawnKeyNew]).isPressed; } else { try { flag = Input.GetKey(SpawnKey); } catch { } } bool num = flag && !_wasHeldLastFrame; _wasHeldLastFrame = flag; if (!num || Time.frameCount == _lastSpawnFrame) { return; } _lastSpawnFrame = Time.frameCount; Plugin.Logger.LogInfo((object)"DevSpawn: key press detected."); PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogInfo((object)"DevSpawn: no local player (not in-game yet)."); return; } if ((Object)(object)NetworkManager.Singleton == (Object)null || (!NetworkManager.Singleton.IsHost && !NetworkManager.Singleton.IsServer)) { Plugin.Logger.LogInfo((object)"DevSpawn: host-only. Ignoring press."); return; } IReadOnlyList<Item> customItems = PngScrap.CustomItems; if (customItems.Count == 0) { Plugin.Logger.LogInfo((object)"DevSpawn: no custom items registered."); return; } Item item = customItems[_rotationIndex % customItems.Count]; _rotationIndex++; Vector3 position = ((Component)val).transform.position + ((Component)val).transform.forward * 1.5f + Vector3.up * 0.5f; SpawnItem(item, position); } private static void SpawnItem(Item item, Vector3 position) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item.spawnPrefab == (Object)null) { Plugin.Logger.LogWarning((object)("DevSpawn: item '" + item.itemName + "' has no spawnPrefab.")); return; } GameObject obj = Object.Instantiate<GameObject>(item.spawnPrefab, position, Quaternion.identity); obj.SetActive(true); GrabbableObject component = obj.GetComponent<GrabbableObject>(); int num = 0; if ((Object)(object)component != (Object)null) { component.fallTime = 0f; num = (component.scrapValue = Random.Range(item.minValue, item.maxValue + 1)); component.SetScrapValue(num); } NetworkObject component2 = obj.GetComponent<NetworkObject>(); if ((Object)(object)component2 != (Object)null) { component2.Spawn(true); } else { Plugin.Logger.LogWarning((object)("DevSpawn: '" + item.itemName + "' prefab has no NetworkObject. Spawned locally only — won't sync to clients.")); } Plugin.Logger.LogInfo((object)$"DevSpawn: spawned '{item.itemName}' at {position} (value {num})."); } } [BepInPlugin("com.yourname.lethalmodtemplate", "LethalModTemplate", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string ModGuid = "com.yourname.lethalmodtemplate"; public const string ModName = "LethalModTemplate"; public const string ModVersion = "1.0.0"; private readonly Harmony _harmony = new Harmony("com.yourname.lethalmodtemplate"); private int _updateTick; public static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } private void Awake() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"LethalModTemplate v1.0.0 is loading..."); _harmony.PatchAll(typeof(Plugin).Assembly); Logger.LogInfo((object)"LethalModTemplate is loaded! Harmony patches applied."); Logger.LogInfo((object)$"Dev hotkey: press {DevSpawn.SpawnKey} in-game (as host) to spawn custom scrap."); } private void Update() { _updateTick++; if (_updateTick % 300 == 0) { bool flag = Keyboard.current != null; Logger.LogInfo((object)($"Heartbeat: Plugin.Update tick={_updateTick}, " + $"Keyboard.current={flag}")); } DevSpawn.CheckInput(); } } [HarmonyPatch] internal static class PngScrap { private const string BaseItemName = "Large axle"; private const int MinValue = 40; private const int MaxValue = 140; private const int SpawnWeight = 50; private const int SpawnBoost = 5; private const float CardHeightMeters = 1f; private const float CardThicknessMeters = 0.05f; private static readonly List<Item> _customItems = new List<Item>(); private static readonly Dictionary<Item, int> _itemWeights = new Dictionary<Item, int>(); private static bool _builtPrefabs; private static bool _registeredWithItemList; public static IReadOnlyList<Item> CustomItems => _customItems; [HarmonyPatch(typeof(GameNetworkManager), "Start")] [HarmonyPostfix] private static void OnGameNetworkManagerStart(GameNetworkManager __instance) { if (_builtPrefabs) { return; } _builtPrefabs = true; string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { Plugin.Logger.LogWarning((object)"Couldn't locate mod folder; skipping PNG scrap."); return; } string[] files = Directory.GetFiles(directoryName, "*.png", SearchOption.TopDirectoryOnly); Plugin.Logger.LogInfo((object)$"PngScrap: scanned '{directoryName}', found {files.Length} PNG(s)."); if (files.Length == 0) { return; } Item val = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item i) => (Object)(object)i != (Object)null && i.itemName == "Large axle")); if ((Object)(object)val == (Object)null || (Object)(object)val.spawnPrefab == (Object)null) { Plugin.Logger.LogWarning((object)"PngScrap: couldn't find base item 'Large axle' (or it has no prefab). Available item names will be logged at StartOfRound.Awake."); return; } string[] array = files; foreach (string text in array) { try { Item val2 = BuildItemFromPng(val, text); if ((Object)(object)val2 == (Object)null) { continue; } if ((Object)(object)val2.spawnPrefab != (Object)null) { AssignUniqueNetworkHash(val2.spawnPrefab, val2.itemName); if ((Object)(object)NetworkManager.Singleton != (Object)null) { NetworkManager.Singleton.AddNetworkPrefab(val2.spawnPrefab); } } _customItems.Add(val2); Plugin.Logger.LogInfo((object)("PngScrap: built '" + val2.itemName + "' from " + Path.GetFileName(text) + ".")); } catch (Exception arg) { Plugin.Logger.LogError((object)$"PngScrap: failed on {Path.GetFileName(text)}: {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void OnStartOfRoundAwake(StartOfRound __instance) { if (__instance.allItemsList?.itemsList == null) { return; } if (!_registeredWithItemList) { Plugin.Logger.LogInfo((object)"PngScrap: vanilla item names (for reference):"); foreach (Item items in __instance.allItemsList.itemsList) { if ((Object)(object)items != (Object)null) { Plugin.Logger.LogInfo((object)(" - \"" + items.itemName + "\"")); } } } foreach (Item customItem in _customItems) { if (!__instance.allItemsList.itemsList.Contains(customItem)) { __instance.allItemsList.itemsList.Add(customItem); Plugin.Logger.LogInfo((object)("PngScrap: registered '" + customItem.itemName + "' in allItemsList.")); } } _registeredWithItemList = true; } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPrefix] private static void OnGenerateNewLevel(RoundManager __instance) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown if (_customItems.Count == 0) { return; } SelectableLevel currentLevel = __instance.currentLevel; if (currentLevel?.spawnableScrap == null) { return; } foreach (Item item in _customItems) { int value; int num = (_itemWeights.TryGetValue(item, out value) ? value : 50); int num2 = currentLevel.spawnableScrap.Count((SpawnableItemWithRarity s) => (Object)(object)s.spawnableItem == (Object)(object)item); int num3 = 5 - num2; if (num3 > 0) { for (int i = 0; i < num3; i++) { currentLevel.spawnableScrap.Add(new SpawnableItemWithRarity(item, num)); } Plugin.Logger.LogInfo((object)($"PngScrap: added '{item.itemName}' x{num3} (total {num2 + num3}) " + $"to scrap pool on '{currentLevel.PlanetName}' (per-ticket weight {num}, " + $"effective {num * (num2 + num3)}).")); } } } private static Item BuildItemFromPng(Item baseItem, string pngPath) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) byte[] array = File.ReadAllBytes(pngPath); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, array); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Object)val).name = Path.GetFileNameWithoutExtension(pngPath); string text = ResolveDisplayName(pngPath); Item val2 = Object.Instantiate<Item>(baseItem); ((Object)val2).name = text; val2.itemName = text; (int min, int max) tuple = ResolveValueRange(pngPath); int item = tuple.min; int item2 = tuple.max; val2.minValue = item; val2.maxValue = item2; val2.weight = 1f; val2.isScrap = true; val2.canBeGrabbedBeforeGameStart = false; val2.twoHanded = false; val2.twoHandedAnimation = false; val2.rotationOffset = new Vector3(0f, 180f, 0f); val2.restingRotation = Vector3.zero; val2.positionOffset = Vector3.zero; val2.verticalOffset = 0.5f; GameObject val3 = Object.Instantiate<GameObject>(baseItem.spawnPrefab); Object.DontDestroyOnLoad((Object)(object)val3); ((Object)val3).hideFlags = (HideFlags)61; val3.SetActive(false); ((Object)val3).name = text; val3.transform.localScale = Vector3.one; Transform[] componentsInChildren = val3.GetComponentsInChildren<Transform>(true); foreach (Transform val4 in componentsInChildren) { if (!((Object)(object)val4 == (Object)(object)val3.transform)) { val4.localScale = Vector3.one; } } GrabbableObject component = val3.GetComponent<GrabbableObject>(); if ((Object)(object)component != (Object)null) { component.itemProperties = val2; } float num = ((((Texture)val).height > 0) ? ((float)((Texture)val).width / (float)((Texture)val).height) : 1f); float num2 = 1f * num; float num3 = 1f; float num4 = 0.05f; Mesh sharedMesh = BuildFlatCardMesh(num2, num3, num4); StripTemplateVisuals(val3); val3.AddComponent<MeshFilter>().sharedMesh = sharedMesh; ((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterial = CreateCardMaterial(val, text); BoxCollider obj = val3.AddComponent<BoxCollider>(); obj.size = new Vector3(num2, num3, num4); obj.center = Vector3.zero; ((Collider)obj).isTrigger = false; AudioSource val5 = val3.GetComponent<AudioSource>(); if ((Object)(object)val5 == (Object)null) { val5 = val3.AddComponent<AudioSource>(); } val5.playOnAwake = false; val5.loop = false; val5.spatialBlend = 1f; val5.rolloffMode = (AudioRolloffMode)1; val5.minDistance = 2f; val5.maxDistance = 25f; val5.volume = 1f; ScanNodeProperties[] componentsInChildren2 = val3.GetComponentsInChildren<ScanNodeProperties>(true); foreach (ScanNodeProperties obj2 in componentsInChildren2) { obj2.headerText = text; obj2.subText = "Value:"; obj2.scrapValue = 40; obj2.nodeType = 2; } TryLoadSidecarAudio(pngPath, val2); Plugin.Logger.LogInfo((object)("PngScrap: '" + val2.itemName + "' final grabSFX = " + (((Object)(object)val2.grabSFX != (Object)null) ? ("'" + ((Object)val2.grabSFX).name + "'") : "<null>"))); _itemWeights[val2] = ResolveSpawnWeight(pngPath); val2.spawnPrefab = val3; return val2; } private static void TryLoadSidecarAudio(string pngPath, Item item) { string? path = Path.GetDirectoryName(pngPath) ?? string.Empty; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string text = Path.Combine(path, fileNameWithoutExtension + ".wav"); string path2 = Path.Combine(path, fileNameWithoutExtension + ".drop.wav"); if (File.Exists(text)) { AudioClip val = LoadWavFile(text); if ((Object)(object)val != (Object)null) { AssignAllSfxFields(item, val); Plugin.Logger.LogInfo((object)("PngScrap: loaded '" + Path.GetFileName(text) + "' " + $"({val.length:F2}s, {val.frequency}Hz, {val.channels}ch) for '{item.itemName}'.")); } } else { Plugin.Logger.LogInfo((object)("PngScrap: no sidecar WAV for '" + item.itemName + "' (looked for '" + text + "').")); } if (File.Exists(path2)) { AudioClip val2 = LoadWavFile(path2); if ((Object)(object)val2 != (Object)null) { item.dropSFX = val2; Plugin.Logger.LogInfo((object)("PngScrap: overrode drop SFX with '" + Path.GetFileName(path2) + "' for '" + item.itemName + "'.")); } } } private static void AssignAllSfxFields(Item item, AudioClip clip) { if ((Object)(object)item == (Object)null || (Object)(object)clip == (Object)null) { return; } string[] array = new string[1] { "grabSFX" }; foreach (string text in array) { FieldInfo field = typeof(Item).GetField(text, BindingFlags.Instance | BindingFlags.Public); if (field == null) { Plugin.Logger.LogInfo((object)("PngScrap: Item." + text + " not present in this LC version — skipped.")); } else if (!(field.FieldType != typeof(AudioClip))) { field.SetValue(item, clip); Plugin.Logger.LogInfo((object)("PngScrap: Item." + text + " = '" + ((Object)clip).name + "'")); } } array = new string[3] { "dropSFX", "pocketSFX", "throwSFX" }; foreach (string text2 in array) { FieldInfo field2 = typeof(Item).GetField(text2, BindingFlags.Instance | BindingFlags.Public); if (!(field2 == null) && !(field2.FieldType != typeof(AudioClip))) { field2.SetValue(item, null); Plugin.Logger.LogInfo((object)("PngScrap: Item." + text2 + " = <null>")); } } } private static AudioClip LoadWavFile(string path) { byte[] array; try { array = File.ReadAllBytes(path); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("PngScrap: couldn't read " + Path.GetFileName(path) + ": " + ex.Message)); return null; } if (array.Length < 44 || array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70 || array[8] != 87 || array[9] != 65 || array[10] != 86 || array[11] != 69) { Plugin.Logger.LogWarning((object)("PngScrap: " + Path.GetFileName(path) + " is not a valid WAV.")); return null; } int num = 1; int num2 = 44100; int num3 = 16; int num4 = -1; int num5 = 0; bool flag = false; int num6 = 12; while (num6 + 8 <= array.Length) { string @string = Encoding.ASCII.GetString(array, num6, 4); int num7 = BitConverter.ToInt32(array, num6 + 4); int num8 = num6 + 8; if (@string == "fmt ") { int num9 = BitConverter.ToInt16(array, num8); num = BitConverter.ToInt16(array, num8 + 2); num2 = BitConverter.ToInt32(array, num8 + 4); num3 = BitConverter.ToInt16(array, num8 + 14); if (num9 != 1) { Plugin.Logger.LogWarning((object)($"PngScrap: {Path.GetFileName(path)} isn't PCM (format code {num9}). " + "Re-export as 16-bit PCM WAV (Audacity: File > Export > WAV, encoding 'Signed 16-bit PCM').")); return null; } flag = true; } else if (@string == "data") { num4 = num8; num5 = num7; break; } num6 = num8 + num7; if ((num7 & 1) == 1) { num6++; } } if (!flag || num4 < 0) { Plugin.Logger.LogWarning((object)("PngScrap: " + Path.GetFileName(path) + " is missing fmt/data chunks.")); return null; } if (num3 != 16) { Plugin.Logger.LogWarning((object)($"PngScrap: {Path.GetFileName(path)} is {num3}-bit; need 16-bit PCM. " + "Re-export from Audacity as 'Signed 16-bit PCM'.")); return null; } int num10 = num5 / 2; int num11 = num10 / num; float[] array2 = new float[num10]; for (int i = 0; i < num10; i++) { short num12 = BitConverter.ToInt16(array, num4 + i * 2); array2[i] = (float)num12 / 32768f; } AudioClip obj = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num11, num, num2, false); obj.SetData(array2, 0); return obj; } private static void StripTemplateVisuals(GameObject prefab) { MeshFilter[] componentsInChildren = prefab.GetComponentsInChildren<MeshFilter>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } MeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshRenderer>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } SkinnedMeshRenderer[] componentsInChildren3 = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } LODGroup[] componentsInChildren4 = prefab.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } Collider[] componentsInChildren5 = prefab.GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren5) { if (!val.isTrigger) { Object.DestroyImmediate((Object)(object)val); } } } private static Material CreateCardMaterial(Texture2D tex, string itemName) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown Shader val = Shader.Find("HDRP/Lit") ?? Shader.Find("HDRP/Unlit") ?? Shader.Find("Standard") ?? Shader.Find("Sprites/Default"); Material val2 = new Material(val) { name = itemName + "Mat" }; if (val2.HasProperty("_BaseColorMap")) { val2.SetTexture("_BaseColorMap", (Texture)(object)tex); } if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)tex); } val2.mainTexture = (Texture)(object)tex; if (val2.HasProperty("_AlphaCutoffEnable")) { val2.SetFloat("_AlphaCutoffEnable", 1f); } if (val2.HasProperty("_AlphaCutoff")) { val2.SetFloat("_AlphaCutoff", 0.5f); } val2.EnableKeyword("_ALPHATEST_ON"); Plugin.Logger.LogInfo((object)("PngScrap: created material for '" + itemName + "' using shader '" + (((val != null) ? ((Object)val).name : null) ?? "<null>") + "'.")); return val2; } private static Mesh BuildFlatCardMesh(float w, float h, float d) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_022d: 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_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Expected O, but got Unknown float num = w * 0.5f; float num2 = h * 0.5f; float num3 = d * 0.5f; Vector3[] vertices = (Vector3[])(object)new Vector3[24] { new Vector3(0f - num, 0f - num2, num3), new Vector3(num, 0f - num2, num3), new Vector3(num, num2, num3), new Vector3(0f - num, num2, num3), new Vector3(num, 0f - num2, 0f - num3), new Vector3(0f - num, 0f - num2, 0f - num3), new Vector3(0f - num, num2, 0f - num3), new Vector3(num, num2, 0f - num3), new Vector3(0f - num, num2, num3), new Vector3(num, num2, num3), new Vector3(num, num2, 0f - num3), new Vector3(0f - num, num2, 0f - num3), new Vector3(num, 0f - num2, num3), new Vector3(0f - num, 0f - num2, num3), new Vector3(0f - num, 0f - num2, 0f - num3), new Vector3(num, 0f - num2, 0f - num3), new Vector3(num, 0f - num2, num3), new Vector3(num, 0f - num2, 0f - num3), new Vector3(num, num2, 0f - num3), new Vector3(num, num2, num3), new Vector3(0f - num, 0f - num2, 0f - num3), new Vector3(0f - num, 0f - num2, num3), new Vector3(0f - num, num2, num3), new Vector3(0f - num, num2, 0f - num3) }; Vector2[] array = (Vector2[])(object)new Vector2[24] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2) }; for (int i = 8; i < 24; i++) { array[i] = new Vector2(0.5f, 0.5f); } int[] array2 = new int[36]; int num4 = 0; for (int j = 0; j < 6; j++) { int num5 = j * 4; array2[num4++] = num5; array2[num4++] = num5 + 2; array2[num4++] = num5 + 1; array2[num4++] = num5; array2[num4++] = num5 + 3; array2[num4++] = num5 + 2; } Mesh val = new Mesh { name = "PngCardMesh", vertices = vertices, uv = array, triangles = array2 }; val.RecalculateNormals(); val.RecalculateTangents(); val.RecalculateBounds(); return val; } private static void AssignUniqueNetworkHash(GameObject prefab, string itemName) { NetworkObject component = prefab.GetComponent<NetworkObject>(); if (!((Object)(object)component == (Object)null)) { uint num = 2166136261u; string text = "LethalModTemplate.PngScrap:" + itemName; foreach (char c in text) { num ^= c; num *= 16777619; } if (num == 0) { num = 1u; } FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(component, num); Plugin.Logger.LogInfo((object)$"PngScrap: set GlobalObjectIdHash={num} for '{itemName}'."); } else { Plugin.Logger.LogWarning((object)"PngScrap: couldn't find NetworkObject.GlobalObjectIdHash field via reflection. Multiplayer may be unstable."); } } } private static string ResolveDisplayName(string pngPath) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string path = Path.Combine(Path.GetDirectoryName(pngPath) ?? string.Empty, fileNameWithoutExtension + ".txt"); if (File.Exists(path)) { string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { Plugin.Logger.LogInfo((object)("PngScrap: using sidecar name '" + text + "' from " + Path.GetFileName(path) + ".")); return text; } } } return PrettifyFileName(fileNameWithoutExtension); } private static int ResolveSpawnWeight(string pngPath) { string? path = Path.GetDirectoryName(pngPath) ?? string.Empty; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string path2 = Path.Combine(path, fileNameWithoutExtension + ".weight.txt"); if (!File.Exists(path2)) { return 50; } string[] array = File.ReadAllLines(path2); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { if (int.TryParse(text, out var result) && result > 0) { Plugin.Logger.LogInfo((object)$"PngScrap: weight={result} for '{fileNameWithoutExtension}' from {Path.GetFileName(path2)}."); return result; } Plugin.Logger.LogWarning((object)("PngScrap: couldn't parse '" + text + "' in " + Path.GetFileName(path2) + " as an int — " + $"using default {50}.")); break; } } return 50; } private static (int min, int max) ResolveValueRange(string pngPath) { string? path = Path.GetDirectoryName(pngPath) ?? string.Empty; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string path2 = Path.Combine(path, fileNameWithoutExtension + ".value.txt"); if (!File.Exists(path2)) { return (40, 140); } string[] array = File.ReadAllLines(path2); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { string[] array2 = text.Split('-'); if (array2.Length == 2 && int.TryParse(array2[0].Trim(), out var result) && int.TryParse(array2[1].Trim(), out var result2) && result >= 0 && result2 >= result) { Plugin.Logger.LogInfo((object)$"PngScrap: value={result}-{result2} for '{fileNameWithoutExtension}' from {Path.GetFileName(path2)}."); return (result, result2); } Plugin.Logger.LogWarning((object)("PngScrap: couldn't parse '" + text + "' in " + Path.GetFileName(path2) + " (need 'MIN-MAX') — " + $"using default {40}-{140}.")); break; } } return (40, 140); } private static string PrettifyFileName(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return "Mystery Photo"; } string text = raw.Replace('_', ' ').Replace('-', ' ').Trim(); if (text.Length == 0) { return "Mystery Photo"; } string[] array = text.Split(' '); for (int i = 0; i < array.Length; i++) { if (array[i].Length > 0) { array[i] = char.ToUpper(array[i][0]) + array[i].Substring(1); } } return string.Join(" ", array); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "LethalModTemplate"; public const string PLUGIN_NAME = "LethalModTemplate"; public const string PLUGIN_VERSION = "1.0.0"; } }
JaundiceJoeItem/LethalModTemplate.dll
Decompiled 2 months 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.Text; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [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("LethalModTemplate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A starter Lethal Company mod that adds a new scrap item.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalModTemplate")] [assembly: AssemblyTitle("LethalModTemplate")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 LethalModTemplate { [HarmonyPatch] internal static class CustomScrap { private const string DisplayName = "Lucky Cushion"; private const string BaseItemName = "Whoopie cushion"; private const int MinValue = 60; private const int MaxValue = 120; private const int SpawnWeight = 20; private const float WeightKilograms = 0.5f; private static Item _customItem; private static bool _attemptedBuild; [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void OnStartOfRoundAwake(StartOfRound __instance) { if (_attemptedBuild) { return; } _attemptedBuild = true; Item val = __instance.allItemsList?.itemsList?.FirstOrDefault((Func<Item, bool>)((Item i) => (Object)(object)i != (Object)null && i.itemName == "Whoopie cushion")); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogWarning((object)"Couldn't find base item 'Whoopie cushion' to clone. Try a different BaseItemName (check StartOfRound.allItemsList in a logger)."); return; } Item val2 = Object.Instantiate<Item>(val); ((Object)val2).name = "Lucky Cushion"; val2.itemName = "Lucky Cushion"; val2.minValue = 60; val2.maxValue = 120; val2.weight = 1.005f; val2.isScrap = true; val2.canBeGrabbedBeforeGameStart = false; if ((Object)(object)val2.spawnPrefab != (Object)null) { _customItem = val2; __instance.allItemsList.itemsList.Add(val2); Plugin.Logger.LogInfo((object)"Registered custom scrap 'Lucky Cushion' cloned from 'Whoopie cushion'."); } else { Plugin.Logger.LogWarning((object)"Base item 'Whoopie cushion' had no spawnPrefab. Skipping registration."); } } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPrefix] private static void OnGenerateNewLevel(RoundManager __instance) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if (!((Object)(object)_customItem == (Object)null)) { SelectableLevel currentLevel = __instance.currentLevel; if (!((Object)(object)currentLevel == (Object)null) && currentLevel.spawnableScrap != null && !currentLevel.spawnableScrap.Any((SpawnableItemWithRarity s) => (Object)(object)s.spawnableItem == (Object)(object)_customItem)) { currentLevel.spawnableScrap.Add(new SpawnableItemWithRarity(_customItem, 20)); Plugin.Logger.LogInfo((object)string.Format("Added '{0}' to scrap pool on level '{1}' (weight {2}).", "Lucky Cushion", currentLevel.PlanetName, 20)); } } } } [HarmonyPatch] internal static class DevSpawnInputHook { private static int _tick; [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PollDevSpawn() { _tick++; if (_tick % 300 == 0) { Plugin.Logger.LogInfo((object)($"Heartbeat (PlayerControllerB.Update): tick={_tick}, " + $"Keyboard.current={Keyboard.current != null}")); } DevSpawn.CheckInput(); } } internal static class DevSpawn { public static readonly KeyCode SpawnKey = (KeyCode)92; public static readonly Key SpawnKeyNew = (Key)10; private static int _rotationIndex; private static int _lastSpawnFrame = -1; private static bool _wasHeldLastFrame; public static void CheckInput() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) bool flag = false; Keyboard current = Keyboard.current; if (current != null) { flag = ((ButtonControl)current[SpawnKeyNew]).isPressed; } else { try { flag = Input.GetKey(SpawnKey); } catch { } } bool num = flag && !_wasHeldLastFrame; _wasHeldLastFrame = flag; if (!num || Time.frameCount == _lastSpawnFrame) { return; } _lastSpawnFrame = Time.frameCount; Plugin.Logger.LogInfo((object)"DevSpawn: key press detected."); PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogInfo((object)"DevSpawn: no local player (not in-game yet)."); return; } if ((Object)(object)NetworkManager.Singleton == (Object)null || (!NetworkManager.Singleton.IsHost && !NetworkManager.Singleton.IsServer)) { Plugin.Logger.LogInfo((object)"DevSpawn: host-only. Ignoring press."); return; } IReadOnlyList<Item> customItems = PngScrap.CustomItems; if (customItems.Count == 0) { Plugin.Logger.LogInfo((object)"DevSpawn: no custom items registered."); return; } Item item = customItems[_rotationIndex % customItems.Count]; _rotationIndex++; Vector3 position = ((Component)val).transform.position + ((Component)val).transform.forward * 1.5f + Vector3.up * 0.5f; SpawnItem(item, position); } private static void SpawnItem(Item item, Vector3 position) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item.spawnPrefab == (Object)null) { Plugin.Logger.LogWarning((object)("DevSpawn: item '" + item.itemName + "' has no spawnPrefab.")); return; } GameObject obj = Object.Instantiate<GameObject>(item.spawnPrefab, position, Quaternion.identity); obj.SetActive(true); GrabbableObject component = obj.GetComponent<GrabbableObject>(); int num = 0; if ((Object)(object)component != (Object)null) { component.fallTime = 0f; num = (component.scrapValue = Random.Range(item.minValue, item.maxValue + 1)); component.SetScrapValue(num); } NetworkObject component2 = obj.GetComponent<NetworkObject>(); if ((Object)(object)component2 != (Object)null) { component2.Spawn(true); } else { Plugin.Logger.LogWarning((object)("DevSpawn: '" + item.itemName + "' prefab has no NetworkObject. Spawned locally only — won't sync to clients.")); } Plugin.Logger.LogInfo((object)$"DevSpawn: spawned '{item.itemName}' at {position} (value {num})."); } } [BepInPlugin("com.yourname.lethalmodtemplate", "LethalModTemplate", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string ModGuid = "com.yourname.lethalmodtemplate"; public const string ModName = "LethalModTemplate"; public const string ModVersion = "1.0.0"; private readonly Harmony _harmony = new Harmony("com.yourname.lethalmodtemplate"); private int _updateTick; public static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } private void Awake() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"LethalModTemplate v1.0.0 is loading..."); _harmony.PatchAll(typeof(Plugin).Assembly); Logger.LogInfo((object)"LethalModTemplate is loaded! Harmony patches applied."); Logger.LogInfo((object)$"Dev hotkey: press {DevSpawn.SpawnKey} in-game (as host) to spawn custom scrap."); } private void Update() { _updateTick++; if (_updateTick % 300 == 0) { bool flag = Keyboard.current != null; Logger.LogInfo((object)($"Heartbeat: Plugin.Update tick={_updateTick}, " + $"Keyboard.current={flag}")); } DevSpawn.CheckInput(); } } [HarmonyPatch] internal static class PngScrap { private const string BaseItemName = "Large axle"; private const int MinValue = 40; private const int MaxValue = 140; private const int SpawnWeight = 50; private const int SpawnBoost = 5; private const float CardHeightMeters = 1f; private const float CardThicknessMeters = 0.05f; private static readonly List<Item> _customItems = new List<Item>(); private static readonly Dictionary<Item, int> _itemWeights = new Dictionary<Item, int>(); private static bool _builtPrefabs; private static bool _registeredWithItemList; public static IReadOnlyList<Item> CustomItems => _customItems; [HarmonyPatch(typeof(GameNetworkManager), "Start")] [HarmonyPostfix] private static void OnGameNetworkManagerStart(GameNetworkManager __instance) { if (_builtPrefabs) { return; } _builtPrefabs = true; string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { Plugin.Logger.LogWarning((object)"Couldn't locate mod folder; skipping PNG scrap."); return; } string[] files = Directory.GetFiles(directoryName, "*.png", SearchOption.TopDirectoryOnly); Plugin.Logger.LogInfo((object)$"PngScrap: scanned '{directoryName}', found {files.Length} PNG(s)."); if (files.Length == 0) { return; } Item val = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item i) => (Object)(object)i != (Object)null && i.itemName == "Large axle")); if ((Object)(object)val == (Object)null || (Object)(object)val.spawnPrefab == (Object)null) { Plugin.Logger.LogWarning((object)"PngScrap: couldn't find base item 'Large axle' (or it has no prefab). Available item names will be logged at StartOfRound.Awake."); return; } string[] array = files; foreach (string text in array) { try { Item val2 = BuildItemFromPng(val, text); if ((Object)(object)val2 == (Object)null) { continue; } if ((Object)(object)val2.spawnPrefab != (Object)null) { AssignUniqueNetworkHash(val2.spawnPrefab, val2.itemName); if ((Object)(object)NetworkManager.Singleton != (Object)null) { NetworkManager.Singleton.AddNetworkPrefab(val2.spawnPrefab); } } _customItems.Add(val2); Plugin.Logger.LogInfo((object)("PngScrap: built '" + val2.itemName + "' from " + Path.GetFileName(text) + ".")); } catch (Exception arg) { Plugin.Logger.LogError((object)$"PngScrap: failed on {Path.GetFileName(text)}: {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void OnStartOfRoundAwake(StartOfRound __instance) { if (__instance.allItemsList?.itemsList == null) { return; } if (!_registeredWithItemList) { Plugin.Logger.LogInfo((object)"PngScrap: vanilla item names (for reference):"); foreach (Item items in __instance.allItemsList.itemsList) { if ((Object)(object)items != (Object)null) { Plugin.Logger.LogInfo((object)(" - \"" + items.itemName + "\"")); } } } foreach (Item customItem in _customItems) { if (!__instance.allItemsList.itemsList.Contains(customItem)) { __instance.allItemsList.itemsList.Add(customItem); Plugin.Logger.LogInfo((object)("PngScrap: registered '" + customItem.itemName + "' in allItemsList.")); } } _registeredWithItemList = true; } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPrefix] private static void OnGenerateNewLevel(RoundManager __instance) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown if (_customItems.Count == 0) { return; } SelectableLevel currentLevel = __instance.currentLevel; if (currentLevel?.spawnableScrap == null) { return; } foreach (Item item in _customItems) { int value; int num = (_itemWeights.TryGetValue(item, out value) ? value : 50); int num2 = currentLevel.spawnableScrap.Count((SpawnableItemWithRarity s) => (Object)(object)s.spawnableItem == (Object)(object)item); int num3 = 5 - num2; if (num3 > 0) { for (int i = 0; i < num3; i++) { currentLevel.spawnableScrap.Add(new SpawnableItemWithRarity(item, num)); } Plugin.Logger.LogInfo((object)($"PngScrap: added '{item.itemName}' x{num3} (total {num2 + num3}) " + $"to scrap pool on '{currentLevel.PlanetName}' (per-ticket weight {num}, " + $"effective {num * (num2 + num3)}).")); } } } private static Item BuildItemFromPng(Item baseItem, string pngPath) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) byte[] array = File.ReadAllBytes(pngPath); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, array); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Object)val).name = Path.GetFileNameWithoutExtension(pngPath); string text = ResolveDisplayName(pngPath); Item val2 = Object.Instantiate<Item>(baseItem); ((Object)val2).name = text; val2.itemName = text; (int min, int max) tuple = ResolveValueRange(pngPath); int item = tuple.min; int item2 = tuple.max; val2.minValue = item; val2.maxValue = item2; val2.weight = 1f; val2.isScrap = true; val2.canBeGrabbedBeforeGameStart = false; val2.twoHanded = false; val2.twoHandedAnimation = false; val2.rotationOffset = new Vector3(0f, 180f, 0f); val2.restingRotation = Vector3.zero; val2.positionOffset = Vector3.zero; val2.verticalOffset = 0.5f; GameObject val3 = Object.Instantiate<GameObject>(baseItem.spawnPrefab); Object.DontDestroyOnLoad((Object)(object)val3); ((Object)val3).hideFlags = (HideFlags)61; val3.SetActive(false); ((Object)val3).name = text; val3.transform.localScale = Vector3.one; Transform[] componentsInChildren = val3.GetComponentsInChildren<Transform>(true); foreach (Transform val4 in componentsInChildren) { if (!((Object)(object)val4 == (Object)(object)val3.transform)) { val4.localScale = Vector3.one; } } GrabbableObject component = val3.GetComponent<GrabbableObject>(); if ((Object)(object)component != (Object)null) { component.itemProperties = val2; } float num = ((((Texture)val).height > 0) ? ((float)((Texture)val).width / (float)((Texture)val).height) : 1f); float num2 = 1f * num; float num3 = 1f; float num4 = 0.05f; Mesh sharedMesh = BuildFlatCardMesh(num2, num3, num4); StripTemplateVisuals(val3); val3.AddComponent<MeshFilter>().sharedMesh = sharedMesh; ((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterial = CreateCardMaterial(val, text); BoxCollider obj = val3.AddComponent<BoxCollider>(); obj.size = new Vector3(num2, num3, num4); obj.center = Vector3.zero; ((Collider)obj).isTrigger = false; AudioSource val5 = val3.GetComponent<AudioSource>(); if ((Object)(object)val5 == (Object)null) { val5 = val3.AddComponent<AudioSource>(); } val5.playOnAwake = false; val5.loop = false; val5.spatialBlend = 1f; val5.rolloffMode = (AudioRolloffMode)1; val5.minDistance = 2f; val5.maxDistance = 25f; val5.volume = 1f; ScanNodeProperties[] componentsInChildren2 = val3.GetComponentsInChildren<ScanNodeProperties>(true); foreach (ScanNodeProperties obj2 in componentsInChildren2) { obj2.headerText = text; obj2.subText = "Value:"; obj2.scrapValue = 40; obj2.nodeType = 2; } TryLoadSidecarAudio(pngPath, val2); Plugin.Logger.LogInfo((object)("PngScrap: '" + val2.itemName + "' final grabSFX = " + (((Object)(object)val2.grabSFX != (Object)null) ? ("'" + ((Object)val2.grabSFX).name + "'") : "<null>"))); _itemWeights[val2] = ResolveSpawnWeight(pngPath); val2.spawnPrefab = val3; return val2; } private static void TryLoadSidecarAudio(string pngPath, Item item) { string? path = Path.GetDirectoryName(pngPath) ?? string.Empty; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string text = Path.Combine(path, fileNameWithoutExtension + ".wav"); string path2 = Path.Combine(path, fileNameWithoutExtension + ".drop.wav"); if (File.Exists(text)) { AudioClip val = LoadWavFile(text); if ((Object)(object)val != (Object)null) { AssignAllSfxFields(item, val); Plugin.Logger.LogInfo((object)("PngScrap: loaded '" + Path.GetFileName(text) + "' " + $"({val.length:F2}s, {val.frequency}Hz, {val.channels}ch) for '{item.itemName}'.")); } } else { Plugin.Logger.LogInfo((object)("PngScrap: no sidecar WAV for '" + item.itemName + "' (looked for '" + text + "').")); } if (File.Exists(path2)) { AudioClip val2 = LoadWavFile(path2); if ((Object)(object)val2 != (Object)null) { item.dropSFX = val2; Plugin.Logger.LogInfo((object)("PngScrap: overrode drop SFX with '" + Path.GetFileName(path2) + "' for '" + item.itemName + "'.")); } } } private static void AssignAllSfxFields(Item item, AudioClip clip) { if ((Object)(object)item == (Object)null || (Object)(object)clip == (Object)null) { return; } string[] array = new string[1] { "grabSFX" }; foreach (string text in array) { FieldInfo field = typeof(Item).GetField(text, BindingFlags.Instance | BindingFlags.Public); if (field == null) { Plugin.Logger.LogInfo((object)("PngScrap: Item." + text + " not present in this LC version — skipped.")); } else if (!(field.FieldType != typeof(AudioClip))) { field.SetValue(item, clip); Plugin.Logger.LogInfo((object)("PngScrap: Item." + text + " = '" + ((Object)clip).name + "'")); } } array = new string[3] { "dropSFX", "pocketSFX", "throwSFX" }; foreach (string text2 in array) { FieldInfo field2 = typeof(Item).GetField(text2, BindingFlags.Instance | BindingFlags.Public); if (!(field2 == null) && !(field2.FieldType != typeof(AudioClip))) { field2.SetValue(item, null); Plugin.Logger.LogInfo((object)("PngScrap: Item." + text2 + " = <null>")); } } } private static AudioClip LoadWavFile(string path) { byte[] array; try { array = File.ReadAllBytes(path); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("PngScrap: couldn't read " + Path.GetFileName(path) + ": " + ex.Message)); return null; } if (array.Length < 44 || array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70 || array[8] != 87 || array[9] != 65 || array[10] != 86 || array[11] != 69) { Plugin.Logger.LogWarning((object)("PngScrap: " + Path.GetFileName(path) + " is not a valid WAV.")); return null; } int num = 1; int num2 = 44100; int num3 = 16; int num4 = -1; int num5 = 0; bool flag = false; int num6 = 12; while (num6 + 8 <= array.Length) { string @string = Encoding.ASCII.GetString(array, num6, 4); int num7 = BitConverter.ToInt32(array, num6 + 4); int num8 = num6 + 8; if (@string == "fmt ") { int num9 = BitConverter.ToInt16(array, num8); num = BitConverter.ToInt16(array, num8 + 2); num2 = BitConverter.ToInt32(array, num8 + 4); num3 = BitConverter.ToInt16(array, num8 + 14); if (num9 != 1) { Plugin.Logger.LogWarning((object)($"PngScrap: {Path.GetFileName(path)} isn't PCM (format code {num9}). " + "Re-export as 16-bit PCM WAV (Audacity: File > Export > WAV, encoding 'Signed 16-bit PCM').")); return null; } flag = true; } else if (@string == "data") { num4 = num8; num5 = num7; break; } num6 = num8 + num7; if ((num7 & 1) == 1) { num6++; } } if (!flag || num4 < 0) { Plugin.Logger.LogWarning((object)("PngScrap: " + Path.GetFileName(path) + " is missing fmt/data chunks.")); return null; } if (num3 != 16) { Plugin.Logger.LogWarning((object)($"PngScrap: {Path.GetFileName(path)} is {num3}-bit; need 16-bit PCM. " + "Re-export from Audacity as 'Signed 16-bit PCM'.")); return null; } int num10 = num5 / 2; int num11 = num10 / num; float[] array2 = new float[num10]; for (int i = 0; i < num10; i++) { short num12 = BitConverter.ToInt16(array, num4 + i * 2); array2[i] = (float)num12 / 32768f; } AudioClip obj = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num11, num, num2, false); obj.SetData(array2, 0); return obj; } private static void StripTemplateVisuals(GameObject prefab) { MeshFilter[] componentsInChildren = prefab.GetComponentsInChildren<MeshFilter>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } MeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshRenderer>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } SkinnedMeshRenderer[] componentsInChildren3 = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } LODGroup[] componentsInChildren4 = prefab.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } Collider[] componentsInChildren5 = prefab.GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren5) { if (!val.isTrigger) { Object.DestroyImmediate((Object)(object)val); } } } private static Material CreateCardMaterial(Texture2D tex, string itemName) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown Shader val = Shader.Find("HDRP/Lit") ?? Shader.Find("HDRP/Unlit") ?? Shader.Find("Standard") ?? Shader.Find("Sprites/Default"); Material val2 = new Material(val) { name = itemName + "Mat" }; if (val2.HasProperty("_BaseColorMap")) { val2.SetTexture("_BaseColorMap", (Texture)(object)tex); } if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)tex); } val2.mainTexture = (Texture)(object)tex; if (val2.HasProperty("_AlphaCutoffEnable")) { val2.SetFloat("_AlphaCutoffEnable", 1f); } if (val2.HasProperty("_AlphaCutoff")) { val2.SetFloat("_AlphaCutoff", 0.5f); } val2.EnableKeyword("_ALPHATEST_ON"); Plugin.Logger.LogInfo((object)("PngScrap: created material for '" + itemName + "' using shader '" + (((val != null) ? ((Object)val).name : null) ?? "<null>") + "'.")); return val2; } private static Mesh BuildFlatCardMesh(float w, float h, float d) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_022d: 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_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Expected O, but got Unknown float num = w * 0.5f; float num2 = h * 0.5f; float num3 = d * 0.5f; Vector3[] vertices = (Vector3[])(object)new Vector3[24] { new Vector3(0f - num, 0f - num2, num3), new Vector3(num, 0f - num2, num3), new Vector3(num, num2, num3), new Vector3(0f - num, num2, num3), new Vector3(num, 0f - num2, 0f - num3), new Vector3(0f - num, 0f - num2, 0f - num3), new Vector3(0f - num, num2, 0f - num3), new Vector3(num, num2, 0f - num3), new Vector3(0f - num, num2, num3), new Vector3(num, num2, num3), new Vector3(num, num2, 0f - num3), new Vector3(0f - num, num2, 0f - num3), new Vector3(num, 0f - num2, num3), new Vector3(0f - num, 0f - num2, num3), new Vector3(0f - num, 0f - num2, 0f - num3), new Vector3(num, 0f - num2, 0f - num3), new Vector3(num, 0f - num2, num3), new Vector3(num, 0f - num2, 0f - num3), new Vector3(num, num2, 0f - num3), new Vector3(num, num2, num3), new Vector3(0f - num, 0f - num2, 0f - num3), new Vector3(0f - num, 0f - num2, num3), new Vector3(0f - num, num2, num3), new Vector3(0f - num, num2, 0f - num3) }; Vector2[] array = (Vector2[])(object)new Vector2[24] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2), default(Vector2) }; for (int i = 8; i < 24; i++) { array[i] = new Vector2(0.5f, 0.5f); } int[] array2 = new int[36]; int num4 = 0; for (int j = 0; j < 6; j++) { int num5 = j * 4; array2[num4++] = num5; array2[num4++] = num5 + 2; array2[num4++] = num5 + 1; array2[num4++] = num5; array2[num4++] = num5 + 3; array2[num4++] = num5 + 2; } Mesh val = new Mesh { name = "PngCardMesh", vertices = vertices, uv = array, triangles = array2 }; val.RecalculateNormals(); val.RecalculateTangents(); val.RecalculateBounds(); return val; } private static void AssignUniqueNetworkHash(GameObject prefab, string itemName) { NetworkObject component = prefab.GetComponent<NetworkObject>(); if (!((Object)(object)component == (Object)null)) { uint num = 2166136261u; string text = "LethalModTemplate.PngScrap:" + itemName; foreach (char c in text) { num ^= c; num *= 16777619; } if (num == 0) { num = 1u; } FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(component, num); Plugin.Logger.LogInfo((object)$"PngScrap: set GlobalObjectIdHash={num} for '{itemName}'."); } else { Plugin.Logger.LogWarning((object)"PngScrap: couldn't find NetworkObject.GlobalObjectIdHash field via reflection. Multiplayer may be unstable."); } } } private static string ResolveDisplayName(string pngPath) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string path = Path.Combine(Path.GetDirectoryName(pngPath) ?? string.Empty, fileNameWithoutExtension + ".txt"); if (File.Exists(path)) { string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { Plugin.Logger.LogInfo((object)("PngScrap: using sidecar name '" + text + "' from " + Path.GetFileName(path) + ".")); return text; } } } return PrettifyFileName(fileNameWithoutExtension); } private static int ResolveSpawnWeight(string pngPath) { string? path = Path.GetDirectoryName(pngPath) ?? string.Empty; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string path2 = Path.Combine(path, fileNameWithoutExtension + ".weight.txt"); if (!File.Exists(path2)) { return 50; } string[] array = File.ReadAllLines(path2); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { if (int.TryParse(text, out var result) && result > 0) { Plugin.Logger.LogInfo((object)$"PngScrap: weight={result} for '{fileNameWithoutExtension}' from {Path.GetFileName(path2)}."); return result; } Plugin.Logger.LogWarning((object)("PngScrap: couldn't parse '" + text + "' in " + Path.GetFileName(path2) + " as an int — " + $"using default {50}.")); break; } } return 50; } private static (int min, int max) ResolveValueRange(string pngPath) { string? path = Path.GetDirectoryName(pngPath) ?? string.Empty; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string path2 = Path.Combine(path, fileNameWithoutExtension + ".value.txt"); if (!File.Exists(path2)) { return (40, 140); } string[] array = File.ReadAllLines(path2); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { string[] array2 = text.Split('-'); if (array2.Length == 2 && int.TryParse(array2[0].Trim(), out var result) && int.TryParse(array2[1].Trim(), out var result2) && result >= 0 && result2 >= result) { Plugin.Logger.LogInfo((object)$"PngScrap: value={result}-{result2} for '{fileNameWithoutExtension}' from {Path.GetFileName(path2)}."); return (result, result2); } Plugin.Logger.LogWarning((object)("PngScrap: couldn't parse '" + text + "' in " + Path.GetFileName(path2) + " (need 'MIN-MAX') — " + $"using default {40}-{140}.")); break; } } return (40, 140); } private static string PrettifyFileName(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return "Mystery Photo"; } string text = raw.Replace('_', ' ').Replace('-', ' ').Trim(); if (text.Length == 0) { return "Mystery Photo"; } string[] array = text.Split(' '); for (int i = 0; i < array.Length; i++) { if (array[i].Length > 0) { array[i] = char.ToUpper(array[i][0]) + array[i].Substring(1); } } return string.Join(" ", array); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "LethalModTemplate"; public const string PLUGIN_NAME = "LethalModTemplate"; public const string PLUGIN_VERSION = "1.0.0"; } }