Decompiled source of BrighterNights v0.5.0

BrighterNights.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JG224.BrighterNights.Core;
using JG224.BrighterNights.Runtime;
using JG224.ModCore.API;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.PostProcessing;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BrighterNights")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyInformationalVersion("0.5.0")]
[assembly: AssemblyProduct("BrighterNights")]
[assembly: AssemblyTitle("BrighterNights")]
[assembly: AssemblyVersion("0.5.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 JG224.BrighterNights
{
	internal sealed class BrighterNightsConfig
	{
		private readonly List<ConfigEntryBase> _entries = new List<ConfigEntryBase>();

		internal ConfigEntry<bool> Enabled { get; }

		internal ConfigEntry<float> NightStrength { get; }

		internal ConfigEntry<float> SwampStrength { get; }

		internal ConfigEntry<bool> AffectInteriors { get; }

		internal ConfigEntry<float> InteriorStrength { get; }

		internal BrighterNightsConfig(ConfigFile file)
		{
			Enabled = Add<bool>(file.Bind<bool>("General", "Enabled", true, "Improve dark-scene visibility on this client. Disable to restore the normal view immediately."));
			NightStrength = Add<float>(file.Bind<float>("Visibility", "NightStrength", 0.1f, Strength("Nighttime visibility boost. Fades in from 18:00 to 20:24, stays full until 06:00, then fades out by 08:00. Zero from 08:00 to 18:00.")));
			SwampStrength = Add<float>(file.Bind<float>("Visibility", "SwampStrength", 0.15f, Strength("Minimum outdoor Swamp visibility boost, including daytime. At night the stronger boost wins; they do not stack.")));
			AffectInteriors = Add<bool>(file.Bind<bool>("Visibility", "AffectInteriors", true, "Apply InteriorStrength in the game's dungeon interiors (caves, crypts, chambers and mines). Buildings and shelter do not count. Off leaves interiors unchanged even at night or in the Swamp."));
			InteriorStrength = Add<float>(file.Bind<float>("Visibility", "InteriorStrength", 0.15f, Strength("Visibility boost inside dungeon interiors, independent of outdoor time and biome.")));
		}

		internal IEnumerable<IDisposable> RegisterMetadata(ICoreServices services, ModuleId owner)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			foreach (ConfigEntryBase entry in _entries)
			{
				yield return services.Configuration.Register(new ConfigSettingDescriptor(owner, entry.Definition.Section, entry.Definition.Key, (ConfigScope)1, (Func<string>)(() => Convert.ToString(entry.BoxedValue, CultureInfo.InvariantCulture)), 1));
			}
		}

		private ConfigEntry<T> Add<T>(ConfigEntry<T> entry)
		{
			_entries.Add((ConfigEntryBase)(object)entry);
			return entry;
		}

		private static ConfigDescription Strength(string description)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			return new ConfigDescription(description + " Range 0 to 1; 0 disables this boost. This changes the camera's neutral gamma, not light sources or fog.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>());
		}
	}
	[BepInPlugin("com.jg224.brighternights", "BrighterNights", "0.5.0")]
	[BepInProcess("valheim.exe")]
	[BepInDependency("com.jg224.modcore", "0.5.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.jg224.brighternights";

		public const string PluginName = "BrighterNights";

		public const string PluginVersion = "0.5.0";

		public const string ModCoreGuid = "com.jg224.modcore";

		public const string ConfigFileName = "com.jg224.brighternights.cfg";

		public const int ProtocolVersion = 1;

		public static readonly ModuleId ModuleId = new ModuleId("brighternights");

		private readonly List<IDisposable> _registrations = new List<IDisposable>();

		private Harmony _harmony;

		private bool _active;

		private bool _shutDown;

		private static ModuleRuntimeState _state;

		private static string _reason;

		private static bool _registered;

		internal static ICoreServices Core { get; private set; }

		internal static BrighterNightsConfig Settings { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				if (!ModCoreApi.IsAvailable)
				{
					throw new InvalidOperationException("ModCore did not initialize before BrighterNights.");
				}
				Core = ModCoreApi.Services;
				if (!string.Equals(Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath), "com.jg224.brighternights.cfg", StringComparison.Ordinal))
				{
					throw new InvalidOperationException("Unexpected BrighterNights configuration filename.");
				}
				Settings = new BrighterNightsConfig(((BaseUnityPlugin)this).Config);
				RegisterWithCore();
				_harmony = new Harmony("com.jg224.brighternights");
				_harmony.PatchAll(typeof(Plugin).Assembly);
				_active = true;
				Game.isModded = true;
				ReportState((ModuleRuntimeState)2, "Client-local visibility adjustment ready.");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"BrighterNights 0.5.0 loaded; client only.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("BrighterNights failed to initialize safely: " + ex));
				if (Core != null)
				{
					ReportState((ModuleRuntimeState)5, ex.Message);
				}
				Shutdown();
				throw;
			}
		}

		private void RegisterWithCore()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			SemanticVersion val = default(SemanticVersion);
			if (!SemanticVersion.TryParse("0.5.0", ref val))
			{
				throw new InvalidOperationException("Invalid BrighterNights release version.");
			}
			_registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "com.jg224.brighternights", "BrighterNights", val, 1, (ModuleSide)1, (ModuleRequirement)1, 0uL, 1, 1)));
			_registered = true;
			_registrations.AddRange(Settings.RegisterMetadata(Core, ModuleId));
			_registrations.Add(Core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)9, (Action<LifecycleEvent>)delegate
			{
				VisibilityRuntime.Reset();
			}, 0));
			_registrations.Add(Core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)3, (Action<LifecycleEvent>)delegate
			{
				VisibilityRuntime.Reset();
			}, 0));
		}

		private void LateUpdate()
		{
			if (!_active)
			{
				return;
			}
			try
			{
				VisibilityRuntime.Tick();
			}
			catch (Exception ex)
			{
				_active = false;
				VisibilityRuntime.Reset();
				ReportState((ModuleRuntimeState)5, "Visibility adjustment stopped: " + ex.Message);
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}

		internal static void ReportState(ModuleRuntimeState state, string reason)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			//IL_0057: 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)
			if (reason != null && reason.Length > 1024)
			{
				reason = reason.Substring(0, 1024);
			}
			if (_state == state && _reason == reason)
			{
				return;
			}
			_state = state;
			_reason = reason;
			if (_registered)
			{
				ICoreServices core = Core;
				if (core != null)
				{
					core.Modules.SetState(ModuleId, state, reason);
				}
			}
			if ((int)state != 2)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)reason);
				}
			}
		}

		private void OnDisable()
		{
			VisibilityRuntime.Reset();
		}

		private void OnDestroy()
		{
			Shutdown();
		}

		private void Shutdown()
		{
			if (_shutDown)
			{
				return;
			}
			_shutDown = true;
			_active = false;
			VisibilityRuntime.Reset();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			for (int num = _registrations.Count - 1; num >= 0; num--)
			{
				try
				{
					_registrations[num].Dispose();
				}
				catch (Exception ex)
				{
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					if (logger != null)
					{
						logger.LogWarning((object)("Registration cleanup failed: " + ex.Message));
					}
				}
			}
			_registrations.Clear();
			_registered = false;
			Core = null;
			Settings = null;
			Log = null;
			_reason = null;
		}
	}
}
namespace JG224.BrighterNights.Core
{
	public static class VisibilityRules
	{
		public const float DefaultNightStrength = 0.1f;

