using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("DarkwaterFlashlight")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DarkwaterFlashlight")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f9df4c08-37db-4968-b67e-f54cabf2c0de")]
[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 DarkwaterFlashlight;
[BepInPlugin("egys1n.beltlantern", "Belt Lantern", "1.2.1")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGUID = "egys1n.beltlantern";
public const string PluginName = "Belt Lantern";
public const string PluginVersion = "1.2.1";
internal static ManualLogSource Log;
internal static Harmony HarmonyInstance;
public static ConfigEntry<KeyCode> ToggleKey;
public static ConfigEntry<KeyCode> SlotKey;
public static ConfigEntry<float> LightIntensity;
public static ConfigEntry<float> LightRange;
public static ConfigEntry<float> OffsetX;
public static ConfigEntry<float> OffsetY;
public static ConfigEntry<float> OffsetZ;
internal static FlashlightSlotController SlotController;
private void Awake()
{
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Expected O, but got Unknown
//IL_0138: 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)
Log = ((BaseUnityPlugin)this).Logger;
ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "ToggleLight", (KeyCode)108, "Toggle the belt lantern ON / OFF");
SlotKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "MoveToSlot", (KeyCode)118, "Move lantern between hand and belt slot");
LightIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Light", "IntensityValue", 2.7f, "Point light intensity (higher = brighter). Default 2.7");
LightRange = ((BaseUnityPlugin)this).Config.Bind<float>("Light", "Range", 12f, "Point light radius in metres. Default 12");
OffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "OffsetX", 0.2f, "Left/Right offset from head bone");
OffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "OffsetY", -0.7f, "Up/Down offset (negative = lower, belt level)");
OffsetZ = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "OffsetZ", 0.1f, "Forward/Back offset");
HarmonyInstance = new Harmony("egys1n.beltlantern");
HarmonyInstance.PatchAll();
Log.LogInfo((object)"Belt Lantern v1.2.1 loaded.");
Log.LogInfo((object)$" Toggle: [{ToggleKey.Value}] | Slot transfer: [{SlotKey.Value}]");
}
private void Update()
{
if ((Object)(object)SlotController == (Object)null)
{
TryAttachController();
}
else
{
SlotController.ProcessInput();
}
}
private void TryAttachController()
{
C_Controller_Player[] array = Object.FindObjectsByType<C_Controller_Player>((FindObjectsSortMode)0);
foreach (C_Controller_Player val in array)
{
if (!((Object)(object)((C_Controller)val).E_Inventory() == (Object)null))
{
FlashlightSlotController component = ((Component)val).GetComponent<FlashlightSlotController>();
if ((Object)(object)component != (Object)null)
{
SlotController = component;
break;
}
SlotController = ((Component)val).gameObject.AddComponent<FlashlightSlotController>();
SlotController.Initialize(val);
Log.LogInfo((object)"FlashlightSlotController attached to local player.");
break;
}
}
}
private void OnDestroy()
{
Harmony harmonyInstance = HarmonyInstance;
if (harmonyInstance != null)
{
harmonyInstance.UnpatchSelf();
}
}
}
public class FlashlightSlotController : MonoBehaviour
{
public enum SlotState
{
Empty,
OccupiedOff,
OccupiedOn
}
[CompilerGenerated]
private sealed class <AtmosphericFlicker>d__46 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public FlashlightSlotController <>4__this;
private float <dipTarget>5__2;
private float <dipDuration>5__3;
private float <elapsed>5__4;
private float <startIntensity>5__5;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <AtmosphericFlicker>d__46(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Expected O, but got Unknown
int num = <>1__state;
FlashlightSlotController flashlightSlotController = <>4__this;
switch (num)
{
default:
return false;
case 0:
{
<>1__state = -1;
flashlightSlotController.flickerRunning = true;
float num2 = Random.Range(0.2f, 0.4f);
<dipTarget>5__2 = flashlightSlotController.targetIntensity * (1f - num2);
<dipDuration>5__3 = Random.Range(0.1f, 0.3f);
<elapsed>5__4 = 0f;
<startIntensity>5__5 = flashlightSlotController.beltLight.intensity;
goto IL_00d9;
}
case 1:
<>1__state = -1;
goto IL_00d9;
case 2:
{
<>1__state = -1;
flashlightSlotController.beltLight.intensity = flashlightSlotController.targetIntensity;
flashlightSlotController.flickerRunning = false;
return false;
}
IL_00d9:
if (<elapsed>5__4 < <dipDuration>5__3)
{
<elapsed>5__4 += Time.deltaTime;
flashlightSlotController.beltLight.intensity = Mathf.Lerp(<startIntensity>5__5, <dipTarget>5__2, <elapsed>5__4 / <dipDuration>5__3);
<>2__current = null;
<>1__state = 1;
return true;
}
<>2__current = (object)new WaitForSeconds(0.04f);
<>1__state = 2;
return true;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <Co_NetworkSync>d__57 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public FlashlightSlotController <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Co_NetworkSync>d__57(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
int num = <>1__state;
FlashlightSlotController flashlightSlotController = <>4__this;
if (num != 0)
{
if (num != 1)
{
return false;
}
<>1__state = -1;
C_Controller_Player[] array = Object.FindObjectsByType<C_Controller_Player>((FindObjectsSortMode)0);
foreach (C_Controller_Player val in array)
{
if (!((Object)(object)val == (Object)(object)flashlightSlotController.playerController))
{
flashlightSlotController.ReconcileRemotePlayer(val);
}
}
}
else
{
<>1__state = -1;
}
<>2__current = (object)new WaitForSeconds(5f);
<>1__state = 1;
return true;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <LoadAudioClip>d__33 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public FlashlightSlotController <>4__this;
private UnityWebRequest <www>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadAudioClip>d__33(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<www>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Invalid comparison between Unknown and I4
try
{
int num = <>1__state;
FlashlightSlotController flashlightSlotController = <>4__this;
switch (num)
{
default:
return false;
case 0:
{
<>1__state = -1;
string text = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "SFX_Lantern_Belt_Action.wav");
if (!File.Exists(text))
{
Plugin.Log.LogWarning((object)("[SFX] Sound file not found at: " + text + ". Audio will be disabled."));
return false;
}
string text2 = "file://" + text;
<www>5__2 = UnityWebRequestMultimedia.GetAudioClip(text2, (AudioType)20);
<>1__state = -3;
<>2__current = <www>5__2.SendWebRequest();
<>1__state = 1;
return true;
}
case 1:
<>1__state = -3;
if ((int)<www>5__2.result == 1)
{
_sfxAction = DownloadHandlerAudioClip.GetContent(<www>5__2);
flashlightSlotController._isAudioLoaded = true;
Plugin.Log.LogInfo((object)"SFX_Lantern_Belt_Action.wav loaded successfully.");
}
else
{
Plugin.Log.LogError((object)("[SFX] Failed to load: " + <www>5__2.error));
}
<>m__Finally1();
<www>5__2 = null;
return false;
}
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<www>5__2 != null)
{
((IDisposable)<www>5__2).Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private C_Controller_Player playerController;
private E_Inventory playerInventory;
private Light beltLight;
private GameObject beltLightObject;
private PlayerItem storedLanternItem;
private static AudioClip _sfxAction;
private AudioSource _audioSource;
private bool _isAudioLoaded;
private bool _showSettings;
private float _settingR = 0.8f;
private float _settingG = 0.62f;
private float _settingB = 0.42f;
private float _settingIntensity = 2.7f;
private Rect _settingWinRect = new Rect(60f, 60f, 340f, 260f);
private bool inputCooldown;
private float cooldownTimer;
private const float INPUT_COOLDOWN = 0.3f;
private float flickerTimer;
private bool flickerRunning;
private float targetIntensity = 2.7f;
private Texture2D hudIconTexture;
private const int HUD_ICON_SIZE = 42;
private const int HUD_MARGIN = 8;
private RectTransform _inventoryBarRect;
private float _findBarCooldown;
internal static bool NetworkSyncState;
internal static bool NetworkSyncDirty;
public SlotState CurrentState { get; private set; }
public void Initialize(C_Controller_Player player)
{
playerController = player;
playerInventory = ((C_Controller)player).E_Inventory();
CreateBeltLight();
CreateHUDIcon();
ScheduleNextFlicker();
FindInventoryBar();
((MonoBehaviour)this).StartCoroutine(Co_NetworkSync());
InitializeAudio();
Plugin.Log.LogInfo((object)"Belt Lantern Mod initialized.");
}
private void CreateBeltLight()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
beltLightObject = new GameObject("BeltLanternLight");
Transform val = (((Object)(object)playerController.headJoint != (Object)null) ? playerController.headJoint : ((Component)playerController).transform);
beltLightObject.transform.SetParent(val, false);
beltLightObject.transform.localPosition = new Vector3(Plugin.OffsetX.Value, Plugin.OffsetY.Value, Plugin.OffsetZ.Value);
beltLightObject.transform.localRotation = Quaternion.identity;
beltLight = beltLightObject.AddComponent<Light>();
beltLight.type = (LightType)2;
beltLight.color = new Color(0.8f, 0.62f, 0.42f);
beltLight.intensity = Plugin.LightIntensity.Value;
beltLight.range = Plugin.LightRange.Value;
beltLight.shadows = (LightShadows)2;
beltLight.shadowStrength = 0.4f;
beltLight.renderMode = (LightRenderMode)1;
targetIntensity = Plugin.LightIntensity.Value;
beltLightObject.SetActive(false);
Plugin.Log.LogInfo((object)"Belt lantern Point Light created.");
}
private void InitializeAudio()
{
_audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
_audioSource.playOnAwake = false;
_audioSource.spatialBlend = 1f;
_audioSource.volume = 0.7f;
((MonoBehaviour)this).StartCoroutine(LoadAudioClip());
}
[IteratorStateMachine(typeof(<LoadAudioClip>d__33))]
private IEnumerator LoadAudioClip()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadAudioClip>d__33(0)
{
<>4__this = this
};
}
private void PlayActionSFX()
{
if (_isAudioLoaded && (Object)(object)_sfxAction != (Object)null && (Object)(object)_audioSource != (Object)null)
{
_audioSource.PlayOneShot(_sfxAction);
}
}
private void CreateHUDIcon()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
hudIconTexture = new Texture2D(42, 42, (TextureFormat)4, false);
Color val = default(Color);
((Color)(ref val))..ctor(0f, 0f, 0f, 0f);
Color col = default(Color);
((Color)(ref col))..ctor(1f, 0.85f, 0.3f, 1f);
new Color(1f, 0.8f, 0.2f, 0.3f);
for (int i = 0; i < 42; i++)
{
for (int j = 0; j < 42; j++)
{
hudIconTexture.SetPixel(i, j, val);
}
}
int num = 21;
int num2 = 21;
for (int k = 0; k < 42; k++)
{
for (int l = 0; l < 42; l++)
{
float num3 = Vector2.Distance(new Vector2((float)k, (float)l), new Vector2((float)num, (float)num2));
if (num3 < 18f)
{
float num4 = Mathf.Lerp(0.4f, 0f, num3 / 18f);
hudIconTexture.SetPixel(k, l, new Color(1f, 0.8f, 0.2f, num4));
}
}
}
DrawFilledRect(hudIconTexture, num - 6, num2 - 7, 12, 14, col);
DrawFilledRect(hudIconTexture, num - 4, num2 - 5, 8, 10, new Color(1f, 1f, 1f, 0.8f));
DrawFilledRect(hudIconTexture, num - 7, num2 + 7, 14, 3, col);
DrawFilledRect(hudIconTexture, num - 8, num2 - 10, 16, 3, col);
DrawFilledRect(hudIconTexture, num - 1, num2 + 10, 3, 5, col);
hudIconTexture.Apply();
}
private static void DrawFilledRect(Texture2D tex, int x0, int y0, int w, int h, Color col)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
for (int i = x0; i < x0 + w && i < ((Texture)tex).width; i++)
{
for (int j = y0; j < y0 + h && j < ((Texture)tex).height; j++)
{
if (i >= 0 && j >= 0)
{
tex.SetPixel(i, j, col);
}
}
}
}
private void OnGUI()
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
if (CurrentState == SlotState.Empty || (Object)(object)hudIconTexture == (Object)null)
{
return;
}
if ((Object)(object)_inventoryBarRect == (Object)null)
{
_findBarCooldown -= Time.deltaTime;
if (_findBarCooldown <= 0f)
{
FindInventoryBar();
_findBarCooldown = 2f;
}
}
float num = ((CurrentState == SlotState.OccupiedOn) ? 1f : 0.4f);
GUI.color = new Color(1f, 1f, 1f, num);
float num2;
float num3;
if ((Object)(object)_inventoryBarRect != (Object)null)
{
Vector3[] array = (Vector3[])(object)new Vector3[4];
_inventoryBarRect.GetWorldCorners(array);
float x = array[0].x;
float y = array[0].y;
num2 = x - 42f - 8f;
num3 = (float)Screen.height - y - 42f;
}
else
{
num2 = (float)Screen.width * 0.5f - (float)Screen.width * 0.22f - 42f;
num3 = (float)Screen.height * 0.88f - 42f;
}
GUI.DrawTexture(new Rect(num2, num3, 42f, 42f), (Texture)(object)hudIconTexture);
GUI.color = Color.white;
if (_showSettings)
{
DrawSettingsWindow();
}
}
private void DrawSettingsWindow()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
_settingWinRect = GUI.Window(9823, _settingWinRect, new WindowFunction(SettingsWindowContent), "Belt Lantern — Настройка");
}
private void SettingsWindowContent(int id)
{
//IL_0055: 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_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
//IL_026e: Unknown result type (might be due to invalid IL or missing references)
//IL_0288: Unknown result type (might be due to invalid IL or missing references)
//IL_0297: Unknown result type (might be due to invalid IL or missing references)
//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
//IL_0323: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)beltLight == (Object)null)
{
GUI.Label(new Rect(10f, 30f, 320f, 20f), "Лампа не активна.");
return;
}
float num = 28f;
float num2 = 100f;
float num3 = 210f;
GUI.Label(new Rect(10f, num, num2, 20f), $"Яркость: {_settingIntensity:F1}");
float num4 = GUI.HorizontalSlider(new Rect(120f, num + 4f, num3, 16f), _settingIntensity, 0.5f, 10f);
if (Mathf.Abs(num4 - _settingIntensity) > 0.01f)
{
_settingIntensity = num4;
beltLight.intensity = _settingIntensity;
targetIntensity = _settingIntensity;
}
num += 30f;
GUI.Label(new Rect(10f, num, num2, 20f), $"Красный: {_settingR:F2}");
float num5 = GUI.HorizontalSlider(new Rect(120f, num + 4f, num3, 16f), _settingR, 0.5f, 1f);
if (Mathf.Abs(num5 - _settingR) > 0.001f)
{
_settingR = num5;
ApplyColor();
}
num += 30f;
GUI.Label(new Rect(10f, num, num2, 20f), $"Зелёный: {_settingG:F2}");
float num6 = GUI.HorizontalSlider(new Rect(120f, num + 4f, num3, 16f), _settingG, 0.4f, 1f);
if (Mathf.Abs(num6 - _settingG) > 0.001f)
{
_settingG = num6;
ApplyColor();
}
num += 30f;
GUI.Label(new Rect(10f, num, num2, 20f), $"Синий: {_settingB:F2}");
float num7 = GUI.HorizontalSlider(new Rect(120f, num + 4f, num3, 16f), _settingB, 0.1f, 1f);
if (Mathf.Abs(num7 - _settingB) > 0.001f)
{
_settingB = num7;
ApplyColor();
}
num += 30f;
GUI.color = new Color(_settingR, _settingG, _settingB);
GUI.DrawTexture(new Rect(10f, num, 320f, 24f), (Texture)(object)Texture2D.whiteTexture);
GUI.color = Color.white;
num += 32f;
GUI.Label(new Rect(10f, num, 320f, 20f), $"new Color({_settingR:F2}f, {_settingG:F2}f, {_settingB:F2}f) intensity={_settingIntensity:F1}f");
num += 28f;
if (GUI.Button(new Rect(10f, num, 320f, 26f), "Закрыть (Alt+V)"))
{
_showSettings = false;
}
GUI.DragWindow();
}
private void ApplyColor()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)beltLight != (Object)null)
{
beltLight.color = new Color(_settingR, _settingG, _settingB);
}
}
private void FindInventoryBar()
{
GameObject val = GameObject.Find("PlayerUI");
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)"[HUD] PlayerUI not found yet — will retry.");
return;
}
_inventoryBarRect = val.GetComponent<RectTransform>();
Plugin.Log.LogInfo((object)("[HUD] Bound to " + ((Object)val).name + " (RectTransform found)."));
RectTransform val2 = FindChildWithKeyword(val.transform, new string[5] { "inventory", "item", "slot", "hotbar", "equip" });
if ((Object)(object)val2 != (Object)null)
{
_inventoryBarRect = val2;
Plugin.Log.LogInfo((object)("[HUD] Refined binding to deeper child: " + ((Object)val2).name));
}
}
private RectTransform FindChildWithKeyword(Transform parent, string[] keywords)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Expected O, but got Unknown
foreach (Transform item in parent)
{
Transform val = item;
string text = ((Object)val).name.ToLower();
foreach (string value in keywords)
{
if (text.Contains(value))
{
return ((Component)val).GetComponent<RectTransform>();
}
}
RectTransform val2 = FindChildWithKeyword(val, keywords);
if ((Object)(object)val2 != (Object)null)
{
return val2;
}
}
return null;
}
public void ProcessInput()
{
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)playerInventory == (Object)null || (Object)(object)playerController == (Object)null)
{
return;
}
if (inputCooldown)
{
cooldownTimer -= Time.deltaTime;
if (!(cooldownTimer <= 0f))
{
return;
}
inputCooldown = false;
}
if (IsPlayerBusy())
{
return;
}
if (CurrentState == SlotState.OccupiedOn)
{
TickFlicker();
}
bool flag = Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
if (flag && Input.GetKeyDown((KeyCode)118))
{
_showSettings = !_showSettings;
if (_showSettings && (Object)(object)beltLight != (Object)null)
{
_settingR = beltLight.color.r;
_settingG = beltLight.color.g;
_settingB = beltLight.color.b;
_settingIntensity = beltLight.intensity;
}
StartCooldown();
}
else
{
if (Input.GetKeyDown(Plugin.ToggleKey.Value))
{
HandleToggleLight();
StartCooldown();
}
if (!flag && Input.GetKeyDown(Plugin.SlotKey.Value))
{
HandleSlotTransfer();
StartCooldown();
}
}
}
private void ScheduleNextFlicker()
{
flickerTimer = Random.Range(30f, 120f);
}
private void TickFlicker()
{
flickerTimer -= Time.deltaTime;
if (flickerTimer <= 0f && !flickerRunning)
{
((MonoBehaviour)this).StartCoroutine(AtmosphericFlicker());
ScheduleNextFlicker();
}
}
[IteratorStateMachine(typeof(<AtmosphericFlicker>d__46))]
private IEnumerator AtmosphericFlicker()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <AtmosphericFlicker>d__46(0)
{
<>4__this = this
};
}
private void HandleToggleLight()
{
switch (CurrentState)
{
case SlotState.OccupiedOff:
beltLightObject.SetActive(true);
CurrentState = SlotState.OccupiedOn;
BroadcastLightState(on: true);
PlayActionSFX();
Plugin.Log.LogInfo((object)"Belt lantern ON.");
break;
case SlotState.OccupiedOn:
beltLightObject.SetActive(false);
CurrentState = SlotState.OccupiedOff;
BroadcastLightState(on: false);
PlayActionSFX();
Plugin.Log.LogInfo((object)"Belt lantern OFF.");
break;
case SlotState.Empty:
break;
}
}
private void BroadcastLightState(bool on)
{
NetworkSyncState = on;
NetworkSyncDirty = true;
DispatchNetworkState(on);
Plugin.Log.LogInfo((object)$"[NET] Broadcasting belt lamp state = {on}");
}
public static void ApplyRemoteLightState(C_Controller_Player remotePlayer, bool on)
{
BeltLanternRemoteMirror beltLanternRemoteMirror = ((Component)remotePlayer).GetComponent<BeltLanternRemoteMirror>();
if ((Object)(object)beltLanternRemoteMirror == (Object)null)
{
beltLanternRemoteMirror = ((Component)remotePlayer).gameObject.AddComponent<BeltLanternRemoteMirror>();
}
beltLanternRemoteMirror.SetState(on);
}
private void HandleSlotTransfer()
{
if ((Object)(object)playerInventory == (Object)null)
{
return;
}
if (playerInventory.HoldingLantern())
{
if (CurrentState != 0)
{
Plugin.Log.LogInfo((object)"Belt slot already occupied!");
}
else
{
MoveFromHandToSlot();
}
}
else if (CurrentState == SlotState.OccupiedOff || CurrentState == SlotState.OccupiedOn)
{
if (playerInventory.currentlyEquippedItem != null)
{
Plugin.Log.LogInfo((object)"Hands busy — unequip current item first.");
}
else
{
MoveFromSlotToHand();
}
}
else
{
Plugin.Log.LogInfo((object)"No lantern to move. Equip a lantern, then press V.");
}
}
private void MoveFromHandToSlot()
{
storedLanternItem = playerInventory.currentlyEquippedItem.DeepCopy();
int num = -1;
for (int i = 0; i < playerInventory.inventoryItems.Length; i++)
{
if (playerInventory.inventoryItems[i] != null && playerInventory.inventoryItems[i].GetHash() == storedLanternItem.GetHash())
{
num = i;
break;
}
}
playerInventory.UnequipCurrentItem(false);
if (num >= 0)
{
playerInventory.DestroyItem(storedLanternItem.GetHash(), 1, num);
}
CurrentState = SlotState.OccupiedOff;
Plugin.Log.LogInfo((object)("Lantern → belt slot. (" + storedLanternItem.itemData.name + ")"));
}
private void MoveFromSlotToHand()
{
if (storedLanternItem == null)
{
Plugin.Log.LogWarning((object)"No stored lantern data to restore!");
CurrentState = SlotState.Empty;
return;
}
if (CurrentState == SlotState.OccupiedOn)
{
beltLightObject.SetActive(false);
BroadcastLightState(on: false);
}
if (!playerInventory.AddItem(storedLanternItem.DeepCopy(), false))
{
Plugin.Log.LogInfo((object)"Inventory full! Cannot retrieve lantern.");
if (CurrentState == SlotState.OccupiedOn)
{
beltLightObject.SetActive(true);
BroadcastLightState(on: true);
}
}
else
{
storedLanternItem = null;
CurrentState = SlotState.Empty;
Plugin.Log.LogInfo((object)"Lantern ← belt slot returned to inventory.");
}
}
public void OnPlayerDeath()
{
if (CurrentState != 0)
{
Plugin.Log.LogInfo((object)"Player died — dropping belt lantern.");
beltLightObject.SetActive(false);
BroadcastLightState(on: false);
if (storedLanternItem != null)
{
playerInventory.DropItem(storedLanternItem, 1);
storedLanternItem = null;
}
CurrentState = SlotState.Empty;
}
}
private bool IsPlayerBusy()
{
if (playerController.UsingTerminal())
{
return true;
}
if (playerInventory.lockInventory)
{
return true;
}
E_HealthController component = ((Component)playerController).GetComponent<E_HealthController>();
if ((Object)(object)component != (Object)null && component.dead)
{
return true;
}
return false;
}
[IteratorStateMachine(typeof(<Co_NetworkSync>d__57))]
private IEnumerator Co_NetworkSync()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Co_NetworkSync>d__57(0)
{
<>4__this = this
};
}
private void ReconcileRemotePlayer(C_Controller_Player remotePlayer)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
try
{
E_Inventory val = ((C_Controller)remotePlayer).E_Inventory();
if ((Object)(object)val == (Object)null)
{
return;
}
bool flag = false;
bool flag2 = false;
PlayerItem currentlyEquippedItem = val.currentlyEquippedItem;
if (currentlyEquippedItem != null && IsLantern(currentlyEquippedItem))
{
flag2 = true;
}
foreach (Transform item in ((Component)val).transform)
{
PlayerItem component = ((Component)item).GetComponent<PlayerItem>();
if (component != null && IsLantern(component))
{
flag = true;
break;
}
}
bool on = flag && !flag2;
ApplyRemoteLightState(remotePlayer, on);
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Sync error for player " + ((Object)remotePlayer).name + ": " + ex.Message));
}
}
public void DispatchNetworkState(bool on)
{
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
try
{
Type type = AccessTools.TypeByName("E_ChatController");
if (type == null)
{
return;
}
Object val = Object.FindFirstObjectByType(type);
if (!(val == (Object)null))
{
string name = ((Object)((Component)playerController).gameObject).name;
string text = (on ? "1" : "0");
string text2 = "/BELT_SYNC:" + name + ":" + text;
MethodInfo methodInfo = AccessTools.Method(type, "AddMessage", new Type[3]
{
typeof(string),
typeof(string),
typeof(Color)
}, (Type[])null);
if (methodInfo != null)
{
methodInfo.Invoke(val, new object[3]
{
text2,
name,
Color.black
});
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Net] Dispatch error: " + ex.Message));
}
}
private bool IsLantern(PlayerItem item)
{
if (item == null || item.itemData == null)
{
return false;
}
if (!item.itemData.name.ToLower().Contains("lantern"))
{
return item.itemData.name.ToLower().Contains("flashlight");
}
return true;
}
private void StartCooldown()
{
inputCooldown = true;
cooldownTimer = 0.3f;
}
private void OnDestroy()
{
if ((Object)(object)beltLightObject != (Object)null)
{
Object.Destroy((Object)(object)beltLightObject);
}
if ((Object)(object)hudIconTexture != (Object)null)
{
Object.Destroy((Object)(object)hudIconTexture);
}
}
}
public static class FlashlightSlotPatches
{
[HarmonyPatch(typeof(E_HealthController), "KillPlayer")]
[HarmonyPostfix]
public static void KillPlayer_Postfix(E_HealthController __instance)
{
if (!((Object)(object)Plugin.SlotController == (Object)null) && !((Object)/*isinst with value type is only supported in some contexts*/ == (Object)null))
{
Plugin.Log.LogInfo((object)"[Patch] KillPlayer — dropping belt lantern.");
Plugin.SlotController.OnPlayerDeath();
}
}
[HarmonyPatch(typeof(E_Inventory), "DropAllItems")]
[HarmonyPostfix]
public static void DropAllItems_Postfix(E_Inventory __instance)
{
if (!((Object)(object)Plugin.SlotController == (Object)null))
{
Plugin.Log.LogInfo((object)"[Patch] DropAllItems — clearing belt slot.");
Plugin.SlotController.OnPlayerDeath();
}
}
[HarmonyPatch(typeof(C_Controller_Player), "RPC_EquipItem")]
[HarmonyPostfix]
public static void RPC_EquipItem_Postfix(C_Controller_Player __instance, int P_itemID, bool P_override)
{
if (FlashlightSlotController.NetworkSyncDirty)
{
FlashlightSlotController.NetworkSyncDirty = false;
}
if ((!((Object)(object)Plugin.SlotController != (Object)null) || !((Object)(object)__instance == (Object)(object)((Component)Plugin.SlotController).GetComponent<C_Controller_Player>())) && !((Object)(object)Plugin.SlotController == (Object)null))
{
FlashlightSlotController.ApplyRemoteLightState(__instance, FlashlightSlotController.NetworkSyncState);
}
}
[HarmonyPatch("E_ChatController", "AddMessage")]
[HarmonyPrefix]
public static bool AddMessage_Prefix(string P_message, string P_user, Color P_color)
{
if (string.IsNullOrEmpty(P_message))
{
return true;
}
if (P_message.StartsWith("/BELT_SYNC"))
{
Plugin.Log.LogInfo((object)("[Net] Intercepted mod packet: " + P_message));
try
{
string[] array = P_message.Split(new char[1] { ':' });
if (array.Length >= 3)
{
string text = array[1];
bool on = array[2] == "1";
C_Controller_Player[] array2 = Object.FindObjectsByType<C_Controller_Player>((FindObjectsSortMode)0);
foreach (C_Controller_Player val in array2)
{
if (((Object)((Component)val).gameObject).name == text)
{
FlashlightSlotController.ApplyRemoteLightState(val, on);
break;
}
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Net] Intercept parse error: " + ex.Message));
}
return false;
}
return true;
}
}
public class BeltLanternRemoteMirror : MonoBehaviour
{
private Light mirrorLight;
private GameObject mirrorLightObject;
private bool isOn;
private void Awake()
{
CreateMirrorLight();
}
private void CreateMirrorLight()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: 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)
mirrorLightObject = new GameObject("BeltLanternMirror");
Transform val = null;
C_Controller_Player component = ((Component)this).GetComponent<C_Controller_Player>();
val = ((!((Object)(object)component != (Object)null) || !((Object)(object)component.headJoint != (Object)null)) ? ((Component)this).transform : component.headJoint);
mirrorLightObject.transform.SetParent(val, false);
mirrorLightObject.transform.localPosition = new Vector3(Plugin.OffsetX.Value, Plugin.OffsetY.Value, Plugin.OffsetZ.Value);
mirrorLightObject.transform.localRotation = Quaternion.identity;
mirrorLight = mirrorLightObject.AddComponent<Light>();
mirrorLight.type = (LightType)2;
mirrorLight.color = new Color(1f, 0.7f, 0.28f);
mirrorLight.intensity = Plugin.LightIntensity.Value;
mirrorLight.range = Plugin.LightRange.Value;
mirrorLight.shadows = (LightShadows)0;
mirrorLight.renderMode = (LightRenderMode)0;
mirrorLightObject.SetActive(false);
}
public void SetState(bool on)
{
isOn = on;
if ((Object)(object)mirrorLightObject != (Object)null)
{
mirrorLightObject.SetActive(on);
}
}
private void OnDestroy()
{
if ((Object)(object)mirrorLightObject != (Object)null)
{
Object.Destroy((Object)(object)mirrorLightObject);
}
}
}