Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DimmingFlashlights v0.0.9
DimmingFlashlights.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DimmingFlashlights.NetcodePatcher; using DimmingFlashlights.Network; using DimmingFlashlights.Patches; using DimmingFlashlights.Utils; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; 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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("DimmingFlashlights")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.0.9.0")] [assembly: AssemblyInformationalVersion("0.0.9")] [assembly: AssemblyProduct("DimmingFlashlights")] [assembly: AssemblyTitle("DimmingFlashlights")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.9.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } [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 DimmingFlashlights { internal static class ConfigManager { internal static ConfigEntry<float> MinimumBrightnessScale { get; private set; } internal static ConfigEntry<float> BatteryThreshold { get; private set; } internal static void Bind(ConfigFile config) { MinimumBrightnessScale = config.Bind<float>("Settings", "Minimum brightness scale", 0.15f, "Lowest possible brightness multiplier when the battery is near empty. Default is 15% brightness"); BatteryThreshold = config.Bind<float>("Settings", "Battery Threshold", 0.6f, "Battery level at which full brightness stops and dimming begins. Default is 60% battery"); } } [BepInPlugin("MrHat.DimmingFlashlights", "DimmingFlashlights", "0.0.9")] internal class Plugin : BaseUnityPlugin { internal const string modGUID = "MrHat.DimmingFlashlights"; internal const string modName = "DimmingFlashlights"; internal const string modVersion = "0.0.9"; private Harmony _harmony; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ConfigManager.Bind(((BaseUnityPlugin)this).Config); InitialiseNetworkSerialisation(); _harmony = new Harmony("MrHat.DimmingFlashlights"); _harmony.PatchAll(typeof(NetworkManagerPatches)); _harmony.PatchAll(typeof(FlashlightItemPatches)); _harmony.PatchAll(typeof(PlayerControllerBPatches)); _harmony.PatchAll(typeof(StartOfRoundPatches)); Log.LogInfo((object)"DimmingFlashlights loaded"); } private static void InitialiseNetworkSerialisation() { MethodInfo methodInfo = typeof(Plugin).Assembly.GetType("__GEN.NetworkVariableSerializationHelper")?.GetMethod("InitializeSerialization", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo == null) { Log.LogFatal((object)"DimmingFlashlights serialisation method was not found, flashlights will probably break the game"); return; } methodInfo.Invoke(null, null); Log.LogDebug((object)"DimmingFlashlights serialisation initialised"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "DimmingFlashlights"; public const string PLUGIN_NAME = "DimmingFlashlights"; public const string PLUGIN_VERSION = "0.0.9"; } } namespace DimmingFlashlights.Utils { internal static class FlashlightDimming { private const float MessageInterval = 1.2f; private static readonly Dictionary<ulong, float[]> OriginalHelmetIntensities = new Dictionary<ulong, float[]>(); private static readonly Dictionary<ulong, float> NextFlashlightMessages = new Dictionary<ulong, float>(); private static readonly HashSet<ulong> FlashlightsThatDimmed = new HashSet<ulong>(); internal static void Clear() { OriginalHelmetIntensities.Clear(); NextFlashlightMessages.Clear(); FlashlightsThatDimmed.Clear(); } internal static bool FlashlightMessageDue(ulong networkObjectId, float currentTime) { if (NextFlashlightMessages.TryGetValue(networkObjectId, out var value) && currentTime < value) { return false; } NextFlashlightMessages[networkObjectId] = currentTime + 1.2f; return true; } internal static bool DimmingLogDue(ulong networkObjectId, float charge) { float num = Mathf.Clamp01(ConfigManager.BatteryThreshold.Value); return Mathf.Clamp01(charge) < num && FlashlightsThatDimmed.Add(networkObjectId); } internal static bool HelmetIntensitiesKnown(ulong clientId) { return OriginalHelmetIntensities.ContainsKey(clientId); } internal static void RememberHelmetIntensities(ulong clientId, float[] intensities) { OriginalHelmetIntensities[clientId] = intensities; } internal static float OriginalHelmetIntensity(ulong clientId, int index) { if (OriginalHelmetIntensities.TryGetValue(clientId, out float[] value) && index >= 0 && index < value.Length) { return value[index]; } return 0f; } internal static void DimFlashlight(FlashlightItem flashlight, float charge) { Light flashlightBulb = flashlight.flashlightBulb; flashlightBulb.intensity *= Brightness(charge); } internal static float Brightness(float charge) { float num = Mathf.Clamp01(ConfigManager.BatteryThreshold.Value); float num2 = Mathf.Clamp01(ConfigManager.MinimumBrightnessScale.Value); charge = Mathf.Clamp01(charge); if (num <= 0f || charge >= num) { return 1f; } float num3 = Mathf.Clamp01(charge / num); return Mathf.Clamp01(num2 + (1f - num2) * num3); } } } namespace DimmingFlashlights.Patches { internal static class FlashlightItemPatches { [HarmonyPostfix] [HarmonyPatch(typeof(FlashlightItem), "Update")] private static void UpdatePostfix(FlashlightItem __instance) { if (((GrabbableObject)__instance).insertedBattery == null || (Object)(object)((NetworkBehaviour)__instance).NetworkObject == (Object)null) { return; } float num = Mathf.Clamp01(((GrabbableObject)__instance).insertedBattery.charge); ulong networkObjectId = ((NetworkBehaviour)__instance).NetworkObject.NetworkObjectId; if (((NetworkBehaviour)__instance).IsOwner && FlashlightDimming.FlashlightMessageDue(networkObjectId, Time.time)) { DimmingFlashlightsNetwork.PublishFlashlightCharge(networkObjectId, num); } float charge = (((NetworkBehaviour)__instance).IsOwner ? num : DimmingFlashlightsNetwork.FlashlightChargeFor(networkObjectId, num)); if (FlashlightDimming.DimmingLogDue(networkObjectId, charge)) { string text = ((GrabbableObject)__instance).itemProperties?.itemName ?? "Flashlight"; string text2 = ((GrabbableObject)__instance).playerHeldBy?.playerUsername; if (string.IsNullOrEmpty(text2)) { Plugin.Log.LogDebug((object)(text + " started dimming whilst held by no one")); } else { Plugin.Log.LogDebug((object)(text + " started dimming whilst held by " + text2)); } } FlashlightDimming.DimFlashlight(__instance, charge); } } internal static class NetworkManagerPatches { private static GameObject? dimmingFlashlightsPrefab; private static NetworkManager? networkManager; [HarmonyPostfix] [HarmonyPatch(typeof(NetworkManager), "SetSingleton")] private static void SetSingletonPostfix() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || (Object)(object)singleton == (Object)(object)networkManager) { return; } if ((Object)(object)networkManager != (Object)null) { networkManager.OnServerStarted -= SpawnDimmingFlashlightsNetwork; } if ((Object)(object)dimmingFlashlightsPrefab == (Object)null) { GameObject val = new GameObject("MrHat.DimmingFlashlights.Network"); ((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x3D); Object.DontDestroyOnLoad((Object)(object)val); NetworkObject obj = val.AddComponent<NetworkObject>(); val.AddComponent<DimmingFlashlightsNetwork>(); FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { Plugin.Log.LogError((object)"DimmingFlashlights network prefab hash field was not found, networking will not work for DimmingFlashlights"); Object.Destroy((Object)(object)val); return; } uint num = 17u; string text = "MrHat.DimmingFlashlights"; foreach (char c in text) { num = (num * 31) ^ c; } field.SetValue(obj, num); dimmingFlashlightsPrefab = val; } singleton.PrefabHandler.AddNetworkPrefab(dimmingFlashlightsPrefab); singleton.OnServerStarted += SpawnDimmingFlashlightsNetwork; networkManager = singleton; Plugin.Log.LogDebug((object)"DimmingFlashlights network prefab loaded"); } private static void SpawnDimmingFlashlightsNetwork() { NetworkManager? obj = networkManager; if (obj != null && obj.IsServer && !((Object)(object)DimmingFlashlightsNetwork.Instance != (Object)null)) { GameObject val = Object.Instantiate<GameObject>(dimmingFlashlightsPrefab); ((Object)val).name = "MrHat.DimmingFlashlights.Network"; Object.DontDestroyOnLoad((Object)(object)val); val.GetComponent<NetworkObject>().Spawn(false); Plugin.Log.LogDebug((object)"DimmingFlashlights network values spawned"); } } } internal static class PlayerControllerBPatches { [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void LateUpdatePostfix(PlayerControllerB __instance) { Light[] allHelmetLights = __instance.allHelmetLights; if (allHelmetLights.Length == 0) { return; } ulong ownerClientId = ((NetworkBehaviour)__instance).OwnerClientId; if (!FlashlightDimming.HelmetIntensitiesKnown(ownerClientId)) { float[] array = new float[allHelmetLights.Length]; for (int i = 0; i < allHelmetLights.Length; i++) { array[i] = allHelmetLights[i].intensity; } FlashlightDimming.RememberHelmetIntensities(ownerClientId, array); } float num = 1f; GrabbableObject pocketedFlashlight = __instance.pocketedFlashlight; if (pocketedFlashlight?.insertedBattery != null) { num = Mathf.Clamp01(pocketedFlashlight.insertedBattery.charge); if (!((NetworkBehaviour)__instance).IsOwner && (Object)(object)((NetworkBehaviour)pocketedFlashlight).NetworkObject != (Object)null) { num = DimmingFlashlightsNetwork.FlashlightChargeFor(((NetworkBehaviour)pocketedFlashlight).NetworkObject.NetworkObjectId, num); } } float num2 = FlashlightDimming.Brightness(num); for (int j = 0; j < allHelmetLights.Length; j++) { float num3 = FlashlightDimming.OriginalHelmetIntensity(ownerClientId, j); allHelmetLights[j].intensity = num3 * num2; } } } internal static class StartOfRoundPatches { [HarmonyPatch(typeof(StartOfRound), "OnDestroy")] [HarmonyPostfix] private static void OnDestroyPostfix() { Stopwatch stopwatch = Stopwatch.StartNew(); FlashlightDimming.Clear(); DimmingFlashlightsNetwork.DespawnNetworkValues(); Plugin.Log.LogInfo((object)$"Cleanup complete in {stopwatch.Elapsed.TotalMilliseconds:F3} ms"); } } } namespace DimmingFlashlights.Network { internal struct FlashlightCharge : INetworkSerializable, IEquatable<FlashlightCharge> { internal ulong NetworkObjectId; internal float Charge; internal FlashlightCharge(ulong networkObjectId, float charge) { NetworkObjectId = networkObjectId; Charge = charge; } public bool Equals(FlashlightCharge other) { return NetworkObjectId == other.NetworkObjectId && Charge.Equals(other.Charge); } public unsafe void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter { //IL_000b: 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) //IL_0022: 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) ((BufferSerializer<ulong>*)(&serializer))->SerializeValue<ulong>(ref NetworkObjectId, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref Charge, default(ForPrimitives)); } } internal class DimmingFlashlightsNetwork : NetworkBehaviour { private NetworkList<FlashlightCharge> flashlightCharges = new NetworkList<FlashlightCharge>(); internal static DimmingFlashlightsNetwork? Instance { get; private set; } public override void OnNetworkSpawn() { ((NetworkBehaviour)this).OnNetworkSpawn(); Instance = this; Plugin.Log.LogDebug((object)"DimmingFlashlights network started"); } public override void OnNetworkDespawn() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } Plugin.Log.LogDebug((object)"DimmingFlashlights network despawned"); ((NetworkBehaviour)this).OnNetworkDespawn(); } public override void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } ((NetworkBehaviour)this).OnDestroy(); } internal static void DespawnNetworkValues() { DimmingFlashlightsNetwork instance = Instance; if (!((Object)(object)instance == (Object)null)) { Instance = null; NetworkObject networkObject = ((NetworkBehaviour)instance).NetworkObject; NetworkManager networkManager = networkObject.NetworkManager; if ((Object)(object)networkManager == (Object)null) { Object.Destroy((Object)(object)((Component)instance).gameObject); } else if (((NetworkBehaviour)instance).IsServer && ((NetworkBehaviour)instance).IsSpawned && !networkManager.ShutdownInProgress && networkManager.SpawnManager != null) { networkObject.Despawn(true); } else { Object.Destroy((Object)(object)((Component)instance).gameObject); } } } internal static void PublishFlashlightCharge(ulong networkObjectId, float charge) { DimmingFlashlightsNetwork instance = Instance; if (instance != null && ((NetworkBehaviour)instance).IsSpawned) { instance.PublishFlashlightChargeRpc(networkObjectId, Mathf.Clamp01(charge)); } } internal static float FlashlightChargeFor(ulong networkObjectId, float fallbackCharge) { DimmingFlashlightsNetwork instance = Instance; if (instance == null || !((NetworkBehaviour)instance).IsSpawned) { return fallbackCharge; } for (int i = 0; i < instance.flashlightCharges.Count; i++) { FlashlightCharge flashlightCharge = instance.flashlightCharges[i]; if (flashlightCharge.NetworkObjectId == networkObjectId) { return flashlightCharge.Charge; } } return fallbackCharge; } [Rpc(/*Could not decode attribute arguments.*/)] private void PublishFlashlightChargeRpc(ulong networkObjectId, float charge) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1) { RpcAttributeParams val = new RpcAttributeParams { RequireOwnership = false }; RpcParams val3 = default(RpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendRpc(1962553790u, val3, val, (SendTo)2, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, networkObjectId); ((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref charge, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendRpc(ref val2, 1962553790u, val3, val, (SendTo)2, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 1) { return; } base.__rpc_exec_stage = (__RpcExecStage)0; charge = Mathf.Clamp01(charge); for (int i = 0; i < flashlightCharges.Count; i++) { if (flashlightCharges[i].NetworkObjectId == networkObjectId) { if (!flashlightCharges[i].Charge.Equals(charge)) { flashlightCharges[i] = new FlashlightCharge(networkObjectId, charge); } return; } } flashlightCharges.Add(new FlashlightCharge(networkObjectId, charge)); if (!((NetworkBehaviour)this).NetworkManager.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out var value)) { Plugin.Log.LogWarning((object)"A flashlight battery charge was received before its flashlight spawned on the network"); return; } FlashlightItem component = ((Component)value).GetComponent<FlashlightItem>(); string text = ((GrabbableObject)component).itemProperties.itemName ?? "Flashlight"; string text2 = ((GrabbableObject)component).playerHeldBy?.playerUsername; if (string.IsNullOrEmpty(text2)) { Plugin.Log.LogDebug((object)(text + " found, held by nobody")); } else { Plugin.Log.LogDebug((object)(text + " held by " + text2)); } } protected override void __initializeVariables() { if (flashlightCharges == null) { throw new Exception("DimmingFlashlightsNetwork.flashlightCharges cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)flashlightCharges).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)flashlightCharges, "flashlightCharges"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)flashlightCharges); ((NetworkBehaviour)this).__initializeVariables(); } protected override void __initializeRpcs() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown ((NetworkBehaviour)this).__registerRpc(1962553790u, new RpcReceiveHandler(__rpc_handler_1962553790), "PublishFlashlightChargeRpc"); ((NetworkBehaviour)this).__initializeRpcs(); } private static void __rpc_handler_1962553790(NetworkBehaviour? target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { ulong networkObjectId = default(ulong); ByteUnpacker.ReadValueBitPacked(reader, ref networkObjectId); float charge = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref charge, default(ForPrimitives)); target.__rpc_exec_stage = (__RpcExecStage)1; ((DimmingFlashlightsNetwork)(object)target).PublishFlashlightChargeRpc(networkObjectId, charge); target.__rpc_exec_stage = (__RpcExecStage)0; } } protected internal override string? __getTypeName() { return "DimmingFlashlightsNetwork"; } } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedINetworkSerializable<FlashlightCharge>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<FlashlightCharge>(); } } } namespace DimmingFlashlights.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }