Decompiled source of FlashLight v1.0.6

BepInEx/plugins/MagliteFlashlight/MagliteFlashlight.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: AssemblyTitle("FlashLight")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyDescription("Craftable Valheim flashlight with adjustable brightness")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("1.0.6.0")]
namespace MagliteFlashlight;

public sealed class FlashlightBeam : MonoBehaviour
{
	private const string OnKey = "maglite_on";

	private const string IntensityKey = "maglite_intensity";

	private const string DirectionKey = "maglite_direction";

	private const string RangeKey = "maglite_range";

	private const string AngleKey = "maglite_angle";

	public Light Beam;

	private Player player;

	private ZNetView view;

	private float nextSync;

	private bool wasHeld;

	private bool gripCalibrated;

	private float calibrateAt;

	private Quaternion handleRoll = Quaternion.identity;

	private void Start()
	{
		player = ((Component)this).GetComponentInParent<Player>();
		if ((Object)(object)player != (Object)null)
		{
			view = ((Component)player).GetComponent<ZNetView>();
		}
	}

	private void LateUpdate()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_034a: Unknown result type (might be due to invalid IL or missing references)
		//IL_034f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0399: Unknown result type (might be due to invalid IL or missing references)
		//IL_0338: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_040e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0407: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Beam == (Object)null)
		{
			return;
		}
		Plugin instance = Plugin.Instance;
		VisEquipment val = (((Object)(object)player != (Object)null) ? ((Humanoid)player).GetVisEquipment() : null);
		bool flag = (Object)(object)val != (Object)null && (Object)(object)val.m_rightHand != (Object)null && ((Component)this).transform.IsChildOf(val.m_rightHand) && !((Character)player).IsDead() && !((Character)player).IsTeleporting();
		if (flag && !wasHeld)
		{
			gripCalibrated = false;
			handleRoll = Quaternion.identity;
			calibrateAt = Time.time + 0.75f;
		}
		if (!flag)
		{
			gripCalibrated = false;
		}
		wasHeld = flag;
		if ((Object)(object)instance != (Object)null)
		{
			((Component)this).transform.localScale = Vector3.one * LightMath.Safe(instance.ModelScale.Value, 0.5f, 3f, 1.65f);
			Vector3 value = instance.GripPosition.Value;
			Vector3 value2 = instance.GripRotation.Value;
			((Component)this).transform.localPosition = ((flag && Finite(value)) ? value : Vector3.zero);
			if (flag && !gripCalibrated && Time.time >= calibrateAt)
			{
				Vector3 forward = ((Component)this).transform.parent.forward;
				Vector3 val2 = Vector3.ProjectOnPlane(((Component)this).transform.parent.up, forward);
				Vector3 val3 = Vector3.ProjectOnPlane(Vector3.up, forward);
				if (((Vector3)(ref val3)).sqrMagnitude > 0.01f && ((Vector3)(ref val2)).sqrMagnitude > 0.01f)
				{
					float num = Vector3.SignedAngle(val2, val3, forward);
					handleRoll = Quaternion.AngleAxis(num, Vector3.forward);
					gripCalibrated = true;
				}
			}
			((Component)this).transform.localRotation = ((flag && Finite(value2)) ? (handleRoll * Quaternion.Euler(value2)) : Quaternion.identity);
		}
		if (!flag || (Object)(object)instance == (Object)null)
		{
			((Behaviour)Beam).enabled = false;
			((Component)Beam).transform.localRotation = Quaternion.identity;
			return;
		}
		bool flag2 = (Object)(object)player == (Object)(object)Player.m_localPlayer;
		ZDO val4 = (((Object)(object)view != (Object)null) ? view.GetZDO() : null);
		bool flag3 = (flag2 ? instance.LightOn.Value : (val4 != null && val4.GetBool("maglite_on", false)));
		float value3 = (flag2 ? instance.Brightness.Value : ((val4 != null) ? val4.GetFloat("maglite_intensity", 2.5f) : 2.5f));
		float value4 = (flag2 ? instance.Range.Value : ((val4 != null) ? val4.GetFloat("maglite_range", 40f) : 40f));
		float value5 = (flag2 ? instance.BeamAngle.Value : ((val4 != null) ? val4.GetFloat("maglite_angle", 55f) : 55f));
		Vector3 value6 = (flag2 ? ((Character)player).GetLookDir() : ((val4 != null) ? val4.GetVec3("maglite_direction", ((Component)player).transform.forward) : ((Component)player).transform.forward));
		value3 = LightMath.Safe(value3, 0.25f, 8f, 2.5f);
		value4 = LightMath.Safe(value4, 5f, 80f, 40f);
		value5 = LightMath.Safe(value5, 15f, 90f, 55f);
		if (!Finite(value6) || ((Vector3)(ref value6)).sqrMagnitude < 0.001f)
		{
			value6 = ((Component)player).transform.forward;
		}
		Quaternion val5 = Quaternion.LookRotation(((Vector3)(ref value6)).normalized);
		((Component)Beam).transform.rotation = (flag2 ? val5 : Quaternion.Slerp(((Component)Beam).transform.rotation, val5, 1f - Mathf.Exp(-15f * Time.deltaTime)));
		((Behaviour)Beam).enabled = flag3;
		Beam.intensity = value3;
		Beam.range = value4;
		Beam.spotAngle = value5;
		Beam.innerSpotAngle = value5 * 0.65f;
		Beam.shadows = (LightShadows)(instance.Shadows.Value ? 2 : 0);
		if (flag2 && val4 != null && view.IsOwner() && Time.unscaledTime >= nextSync)
		{
			nextSync = Time.unscaledTime + 0.1f;
			val4.Set("maglite_on", flag3);
			val4.Set("maglite_intensity", value3);
			val4.Set("maglite_range", value4);
			val4.Set("maglite_angle", value5);
			val4.Set("maglite_direction", ((Vector3)(ref value6)).normalized);
		}
	}

	private static bool Finite(Vector3 value)
	{
		if (!float.IsNaN(value.x) && !float.IsNaN(value.y) && !float.IsNaN(value.z) && !float.IsInfinity(value.x) && !float.IsInfinity(value.y))
		{
			return !float.IsInfinity(value.z);
		}
		return false;
	}

	private void OnDisable()
	{
		if ((Object)(object)Beam != (Object)null)
		{
			((Behaviour)Beam).enabled = false;
		}
	}
}
internal static class FlashlightModel
{
	internal static void Build(Transform attach, Material templateMaterial)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		float scale = LightMath.Safe(Plugin.Instance.ModelScale.Value, 0.5f, 3f, 1.65f);
		GameObject val = ImportedModel.Create(attach, scale, templateMaterial);
		GameObject val2 = new GameObject("Maglite beam");
		val2.transform.SetParent(val.transform, false);
		val2.transform.localPosition = ImportedModel.LensPosition;
		Light val3 = val2.AddComponent<Light>();
		val3.type = (LightType)0;
		val3.color = new Color(1f, 0.97f, 0.9f);
		val3.range = 40f;
		val3.spotAngle = 55f;
		val3.intensity = 2.5f;
		val3.shadows = (LightShadows)2;
		val3.shadowNearPlane = 0.05f;
		val3.shadowBias = 0.02f;
		val3.renderMode = (LightRenderMode)1;
		((Behaviour)val3).enabled = false;
		val.AddComponent<FlashlightBeam>().Beam = val3;
		Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
		foreach (Transform val4 in componentsInChildren)
		{
			((Component)val4).gameObject.layer = ((Component)attach).gameObject.layer;
		}
	}

	internal static Sprite CreateIcon()
	{
		return ImportedModel.CreateIcon();
	}
}
internal static class ImportedModel
{
	internal static readonly Vector3 LensPosition = new Vector3(0f, -0.06798112f, 0.17294396f);