		public const float DefaultSwampStrength = 0.15f;

		public const float DefaultInteriorStrength = 0.15f;

		public const float DefaultTransitionRate = 3f;

		public static float NightFactor(float dayFraction)
		{
			if (!IsFinite(dayFraction) || dayFraction < 0f || dayFraction > 1f || (dayFraction >= 1f / 3f && dayFraction <= 0.75f))
			{
				return 0f;
			}
			if (dayFraction <= 0.25f || dayFraction >= 0.85f)
			{
				return 1f;
			}
			float num = ((dayFraction < 1f / 3f) ? ((1f / 3f - dayFraction) / 0.08333334f) : ((dayFraction - 0.75f) / 0.1f));
			return ClampStrength(num * num * (3f - 2f * num));
		}

		public static float GetTargetLift(bool enabled, float nightFactor, bool isSwamp, bool isInterior, bool affectInteriors, float nightStrength, float swampStrength, float interiorStrength)
		{
			if (!enabled)
			{
				return 0f;
			}
			if (isInterior)
			{
				if (!affectInteriors)
				{
					return 0f;
				}
				return ClampStrength(interiorStrength);
			}
			float val = ClampStrength(nightFactor) * ClampStrength(nightStrength);
			float val2 = (isSwamp ? ClampStrength(swampStrength) : 0f);
			return Math.Max(val, val2);
		}

