Decompiled source of GlowierSticks v0.8.0

GlowierSticks.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using GTFO.API;
using GameData;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SNetwork;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("GlowierSticks")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GlowierSticks")]
[assembly: AssemblyTitle("GlowierSticks")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace GlowierSticks
{
	public static class Configuration
	{
		public static class LocalConfig
		{
			private static readonly ConfigFile configFile;

			public const double DEFAULT_GLOWSTICK_RANGE = 15.0;

			private static readonly ConfigEntry<double> _glowstickRange;

			public const bool DEFAULT_DO_LIGHTNESS_NORMALIZATION = true;

			private static readonly ConfigEntry<bool> _doLightnessRangeNormalization;

			public const float DEFAULT_GLOWSTICK_FADE_IN_TIME = 3f;

			private static readonly ConfigEntry<float> _glowstickFadeInTime;

			public const float DEFAULT_GLOWSTICK_DURATION = 237f;

			private static readonly ConfigEntry<float> _glowstickDuration;

			public const float DEFAULT_GLOWSTICK_FADE_OUT_TIME = 60f;

			private static readonly ConfigEntry<float> _glowstickFadeOutTime;

			public const int DEFAULT_GLOWSTICK_COUNT_MAX = 8;

			private static readonly ConfigEntry<int> _glowstickCountMax;

			public const int DEFAULT_GLOWSTICK_COUNT_MIN = 7;

			private static readonly ConfigEntry<int> _glowstickCountMin;

			private static readonly ConfigEntry<bool> _doDebug;

			public static double GlowstickRange => _glowstickRange.Value;

			public static bool DoLightnessRangeNormalization => _doLightnessRangeNormalization.Value;

			public static float GlowstickFadeInTime => _glowstickFadeInTime.Value;

			public static float GlowstickDuration => _glowstickDuration.Value;

			public static float GlowstickFadeOutTime => _glowstickFadeOutTime.Value;

			public static int GlowstickCountMax => _glowstickCountMax.Value;

			public static int GlowstickCountMin => _glowstickCountMin.Value;

			public static bool DoDebug => _doDebug.Value;

			static LocalConfig()
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "GlowierSticks.cfg"), true);
				_glowstickRange = configFile.Bind<double>("General Settings", "Target glowstick range", 15.0, "Total range of glowstick light, in meters (base game uses 5m); depending on color, brightly lit area reaches up to ~75% of this distance");
				_doLightnessRangeNormalization = configFile.Bind<bool>("General Settings", "Light range normalization", true, "Whether to adjust glowstick light range so that every glowstick light color visually reaches about as far as a base-game yellow glowstick would");
				_glowstickFadeInTime = configFile.Bind<float>("General Settings", "Glowstick fade-in time", 3f, "Time required for a glowstick to reach full brightness from the moment it's thrown, in seconds (base game uses 2)");
				_glowstickDuration = configFile.Bind<float>("General Settings", "Glowstick duration", 237f, "Time glowstick light will shine for at full brightness, in seconds (base game uses 60)");
				_glowstickFadeOutTime = configFile.Bind<float>("General Settings", "Glowstick fade-out time", 60f, "Time over which glowstick light will gradually fade out once its duration expires; (base game uses 3)");
				_glowstickCountMax = configFile.Bind<int>("Generation Settings", "Glowstick maximum count", 8, "Maximum number of glowsticks in a randomly generated pack");
				_glowstickCountMin = configFile.Bind<int>("Generation Settings", "Glowstick minimum count", 7, "Miminum number of glowsticks in a randomly generated pack");
				_doDebug = configFile.Bind<bool>("Misc Settings", "Debug output", false, "Whether to output various debugging messages");
			}
		}

		public static class RemoteConfig
		{
			internal struct ConfigPacket
			{
				public double GlowstickRange;

				public bool DoLightnessRangeNormalization;

				public float GlowstickFadeInTime;

				public float GlowstickDuration;

				public float GlowstickFadeOutTime;

				public int GlowstickCountMax;

				public int GlowstickCountMin;

				public ConfigPacket()
				{
					GlowstickRange = LocalConfig.GlowstickRange;
					DoLightnessRangeNormalization = LocalConfig.DoLightnessRangeNormalization;
					GlowstickFadeInTime = LocalConfig.GlowstickFadeInTime;
					GlowstickDuration = LocalConfig.GlowstickDuration;
					GlowstickFadeOutTime = LocalConfig.GlowstickFadeOutTime;
					GlowstickCountMax = LocalConfig.GlowstickCountMax;
					GlowstickCountMin = LocalConfig.GlowstickCountMin;
				}
			}

			private static bool _isReady = false;

			private static double _glowstickRange = 15.0;

			private static bool _doLightnessRangeNormalization = true;

			private static float _glowstickFadeInTime = 3f;

			private static float _glowstickDuration = 237f;

			private static float _glowstickFadeOutTime = 60f;

			private static int _glowstickCountMax = 8;

			private static int _glowstickCountMin = 7;

			public static bool IsReady => _isReady;

			public static double GlowstickRange => _glowstickRange;

			public static bool DoLightnessRangeNormalization => _doLightnessRangeNormalization;

			public static float GlowstickFadeInTime => _glowstickFadeInTime;

			public static float GlowstickDuration => _glowstickDuration;

			public static float GlowstickFadeOutTime => _glowstickFadeOutTime;

			public static int GlowstickCountMax => _glowstickCountMax;

			public static int GlowstickCountMin => _glowstickCountMin;

			internal static void LoadRemoteConfig(ConfigPacket packet)
			{
				if (_isReady)
				{
					Logging.Warning("New remote config received before the current was invalidated!");
					return;
				}
				Logging.Debug("Loading remote settings:\n" + $"GlowstickRange = {packet.GlowstickRange}\n" + $"DoLightnessNormalization = {packet.DoLightnessRangeNormalization}\n" + $"GlowstickFadeInTime = {packet.GlowstickFadeInTime}\n" + $"GlowstickDuration = {packet.GlowstickDuration}\n" + $"GlowstickFadeOutTime = {packet.GlowstickFadeOutTime}\n" + $"GlowstickCountMax = {packet.GlowstickCountMax}\n" + $"GlowstickCountMin = {packet.GlowstickCountMin}");
				_glowstickRange = packet.GlowstickRange;
				_doLightnessRangeNormalization = packet.DoLightnessRangeNormalization;
				_glowstickFadeInTime = packet.GlowstickFadeInTime;
				_glowstickDuration = packet.GlowstickDuration;
				_glowstickFadeOutTime = packet.GlowstickFadeOutTime;
				_glowstickCountMax = packet.GlowstickCountMax;
				_glowstickCountMin = packet.GlowstickCountMin;
				_isReady = true;
			}

			internal static void InvalidateRemoteConfig()
			{
				Logging.Debug("Invalidating remote config");
				_isReady = false;
			}
		}

		private static readonly HashSet<uint> TRACKED_GLOWSTICK_PIDS = new HashSet<uint> { 114u, 130u, 167u, 174u };

		public static double GlowstickRange => SNet.IsMaster ? LocalConfig.GlowstickRange : RemoteConfig.GlowstickRange;

		public static bool DoLightnessRangeNormalization => SNet.IsMaster ? LocalConfig.DoLightnessRangeNormalization : RemoteConfig.DoLightnessRangeNormalization;

		public static float GlowstickFadeInTime => SNet.IsMaster ? LocalConfig.GlowstickFadeInTime : RemoteConfig.GlowstickFadeInTime;

		public static float GlowstickDuration => SNet.IsMaster ? LocalConfig.GlowstickDuration : RemoteConfig.GlowstickDuration;

		public static float GlowstickFadeOutTime => SNet.IsMaster ? LocalConfig.GlowstickFadeOutTime : RemoteConfig.GlowstickFadeOutTime;

		public static int GlowstickCountMax => SNet.IsMaster ? LocalConfig.GlowstickCountMax : RemoteConfig.GlowstickCountMax;

		public static int GlowstickCountMin => SNet.IsMaster ? LocalConfig.GlowstickCountMin : RemoteConfig.GlowstickCountMin;

		public static HashSet<uint> TrackedGlowstickPIDs => TRACKED_GLOWSTICK_PIDS;

		public static bool IsEligibleGlowstick(ItemDataBlock itemDataBlock)
		{
			return TRACKED_GLOWSTICK_PIDS.Contains(((GameDataBlockBase<ItemDataBlock>)(object)itemDataBlock).persistentID);
		}
	}
	[BepInPlugin("CinnamonSnowball.GlowierSticks", "GlowierSticks", "0.8.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class Plugin : BasePlugin
	{
		internal static class GlowstickTweaks
		{
			[HarmonyPatch]
			internal static class GlowstickPatches
			{
				[HarmonyPatch(typeof(SNet_SyncManager), "OnFoundMaster")]
				[HarmonyPostfix]
				private static void PostFoundMaster()
				{
					if (SNet.IsMaster)
					{
						ModifyTemplates();
					}
				}

				internal static void OnReceiveConfigPacket()
				{
					ModifyTemplates();
				}

				[HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")]
				[HarmonyPostfix]
				private static void PostLeaveHub()
				{
					ResetTemplates();
				}

				[HarmonyPatch(typeof(GlowstickInstance), "Setup")]
				[HarmonyPostfix]
				private static void PostGlowstickInstanceSetup(GlowstickInstance __instance)
				{
					if (!SNet.IsMaster && !Configuration.RemoteConfig.IsReady)
					{
						Logging.Debug("Aborting glowstick modification: in an unmodded lobby!");
						return;
					}
					if (!Configuration.IsEligibleGlowstick(((Item)__instance).ItemDataBlock))
					{
						Logging.Debug("Aborting glowstick modification: persistent ID not in list of glowsticks to modify!");
						return;
					}
					Logging.Debug("Setting up thrown glowstick...");
					double num = 1.0;
					if (Configuration.DoLightnessRangeNormalization)
					{
						num = CalculateLightnessRangeMultiplier(__instance);
						Logging.Debug($"Lightness range multiplier: {Math.Round(num, 3)}");
					}
					double num2 = Configuration.GlowstickRange * num / 5.0;
					Logging.Debug($"Light range: {Math.Round(__instance.s_lightRange, 3)} → {Math.Round((double)__instance.s_lightRange * num2, 3)}{(Configuration.DoLightnessRangeNormalization ? " (lightness-normalized)" : "")}");
					__instance.s_lightRange *= (float)num2;
					float num3 = Configuration.GlowstickDuration / 60f;
					Logging.Debug($"Duration: {Math.Round(__instance.s_lightLifeTime, 3)} → {Math.Round(__instance.s_lightLifeTime * num3, 3)}");
					__instance.s_lightLifeTime *= num3;
					Logging.Debug("Setup done!");
				}

				[HarmonyPatch(typeof(GlowstickInstance), "Update")]
				[HarmonyPrefix]
				private static void PreGlowstickInstanceUpdate(GlowstickInstance __instance)
				{
					//IL_0030: Unknown result type (might be due to invalid IL or missing references)
					//IL_0036: Invalid comparison between Unknown and I4
					//IL_0053: Unknown result type (might be due to invalid IL or missing references)
					//IL_0059: Invalid comparison between Unknown and I4
					if ((SNet.IsMaster || Configuration.RemoteConfig.IsReady) && Configuration.IsEligibleGlowstick(((Item)__instance).ItemDataBlock))
					{
						if ((int)__instance.m_state == 1)
						{
							__instance.m_progressionSpeed = 1f / Configuration.GlowstickFadeInTime;
						}
						else if ((int)__instance.m_state == 3)
						{
							__instance.m_progressionSpeed = 1f / Configuration.GlowstickFadeOutTime;
						}
					}
				}
			}

			private const double IDEAL_LIGHT_COLOR_OKLCH_LIGHTNESS = 0.9;

			private const double VANILLA_GLOWSTICK_RANGE = 5.0;

			private const float VANILLA_GLOWSTICK_DURATION = 60f;

			private static readonly Dictionary<uint, List<int>> baseAmmoCounts = new Dictionary<uint, List<int>>();

			private static double CalculateOKLCHLightness(Color lightColor)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				double num = lightColor.r;
				double num2 = lightColor.g;
				double num3 = lightColor.b;
				double num4 = ((num <= 0.04045) ? (num / 12.92) : Math.Pow((num + 0.055) / 1.055, 2.4));
				double num5 = ((num2 <= 0.04045) ? (num2 / 12.92) : Math.Pow((num2 + 0.055) / 1.055, 2.4));
				double num6 = ((num3 <= 0.04045) ? (num3 / 12.92) : Math.Pow((num3 + 0.055) / 1.055, 2.4));
				double num7 = Math.Cbrt(num4 * 0.4122214708 + num5 * 0.5363325363 + num6 * 0.0514459929);
				double num8 = Math.Cbrt(num4 * 0.2119034982 + num5 * 0.6806995451 + num6 * 0.1073969566);
				double num9 = Math.Cbrt(num4 * 0.0883024619 + num5 * 0.2817188376 + num6 * 0.6299787005);
				return num7 * 0.2104542553 + num8 * 0.793617785 - num9 * 0.0040720468;
			}

			private static double CalculateLightnessRangeMultiplier(GlowstickInstance glowstick)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				double num = CalculateOKLCHLightness(glowstick.m_LightColorTarget);
				Logging.Debug($"OKLCH lightness of glowstick light color: {Math.Round(num, 3)}");
				return Math.Sqrt(0.9 / num);
			}

			internal static void ModifyTemplates()
			{
				Logging.Debug("Modifying glowstick templates...");
				int glowstickCountMax = Configuration.GlowstickCountMax;
				int glowstickCountMin = Configuration.GlowstickCountMin;
				foreach (uint trackedGlowstickPID in Configuration.TrackedGlowstickPIDs)
				{
					ItemDataBlock block = GameDataBlockBase<ItemDataBlock>.GetBlock(trackedGlowstickPID);
					if (!baseAmmoCounts.ContainsKey(trackedGlowstickPID))
					{
						baseAmmoCounts[trackedGlowstickPID] = new List<int> { block.ConsumableAmmoMax, block.ConsumableAmmoMin };
					}
					Logging.Debug($"{((GameDataBlockBase<ItemDataBlock>)(object)block).name}({trackedGlowstickPID}) ammo: max {block.ConsumableAmmoMax} → {glowstickCountMax}; min {block.ConsumableAmmoMin} → {glowstickCountMin}");
					block.ConsumableAmmoMax = glowstickCountMax;
					block.ConsumableAmmoMin = glowstickCountMin;
				}
				Logging.Debug("Template modification done!");
			}

			internal static void ResetTemplates()
			{
				Logging.Debug("Resetting glowstick templates...");
				foreach (uint trackedGlowstickPID in Configuration.TrackedGlowstickPIDs)
				{
					ItemDataBlock block = GameDataBlockBase<ItemDataBlock>.GetBlock(trackedGlowstickPID);
					List<int> list = baseAmmoCounts[trackedGlowstickPID];
					Logging.Debug($"{((GameDataBlockBase<ItemDataBlock>)(object)block).name}({trackedGlowstickPID}): max {block.ConsumableAmmoMax} → {list[0]}; min {block.ConsumableAmmoMin} → {list[1]}");
					block.ConsumableAmmoMax = list[0];
					block.ConsumableAmmoMin = list[1];
				}
				Logging.Debug("Template reset done!");
			}
		}

		public const string MOD_NAME = "GlowierSticks";

		public const string MOD_AUTHOR = "CinnamonSnowball";

		public const string MOD_GUID = "CinnamonSnowball.GlowierSticks";

		public const string MOD_VERSION = "0.8.0";

		public override void Load()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			Harmony val = new Harmony("CinnamonSnowball.GlowierSticks");
			val.PatchAll();
			AssetAPI.OnStartupAssetsLoaded += AssetAPI_OnStartupAssetsLoaded;
			Logging.Info($"GlowierSticks loaded with {val.GetPatchedMethods().Count()} patches!");
		}

		private void AssetAPI_OnStartupAssetsLoaded()
		{
			RemoteConfigSync.Init();
		}
	}
	internal static class Logging
	{
		private static readonly ManualLogSource logger = Logger.CreateLogSource("GlowierSticks");

		public static void Log(string format, params object[] args)
		{
			Log(string.Format(format, args));
		}

		public static void Log(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)8, (object)str);
			}
		}

		public static void Warning(string format, params object[] args)
		{
			Warning(string.Format(format, args));
		}

		public static void Warning(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)4, (object)str);
			}
		}

		public static void Error(string format, params object[] args)
		{
			Error(string.Format(format, args));
		}

		public static void Error(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)2, (object)str);
			}
		}

		public static void Info(string format, params object[] args)
		{
			Info(string.Format(format, args));
		}

		public static void Info(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)16, (object)str);
			}
		}

		public static void Debug(string format, params object[] args)
		{
			Debug(string.Format(format, args));
		}

		public static void Debug(string str)
		{
			if (Configuration.LocalConfig.DoDebug && logger != null)
			{
				logger.Log((LogLevel)32, (object)str);
			}
		}
	}
	[HarmonyPatch]
	internal static class RemoteConfigSync
	{
		[HarmonyPatch]
		private static class RemoteConfigSyncPatches
		{
			[HarmonyPatch(typeof(SNet_SyncManager), "OnPlayerSpawnedAgent")]
			[HarmonyPostfix]
			private static void PostOnPlayerSpawnedAgent(SNet_Player player)
			{
				if (SNet.IsMaster && !player.IsLocal && !player.IsBot)
				{
					SendConfigPacket(player);
				}
			}

			[HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")]
			[HarmonyPostfix]
			private static void PostLeaveHub()
			{
				Configuration.RemoteConfig.InvalidateRemoteConfig();
			}
		}

		private static readonly string SYNC_EVENT_NAME = "GLOWIERSTICKS_CONFIG_SYNC";

		internal static void Init()
		{
			NetworkAPI.RegisterEvent<Configuration.RemoteConfig.ConfigPacket>(SYNC_EVENT_NAME, (Action<ulong, Configuration.RemoteConfig.ConfigPacket>)ReceiveConfigPacket);
		}

		internal static void SendConfigPacket(SNet_Player target)
		{
			Logging.Debug($"Sending config packet to player #{target.PlayerSlotIndex() + 1}");
			NetworkAPI.InvokeEvent<Configuration.RemoteConfig.ConfigPacket>(SYNC_EVENT_NAME, new Configuration.RemoteConfig.ConfigPacket(), target, (SNet_ChannelType)2);
		}

		internal static void ReceiveConfigPacket(ulong sender, Configuration.RemoteConfig.ConfigPacket packet)
		{
			SNet_Player val = default(SNet_Player);
			if (!SNet.TryGetPlayer(sender, ref val))
			{
				Logging.Warning($"Received config packet from lookup ID {sender} but they're not a player in our session!");
			}
			else if ((Object)(object)val != (Object)(object)SNet.Master)
			{
				Logging.Warning($"Received config packet from player #{val.PlayerSlotIndex() + 1} but they're not the host!");
			}
			else
			{
				Logging.Debug($"Config packet received from host player #{val.PlayerSlotIndex() + 1}");
				Configuration.RemoteConfig.LoadRemoteConfig(packet);
				Plugin.GlowstickTweaks.GlowstickPatches.OnReceiveConfigPacket();
			}
		}
	}
}