	internal static readonly Vector3 BoundsCenter = new Vector3(0f, -0.06285756f, 0.04976726f);

	internal static readonly Vector3 BoundsSize = new Vector3(0.13281032f, 0.14411001f, 0.24f);

	internal static GameObject Create(Transform parent, float scale, Material fallback)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Expected O, but got Unknown
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Expected O, but got Unknown
		GameObject val = new GameObject("MagliteModel");
		val.transform.SetParent(parent, false);
		val.transform.localScale = Vector3.one * scale;
		Shader val2 = Shader.Find("Standard");
		if ((Object)(object)val2 == (Object)null && (Object)(object)fallback != (Object)null)
		{
			val2 = fallback.shader;
		}
		if ((Object)(object)val2 == (Object)null)
		{
			throw new InvalidOperationException("Flashlight material shader unavailable.");
		}
		using Stream input = Resource("flashlight.mesh");
		using BinaryReader binaryReader = new BinaryReader(input);
		if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "MFL2")
		{
			throw new InvalidDataException("Invalid flashlight mesh header.");
		}
		int num = Count(binaryReader, 1, 32);
		for (int i = 0; i < num; i++)
		{
			string text = Encoding.UTF8.GetString(binaryReader.ReadBytes(Count(binaryReader, 1, 64)));
			int num2 = Count(binaryReader, 3, 65535);
			Vector3[] vertices = ReadVectors(binaryReader, num2);
			Vector3[] normals = ReadVectors(binaryReader, num2);
			Vector2[] array = (Vector2[])(object)new Vector2[num2];
			for (int j = 0; j < num2; j++)
			{
				ref Vector2 reference = ref array[j];
				reference = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			int num3 = Count(binaryReader, 3, 1000000);
			if (num3 % 3 != 0)
			{
				throw new InvalidDataException("Invalid triangle count.");
			}
			int[] array2 = new int[num3];
			for (int k = 0; k < num3; k++)
			{
				array2[k] = binaryReader.ReadInt32();
				if (array2[k] < 0 || array2[k] >= num2)
				{
					throw new InvalidDataException("Mesh index out of range.");
				}
			}
			Mesh val3 = new Mesh();
			((Object)val3).name = "Flashlight_" + text;
			Mesh val4 = val3;
			val4.vertices = vertices;
			val4.normals = normals;
			val4.uv = array;
			val4.triangles = array2;
			val4.RecalculateBounds();
			val4.RecalculateTangents();
			GameObject val5 = new GameObject(text);
			val5.transform.SetParent(val.transform, false);
			val5.AddComponent<MeshFilter>().sharedMesh = val4;
			MeshRenderer val6 = val5.AddComponent<MeshRenderer>();
			((Renderer)val6).sharedMaterial = CreateMaterial(text, val2);
			((Renderer)val6).shadowCastingMode = (ShadowCastingMode)(!(text == "steklo"));
		}
		if (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length)
		{
			throw new InvalidDataException("Trailing mesh data.");
		}
		return val;
	}

	private static Material CreateMaterial(string name, Shader shader)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		Material val = new Material(shader);
		((Object)val).name = "Flashlight_" + name;
		Material val2 = val;
		val2.SetColor("_Color", Color.white);
		val2.SetTexture("_MainTex", (Texture)(object)Texture(name + "_color.png", linear: false, required: true));
		val2.SetTexture("_MetallicGlossMap", (Texture)(object)Texture(name + "_metal.png", linear: true, required: true));
		val2.SetFloat("_GlossMapScale", 0.8f);
		val2.EnableKeyword("_METALLICGLOSSMAP");
		Texture2D val3 = Texture(name + "_normal.png", linear: true, required: false);
		if ((Object)(object)val3 != (Object)null)
		{
			val2.SetTexture("_BumpMap", (Texture)(object)val3);
			val2.SetFloat("_BumpScale", 0.7f);
			val2.EnableKeyword("_NORMALMAP");
		}
		if (name == "steklo")
		{
			val2.SetFloat("_Mode", 3f);
			val2.SetOverrideTag("RenderType", "Transparent");
			val2.SetInt("_SrcBlend", 1);
			val2.SetInt("_DstBlend", 10);
			val2.SetInt("_ZWrite", 0);
			val2.DisableKeyword("_ALPHATEST_ON");
			val2.DisableKeyword("_ALPHABLEND_ON");
			val2.EnableKeyword("_ALPHAPREMULTIPLY_ON");
			val2.renderQueue = 3000;
		}
		return val2;
	}

	private static Texture2D Texture(string name, bool linear, bool required)
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MagliteFlashlight.Assets." + name);
		if (stream == null)
		{
			if (required)
			{
				throw new FileNotFoundException("Missing embedded texture", name);
			}
			return null;
		}
		using MemoryStream memoryStream = new MemoryStream();
		stream.CopyTo(memoryStream);
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear);
		((Object)val).name = name;
		((Texture)val).anisoLevel = 4;
		Texture2D val2 = val;
		if (!ImageConversion.LoadImage(val2, memoryStream.ToArray(), true))
		{
			throw new InvalidDataException("Could not decode " + name);
		}
		return val2;
	}

	internal static Sprite CreateIcon()
	{
		//IL_0026: 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)
		Texture2D val = Texture("icon.png", linear: false, required: true);
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width);
	}

	private static Stream Resource(string name)
	{
		Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MagliteFlashlight.Assets." + name);
		if (manifestResourceStream == null)
		{
			throw new FileNotFoundException("Missing embedded flashlight asset", name);
		}
		return manifestResourceStream;
	}

	private static int Count(BinaryReader reader, int min, int max)
	{
		int num = reader.ReadInt32();
		if (num < min || num > max)
		{
			throw new InvalidDataException("Invalid mesh data count.");
		}
		return num;
	}

	private static Vector3[] ReadVectors(BinaryReader reader, int count)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		Vector3[] array = (Vector3[])(object)new Vector3[count];
		for (int i = 0; i < count; i++)
		{
			ref Vector3 reference = ref array[i];
			reference = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
		}
		return array;
	}
}
internal static class LightMath
{
	internal static float Safe(float value, float min, float max, float fallback)
	{
		if (float.IsNaN(value) || float.IsInfinity(value))
		{
			return fallback;
		}
		return Math.Max(min, Math.Min(max, value));
	}