		public static float SmoothLift(float current, float target, float unscaledDeltaTime, float transitionRate)
		{
			target = ClampStrength(target);
			if (target == 0f)
			{
				return 0f;
			}
			current = ClampStrength(current);
			if (!IsFinite(unscaledDeltaTime) || unscaledDeltaTime <= 0f || !IsFinite(transitionRate) || transitionRate <= 0f)
			{
				return current;
			}
			double num = Math.Exp((0.0 - (double)transitionRate) * (double)unscaledDeltaTime);
			return ClampStrength((float)((double)target + (double)(current - target) * num));
		}

		public static float ClampStrength(float value)
		{
			if (!IsFinite(value) || value <= 0f)
			{
				return 0f;
			}
			if (!(value >= 1f))
			{
				return value;
			}
			return 1f;
		}

		private static bool IsFinite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}
	}
}
namespace JG224.BrighterNights.Runtime
{
	internal static class VisibilityRuntime
	{
		private const float GammaScale = 0.2f;

		private static GameCamera _gameCamera;

		private static Camera _camera;

		private static PostProcessingBehaviour _postProcessing;

		private static ColorGradingComponent _grading;

		private static ColorGradingModel _model;

		private static ColorGradingModel _sourceModel;

		private static float _strength;

		private static float _preparedStrength = -1f;

		private static float _nextRendererLookup;

		private static bool _preparing;

		private static bool _renderFaulted;

		private static bool _sourceChanged;

		internal static void Tick()
		{
			if (_renderFaulted)
			{
				return;
			}
			GameCamera instance = GameCamera.instance;
			if ((Object)(object)_gameCamera != (Object)(object)instance)
			{
				Reset();
				_gameCamera = instance;
				if (Object.op_Implicit((Object)(object)instance))
				{
					_camera = ((Component)instance).GetComponent<Camera>();
					_postProcessing = ((Component)instance).GetComponent<PostProcessingBehaviour>();
					_nextRendererLookup = Time.unscaledTime + 1f;
				}
			}
			else if (Object.op_Implicit((Object)(object)instance) && (!Object.op_Implicit((Object)(object)_camera) || !Object.op_Implicit((Object)(object)_postProcessing)) && Time.unscaledTime >= _nextRendererLookup)
			{
				_camera = ((Component)instance).GetComponent<Camera>();
				_postProcessing = ((Component)instance).GetComponent<PostProcessingBehaviour>();
				_nextRendererLookup = Time.unscaledTime + 1f;
			}
			float target = GetTarget();
			_strength = VisibilityRules.SmoothLift(_strength, target, Time.unscaledDeltaTime, 3f);
			if (target == 0f)
			{
				ReleaseGrading();
				Plugin.ReportState((ModuleRuntimeState)2, "Client-local visibility adjustment ready.");
			}
			else if (!Object.op_Implicit((Object)(object)_camera) || !Object.op_Implicit((Object)(object)_postProcessing) || !((Behaviour)_postProcessing).isActiveAndEnabled || !Object.op_Implicit((Object)(object)_postProcessing.profile) || _postProcessing.profile.colorGrading == null || !((PostProcessingModel)_postProcessing.profile.colorGrading).enabled)
			{
				_strength = 0f;
				ReleaseGrading();
				Plugin.ReportState((ModuleRuntimeState)3, "The game camera's color grading is unavailable or disabled; BrighterNights is inactive. Restore the normal renderer or check graphics mods.");
			}
			else
			{
				Plugin.ReportState((ModuleRuntimeState)2, "Client-local visibility adjustment ready.");
			}
		}

