Decompiled source of BlackPeakRemix LightExtension v0.3.0

BlackPeak.LightExtension.dll

Decompiled a week ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Peak.Network;
using Photon.Pun;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace BlackPeak.LightExtension;

internal sealed class BinocularNightVisionRuntime : MonoBehaviour
{
	private static readonly FieldInfo MainCameraField = AccessTools.Field(typeof(MainCamera), "cam");

	private Action_ShowBinocularOverlay _overlay;

	private Light _nightVisionLight;

	private Canvas _overlayCanvas;

	private Image _overlayImage;

	internal void Init(Actions_Binoculars actions)
	{
		_overlay = (((Object)(object)actions != (Object)null) ? actions.binocOverlay : null);
		((Behaviour)this).enabled = true;
	}

	private void Update()
	{
		if (!BlackPeakLightExtensionPlugin.BinocularNightVisionEnabled)
		{
			DisableEffects();
			return;
		}
		EnsureEffectsExist();
		ApplyState((Object)(object)_overlay != (Object)null && _overlay.binocularsActive);
	}

	internal void DisableEffects()
	{
		ApplyState(active: false);
	}

	private void EnsureEffectsExist()
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Expected O, but got Unknown
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Expected O, but got Unknown
		//IL_0174: 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_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		Camera val = (Camera)(((Object)(object)MainCamera.instance != (Object)null && MainCameraField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!((Object)(object)val == (Object)null))
		{
			if ((Object)(object)_nightVisionLight == (Object)null)
			{
				GameObject val2 = new GameObject("BPL_BinocularNightVisionLight");
				val2.transform.SetParent(((Component)val).transform, false);
				_nightVisionLight = val2.AddComponent<Light>();
				_nightVisionLight.type = (LightType)0;
				_nightVisionLight.spotAngle = 42f;
				_nightVisionLight.innerSpotAngle = 18f;
				_nightVisionLight.shadows = (LightShadows)0;
				_nightVisionLight.color = new Color(0.65f, 1f, 0.72f, 1f);
				((Behaviour)_nightVisionLight).enabled = false;
			}
			if ((Object)(object)_overlayCanvas == (Object)null)
			{
				GameObject val3 = new GameObject("BPL_BinocularNightVisionOverlay");
				_overlayCanvas = val3.AddComponent<Canvas>();
				_overlayCanvas.renderMode = (RenderMode)0;
				_overlayCanvas.sortingOrder = 32000;
				val3.AddComponent<CanvasScaler>();
				val3.AddComponent<GraphicRaycaster>();
				GameObject val4 = new GameObject("Overlay");
				val4.transform.SetParent(val3.transform, false);
				_overlayImage = val4.AddComponent<Image>();
				((Graphic)_overlayImage).raycastTarget = false;
				RectTransform rectTransform = ((Graphic)_overlayImage).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = Vector2.zero;
				rectTransform.offsetMax = Vector2.zero;
				((Component)_overlayCanvas).gameObject.SetActive(false);
			}
		}
	}

	private void ApplyState(bool active)
	{
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_nightVisionLight != (Object)null)
		{
			_nightVisionLight.intensity = BlackPeakLightExtensionPlugin.BinocularNightVisionLightIntensity.Value;
			_nightVisionLight.range = BlackPeakLightExtensionPlugin.BinocularNightVisionLightRange.Value;
			((Behaviour)_nightVisionLight).enabled = active;
		}
		if ((Object)(object)_overlayCanvas != (Object)null)
		{
			((Component)_overlayCanvas).gameObject.SetActive(active);
		}
		if ((Object)(object)_overlayImage != (Object)null)
		{
			((Graphic)_overlayImage).color = new Color(0.28f, 0.95f, 0.35f, BlackPeakLightExtensionPlugin.BinocularOverlayOpacity.Value);
		}
	}

	private void OnDisable()
	{
		ApplyState(active: false);
	}

	private void OnDestroy()
	{
		if ((Object)(object)_nightVisionLight != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_nightVisionLight).gameObject);
		}
		if ((Object)(object)_overlayCanvas != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_overlayCanvas).gameObject);
		}
	}
}
[BepInPlugin("shiro.BlackPeak.LightExtension", "BlackPeak LightExtension", "0.3.0")]
public sealed class BlackPeakLightExtensionPlugin : BaseUnityPlugin
{
	public const string Guid = "shiro.BlackPeak.LightExtension";

