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 WearableTorches v1.0.5
WearableTorches.dll
Decompiled 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("WearableTorches")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("WearableTorches")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("a614924a-5167-4a9b-96b5-859ddb3331ad")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace WearableTorches; [BepInPlugin("com.thomas.wearabletorches", "Wearable Torches", "1.0.6")] public class WearableTorchesPlugin : BaseUnityPlugin { internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("com.thomas.wearabletorches"); _harmony.PatchAll(); Log.LogInfo((object)"Wearable Torches loaded (G key, torch required in hand)"); } private void Update() { if (ZInput.instance == null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { WearableTorchManager.HandleLocalInput(localPlayer); } foreach (Player allPlayer in Player.GetAllPlayers()) { WearableTorchManager.SyncBackTorchForPlayer(allPlayer); } } private void OnDestroy() { WearableTorchManager.ForceDestroyBackTorch(); } } public static class WearableTorchManager { private static readonly Dictionary<long, GameObject> BackTorches = new Dictionary<long, GameObject>(); public const string ZdoKeyBackTorch = "WearableTorches_BackTorch"; public const string ZdoKeyBackTorchPrefab = "WearableTorches_BackTorchPrefab"; private static readonly Vector3 FlameOffset = new Vector3(0f, 0f, 0.61f); private static readonly Vector3 LightOffset = new Vector3(0f, 0f, 0.61f); private static readonly Quaternion BackRotationOffset = Quaternion.Euler(-80f, 0f, 0f); private static long GetPlayerKey(Player player) { if ((Object)(object)player == (Object)null) { return 0L; } return player.GetPlayerID(); } private static GameObject FindExistingBackTorchObject(Player player) { if ((Object)(object)player == (Object)null) { return null; } Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == "BackTorchObject") { return ((Component)val).gameObject; } } return null; } public static void HandleLocalInput(Player player) { ZNetView nView = GetNView(player); if ((Object)(object)nView == (Object)null || !nView.IsOwner() || !ZInput.GetKeyDown((KeyCode)103, true)) { return; } ZDO zDO = nView.GetZDO(); if (zDO == null) { return; } if (!zDO.GetBool("WearableTorches_BackTorch", false)) { ItemData torchInHands = GetTorchInHands(player); if (torchInHands == null) { WearableTorchesPlugin.Log.LogInfo((object)("Back torch: no torch in hand, toggle ignored for " + player.GetPlayerName())); return; } GameObject dropPrefab = torchInHands.m_dropPrefab; if ((Object)(object)dropPrefab == (Object)null) { WearableTorchesPlugin.Log.LogWarning((object)("Back torch: torch in hand has no dropPrefab for " + player.GetPlayerName())); return; } string name = ((Object)dropPrefab).name; if (!string.IsNullOrEmpty(name)) { zDO.Set("WearableTorches_BackTorchPrefab", name); zDO.Set("WearableTorches_BackTorch", true); HideVanillaTorchVisuals(player, hide: true); WearableTorchesPlugin.Log.LogInfo((object)("Back torch ON (G key, from hand) for " + player.GetPlayerName() + " prefab=" + name)); } } else { zDO.Set("WearableTorches_BackTorch", false); zDO.Set("WearableTorches_BackTorchPrefab", ""); HideVanillaTorchVisuals(player, hide: false); WearableTorchesPlugin.Log.LogInfo((object)("Back torch OFF (G key) for " + player.GetPlayerName())); } } public static void SyncBackTorchForPlayer(Player player) { if ((Object)(object)player == (Object)null) { return; } ZNetView nView = GetNView(player); if ((Object)(object)nView == (Object)null) { return; } ZDO zDO = nView.GetZDO(); if (zDO == null) { return; } bool @bool = zDO.GetBool("WearableTorches_BackTorch", false); string @string = zDO.GetString("WearableTorches_BackTorchPrefab", ""); long playerKey = GetPlayerKey(player); if (playerKey == 0L) { return; } BackTorches.TryGetValue(playerKey, out var value); if (@bool && !string.IsNullOrEmpty(@string)) { if ((Object)(object)value != (Object)null) { return; } GameObject val = FindExistingBackTorchObject(player); if ((Object)(object)val != (Object)null) { BackTorches[playerKey] = val; return; } GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(@string) : null); if ((Object)(object)val2 == (Object)null) { WearableTorchesPlugin.Log.LogWarning((object)("Back torch: prefab '" + @string + "' not found in ZNetScene")); return; } GameObject val3 = CreateBackTorchVisual(player, val2); if ((Object)(object)val3 != (Object)null) { BackTorches[playerKey] = val3; } } else if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); BackTorches.Remove(playerKey); } else { GameObject val4 = FindExistingBackTorchObject(player); if ((Object)(object)val4 != (Object)null) { Object.Destroy((Object)(object)val4); } } } private static ZNetView GetNView(Player player) { if (!((Object)(object)player != (Object)null)) { return null; } return ((Component)player).GetComponent<ZNetView>(); } internal static bool IsTorch(ItemData item) { if (item == null) { return false; } return ((item.m_shared != null) ? item.m_shared.m_name : "").ToLower().Contains("torch"); } private static ItemData GetTorchInHands(Player player) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo method = typeof(Player).GetMethod("GetRightItem", BindingFlags.Instance | BindingFlags.NonPublic); MethodInfo method2 = typeof(Player).GetMethod("GetLeftItem", BindingFlags.Instance | BindingFlags.NonPublic); ItemData val = ((!(method != null)) ? ((ItemData)null) : ((ItemData)method.Invoke(player, null))); ItemData val2 = ((!(method2 != null)) ? ((ItemData)null) : ((ItemData)method2.Invoke(player, null))); if (IsTorch(val)) { return val; } if (IsTorch(val2)) { return val2; } return null; } catch (Exception ex) { WearableTorchesPlugin.Log.LogError((object)("GetTorchInHands reflection error: " + ex)); return null; } } private static GameObject CreateBackTorchVisual(Player player, GameObject prefab) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0091: 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) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return null; } GameObject val = FindExistingBackTorchObject(player); if ((Object)(object)val != (Object)null) { return val; } Transform val2 = FindBackAttach(player); GameObject val3 = new GameObject("BackTorchObject"); val3.transform.SetParent(val2, false); val3.transform.localRotation = BackRotationOffset; val3.transform.localPosition = new Vector3(-0.0026f, -0.002f, -0.0017f); Vector3 lossyScale = val2.lossyScale; val3.transform.localScale = new Vector3((lossyScale.x != 0f) ? (1f / lossyScale.x) : 1f, (lossyScale.y != 0f) ? (1f / lossyScale.y) : 1f, (lossyScale.z != 0f) ? (1f / lossyScale.z) : 1f); MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Object)Object.Instantiate<GameObject>(((Component)componentsInChildren[i]).gameObject, val3.transform, false)).name = "BackTorchMesh"; } GameObject val4 = FindTorchFlamesOnPlayer(player); if ((Object)(object)val4 == (Object)null) { val4 = FindTorchFlamesInPrefab(prefab); } if ((Object)(object)val4 != (Object)null) { GameObject obj = Object.Instantiate<GameObject>(val4, val3.transform, false); ((Object)obj).name = "BackTorchFlames"; obj.transform.localRotation = Quaternion.identity; obj.transform.localPosition = FlameOffset; } GameObject val5 = new GameObject("BackTorchLight"); val5.transform.SetParent(val3.transform, false); val5.transform.localRotation = Quaternion.identity; val5.transform.localPosition = LightOffset; Light obj2 = val5.AddComponent<Light>(); obj2.type = (LightType)2; obj2.color = new Color(1f, 0.52f, 0.22f); obj2.range = 14f; obj2.intensity = 1.35f; obj2.shadows = (LightShadows)2; return val3; } internal static void HideVanillaTorchVisuals(Player player, bool hide) { if ((Object)(object)player == (Object)null) { return; } MeshRenderer[] componentsInChildren = ((Component)player).GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { Transform transform = ((Component)val).transform; if (!IsUnderBackTorchObject(transform)) { string text = ((Object)transform).name.ToLower(); string text2 = (((Object)(object)transform.parent != (Object)null) ? ((Object)transform.parent).name.ToLower() : ""); if (text.Contains("torch") || text2.Contains("torch")) { ((Renderer)val).enabled = !hide; } } } SkinnedMeshRenderer[] componentsInChildren2 = ((Component)player).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val2 in componentsInChildren2) { Transform transform2 = ((Component)val2).transform; if (!IsUnderBackTorchObject(transform2)) { string text3 = ((Object)transform2).name.ToLower(); string text4 = (((Object)(object)transform2.parent != (Object)null) ? ((Object)transform2.parent).name.ToLower() : ""); if (text3.Contains("torch") || text4.Contains("torch")) { ((Renderer)val2).enabled = !hide; } } } } private static bool IsUnderBackTorchObject(Transform t) { while ((Object)(object)t != (Object)null) { if (((Object)t).name == "BackTorchObject") { return true; } t = t.parent; } return false; } private static Transform FindBackAttach(Player player) { string[] array = new string[3] { "Visual/Armature/Hips/Spine/Spine1/Spine2", "Visual/Armature/Hips/Spine/Spine1", "Visual/Armature/Hips/Spine" }; foreach (string text in array) { Transform val = ((Component)player).transform.Find(text); if ((Object)(object)val != (Object)null) { return val; } } return ((Component)player).transform; } private static GameObject FindTorchFlamesOnPlayer(Player player) { Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name.ToLower().Contains("torch") && !((Object)(object)((Component)val).GetComponentInChildren<ParticleSystem>(true) == (Object)null) && !((Object)(object)((Component)val).GetComponentInChildren<MeshRenderer>(true) != (Object)null) && !((Object)(object)((Component)val).GetComponentInChildren<SkinnedMeshRenderer>(true) != (Object)null)) { return ((Component)val).gameObject; } } return null; } private static GameObject FindTorchFlamesInPrefab(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return null; } ParticleSystem[] componentsInChildren = prefab.GetComponentsInChildren<ParticleSystem>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Transform transform = ((Component)componentsInChildren[i]).transform; MeshRenderer component = ((Component)transform).GetComponent<MeshRenderer>(); SkinnedMeshRenderer component2 = ((Component)transform).GetComponent<SkinnedMeshRenderer>(); if ((Object)(object)component == (Object)null && (Object)(object)component2 == (Object)null) { return ((Component)transform).gameObject; } } return null; } private static void DestroyBackTorch() { foreach (KeyValuePair<long, GameObject> backTorch in BackTorches) { if ((Object)(object)backTorch.Value != (Object)null) { Object.Destroy((Object)(object)backTorch.Value); } } BackTorches.Clear(); } public static void ForceDestroyBackTorch() { DestroyBackTorch(); } public static void RemoveBackTorch(Player player) { if ((Object)(object)player == (Object)null) { return; } long playerKey = GetPlayerKey(player); if (playerKey != 0L && BackTorches.TryGetValue(playerKey, out var value)) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } BackTorches.Remove(playerKey); } GameObject val = FindExistingBackTorchObject(player); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } } [HarmonyPatch(typeof(Player), "OnDestroy")] public static class Player_OnDestroy_Patch { private static void Prefix(Player __instance) { WearableTorchManager.RemoveBackTorch(__instance); } }