using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("BetterLanternsAndLights")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("https://github.com/bryon82/SailwindBetterLanternsAndLights")]
[assembly: AssemblyCompany("raddude")]
[assembly: AssemblyProduct("BetterLanternsAndLights")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("609d6bc4-2d2c-4fb9-98b4-b62976cadb47")]
[assembly: AssemblyFileVersion("1.1.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.3.0")]
[module: UnverifiableCode]
namespace BetterLanternsAndLights
{
[BepInPlugin("com.raddude.betterlanternsandlights", "Better Lanterns and Lights", "1.1.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class BLL_Plugin : BaseUnityPlugin
{
public const string PLUGIN_GUID = "com.raddude.betterlanternsandlights";
public const string PLUGIN_NAME = "Better Lanterns and Lights";
public const string PLUGIN_VERSION = "1.1.3";
public const string DYNAMIC_LIGHTS_GUID = "com.nandbrew.dynamiclights";
public const string BETTER_NPC_BOATS_GUID = "com.raddude.betternpcboats";
private static ManualLogSource _logger;
public static Light PlayerLight { get; internal set; }
internal static BLL_Plugin Instance { get; private set; }
internal static void LogDebug(string message)
{
_logger.LogDebug((object)message);
}
internal static void LogInfo(string message)
{
_logger.LogInfo((object)message);
}
internal static void LogWarning(string message)
{
_logger.LogWarning((object)message);
}
internal static void LogError(string message)
{
_logger.LogError((object)message);
}
private void Awake()
{
if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
return;
}
Instance = this;
_logger = ((BaseUnityPlugin)this).Logger;
Configs.InitializeConfigs();
Harmony harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.raddude.betterlanternsandlights");
bool flag = false;
bool flag2 = false;
foreach (PluginInfo value in Chainloader.PluginInfos.Values)
{
if (value.Metadata.GUID == "com.nandbrew.dynamiclights")
{
LogInfo("Enabling compatibility with Dynamic Lights.");
DynamicLights.ApplyPatch(harmony);
flag = true;
}
else if (value.Metadata.GUID == "com.raddude.betternpcboats")
{
LogInfo("Enabling compatibility with Better NPC Boats.");
BetterNPCBoats.ApplyPatch(harmony);
flag2 = true;
}
if (flag && flag2)
{
break;
}
}
SceneManager.sceneLoaded += DragonCliffs.SceneLoaded;
}
}
internal class BetterNPCBoats
{
public static void ApplyPatch(Harmony harmony)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
Type type = AccessTools.TypeByName("BetterNPCBoats.BetterNPCFishingBoat");
MethodInfo methodInfo = AccessTools.Method(type, "ToggleLanterns", (Type[])null, (Type[])null);
harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(BetterNPCBoats), "ToggleLanternsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
private static void ToggleLanternsPostfix(object __instance, bool state)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
Component val = (Component)__instance;
LanternFlicker componentInChildren = val.GetComponentInChildren<LanternFlicker>();
if (!((Object)(object)componentInChildren == (Object)null))
{
componentInChildren.SetFlicker(state);
}
}
}
internal class DynamicLights
{
public static void ApplyPatch(Harmony harmony)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
Type type = AccessTools.TypeByName("Dynamic_Lights.IslandStreetlightFire");
MethodInfo methodInfo = AccessTools.Method(type, "SetLight", (Type[])null, (Type[])null);
harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(DynamicLights), "SetLightPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
private static void SetLightPostfix(object __instance, bool newState)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
Component val = (Component)__instance;
LanternFlicker component = val.GetComponent<LanternFlicker>();
if (!((Object)(object)component == (Object)null))
{
component.SetFlicker(newState);
}
}
}
internal class InteriorPatches
{
[HarmonyPatch(typeof(InteriorEffectsTrigger))]
internal static class InteriorEffectsTriggerPatch
{
[HarmonyPatch("OnTriggerEnter")]
[HarmonyPostfix]
private static void OnTriggerEnter(Collider other)
{
if (!((Object)(object)other == (Object)null))
{
LanternFlicker componentInParent = ((Component)other).GetComponentInParent<LanternFlicker>();
if (!((Object)(object)componentInParent == (Object)null))
{
componentInParent.isInside = true;
}
}
}
[HarmonyPatch("OnTriggerExit")]
[HarmonyPostfix]
private static void OnTriggerExit(Collider other)
{
if (!((Object)(object)other == (Object)null))
{
LanternFlicker componentInParent = ((Component)other).GetComponentInParent<LanternFlicker>();
if (!((Object)(object)componentInParent == (Object)null))
{
componentInParent.isInside = false;
}
}
}
}
}
internal class IslandLightsPatches
{
[HarmonyPatch(typeof(IslandStreetlightsManager), "Awake")]
internal class IslandlightsAwakePatch
{
public static void Postfix(IslandStreetlightsManager __instance)
{
Light[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Light>();
Light[] array = componentsInChildren;
foreach (Light val in array)
{
if (((Object)((Component)val).transform.parent).name.Contains("candle") || ((Object)val).name.Contains("Brazier") || ((Object)((Component)val).transform.parent).name.Contains("shop stove"))
{
LanternFlicker lanternFlicker = ((Component)val).gameObject.AddComponent<LanternFlicker>();
lanternFlicker.SetFlicker(enable: true);
}
}
}
}
}
internal class LanternPatches
{
[HarmonyPatch(typeof(PrefabsDirectory), "PopulateShipItems")]
internal class AddPaperLanternFlickerPatch
{
public static void Postfix(PrefabsDirectory __instance)
{
int[] array = new int[7] { 110, 111, 112, 113, 114, 133, 134 };
int[] array2 = array;
foreach (int num in array2)
{
__instance.directory[num].AddComponent<LanternFlicker>();
}
}
}
[HarmonyPatch(typeof(ShipItemLight), "SetLight")]
internal class ShipItemLightSetLightPatch
{
public static void Postfix(ShipItemLight __instance, bool state)
{
LanternFlicker component = ((Component)__instance).GetComponent<LanternFlicker>();
if (!((Object)(object)component == (Object)null))
{
component.SetFlicker(state);
}
}
}
[HarmonyPatch(typeof(GPButtonInventorySlot), "Awake")]
public class AddInventoryLantern
{
public static void Postfix(GPButtonInventorySlot __instance)
{
InventoryLantern inventoryLantern = ((Component)__instance).gameObject.AddComponent<InventoryLantern>();
inventoryLantern.InventorySlot = __instance;
}
}
}
internal class PlayerLightPatches
{
[HarmonyPatch(typeof(PlayerControllerMirror), "Awake")]
internal class PlayerControllerMirrorAwakePatch
{
public static void Postfix()
{
Camera main = Camera.main;
BLL_Plugin.PlayerLight = ((main != null) ? ((Component)main).GetComponent<Light>() : null);
((Behaviour)BLL_Plugin.PlayerLight).enabled = Configs.enablePlayerLight.Value;
}
}
}
internal class StreetLightPatches
{
[HarmonyPatch(typeof(IslandStreetlight))]
internal class IslandStreetlightPatches
{
[HarmonyPostfix]
[HarmonyPatch("Awake")]
public static void AddFlicker(IslandStreetlight __instance, Light ___light)
{
if (!(((Object)___light).name == "senna_lantern_light"))
{
((Component)__instance).gameObject.AddComponent<LanternFlicker>();
}
}
[HarmonyPostfix]
[HarmonyPatch("SetLight")]
public static void AddFlickerToLight(IslandStreetlight __instance, bool newState)
{
LanternFlicker component = ((Component)__instance).GetComponent<LanternFlicker>();
if (!((Object)(object)component == (Object)null))
{
component.SetFlicker(newState);
}
}
}
}
internal class DragonCliffs
{
internal const string DRAGON_CLIFFS_SCENE = "island 9 E Dragon Cliffs";
internal static List<GameObject> DCGateLightGOs { get; private set; }
internal static void SceneLoaded(Scene scene, LoadSceneMode _)
{
if (((Scene)(ref scene)).name == "island 9 E Dragon Cliffs")
{
Initialize();
}
}
internal static void Initialize()
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: 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)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: 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_0128: Unknown result type (might be due to invalid IL or missing references)
DCGateLightGOs = new List<GameObject>();
Vector3[] array = (Vector3[])(object)new Vector3[2]
{
new Vector3(0f, 3.35f, 3.1f),
new Vector3(0f, -3.35f, 3.1f)
};
GameObject val = GameObject.Find("island 9 E (dragon cliffs) scenery");
Transform val2 = ((IEnumerable<Transform>)((Component)val.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.Equals("east_gate (4)")));
Transform child = ((IEnumerable<Transform>)((Component)val.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.Equals("east_street_rope (1)"))).GetChild(0);
Vector3[] array2 = array;
foreach (Vector3 localPosition in array2)
{
GameObject val3 = Object.Instantiate<GameObject>(((Component)child).gameObject, val2);
val3.transform.localScale = new Vector3(1.33f, 1.33f, 1.33f);
val3.transform.localPosition = localPosition;
val3.transform.localEulerAngles = new Vector3(0f, 0f, 270f);
val3.GetComponent<Light>().range = 50f;
val3.GetComponent<Light>().intensity = 1.5f;
DCGateLightGOs.Add(val3);
val3.SetActive(Configs.addDcGateLights.Value);
}
BLL_Plugin.LogDebug("Dragon Cliffs gate lights added");
}
}
internal class InventoryLantern : MonoBehaviour
{
internal GPButtonInventorySlot InventorySlot { get; set; }
private void LateUpdate()
{
if (Configs.enableInventoryLantern.Value && ((GoPointerButton)InventorySlot).IsLookedAt())
{
ShipItem currentItem = InventorySlot.currentItem;
if (currentItem is ShipItemLight && (GameInput.GetKeyDown((InputName)9) || Input.GetMouseButtonDown(1)))
{
((GoPointerButton)currentItem).OnAltActivate();
}
}
}
}
internal class LanternFlicker : MonoBehaviour
{
private bool isStreetLight = false;
internal Coroutine flickerCoroutine;
private Material paperMaterial;
private Material paperOnMat;
private Material paperOffMat;
private Light light;
private Color baseEmission;
private float minIntensity = 1f;
internal float maxIntensity = 1.5f;
private float minEmission = 0.5f;
private float maxEmission = 0.8f;
private float minWindSpeed = 20f;
private float maxWindSpeed = 40f;
private float minFlickerSpeed = 0.5f;
private float maxFlickerSpeed = 2f;
private float minFastSpeed = 6f;
private float maxFastSpeed = 15f;
private float minFastAmount = 0.2f;
private float maxFastAmount = 0.5f;
internal float lightIntensity;
internal bool isInside = false;
private void Awake()
{
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
light = ((Component)this).GetComponentInChildren<Light>();
maxIntensity = light.intensity;
minIntensity = light.intensity - 0.5f;
ShipItemLight component = ((Component)this).GetComponent<ShipItemLight>();
Renderer val = null;
if ((Object)(object)component != (Object)null)
{
val = component.GetPrivateField<Renderer>("paperRenderer");
paperOffMat = component.GetPrivateField<Material>("paperOffMat");
paperOnMat = ((val != null) ? val.sharedMaterial : null);
}
IslandStreetlight component2 = ((Component)this).GetComponent<IslandStreetlight>();
if ((Object)(object)component2 != (Object)null)
{
val = component2.GetPrivateField<Renderer>("renderer");
paperOffMat = component2.GetPrivateField<Material>("offMat");
paperOnMat = ((val != null) ? val.sharedMaterial : null);
isStreetLight = true;
}
if ((Object)(object)val != (Object)null)
{
paperMaterial = val.material;
}
if ((Object)(object)paperOnMat != (Object)null)
{
baseEmission = paperOnMat.GetColor("_EmissionColor");
}
}
internal void SetFlicker(bool enable)
{
if (((Component)this).gameObject.activeInHierarchy)
{
if (Configs.enableLanternFlicker.Value && enable && flickerCoroutine == null)
{
flickerCoroutine = ((MonoBehaviour)this).StartCoroutine(Flicker());
}
else if (!enable && flickerCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(flickerCoroutine);
flickerCoroutine = null;
}
}
}
private IEnumerator Flicker()
{
float slowTime = Random.value * 100f;
float fastTime = Random.value * 100f;
while (true)
{
float windSpeed = ((Vector3)(ref Wind.currentWind)).magnitude;
if (isInside || isStreetLight)
{
windSpeed = 0f;
}
float windAmount = Mathf.InverseLerp(minWindSpeed, maxWindSpeed, windSpeed);
float slowSpeed = Mathf.Lerp(minFlickerSpeed, maxFlickerSpeed, windAmount);
float fastSpeed = Mathf.Lerp(minFastSpeed, maxFastSpeed, windAmount);
slowTime += Time.deltaTime * slowSpeed;
fastTime += Time.deltaTime * fastSpeed;
float slow = Mathf.PerlinNoise(slowTime, 0f);
float fast = Mathf.PerlinNoise(fastTime, 100f);
float fastAmount = Mathf.Lerp(minFastAmount, maxFastAmount, windAmount);
float slowAmount = 1f - fastAmount;
float flicker = slow * slowAmount + fast * fastAmount;
flicker = Mathf.Clamp01(flicker);
lightIntensity = Mathf.Lerp(minIntensity, maxIntensity, flicker);
light.intensity = lightIntensity;
if ((Object)(object)paperOffMat == (Object)null)
{
yield return null;
continue;
}
float materialAmount = Mathf.Lerp(0.9f, 1f, flicker);
paperMaterial.Lerp(paperOffMat, paperOnMat, materialAmount);
float emissionStrength = Mathf.Lerp(minEmission, maxEmission, flicker);
paperMaterial.SetColor("_EmissionColor", baseEmission * emissionStrength);
yield return null;
}
}
}
internal class Configs
{
internal static ConfigEntry<bool> enableLanternFlicker;
internal static ConfigEntry<bool> addDcGateLights;
internal static ConfigEntry<bool> enablePlayerLight;
internal static ConfigEntry<bool> enableInventoryLantern;
internal static void InitializeConfigs()
{
ConfigFile config = ((BaseUnityPlugin)BLL_Plugin.Instance).Config;
enableLanternFlicker = config.Bind<bool>("Settings", "Enable lantern flicker", true, (ConfigDescription)null);
addDcGateLights = config.Bind<bool>("Settings", "Add Dragon Cliffs Gate Lights", true, (ConfigDescription)null);
enablePlayerLight = config.Bind<bool>("Settings", "Ambient Player Light", false, "Light emanating from the player.");
enableInventoryLantern = config.Bind<bool>("Settings", "Activate Lantern In Inventory", true, "The ability to activate the lantern while it is in an inventory slot.");
enablePlayerLight.SettingChanged += delegate
{
UpdatePlayerLight();
};
addDcGateLights.SettingChanged += delegate
{
UpdateDCGateLights();
};
}
internal static void UpdateDCGateLights()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
Scene sceneByName = SceneManager.GetSceneByName("island 9 E Dragon Cliffs");
if (((Scene)(ref sceneByName)).isLoaded && DragonCliffs.DCGateLightGOs == null)
{
return;
}
foreach (GameObject dCGateLightGO in DragonCliffs.DCGateLightGOs)
{
if ((Object)(object)dCGateLightGO != (Object)null)
{
dCGateLightGO.SetActive(addDcGateLights.Value);
}
}
}
internal static void UpdatePlayerLight()
{
if ((Object)(object)BLL_Plugin.PlayerLight != (Object)null)
{
((Behaviour)BLL_Plugin.PlayerLight).enabled = enablePlayerLight.Value;
}
}
}
internal static class Extensions
{
public static T GetPrivateField<T>(this object obj, string field)
{
return (T)Traverse.Create(obj).Field(field).GetValue();
}
}
}
namespace BetterLanternsAndLights.Patches
{
internal class StovePatches
{
[HarmonyPatch(typeof(PrefabsDirectory), "PopulateShipItems")]
internal class AddPaperLanternFlickerPatch
{
public static void Postfix(PrefabsDirectory __instance)
{
int[] array = new int[6] { 105, 106, 107, 377, 378, 379 };
int[] array2 = array;
foreach (int num in array2)
{
__instance.directory[num].AddComponent<LanternFlicker>();
}
}
}
[HarmonyPatch(typeof(ShipItemStove))]
internal class StoveFuelTriggerUpdatePatch
{
[HarmonyPostfix]
[HarmonyPatch("ExtraLateUpdate")]
public static void SetLightFlicker(ShipItemStove __instance, StoveFuelTrigger ___fuelTrigger)
{
if (!((Object)(object)___fuelTrigger == (Object)null))
{
LanternFlicker component = ((Component)__instance).GetComponent<LanternFlicker>();
if (!((Object)(object)component == (Object)null) && component.flickerCoroutine != null)
{
___fuelTrigger.GetPrivateField<Light>("light").intensity = component.lightIntensity;
}
}
}
[HarmonyPostfix]
[HarmonyPatch("OnItemClick")]
public static void ToggleFlicker(ShipItemStove __instance, StoveFuelTrigger ___fuelTrigger, PickupableItem heldItem)
{
if (!((Object)(object)___fuelTrigger == (Object)null))
{
LanternFlicker component = ((Component)__instance).GetComponent<LanternFlicker>();
if (!((Object)(object)component == (Object)null) && component.flickerCoroutine == null && !((Object)(object)((Component)heldItem).GetComponent<StoveFuel>() == (Object)null))
{
component.maxIntensity = (float)(___fuelTrigger.GetPrivateField<int>("currentFuel") / ___fuelTrigger.GetPrivateField<int>("maxFuel")) * ___fuelTrigger.GetPrivateField<float>("initialLightIntensity");
component.SetFlicker(enable: true);
}
}
}
}
[HarmonyPatch(typeof(StoveFuelTrigger), "UnregisterBurntFuel")]
internal class StoveFuelTriggerUnregisterBurntFuelPatch
{
[HarmonyPostfix]
[HarmonyPatch("UnregisterBurntFuel")]
public static void StopFlicker(ShipItemStove ___stove, float ___initialLightIntensity, int ___currentFuel, int ___maxFuel)
{
LanternFlicker component = ((Component)___stove).GetComponent<LanternFlicker>();
if (!((Object)(object)component == (Object)null))
{
component.maxIntensity = (float)(___currentFuel / ___maxFuel) * ___initialLightIntensity;
if (___currentFuel <= 0)
{
component.SetFlicker(enable: false);
}
}
}
}
}
}