	internal static float Adjust(float value, float delta)
	{
		return Safe((float)Math.Round(Safe(value, 0.25f, 8f, 2.5f) + delta, 3), 0.25f, 8f, 2.5f);
	}
}
[BepInDependency("com.jotunn.jotunn", "2.30.0")]
[BepInPlugin("local.valheim.magliteflashlight", "FlashLight", "1.0.6")]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Guid = "local.valheim.magliteflashlight";

	public const string Name = "FlashLight";

	public const string Version = "1.0.6";

	public const string PrefabName = "MagliteFlashlight";

	internal static Plugin Instance;

	internal ConfigEntry<float> Brightness;

	internal ConfigEntry<float> Step;

	internal ConfigEntry<float> Range;

	internal ConfigEntry<float> BeamAngle;

	internal ConfigEntry<bool> LightOn;

	internal ConfigEntry<bool> Shadows;

	internal ConfigEntry<float> ModelScale;

	internal ConfigEntry<Vector3> GripPosition;

	internal ConfigEntry<Vector3> GripRotation;

	private ButtonConfig toggle;

	private ButtonConfig brighter;

	private ButtonConfig dimmer;

	private Harmony harmony;

	private void Awake()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Expected O, but got Unknown
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Expected O, but got Unknown
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Expected O, but got Unknown
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Expected O, but got Unknown
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0316: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Expected O, but got Unknown
		//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Expected O, but got Unknown
		Instance = this;
		Brightness = ((BaseUnityPlugin)this).Config.Bind<float>("Light", "Brightness", 2.5f, new ConfigDescription("Beam intensity. Saved when changed with hotkeys.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 8f), new object[0]));
		Step = ((BaseUnityPlugin)this).Config.Bind<float>("Light", "BrightnessStep", 0.25f, new ConfigDescription("Intensity change per key press.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f), new object[0]));
		Range = ((BaseUnityPlugin)this).Config.Bind<float>("Light", "Range", 40f, new ConfigDescription("Beam reach in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 80f), new object[0]));
		BeamAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Light", "BeamAngle", 55f, new ConfigDescription("Cone width in degrees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(15f, 90f), new object[0]));
		LightOn = ((BaseUnityPlugin)this).Config.Bind<bool>("Light", "Enabled", true, "Remembered on/off state; only emits while held.");
		Shadows = ((BaseUnityPlugin)this).Config.Bind<bool>("Light", "Shadows", true, "Cast shadows to keep the beam from shining through walls. Disable for performance.");
		ModelScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "ModelScale", 1.65f, new ConfigDescription("Flashlight size multiplier. 1.65 makes the uploaded model about 40 cm long. Local visual preference.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), new object[0]));
		GripPosition = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Appearance", "GripPosition", Vector3.zero, "Position offset in the hand attachment's local coordinates, in metres.");
		GripRotation = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Appearance", "GripRotation", Vector3.zero, "Extra grip rotation in degrees (X, Y, Z), applied after aligning the handle above the body. The model follows the hand.");
		if (GripRotation.Value == new Vector3(-90f, 0f, 0f))
		{
			GripRotation.Value = Vector3.zero;
		}
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "item_maglite", "FlashLight" },
			{ "item_maglite_desc", "A sturdy black-and-yellow flashlight powered by a surtling core. Equip and aim with your view. Adjustable brightness, no fuel consumption." },
			{ "maglite_toggle", "Light on/off" },
			{ "maglite_brighter", "Brighter" },
			{ "maglite_dimmer", "Dimmer" }
		});
		if (!GUIManager.IsHeadless())
		{
			toggle = BindButton("Toggle", (KeyCode)108, "$maglite_toggle");
			brighter = BindButton("Brighter", (KeyCode)93, "$maglite_brighter");
			dimmer = BindButton("Dimmer", (KeyCode)91, "$maglite_dimmer");
			KeyHintManager instance = KeyHintManager.Instance;
			KeyHintConfig val = new KeyHintConfig();
			val.Item = "MagliteFlashlight";
			val.ButtonConfigs = (ButtonConfig[])(object)new ButtonConfig[3] { toggle, dimmer, brighter };
			instance.AddKeyHint(val);
		}
		harmony = new Harmony("local.valheim.magliteflashlight");
		harmony.PatchAll(typeof(Plugin).Assembly);
		PrefabManager.OnVanillaPrefabsAvailable += RegisterItem;
	}

	private ButtonConfig BindButton(string name, KeyCode key, string hint)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		ButtonConfig val = new ButtonConfig();
		val.Name = "Maglite_" + name;
		val.Config = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", name, key, "Only active with the flashlight equipped and gameplay input available.");
		val.HintToken = hint;
		val.ActiveInGUI = false;
		val.ActiveInCustomGUI = false;
		ButtonConfig val2 = val;
		InputManager.Instance.AddButton("local.valheim.magliteflashlight", val2);
		return val2;
	}

	private void RegisterItem()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		//IL_00b9: 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)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			ItemConfig val = new ItemConfig();
			val.Name = "$item_maglite";
			val.Description = "$item_maglite_desc";
			val.CraftingStation = "piece_workbench";
			val.MinStationLevel = 1;
			val.Amount = 1;
			val.Weight = 1.5f;
			ItemConfig val2 = val;
			val2.AddRequirement("Bronze", 2, 0);
			val2.AddRequirement("Crystal", 1, 0);
			val2.AddRequirement("SurtlingCore", 1, 0);
			CustomItem val3 = new CustomItem("MagliteFlashlight", "Club", val2);
			SharedData shared = val3.ItemDrop.m_itemData.m_shared;
			shared.m_maxQuality = 1;
			shared.m_useDurability = false;
			shared.m_canBeReparied = false;
			shared.m_movementModifier = 0f;
			shared.m_damages = default(DamageTypes);
			shared.m_damagesPerLevel = default(DamageTypes);
			shared.m_attackForce = 0f;
			shared.m_equipStatusEffect = null;
			shared.m_attackStatusEffect = null;
			shared.m_maxStackSize = 1;
			shared.m_teleportable = true;
			Transform val4 = val3.ItemPrefab.transform.Find("attach");
			if ((Object)(object)val4 == (Object)null)
			{
				throw new InvalidOperationException("Club prefab no longer has an attach transform.");
			}
			Material val5 = null;
			Renderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val6 in componentsInChildren)
			{
				if ((Object)(object)val5 == (Object)null)
				{
					val5 = val6.sharedMaterial;
				}
				val6.enabled = false;
			}
			Light[] componentsInChildren2 = ((Component)val4).GetComponentsInChildren<Light>(true);
			foreach (Light val7 in componentsInChildren2)
			{
				((Behaviour)val7).enabled = false;
			}
			Collider[] componentsInChildren3 = val3.ItemPrefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val8 in componentsInChildren3)
			{
				val8.enabled = false;
			}
			for (int num = val4.childCount - 1; num >= 0; num--)
			{
				Object.DestroyImmediate((Object)(object)((Component)val4.GetChild(num)).gameObject);
			}
			Transform val9 = val3.ItemPrefab.transform.Find("attach_back");
			if ((Object)(object)val9 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)val9).gameObject);
			}
			BoxCollider val10 = ((Component)val4).gameObject.AddComponent<BoxCollider>();
			float num2 = LightMath.Safe(ModelScale.Value, 0.5f, 3f, 1.65f);
			val10.size = ImportedModel.BoundsSize * num2;
			val10.center = ImportedModel.BoundsCenter * num2;
			if (!GUIManager.IsHeadless())
			{
				FlashlightModel.Build(val4, val5);
				shared.m_icons = (Sprite[])(object)new Sprite[1] { FlashlightModel.CreateIcon() };
			}
			if (!ItemManager.Instance.AddItem(val3))
			{
				throw new InvalidOperationException("Jotunn rejected the flashlight item.");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered MagliteFlashlight: workbench, 2 Bronze + 1 Crystal + 1 SurtlingCore.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not register FlashLight: " + ex));
		}
		finally
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterItem;
		}
	}

	internal static bool IsFlashlight(ItemData item)
	{
		if (item != null && (Object)(object)item.m_dropPrefab != (Object)null)
		{
			return ((Object)item.m_dropPrefab).name == "MagliteFlashlight";
		}
		return false;
	}

	private void Update()
	{
		Player localPlayer = Player.m_localPlayer;
		if (toggle != null && ZInput.instance != null && !((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && IsFlashlight(((Humanoid)localPlayer).RightItem))
		{
			bool flag = false;
			if (ZInput.GetButtonDown(toggle.Name))
			{
				LightOn.Value = !LightOn.Value;
				flag = true;
			}
			if (ZInput.GetButtonDown(brighter.Name))
			{
				Brightness.Value = LightMath.Adjust(Brightness.Value, Step.Value);
				flag = true;
			}
			if (ZInput.GetButtonDown(dimmer.Name))
			{
				Brightness.Value = LightMath.Adjust(Brightness.Value, 0f - Step.Value);
				flag = true;
			}
			if (flag && (Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)1, LightOn.Value ? $"FlashLight brightness: {Brightness.Value:0.00} / 8" : "FlashLight: off", 0, (Sprite)null, false, true);
			}
		}
	}

	private void OnDestroy()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterItem;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		Instance = null;
	}
}
[HarmonyPatch(typeof(Humanoid), "StartAttack")]
internal static class NoFlashlightAttack
{
	private static bool Prefix(Humanoid __instance, ref bool __result)
	{
		if (!Plugin.IsFlashlight(__instance.RightItem))
		{
			return true;
		}
		__result = false;
		return false;
	}
}