Decompiled source of RustyHeathensMistControl v0.2.1

RustyHeathensMistControl.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Rusty Heathens Mist Control")]
[assembly: AssemblyDescription("Admin-synced Mistlands, wisp range and ambient brightness controls")]
[assembly: AssemblyCompany("RustyHeathens")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyVersion("0.2.1.0")]
namespace RustyHeathensMistControl;

internal static class GammaControl
{
	[HarmonyPatch(typeof(EnvMan), "SetEnv")]
	private static class EnvironmentPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			CaptureEnvironment();
		}
	}

	private static Color original;

	private static Color applied;

	private static bool captured;

	private static bool changed;

	internal static void CaptureEnvironment()
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Utils.GetMainCamera() == (Object)null)
		{
			Restore();
			return;
		}
		original = RenderSettings.ambientLight;
		captured = true;
		changed = false;
		Apply(((Object)(object)Plugin.Instance == (Object)null) ? MistSettings.Vanilla : Plugin.Instance.Effective);
	}

	private static void Apply(MistSettings settings)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		Color val = original;
		if (settings.GammaEnabled)
		{
			GammaMath.Brighten(ref val.r, ref val.g, ref val.b, settings.Brightness);
		}
		applied = val;
		changed = !Same(val, original);
		RenderSettings.ambientLight = val;
	}

	internal static void Refresh(MistSettings settings)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if (captured)
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				Restore();
			}
			else if (!Same(RenderSettings.ambientLight, changed ? applied : original))
			{
				captured = (changed = false);
			}
			else
			{
				Apply(settings);
			}
		}
	}

	internal static void Restore()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		if (captured && changed && Same(RenderSettings.ambientLight, applied))
		{
			RenderSettings.ambientLight = original;
		}
		captured = (changed = false);
	}

	private static bool Same(Color a, Color b)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		if (Mathf.Approximately(a.r, b.r) && Mathf.Approximately(a.g, b.g) && Mathf.Approximately(a.b, b.b))
		{
			return Mathf.Approximately(a.a, b.a);
		}
		return false;
	}
}
internal static class GammaMath
{
	internal static void Brighten(ref float r, ref float g, ref float b, int brightness)
	{
		if (brightness <= 0)
		{
			return;
		}
		float num = (float)Math.Min(100, brightness) / 100f;
		if (!Finite(r) || !Finite(g) || !Finite(b))
		{
			r = (g = (b = num));
			return;
		}
		r = Math.Max(0f, r);
		g = Math.Max(0f, g);
		b = Math.Max(0f, b);
		float num2 = r / 3f + g / 3f + b / 3f;
		if (!(num2 >= num))
		{
			if (num2 <= 1E-06f)
			{
				r = (g = (b = num));
				return;
			}
			float num3 = num / num2;
			r *= num3;
			g *= num3;
			b *= num3;
		}
	}

	private static bool Finite(float value)
	{
		if (!float.IsNaN(value))
		{
			return !float.IsInfinity(value);
		}
		return false;
	}
}
internal sealed class MistSettings
{
	internal const int MinRadius = 5;

	internal const int MaxRadius = 60;

	internal readonly bool Enabled;

	internal readonly bool RemoveMist;

	internal readonly bool GammaEnabled;

	internal readonly int WispRadius;

	internal readonly int TorchRadius;

	internal readonly int Brightness;

	internal static MistSettings Defaults => new MistSettings(enabled: true, removeMist: false, 25, 30, gamma: true);

	internal static MistSettings Vanilla => new MistSettings(enabled: false, removeMist: false, 25, 30);

	internal bool Valid
	{
		get
		{
			if (WispRadius >= 5 && WispRadius <= 60 && TorchRadius >= 5 && TorchRadius <= 60 && Brightness >= 0)
			{
				return Brightness <= 100;
			}
			return false;
		}
	}

	internal MistSettings(bool enabled, bool removeMist, int wisp, int torch, bool gamma = false, int brightness = 60)
	{
		Enabled = enabled;
		RemoveMist = removeMist;
		WispRadius = wisp;
		TorchRadius = torch;
		GammaEnabled = gamma;
		Brightness = brightness;
	}

	internal bool Same(MistSettings other)
	{
		if (other != null && Enabled == other.Enabled && RemoveMist == other.RemoveMist && WispRadius == other.WispRadius && TorchRadius == other.TorchRadius && GammaEnabled == other.GammaEnabled)
		{
			return Brightness == other.Brightness;
		}
		return false;
	}

	internal string Wire()
	{
		string[] obj = new string[11]
		{
			Enabled ? "1" : "0",
			"|",
			RemoveMist ? "1" : "0",
			"|",
			null,
			null,
			null,
			null,
			null,
			null,
			null
		};
		int wispRadius = WispRadius;
		obj[4] = wispRadius.ToString(CultureInfo.InvariantCulture);
		obj[5] = "|";
		wispRadius = TorchRadius;
		obj[6] = wispRadius.ToString(CultureInfo.InvariantCulture);
		obj[7] = "|";
		obj[8] = (GammaEnabled ? "1" : "0");
		obj[9] = "|";
		wispRadius = Brightness;
		obj[10] = wispRadius.ToString(CultureInfo.InvariantCulture);
		return string.Concat(obj);
	}

	internal static bool TryRead(string[] parts, int offset, out MistSettings settings)
	{
		settings = null;
		if (parts.Length < offset + 6 || !Bit(parts[offset], out var result) || !Bit(parts[offset + 1], out var result2) || !Number(parts[offset + 2], out var result3) || !Number(parts[offset + 3], out var result4) || !Bit(parts[offset + 4], out var result5) || !Number(parts[offset + 5], out var result6))
		{
			return false;
		}
		MistSettings mistSettings = new MistSettings(result, result2, result3, result4, result5, result6);
		if (!mistSettings.Valid)
		{
			return false;
		}
		settings = mistSettings;
		return true;
	}

	internal static bool Bit(string value, out bool result)
	{
		result = value == "1";
		if (!result)
		{
			return value == "0";
		}
		return true;
	}