	public const string Name = "BlackPeak LightExtension";

	public const string Version = "0.3.0";

	internal static ManualLogSource Log { get; private set; }

	internal static ConfigEntry<BurnDurationOption> LanternBurnDuration { get; private set; }

	internal static ConfigEntry<BurnDurationOption> TorchBurnDuration { get; private set; }

	internal static ConfigEntry<float> TorchLightIntensity { get; private set; }

	internal static ConfigEntry<float> TorchLightRange { get; private set; }

	internal static ConfigEntry<bool> EnableBinocularNightVision { get; private set; }

	internal static ConfigEntry<float> BinocularNightVisionLightIntensity { get; private set; }

	internal static ConfigEntry<float> BinocularNightVisionLightRange { get; private set; }

	internal static ConfigEntry<float> BinocularOverlayOpacity { get; private set; }

	internal static float LanternBurnSecondsValue => (float)LanternBurnDuration.Value;

	internal static float TorchBurnSecondsValue => (float)TorchBurnDuration.Value;

	internal static float TorchLightIntensityValue => TorchLightIntensity.Value;

	internal static float TorchLightRangeValue => TorchLightRange.Value;

	internal static bool BinocularNightVisionEnabled => EnableBinocularNightVision.Value;

	private void Awake()
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Expected O, but got Unknown
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Expected O, but got Unknown
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		LanternBurnDuration = ((BaseUnityPlugin)this).Config.Bind<BurnDurationOption>("Light Sources", "Lantern Burn Duration", BurnDurationOption.Seconds1200, "Lantern lifetime in seconds.");
		TorchBurnDuration = ((BaseUnityPlugin)this).Config.Bind<BurnDurationOption>("Light Sources", "Torch Burn Duration", BurnDurationOption.Seconds1200, "Torch lifetime in seconds.");
		TorchLightIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Light Sources", "Torch Light Intensity", 10f, new ConfigDescription("Brightness intensity for the original torch light source.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
		TorchLightRange = ((BaseUnityPlugin)this).Config.Bind<float>("Light Sources", "Torch Light Range", 45f, new ConfigDescription("Range of the original torch light source.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
		EnableBinocularNightVision = ((BaseUnityPlugin)this).Config.Bind<bool>("Enhanced Items", "Enable Binocular Night Vision", true, "Enhances binoculars with a local night vision effect.");
		BinocularNightVisionLightIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Enhanced Items", "Binocular Night Vision Light Intensity", 10f, "Local night vision spotlight intensity.");
		BinocularNightVisionLightRange = ((BaseUnityPlugin)this).Config.Bind<float>("Enhanced Items", "Binocular Night Vision Light Range", 270f, "Local night vision spotlight range.");
		BinocularOverlayOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Enhanced Items", "Binocular Night Vision Overlay Opacity", 0.05f, "Green overlay opacity while binocular night vision is active.");
		Harmony val = new Harmony("shiro.BlackPeak.LightExtension");
		val.PatchAll();
		ResolveKnownConflicts(val);
		Log.LogInfo((object)string.Format("{0} loaded. Lantern={1}, Torch={2}", "BlackPeak LightExtension", LanternBurnDuration.Value, TorchBurnDuration.Value));
	}

	private static void ResolveKnownConflicts(Harmony harmony)
	{
		MethodInfo methodInfo = AccessTools.Method(typeof(Lantern), "UpdateFuel", (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			return;
		}
		Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
		if (patchInfo == null || patchInfo.Prefixes == null)
		{
			return;
		}
		bool flag = false;
		foreach (Patch prefix in patchInfo.Prefixes)
		{
			if (prefix.owner == "HnskNoah.BlackPeakRemix")
			{
				flag = true;
				break;
			}
		}
		if (flag)
		{
			harmony.Unpatch((MethodBase)methodInfo, (HarmonyPatchType)1, "HnskNoah.BlackPeakRemix");
			Log.LogInfo((object)"[Conflict] Removed BlackPeakRemix prefix from Lantern.UpdateFuel so LightExtension controls lantern/torch burn time.");
		}
	}
}
public enum BurnDurationOption
{
	Seconds60 = 60,
	Seconds120 = 120,
	Seconds240 = 240,
	Seconds360 = 360,
	Seconds600 = 600,
	Seconds1200 = 1200,
	Seconds1800 = 1800,
	Seconds2400 = 2400,
	Seconds3600 = 3600,
	Infinite = 100000
}
internal sealed class GlobalSignalFlareController
{
}
internal static class LightSourceItemHelpers
{
	internal const int LanternItemId = 42;

	internal const int TorchItemId = 109;

	internal const int LanternFuelDataKey = 10;

	internal const int UseCountDataKey = 2;

	internal const int UseRemainingPercentageDataKey = 11;

	internal static bool IsNormalLantern(Lantern lantern)
	{
		Item val = (((Object)(object)lantern != (Object)null) ? ((Component)lantern).GetComponent<Item>() : null);
		if ((Object)(object)val != (Object)null)
		{
			return val.itemID == 42;
		}
		return false;
	}

	internal static bool IsTorchLantern(Lantern lantern)
	{
		Item val = (((Object)(object)lantern != (Object)null) ? ((Component)lantern).GetComponent<Item>() : null);
		if ((Object)(object)val != (Object)null)
		{
			return val.itemID == 109;
		}
		return false;
	}

	internal static bool IsManagedBurnSource(Lantern lantern)
	{
		if (!IsNormalLantern(lantern))
		{
			return IsTorchLantern(lantern);
		}
		return true;
	}

	internal static float GetConfiguredBurnSeconds(Lantern lantern)
	{
		if (IsTorchLantern(lantern))
		{
			return BlackPeakLightExtensionPlugin.TorchBurnSecondsValue;
		}
		return BlackPeakLightExtensionPlugin.LanternBurnSecondsValue;
	}

	internal static bool IsTorchItem(Item item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return false;
		}
		if (item.itemID != 109 && !((Object)(object)((Component)item).GetComponent<ItemTorch>() != (Object)null))
		{
			return ((Object)item).name.ToLowerInvariant().Contains("torch");
		}
		return true;
	}

	internal static T GetOrAddComponent<T>(GameObject gameObject) where T : Component
	{
		T component = gameObject.GetComponent<T>();
		if ((Object)(object)component != (Object)null)
		{
			return component;
		}
		return gameObject.AddComponent<T>();
	}
}
internal static class Patch_ActionTorch_Diagnostics
{
}
[HarmonyPatch(typeof(Actions_Binoculars))]
internal static class Patch_Binoculars_NightVision
{
	[HarmonyPostfix]
	[HarmonyPatch("Subscribe")]
	private static void PostSubscribe(Actions_Binoculars __instance)
	{
		if (BlackPeakLightExtensionPlugin.BinocularNightVisionEnabled && !((Object)(object)__instance == (Object)null))
		{
			LightSourceItemHelpers.GetOrAddComponent<BinocularNightVisionRuntime>(((Component)__instance).gameObject).Init(__instance);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch("Unsubscribe")]
	private static void PostUnsubscribe(Actions_Binoculars __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			BinocularNightVisionRuntime component = ((Component)__instance).GetComponent<BinocularNightVisionRuntime>();
			if ((Object)(object)component != (Object)null)
			{
				component.DisableEffects();
				((Behaviour)component).enabled = false;
			}
		}
	}
}
internal static class Patch_Flare_SignalEnhancement
{
}
internal static class Patch_Item_TorchDiagnostics
{
}
[HarmonyPatch(typeof(Lantern))]
[HarmonyBefore(new string[] { "HnskNoah.BlackPeakRemix" })]
internal static class Patch_Lantern_BurnDuration
{
	private static readonly FieldInfo LitField = AccessTools.Field(typeof(Lantern), "lit");

