Decompiled source of VikingAllfather v0.2.4

VikingAllfather.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VikingAllfather")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.4.0")]
[assembly: AssemblyInformationalVersion("0.2.4")]
[assembly: AssemblyProduct("VikingAllfather")]
[assembly: AssemblyTitle("VikingAllfather")]
[assembly: AssemblyVersion("0.2.4.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VikingAllfather
{
	[BepInPlugin("JustQOL.VikingAllfather", "Viking Allfather", "0.2.4")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class GearEdit
		{
			internal ItemData Item;

			internal int Before;

			internal int After;

			internal float Durability;
		}

		private sealed class BrowserState
		{
			public string Search = "";

			public string Category = "All";

			public string Quantity = "1";

			public string Quality = "1";

			public string Stars = "0";

			public bool Favorites;

			public int Page;

			public Vector2 Scroll;
		}

		private sealed class Entry
		{
			public GameObject Prefab;

			public string Name;

			public string Category;

			public Sprite Icon;
		}

		private sealed class Bookmark
		{
			public string Name;

			public Vector3 Position;
		}

		private sealed class LoadedGrave
		{
			public Vector3 Position;

			public long Time;
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass283_0
		{
			public Plugin <>4__this;

			public Player p;

			public Minimap map;

			public BitArray own;

			public BitArray shared;

			public long world;

			internal void <DrawTravelMap>b__0()
			{
				<>4__this.ChangeTravelZoom(<>4__this.travelMapZoom / 2f);
			}

			internal void <DrawTravelMap>b__1()
			{
				<>4__this.ChangeTravelZoom(<>4__this.travelMapZoom * 2f);
			}

			internal void <DrawTravelMap>b__2()
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: 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)
				<>4__this.travelMapZoom = Mathf.Max(8f, <>4__this.travelMapZoom);
				<>4__this.travelMapCenter = new Vector2(TravelMapRules.UV(((Component)p).transform.position.x, map.m_textureSize, map.m_pixelSize), TravelMapRules.UV(((Component)p).transform.position.z, map.m_textureSize, map.m_pixelSize));
				<>4__this.ClampTravelCenter();
				<>4__this.travelFogAt = 0f;
			}

			internal void <DrawTravelMap>b__3()
			{
				//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)
				<>4__this.travelMapZoom = 1f;
				<>4__this.travelMapCenter = new Vector2(0.5f, 0.5f);
				<>4__this.travelFogAt = 0f;
			}

			internal void <DrawTravelMap>b__4()
			{
				//IL_0014: 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)
				<>c__DisplayClass283_2 CS$<>8__locals7 = new <>c__DisplayClass283_2
				{
					CS$<>8__locals2 = this,
					destination = <>4__this.mapDestination,
					selectedWorld = world,
					character = p
				};
				<>4__this.Confirm("Teleport to map point " + ((Vector3)(ref CS$<>8__locals7.destination)).ToString("F1") + "? Terrain will load during travel. Water, structures and hazards may be present.", delegate
				{
					//IL_0071: Unknown result type (might be due to invalid IL or missing references)
					if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.GetWorldUID() != CS$<>8__locals7.selectedWorld || (Object)(object)Player.m_localPlayer != (Object)(object)CS$<>8__locals7.character)
					{
						throw new InvalidOperationException("World or character changed; select a destination again.");
					}
					if (((Character)CS$<>8__locals7.character).IsDead() || CS$<>8__locals7.CS$<>8__locals2.<>4__this.terrainCameraMode)
					{
						throw new InvalidOperationException("Leave terrain camera mode and use a living character before travel.");
					}
					CS$<>8__locals7.CS$<>8__locals2.<>4__this.Teleport(CS$<>8__locals7.destination);
				});
			}

			internal void <DrawTravelMap>b__5()
			{
				<>4__this.x = <>4__this.mapDestination.x.ToString("R", CultureInfo.InvariantCulture);
				<>4__this.y = <>4__this.mapDestination.y.ToString("R", CultureInfo.InvariantCulture);
				<>4__this.z = <>4__this.mapDestination.z.ToString("R", CultureInfo.InvariantCulture);
				<>4__this.Note("Map destination copied to coordinates.");
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass283_2
		{
			public long selectedWorld;

			public Player character;

			public Vector3 destination;

			public <>c__DisplayClass283_0 CS$<>8__locals2;

			internal void <DrawTravelMap>b__7()
			{
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.GetWorldUID() != selectedWorld || (Object)(object)Player.m_localPlayer != (Object)(object)character)
				{
					throw new InvalidOperationException("World or character changed; select a destination again.");
				}
				if (((Character)character).IsDead() || CS$<>8__locals2.<>4__this.terrainCameraMode)
				{
					throw new InvalidOperationException("Leave terrain camera mode and use a living character before travel.");
				}
				CS$<>8__locals2.<>4__this.Teleport(destination);
			}
		}

		private bool damageBoost;

		private bool criticalHits;

		private bool elemental;

		private bool knockbackBoost;

		private bool staggerBoost;

		private bool damageShield;

		private bool noKnockback;

		private bool regeneration;

		private bool adrenaline;

		private bool combatPlayers;

		private bool combatTamed;

		private bool advancedCombat;

		private ConfigEntry<float> damageScale;

		private ConfigEntry<float> critChance;

		private ConfigEntry<float> critScale;

		private ConfigEntry<float> pushScale;

		private ConfigEntry<float> staggerScale;

		private ConfigEntry<float> shieldPercent;

		private ConfigEntry<float> regenRate;

		private ConfigEntry<float> fireBonus;

		private ConfigEntry<float> frostBonus;

		private ConfigEntry<float> lightningBonus;

		private ConfigEntry<float> poisonBonus;

		private ConfigEntry<float> spiritBonus;

		private float regenClock;

		private int combatHits;

		private int combatCrits;

		private float lastCombatDamage;

		private bool allowBeyondQuality;

		private bool equippedGearOnly;

		private string gearSearch = "";

		private string gearTarget = "10";

		private ItemData selectedGear;

		private readonly List<GearEdit> gearUndo = new List<GearEdit>();

		private Player gearUndoOwner;

		private long gearUndoWorld;

		public const string Id = "JustQOL.VikingAllfather";

		internal static Plugin Instance;

		internal bool Open;

		internal bool Stamina;

		internal bool Eitr;

		internal bool Durability;

		internal bool Weight;

		internal bool NoFall;

		internal bool FreeCraft;

		internal bool FreeBuild;

		internal bool IgnoreStation;

		private bool god;

		private bool ghost;

		private bool fly;

		private bool favoritesOnly;

		private Harmony harmony;

		private RemotePowers powerLink;

		private ConfigEntry<KeyCode> menuKey;

		private ConfigEntry<KeyCode> panicKey;

		private ConfigEntry<KeyCode> menuModifier;

		private ConfigEntry<KeyCode> panicModifier;

		private ConfigEntry<string> favoriteConfig;

		private ConfigEntry<string> bookmarkConfig;

		private ConfigEntry<string> deathConfig;

		private ConfigEntry<float> uiScale;

		private ConfigEntry<float> remoteIdleMinutes;

		private ConfigEntry<bool> compactRows;

		private ConfigEntry<bool> rememberTab;

		private ConfigEntry<bool> receiveRequests;

		private ConfigEntry<bool> permitRemotePowers;

		private ConfigEntry<bool> permitRemoteTravel;

		private ConfigEntry<bool> permitRemoteRecovery;

		private ConfigEntry<bool> shareRemoteData;

		private ConfigEntry<string> lastTab;

		private ConfigEntry<string> playerFavorites;

		private readonly HashSet<string> favoritePlayers = new HashSet<string>();

		private Vector2 sidebarScroll;

		private float scaleDraft = 1f;

		private float idleDraft = 10f;

		private float ignoreShortcutUntil;

		private int bindingTarget;

		private int playerFilter;

		private bool showNativeActions;

		private readonly DeathHistory deathHistory = new DeathHistory();

		private readonly HashSet<string> favorites = new HashSet<string>();

		private readonly List<Bookmark> bookmarks = new List<Bookmark>();

		private readonly List<Entry> items = new List<Entry>();

		private readonly List<Entry> creatures = new List<Entry>();

		private readonly List<string> history = new List<string>();

		private Player tracked;

		private bool oldGod;

		private bool oldGhost;

		private bool oldFly;

		private bool oldFree;

		private float oldRun;

		private float oldSwim;

		private float oldJump;

		private int oldFlySpeed;

		private float speed = 1f;

		private float jump = 1f;

		private float swim = 1f;

		private float flightSpeed = 20f;

		private Rect window = new Rect(70f, 65f, 960f, 690f);

		private Vector2 scroll;

		private string tab = "Home";

		private string search = "";

		private string quantity = "1";

		private string quality = "1";

		private string stars = "0";

		private string bookmarkName = "Home";

		private string x = "0";

		private string y = "50";

		private string z = "0";

		private string status = "F5 opens the menu. Powers start disabled.";

		private string category = "All";

		private string pending = "";

		private Action pendingAction;

		private string[] tabs = new string[16]
		{
			"Home", "Player", "Combat", "Inventory", "Skills", "Camera", "Players", "Items", "Creatures", "Building",
			"Terrain", "Travel", "Environment", "Activity", "Settings", "Help"
		};

		private readonly TerrainEditor terrainEditor = new TerrainEditor();

		private Vector3 terrainPoint;

		private bool haveTerrainPoint;

		private bool terrainCameraMode;

		private bool terrainCameraWasFree;

		private bool terrainLocked;

		private bool terrainSnap;

		private float terrainRadius = 3f;

		private float terrainDepth = 3f;

		private float terrainDelta = 0.1f;

		private float terrainAngle;

		private float terrainGrid = 0.5f;

		private int terrainShape;

		private string terrainHeight = "0";

		private int terrainTool;

		private LineRenderer terrainPreview;

		private Material terrainMaterial;

		private LineRenderer terrainInnerPreview;

		private GUIStyle titleStyle;

		private GUIStyle mutedStyle;

		private GUIStyle rowStyle;

		private GUIStyle headingStyle;

		private readonly Dictionary<string, BrowserState> browserStates = new Dictionary<string, BrowserState>();

		private Texture2D panelTexture;

		private GUISkin allfatherSkin;

		private Font interfaceFont;

		private CursorLockMode oldCursor;

		private bool oldCursorVisible;

		private string exactTerrainStep = "0.10";

		private string playerSearch = "";

		private string selectedDistantPlayer = "";

		private readonly Dictionary<long, Vector3> previousPlayerPositions = new Dictionary<long, Vector3>();

		private int page;

		private string skillSearch = "";

		private string skillLevel = "50";

		private EnvMan environment;

		private bool ownTime;

		private bool ownWeather;

		private bool ownWind;

		private bool priorTimeEnabled;

		private bool priorWindEnabled;

		private float priorTime;

		private float priorWindAngle;

		private float priorWindIntensity;

		private float timeOfDay = 0.5f;

		private float windAngle;

		private float windIntensity = 0.5f;

		private string priorWeather;

		private Vector3 previous;

		private bool havePrevious;

		private Texture2D travelFog;

		private Color32[] travelFogPixels;

		private Vector2 travelMapCenter = new Vector2(0.5f, 0.5f);

		private float travelMapZoom = 1f;

		private float travelFogAt;

		private Rect travelFogUV;

		private Minimap travelMapOwner;

		private long travelMapWorld;

		private Vector3 mapDestination;

		private bool mapSelected;

		private bool mapPanning;

		private bool mapHeightLoaded;

		private const int FogSize = 256;

		private static readonly FieldInfo ExploredField = AccessTools.Field(typeof(Minimap), "m_explored");

		private static readonly FieldInfo OtherExploredField = AccessTools.Field(typeof(Minimap), "m_exploredOthers");

		internal bool OriginalNoCost => oldFree;

		internal bool AllowRemoteRequests => receiveRequests.Value;

		internal bool AllowRemotePowers => permitRemotePowers.Value;

		internal int RemoteIdleSeconds
		{
			get
			{
				float num = remoteIdleMinutes.Value;
				if (float.IsNaN(num) || float.IsInfinity(num))
				{
					num = 10f;
				}
				return Mathf.RoundToInt(Mathf.Clamp(num, 1f, 60f) * 60f);
			}
		}

		internal string MenuShortcut => Shortcut(menuModifier.Value, menuKey.Value);

		internal bool TerrainCameraMode => terrainCameraMode;

		internal bool UsesConsoleKeyThisFrame
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Invalid comparison between Unknown and I4
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && (int)menuKey.Value == 286 && ModifierHeld(menuModifier.Value))
				{
					return ZInput.GetKeyDown((KeyCode)286, true);
				}
				return false;
			}
		}

		private void BindCombat()
		{
			damageScale = CombatSetting("DamageMultiplier", 2f, 1f, 100f, "Outgoing character hit multiplier.");
			critChance = CombatSetting("CriticalChance", 25f, 0f, 100f, "Chance per outgoing hit, percent.");
			critScale = CombatSetting("CriticalMultiplier", 2f, 1f, 10f, "Critical damage multiplier, after outgoing scaling.");
			pushScale = CombatSetting("KnockbackMultiplier", 2f, 0f, 10f, "Outgoing push multiplier; zero disables push.");
			staggerScale = CombatSetting("StaggerMultiplier", 2f, 0f, 10f, "Outgoing stagger multiplier.");
			shieldPercent = CombatSetting("DamageReduction", 50f, 0f, 100f, "Incoming direct hit reduction percent, before armor.");
			regenRate = CombatSetting("RegenerationPerSecond", 5f, 1f, 100f, "Health healed per second while alive.");
			fireBonus = CombatSetting("FireBonus", 0f, 0f, 500f, "Flat fire damage per character hit.");
			frostBonus = CombatSetting("FrostBonus", 0f, 0f, 500f, "Flat frost damage per character hit.");
			lightningBonus = CombatSetting("LightningBonus", 25f, 0f, 500f, "Flat lightning damage per character hit.");
			poisonBonus = CombatSetting("PoisonBonus", 0f, 0f, 500f, "Flat poison damage per character hit.");
			spiritBonus = CombatSetting("SpiritBonus", 0f, 0f, 500f, "Flat spirit damage per character hit.");
		}

		private ConfigEntry<float> CombatSetting(string name, float initial, float min, float max, string description)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<float>("Combat", name, initial, new ConfigDescription(description + " Strength is saved; switches start off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
		}

		private static float Safe(ConfigEntry<float> setting, float min, float max)
		{
			return CombatRules.Bounded(setting.Value, min, max, min);
		}

		private void CombatSlider(string label, ConfigEntry<float> setting, float min, float max)
		{
			float num = Safe(setting, min, max);
			float num2 = Slider(label, num, min, max);
			if (num2 != num)
			{
				setting.Value = num2;
			}
		}

		private void ResetCombat()
		{
			damageBoost = (criticalHits = (elemental = (knockbackBoost = (staggerBoost = (damageShield = (noKnockback = (regeneration = (adrenaline = (combatPlayers = (combatTamed = false))))))))));
			regenClock = 0f;
			combatHits = (combatCrits = 0);
			lastCombatDamage = 0f;
		}

		private void TickCombat(Player p)
		{
			if (((Character)p).IsDead() || ((Character)p).IsTeleporting())
			{
				regenClock = 0f;
				return;
			}
			if (adrenaline)
			{
				((Character)p).AddAdrenaline(((Character)p).GetMaxAdrenaline());
			}
			if (!regeneration)
			{
				regenClock = 0f;
				return;
			}
			regenClock += Time.deltaTime;
			if (regenClock >= 1f)
			{
				((Character)p).Heal(Safe(regenRate, 1f, 100f), true);
				regenClock = 0f;
			}
		}

		internal void OutgoingCombat(Character target, ref HitData hit)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)target) && !((Object)(object)target == (Object)(object)localPlayer) && hit != null && !((Object)(object)hit.GetAttacker() != (Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && (!target.IsPlayer() || combatPlayers) && (!target.IsTamed() || combatTamed) && (damageBoost || criticalHits || elemental || knockbackBoost || staggerBoost))
			{
				hit = hit.Clone();
				hit.m_damage = ((DamageTypes)(ref hit.m_damage)).Clone();
				if (elemental)
				{
					hit.m_damage.m_fire += Safe(fireBonus, 0f, 500f);
					hit.m_damage.m_frost += Safe(frostBonus, 0f, 500f);
					hit.m_damage.m_lightning += Safe(lightningBonus, 0f, 500f);
					hit.m_damage.m_poison += Safe(poisonBonus, 0f, 500f);
					hit.m_damage.m_spirit += Safe(spiritBonus, 0f, 500f);
				}
				bool flag = criticalHits && CombatRules.Critical(Safe(critChance, 0f, 100f), Random.value);
				((DamageTypes)(ref hit.m_damage)).Modify(CombatRules.Multiplier(damageBoost ? Safe(damageScale, 1f, 100f) : 1f, flag, Safe(critScale, 1f, 10f)));
				if (knockbackBoost)
				{
					HitData obj = hit;
					obj.m_pushForce *= Safe(pushScale, 0f, 10f);
				}
				if (staggerBoost)
				{
					HitData obj2 = hit;
					obj2.m_staggerMultiplier *= Safe(staggerScale, 0f, 10f);
				}
				combatHits++;
				if (flag)
				{
					combatCrits++;
				}
				lastCombatDamage = ((DamageTypes)(ref hit.m_damage)).GetTotalDamage();
			}
		}

		internal void IncomingCombat(Character target, ref HitData hit)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Object)(object)target != (Object)(object)Player.m_localPlayer) && hit != null && (damageShield || noKnockback))
			{
				hit = hit.Clone();
				hit.m_damage = ((DamageTypes)(ref hit.m_damage)).Clone();
				if (damageShield)
				{
					((DamageTypes)(ref hit.m_damage)).Modify(CombatRules.Incoming(Safe(shieldPercent, 0f, 100f)));
				}
				if (noKnockback)
				{
					hit.m_pushForce = 0f;
				}
			}
		}

		private void DrawHome(Player p)
		{
			Header("Quick Actions");
			Hint("Your common controls in one place. Choose a section for detailed settings. Powers start disabled; Reset powers restores this session's switches.");
			Toggle("God mode", ref god, delegate(bool v)
			{
				p.SetGodMode(v || oldGod);
			});
			Toggle("Flight", ref fly, delegate(bool v)
			{
				if (p.InDebugFlyMode() != (v || oldFly))
				{
					p.ToggleDebugFly();
				}
				if (!v)
				{
					Character.m_debugFlySpeed = oldFlySpeed;
				}
			});
			Toggle("Unlimited stamina", ref Stamina);
			Toggle("Unlimited eitr", ref Eitr);
			Toggle("Boost damage", ref damageBoost);
			if (damageBoost)
			{
				CombatSlider("Damage multiplier", damageScale, 1f, 100f);
			}
			Button("Heal", delegate
			{
				((Character)p).Heal(((Character)p).GetMaxHealth(), true);
				Note("Health refilled.");
			});
			Button("Last grave / death history", delegate
			{
				SwitchTab("Travel");
			});
			Header("Find a tool");
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Button("Combat abilities", delegate
			{
				SwitchTab("Combat");
			});
			Button("Items & gear", delegate
			{
				SwitchTab("Items");
			});
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Button("Creative building", delegate
			{
				SwitchTab("Building");
			});
			Button("Terrain editor", delegate
			{
				SwitchTab("Terrain");
			});
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Button("Online players", delegate
			{
				SwitchTab("Players");
			});
			Button("Settings & keys", delegate
			{
				SwitchTab("Settings");
			});
			GUILayout.EndHorizontal();
		}

		private void DrawCombat()
		{
			Header("Combat abilities");
			Hint("Applied to your attributed melee, ranged and magic character hits. Strength values save; switches remain session-only. Armor, resistances, PvP rules and other mods still apply. No server plugin required; live compatibility is unverified.");
			Header("Damage");
			Toggle("Damage multiplier", ref damageBoost);
			if (damageBoost)
			{
				CombatSlider("Damage", damageScale, 1f, 100f);
			}
			Toggle("Critical strikes", ref criticalHits);
			if (criticalHits)
			{
				CombatSlider("Critical chance (%)", critChance, 0f, 100f);
				CombatSlider("Critical multiplier", critScale, 1f, 10f);
			}
			Toggle("Elemental infusion", ref elemental);
			if (elemental)
			{
				CombatSlider("Added fire", fireBonus, 0f, 500f);
				CombatSlider("Added frost", frostBonus, 0f, 500f);
				CombatSlider("Added lightning", lightningBonus, 0f, 500f);
				CombatSlider("Added poison", poisonBonus, 0f, 500f);
				CombatSlider("Added spirit", spiritBonus, 0f, 500f);
				Hint("Flat elemental additions are applied before damage and critical multipliers; poison/fire can deal damage over time under normal game rules.");
			}
			Header("Impact");
			Toggle("Knockback control", ref knockbackBoost);
			if (knockbackBoost)
			{
				CombatSlider("Knockback", pushScale, 0f, 10f);
			}
			Toggle("Stagger control", ref staggerBoost);
			if (staggerBoost)
			{
				CombatSlider("Stagger", staggerScale, 0f, 10f);
			}
			Header("Defense & endurance");
			Toggle("Damage reduction", ref damageShield);
			if (damageShield)
			{
				CombatSlider("Reduction (%)", shieldPercent, 0f, 100f);
			}
			Toggle("Prevent incoming hit knockback", ref noKnockback);
			Toggle("Health regeneration", ref regeneration);
			if (regeneration)
			{
				CombatSlider("Health / second", regenRate, 1f, 100f);
			}
			Toggle("Maintain adrenaline", ref adrenaline);
			Hint("Damage reduction changes direct incoming hits before armor. Existing status-effect damage, drowning and environmental drains can use other paths. God mode remains in Player / Home.");
			Header("Ability presets");
			Hint("Presets replace combat switches and strengths after confirmation; tweak each control afterward.");
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Button("Thor", delegate
			{
				CombatPreset("Thor");
			});
			Button("Berserker", delegate
			{
				CombatPreset("Berserker");
			});
			Button("Guardian", delegate
			{
				CombatPreset("Guardian");
			});
			GUILayout.EndHorizontal();
			advancedCombat = GUILayout.Toggle(advancedCombat, "Advanced targets & diagnostics", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			if (advancedCombat)
			{
				Toggle("Also modify hits on players (normal PvP checks remain)", ref combatPlayers);
				Toggle("Also modify hits on tamed creatures", ref combatTamed);
				Hint("Targets must be simulated/loaded for normal attacks. Combat powers are local controls, separate from cooperative remote powers. Object/building/resource damage is unchanged.");
				Hint("Modified outgoing hits: " + combatHits + " | Critical rolls: " + combatCrits + " | Last pre-armor damage: " + lastCombatDamage.ToString("0.0") + ". These count generated hits, not confirmed damage.");
			}
			Button("Reset combat only", delegate
			{
				ResetCombat();
				Note("Combat switches disabled; saved strengths retained.");
			});
		}

		private void CombatPreset(string name)
		{
			Confirm("Apply " + name + "? This replaces current combat switches and strengths. Player/tamed targets stay excluded.", delegate
			{
				ResetCombat();
				damageScale.Value = 2f;
				critChance.Value = 25f;
				critScale.Value = 2f;
				pushScale.Value = 2f;
				staggerScale.Value = 2f;
				shieldPercent.Value = 50f;
				regenRate.Value = 5f;
				ConfigEntry<float> obj = fireBonus;
				ConfigEntry<float> obj2 = frostBonus;
				ConfigEntry<float> obj3 = lightningBonus;
				ConfigEntry<float> obj4 = poisonBonus;
				float num = (spiritBonus.Value = 0f);
				float num3 = (obj4.Value = num);
				float num5 = (obj3.Value = num3);
				float value = (obj2.Value = num5);
				obj.Value = value;
				if (name == "Thor")
				{
					damageBoost = (elemental = (knockbackBoost = true));
					damageScale.Value = 3f;
					lightningBonus.Value = 75f;
					pushScale.Value = 3f;
				}
				if (name == "Berserker")
				{
					damageBoost = (criticalHits = (staggerBoost = (adrenaline = true)));
					damageScale.Value = 5f;
					critChance.Value = 40f;
					critScale.Value = 3f;
					staggerScale.Value = 3f;
				}
				if (name == "Guardian")
				{
					damageShield = (noKnockback = (regeneration = true));
					shieldPercent.Value = 75f;
					regenRate.Value = 10f;
				}
				Note(name + " combat preset applied.");
			});
		}

		private static bool WorkshopGear(ItemData item)
		{
			if (item != null && item.m_shared.m_maxStackSize == 1)
			{
				if (!item.IsEquipable())
				{
					return item.m_shared.m_maxQuality > 1;
				}
				return true;
			}
			return false;
		}

		private void ClearGearWorkshop()
		{
			selectedGear = null;
			gearUndo.Clear();
			gearUndoOwner = null;
			allowBeyondQuality = false;
		}

		private void DrawGearWorkshop(Player p)
		{
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			Inventory inv = ((Humanoid)p).GetInventory();
			Header("Gear Workshop");
			Hint("Set weapon, armor, shield and tool quality beyond levels 3–4. Edits are permanent, cost no resources and grant no recipe knowledge. Existing cheated flags are preserved. Reset powers does not undo quality edits.");
			Toggle("Allow beyond normal quality cap (up to 100)", ref allowBeyondQuality);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Target quality", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) });
			gearTarget = GUILayout.TextField(gearTarget, 3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) });
			int[] array = new int[5] { 5, 10, 25, 50, 100 };
			for (int i = 0; i < array.Length; i++)
			{
				int preset = array[i];
				Button(preset.ToString(), delegate
				{
					gearTarget = preset.ToString();
				}, 45f);
			}
			GUILayout.EndHorizontal();
			Hint("Higher quality uses the item's own stat growth. Some gear has no per-level growth; other mods may clamp or reject over-cap values.");
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Find gear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			gearSearch = GUILayout.TextField(gearSearch, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) });
			GUILayout.EndHorizontal();
			Toggle("Show equipped gear only", ref equippedGearOnly);
			if (selectedGear != null && !inv.GetAllItems().Contains(selectedGear))
			{
				selectedGear = null;
			}
			ItemData[] array2 = (from val in inv.GetAllItems().Where(WorkshopGear)
				where !equippedGearOnly || val.m_equipped
				where Localization.instance.Localize(val.m_shared.m_name).IndexOf(gearSearch, StringComparison.OrdinalIgnoreCase) >= 0
				select val).ToArray();
			foreach (ItemData item in array2)
			{
				string text = Localization.instance.Localize(item.m_shared.m_name) + "  Q" + item.m_quality + " / normal " + Math.Max(1, item.m_shared.m_maxQuality) + (item.m_equipped ? "  [equipped]" : "") + "  [" + item.m_gridPos.x + "," + item.m_gridPos.y + "]";
				Button(((selectedGear == item) ? "Selected: " : "") + text, delegate
				{
					selectedGear = item;
				});
			}
			if (selectedGear != null)
			{
				ItemData item2 = selectedGear;
				Header(Localization.instance.Localize(item2.m_shared.m_name));
				if (int.TryParse(gearTarget, out var result) && result >= 1 && result <= 100 && (allowBeyondQuality || result <= Math.Max(1, item2.m_shared.m_maxQuality)))
				{
					string[] obj = new string[8]
					{
						"Quality ",
						item2.m_quality.ToString(),
						" → ",
						result.ToString(),
						" | Damage ",
						null,
						null,
						null
					};
					DamageTypes damage = item2.GetDamage();
					obj[5] = ((DamageTypes)(ref damage)).GetTotalDamage().ToString("0.0");
					obj[6] = " → ";
					damage = item2.GetDamage(result, (float)item2.m_worldLevel);
					obj[7] = ((DamageTypes)(ref damage)).GetTotalDamage().ToString("0.0");
					Hint(string.Concat(obj));
					Hint("Armor " + item2.GetArmor().ToString("0.0") + " → " + item2.GetArmor(result, (float)item2.m_worldLevel).ToString("0.0") + " | Block " + item2.GetBaseBlockPower().ToString("0.0") + " → " + item2.GetBaseBlockPower(result).ToString("0.0") + " | Durability " + item2.GetMaxDurability().ToString("0") + " → " + item2.GetMaxDurability(result).ToString("0"));
				}
				else
				{
					Hint("Enter quality 1–100; enable beyond-cap editing when target exceeds this item's normal maximum.");
				}
				Button("Set selected gear quality", delegate
				{
					QueueGearEdit(p, (ItemData[])(object)new ItemData[1] { item2 }, normal: false);
				});
				Button("Return selected gear to normal cap", delegate
				{
					QueueGearEdit(p, (ItemData[])(object)new ItemData[1] { item2 }, normal: true);
				});
			}
			Button("Set all equipped gear to target quality", delegate
			{
				QueueGearEdit(p, (from val in inv.GetAllItems()
					where val.m_equipped && WorkshopGear(val)
					select val).ToArray(), normal: false);
			});
			if (gearUndo.Count <= 0)
			{
				return;
			}
			Button("Undo last gear quality edit", delegate
			{
				Confirm("Restore previous qualities for the last edited gear? Every edited item must still be carried and have the quality Allfather assigned.", delegate
				{
					UndoGear(p);
				});
			});
		}

		private void QueueGearEdit(Player p, ItemData[] items, bool normal)
		{
			if (items.Length == 0)
			{
				throw new InvalidOperationException("No matching gear is carried/equipped.");
			}
			int requested = (normal ? 1 : Rules.PositiveCount(gearTarget, 100));
			GearEdit[] planned = items.Select((ItemData i) => new GearEdit
			{
				Item = i,
				Before = i.m_quality,
				After = (normal ? Math.Max(1, i.m_shared.m_maxQuality) : GearRules.Quality(requested, i.m_shared.m_maxQuality, allowBeyondQuality)),
				Durability = i.m_durability
			}).ToArray();
			long world = ZNet.instance.GetWorldUID();
			Confirm("Set " + items.Length + " gear item(s) " + (normal ? "to each item's normal cap" : ("to quality " + requested)) + "? This can increase or decrease quality. Values persist with your character; this does not repair the item.", delegate
			{
				if ((Object)(object)Player.m_localPlayer != (Object)(object)p || !Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.GetWorldUID() != world)
				{
					throw new InvalidOperationException("Character/world changed. Select gear again.");
				}
				Inventory inventory = ((Humanoid)p).GetInventory();
				if (planned.Any((GearEdit e) => !inventory.GetAllItems().Contains(e.Item) || e.Item.m_quality != e.Before))
				{
					throw new InvalidOperationException("Gear changed or left your inventory. Select it again.");
				}
				gearUndo.Clear();
				gearUndoOwner = p;
				gearUndoWorld = world;
				GearEdit[] array = planned;
				foreach (GearEdit gearEdit in array)
				{
					gearEdit.Item.m_quality = gearEdit.After;
					gearEdit.Item.m_durability = Math.Min(gearEdit.Item.m_durability, gearEdit.Item.GetMaxDurability());
					gearUndo.Add(gearEdit);
				}
				AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null).Invoke(inventory, new object[2] { true, false });
				Note("Set quality on " + planned.Length + " gear item(s). Last quality edit can be undone while these items remain carried.");
			});
		}

		private void UndoGear(Player p)
		{
			Inventory inv = ((Humanoid)p).GetInventory();
			if ((Object)(object)p != (Object)(object)gearUndoOwner || !Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.GetWorldUID() != gearUndoWorld || gearUndo.Any((GearEdit e) => !inv.GetAllItems().Contains(e.Item) || e.Item.m_quality != e.After))
			{
				throw new InvalidOperationException("Undo refused: character/world, carried gear or quality changed.");
			}
			foreach (GearEdit item in gearUndo)
			{
				item.Item.m_quality = item.Before;
				item.Item.m_durability = Math.Min(item.Item.m_durability, item.Item.GetMaxDurability());
			}
			gearUndo.Clear();
			AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null).Invoke(inv, new object[2] { true, false });
			Note("Previous gear qualities restored. Durability wear is retained.");
		}

		private void Awake()
		{
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Expected O, but got Unknown
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			powerLink = new RemotePowers(this);
			menuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "Menu", (KeyCode)286, "Open or close the menu.");
			panicKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "Reset", (KeyCode)290, "Restore tracked player settings and disable Allfather powers.");
			menuModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "MenuModifier", (KeyCode)0, "Hold this modifier with Menu. None means press the menu key alone.");
			panicModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "ResetModifier", (KeyCode)308, "Hold this modifier with Reset. Either Alt key works. None disables the modifier requirement.");
			status = MenuShortcut + " opens the menu. Powers start disabled.";
			favoriteConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Browser", "Favorites", "", "Favorite prefab names, separated by semicolons.");
			bookmarkConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Travel", "Bookmarks", "", "Saved positions. Coordinates are not world specific; verify the world before using.");
			deathConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Travel", "DeathHistory", "", "Latest three deaths per character and world. Timestamp 0 means imported from the game's saved death point.");
			uiScale = ((BaseUnityPlugin)this).Config.Bind<float>("Interface", "Scale", 1f, "Menu scale (0.75–1.5), constrained to fit the screen.");
			compactRows = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "CompactActions", false, "Use shorter action buttons.");
			rememberTab = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "RememberTab", true, "Restore the last selected tab on the next launch.");
			lastTab = ((BaseUnityPlugin)this).Config.Bind<string>("Interface", "LastTab", "Home", "Last selected menu tab.");
			playerFavorites = ((BaseUnityPlugin)this).Config.Bind<string>("Players", "Favorites", "", "Locally saved favorite account IDs; names are a fallback when account ID is unavailable.");
			receiveRequests = ((BaseUnityPlugin)this).Config.Bind<bool>("Remote", "ReceiveRequests", true, "Allow other Allfather clients to request control. Approval is still mandatory.");
			permitRemotePowers = ((BaseUnityPlugin)this).Config.Bind<bool>("Remote", "AllowPowers", true, "Allow approved controllers to change power switches.");
			permitRemoteTravel = ((BaseUnityPlugin)this).Config.Bind<bool>("Remote", "AllowTravel", true, "Allow approved controllers to request teleports.");
			permitRemoteRecovery = ((BaseUnityPlugin)this).Config.Bind<bool>("Remote", "AllowRecovery", true, "Allow approved controllers to heal, refill resources and repair items.");
			shareRemoteData = ((BaseUnityPlugin)this).Config.Bind<bool>("Remote", "SharePositionAndDeaths", true, "Permit explicit position/death-history requests after control approval.");
			remoteIdleMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Remote", "IdleMinutes", 10f, "Revoke approved remote access after 1–60 idle minutes.");
			BindCombat();
			scaleDraft = ShortcutRules.Scale(uiScale.Value);
			idleDraft = (float)RemoteIdleSeconds / 60f;
			if (rememberTab.Value && tabs.Contains(lastTab.Value))
			{
				tab = lastTab.Value;
			}
			string[] array = playerFavorites.Value.Split(';');
			foreach (string text in array)
			{
				if (text.Length > 0)
				{
					favoritePlayers.Add(text);
				}
			}
			deathHistory.Load(deathConfig.Value);
			array = favoriteConfig.Value.Split(';');
			foreach (string text2 in array)
			{
				if (text2.Length > 0)
				{
					favorites.Add(text2);
				}
			}
			array = bookmarkConfig.Value.Split(';');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split('|');
				if (array2.Length == 4 && Float(array2[1], out var n) && Float(array2[2], out var n2) && Float(array2[3], out var n3))
				{
					bookmarks.Add(new Bookmark
					{
						Name = array2[0],
						Position = new Vector3(n, n2, n3)
					});
				}
			}
			harmony = new Harmony("JustQOL.VikingAllfather");
			harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Viking Allfather loaded. Client only; " + Shortcut(menuModifier.Value, menuKey.Value) + " menu / " + Shortcut(panicModifier.Value, panicKey.Value) + " reset."));
		}

		private void Update()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			if (ZInput.instance == null)
			{
				return;
			}
			if (bindingTarget == 0 && Time.unscaledTime >= ignoreShortcutUntil)
			{
				if (ModifierHeld(menuModifier.Value) && ZInput.GetKeyDown(menuKey.Value, true))
				{
					SetOpen(!Open);
				}
				if (ModifierHeld(panicModifier.Value) && ZInput.GetKeyDown(panicKey.Value, true))
				{
					Restore();
					SetOpen(value: false);
					Note("Allfather powers reset.");
				}
				if (Open && ZInput.GetKeyDown((KeyCode)27, true))
				{
					if (pendingAction != null)
					{
						pendingAction = null;
						pending = "";
					}
					else
					{
						SetOpen(value: false);
					}
				}
			}
			Player localPlayer = Player.m_localPlayer;
			if (tracked != localPlayer)
			{
				Restore();
				tracked = localPlayer;
				if (Object.op_Implicit((Object)(object)localPlayer))
				{
					oldGod = ((Character)localPlayer).InGodMode();
					oldGhost = ((Character)localPlayer).InGhostMode();
					oldFly = localPlayer.InDebugFlyMode();
					oldFree = localPlayer.NoCostCheat();
					oldRun = ((Character)localPlayer).m_runSpeed;
					oldSwim = ((Character)localPlayer).m_swimSpeed;
					oldJump = ((Character)localPlayer).m_jumpForce;
					oldFlySpeed = Character.m_debugFlySpeed;
					items.Clear();
					creatures.Clear();
					previousPlayerPositions.Clear();
					selectedDistantPlayer = "";
					havePrevious = false;
					haveTerrainPoint = false;
					terrainEditor.Clear();
					ClearTravelMap();
					ClearGearWorkshop();
					Run(ImportLatestDeath);
				}
			}
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				if (Open)
				{
					SetOpen(value: false);
				}
				return;
			}
			if (Stamina)
			{
				((Character)localPlayer).AddStamina(((Character)localPlayer).GetMaxStamina());
			}
			if (Eitr)
			{
				((Character)localPlayer).AddEitr(((Character)localPlayer).GetMaxEitr());
			}
			if (Durability)
			{
				foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems())
				{
					allItem.m_durability = allItem.GetMaxDurability();
				}
			}
			if (speed != 1f)
			{
				((Character)localPlayer).m_runSpeed = oldRun * speed;
			}
			if (swim != 1f)
			{
				((Character)localPlayer).m_swimSpeed = oldSwim * swim;
			}
			if (jump != 1f)
			{
				((Character)localPlayer).m_jumpForce = oldJump * jump;
			}
			if (fly)
			{
				Character.m_debugFlySpeed = Mathf.RoundToInt(flightSpeed);
			}
			TickCombat(localPlayer);
			powerLink.Tick();
		}

		private void LateUpdate()
		{
			if (Open)
			{
				UnlockCursor();
			}
			UpdateTerrainCamera();
			UpdateTerrainPreview();
		}

		internal void UnlockCursor()
		{
			ZCursor.LockState = (CursorLockMode)0;
			ZCursor.Show();
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		private void SetOpen(bool value)
		{
			//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_00b1: Unknown result type (might be due to invalid IL or missing references)
			if (!value)
			{
				pendingAction = null;
				pending = "";
			}
			if (!value)
			{
				bindingTarget = 0;
				if (lastTab != null && rememberTab.Value && tabs.Contains(tab))
				{
					lastTab.Value = tab;
				}
			}
			if (Open == value)
			{
				return;
			}
			if (value)
			{
				oldCursor = Cursor.lockState;
				oldCursorVisible = Cursor.visible;
			}
			Open = value;
			if (value && Object.op_Implicit((Object)(object)Console.instance) && Console.IsVisible())
			{
				((Component)((Terminal)Console.instance).m_chatWindow).gameObject.SetActive(false);
			}
			if (!value)
			{
				Cursor.lockState = oldCursor;
				Cursor.visible = oldCursorVisible;
				if (Object.op_Implicit((Object)(object)GameCamera.instance))
				{
					GameCamera.instance.UpdateMouseCapture();
				}
			}
			else
			{
				UnlockCursor();
			}
		}

		private void Restore()
		{
			powerLink?.Reset(restore: false);
			ExitTerrainCamera();
			RestoreEnvironment();
			pendingAction = null;
			pending = "";
			if (fly)
			{
				Character.m_debugFlySpeed = oldFlySpeed;
			}
			if (Object.op_Implicit((Object)(object)tracked))
			{
				if (god)
				{
					tracked.SetGodMode(oldGod);
				}
				if (ghost)
				{
					tracked.SetGhostMode(oldGhost);
				}
				if (fly && tracked.InDebugFlyMode() != oldFly)
				{
					tracked.ToggleDebugFly();
				}
				if (FreeBuild)
				{
					tracked.SetNoPlacementCost(oldFree);
				}
				if (speed != 1f)
				{
					((Character)tracked).m_runSpeed = oldRun;
				}
				if (swim != 1f)
				{
					((Character)tracked).m_swimSpeed = oldSwim;
				}
				if (jump != 1f)
				{
					((Character)tracked).m_jumpForce = oldJump;
				}
			}
			god = (ghost = (fly = (Stamina = (Eitr = (Durability = (Weight = (NoFall = (FreeCraft = (FreeBuild = (IgnoreStation = false))))))))));
			speed = (swim = (jump = 1f));
			ResetCombat();
		}

		private void OnDestroy()
		{
			ClearGearWorkshop();
			ClearTravelMap();
			Restore();
			SetOpen(value: false);
			powerLink?.Dispose();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if (Object.op_Implicit((Object)(object)panelTexture))
			{
				Object.Destroy((Object)(object)panelTexture);
			}
			if (Object.op_Implicit((Object)(object)allfatherSkin))
			{
				Object.Destroy((Object)(object)allfatherSkin);
			}
			if (Object.op_Implicit((Object)(object)interfaceFont))
			{
				Object.Destroy((Object)(object)interfaceFont);
			}
			if (Object.op_Implicit((Object)(object)terrainPreview))
			{
				Object.Destroy((Object)(object)((Component)terrainPreview).gameObject);
			}
			if (Object.op_Implicit((Object)(object)terrainInnerPreview))
			{
				Object.Destroy((Object)(object)((Component)terrainInnerPreview).gameObject);
			}
			if (Object.op_Implicit((Object)(object)terrainMaterial))
			{
				Object.Destroy((Object)(object)terrainMaterial);
			}
			Instance = null;
		}

		internal bool Local(Player p)
		{
			if (Object.op_Implicit((Object)(object)p))
			{
				return (Object)(object)p == (Object)(object)Player.m_localPlayer;
			}
			return false;
		}

		private static bool ModifierHeld(KeyCode key)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Invalid comparison between Unknown and I4
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Invalid comparison between Unknown and I4
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Invalid comparison between Unknown and I4
			bool flag = ZInput.GetKey((KeyCode)308, true) || ZInput.GetKey((KeyCode)307, true);
			bool flag2 = ZInput.GetKey((KeyCode)306, true) || ZInput.GetKey((KeyCode)305, true);
			bool flag3 = ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true);
			int num = (((int)key != 0) ? (((int)key == 308 || (int)key == 307) ? 1 : (((int)key == 306 || (int)key == 305) ? 2 : (((int)key == 304 || (int)key == 303) ? 3 : (-1)))) : 0);
			if (num < 0)
			{
				if (ZInput.GetKey(key, true) && !flag && !flag2)
				{
					return !flag3;
				}
				return false;
			}
			return ShortcutRules.Matches(num, flag, flag2, flag3);
		}

		private unsafe static string Shortcut(KeyCode modifier, KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			return (((int)modifier == 0) ? "" : (((int)modifier == 308 || (int)modifier == 307) ? "Alt+" : (((int)modifier == 306 || (int)modifier == 305) ? "Ctrl+" : (((int)modifier == 304 || (int)modifier == 303) ? "Shift+" : (((object)(*(KeyCode*)(&modifier))/*cast due to .constrained prefix*/).ToString() + "+"))))) + ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
		}

		private static bool Float(string s, out float n)
		{
			return Rules.FiniteFloat(s, out n);
		}

		private static int Number(string s, int max)
		{
			return Rules.PositiveCount(s, max);
		}

		internal void Note(string message)
		{
			status = message;
			history.Insert(0, DateTime.Now.ToString("HH:mm:ss") + "  " + message);
			if (history.Count > 150)
			{
				history.RemoveAt(150);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}

		internal void Run(Action action)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				Note("Action failed: " + ex.Message);
				if (!(ex is InvalidOperationException))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)ex);
				}
			}
		}

		internal void Confirm(string message, Action action)
		{
			pending = message;
			pendingAction = action;
		}

		internal void Button(string label, Action action, float width = 0f)
		{
			ConfigEntry<bool> obj = compactRows;
			float num = ((obj != null && obj.Value) ? 25 : 32);
			if ((width > 0f) ? GUILayout.Button(label, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(width),
				GUILayout.Height(num)
			}) : GUILayout.Button(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num) }))
			{
				Run(action);
			}
		}

		internal void Header(string text)
		{
			GUILayout.Space(12f);
			GUILayout.Label(text, headingStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(4f);
		}

		internal void Hint(string text)
		{
			GUILayout.Label(text, mutedStyle, Array.Empty<GUILayoutOption>());
		}

		internal int SharedPowerMask()
		{
			bool[] array = new bool[11]
			{
				god, fly, Stamina, Eitr, Weight, Durability, NoFall, ghost, FreeCraft, FreeBuild,
				IgnoreStation
			};
			int num = 0;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i])
				{
					num |= 1 << i;
				}
			}
			return num;
		}

		internal void SetSharedPower(SharedPower power, bool enabled)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer != tracked)
			{
				throw new InvalidOperationException("Local character is not ready.");
			}
			switch (power)
			{
			case SharedPower.God:
				localPlayer.SetGodMode(enabled || oldGod);
				god = enabled;
				break;
			case SharedPower.Flight:
				if (localPlayer.InDebugFlyMode() != (enabled || oldFly))
				{
					localPlayer.ToggleDebugFly();
				}
				if (!enabled)
				{
					Character.m_debugFlySpeed = oldFlySpeed;
				}
				fly = enabled;
				break;
			case SharedPower.Stamina:
				Stamina = enabled;
				break;
			case SharedPower.Eitr:
				Eitr = enabled;
				break;
			case SharedPower.Carry:
				Weight = enabled;
				break;
			case SharedPower.Durability:
				Durability = enabled;
				break;
			case SharedPower.NoFall:
				NoFall = enabled;
				break;
			case SharedPower.Ghost:
				localPlayer.SetGhostMode(enabled || oldGhost);
				ghost = enabled;
				break;
			case SharedPower.FreeCraft:
				FreeCraft = enabled;
				break;
			case SharedPower.FreeBuild:
				localPlayer.SetNoPlacementCost(enabled || oldFree);
				FreeBuild = enabled;
				break;
			case SharedPower.IgnoreStation:
				IgnoreStation = enabled;
				break;
			default:
				throw new ArgumentException("Unknown power.");
			}
		}

		private void Toggle(string label, ref bool value, Action<bool> changed = null)
		{
			bool flag = GUILayout.Toggle(value, "  " + label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			if (flag == value)
			{
				return;
			}
			try
			{
				changed?.Invoke(flag);
				value = flag;
				Note(label + (flag ? " enabled." : " disabled."));
			}
			catch (Exception ex)
			{
				Note(label + " failed: " + ex.Message);
				((BaseUnityPlugin)this).Logger.LogWarning((object)ex);
			}
		}

		private float Slider(string label, float value, float min, float max)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			value = GUILayout.HorizontalSlider(value, min, max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(250f) });
			GUILayout.Label(value.ToString("0.0"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
			GUILayout.EndHorizontal();
			return value;
		}

		private void OnGUI()
		{
			//IL_01c5: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			if (!Open && !terrainCameraMode)
			{
				return;
			}
			Matrix4x4 matrix = GUI.matrix;
			GUISkin skin = GUI.skin;
			if (!Object.op_Implicit((Object)(object)allfatherSkin))
			{
				allfatherSkin = Object.Instantiate<GUISkin>(skin);
				interfaceFont = Font.CreateDynamicFontFromOSFont(new string[3] { "Segoe UI", "Arial", "DejaVu Sans" }, 16);
				allfatherSkin.font = interfaceFont;
				GUIStyle[] array = (GUIStyle[])(object)new GUIStyle[7] { allfatherSkin.label, allfatherSkin.button, allfatherSkin.toggle, allfatherSkin.box, allfatherSkin.window, allfatherSkin.textField, allfatherSkin.textArea };
				foreach (GUIStyle obj in array)
				{
					obj.font = interfaceFont;
					obj.fontSize = 14;
				}
				array = allfatherSkin.customStyles;
				foreach (GUIStyle val in array)
				{
					if (val != null)
					{
						val.font = interfaceFont;
					}
				}
			}
			GUI.skin = allfatherSkin;
			float num = Mathf.Clamp(ShortcutRules.Scale(uiScale?.Value ?? 1f), 0.75f, Mathf.Max(0.75f, Mathf.Min(1.5f, (float)Screen.width / 850f)));
			GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f));
			try
			{
				DrawGui((float)Screen.width / num, (float)Screen.height / num);
			}
			finally
			{
				GUI.matrix = matrix;
				GUI.skin = skin;
			}
		}

		private void DrawGui(float viewWidth, float viewHeight)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			//IL_0488: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0578: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d1: Expected O, but got Unknown
			//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0606: Unknown result type (might be due to invalid IL or missing references)
			//IL_061b: Expected O, but got Unknown
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_061b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Expected O, but got Unknown
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: 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)
			//IL_03de: Expected O, but got Unknown
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Expected O, but got Unknown
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Expected O, but got Unknown
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Expected O, but got Unknown
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Invalid comparison between Unknown and I4
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Expected O, but got Unknown
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Invalid comparison between Unknown and I4
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Invalid comparison between Unknown and I4
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Invalid comparison between Unknown and I4
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00cc: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			if (Open && bindingTarget != 0 && (int)Event.current.type == 4 && (int)Event.current.keyCode != 0)
			{
				KeyCode keyCode = Event.current.keyCode;
				if ((int)keyCode == 308 || (int)keyCode == 307 || (int)keyCode == 306 || (int)keyCode == 305 || (int)keyCode == 304 || (int)keyCode == 303)
				{
					Note("Choose a main key; set the modifier separately.");
					Event.current.Use();
					return;
				}
				if ((int)keyCode != 27)
				{
					KeyCode val = ((bindingTarget == 1) ? panicKey.Value : menuKey.Value);
					KeyCode key = ((bindingTarget == 1) ? menuModifier.Value : panicModifier.Value);
					KeyCode key2 = ((bindingTarget == 1) ? panicModifier.Value : menuModifier.Value);
					if (keyCode == val && ModifierGroup(key) == ModifierGroup(key2))
					{
						Note("Menu and reset shortcuts must differ.");
						Event.current.Use();
						return;
					}
					if (bindingTarget == 1)
					{
						menuKey.Value = keyCode;
					}
					else
					{
						panicKey.Value = keyCode;
					}
					Note("Shortcut updated.");
				}
				bindingTarget = 0;
				ignoreShortcutUntil = Time.unscaledTime + 0.25f;
				Event.current.Use();
			}
			if (terrainCameraMode && !Open && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				Rect val2 = new Rect(16f, 16f, 540f, 150f);
				string[] obj = new string[18]
				{
					"TERRAIN CAMERA  /  ", null, null, null, null, null, null, null, null, null,
					null, null, null, null, null, null, null, null
				};
				TerrainEditor.Tool tool = (TerrainEditor.Tool)terrainTool;
				obj[1] = tool.ToString();
				obj[2] = "  /  ";
				TerrainShape terrainShape = (TerrainShape)this.terrainShape;
				obj[3] = terrainShape.ToString();
				obj[4] = "\nSize: ";
				obj[5] = (terrainRadius * 2f).ToString("0.00");
				obj[6] = " × ";
				obj[7] = (CurrentBrush().EffectiveDepth * 2f).ToString("0.00");
				obj[8] = " m   Step: ";
				obj[9] = terrainDelta.ToString("0.00");
				obj[10] = " m   Angle: ";
				obj[11] = terrainAngle.ToString("0");
				obj[12] = "°\nLeft click: apply   PageUp/PageDown: raise/lower   Ctrl+Z: undo\nQ: ";
				obj[13] = (terrainLocked ? "unpin" : "pin");
				obj[14] = " target   [ / ]: size   - / =: step   , / .: rotate\nWASD + Space/Ctrl: camera   Mouse wheel: camera speed\n";
				obj[15] = MenuShortcut;
				obj[16] = ": settings   Escape: leave editor   ";
				obj[17] = (haveTerrainPoint ? ((Vector3)(ref terrainPoint)).ToString("F2") : "Aim at loaded terrain");
				GUI.Box(val2, string.Concat(obj), new GUIStyle(GUI.skin.box)
				{
					alignment = (TextAnchor)0,
					fontSize = 14
				});
				GUI.DrawTexture(new Rect(viewWidth / 2f - 3f, viewHeight / 2f - 3f, 6f, 6f), (Texture)(object)Texture2D.whiteTexture);
				GUI.Box(new Rect(16f, 176f, 540f, 48f), status);
			}
			else if (Open && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				if (titleStyle == null)
				{
					titleStyle = new GUIStyle(GUI.skin.label)
					{
						fontSize = 25,
						fontStyle = (FontStyle)1
					};
					titleStyle.normal.textColor = new Color(1f, 0.79f, 0.4f);
					headingStyle = new GUIStyle(titleStyle)
					{
						fontSize = 17
					};
					mutedStyle = new GUIStyle(GUI.skin.label)
					{
						wordWrap = true,
						fontSize = 14
					};
					mutedStyle.normal.textColor = new Color(0.85f, 0.82f, 0.74f);
					rowStyle = new GUIStyle(GUI.skin.label)
					{
						fontSize = 14,
						wordWrap = false
					};
					panelTexture = new Texture2D(1, 1);
					panelTexture.SetPixel(0, 0, new Color(0.09f, 0.075f, 0.055f, 0.98f));
					panelTexture.Apply();
				}
				Color color = GUI.color;
				GUI.DrawTexture(new Rect(0f, 0f, viewWidth, viewHeight), (Texture)(object)Texture2D.blackTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.4f), 0f, 0f);
				((Rect)(ref window)).width = Mathf.Min(1000f, viewWidth - 16f);
				((Rect)(ref window)).height = Mathf.Min(740f, viewHeight - 16f);
				((Rect)(ref window)).x = Mathf.Clamp(((Rect)(ref window)).x, 0f, Mathf.Max(0f, viewWidth - ((Rect)(ref window)).width));
				((Rect)(ref window)).y = Mathf.Clamp(((Rect)(ref window)).y, 0f, Mathf.Max(0f, viewHeight - ((Rect)(ref window)).height));
				float m = GUI.matrix.m00;
				((Rect)(ref window)).x = Mathf.Round(((Rect)(ref window)).x * m) / m;
				((Rect)(ref window)).y = Mathf.Round(((Rect)(ref window)).y * m) / m;
				GUIStyle val3 = new GUIStyle(GUI.skin.window);
				val3.normal.background = panelTexture;
				val3.onNormal.background = panelTexture;
				window = GUILayout.Window(913048, window, new WindowFunction(DrawWindow), "", val3, Array.Empty<GUILayoutOption>());
				GUI.color = color;
			}
		}

		private void DrawWindow(int id)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0647: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("VIKING ALLFATHER", titleStyle, Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("Close  [" + Shortcut(menuModifier.Value, menuKey.Value) + "]", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(145f),
				GUILayout.Height(32f)
			}))
			{
				SetOpen(value: false);
			}
			GUILayout.EndHorizontal();
			Hint("JUSTQOL  /  CLIENT TOOLKIT  /  0.2.4 TESTING PREVIEW");
			GUILayout.Space(10f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(145f) });
			sidebarScroll = GUILayout.BeginScrollView(sidebarScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(Mathf.Max(120f, ((Rect)(ref window)).height - 180f)) });
			string[] array = tabs;
			foreach (string text in array)
			{
				string text2 = text switch
				{
					"Activity" => "SYSTEM", 
					"Travel" => "WORLD", 
					"Items" => "CREATION", 
					"Players" => "MULTIPLAYER", 
					"Player" => "CHARACTER", 
					"Home" => "QUICK ACCESS", 
					_ => null, 
				};
				if (text2 != null)
				{
					GUILayout.Space(8f);
					GUILayout.Label(text2, mutedStyle, Array.Empty<GUILayoutOption>());
				}
				GUI.backgroundColor = (Color)((tab == text) ? new Color(0.92f, 0.64f, 0.26f) : Color.white);
				if (GUILayout.Button(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }))
				{
					SwitchTab(text);
				}
			}
			GUILayout.EndScrollView();
			GUI.backgroundColor = Color.white;
			GUILayout.FlexibleSpace();
			Button("Reset powers", delegate
			{
				Restore();
				Note("Player settings restored.");
			});
			GUILayout.EndVertical();
			GUILayout.Space(16f);
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUI.enabled = pendingAction == null;
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			Player localPlayer = Player.m_localPlayer;
			switch (tab)
			{
			case "Home":
				DrawHome(localPlayer);
				break;
			case "Combat":
				DrawCombat();
				break;
			case "Player":
				DrawPlayer(localPlayer);
				break;
			case "Players":
				DrawPlayers(localPlayer);
				break;
			case "Items":
				DrawBrowser(animal: false);
				break;
			case "Creatures":
				DrawBrowser(animal: true);
				break;
			case "Building":
				DrawBuilding(localPlayer);
				break;
			case "Terrain":
				DrawTerrain(localPlayer);
				break;
			case "Travel":
				DrawTravel(localPlayer);
				break;
			case "Skills":
				DrawSkills(localPlayer);
				break;
			case "Environment":
				DrawEnvironment();
				break;
			case "Inventory":
				DrawInventory(localPlayer);
				break;
			case "Camera":
				DrawCamera();
				break;
			case "Activity":
				Header("This session");
				foreach (string item in history)
				{
					Hint(item);
				}
				break;
			case "Settings":
				DrawSettings();
				break;
			default:
				DrawHelp();
				break;
			}
			GUILayout.EndScrollView();
			GUI.enabled = true;
			if (pendingAction != null)
			{
				Header("Confirm action");
				Hint(pending);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				Button("Confirm", delegate
				{
					Action action = pendingAction;
					pendingAction = null;
					pending = "";
					action();
				});
				Button("Cancel", delegate
				{
					pendingAction = null;
					pending = "";
				});
				GUILayout.EndHorizontal();
			}
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUILayout.Space(8f);
			GUILayout.Label(status, mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) });
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref window)).width - 125f, 48f));
		}

		private void DrawPlayer(Player p)
		{
			Header("Player powers");
			Hint("Health " + ((Character)p).GetHealth().ToString("0") + " / " + ((Character)p).GetMaxHealth().ToString("0") + "    |    " + p.GetPlayerName());
			Toggle("God mode", ref god, delegate(bool v)
			{
				p.SetGodMode(v || oldGod);
			});
			Toggle("Ghost / ignored by creatures", ref ghost, delegate(bool v)
			{
				p.SetGhostMode(v || oldGhost);
			});
			Toggle("Flight", ref fly, delegate(bool v)
			{
				if (p.InDebugFlyMode() != (v || oldFly))
				{
					p.ToggleDebugFly();
				}
				if (!v)
				{
					Character.m_debugFlySpeed = oldFlySpeed;
				}
			});
			flightSpeed = Slider("Flight speed", flightSpeed, 1f, 100f);
			Hint("Flight uses Valheim movement controls: Space rises, Ctrl descends, Shift boosts. Close menu to move.");
			Toggle("Unlimited stamina", ref Stamina);
			Toggle("Unlimited eitr", ref Eitr);
			Toggle("Unlimited carry capacity", ref Weight);
			Toggle("No fall damage", ref NoFall);
			Toggle("Maintain item durability", ref Durability);
			Header("Movement");
			float num = Slider("Run multiplier", speed, 1f, 5f);
			if (num != speed)
			{
				speed = num;
				((Character)p).m_runSpeed = oldRun * speed;
			}
			num = Slider("Swim multiplier", swim, 1f, 5f);
			if (num != swim)
			{
				swim = num;
				((Character)p).m_swimSpeed = oldSwim * swim;
			}
			num = Slider("Jump multiplier", jump, 1f, 4f);
			if (num != jump)
			{
				jump = num;
				((Character)p).m_jumpForce = oldJump * jump;
			}
			Header("Instant recovery");
			Button("Heal health", delegate
			{
				((Character)p).Heal(((Character)p).GetMaxHealth(), true);
				Note("Health refilled.");
			});
			Button("Refill stamina", delegate
			{
				((Character)p).AddStamina(((Character)p).GetMaxStamina());
				Note("Stamina refilled.");
			});
			Button("Refill eitr", delegate
			{
				((Character)p).AddEitr(((Character)p).GetMaxEitr());
				Note("Eitr refilled.");
			});
			Button("Refill adrenaline", delegate
			{
				((Character)p).AddAdrenaline(((Character)p).GetMaxAdrenaline());
				Note("Adrenaline refilled.");
			});
			Header("Status effects");
			StatusEffect[] array = ((Character)p).GetSEMan().GetStatusEffects().ToArray();
			foreach (StatusEffect effect in array)
			{
				Button("Remove " + Localization.instance.Localize(effect.m_name), delegate
				{
					((Character)p).GetSEMan().RemoveStatusEffect(effect, false);
					Note("Removed status effect " + ((Object)effect).name + ". Equipment and environments may apply it again.");
				});
			}
		}

		internal Vector3 CoordinateTarget()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!Float(x, out var n) || !Float(y, out var n2) || !Float(z, out var n3) || !Rules.ValidDestination(n, n2, n3))
			{
				throw new ArgumentException("Enter valid destination coordinates in Travel first.");
			}
			return new Vector3(n, n2, n3);
		}

		internal IEnumerable<KeyValuePair<string, Vector3>> SavedDestinations()
		{
			return bookmarks.Select((Bookmark b) => new KeyValuePair<string, Vector3>(b.Name, b.Position)).ToArray();
		}

		internal DeathRecord[] CurrentDeathRecords()
		{
			ImportLatestDeath();
			PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
			return deathHistory.For(playerProfile.GetPlayerID(), ZNet.instance.GetWorldUID());
		}

		internal string ExecuteRemoteAction(RemoteAction action, Vector3 destination)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer != tracked)
			{
				throw new InvalidOperationException("Recipient character is not ready.");
			}
			switch (action)
			{
			case RemoteAction.Position:
			case RemoteAction.Deaths:
				if (!shareRemoteData.Value)
				{
					throw new InvalidOperationException("Recipient disabled position/death-history sharing.");
				}
				if (action != RemoteAction.Position)
				{
					return "Death history shared.";
				}
				return "Position shared.";
			case RemoteAction.Status:
				return "Power state refreshed.";
			default:
				if (((Character)localPlayer).IsDead())
				{
					throw new InvalidOperationException("Recipient character is dead.");
				}
				if (action == RemoteAction.Teleport || action == RemoteAction.LatestDeath || action == RemoteAction.Return)
				{
					if (!permitRemoteTravel.Value)
					{
						throw new InvalidOperationException("Recipient disabled remote travel.");
					}
					if (terrainCameraMode)
					{
						throw new InvalidOperationException("Recipient is using the terrain camera editor.");
					}
					if (action == RemoteAction.LatestDeath)
					{
						PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
						if (!playerProfile.HaveDeathPoint())
						{
							throw new InvalidOperationException("Recipient has no recorded death in this world.");
						}
						destination = playerProfile.GetDeathPoint() + Vector3.up;
					}
					if (action == RemoteAction.Return)
					{
						if (!havePrevious)
						{
							throw new InvalidOperationException("Recipient has no previous teleport position in this session.");
						}
						destination = previous;
					}
					Teleport(destination);
					return "Teleport started; arrival is not yet confirmed.";
				}
				if (!permitRemoteRecovery.Value)
				{
					throw new InvalidOperationException("Recipient disabled remote recovery actions.");
				}
				switch (action)
				{
				case RemoteAction.Heal:
					((Character)localPlayer).Heal(((Character)localPlayer).GetMaxHealth(), true);
					return "Health refilled to the current maximum.";
				case RemoteAction.RefillStamina:
					((Character)localPlayer).AddStamina(((Character)localPlayer).GetMaxStamina());
					return "Stamina refilled to the current maximum.";
				case RemoteAction.RefillEitr:
					((Character)localPlayer).AddEitr(((Character)localPlayer).GetMaxEitr());
					return "Eitr refilled to the current maximum.";
				case RemoteAction.Repair:
				{
					Inventory inventory = ((Humanoid)localPlayer).GetInventory();
					foreach (ItemData allItem in inventory.GetAllItems())
					{
						allItem.m_durability = allItem.GetMaxDurability();
					}
					AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null).Invoke(inventory, new object[2] { false, false });
					return "Carried equipment repaired.";
				}
				default:
					throw new ArgumentException("Unknown remote action.");
				}
			}
		}

		private void SettingToggle(string text, ConfigEntry<bool> setting, Action changed = null)
		{
			bool flag = GUILayout.Toggle(setting.Value, "  " + text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			if (flag != setting.Value)
			{
				setting.Value = flag;
				changed?.Invoke();
			}
		}

		private void DrawSettings()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			Header("Interface");
			Hint("Preferences save locally. They do not enable any powers or change server settings.");
			scaleDraft = Slider("Menu scale", scaleDraft, 0.75f, 1.5f);
			Button("Apply scale", delegate
			{
				uiScale.Value = scaleDraft;
				Note("Menu scale saved. It is constrained to fit the screen.");
			});
			SettingToggle("Compact action rows", compactRows);
			SettingToggle("Remember last tab", rememberTab);
			Header("Keyboard shortcuts");
			Hint("Menu: " + MenuShortcut + "    Reset: " + Shortcut(panicModifier.Value, panicKey.Value));
			Button((bindingTarget == 1) ? "Press a key for Menu (Escape cancels)" : "Change menu key", delegate
			{
				bindingTarget = 1;
			});
			Button((bindingTarget == 2) ? "Press a key for Reset (Escape cancels)" : "Change reset key", delegate
			{
				bindingTarget = 2;
			});
			ModifierSetting("Menu modifier", menuModifier);
			ModifierSetting("Reset modifier", panicModifier);
			Button("Restore F5 menu / Alt+F9 reset", delegate
			{
				menuKey.Value = (KeyCode)286;
				menuModifier.Value = (KeyCode)0;
				panicKey.Value = (KeyCode)290;
				panicModifier.Value = (KeyCode)308;
				Note("Default shortcuts restored.");
			});
			Header("Incoming cooperative controls");
			Hint("These preferences apply when someone controls your Allfather client. Session approval is always required; turning a category on does not grant access by itself.");
			SettingToggle("Receive control requests", receiveRequests, delegate
			{
				if (!receiveRequests.Value)
				{
					powerLink.RevokeIncoming();
				}
			});
			SettingToggle("Allow approved power changes", permitRemotePowers);
			SettingToggle("Allow approved teleport actions", permitRemoteTravel);
			SettingToggle("Allow approved healing/refills/repair", permitRemoteRecovery);
			SettingToggle("Share position and death history on explicit request", shareRemoteData);
			idleDraft = Slider("Idle expiry (minutes)", idleDraft, 1f, 60f);
			Button("Save idle expiry", delegate
			{
				idleDraft = Mathf.Round(idleDraft);
				remoteIdleMinutes.Value = idleDraft;
				Note("Remote idle expiry saved.");
			});
			Button("Revoke current incoming control", delegate
			{
				powerLink.RevokeIncoming();
			});
			Header("Session tools");
			Button("Clear activity display", delegate
			{
				history.Clear();
				status = "Activity display cleared; BepInEx logs are unchanged.";
			});
			Hint("Global controls require compatible Allfather 0.2.0 clients, online characters on the same server, and recipient approval. Nearby native controls remain separate. No server plugin is required; routing compatibility still needs live verification.");
		}

		private void ModifierSetting(string label, ConfigEntry<KeyCode> setting)
		{
			//IL_0013: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_0095: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			KeyCode[] array = new KeyCode[4];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			KeyCode[] array2 = (KeyCode[])(object)array;
			int num = ModifierGroup(setting.Value);
			if (num < 0)
			{
				num = 0;
			}
			GUILayout.Label(label, Array.Empty<GUILayoutOption>());
			int num2 = GUILayout.SelectionGrid(num, new string[4] { "None", "Alt", "Ctrl", "Shift" }, 4, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) });
			if (num2 == num)
			{
				return;
			}
			KeyCode val = array2[num2];
			bool num3;
			if (setting != menuModifier)
			{
				if (menuKey.Value == panicKey.Value)
				{
					num3 = ModifierGroup(val) == ModifierGroup(menuModifier.Value);
					goto IL_00ec;
				}
			}
			else if (menuKey.Value == panicKey.Value)
			{
				num3 = ModifierGroup(val) == ModifierGroup(panicModifier.Value);
				goto IL_00ec;
			}
			goto IL_00fa;
			IL_00ec:
			if (num3)
			{
				Note("Menu and reset shortcuts must differ.");
				return;
			}
			goto IL_00fa;
			IL_00fa:
			setting.Value = val;
		}

		private static int ModifierGroup(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if ((int)key != 0)
			{
				if ((int)key != 308 && (int)key != 307)
				{
					if ((int)key != 306 && (int)key != 305)
					{
						if ((int)key != 304 && (int)key != 303)
						{
							return -1;
						}
						return 3;
					}
					return 2;
				}
				return 1;
			}
			return 0;
		}

		private void DrawBuilding(Player p)
		{
			Header("Creative crafting and building");
			Toggle("Free crafting", ref FreeCraft);
			Hint("Craft and upgrade known recipes without consuming ingredients. Recipe, material and station learning is paused while this is enabled. Stations are still required unless separately bypassed.");
			Toggle("Free building", ref FreeBuild, delegate(bool v)
			{
				p.SetNoPlacementCost(v || oldFree);
			});
			Hint("Place hammer pieces without materials or build-station requirements. Does not enable free item crafting.");
			Toggle("Ignore crafting-station requirements", ref IgnoreStation);
			Hint("Bypass item crafting-station and level checks. Ingredients are still required unless Free crafting is enabled. DLC ownership checks remain in place.");
			Header("Builder supplies");
			string[] array = new string[9] { "Wood", "Stone", "FineWood", "RoundLog", "Iron", "Copper", "Bronze", "BlackMetal", "Tar" };
			foreach (string name in array)
			{
				Button("Add 50 " + name, delegate
				{
					SpawnItem(name, 50, 1);
				});
			}
			Hint("Select your hammer and open its build menu. Terrain restrictions and structural support are unchanged in this preview.");
		}

		private void SetTerrainPoint(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			float num = default(float);
			if (!Heightmap.GetHeight(point, ref num))
			{
				throw new InvalidOperationException("Target terrain is not loaded.");
			}
			point.y = num;
			terrainPoint = point;
			haveTerrainPoint = true;
			terrainHeight = num.ToString("F2", CultureInfo.InvariantCulture);
			Note("Terrain target: " + ((Vector3)(ref point)).ToString("F1"));
		}

		private TerrainGeometry CurrentBrush()
		{
			return new TerrainGeometry
			{
				Shape = (TerrainShape)terrainShape,
				Radius = terrainRadius,
				Depth = terrainDepth,
				Angle = terrainAngle
			};
		}

		private void DrawTerrain(Player p)
		{
			Header("Precision terrain editor");
			Hint("Persistent world edits. Terrain must be loaded and naturally client-owned. Undo restores terrain only, not collapsed buildings. Your body stays behind when the camera moves; god mode is separate.");
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Button("Target under me", delegate
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				SetTerrainPoint(((Component)p).transform.position);
			});
			Button("Target at crosshair", delegate
			{
				if (!AimTerrain())
				{
					throw new InvalidOperationException("Aim at loaded terrain within 100 metres.");
				}
			});
			GUILayout.EndHorizontal();
			string[] labels = new string[10] { "Level", "Raise", "Lower", "Smooth", "Dirt path", "Cultivate", "Pave", "Clear vegetation", "Restore surface", "Restore height" };
			Header("Operation");
			terrainTool = GUILayout.SelectionGrid(terrainTool, labels, 2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) });
			Header("Brush shape");
			if (TerrainEditor.SupportsShapes((TerrainEditor.Tool)terrainTool))
			{
				terrainShape = GUILayout.SelectionGrid(terrainShape, new string[6] { "Circle", "Square", "Rectangle", "Ellipse", "Ring", "Diamond" }, 3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(60f) });
			}
			else
			{
				terrainShape = 0;
				Hint("Native smoothing and surface tools use a circular brush.");
			}
			terrainRadius = Slider("Half-width / radius", terrainRadius, 0.25f, 20f);
			terrainDepth = Slider("Half-depth", terrainDepth, 0.25f, 20f);
			terrainDelta = Slider("Height step", terrainDelta, 0.01f, 4f);
			terrainAngle = Slider("Rotation degrees", terrainAngle, 0f, 355f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Exact step (metres)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			exactTerrainStep = GUILayout.TextField(exactTerrainStep, 8, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			Button("Set step", delegate
			{
				if (!Float(exactTerrainStep, out var n) || n < 0.01f || n > 4f)
				{
					throw new ArgumentException("Step must be 0.01–4 metres.");
				}
				terrainDelta = n;
			}, 95f);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Level / smooth height", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			terrainHeight = GUILayout.TextField(terrainHeight, 12, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			Button("Use my height", delegate
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				terrainHeight = ((Component)p).transform.position.y.ToString("F2", CultureInfo.InvariantCulture);
			}, 130f);
			GUILayout.EndHorizontal();
			terrainSnap = GUILayout.Toggle(terrainSnap, "  Snap target to world grid", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) });
			terrainGrid = Slider("Grid spacing", terrainGrid, 0.25f, 4f);
			Hint("Dimensions: " + (terrainRadius * 2f).ToString("0.00") + " × " + (CurrentBrush().EffectiveDepth * 2f).ToString("0.00") + " m. Raise/lower changes each covered terrain vertex by the selected step, within Valheim's native ±8 m limits.");
			Button(terrainCameraMode ? "Resume terrain camera editor" : "Enter terrain camera editor", delegate
			{
				Confirm("Enter armed terrain camera editing? Left click applies the selected tool; PageUp/PageDown raises/lowers. Every click saves terrain. Undo is one step and does not restore structures. Escape exits.", delegate
				{
					if (!Object.op_Implicit((Object)(object)GameCamera.instance))
					{
						throw new InvalidOperationException("Camera unavailable.");
					}
					if (Object.op_Implicit((Object)(object)InventoryGui.instance))
					{
						InventoryGui.instance.Hide();
					}
					if (!terrainCameraMode)
					{
						terrainCameraWasFree = GameCamera.InFreeFly();
						if (!terrainCameraWasFree)
						{
							GameCamera.instance.ToggleFreeFly();
						}
						terrainCameraMode = true;
						terrainLocked = false;
					}
					SetOpen(value: false);
					Note("Terrain camera editor active. Aim at ground; Escape exits.");
				});
			});
			if (terrainCameraMode)
			{
				Button("Exit terrain camera editor", delegate
				{
					ExitTerrainCamera();
					Note("Terrain camera editor stopped.");
				});
			}
			if (haveTerrainPoint)
			{
				Hint("Target: " + ((Vector3)(ref terrainPoint)).ToString("F2"));
				Button("Apply " + labels[terrainTool] + " at captured target", delegate
				{
					Confirm("Apply " + labels[terrainTool] + " to the previewed terrain? Persistent changes may collapse buildings.", delegate
					{
						ApplyTerrain((TerrainEditor.Tool)terrainTool);
					});
				});
			}
			if (!terrainEditor.CanUndo)
			{
				return;
			}
			Button("Undo last terrain operation", delegate
			{
				Confirm("Undo the last terrain operation? Later terrain changes or ownership changes will block undo.", delegate
				{
					terrainEditor.Undo();
					Note("Terrain operation undone.");
				});
			});
		}

		private bool AimTerrain()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Camera mainCamera = Utils.GetMainCamera();
			RaycastHit val = default(RaycastHit);
			if (!Object.op_Implicit((Object)(object)mainCamera) || !Physics.Raycast(mainCamera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)), ref val, 100f, LayerMask.GetMask(new string[1] { "terrain" })))
			{
				haveTerrainPoint = false;
				return false;
			}
			Vector3 point = ((RaycastHit)(ref val)).point;
			if (terrainSnap)
			{
				point.x = Mathf.Round(point.x / terrainGrid) * terrainGrid;
				point.z = Mathf.Round(point.z / terrainGrid) * terrainGrid;
			}
			if (!Heightmap.GetHeight(point, ref point.y))
			{
				haveTerrainPoint = false;
				return false;
			}
			terrainPoint = point;
			haveTerrainPoint = true;
			return true;
		}

		private void ApplyTerrain(TerrainEditor.Tool tool)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			UpdateTerrainPreview();
			if (!haveTerrainPoint || !Object.op_Implicit((Object)(object)terrainPreview) || !((Component)terrainPreview).gameObject.activeInHierarchy)
			{
				throw new InvalidOperationException("Aim at loaded terrain and wait for the gold outline.");
			}
			Vector3 point = terrainPoint;
			if (tool == TerrainEditor.Tool.Level || tool == TerrainEditor.Tool.Smooth)
			{
				if (!Float(terrainHeight, out var n))
				{
					throw new ArgumentException("Enter a valid target height in Terrain settings.");
				}
				point.y = n;
			}
			int num = terrainEditor.Apply(point, CurrentBrush(), terrainDelta, tool);
			string[] obj = new string[9]
			{
				"Applied ",
				tool.ToString(),
				" / ",
				null,
				null,
				null,
				null,
				null,
				null
			};
			TerrainShape terrainShape = (TerrainShape)this.terrainShape;
			obj[3] = terrainShape.ToString();
			obj[4] = " / step ";
			obj[5] = terrainDelta.ToString("0.00");
			obj[6] = " m. Undo available (";
			obj[7] = num.ToString();
			obj[8] = " tiles).";
			Note(string.Concat(obj));
		}

		private void ExitTerrainCamera()
		{
			if (terrainCameraMode && !terrainCameraWasFree && Object.op_Implicit((Object)(object)GameCamera.instance) && GameCamera.InFreeFly())
			{
				GameCamera.instance.ToggleFreeFly();
			}
			terrainCameraMode = false;
			terrainLocked = false;
		}

		private void UpdateTerrainCamera()
		{
			if (!terrainCameraMode || Open || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			if (!GameCamera.InFreeFly())
			{
				terrainCameraMode = false;
			}
			else if (ZInput.GetKeyDown((KeyCode)27, true))
			{
				ExitTerrainCamera();
				Note("Terrain camera editor stopped.");
			}
			else
			{
				if (Console.IsVisible() || (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()) || Menu.IsVisible() || InventoryGui.IsVisible())
				{
					return;
				}
				if (ZInput.GetKeyDown((KeyCode)113, true))
				{
					terrainLocked = !terrainLocked;
					Note(terrainLocked ? "Terrain target pinned." : "Terrain target follows camera.");
				}
				if (!terrainLocked)
				{
					AimTerrain();
				}
				if (ZInput.GetKeyDown((KeyCode)91, true))
				{
					terrainRadius = Mathf.Max(0.25f, terrainRadius - 0.25f);
				}
				if (ZInput.GetKeyDown((KeyCode)93, true))
				{
					terrainRadius = Mathf.Min(20f, terrainRadius + 0.25f);
				}
				if (ZInput.GetKeyDown((KeyCode)45, true))
				{
					terrainDelta = Mathf.Max(0.01f, terrainDelta - 0.01f);
				}
				if (ZInput.GetKeyDown((KeyCode)61, true))
				{
					terrainDelta = Mathf.Min(4f, terrainDelta + 0.01f);
				}
				if (ZInput.GetKeyDown((KeyCode)44, true))
				{
					terrainAngle = (terrainAngle + 355f) % 360f;
				}
				if (ZInput.GetKeyDown((KeyCode)46, true))
				{
					terrainAngle = (terrainAngle + 5f) % 360f;
				}
				if ((ZInput.GetKey((KeyCode)306, true) || ZInput.GetKey((KeyCode)305, true)) && ZInput.GetKeyDown((KeyCode)122, true))
				{
					Run(delegate
					{
						terrainEditor.Undo();
						Note("Terrain operation undone.");
					});
				}
				if (ZInput.GetKeyDown((KeyCode)323, true))
				{
					Run(delegate
					{
						ApplyTerrain((TerrainEditor.Tool)terrainTool);
					});
				}
				if (ZInput.GetKeyDown((KeyCode)280, true))
				{
					Run(delegate
					{
						ApplyTerrain(TerrainEditor.Tool.Raise);
					});
				}
				if (ZInput.GetKeyDown((KeyCode)281, true))
				{
					Run(delegate
					{
						ApplyTerrain(TerrainEditor.Tool.Lower);
					});
				}
			}
		}

		private LineRenderer NewTerrainLine(string name)
		{
			//IL_0001: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			LineRenderer obj = new GameObject(name).AddComponent<LineRenderer>();
			((Renderer)obj).sharedMaterial = terrainMaterial;
			obj.useWorldSpace = true;
			obj.loop = true;
			float startWidth = (obj.endWidth = 0.1f);
			obj.startWidth = startWidth;
			Color val = default(Color);
			((Color)(ref val))..ctor(1f, 0.72f, 0.2f);
			obj.endColor = val;
			obj.startColor = val;
			obj.positionCount = 64;
			return obj;
		}

		private void UpdateTerrainPreview()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			//IL_0144: 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_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_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			bool flag = ((Open && tab == "Terrain") || terrainCameraMode) && haveTerrainPoint;
			if (Object.op_Implicit((Object)(object)terrainPreview))
			{
				((Component)terrainPreview).gameObject.SetActive(flag);
			}
			if (Object.op_Implicit((Object)(object)terrainInnerPreview))
			{
				((Component)terrainInnerPreview).gameObject.SetActive(flag && terrainShape == 4);
			}
			if (!flag)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)terrainPreview))
			{
				Shader val = Shader.Find("Sprites/Default");
				if (!Object.op_Implicit((Object)(object)val))
				{
					return;
				}
				terrainMaterial = new Material(val);
				terrainPreview = NewTerrainLine("Allfather terrain shape");
				terrainInnerPreview = NewTerrainLine("Allfather terrain inner ring");
			}
			TerrainGeometry terrainGeometry = CurrentBrush();
			float num = terrainGeometry.Angle * (MathF.PI / 180f);
			Vector3 val3 = default(Vector3);
			float num9 = default(float);
			for (int i = 0; i < 64; i++)
			{
				TerrainShape shape = terrainGeometry.Shape;
				float num4;
				float num5;
				if (shape == TerrainShape.Square || shape == TerrainShape.Rectangle || shape == TerrainShape.Diamond)
				{
					int num2 = i / 16;
					float num3 = (float)(i % 16) / 16f;
					if (shape == TerrainShape.Diamond)
					{
						Vector2[] array = (Vector2[])(object)new Vector2[4]
						{
							new Vector2(0f, -1f),
							new Vector2(1f, 0f),
							new Vector2(0f, 1f),
							new Vector2(-1f, 0f)
						};
						Vector2 val2 = Vector2.Lerp(array[num2], array[(num2 + 1) % 4], num3);
						num4 = val2.x;
						num5 = val2.y;
					}
					else
					{
						num4 = num2 switch
						{
							2 => 1f - 2f * num3, 
							1 => 1f, 
							0 => -1f + 2f * num3, 
							_ => -1f, 
						};
						num5 = num2 switch
						{
							2 => 1f, 
							1 => -1f + 2f * num3, 
							0 => -1f, 
							_ => 1f - 2f * num3, 
						};
					}
				}
				else
				{
					float num6 = (float)i * MathF.PI / 32f;
					num4 = Mathf.Cos(num6);
					num5 = Mathf.Sin(num6);
				}
				float num7 = num4 * terrainGeometry.Radius;
				float num8 = num5 * terrainGeometry.EffectiveDepth;
				((Vector3)(ref val3))..ctor(num7 * Mathf.Cos(num) - num8 * Mathf.Sin(num), 0f, num7 * Mathf.Sin(num) + num8 * Mathf.Cos(num));
				Vector3 val4 = terrainPo