	internal static bool Number(string value, out int result)
	{
		return int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result);
	}

	internal static int KindForName(string name)
	{
		if (name == null)
		{
			return 0;
		}
		if (name.EndsWith("(Clone)", StringComparison.Ordinal))
		{
			name = name.Substring(0, name.Length - 7);
		}
		if (name == "demister_ball")
		{
			return 1;
		}
		if (name == "piece_groundtorch_mist")
		{
			return 2;
		}
		return 0;
	}
}
internal sealed class WireMessage
{
	internal char Kind;

	internal int Revision;

	internal int Notice;

	internal bool CanEdit;

	internal MistSettings Settings;

	internal static string Update(int revision, MistSettings value)
	{
		return "U|2|" + revision.ToString(CultureInfo.InvariantCulture) + "|" + value.Wire();
	}

	internal static string State(int revision, bool canEdit, MistSettings value, int notice)
	{
		return "S|2|" + revision.ToString(CultureInfo.InvariantCulture) + "|" + (canEdit ? "1" : "0") + "|" + value.Wire() + "|" + notice.ToString(CultureInfo.InvariantCulture);
	}

	internal static bool TryParse(string text, out WireMessage message)
	{
		message = null;
		if (text == null || text.Length > 128)
		{
			return false;
		}
		string[] array = text.Split('|');
		if (array.Length < 2 || array[1] != "2")
		{
			return false;
		}
		WireMessage wireMessage = new WireMessage();
		if (array[0] == "H" && array.Length == 2)
		{
			wireMessage.Kind = 'H';
			message = wireMessage;
			return true;
		}
		if (array.Length < 3 || !MistSettings.Number(array[2], out wireMessage.Revision))
		{
			return false;
		}
		if (array[0] == "U" && array.Length == 9)
		{
			wireMessage.Kind = 'U';
			if (!MistSettings.TryRead(array, 3, out wireMessage.Settings))
			{
				return false;
			}
		}
		else
		{
			if (!(array[0] == "S") || array.Length != 11)
			{
				return false;
			}
			wireMessage.Kind = 'S';
			if (!MistSettings.Bit(array[3], out wireMessage.CanEdit) || !MistSettings.TryRead(array, 4, out wireMessage.Settings) || !MistSettings.Number(array[10], out wireMessage.Notice) || wireMessage.Notice > 5)
			{
				return false;
			}
		}
		message = wireMessage;
		return true;
	}