	private static bool _loggedIntercept;

	[HarmonyPrefix]
	[HarmonyPatch("UpdateFuel")]
	[HarmonyPriority(800)]
	private static bool Prefix(Lantern __instance)
	{
		if (!LightSourceItemHelpers.IsManagedBurnSource(__instance))
		{
			return true;
		}
		if (!((ItemComponent)__instance).HasData((DataEntryKey)10))
		{
			return true;
		}
		if (!(LitField != null) || !(bool)LitField.GetValue(__instance) || !NetworkingUtilities.HasAuthority((MonoBehaviourPunCallbacks)(object)__instance))
		{
			return false;
		}
		float configuredBurnSeconds = LightSourceItemHelpers.GetConfiguredBurnSeconds(__instance);
		if (configuredBurnSeconds >= 100000f)
		{
			return false;
		}
		if (!_loggedIntercept)
		{
			_loggedIntercept = true;
			Item component = ((Component)__instance).GetComponent<Item>();
			BlackPeakLightExtensionPlugin.Log.LogInfo((object)$"[Lantern] Intercepted UpdateFuel for itemID={(ushort)(((Object)(object)component != (Object)null) ? component.itemID : 0)} with {configuredBurnSeconds:0}s");
		}
		float num = 60f / configuredBurnSeconds;
		FloatItemData data = ((ItemComponent)__instance).GetData<FloatItemData>((DataEntryKey)10);
		float num2 = (data.Value = Mathf.Clamp(data.Value - Time.deltaTime * num, 0f, __instance.startingFuel));
		if ((Object)(object)((ItemComponent)__instance).item != (Object)null)
		{
			((ItemComponent)__instance).item.SetUseRemainingPercentage(num2 / __instance.startingFuel);
		}
		if (num2 <= 0f && ((MonoBehaviourPun)__instance).photonView.IsMine)
		{
			__instance.SnuffLantern();
		}
		return false;
	}
}
internal static class Patch_LightVolume_SignalFlareBoost
{
}
[HarmonyBefore(new string[] { "HnskNoah.BlackPeakRemix" })]
[HarmonyPatch(typeof(Action_Torch), "Update")]
internal static class Patch_Torch_BurnDuration
{
	private static readonly FieldInfo ItemField = AccessTools.Field(typeof(ItemActionBase), "item");