		private static float GetTarget()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			BrighterNightsConfig settings = Plugin.Settings;
			Player localPlayer = Player.m_localPlayer;
			if (settings == null || !settings.Enabled.Value || !Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)EnvMan.instance) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || ((Character)localPlayer).InIntro())
			{
				return 0f;
			}
			return VisibilityRules.GetTargetLift(enabled: true, VisibilityRules.NightFactor(EnvMan.instance.GetDayFraction()), (int)localPlayer.GetCurrentBiome() == 2, ((Character)localPlayer).InInterior(), settings.AffectInteriors.Value, settings.NightStrength.Value, settings.SwampStrength.Value, settings.InteriorStrength.Value);
		}

		internal static void Prepare(ColorGradingComponent source, Material material, bool sourceDirty)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//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_012f: Unknown result type (might be due to invalid IL or missing references)
			if (_preparing || _renderFaulted)
			{
				return;
			}
			if (sourceDirty && _sourceModel == ((PostProcessingComponent<ColorGradingModel>)(object)source).model)
			{
				_sourceChanged = true;
			}
			if (_strength <= 0f || ((PostProcessingComponentBase)source).context == null || !Object.op_Implicit((Object)(object)_camera) || (Object)(object)_gameCamera != (Object)(object)GameCamera.instance || (Object)(object)((PostProcessingComponentBase)source).context.camera != (Object)(object)_camera || !Object.op_Implicit((Object)(object)material) || ((PostProcessingComponent<ColorGradingModel>)(object)source).model == null || !((PostProcessingComponentBase)source).active || GetTarget() == 0f)
			{
				return;
			}
			_preparing = true;
			try
			{
				if (_grading == null)
				{
					_model = new ColorGradingModel();
					_grading = new ColorGradingComponent();
				}
				((PostProcessingComponent<ColorGradingModel>)(object)_grading).Init(((PostProcessingComponentBase)source).context, _model);
				if (_sourceModel != ((PostProcessingComponent<ColorGradingModel>)(object)source).model || _sourceChanged || sourceDirty || Mathf.Abs(_preparedStrength - _strength) >= 0.001f)
				{
					Settings settings = ((PostProcessingComponent<ColorGradingModel>)(object)source).model.settings;
					settings.colorWheels.linear.gamma.a += _strength * 0.2f;
					_model.settings = settings;
					_sourceModel = ((PostProcessingComponent<ColorGradingModel>)(object)source).model;
					_preparedStrength = _strength;
					_sourceChanged = false;
				}
				((PostProcessingComponentRenderTexture<ColorGradingModel>)(object)_grading).Prepare(material);
			}
			catch (Exception ex)
			{
				_renderFaulted = true;
				_strength = 0f;
				Plugin.ReportState((ModuleRuntimeState)5, "BrighterNights stopped after a rendering failure; see the error log. " + ex.Message);
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)ex);
				}
				try
				{
					((PostProcessingComponentRenderTexture<ColorGradingModel>)(object)source).Prepare(material);
				}
				finally
				{
					ReleaseGrading();
				}
			}
			finally
			{
				_preparing = false;
			}
		}

		private static void ReleaseGrading()
		{
			if (_grading != null && _model != null)
			{
				((PostProcessingComponentBase)_grading).OnDisable();
			}
			_grading = null;
			_model = null;
			_sourceModel = null;
			_preparedStrength = -1f;
			_sourceChanged = false;
		}

		internal static void Reset()
		{
			_strength = 0f;
			ReleaseGrading();
			_gameCamera = null;
			_camera = null;
			_postProcessing = null;
			_nextRendererLookup = 0f;
			_renderFaulted = false;
		}
	}
}
namespace JG224.BrighterNights.Patches
{
	[HarmonyPatch(typeof(ColorGradingComponent), "Prepare")]
	internal static class ColorGradingPreparePatch
	{
		[HarmonyPrefix]
		private static void Prefix(ColorGradingComponent __instance, out bool __state)
		{
			__state = ((PostProcessingComponent<ColorGradingModel>)(object)__instance).model != null && ((PostProcessingComponent<ColorGradingModel>)(object)__instance).model.isDirty;
		}

		[HarmonyPostfix]
		private static void Postfix(ColorGradingComponent __instance, Material uberMaterial, bool __state)
		{
			VisibilityRuntime.Prepare(__instance, uberMaterial, __state);
		}
	}
}