	internal static int UpdateVerdict(bool admin, int currentRevision, WireMessage request)
	{
		if (!admin)
		{
			return 2;
		}
		if (request == null || request.Kind != 'U' || request.Settings == null || !request.Settings.Valid)
		{
			return 4;
		}
		if (request.Revision != currentRevision)
		{
			return 3;
		}
		return 1;
	}
}
[BepInPlugin("com.rustyheathens.mistcontrol", "Rusty Heathens Mist Control", "0.2.1")]
[BepInIncompatibility("ColdSpirit.GammaMod")]
public sealed class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Menu), "IsVisible")]
	private static class MenuVisiblePatch
	{
		private static void Postfix(ref bool __result)
		{
			if (BlockGameInput)
			{
				__result = true;
			}
		}
	}

	[HarmonyPatch(typeof(Menu), "IsActive")]
	private static class MenuActivePatch
	{
		private static void Postfix(ref bool __result)
		{
			if (BlockGameInput)
			{
				__result = true;
			}
		}
	}

	[HarmonyPatch(typeof(Menu), "Update")]
	private static class MenuUpdatePatch
	{
		private static bool Prefix()
		{
			return !BlockGameInput;
		}
	}

	[HarmonyPatch(typeof(PlayerController), "TakeInput")]
	private static class PlayerInputPatch
	{
		private static bool Prefix(ref bool __result)
		{
			if (!BlockGameInput)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	private static class ConnectionPatch
	{
		private static void Postfix(ZNetPeer __0)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				Instance.RegisterPeer(__0);
			}
		}
	}

	[HarmonyPatch(typeof(ParticleMist), "Update")]
	private static class MistPatch
	{
		private static bool Prefix(ParticleMist __instance)
		{
			if (!HideMist)
			{
				return true;
			}
			ParticleSystem component = ((Component)__instance).GetComponent<ParticleSystem>();
			if ((Object)(object)component != (Object)null && component.particleCount > 0)
			{
				component.Clear(false);
			}
			return false;
		}
	}

	private bool panelOpen;

	private bool draftDirty;

	private bool draftEnabled;

	private bool draftRemove;

	private bool draftGamma;

	private int draftWisp;

	private int draftTorch;

	private int draftBrightness;

	private int draftRevision;

	private int selectedTab;

	private int suppressThroughFrame = -1;

	private Rect panelRect = new Rect(40f, 40f, 560f, 600f);

	private GUISkin panelSkin;

	private GUIStyle headingStyle;

	private GUIStyle mutedStyle;

	private GUIStyle sectionStyle;

	private GUIStyle selectedStyle;

	private readonly Dictionary<GUIStyle, GUIStyle> textOutlines = new Dictionary<GUIStyle, GUIStyle>();

	private readonly List<Texture2D> panelTextures = new List<Texture2D>();

	private Texture2D emblem;

	private CursorLockMode priorLock;

	private bool priorCursor;

	private static readonly Color Blue = new Color(0.12f, 0.67f, 1f);

	public const string Id = "com.rustyheathens.mistcontrol";

	public const string Version = "0.2.1";

	internal const string RpcName = "RHMC_Settings_v2";

	internal static Plugin Instance;

	private Harmony harmony;

	private ConfigEntry<bool> enabledSetting;

	private ConfigEntry<bool> removeMist;

	private ConfigEntry<bool> gammaEnabled;

	private ConfigEntry<int> wispRadius;

	private ConfigEntry<int> torchRadius;

	private ConfigEntry<int> brightness;

	private ConfigEntry<KeyboardShortcut> panelKey;

	private ConfigEntry<KeyboardShortcut> toggleKey;

	private MistSettings localSettings;

	private MistSettings remoteSettings;

	private readonly HashSet<ZRpc> registered = new HashSet<ZRpc>();

	private readonly HashSet<ZRpc> subscribers = new HashSet<ZRpc>();

	private readonly Dictionary<ZRpc, float> requestTimes = new Dictionary<ZRpc, float>();

	private readonly Dictionary<ZRpc, float> helloTimes = new Dictionary<ZRpc, float>();

	private ZNet lastNet;

	private ZRpc serverRpc;

	private int revision;

	private int remoteRevision;

	private int helloAttempts;

	private float nextNetTick;

	private float nextHello;

	private float nextBroadcast;

	private float lastStateAt = -999f;

	private float pendingUntil;

	private bool remoteCanEdit;

	internal string Status = "";

	private Sprite inventoryWood;

	private Color inventoryWoodTint = Color.white;

	internal static bool BlockGameInput
	{
		get
		{
			if ((Object)(object)Instance != (Object)null)
			{
				if (!Instance.panelOpen)
				{
					return Time.frameCount <= Instance.suppressThroughFrame;
				}
				return true;
			}
			return false;
		}
	}

	private float PanelScale => Mathf.Clamp(Mathf.Min((float)Screen.width / 600f, (float)Screen.height / 650f), 0.35f, 1.5f);

	internal MistSettings Effective
	{
		get
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return MistSettings.Vanilla;
			}
			if (ZNet.instance.IsServer())
			{
				return localSettings ?? MistSettings.Vanilla;
			}
			if (!RemoteFresh)
			{
				return MistSettings.Vanilla;
			}
			return remoteSettings;
		}
	}

	internal bool RemoteFresh
	{
		get
		{
			if (remoteSettings != null)
			{
				return Time.realtimeSinceStartup - lastStateAt < 20f;
			}
			return false;
		}
	}

	internal bool CanEdit
	{
		get
		{
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				if (!ZNet.instance.IsServer())
				{
					if (RemoteFresh)
					{
						return remoteCanEdit;
					}
					return false;
				}
				return true;
			}
			return false;
		}
	}

	internal bool Pending => Time.realtimeSinceStartup < pendingUntil;

	internal int CurrentRevision
	{
		get
		{
			if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsServer())
			{
				return remoteRevision;
			}
			return revision;
		}
	}

	internal static bool HideMist
	{
		get
		{
			if ((Object)(object)Instance != (Object)null && Instance.Effective.Enabled)
			{
				return Instance.Effective.RemoveMist;
			}
			return false;
		}
	}

	private void RefreshDraft()
	{
		MistSettings effective = Effective;
		draftEnabled = effective.Enabled;
		draftRemove = effective.RemoveMist;
		draftWisp = effective.WispRadius;
		draftTorch = effective.TorchRadius;
		draftGamma = effective.GammaEnabled;
		draftBrightness = effective.Brightness;
		draftRevision = CurrentRevision;
		draftDirty = false;
	}

	private void OpenPanel()
	{
		//IL_001f: 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)
		FindInventoryWood();
		RefreshDraft();
		panelOpen = true;
		Status = "";
		priorLock = Cursor.lockState;
		priorCursor = Cursor.visible;
		if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer() && !RemoteFresh)
		{
			helloAttempts = 0;
			nextHello = 0f;
			Status = "Requesting server settings...";
		}
		((Rect)(ref panelRect)).x = Mathf.Max(12f, (float)Screen.width * 0.5f / PanelScale - ((Rect)(ref panelRect)).width * 0.5f);
		((Rect)(ref panelRect)).y = Mathf.Max(12f, (float)Screen.height * 0.5f / PanelScale - ((Rect)(ref panelRect)).height * 0.5f);
	}

	private void ClosePanel()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (panelOpen)
		{
			panelOpen = false;
			suppressThroughFrame = Time.frameCount + 1;
			Cursor.lockState = priorLock;
			Cursor.visible = priorCursor;
		}
	}

	private void LateUpdate()
	{
		if (panelOpen)
		{
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}
	}

	private Texture2D Surface(Color fill, Color border)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
		((Object)val).hideFlags = (HideFlags)61;
		for (int i = 0; i < 16; i++)
		{
			for (int j = 0; j < 16; j++)
			{
				val.SetPixel(j, i, (j == 0 || j == 15 || i == 0 || i == 15) ? border : fill);
			}
		}
		val.Apply(false, true);
		panelTextures.Add(val);
		return val;
	}

	private static void Paint(GUIStyle style, Texture2D normal, Texture2D hover, Color text)
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Expected O, but got Unknown
		style.normal.background = normal;
		style.hover.background = hover;
		style.active.background = hover;
		style.focused.background = hover;
		style.onNormal.background = hover;
		style.onHover.background = hover;
		style.onActive.background = hover;
		style.onFocused.background = hover;
		GUIStyleState normal2 = style.normal;
		GUIStyleState hover2 = style.hover;
		GUIStyleState active = style.active;
		Color val = (style.focused.textColor = text);
		Color val3 = (active.textColor = val);
		Color textColor = (hover2.textColor = val3);
		normal2.textColor = textColor;
		GUIStyleState onNormal = style.onNormal;
		GUIStyleState onHover = style.onHover;
		GUIStyleState onActive = style.onActive;
		val = (style.onFocused.textColor = text);
		val3 = (onActive.textColor = val);
		textColor = (onHover.textColor = val3);
		onNormal.textColor = textColor;
		style.border = new RectOffset(2, 2, 2, 2);
	}

	private void CreatePanelSkin()
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Expected O, but got Unknown
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Expected O, but got Unknown
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Expected O, but got Unknown
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Expected O, but got Unknown
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_028c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d9: Expected O, but got Unknown
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Expected O, but got Unknown
		//IL_0322: 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_0342: Expected O, but got Unknown
		//IL_035a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0370: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Expected O, but got Unknown
		//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cd: Expected O, but got Unknown
		//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0413: Unknown result type (might be due to invalid IL or missing references)
		//IL_041d: Expected O, but got Unknown
		panelSkin = Object.Instantiate<GUISkin>(GUI.skin);
		((Object)panelSkin).hideFlags = (HideFlags)61;
		Color baseColor = default(Color);
		((Color)(ref baseColor))..ctor(0.16f, 0.095f, 0.05f);
		Color val = default(Color);
		((Color)(ref val))..ctor(0.26f, 0.16f, 0.085f);
		Color val2 = default(Color);
		((Color)(ref val2))..ctor(0.38f, 0.26f, 0.14f);
		Color baseColor2 = default(Color);
		((Color)(ref baseColor2))..ctor(0.3f, 0.22f, 0.13f);
		Texture2D val3 = WoodSurface(baseColor, val2);
		Texture2D normal = WoodSurface(val, val2);
		Texture2D val4 = WoodSurface(baseColor2, Blue);
		Paint(panelSkin.window, val3, val3, Color.white);
		panelSkin.window.padding = new RectOffset(22, 22, 20, 18);
		panelSkin.window.fontSize = 1;
		panelSkin.label.fontSize = 16;
		panelSkin.label.wordWrap = true;
		panelSkin.label.normal.textColor = Color.white;
		Paint(panelSkin.button, normal, val4, Color.white);
		panelSkin.button.fontSize = 16;
		panelSkin.button.fixedHeight = 36f;
		panelSkin.button.margin = new RectOffset(3, 3, 4, 4);
		panelSkin.button.padding = new RectOffset(10, 10, 6, 6);
		panelSkin.toggle.fontSize = 16;
		panelSkin.toggle.wordWrap = true;
		GUIStyleState normal2 = panelSkin.toggle.normal;
		Color textColor = (panelSkin.toggle.onNormal.textColor = Color.white);
		normal2.textColor = textColor;
		GUIStyleState hover = panelSkin.toggle.hover;
		textColor = (panelSkin.toggle.onHover.textColor = Blue);
		hover.textColor = textColor;
		Paint(panelSkin.horizontalSlider, Surface(val, val2), Surface(val, val2), Color.white);
		panelSkin.horizontalSlider.fixedHeight = 8f;
		panelSkin.horizontalSlider.margin = new RectOffset(5, 5, 9, 13);
		Paint(panelSkin.horizontalSliderThumb, Surface(Blue, Blue), val4, Color.white);
		panelSkin.horizontalSliderThumb.fixedWidth = 18f;
		panelSkin.horizontalSliderThumb.fixedHeight = 22f;
		panelSkin.horizontalSliderThumb.overflow = new RectOffset(0, 0, 7, 7);
		headingStyle = new GUIStyle(panelSkin.label);
		headingStyle.fontSize = 24;
		headingStyle.fontStyle = (FontStyle)1;
		headingStyle.normal.textColor = new Color(0.68f, 0.89f, 1f);
		mutedStyle = new GUIStyle(panelSkin.label);
		mutedStyle.fontSize = 14;
		mutedStyle.normal.textColor = Color.white;
		sectionStyle = new GUIStyle(panelSkin.label);
		sectionStyle.fontSize = 17;
		sectionStyle.fontStyle = (FontStyle)1;
		sectionStyle.normal.textColor = new Color(0.68f, 0.89f, 1f);
		selectedStyle = new GUIStyle(panelSkin.button);
		Paint(selectedStyle, val4, val4, Color.white);
		using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("RHMC.Emblem.png");
		if (stream == null)
		{
			return;
		}
		using MemoryStream memoryStream = new MemoryStream();
		stream.CopyTo(memoryStream);
		emblem = new Texture2D(2, 2);
		((Object)emblem).hideFlags = (HideFlags)61;
		if (!ImageConversion.LoadImage(emblem, memoryStream.ToArray(), true))
		{
			Object.Destroy((Object)(object)emblem);
			emblem = null;
		}
	}

	private void DestroyPanelAssets()
	{
		if ((Object)(object)panelSkin != (Object)null)
		{
			Object.Destroy((Object)(object)panelSkin);
		}
		if ((Object)(object)emblem != (Object)null)
		{
			Object.Destroy((Object)(object)emblem);
		}
		foreach (Texture2D panelTexture in panelTextures)
		{
			if ((Object)(object)panelTexture != (Object)null)
			{
				Object.Destroy((Object)(object)panelTexture);
			}
		}
		panelTextures.Clear();
		textOutlines.Clear();
	}

	private void OnGUI()
	{
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Expected O, but got Unknown
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		if (!panelOpen || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return;
		}
		if ((Object)(object)panelSkin == (Object)null)
		{
			CreatePanelSkin();
		}
		GUISkin skin = GUI.skin;
		Matrix4x4 matrix = GUI.matrix;
		int depth = GUI.depth;
		try
		{
			GUI.skin = panelSkin;
			GUI.depth = -100;
			float panelScale = PanelScale;
			GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(panelScale, panelScale, 1f));
			((Rect)(ref panelRect)).x = Mathf.Clamp(((Rect)(ref panelRect)).x, 0f, Mathf.Max(0f, (float)Screen.width / panelScale - ((Rect)(ref panelRect)).width));
			((Rect)(ref panelRect)).y = Mathf.Clamp(((Rect)(ref panelRect)).y, 0f, Mathf.Max(0f, (float)Screen.height / panelScale - ((Rect)(ref panelRect)).height));
			panelRect = GUILayout.Window(19776301, panelRect, new WindowFunction(DrawPanel), "", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(560f),
				GUILayout.Height(600f)
			});
		}
		finally
		{
			GUI.skin = skin;
			GUI.matrix = matrix;
			GUI.depth = depth;
		}
	}

	private void PanelLabel(string text, params GUILayoutOption[] options)
	{
		PanelLabel(text, panelSkin.label, options);
	}

	private void PanelLabel(string text, GUIStyle style, params GUILayoutOption[] options)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Invalid comparison between Unknown and I4
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: 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_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		GUIContent val = new GUIContent(text);
		Rect rect = GUILayoutUtility.GetRect(val, style, options);
		if ((int)Event.current.type != 7)
		{
			return;
		}
		if (!textOutlines.TryGetValue(style, out var value))
		{
			value = new GUIStyle(style);
			value.normal.textColor = new Color(0.025f, 0.015f, 0.01f, 1f);
			textOutlines.Add(style, value);
		}
		bool enabled = GUI.enabled;
		try
		{
			GUI.enabled = true;
			GUI.Label(new Rect(((Rect)(ref rect)).x - 1f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), val, value);
			GUI.Label(new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), val, value);
			GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y - 1f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), val, value);
			GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), val, value);
			GUI.Label(rect, val, style);
		}
		finally
		{
			GUI.enabled = enabled;
		}
	}

	private void DrawPanel(int id)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0348: Unknown result type (might be due to invalid IL or missing references)
		//IL_034d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0366: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
		DrawInventoryWood(new Rect(0f, 0f, ((Rect)(ref panelRect)).width, ((Rect)(ref panelRect)).height));
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if ((Object)(object)emblem != (Object)null)
		{
			GUILayout.Label((Texture)(object)emblem, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(86f),
				GUILayout.Height(86f)
			});
		}
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Space(9f);
		PanelLabel("RUSTY HEATHENS", headingStyle);
		PanelLabel("MIST CONTROL  /  GAMMA", sectionStyle);
		PanelLabel("Make the darkness answer to you.", mutedStyle);
		GUILayout.EndVertical();
		GUILayout.EndHorizontal();
		bool flag = (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer();
		PanelLabel(flag ? "HOST CONTROLS" : (CanEdit ? "SERVER ADMIN CONTROLS" : "SERVER SETTINGS  /  VIEW ONLY"), mutedStyle);
		GUILayout.Space(6f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("Mist & wisps", (selectedTab == 0) ? selectedStyle : panelSkin.button, Array.Empty<GUILayoutOption>()))
		{
			selectedTab = 0;
		}
		if (GUILayout.Button("Gamma / brightness", (selectedTab == 1) ? selectedStyle : panelSkin.button, Array.Empty<GUILayoutOption>()))
		{
			selectedTab = 1;
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(12f);
		bool enabled = GUI.enabled;
		GUI.enabled = CanEdit && !Pending;
		if (selectedTab == 0)
		{
			DrawMistSettings();
		}
		else
		{
			DrawGammaSettings();
		}
		GUI.enabled = enabled;
		GUILayout.FlexibleSpace();
		PanelLabel(draftDirty ? "Unsaved changes - Apply saves both tabs for everyone." : "Settings are saved on the server and shared with players.", mutedStyle);
		GUI.enabled = CanEdit && !Pending;
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button(Pending ? "Applying..." : "Apply settings", selectedStyle, Array.Empty<GUILayoutOption>()))
		{
			Request(new MistSettings(draftEnabled, draftRemove, draftWisp, draftTorch, draftGamma, draftBrightness), draftRevision);
		}
		if (GUILayout.Button("Reset this tab", Array.Empty<GUILayoutOption>()))
		{
			if (selectedTab == 0)
			{
				draftEnabled = true;
				draftRemove = false;
				draftWisp = 25;
				draftTorch = 30;
			}
			else
			{
				draftGamma = true;
				draftBrightness = 60;
			}
			draftDirty = true;
		}
		GUILayout.EndHorizontal();
		GUI.enabled = enabled;
		string text = Status;
		if (!flag && !RemoteFresh)
		{
			text = "Waiting for matching server version. Local overrides are disabled.";
		}
		else if (!CanEdit && !flag)
		{
			text = "Only server admins can apply changes.";
		}
		PanelLabel(string.IsNullOrEmpty(text) ? " " : text, mutedStyle, GUILayout.Height(40f));
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		PanelLabel(((object)panelKey.Value/*cast due to .constrained prefix*/).ToString() + ": panel  |  " + ((object)toggleKey.Value/*cast due to .constrained prefix*/).ToString() + ": mist", mutedStyle);
		if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) }))
		{
			ClosePanel();
		}
		GUILayout.EndHorizontal();
		GUI.DragWindow(new Rect(0f, 0f, 560f, 108f));
	}

	private void DrawMistSettings()
	{
		Toggle("Enable custom mist settings", ref draftEnabled);
		Toggle("Hide all Mistlands mist", ref draftRemove);
		GUILayout.Space(8f);
		DrawSlider("Wisplight clearing radius", ref draftWisp, 5, 60, " m");
		DrawSlider("Wisp torch clearing radius", ref draftTorch, 5, 60, " m");
		PanelLabel((draftRemove && draftEnabled) ? "Mist is hidden. Bring it back to see your clearing ranges." : ((!draftEnabled) ? "Original mist and clearing ranges will be restored." : "Adjust mist clearing without changing weather fog."), mutedStyle);
	}

	private void DrawGammaSettings()
	{
		Toggle("Enable gamma / brightness boost", ref draftGamma);
		GUILayout.Space(16f);
		DrawSlider("Minimum ambient brightness", ref draftBrightness, 0, 100, "%");
		PanelLabel("Brighten dark nights and caves while keeping the lighting's color.", panelSkin.label);
		GUILayout.Space(12f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("Natural", Array.Empty<GUILayoutOption>()))
		{
			draftGamma = false;
			draftDirty = true;
		}
		if (GUILayout.Button("Soft  /  35%", Array.Empty<GUILayoutOption>()))
		{
			draftGamma = true;
			draftBrightness = 35;
			draftDirty = true;
		}
		if (GUILayout.Button("Clear  /  60%", Array.Empty<GUILayoutOption>()))
		{
			draftGamma = true;
			draftBrightness = 60;
			draftDirty = true;
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(8f);
		PanelLabel((draftGamma && draftBrightness > 0) ? "Only darker ambient lighting is raised. Higher values can flatten shadows." : "Normal game lighting will be restored.", mutedStyle);
		PanelLabel("Brightness works independently of the mist switch.", mutedStyle);
	}

	private void Toggle(string label, ref bool value)
	{
		bool flag = GUILayout.Toggle(value, " " + label, Array.Empty<GUILayoutOption>());
		if (flag != value)
		{
			value = flag;
			draftDirty = true;
		}
	}

	private void DrawSlider(string label, ref int value, int min, int max, string suffix)
	{
		PanelLabel(label + ": " + value + suffix);
		int num = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)value, (float)min, (float)max, Array.Empty<GUILayoutOption>()));
		if (num != value)
		{
			value = num;
			draftDirty = true;
		}
	}

	private void Awake()
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Expected O, but got Unknown
		//IL_0127: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Expected O, but got Unknown
		Instance = this;
		((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
		enabledSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "Enabled", true, "Enable custom mist settings. False restores captured vanilla ranges and mist rendering.");
		removeMist = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "RemoveMist", false, "Hide Mistlands particle mist. Does not delete world objects or change weather fog.");
		AcceptableValueRange<int> val = new AcceptableValueRange<int>(5, 60);
		wispRadius = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "WisplightRadius", 25, new ConfigDescription("Equipped wisplight mist-clearing radius in meters.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
		torchRadius = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "WispTorchRadius", 30, new ConfigDescription("Placed wisp torch mist-clearing radius in meters.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
		gammaEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "GammaEnabled", true, "Brighten dark ambient lighting. Independent of the mist switch; controlled by the server.");
		brightness = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "GammaBrightness", 60, new ConfigDescription("Minimum ambient brightness, 0-100. 60 matches the reference mod default; 0 leaves normal lighting. Does not change monitor gamma.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		panelKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "PanelShortcut", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Local shortcut to open/close the in-game panel.");
		toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ToggleShortcut", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Local admin shortcut to toggle mist visibility.");
		localSettings = ReadLocal();
		((BaseUnityPlugin)this).Config.Save();
		harmony = new Harmony("com.rustyheathens.mistcontrol");
		harmony.PatchAll(typeof(Plugin).Assembly);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Rusty Heathens Mist Control 0.2.1 loaded. F8: panel; Left Shift + F8: mist toggle.");
	}

	private MistSettings ReadLocal()
	{
		return new MistSettings(enabledSetting.Value, removeMist.Value, wispRadius.Value, torchRadius.Value, gammaEnabled.Value, brightness.Value);
	}

	private void Update()
	{
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		if (lastNet != ZNet.instance)
		{
			ResetSession();
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (pendingUntil > 0f && realtimeSinceStartup >= pendingUntil)
		{
			pendingUntil = 0f;
			Status = "No confirmation received. Check the current settings before trying again.";
		}
		if (realtimeSinceStartup >= nextNetTick)
		{
			nextNetTick = realtimeSinceStartup + 0.5f;
			NetworkTick(realtimeSinceStartup);
			RadiusControl.Refresh(Effective);
			GammaControl.Refresh(Effective);
		}
		KeyboardShortcut value;
		if ((Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).IsDead())
		{
			ClosePanel();
		}
		else if (panelOpen)
		{
			if (Input.GetKeyDown((KeyCode)27))
			{
				ClosePanel();
				return;
			}
			value = panelKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				ClosePanel();
			}
		}
		else
		{
			if (InputBlocked())
			{
				return;
			}
			value = toggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				if (!CanEdit)
				{
					Tell("Only a server admin can change mist settings.");
					return;
				}
				MistSettings effective = Effective;
				Request(new MistSettings(enabled: true, !effective.Enabled || !effective.RemoveMist, effective.WispRadius, effective.TorchRadius, effective.GammaEnabled, effective.Brightness), CurrentRevision);
			}
			else
			{
				value = panelKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					OpenPanel();
				}
			}
		}
	}

	private void ResetSession()
	{
		ClosePanel();
		foreach (ZRpc item in registered)
		{
			item.Unregister("RHMC_Settings_v2");
		}
		registered.Clear();
		subscribers.Clear();
		requestTimes.Clear();
		helloTimes.Clear();
		RadiusControl.Restore();
		GammaControl.Restore();
		lastNet = ZNet.instance;
		serverRpc = null;
		remoteSettings = null;
		remoteCanEdit = false;
		revision = (remoteRevision = (helloAttempts = 0));
		lastStateAt = -999f;
		pendingUntil = (nextHello = (nextBroadcast = (nextNetTick = 0f)));
		Status = "";
	}

	internal void RegisterPeer(ZNetPeer peer)
	{
		if (lastNet != ZNet.instance)
		{
			ResetSession();
		}
		if (peer != null && peer.m_rpc != null && registered.Add(peer.m_rpc))
		{
			peer.m_rpc.Register<string>("RHMC_Settings_v2", (Action<ZRpc, string>)OnMessage);
		}
	}

	private void NetworkTick(float now)
	{
		ZNet instance = ZNet.instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		HashSet<ZRpc> hashSet = new HashSet<ZRpc>();
		foreach (ZNetPeer peer in instance.GetPeers())
		{
			RegisterPeer(peer);
			if (peer.m_rpc != null)
			{
				hashSet.Add(peer.m_rpc);
			}
		}
		foreach (ZRpc item in new List<ZRpc>(registered))
		{
			if (!hashSet.Contains(item))
			{
				item.Unregister("RHMC_Settings_v2");
				registered.Remove(item);
				subscribers.Remove(item);
				requestTimes.Remove(item);
				helloTimes.Remove(item);
			}
		}
		if (instance.IsServer())
		{
			if (now >= nextBroadcast)
			{
				nextBroadcast = now + 5f;
				Broadcast();
			}
			return;
		}
		ZRpc val = instance.GetServerPeer()?.m_rpc;
		if (serverRpc != val)
		{
			serverRpc = val;
			remoteSettings = null;
			remoteCanEdit = false;
			helloAttempts = 0;
			nextHello = now;
			lastStateAt = -999f;
			pendingUntil = 0f;
		}
		if (serverRpc != null && now >= nextHello && (RemoteFresh || helloAttempts < 3))
		{
			serverRpc.Invoke("RHMC_Settings_v2", new object[1] { "H|2" });
			helloAttempts++;
			nextHello = now + (RemoteFresh ? 10f : 3f);
		}
		if (!RemoteFresh && helloAttempts >= 3)
		{
			Status = "No server sync. Install the same mod on the server, then reconnect.";
		}
	}

	private static ZNetPeer PeerFor(ZNet net, ZRpc rpc)
	{
		foreach (ZNetPeer peer in net.GetPeers())
		{
			if (peer.m_rpc == rpc)
			{
				return peer;
			}
		}
		return null;
	}

	private static bool IsAdmin(ZNet net, ZRpc rpc)
	{
		if (rpc != null && rpc.GetSocket() != null)
		{
			return net.IsAdmin(rpc.GetSocket().GetHostName());
		}
		return false;
	}

	private void OnMessage(ZRpc rpc, string payload)
	{
		ZNet instance = ZNet.instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		ZNetPeer val = PeerFor(instance, rpc);
		if (val == null || !val.IsReady() || !WireMessage.TryParse(payload, out var message))
		{
			return;
		}
		if (instance.IsServer())
		{
			if (message.Kind != 'H' && message.Kind != 'U')
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			Dictionary<ZRpc, float> dictionary = ((message.Kind == 'H') ? helloTimes : requestTimes);
			if (dictionary.TryGetValue(rpc, out var value) && realtimeSinceStartup - value < 0.2f)
			{
				return;
			}
			dictionary[rpc] = realtimeSinceStartup;
			subscribers.Add(rpc);
			if (message.Kind == 'H')
			{
				SendState(rpc, 0);
				return;
			}
			int num = WireMessage.UpdateVerdict(IsAdmin(instance, rpc), revision, message);
			if (num == 1 && !Commit(message.Settings))
			{
				num = 5;
			}
			if (num == 1)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Visibility settings changed by authenticated server admin.");
				Broadcast(rpc);
				SendState(rpc, 1);
			}
			else
			{
				SendState(rpc, num);
			}
			return;
		}
		ZNetPeer serverPeer = instance.GetServerPeer();
		if (serverPeer != null && serverPeer.m_rpc == rpc && message.Kind == 'S' && (!RemoteFresh || message.Revision >= remoteRevision))
		{
			remoteSettings = message.Settings;
			remoteRevision = message.Revision;
			remoteCanEdit = message.CanEdit;
			lastStateAt = Time.realtimeSinceStartup;
			if (message.Notice != 0)
			{
				pendingUntil = 0f;
			}
			if (message.Notice == 1)
			{
				Status = "Applied to everyone using this mod.";
				RefreshDraft();
			}
			else if (message.Notice == 2)
			{
				Status = "Change refused: only server admins may change these settings.";
			}
			else if (message.Notice == 3)
			{
				Status = "Another admin changed the settings. Review the refreshed values.";
				RefreshDraft();
			}
			else if (message.Notice == 4)
			{
				Status = "Invalid settings were rejected.";
			}
			else if (message.Notice == 5)
			{
				Status = "The server could not save its configuration. Change was not applied.";
			}
			else if (Status.StartsWith("No server sync", StringComparison.Ordinal))
			{
				Status = "Server settings received.";
			}
			if (panelOpen && !draftDirty)
			{
				RefreshDraft();
			}
			RadiusControl.Refresh(Effective);
			GammaControl.Refresh(Effective);
		}
	}

	private void SendState(ZRpc rpc, int notice)
	{
		if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && rpc.IsConnected())
		{
			rpc.Invoke("RHMC_Settings_v2", new object[1] { WireMessage.State(revision, IsAdmin(ZNet.instance, rpc), localSettings, notice) });
		}
	}

	private void Broadcast(ZRpc except = null)
	{
		foreach (ZRpc item in new List<ZRpc>(subscribers))
		{
			if (item != except)
			{
				SendState(item, 0);
			}
		}
	}

	private bool Commit(MistSettings settings)
	{
		if (settings == null || !settings.Valid)
		{
			return false;
		}
		MistSettings entries = localSettings;
		SetEntries(settings);
		try
		{
			((BaseUnityPlugin)this).Config.Save();
		}
		catch (Exception ex)
		{
			SetEntries(entries);
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not save mist settings: " + ex.Message));
			return false;
		}
		if (!settings.Same(localSettings))
		{
			revision++;
		}
		localSettings = settings;
		RadiusControl.Refresh(Effective);
		GammaControl.Refresh(Effective);
		RefreshDraft();
		return true;
	}

	private void SetEntries(MistSettings settings)
	{
		enabledSetting.Value = settings.Enabled;
		removeMist.Value = settings.RemoveMist;
		wispRadius.Value = settings.WispRadius;
		torchRadius.Value = settings.TorchRadius;
		gammaEnabled.Value = settings.GammaEnabled;
		brightness.Value = settings.Brightness;
	}

	internal void Request(MistSettings settings, int expectedRevision)
	{
		if (!CanEdit || !settings.Valid || Pending)
		{
			return;
		}
		if (ZNet.instance.IsServer())
		{
			if (expectedRevision != revision)
			{
				Status = "Settings changed. Review the refreshed values.";
				RefreshDraft();
			}
			else if (Commit(settings))
			{
				Broadcast();
				Tell("Visibility settings applied.");
				Status = "Saved and applied.";
			}
			else
			{
				Status = "Could not save configuration. Change was not applied.";
			}
		}
		else if (serverRpc != null)
		{
			serverRpc.Invoke("RHMC_Settings_v2", new object[1] { WireMessage.Update(expectedRevision, settings) });
			pendingUntil = Time.realtimeSinceStartup + 3f;
			Status = "Requested. Waiting for server confirmation.";
		}
	}

	private static bool InputBlocked()
	{
		if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !Minimap.IsOpen())
		{
			return StoreGui.IsVisible();
		}
		return true;
	}

	private static void Tell(string text)
	{
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
		}
	}

	private void OnDestroy()
	{
		ClosePanel();
		RadiusControl.Restore();
		GammaControl.Restore();
		foreach (ZRpc item in registered)
		{
			item.Unregister("RHMC_Settings_v2");
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		DestroyPanelAssets();
		Instance = null;
	}

	private void FindInventoryWood()
	{
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Invalid comparison between Unknown and I4
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: 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)
		inventoryWood = null;
		InventoryGui instance = InventoryGui.instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_player == (Object)null)
		{
			return;
		}
		int num = 0;
		Image[] componentsInChildren = ((Component)instance.m_player).GetComponentsInChildren<Image>(true);
		foreach (Image val in componentsInChildren)
		{
			Sprite val2 = (((Object)(object)val.overrideSprite != (Object)null) ? val.overrideSprite : val.sprite);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.texture == (Object)null))
			{
				string text = ((Object)val2).name.ToLowerInvariant();
				string text2 = ((Object)val).name.ToLowerInvariant();
				int num2 = (text.Contains("wood") ? 100 : 0);
				switch (text2)
				{
				case "bkg":
				case "background":
				case "bg":
					num2 += 30;
					break;
				}
				if ((int)val.type == 1)
				{
					num2 += 10;
				}
				if (num2 >= 30 && num2 > num && (!val2.packed || (int)val2.packingRotation == 0))
				{
					num = num2;
					inventoryWood = val2;
					inventoryWoodTint = ((Graphic)val).color;
				}
			}
		}
		if ((Object)(object)inventoryWood != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("F8 wood panel uses inventory sprite: " + ((Object)inventoryWood).name));
		}
	}

	private Texture2D WoodSurface(Color baseColor, Color edge)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
		((Object)val).hideFlags = (HideFlags)61;
		for (int i = 0; i < 128; i++)
		{
			for (int j = 0; j < 128; j++)
			{
				float num = 0.9f + 0.065f * Mathf.Sin((float)i * 2.2f + Mathf.Sin((float)j * 0.09f) * 0.7f) + 0.03f * Mathf.Sin((float)i * 0.33f + (float)j * 0.027f);
				Color val2 = baseColor * num;
				val2.a = 1f;
				if (j < 3 || i < 3 || j > 124 || i > 124)
				{
					val2 = edge;
				}
				else if (i % 32 == 0)
				{
					val2 *= 0.6f;
				}
				val.SetPixel(j, i, val2);
			}
		}
		val.Apply(false, true);
		panelTextures.Add(val);
		return val;
	}

	private void DrawInventoryWood(Rect target)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: 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_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)inventoryWood == (Object)null)
		{
			return;
		}
		Rect textureRect;
		try
		{
			textureRect = inventoryWood.textureRect;
		}
		catch
		{
			return;
		}
		Vector4 border = inventoryWood.border;
		float num = Mathf.Min(border.x, ((Rect)(ref target)).width / 3f);
		float num2 = Mathf.Min(border.z, ((Rect)(ref target)).width / 3f);
		float num3 = Mathf.Min(border.y, ((Rect)(ref target)).height / 3f);
		float num4 = Mathf.Min(border.w, ((Rect)(ref target)).height / 3f);
		float[] array = new float[4]
		{
			((Rect)(ref target)).x,
			((Rect)(ref target)).x + num,
			((Rect)(ref target)).xMax - num2,
			((Rect)(ref target)).xMax
		};
		float[] array2 = new float[4]
		{
			((Rect)(ref target)).y,
			((Rect)(ref target)).y + num4,
			((Rect)(ref target)).yMax - num3,
			((Rect)(ref target)).yMax
		};
		float[] array3 = new float[4]
		{
			((Rect)(ref textureRect)).x,
			((Rect)(ref textureRect)).x + border.x,
			((Rect)(ref textureRect)).xMax - border.z,
			((Rect)(ref textureRect)).xMax
		};
		float[] array4 = new float[4]
		{
			((Rect)(ref textureRect)).yMax,
			((Rect)(ref textureRect)).yMax - border.w,
			((Rect)(ref textureRect)).y + border.y,
			((Rect)(ref textureRect)).y
		};
		Texture2D texture = inventoryWood.texture;
		Color color = GUI.color;
		GUI.color = new Color(inventoryWoodTint.r, inventoryWoodTint.g, inventoryWoodTint.b, 1f);
		Rect val = default(Rect);
		Rect val2 = default(Rect);
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				((Rect)(ref val))..ctor(array[j], array2[i], array[j + 1] - array[j], array2[i + 1] - array2[i]);
				if (!(((Rect)(ref val)).width <= 0f) && !(((Rect)(ref val)).height <= 0f))
				{
					((Rect)(ref val2))..ctor(array3[j] / (float)((Texture)texture).width, array4[i + 1] / (float)((Texture)texture).height, (array3[j + 1] - array3[j]) / (float)((Texture)texture).width, (array4[i] - array4[i + 1]) / (float)((Texture)texture).height);
					GUI.DrawTextureWithTexCoords(val, (Texture)(object)texture, val2, true);
				}
			}
		}
		GUI.color = color;
	}
}
internal static class RadiusControl
{
	private sealed class Original
	{
		internal ParticleSystemForceField Field;