	private static readonly FieldInfo TorchLightField = AccessTools.Field(typeof(Action_Torch), "torchLight");

	private static readonly FieldInfo ConsumeOnFullyUsedField = AccessTools.Field(typeof(Action_ReduceUses), "consumeOnFullyUsed");

	private static bool _loggedInit;

	[HarmonyPriority(800)]
	[HarmonyPostfix]
	private static void Postfix(Action_Torch __instance)
	{
		Item val = (Item)((ItemField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!LightSourceItemHelpers.IsTorchItem(val) || (Object)(object)val == (Object)null || ((Object)(object)((MonoBehaviourPun)val).photonView != (Object)null && !((MonoBehaviourPun)val).photonView.IsMine))
		{
			return;
		}
		OptionableIntItemData data = val.GetData<OptionableIntItemData>((DataEntryKey)2);
		if (!data.HasData)
		{
			return;
		}
		TorchBurnRuntime orAddComponent = LightSourceItemHelpers.GetOrAddComponent<TorchBurnRuntime>(((Component)val).gameObject);
		if (!orAddComponent.IsInitialized)
		{
			float remainingPercentage = val.GetData<FloatItemData>((DataEntryKey)11)?.Value ?? 1f;
			orAddComponent.Initialize(Mathf.Max(1f, (float)data.Value), remainingPercentage, BlackPeakLightExtensionPlugin.TorchBurnSecondsValue);
			if (!_loggedInit)
			{
				_loggedInit = true;
				BlackPeakLightExtensionPlugin.Log.LogInfo((object)$"[Torch] Runtime initialized with {orAddComponent.TotalSeconds:0}s total.");
			}
		}
		else if (Mathf.Abs(orAddComponent.TotalSeconds - BlackPeakLightExtensionPlugin.TorchBurnSecondsValue) > 0.01f)
		{
			orAddComponent.Reconfigure(BlackPeakLightExtensionPlugin.TorchBurnSecondsValue);
		}
		if (IsTorchActive(__instance))
		{
			orAddComponent.RemainingSeconds = Mathf.Max(0f, orAddComponent.RemainingSeconds - Time.deltaTime);
			float num = ((orAddComponent.TotalSeconds <= 0f) ? 0f : (orAddComponent.RemainingSeconds / orAddComponent.TotalSeconds));
			val.SetUseRemainingPercentage(num);
			if (orAddComponent.RemainingSeconds > 0f)
			{
				data.Value = Mathf.Max(1, Mathf.CeilToInt(orAddComponent.InitialUseCount * num));
				return;
			}
			data.Value = 0;
			TryConsumeTorch(val);
		}
	}

	private static bool IsTorchActive(Action_Torch torchAction)
	{
		Light val = (Light)((TorchLightField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if ((Object)(object)val != (Object)null && ((Behaviour)val).enabled)
		{
			return ((Component)val).gameObject.activeInHierarchy;
		}
		return false;
	}

	private static void TryConsumeTorch(Item item)
	{
		Action_ReduceUses component = ((Component)item).GetComponent<Action_ReduceUses>();
		if (!((Object)(object)component == (Object)null) && ConsumeOnFullyUsedField != null && (bool)ConsumeOnFullyUsedField.GetValue(component))
		{
			Character holderCharacter = item.holderCharacter;
			if (!((Object)(object)holderCharacter == (Object)null) && holderCharacter.IsLocal && !((Object)(object)holderCharacter.data == (Object)null) && !((Object)(object)holderCharacter.data.currentItem != (Object)(object)item))
			{
				((MonoBehaviour)item).StartCoroutine(item.ConsumeDelayed(false));
			}
		}
	}
}
[HarmonyPatch(typeof(Lantern), "Update")]
[HarmonyBefore(new string[] { "HnskNoah.BlackPeakRemix" })]
internal static class Patch_Torch_LightIntensity
{
	private static readonly FieldInfo LanternLightField = AccessTools.Field(typeof(Lantern), "lanternLight");

	private static readonly FieldInfo LightIntensityField = AccessTools.Field(typeof(Lantern), "lightIntensity");

	private static readonly FieldInfo CurrentLightIntensityField = AccessTools.Field(typeof(Lantern), "currentLightIntensity");

	[HarmonyPriority(800)]
	[HarmonyPostfix]
	private static void Postfix(Lantern __instance)
	{
		if (LightSourceItemHelpers.IsTorchLantern(__instance))
		{
			float num = Mathf.Clamp(BlackPeakLightExtensionPlugin.TorchLightIntensityValue, 0f, 30f);
			Light val = (Light)((LanternLightField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val != (Object)null)
			{
				val.intensity = num;
				val.range = Mathf.Clamp(BlackPeakLightExtensionPlugin.TorchLightRangeValue, 1f, 200f);
			}
			if (LightIntensityField != null)
			{
				LightIntensityField.SetValue(__instance, num);
			}
			if (CurrentLightIntensityField != null)
			{
				CurrentLightIntensityField.SetValue(__instance, num);
			}
		}
	}
}
[HarmonyBefore(new string[] { "HnskNoah.BlackPeakRemix" })]
[HarmonyPatch(typeof(Action_ReduceUses), "ReduceUsesRPC")]
internal static class Patch_Torch_ReduceUses
{
	private static bool _loggedIntercept;

	[HarmonyPriority(800)]
	[HarmonyPrefix]
	private static bool Prefix(Action_ReduceUses __instance)
	{
		Item value = Traverse.Create((object)__instance).Field("item").GetValue<Item>();
		if (!LightSourceItemHelpers.IsTorchItem(value))
		{
			return true;
		}
		if (!_loggedIntercept)
		{
			_loggedIntercept = true;
			BlackPeakLightExtensionPlugin.Log.LogInfo((object)"[Torch] Intercepted ReduceUsesRPC for torch.");
		}
		return false;
	}
}
internal sealed class SignalFlareRuntime
{
}
internal sealed class TorchBurnRuntime : MonoBehaviour
{
	internal bool IsInitialized { get; private set; }

	internal float InitialUseCount { get; private set; }

	internal float TotalSeconds { get; private set; }

	internal float RemainingSeconds { get; set; }

	internal void Initialize(float currentUseCount, float remainingPercentage, float totalSeconds)
	{
		InitialUseCount = Mathf.Max(1f, currentUseCount);
		TotalSeconds = Mathf.Max(1f, totalSeconds);
		RemainingSeconds = Mathf.Clamp01(remainingPercentage) * TotalSeconds;
		IsInitialized = true;
	}

	internal void Reconfigure(float totalSeconds)
	{
		totalSeconds = Mathf.Max(1f, totalSeconds);
		float num = ((TotalSeconds <= 0f) ? 1f : (RemainingSeconds / TotalSeconds));
		TotalSeconds = totalSeconds;
		RemainingSeconds = Mathf.Clamp01(num) * TotalSeconds;
	}
}