		internal float Start;

		internal float End;

		internal int Kind;
	}

	private static readonly Dictionary<Demister, Original> originals = new Dictionary<Demister, Original>();

	internal static void Refresh(MistSettings settings)
	{
		foreach (Demister demister in Demister.GetDemisters())
		{
			if ((Object)(object)demister == (Object)null)
			{
				continue;
			}
			if (!originals.TryGetValue(demister, out var value))
			{
				int num = 0;
				Transform val = ((Component)demister).transform;
				while ((Object)(object)val != (Object)null && num == 0)
				{
					num = MistSettings.KindForName(((Object)val).name);
					val = val.parent;
				}
				if (num == 0)
				{
					continue;
				}
				ParticleSystemForceField component = ((Component)demister).GetComponent<ParticleSystemForceField>();
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				value = new Original
				{
					Field = component,
					Start = component.startRange,
					End = component.endRange,
					Kind = num
				};
				originals.Add(demister, value);
			}
			Apply(value, settings);
		}
		foreach (Demister item in new List<Demister>(originals.Keys))
		{
			Original original = originals[item];
			if ((Object)(object)item == (Object)null || (Object)(object)original.Field == (Object)null)
			{
				originals.Remove(item);
			}
			else
			{
				Apply(original, settings);
			}
		}
	}

	private static void Apply(Original original, MistSettings settings)
	{
		float num = (settings.Enabled ? ((float)((original.Kind == 1) ? settings.WispRadius : settings.TorchRadius)) : original.End);
		float num2 = ((settings.Enabled && original.End > 0f) ? (original.Start * num / original.End) : original.Start);
		if (!Mathf.Approximately(original.Field.endRange, num))
		{
			original.Field.endRange = num;
		}
		if (!Mathf.Approximately(original.Field.startRange, num2))
		{
			original.Field.startRange = num2;
		}
	}

	internal static void Restore()
	{
		foreach (Original value in originals.Values)
		{
			if (!((Object)(object)value.Field == (Object)null))
			{
				value.Field.startRange = value.Start;
				value.Field.endRange = value.End;
			}
		}
		originals.Clear();
	}
}