Decompiled source of WorldControl v3.0.5

plugins/WorldControl.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using WorldControl.Compat;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("WorldControl")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("3.0.5.0")]
[assembly: AssemblyInformationalVersion("3.0.5+df839a2fcf8ee6e01fd4c0ffd524be9bb9d379db")]
[assembly: AssemblyProduct("WorldControl")]
[assembly: AssemblyTitle("WorldControl")]
[assembly: AssemblyVersion("3.0.5.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 WorldControl
{
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("dezzycode.valheim.windcontrol", "World Control", "3.0.5")]
	[BepInDependency("com.jotunn.jotunn", "2.30.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private struct EitrAttackContextState
		{
			public int Depth;

			public bool Secondary;

			public bool Changed;
		}

		private struct EitrReloadCostState
		{
			public Attack Attack;

			public float Value;

			public bool Changed;
		}

		private struct EitrRepairCostState
		{
			public Attack Attack;

			public float Value;

			public bool Changed;
		}

		[HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[]
		{
			typeof(Character),
			typeof(bool)
		})]
		private static class EitrAttackContextPatch
		{
			private static void Prefix(Humanoid __instance, bool __1, ref EitrAttackContextState __state)
			{
				__state = new EitrAttackContextState
				{
					Depth = eitrAttackContextDepth,
					Secondary = eitrAttackContextSecondary,
					Changed = false
				};
				if (CanScaleLocalEitr((Character)(object)((__instance is Player) ? __instance : null)))
				{
					eitrAttackContextDepth++;
					eitrAttackContextSecondary = __1;
					__state.Changed = true;
				}
			}

			private static Exception Finalizer(Exception __exception, ref EitrAttackContextState __state)
			{
				RestoreEitrAttackContext(ref __state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Attack), "GetAttackEitr", new Type[] { })]
		private static class EitrAttackCostPatch
		{
			private static void Postfix(Attack __instance, Humanoid ___m_character, ref float __result)
			{
				if (CanScaleLocalEitr((Character)(object)___m_character) && !(__result <= 0f))
				{
					bool flag;
					if (eitrAttackContextDepth <= 0)
					{
						flag = __instance == eitrActiveAttack && eitrActiveAttackSecondary;
					}
					else
					{
						flag = eitrAttackContextSecondary;
						eitrActiveAttack = __instance;
						eitrActiveAttackSecondary = flag;
					}
					float num = (flag ? instance.playerRules.SecondaryEitr : instance.playerRules.PrimaryEitr);
					if (num != 1f)
					{
						__result *= num;
					}
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "GetDrawEitrDrain")]
		private static class EitrDrawCostPatch
		{
			private static void Postfix(ItemData __instance, ref float __result)
			{
				Plugin instance = Plugin.instance;
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)instance == (Object)null) && instance.playerRulesSynced && !((Object)(object)localPlayer == (Object)null) && __instance != null && !(__result <= 0f))
				{
					float drawEitr = instance.playerRules.DrawEitr;
					if (drawEitr != 1f && ((Humanoid)localPlayer).GetCurrentWeapon() == __instance)
					{
						__result *= drawEitr;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateWeaponLoading", new Type[]
		{
			typeof(ItemData),
			typeof(float)
		})]
		private static class EitrReloadCostPatch
		{
			private static void Prefix(Player __instance, ItemData __0, ref EitrReloadCostState __state)
			{
				__state = ScaleReloadEitrTemporarily(__instance, __0);
			}

			private static Exception Finalizer(Exception __exception, ref EitrReloadCostState __state)
			{
				RestoreReloadEitr(ref __state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Player), "Repair", new Type[]
		{
			typeof(ItemData),
			typeof(Piece)
		})]
		private static class EitrRepairCostPatch
		{
			private static void Prefix(Player __instance, ItemData __0, ref EitrRepairCostState __state)
			{
				__state = ScaleRepairEitrTemporarily(__instance, __0);
			}

			private static Exception Finalizer(Exception __exception, ref EitrRepairCostState __state)
			{
				RestoreRepairEitr(ref __state);
				return __exception;
			}
		}

		private struct RegenTickState
		{
			public float Stamina;

			public float Eitr;

			public bool Changed;
		}

		[HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })]
		private static class PlayerRegenCalculationPatch
		{
			private static void Prefix(Player __instance, ref RegenTickState __state)
			{
				__state = default(RegenTickState);
				Plugin instance = Plugin.instance;
				if ((Object)(object)instance == (Object)null || !instance.playerVitalsSynced || (Object)(object)__instance == (Object)null || __instance != Player.m_localPlayer)
				{
					return;
				}
				float staminaRegen = instance.playerVitals.StaminaRegen;
				float eitrRegen = instance.playerVitals.EitrRegen;
				if (staminaRegen != 1f || eitrRegen != 1f)
				{
					__state.Stamina = __instance.m_staminaRegen;
					__state.Eitr = __instance.m_eiterRegen;
					__state.Changed = true;
					if (staminaRegen != 1f)
					{
						__instance.m_staminaRegen = __state.Stamina * staminaRegen;
					}
					if (eitrRegen != 1f)
					{
						__instance.m_eiterRegen = __state.Eitr * eitrRegen;
					}
				}
			}

			private static Exception Finalizer(Exception __exception, Player __instance, ref RegenTickState __state)
			{
				RestoreRegenTick(__instance, ref __state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(EnvMan), "FixedUpdate")]
		private static class EnvironmentPatch
		{
			private static void Prefix(EnvMan __instance)
			{
				Plugin instance = Plugin.instance;
				if ((Object)(object)instance == (Object)null || instance.session == null || !instance.session.Synced || instance.session.State.Revision == 0L)
				{
					return;
				}
				if ((Object)(object)instance.controlledEnvironment != (Object)(object)__instance)
				{
					instance.RestoreEnvironment();
					instance.controlledEnvironment = __instance;
					instance.savedWeather = __instance.m_debugEnv;
					instance.savedTimeEnabled = __instance.m_debugTimeOfDay;
					instance.savedTime = __instance.m_debugTime;
					instance.savedWindEnabled = __instance.m_debugWind;
					instance.savedWindAngle = __instance.m_debugWindAngle;
					instance.savedWindStrength = __instance.m_debugWindIntensity;
					instance.controlledEnvironmentRevision = -1L;
				}
				long revision = instance.session.State.Revision;
				if (instance.controlledEnvironmentRevision != revision)
				{
					Request settings = instance.session.State.Settings;
					__instance.m_debugEnv = settings.Weather;
					if (settings.WindOn)
					{
						__instance.SetDebugWind(settings.Angle, settings.Strength);
					}
					else
					{
						__instance.ResetDebugWind();
					}
					if (settings.TimeMode == 1)
					{
						instance.ownedTime = true;
						__instance.m_debugTimeOfDay = false;
					}
					else if (instance.ownedTime)
					{
						__instance.m_debugTimeOfDay = false;
						instance.ownedTime = false;
					}
					instance.controlledEnvironmentRevision = revision;
				}
			}
		}

		[HarmonyPatch(typeof(EnvMan), "RescaleDayFraction")]
		private static class HeldDayTargetPatch
		{
			private static void Postfix(EnvMan __instance, ref float __result)
			{
				Plugin instance = Plugin.instance;
				if ((Object)(object)instance != (Object)null && (Object)(object)instance.controlledEnvironment == (Object)(object)__instance && instance.session != null && instance.session.Synced && instance.session.State.Settings.TimeMode == 1)
				{
					__result = instance.session.State.Settings.Hour / 24f;
				}
			}
		}

		internal struct BannedPlayer
		{
			public string Id;

			public string Name;
		}

		[HarmonyPatch(typeof(Plugin), "PlayerRule")]
		private static class PlayerRuleFiveMaxPatch
		{
			private static void Postfix(float value, ref bool __result)
			{
				__result = !float.IsNaN(value) && !float.IsInfinity(value) && value >= 0f && value <= 5f;
			}
		}

		[HarmonyPatch(typeof(Plugin), "ValidPlayerRules")]
		private static class PlayerRulesBuffOnlyValidationPatch
		{
			[HarmonyPriority(0)]
			private static void Postfix(PlayerResourceRules r, ref bool __result)
			{
				if (__result)
				{
					__result = BuffOnlyPlayerRules(r);
				}
			}
		}

		private sealed class AttackBaseline
		{
			public float AttackAdrenaline;
		}

		private sealed class ShieldBaseline
		{
			public float Block;

			public float Parry;
		}

		[HarmonyPatch(typeof(Player), "GetBuildStamina")]
		private static class PlayerRulesHomeStaminaPatch
		{
			private static void Postfix(Player __instance, ref float __result)
			{
				Plugin instance = Plugin.instance;
				if (!((Object)(object)instance == (Object)null) && instance.playerRulesSynced && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					__result *= instance.playerRules.HomeStamina;
				}
			}
		}

		private sealed class PlayerLine
		{
			public GameObject Row;

			public TMP_Text Name;

			public TMP_Text Where;

			public Button Bring;

			public Button Visit;

			public Button Kick;

			public Button Ban;

			public Button Admin;

			public TMP_Text AdminText;
		}

		private sealed class BannedLine
		{
			public GameObject Row;

			public TMP_Text Name;

			public TMP_Text Id;

			public Button Unban;
		}

		[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
		private static class PlayerVitalMaximumPatch
		{
			private static void Postfix(Player __instance, ref float __0, ref float __1, ref float __2)
			{
				Plugin instance = Plugin.instance;
				if (!((Object)(object)instance == (Object)null) && instance.playerVitalsSynced && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					__0 *= instance.playerVitals.MaxHealth;
					__1 *= instance.playerVitals.MaxStamina;
					__2 *= instance.playerVitals.MaxEitr;
				}
			}
		}

		[HarmonyPatch(typeof(Plugin), "EndSession")]
		private static class PlayerVitalsSessionEndPatch
		{
			private static void Prefix(Plugin __instance)
			{
				if ((Object)(object)__instance != (Object)null)
				{
					__instance.RestorePlayerVitalsLocal();
				}
			}
		}

		[HarmonyPatch(typeof(Plugin), "ValidVitalMax")]
		private static class PlayerVitalsMaxValidationPatch
		{
			private static void Postfix(float value, ref bool __result)
			{
				__result = !float.IsNaN(value) && !float.IsInfinity(value) && value >= 1f && value <= 5f;
			}
		}

		[HarmonyPatch(typeof(Plugin), "ValidVitalRegen")]
		private static class PlayerVitalsRegenValidationPatch
		{
			private static void Postfix(float value, ref bool __result)
			{
				__result = !float.IsNaN(value) && !float.IsInfinity(value) && value >= 1f && value <= 5f;
			}
		}

		[HarmonyPatch(typeof(RandEventSystem), "UpdateRandomEvent")]
		private static class EventPausePatch
		{
			private static bool Prefix()
			{
				if (!((Object)(object)instance == (Object)null) && instance.session != null && instance.session.Server)
				{
					return !instance.session.State.Settings.EventsPaused;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(ZNet), "OnDestroy")]
		private static class SessionEndPatch
		{
			private static void Prefix(ZNet __instance)
			{
				if ((Object)(object)instance != (Object)null && instance.network == __instance)
				{
					instance.EndSession();
				}
			}
		}

		private struct RainWetState
		{
			public bool Original;

			public bool Changed;
		}

		[HarmonyPatch(typeof(WearNTear), "IsWet")]
		private static class RainDamageWearPatch
		{
			private static void Prefix(WearNTear __instance, ref RainWetState __state)
			{
				__state = default(RainWetState);
				Plugin instance = Plugin.instance;
				if ((Object)(object)instance == (Object)null || instance.session == null || !instance.session.Synced || !instance.session.State.Settings.NoRainDamage || (Object)(object)__instance == (Object)null || !TryGetRainWetField())
				{
					return;
				}
				try
				{
					ref bool reference = ref rainWetField.Invoke(__instance);
					__state.Original = reference;
					__state.Changed = true;
					reference = false;
				}
				catch
				{
				}
			}

			private static Exception Finalizer(Exception __exception, WearNTear __instance, ref RainWetState __state)
			{
				RestoreRainWet(__instance, ref __state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Plugin), "Remember")]
		private static class RainDamageRememberPatch
		{
			[HarmonyPriority(0)]
			private static void Postfix(Plugin __instance)
			{
				if ((Object)(object)__instance != (Object)null)
				{
					__instance.RememberRainDamageSetting();
				}
			}
		}

		[HarmonyPatch(typeof(Plugin), "Recall")]
		private static class RainDamageRecallPatch
		{
			[HarmonyPriority(0)]
			private static void Postfix(Plugin __instance)
			{
				if ((Object)(object)__instance != (Object)null)
				{
					__instance.RecallRainDamageSetting();
				}
			}
		}

		private struct StaminaAttackContextState
		{
			public int Depth;

			public bool Secondary;

			public bool Changed;
		}

		private struct StaminaReloadState
		{
			public Attack Attack;

			public float Value;

			public bool Changed;
		}

		private struct BlockStaminaState
		{
			public float Normal;

			public float Perfect;

			public bool Changed;
		}

		[HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[]
		{
			typeof(Character),
			typeof(bool)
		})]
		private static class StaminaAttackContextPatch
		{
			private static void Prefix(Humanoid __instance, bool __1, ref StaminaAttackContextState __state)
			{
				__state = new StaminaAttackContextState
				{
					Depth = staminaAttackContextDepth,
					Secondary = staminaAttackContextSecondary,
					Changed = false
				};
				if (CanScaleLocalStamina((Character)(object)((__instance is Player) ? __instance : null)))
				{
					staminaAttackContextDepth++;
					staminaAttackContextSecondary = __1;
					__state.Changed = true;
				}
			}

			private static Exception Finalizer(Exception __exception, ref StaminaAttackContextState __state)
			{
				RestoreStaminaAttackContext(ref __state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Attack), "GetAttackStamina", new Type[] { })]
		private static class StaminaAttackCostPatch
		{
			private static void Postfix(Attack __instance, Humanoid ___m_character, ref float __result)
			{
				Plugin instance = Plugin.instance;
				if (!((Object)(object)instance == (Object)null) && instance.playerRulesSynced && CanScaleLocalStamina((Character)(object)___m_character) && !(__result <= 0f) && (__instance == null || !__instance.m_isHomeItem))
				{
					bool flag;
					if (staminaAttackContextDepth <= 0)
					{
						flag = __instance == staminaActiveAttack && staminaActiveAttackSecondary;
					}
					else
					{
						flag = staminaAttackContextSecondary;
						staminaActiveAttack = __instance;
						staminaActiveAttackSecondary = flag;
					}
					float num = (flag ? instance.playerRules.SecondaryStamina : instance.playerRules.PrimaryStamina);
					if (num != 1f)
					{
						__result *= num;
					}
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "GetDrawStaminaDrain")]
		private static class StaminaDrawCostPatch
		{
			private static void Postfix(ItemData __instance, ref float __result)
			{
				Plugin instance = Plugin.instance;
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)instance == (Object)null) && instance.playerRulesSynced && !((Object)(object)localPlayer == (Object)null) && __instance != null && !(__result <= 0f))
				{
					float drawStamina = instance.playerRules.DrawStamina;
					if (drawStamina != 1f && ((Humanoid)localPlayer).GetCurrentWeapon() == __instance)
					{
						__result *= drawStamina;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateWeaponLoading", new Type[]
		{
			typeof(ItemData),
			typeof(float)
		})]
		private static class StaminaReloadCostPatch
		{
			private static void Prefix(Player __instance, ItemData __0, ref StaminaReloadState __state)
			{
				__state = default(StaminaReloadState);
				if (CanScaleLocalStamina((Character)(object)__instance) && __0 != null && __0.m_shared != null && __0.m_shared.m_attack != null)
				{
					float reloadStamina = instance.playerRules.ReloadStamina;
					if (reloadStamina != 1f)
					{
						Attack val = (__state.Attack = __0.m_shared.m_attack);
						__state.Value = val.m_reloadStaminaDrain;
						__state.Changed = true;
						val.m_reloadStaminaDrain = __state.Value * reloadStamina;
					}
				}
			}

			private static Exception Finalizer(Exception __exception, ref StaminaReloadState __state)
			{
				RestoreStaminaReload(ref __state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Humanoid), "BlockAttack", new Type[]
		{
			typeof(HitData),
			typeof(Character)
		})]
		private static class BlockStaminaCostPatch
		{
			private static void Prefix(Humanoid __instance, ref BlockStaminaState __state)
			{
				__state = default(BlockStaminaState);
				if (CanScaleLocalStamina((Character)(object)((__instance is Player) ? __instance : null)))
				{
					float block = instance.playerRules.Block;
					if (block != 1f)
					{
						__state.Normal = __instance.m_blockStaminaDrain;
						__state.Perfect = __instance.m_perfectBlockStaminaDrain;
						__state.Changed = true;
						__instance.m_blockStaminaDrain = __state.Normal * block;
						__instance.m_perfectBlockStaminaDrain = __state.Perfect * block;
					}
				}
			}

			private static Exception Finalizer(Exception __exception, Humanoid __instance, ref BlockStaminaState __state)
			{
				RestoreBlockStamina(__instance, ref __state);
				return __exception;
			}
		}

		private sealed class TerrainOpSnapshot
		{
			private readonly TerrainOp op;

			private readonly float level;

			private readonly float raise;

			private readonly float smooth;

			private readonly float paint;

			public TerrainOpSnapshot(TerrainOp value)
			{
				op = value;
				Settings settings = value.m_settings;
				level = settings.m_levelRadius;
				raise = settings.m_raiseRadius;
				smooth = settings.m_smoothRadius;
				paint = settings.m_paintRadius;
			}

			public void Restore()
			{
				if (!((Object)(object)op == (Object)null) && op.m_settings != null)
				{
					op.m_settings.m_levelRadius = level;
					op.m_settings.m_raiseRadius = raise;
					op.m_settings.m_smoothRadius = smooth;
					op.m_settings.m_paintRadius = paint;
				}
			}
		}

		private sealed class TerrainModifierSnapshot
		{
			private readonly TerrainModifier modifier;

			private readonly float level;

			private readonly float smooth;

			public TerrainModifierSnapshot(TerrainModifier value)
			{
				modifier = value;
				level = value.m_levelRadius;
				smooth = value.m_smoothRadius;
			}

			public void Restore()
			{
				if (!((Object)(object)modifier == (Object)null))
				{
					modifier.m_levelRadius = level;
					modifier.m_smoothRadius = smooth;
				}
			}
		}

		private sealed class PlacementRadiusScope
		{
			public readonly HashSet<int> Seen = new HashSet<int>();

			public readonly List<TerrainOpSnapshot> Ops = new List<TerrainOpSnapshot>();

			public readonly List<TerrainModifierSnapshot> Modifiers = new List<TerrainModifierSnapshot>();

			public void Restore()
			{
				foreach (TerrainOpSnapshot op in Ops)
				{
					op.Restore();
				}
				foreach (TerrainModifierSnapshot modifier in Modifiers)
				{
					modifier.Restore();
				}
			}
		}

		[HarmonyPatch]
		private static class TerrainPlacementPatch
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!(methodInfo.Name != "TryPlacePiece") && !(methodInfo.ReturnType != typeof(bool)))
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Piece))
						{
							yield return methodInfo;
						}
					}
				}
			}

			[HarmonyPriority(800)]
			private static bool Prefix(Player __instance, Piece piece, ref bool __result)
			{
				RestoreTerrainRadiusScope();
				Plugin instance = Plugin.instance;
				if ((Object)(object)instance == (Object)null || instance.terrainEnabled == null || !instance.terrainEnabled.Value || !instance.CanEdit || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || (Object)(object)piece == (Object)null)
				{
					return true;
				}
				if (instance.IsTerrainRampPiece(piece))
				{
					__result = instance.ApplyRamp(__instance);
					return false;
				}
				if (instance.IsTerrainRevertPiece(piece))
				{
					__result = instance.ApplyRevert(__instance);
					return false;
				}
				if (instance.terrainToolRadiusEnabled == null || !instance.terrainToolRadiusEnabled.Value)
				{
					return true;
				}
				TerrainToolKind terrainToolKind = GetTerrainToolKind(((Humanoid)__instance).GetCurrentWeapon());
				if (terrainToolKind == TerrainToolKind.None)
				{
					return true;
				}
				float configuredTerrainRadius = instance.GetConfiguredTerrainRadius(terrainToolKind);
				PlacementRadiusScope placementRadiusScope = new PlacementRadiusScope();
				try
				{
					ScaleTerrainComponents(((Component)piece).gameObject, configuredTerrainRadius, placementRadiusScope);
					Piece val = null;
					try
					{
						val = __instance.GetSelectedPiece();
					}
					catch
					{
					}
					if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)piece)
					{
						ScaleTerrainComponents(((Component)val).gameObject, configuredTerrainRadius, placementRadiusScope);
					}
					if (placementRadiusScope.Ops.Count == 0 && placementRadiusScope.Modifiers.Count == 0)
					{
						placementRadiusScope.Restore();
						return true;
					}
					terrainActiveRadiusScope = placementRadiusScope;
				}
				catch
				{
					placementRadiusScope.Restore();
					throw;
				}
				return true;
			}

			private static Exception Finalizer(Exception __exception)
			{
				RestoreTerrainRadiusScope();
				return __exception;
			}
		}

		[HarmonyPatch]
		private static class TerrainGridMovementPatch
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "SetControls")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					foreach (ParameterInfo parameterInfo in parameters)
					{
						if (parameterInfo.Name == "movedir" && parameterInfo.ParameterType == typeof(Vector3))
						{
							yield return methodInfo;
							break;
						}
					}
				}
			}

			private static void Prefix(Player __instance, ref Vector3 movedir)
			{
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: 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)
				//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0111: Unknown result type (might be due to invalid IL or missing references)
				//IL_0118: Unknown result type (might be due to invalid IL or missing references)
				//IL_011d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0122: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0146: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_018b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0191: Unknown result type (might be due to invalid IL or missing references)
				//IL_0196: 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_019b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a7: 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)
				Plugin instance = Plugin.instance;
				if ((Object)(object)instance == (Object)null || instance.terrainEnabled == null || !instance.terrainEnabled.Value || instance.terrainGridMovement == null || !instance.terrainGridMovement.Value || !instance.CanEdit || instance.windowOpen || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !IsTerrainPickaxe(((Humanoid)__instance).GetCurrentWeapon()) || instance.terrainFlattenHold == null || !ShortcutHeld(instance.terrainFlattenHold.Value))
				{
					return;
				}
				Vector2 val = new Vector2(movedir.x, movedir.z);
				float num = Mathf.Clamp01(((Vector2)(ref val)).magnitude);
				if (!(num < 0.001f))
				{
					Vector3 val2 = ((Character)__instance).GetLookDir();
					val2.y = 0f;
					if (((Vector3)(ref val2)).sqrMagnitude < 0.001f)
					{
						val2 = ((Component)__instance).transform.forward;
						val2.y = 0f;
					}
					((Vector3)(ref val2)).Normalize();
					Vector3 val3 = Vector3.Cross(Vector3.up, val2);
					Vector3 normalized = ((Vector3)(ref val3)).normalized;
					Vector3 val4 = val2 * movedir.z + normalized * movedir.x;
					val4.y = 0f;
					if (!(((Vector3)(ref val4)).sqrMagnitude < 0.001f))
					{
						((Vector3)(ref val4)).Normalize();
						float num2 = Mathf.Round(Mathf.Atan2(val4.x, val4.z) * 57.29578f / 45f) * 45f * ((float)Math.PI / 180f);
						Vector3 val5 = new Vector3(Mathf.Sin(num2), 0f, Mathf.Cos(num2)) * num;
						movedir.x = Vector3.Dot(val5, normalized);
						movedir.z = Vector3.Dot(val5, val2);
						movedir.y = 0f;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Plugin), "CreateTerrainActionPiece")]
		private static class TerrainActionPieceUsagePatch
		{
			[HarmonyPriority(0)]
			private static void Postfix(PieceTable table, GameObject __result)
			{
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: 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_0085: 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)
				if ((Object)(object)table == (Object)null || (Object)(object)__result == (Object)null)
				{
					return;
				}
				Piece component = __result.GetComponent<Piece>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				int num = FindHoeGroundIndex(table);
				if (num >= 0 && num < table.m_pieces.Count && (Object)(object)table.m_pieces[num] != (Object)null)
				{
					Piece component2 = table.m_pieces[num].GetComponent<Piece>();
					if ((Object)(object)component2 != (Object)null)
					{
						component.m_category = component2.m_category;
						component.m_usage = (UsageTagFlags)(((int)component2.m_usage == 0) ? 1 : ((int)component2.m_usage));
						return;
					}
				}
				if ((int)component.m_usage == 0)
				{
					component.m_usage = (UsageTagFlags)1;
				}
			}
		}

		private sealed class SearchEntry
		{
			public int Page;

			public int Mode;

			public string Section;

			public RectTransform Row;

			public TMP_Text Title;

			public TMP_Text Description;
		}

		private sealed class FoundLine
		{
			public GameObject Row;

			public TMP_Text Title;

			public TMP_Text Where;

			public SearchEntry Entry;
		}

		[HarmonyPatch(typeof(ZCursor), "set_LockState")]
		private static class PointerLockGuard
		{
			[HarmonyPriority(0)]
			private static bool Prefix(ref CursorLockMode value)
			{
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Invalid comparison between Unknown and I4
				if (!OwnsPointer)
				{
					return true;
				}
				if (value)
				{
					instance.preventedCursorLocks++;
				}
				value = (CursorLockMode)0;
				return (int)Cursor.lockState > 0;
			}
		}

		[HarmonyPatch(typeof(ZCursor), "Hide")]
		private static class PointerVisibilityGuard
		{
			private static bool Prefix()
			{
				return !OwnsPointer;
			}
		}

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

		private static int eitrAttackContextDepth;

		private static bool eitrAttackContextSecondary;

		private static Attack eitrActiveAttack;

		private static bool eitrActiveAttackSecondary;

		private EnvMan controlledEnvironment;

		private string savedWeather;

		private float savedTime;

		private float savedWindAngle;

		private float savedWindStrength;

		private bool savedTimeEnabled;

		private bool savedWindEnabled;

		private bool ownedTime;

		private long controlledEnvironmentRevision = -1L;

		private const string ModerateRpc = "DezzyCode.WorldControl.Moderate.v1";

		private const string ModerationRpc = "DezzyCode.WorldControl.Moderation.v1";

		private const int ModerationLimit = 4096;

		private ConfigEntry<string> bannedNames;

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

		private static FieldInfo adminListField;

		private static FieldInfo bannedListField;

		private static MethodInfo kickMethod;

		private static MethodInfo banMethod;

		private static MethodInfo unbanMethod;

		private static MethodInfo sendAdminListMethod;

		private static MethodInfo listAdd;

		private static MethodInfo listRemove;

		private static MethodInfo listGet;

		private static bool moderationReflected;

		private static bool moderationUsable;

		private readonly HashSet<ZDOID> moderationOnline = new HashSet<ZDOID>();

		private readonly HashSet<ZDOID> moderationAdmins = new HashSet<ZDOID>();

		private readonly List<BannedPlayer> moderationBanned = new List<BannedPlayer>();

		private bool moderationKnown;

		private float nextModerationQuery;

		private const float GoWidth = 110f;

		private const float PlayerReductionMin = 0f;

		private const float PlayerReductionMax = 1f;

		private const float PlayerBoostMin = 1f;

		private const float PlayerBoostMax = 5f;

		private const float ConfirmWidth = 560f;

		private const float ConfirmHeight = 240f;

		private GameObject confirmOverlay;

		private TMP_Text confirmTitle;

		private TMP_Text confirmQuestion;

		private TMP_Text confirmYesText;

		private Action confirmed;

		private const int PlayerRulesWireVersion = 1;

		private const string PlayerRulesRequestRpc = "DezzyCode.WorldControl.PlayerRules.Request.v1";

		private const string PlayerRulesStateRpc = "DezzyCode.WorldControl.PlayerRules.State.v1";

		private const float PlayerRuleMin = 0f;

		private const float PlayerRuleMax = 3f;

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

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

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

		private readonly List<ZRpc> playerRulesStale = new List<ZRpc>();

		private ConfigEntry<string> playerRulesStored;

		private bool playerRulesConfigReady;

		private bool playerRulesLoadedForServer;

		private bool playerRulesSynced;

		private bool playerRulesDraftDirty;

		private long playerRulesRevision;

		private float nextPlayerRulesQuery;

		private ZNet playerRulesNetwork;

		private PlayerResourceRules playerRules = PlayerResourceRules.Vanilla;

		private PlayerResourceRules playerRulesDraft = PlayerResourceRules.Vanilla;

		private int playerPageMode = 4;

		private Player playerRulesAppliedPlayer;

		private readonly Dictionary<string, float> playerFieldBaselines = new Dictionary<string, float>();

		private ObjectDB playerRulesObjectDb;

		private long playerRulesAppliedRevision = -1L;

		private readonly Dictionary<Attack, AttackBaseline> attackBaselines = new Dictionary<Attack, AttackBaseline>();

		private readonly Dictionary<Projectile, float> projectileBaselines = new Dictionary<Projectile, float>();

		private readonly Dictionary<SharedData, ShieldBaseline> shieldBaselines = new Dictionary<SharedData, ShieldBaseline>();

		private readonly List<PlayerLine> playerLines = new List<PlayerLine>();

		private readonly List<BannedLine> bannedLines = new List<BannedLine>();

		private Transform playerList;

		private RectTransform onlineHeading;

		private RectTransform bannedHeading;

		private GameObject noneBanned;

		private GameObject oldServer;

		private const float SubTabWidth = 130f;

		private const float SubTabHeight = 38f;

		private const float ValueResetWidth = 230f;

		private const int ValueSteps = 20;

		private readonly List<GameObject>[] valueGroups = new List<GameObject>[4]
		{
			new List<GameObject>(),
			new List<GameObject>(),
			new List<GameObject>(),
			new List<GameObject>()
		};

		private static readonly int[] ValueModes = new int[4] { 4, 1, 2, 3 };

		private static readonly string[] ValueTabKeys = new string[4] { "values.vitals", "values.stamina", "values.eitr", "values.adrenaline" };

		private const int PlayerVitalsWireVersion = 2;

		private const string PlayerVitalsRequestRpc = "DezzyCode.WorldControl.PlayerVitals.Request.v1";

		private const string PlayerVitalsStateRpc = "DezzyCode.WorldControl.PlayerVitals.State.v1";

		private const float VitalMaxMin = 0.1f;

		private const float VitalMaxMax = 3f;

		private const float VitalRegenMin = 0f;

		private const float VitalRegenMax = 3f;

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

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

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

		private readonly List<ZRpc> playerVitalsStale = new List<ZRpc>();

		private ConfigEntry<string> playerVitalsStored;

		private bool playerVitalsConfigReady;

		private bool playerVitalsLoadedForServer;

		private bool playerVitalsSynced;

		private bool playerVitalsDraftDirty;

		private long playerVitalsRevision;

		private long playerVitalsAppliedRevision = -1L;

		private float nextPlayerVitalsQuery;

		private float nextPlayerVitalsMaintenance;

		private ZNet playerVitalsNetwork;

		private PlayerVitalRules playerVitals = PlayerVitalRules.Vanilla;

		private PlayerVitalRules playerVitalsDraft = PlayerVitalRules.Vanilla;

		private Player playerVitalsAppliedPlayer;

		private bool playerVitalsUpdateFoodWarned;

		private static MethodInfo PlayerUpdateFoodMethod;

		private static bool playerUpdateFoodResolved;

		private const float VitalBoostMin = 1f;

		private const float VitalBoostMax = 5f;

		public const string PluginGuid = "dezzycode.valheim.windcontrol";

		private const string RequestRpc = "DezzyCode.WorldControl.Request.v3";

		private const string StateRpc = "DezzyCode.WorldControl.State.v3";

		private const string TeleportRpc = "DezzyCode.WorldControl.Teleport.v1";

		private const string SayRpc = "DezzyCode.WorldControl.Say.v1";

		private static Plugin instance;

		private Harmony harmony;

		private ZNet network;

		private Session session;

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

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

		private readonly List<ZRpc> stale = new List<ZRpc>();

		private readonly Dictionary<ZRpc, ZNetPeer> peersByRpc = new Dictionary<ZRpc, ZNetPeer>();

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

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

		private InitialSync initialSync = new InitialSync();

		private ZRpc serverConnection;

		private bool openWhenSynced;

		private float nextManualQuery;

		private float nextPeerMaintenance;

		private int knownPeerCount = -1;

		private ConfigEntry<KeyCode> toggleKey;

		private ConfigEntry<string> language;

		private readonly ConfigEntry<string>[] presets = new ConfigEntry<string>[3];

		private readonly ConfigEntry<string>[] places = new ConfigEntry<string>[3];

		private ConfigEntry<string> stored;

		private bool recalled;

		private string builtFor = "Auto";

		private bool windowOpen;

		private int blockThroughFrame = -1;

		private string statusKey = "status.checking";

		private Request draft = Protocol.Defaults;

		private static FieldRef<RandEventSystem, RandomEvent> randomEventField;

		private static bool randomEventTried;

		private static FieldRef<WearNTear, bool> rainWetField;

		private static bool rainWetFieldTried;

		private float nextPlayerRulesMaintenance;

		private float nextPlayerVitalsTickOptimized;

		private static int staminaAttackContextDepth;

		private static bool staminaAttackContextSecondary;

		private static Attack staminaActiveAttack;

		private static bool staminaActiveAttackSecondary;

		private ConfigEntry<bool> terrainEnabled;

		private ConfigEntry<float> terrainFlattenSize;

		private ConfigEntry<float> terrainFlattenSmoothness;

		private ConfigEntry<TerrainFlattenShape> terrainFlattenShape;

		private ConfigEntry<TerrainGroundTexture> terrainGroundTexture;

		private ConfigEntry<KeyboardShortcut> terrainFlattenHold;

		private ConfigEntry<bool> terrainGridMovement;

		private ConfigEntry<bool> terrainToolRadiusEnabled;

		private ConfigEntry<float> terrainHoeRadius;

		private ConfigEntry<float> terrainCultivatorRadius;

		private ConfigEntry<KeyboardShortcut> terrainRadiusIncrease;

		private ConfigEntry<KeyboardShortcut> terrainRadiusDecrease;

		private ConfigEntry<float> terrainRampThickness;

		private ConfigEntry<float> terrainRevertRadius;

		private bool terrainHolding;

		private Vector3 terrainLastCenter = new Vector3(100000f, 100000f, 100000f);

		private float terrainLastSize = -1f;

		private float terrainLastSmooth = -1f;

		private float terrainLastApply = -10f;

		private TerrainFlattenShape terrainLastShape;

		private TerrainGroundTexture terrainLastTexture;

		private bool terrainBackendWarned;

		private GameObject terrainPreviewRoot;

		private LineRenderer flattenPreview;

		private LineRenderer radiusPreview;

		private LineRenderer rampOutlinePreview;

		private LineRenderer rampCenterPreview;

		private LineRenderer revertPreview;

		private Material flattenPreviewMaterial;

		private Material radiusPreviewMaterial;

		private Material rampPreviewMaterial;

		private Material revertPreviewMaterial;

		private PieceTable terrainHoeTable;

		private GameObject terrainRampPrefab;

		private GameObject terrainRevertPrefab;

		private Player terrainPiecesTaughtTo;

		private static FieldRef<Player, HashSet<string>> terrainKnownRecipes;

		private static bool terrainKnownRecipesTried;

		private Texture2D terrainRampIconTexture;

		private Texture2D terrainRevertIconTexture;

		private Sprite terrainRampIcon;

		private Sprite terrainRevertIcon;

		private static MethodInfo terrainUpdatePiecesMethod;

		private static FieldInfo terrainHmapField;

		private static FieldInfo terrainLevelDeltaField;

		private static FieldInfo terrainSmoothDeltaField;

		private static FieldInfo terrainModifiedHeightField;

		private static FieldInfo terrainPaintMaskField;

		private static FieldInfo terrainModifiedPaintField;

		private static FieldInfo terrainNviewField;

		private static MethodInfo terrainSaveMethod;

		private static PlacementRadiusScope terrainActiveRadiusScope;

		private static readonly RaycastHit[] TerrainRaycastBuffer = (RaycastHit[])(object)new RaycastHit[256];

		private static readonly HashSet<TerrainComp> TerrainCompilerBuffer = new HashSet<TerrainComp>();

		private static readonly object[] TerrainSaveArguments = new object[1] { false };

		private static bool terrainFastAccessTried;

		private static FieldRef<TerrainComp, Heightmap> terrainHmapFastRef;

		private static FieldRef<TerrainComp, float[]> terrainLevelDeltaFastRef;

		private static FieldRef<TerrainComp, float[]> terrainSmoothDeltaFastRef;

		private static FieldRef<TerrainComp, bool[]> terrainModifiedHeightFastRef;

		private static FieldRef<TerrainComp, Color[]> terrainPaintMaskFastRef;

		private static FieldRef<TerrainComp, bool[]> terrainModifiedPaintFastRef;

		private static FieldRef<TerrainComp, ZNetView> terrainNviewFastRef;

		private static Action<TerrainComp, bool> terrainSaveFast;

		private float terrainNextPreviewUpdate;

		private float terrainNextPieceCheck;

		private bool terrainPieceTextReady;

		private int terrainPieceTextVersion = -1;

		private const float CompassSize = 280f;

		private const float CompassRing = 104f;

		private const float CompassLabels = 127f;

		private static Sprite compassRing;

		private static Sprite compassDot;

		private static readonly string[] CompassKeys = new string[8] { "wind.n", "wind.ne", "wind.e", "wind.se", "wind.s", "wind.sw", "wind.w", "wind.nw" };

		internal const float PanelWidth = 1020f;

		internal const float PanelHeight = 810f;

		private const float SidebarLeft = 18f;

		private const float SidebarWidth = 196f;

		private const float TabStep = 48f;

		private const float TabHeight = 44f;

		private const float ContentLeft = 228f;

		private const float ContentTop = 118f;

		private const float ContentBottom = 86f;

		private const float RowHeight = 48f;

		private const float ControlMargin = 16f;

		private const float ControlGap = 8f;

		private const float ButtonHeight = 34f;

		private const float SliderWidth = 250f;

		private const float ValueWidth = 76f;

		private const float RowWidth = 754f;

		private static readonly Color TextWhite = Color.white;

		private static readonly Color TextQuiet = new Color(0.68f, 0.66f, 0.6f);

		private static readonly Color TextHint = new Color(0.84f, 0.78f, 0.6f);

		private static readonly Color TextIdle = new Color(0.85f, 0.83f, 0.78f);

		private static readonly Color StripeLight = new Color(1f, 1f, 1f, 0.035f);

		private static readonly Color StripeDark = new Color(0f, 0f, 0f, 0.12f);

		private Transform rowList;

		private int rowIndex;

		private const float PixelsPerNotch = 75f;

		private const float FallbackSensitivity = 1500f;

		private readonly List<ScrollRect> scrollViews = new List<ScrollRect>();

		private static Type scrollModuleType;

		private static PropertyInfo scrollDeltaPerTick;

		private const int MostFound = 40;

		private readonly List<SearchEntry> searchIndex = new List<SearchEntry>();

		private readonly List<FoundLine> foundLines = new List<FoundLine>();

		private readonly List<SearchEntry> found = new List<SearchEntry>();

		private TMP_InputField searchField;

		private string searchQuery = "";

		private Transform foundList;

		private TMP_Text foundNone;

		private bool allPagesBuilt;

		private int buildingPage = -1;

		private int buildingMode = -1;

		private string buildingSection = "";

		private RectTransform scrollTarget;

		private Image fadeImage;

		private Color fadeColour;

		private float fadeUntil;

		private const string LogoFile = "WorldControl_logo.png";

		private const float LogoTop = 10f;

		private const float LogoHeight = 76f;

		private const float LogoMostWidth = 380f;

		private static Sprite logo;

		private static bool logoMissing;

		private bool statusOneLine;

		private static TMP_FontAsset sansFont;

		private static TMP_FontAsset serifFont;

		private static Material sansEdged;

		private static Material serifEdged;

		private static TextMeshProUGUI measureText;

		private const int PageOverview = 0;

		private const int PageTime = 1;

		private const int PageWeather = 2;

		private const int PageWind = 3;

		private const int PageEvents = 4;

		private const int PagePresets = 5;

		private const int PagePlayers = 6;

		private const int PagePlaces = 7;

		private const int PageSay = 8;

		private const int PagePlayerValues = 9;

		private const int PageTerrain = 10;

		private const int PageSearch = 11;

		private const int PageCount = 12;

		private static readonly string[] TabKeys = new string[11]
		{
			"tab.overview", "tab.time", "tab.weather", "tab.wind", "tab.events", "tab.presets", "tab.players", "tab.places", "tab.say", "tab.values",
			"tab.terrain"
		};

		private const float SearchHeight = 32f;

		private const float SearchGap = 8f;

		private const float SearchWidth = 260f;

		private const float ListTop = 158f;

		private const float PageHeight = 566f;

		private GameObject panel;

		private readonly GameObject[] pages = (GameObject[])(object)new GameObject[12];

		private readonly bool[] pageBuilt = new bool[12];

		private readonly Button[] tabButtons = (Button[])(object)new Button[12];

		private TMP_InputField _message;

		private TMP_InputField _placeName;

		private readonly List<TMP_InputField> typingFields = new List<TMP_InputField>();

		private static List<string> eventNames;

		private readonly List<Action> frameRefresh = new List<Action>();

		private readonly List<Action>[] pageRefresh = NewPageRefresh();

		private List<Action> refresh;

		private TMP_Text clockText;

		private TMP_Text worldClockText;

		private TMP_Text statusText;

		private Button applyButton;

		private Button resetButton;

		private bool uiInputBlocked;

		private bool controlsDirty;

		private int preventedCursorLocks;

		private int recoveredCursorLocks;

		private int tab;

		private float nextUiRequest;

		private float nextUiRefresh;

		private static readonly Dictionary<string, string> EventTitles = new Dictionary<string, string>();

		private static readonly Biome[] SingleBiomes;

		private static readonly List<PlayerInfo> PlayerBuffer;

		private static int playersCachedFrame;

		private static readonly CultureInfo Culture;

		private bool HasState
		{
			get
			{
				if (session == null || !session.Synced || (Object)(object)network == (Object)null)
				{
					return false;
				}
				if (session.Server)
				{
					return true;
				}
				ZNetPeer serverPeer = network.GetServerPeer();
				if (serverPeer != null && serverConnection != null && serverPeer.m_rpc == serverConnection)
				{
					return serverConnection.IsConnected();
				}
				return false;
			}
		}

		private bool CanEdit
		{
			get
			{
				if (HasState)
				{
					if (!session.Server)
					{
						return session.State.CanEdit;
					}
					return true;
				}
				return false;
			}
		}

		private static Color Orange => GUIManager.Instance.ValheimOrange;

		private static Color Beige => GUIManager.Instance.ValheimBeige;

		private bool Searching => searchQuery.Length > 0;

		private int Shown
		{
			get
			{
				if (!Searching)
				{
					return tab;
				}
				return 11;
			}
		}

		private static TMP_FontAsset Sans
		{
			get
			{
				if ((Object)(object)sansFont == (Object)null)
				{
					sansFont = GUIManager.Instance.TMP_AveriaSansLibre;
				}
				if ((Object)(object)sansFont == (Object)null)
				{
					sansFont = Cache.GetPrefab<TMP_FontAsset>("Valheim-AveriaSansLibre");
				}
				return sansFont;
			}
		}

		private static TMP_FontAsset Serif
		{
			get
			{
				if ((Object)(object)serifFont == (Object)null)
				{
					serifFont = Cache.GetPrefab<TMP_FontAsset>("Valheim-AveriaSerifLibre");
				}
				if (!((Object)(object)serifFont != (Object)null))
				{
					return Sans;
				}
				return serifFont;
			}
		}

		private static bool BlockInput
		{
			get
			{
				if ((Object)(object)instance != (Object)null)
				{
					if (!instance.windowOpen)
					{
						return Time.frameCount <= instance.blockThroughFrame;
					}
					return true;
				}
				return false;
			}
		}

		private static bool OwnsPointer
		{
			get
			{
				if ((Object)(object)instance != (Object)null && instance.windowOpen)
				{
					return Application.isFocused;
				}
				return false;
			}
		}

		private static bool CanScaleLocalEitr(Character character)
		{
			Plugin plugin = instance;
			if ((Object)(object)plugin != (Object)null && plugin.playerRulesSynced && (Object)(object)character != (Object)null)
			{
				return (object)character == Player.m_localPlayer;
			}
			return false;
		}

		private static EitrReloadCostState ScaleReloadEitrTemporarily(Player player, ItemData weapon)
		{
			EitrReloadCostState result = default(EitrReloadCostState);
			if (!CanScaleLocalEitr((Character)(object)player) || weapon == null || weapon.m_shared == null || weapon.m_shared.m_attack == null)
			{
				return result;
			}
			float reloadEitr = instance.playerRules.ReloadEitr;
			if (reloadEitr == 1f)
			{
				return result;
			}
			Attack val = (result.Attack = weapon.m_shared.m_attack);
			result.Value = val.m_reloadEitrDrain;
			result.Changed = true;
			val.m_reloadEitrDrain = result.Value * reloadEitr;
			return result;
		}

		private static void RestoreReloadEitr(ref EitrReloadCostState state)
		{
			if (state.Changed)
			{
				if (state.Attack != null)
				{
					state.Attack.m_reloadEitrDrain = state.Value;
				}
				state.Changed = false;
			}
		}

		private static EitrRepairCostState ScaleRepairEitrTemporarily(Player player, ItemData tool)
		{
			EitrRepairCostState result = default(EitrRepairCostState);
			if (!CanScaleLocalEitr((Character)(object)player) || tool == null || tool.m_shared == null || tool.m_shared.m_attack == null)
			{
				return result;
			}
			float primaryEitr = instance.playerRules.PrimaryEitr;
			if (primaryEitr == 1f)
			{
				return result;
			}
			Attack val = (result.Attack = tool.m_shared.m_attack);
			result.Value = val.m_attackEitr;
			result.Changed = true;
			val.m_attackEitr = result.Value * primaryEitr;
			return result;
		}

		private static void RestoreRepairEitr(ref EitrRepairCostState state)
		{
			if (state.Changed)
			{
				if (state.Attack != null)
				{
					state.Attack.m_attackEitr = state.Value;
				}
				state.Changed = false;
			}
		}

		private static void RestoreEitrAttackContext(ref EitrAttackContextState state)
		{
			if (state.Changed)
			{
				eitrAttackContextDepth = state.Depth;
				eitrAttackContextSecondary = state.Secondary;
				state.Changed = false;
			}
		}

		private static void RestoreRegenTick(Player player, ref RegenTickState state)
		{
			if (state.Changed)
			{
				if ((Object)(object)player != (Object)null)
				{
					player.m_staminaRegen = state.Stamina;
					player.m_eiterRegen = state.Eitr;
				}
				state.Changed = false;
			}
		}

		private void RestoreEnvironment()
		{
			if ((Object)(object)controlledEnvironment != (Object)null)
			{
				controlledEnvironment.m_debugEnv = savedWeather;
				controlledEnvironment.m_debugTimeOfDay = savedTimeEnabled;
				controlledEnvironment.m_debugTime = savedTime;
				if (savedWindEnabled)
				{
					controlledEnvironment.SetDebugWind(savedWindAngle, savedWindStrength);
				}
				else
				{
					controlledEnvironment.ResetDebugWind();
				}
			}
			controlledEnvironment = null;
			ownedTime = false;
			controlledEnvironmentRevision = -1L;
		}

		private void BindModerationConfig()
		{
			bannedNames = ((BaseUnityPlugin)this).Config.Bind<string>("Server - Moderation", "Banned names", "", "Written by the World Control server: the names of players it banned, id|name;id|name. The ban itself is in the game's bannedlist.txt.");
		}

		private bool ReflectModeration()
		{
			if (moderationReflected)
			{
				return moderationUsable;
			}
			moderationReflected = true;
			try
			{
				adminListField = AccessTools.Field(typeof(ZNet), "m_adminList");
				bannedListField = AccessTools.Field(typeof(ZNet), "m_bannedList");
				kickMethod = AccessTools.Method(typeof(ZNet), "InternalKick", new Type[1] { typeof(ZNetPeer) }, (Type[])null);
				banMethod = AccessTools.Method(typeof(ZNet), "InternalBan", new Type[2]
				{
					typeof(ZRpc),
					typeof(string)
				}, (Type[])null);
				unbanMethod = AccessTools.Method(typeof(ZNet), "InternalUnban", new Type[2]
				{
					typeof(ZRpc),
					typeof(string)
				}, (Type[])null);
				sendAdminListMethod = AccessTools.Method(typeof(ZNet), "SendAdminList", (Type[])null, (Type[])null);
				Type type = ((adminListField != null) ? adminListField.FieldType : null);
				listAdd = ((type != null) ? AccessTools.Method(type, "Add", new Type[1] { typeof(string) }, (Type[])null) : null);
				listRemove = ((type != null) ? AccessTools.Method(type, "Remove", new Type[1] { typeof(string) }, (Type[])null) : null);
				listGet = ((type != null) ? AccessTools.Method(type, "GetList", (Type[])null, (Type[])null) : null);
				moderationUsable = adminListField != null && bannedListField != null && kickMethod != null && banMethod != null && unbanMethod != null && listAdd != null && listRemove != null && listGet != null;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Moderation is not available: " + ex.Message));
				moderationUsable = false;
			}
			if (!moderationUsable)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Moderation is not available: this game version lacks a kick, ban or admin list member it needs.");
			}
			return moderationUsable;
		}

		private List<string> GameList(FieldInfo field)
		{
			object value = field.GetValue(network);
			if (value == null)
			{
				return null;
			}
			return listGet.Invoke(value, null) as List<string>;
		}

		private void OnModerate(ZRpc rpc, ZPackage package)
		{
			ZNetPeer val = ReadyPeer(rpc);
			if (session == null || !session.Server || val == null || package == null || package.Size() > 256)
			{
				return;
			}
			ModerationKind moderationKind;
			long user;
			uint id;
			string text;
			try
			{
				moderationKind = (ModerationKind)package.ReadByte();
				user = package.ReadLong();
				id = package.ReadUInt();
				text = package.ReadString();
			}
			catch (Exception)
			{
				return;
			}
			if (text == null || text.Length > 96 || (moderationEdits.TryGetValue(rpc, out var value) && Time.unscaledTime < value))
			{
				return;
			}
			moderationEdits[rpc] = Time.unscaledTime + 0.4f;
			if (IsAdmin(rpc))
			{
				if (moderationKind != ModerationKind.Query)
				{
					Moderate(moderationKind, user, id, text, val);
				}
				SendModeration(rpc);
			}
		}

		private void Moderate(ModerationKind kind, long user, uint id, string target, ZNetPeer asker)
		{
			if (!ReflectModeration())
			{
				return;
			}
			string text = ((asker != null) ? asker.m_playerName : (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "host"));
			if (kind == ModerationKind.Unban)
			{
				if (!string.IsNullOrEmpty(target))
				{
					unbanMethod.Invoke(network, new object[2] { null, target });
					ForgetBannedName(target);
					((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " unbanned " + target + "."));
					BroadcastModeration();
				}
				return;
			}
			ZNetPeer val = PeerFor(user, id);
			if (val == null || val.m_rpc == null || (asker != null && val == asker))
			{
				return;
			}
			string hostName = val.m_rpc.GetSocket().GetHostName();
			if (string.IsNullOrEmpty(hostName))
			{
				return;
			}
			switch (kind)
			{
			case ModerationKind.Kick:
				kickMethod.Invoke(network, new object[1] { val });
				((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " kicked " + val.m_playerName + "."));
				break;
			case ModerationKind.Ban:
				banMethod.Invoke(network, new object[2] { null, hostName });
				RememberBannedName(hostName, val.m_playerName);
				kickMethod.Invoke(network, new object[1] { val });
				((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " banned " + val.m_playerName + " (" + hostName + ")."));
				break;
			case ModerationKind.MakeAdmin:
				listAdd.Invoke(adminListField.GetValue(network), new object[1] { hostName });
				AdminListChanged(val);
				((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " made " + val.m_playerName + " an admin."));
				break;
			case ModerationKind.RemoveAdmin:
			{
				object value = adminListField.GetValue(network);
				foreach (string item in new List<string>(GameList(adminListField) ?? new List<string>()))
				{
					if (SameId(item, hostName))
					{
						listRemove.Invoke(value, new object[1] { item });
					}
				}
				AdminListChanged(val);
				((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " removed the admin rights of " + val.m_playerName + "."));
				break;
			}
			}
			BroadcastModeration();
		}

		private static bool SameId(string entry, string host)
		{
			if (string.IsNullOrEmpty(entry))
			{
				return false;
			}
			if (!(entry == host) && !entry.EndsWith("_" + host, StringComparison.Ordinal))
			{
				return host.EndsWith("_" + entry, StringComparison.Ordinal);
			}
			return true;
		}

		private void AdminListChanged(ZNetPeer peer)
		{
			try
			{
				sendAdminListMethod?.Invoke(network, null);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Cannot send the admin list: " + ex.GetBaseException().Message));
			}
			if (peer != null && peer.m_rpc != null && peer.m_rpc.IsConnected() && participants.Contains(peer.m_rpc))
			{
				SendState(peer.m_rpc);
				SendModeration(peer.m_rpc);
			}
		}

		private void RememberBannedName(string id, string name)
		{
			Dictionary<string, string> dictionary = BannedNames();
			dictionary[id] = (name ?? "").Replace("|", " ").Replace(";", " ");
			SaveBannedNames(dictionary);
		}

		private void ForgetBannedName(string id)
		{
			Dictionary<string, string> dictionary = BannedNames();
			if (dictionary.Remove(id))
			{
				SaveBannedNames(dictionary);
			}
		}

		private Dictionary<string, string> BannedNames()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			if (bannedNames == null || string.IsNullOrEmpty(bannedNames.Value))
			{
				return dictionary;
			}
			string[] array = bannedNames.Value.Split(new char[1] { ';' });
			foreach (string text in array)
			{
				int num = text.IndexOf('|');
				if (num > 0)
				{
					dictionary[text.Substring(0, num)] = text.Substring(num + 1);
				}
			}
			return dictionary;
		}

		private void SaveBannedNames(Dictionary<string, string> names)
		{
			if (bannedNames == null)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, string> name in names)
			{
				list.Add(name.Key + "|" + name.Value);
			}
			bannedNames.Value = string.Join(";", list.ToArray());
		}

		private ZPackage ModerationPackage(ZRpc to)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			List<ZNetPeer> peers = network.GetPeers();
			List<ZNetPeer> list = new List<ZNetPeer>();
			foreach (ZNetPeer item in peers)
			{
				if (item != null && item.IsReady() && item.m_rpc != null)
				{
					list.Add(item);
				}
			}
			val.Write(list.Count);
			foreach (ZNetPeer item2 in list)
			{
				val.Write(((ZDOID)(ref item2.m_characterID)).UserID);
				val.Write(((ZDOID)(ref item2.m_characterID)).ID);
				val.Write(network.IsAdmin(item2.m_rpc.GetSocket().GetHostName()));
			}
			List<string> list2 = GameList(bannedListField) ?? new List<string>();
			Dictionary<string, string> dictionary = BannedNames();
			int num = Mathf.Min(list2.Count, 100);
			val.Write(num);
			for (int i = 0; i < num; i++)
			{
				string text = list2[i] ?? "";
				val.Write(text);
				val.Write(dictionary.TryGetValue(text, out var value) ? value : "");
			}
			return val;
		}

		private void SendModeration(ZRpc rpc)
		{
			if (session != null && session.Server && rpc != null && rpc.IsConnected() && ReflectModeration())
			{
				ZPackage val = ModerationPackage(rpc);
				if (val.Size() <= 4096)
				{
					rpc.Invoke("DezzyCode.WorldControl.Moderation.v1", new object[1] { val });
				}
			}
		}

		private void BroadcastModeration()
		{
			if (session == null || !session.Server)
			{
				return;
			}
			foreach (ZNetPeer peer in network.GetPeers())
			{
				if (peer != null && peer.IsReady() && peer.m_rpc != null && peer.m_rpc.IsConnected() && participants.Contains(peer.m_rpc) && IsAdmin(peer.m_rpc))
				{
					SendModeration(peer.m_rpc);
				}
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null && ReflectModeration())
			{
				ReadModeration(ModerationPackage(null));
			}
		}

		private void OnModeration(ZRpc rpc, ZPackage package)
		{
			if (session == null || session.Server || package == null || package.Size() > 4096 || (Object)(object)network == (Object)null)
			{
				return;
			}
			ZNetPeer serverPeer = network.GetServerPeer();
			if (serverPeer == null || serverPeer.m_rpc != rpc)
			{
				return;
			}
			try
			{
				ReadModeration(package);
			}
			catch (Exception)
			{
			}
		}

		private void ReadModeration(ZPackage package)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			package.SetPos(0);
			int num = package.ReadInt();
			if (num < 0 || num > 256)
			{
				return;
			}
			moderationOnline.Clear();
			moderationAdmins.Clear();
			ZDOID item = default(ZDOID);
			for (int i = 0; i < num; i++)
			{
				((ZDOID)(ref item))..ctor(package.ReadLong(), package.ReadUInt());
				bool num2 = package.ReadBool();
				moderationOnline.Add(item);
				if (num2)
				{
					moderationAdmins.Add(item);
				}
			}
			int num3 = package.ReadInt();
			if (num3 >= 0 && num3 <= 100)
			{
				moderationBanned.Clear();
				for (int j = 0; j < num3; j++)
				{
					moderationBanned.Add(new BannedPlayer
					{
						Id = package.ReadString(),
						Name = package.ReadString()
					});
				}
				moderationKnown = true;
				controlsDirty = true;
			}
		}

		private void QueryModeration()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (session == null || Time.unscaledTime < nextModerationQuery)
			{
				return;
			}
			nextModerationQuery = Time.unscaledTime + 3f;
			if (session.Server)
			{
				if (ReflectModeration())
				{
					ReadModeration(ModerationPackage(null));
				}
			}
			else
			{
				SendModerate(ModerationKind.Query, ZDOID.None, "");
			}
		}

		private void SendModerate(ModerationKind kind, ZDOID target, string id)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			if (!CanEdit)
			{
				return;
			}
			if (session.Server)
			{
				Moderate(kind, ((ZDOID)(ref target)).UserID, ((ZDOID)(ref target)).ID, id, null);
				return;
			}
			ZNetPeer serverPeer = network.GetServerPeer();
			if (serverPeer != null && serverPeer.IsReady() && serverPeer.m_rpc != null && serverPeer.m_rpc.IsConnected())
			{
				ZPackage val = new ZPackage();
				val.Write((byte)kind);
				val.Write(((ZDOID)(ref target)).UserID);
				val.Write(((ZDOID)(ref target)).ID);
				val.Write(id ?? "");
				serverPeer.m_rpc.Invoke("DezzyCode.WorldControl.Moderate.v1", new object[1] { val });
			}
		}

		private void ResetModeration()
		{
			moderationOnline.Clear();
			moderationAdmins.Clear();
			moderationBanned.Clear();
			moderationKnown = false;
			nextModerationQuery = 0f;
			moderationEdits.Clear();
		}

		private void BuildOverview(Transform list)
		{
			Hint(Words.T("overview.hint"));
			Section(Words.T("section.server"));
			OverviewRow("overview.time", 1, delegate
			{
				Request settings = session.State.Settings;
				return (settings.TimeMode != 1) ? Words.T("time.natural") : Words.T("overview.time.held", UiOptions.Clock(settings.Hour / 24f));
			});
			OverviewRow("overview.weather", 2, () => UiOptions.WeatherName(session.State.Settings.Weather));
			OverviewRow("overview.wind", 3, delegate
			{
				Request settings = session.State.Settings;
				return (!settings.WindOn) ? Words.T("wind.natural") : Words.T("presets.wind", CompassName(WindFrom(settings.Angle)), (settings.Strength * 100f).ToString("0"));
			});
			OverviewRow("overview.rain", 2, () => Words.T(session.State.Settings.NoRainDamage ? "switch.off" : "switch.on"));
			OverviewRow("overview.event", 4, delegate
			{
				RandomEvent val = Running();
				string text = ((val != null && !string.IsNullOrEmpty(val.m_name)) ? Words.T("events.running", Told(val.m_name) + "  " + UiOptions.Countdown(val.m_duration - val.m_time)) : Words.T("events.none"));
				return (!session.State.Settings.EventsPaused) ? text : (text + "   ·   " + Words.T("overview.events.paused"));
			});
			OverviewRow("overview.players", 6, delegate
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				List<PlayerInfo> list2 = Players();
				List<string> list3 = new List<string>();
				for (int i = 0; i < list2.Count && i < 6; i++)
				{
					list3.Add(list2[i].m_name);
				}
				string text = string.Join(", ", list3.ToArray()) + ((list2.Count > 6) ? ", …" : "");
				return Words.T("players.count", list2.Count.ToString()) + ((list2.Count > 0) ? ("   ·   " + text) : "");
			});
			OverviewRow("overview.values", 9, () => Words.T((playerRulesSynced && playerVitalsSynced) ? ((playerRules.Equals(PlayerResourceRules.Vanilla) && playerVitals.Equals(PlayerVitalRules.Vanilla)) ? "overview.values.vanilla" : "overview.values.changed") : "values.status.waiting"));
			TMP_Text titleText;
			TMP_Text pendingText;
			RectTransform row = Row(Words.T("overview.pending"), "", Total(new float[1] { 230f }), out titleText, out pendingText);
			Button apply = RowButtons(row, new float[1] { 230f }, new string[1] { Words.T("btn.apply") }, new Action[1]
			{
				delegate
				{
					Submit(ActionKind.All);
					SubmitAllPlayerDrafts();
				}
			})[0];
			refresh.Add(delegate
			{
				//IL_0041: 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)
				string text = PendingChanges();
				pendingText.text = (string.IsNullOrEmpty(text) ? Words.T("overview.pending.none") : text);
				((Graphic)pendingText).color = (string.IsNullOrEmpty(text) ? TextQuiet : Orange);
				((Selectable)apply).interactable = CanAct() && !string.IsNullOrEmpty(text);
			});
			Section(Words.T("section.local"));
			OverviewRow("overview.terrain", 10, () => Words.T((terrainEnabled != null && terrainEnabled.Value) ? "switch.on" : "switch.off"));
			OverviewRow("overview.places", 7, delegate
			{
				int num = 0;
				for (int i = 0; i < places.Length; i++)
				{
					if (Stored(i, out var _))
					{
						num++;
					}
				}
				return Words.T("overview.places.count", num.ToString(), places.Length.ToString());
			});
		}

		private void OverviewRow(string key, int page, Func<string> now)
		{
			TMP_Text titleText;
			TMP_Text text;
			RectTransform row = Row(Words.T(key), "", 110f, out titleText, out text);
			RowButtons(row, new float[1] { 110f }, new string[1] { Words.T("overview.go") }, new Action[1]
			{
				delegate
				{
					EndSearch();
					tab = page;
				}
			});
			refresh.Add(delegate
			{
				text.text = now();
			});
		}

		private string PendingChanges()
		{
			Request settings = session.State.Settings;
			List<string> list = new List<string>();
			if (draft.TimeMode != settings.TimeMode || (draft.TimeMode != 0 && !Mathf.Approximately(draft.Hour, settings.Hour)))
			{
				list.Add(Words.T("tab.time"));
			}
			if ((draft.Weather ?? "") != (settings.Weather ?? "") || draft.NoRainDamage != settings.NoRainDamage)
			{
				list.Add(Words.T("tab.weather"));
			}
			if (draft.WindOn != settings.WindOn || (draft.WindOn && (!Mathf.Approximately(draft.Angle, settings.Angle) || !Mathf.Approximately(draft.Strength, settings.Strength))))
			{
				list.Add(Words.T("tab.wind"));
			}
			if (draft.EventsPaused != settings.EventsPaused)
			{
				list.Add(Words.T("tab.events"));
			}
			if (playerRulesDraftDirty || playerVitalsDraftDirty)
			{
				list.Add(Words.T("tab.values"));
			}
			if (list.Count != 0)
			{
				return Words.T("overview.pending.some", string.Join(", ", list.ToArray()));
			}
			return "";
		}

		private static bool InRange(float value, float min, float max)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value) && value >= min)
			{
				return value <= max;
			}
			return false;
		}

		private static bool BuffOnlyPlayerRules(PlayerResourceRules r)
		{
			if (!InRange(r.Run, 0f, 1f) || !InRange(r.Jump, 0f, 1f) || !InRange(r.Dodge, 0f, 1f) || !InRange(r.Swim, 0f, 1f) || !InRange(r.Sneak, 0f, 1f) || !InRange(r.Encumbered, 0f, 1f) || !InRange(r.Block, 0f, 1f) || !InRange(r.Grapple, 0f, 1f) || !InRange(r.PrimaryStamina, 0f, 1f) || !InRange(r.SecondaryStamina, 0f, 1f) || !InRange(r.DrawStamina, 0f, 1f) || !InRange(r.ReloadStamina, 0f, 1f) || !InRange(r.HomeStamina, 0f, 1f) || !InRange(r.PrimaryEitr, 0f, 1f) || !InRange(r.SecondaryEitr, 0f, 1f) || !InRange(r.DrawEitr, 0f, 1f) || !InRange(r.ReloadEitr, 0f, 1f))
			{
				return false;
			}
			if (!InRange(r.PrimaryAdrenaline, 1f, 5f) || !InRange(r.SecondaryAdrenaline, 1f, 5f) || !InRange(r.ProjectileAdrenaline, 1f, 5f) || !InRange(r.BlockAdrenaline, 1f, 5f) || !InRange(r.ParryAdrenaline, 1f, 5f) || !InRange(r.PerfectDodgeAdrenaline, 1f, 5f) || !InRange(r.StaggerAdrenaline, 1f, 5f) || !InRange(r.GuardianAdrenaline, 1f, 5f))
			{
				return false;
			}
			if (InRange(r.MissAdrenaline, 0f, 1f))
			{
				return InRange(r.DamageAdrenaline, 0f, 1f);
			}
			return false;
		}

		private void ShowPlayerResetConfirmation()
		{
			Confirm("values.confirm.title", "values.confirm.question", "values.confirm.yes", ResetAllPlayerDrafts);
		}

		private void ShowWorldResetConfirmation()
		{
			Confirm("reset.confirm.title", "reset.confirm.question", "reset.confirm.yes", delegate
			{
				Submit(ActionKind.Reset);
			});
		}

		private void Confirm(string titleKey, string questionKey, string yesKey, Action yes)
		{
			ConfirmText(Words.T(titleKey), Words.T(questionKey), Words.T(yesKey), yes);
		}

		private void ConfirmText(string title, string question, string yesText, Action yes)
		{
			if (!((Object)(object)panel == (Object)null))
			{
				if ((Object)(object)confirmOverlay == (Object)null)
				{
					BuildConfirmation();
					BetrValheim.Dress(confirmOverlay);
				}
				confirmTitle.text = title;
				confirmQuestion.text = question;
				if ((Object)(object)confirmYesText != (Object)null)
				{
					confirmYesText.text = yesText;
				}
				confirmed = yes;
				confirmOverlay.transform.SetAsLastSibling();
				confirmOverlay.SetActive(true);
			}
		}

		private void BuildConfirmation()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Confirmation", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(panel.transform, false);
			val.layer = 5;
			Place(val, 0f, 0f, 0f, 810f);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(0f, 0f, 0f, 0.58f);
			((Graphic)component).raycastTarget = true;
			GameObject val2 = GUIManager.Instance.CreateWoodpanel(val.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 560f, 240f, false);
			((Object)val2).name = "ConfirmationBox";
			confirmTitle = Txt("", val2.transform, 22, bold: true, Orange);
			Place(((Component)confirmTitle).gameObject, 28f, 28f, 22f, 56f);
			confirmQuestion = Txt("", val2.transform, 15, bold: false, TextWhite);
			confirmQuestion.alignment = (TextAlignmentOptions)257;
			Place(((Component)confirmQuestion).gameObject, 28f, 28f, 64f, 168f);
			float num = 244f;
			Button val3 = NewButton(val2.transform, "", num, 40f, delegate
			{
				Action action = confirmed;
				HideConfirmation();
				action?.Invoke();
			});
			Place(((Component)val3).gameObject, 28f, 532f - num, 178f, 218f);
			confirmYesText = ((Component)val3).GetComponentInChildren<TMP_Text>();
			Place(((Component)NewButton(val2.transform, Words.T("values.confirm.cancel"), num, 40f, HideConfirmation)).gameObject, 532f - num, 28f, 178f, 218f);
			confirmOverlay = val;
			val.SetActive(false);
		}

		private void HideConfirmation()
		{
			confirmed = null;
			if ((Object)(object)confirmOverlay != (Object)null)
			{
				confirmOverlay.SetActive(false);
			}
		}

		private void EnsurePlayerRulesConfig()
		{
			if (!playerRulesConfigReady)
			{
				playerRulesConfigReady = true;
				playerRulesStored = ((BaseUnityPlugin)this).Config.Bind<string>("Server - Player Rules", "State", "", "Written by the World Control server. Server-authoritative stamina, eitr and adrenaline multipliers.");
			}
		}

		private static bool PlayerRule(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value) && value >= 0f)
			{
				return value <= 3f;
			}
			return false;
		}

		private static bool ValidPlayerRules(PlayerResourceRules r)
		{
			if (PlayerRule(r.Run) && PlayerRule(r.Jump) && PlayerRule(r.Dodge) && PlayerRule(r.Swim) && PlayerRule(r.Sneak) && PlayerRule(r.Encumbered) && PlayerRule(r.Block) && PlayerRule(r.Grapple) && PlayerRule(r.PrimaryStamina) && PlayerRule(r.SecondaryStamina) && PlayerRule(r.DrawStamina) && PlayerRule(r.ReloadStamina) && PlayerRule(r.HomeStamina) && PlayerRule(r.PrimaryEitr) && PlayerRule(r.SecondaryEitr) && PlayerRule(r.DrawEitr) && PlayerRule(r.ReloadEitr) && PlayerRule(r.PrimaryAdrenaline) && PlayerRule(r.SecondaryAdrenaline) && PlayerRule(r.ProjectileAdrenaline) && PlayerRule(r.BlockAdrenaline) && PlayerRule(r.ParryAdrenaline) && PlayerRule(r.PerfectDodgeAdrenaline) && PlayerRule(r.StaggerAdrenaline) && PlayerRule(r.MissAdrenaline) && PlayerRule(r.DamageAdrenaline))
			{
				return PlayerRule(r.GuardianAdrenaline);
			}
			return false;
		}

		private static void WritePlayerRules(BinaryWriter w, PlayerResourceRules r)
		{
			w.Write(r.Run);
			w.Write(r.Jump);
			w.Write(r.Dodge);
			w.Write(r.Swim);
			w.Write(r.Sneak);
			w.Write(r.Encumbered);
			w.Write(r.Block);
			w.Write(r.Grapple);
			w.Write(r.PrimaryStamina);
			w.Write(r.SecondaryStamina);
			w.Write(r.DrawStamina);
			w.Write(r.ReloadStamina);
			w.Write(r.HomeStamina);
			w.Write(r.PrimaryEitr);
			w.Write(r.SecondaryEitr);
			w.Write(r.DrawEitr);
			w.Write(r.ReloadEitr);
			w.Write(r.PrimaryAdrenaline);
			w.Write(r.SecondaryAdrenaline);
			w.Write(r.ProjectileAdrenaline);
			w.Write(r.BlockAdrenaline);
			w.Write(r.ParryAdrenaline);
			w.Write(r.PerfectDodgeAdrenaline);
			w.Write(r.StaggerAdrenaline);
			w.Write(r.MissAdrenaline);
			w.Write(r.DamageAdrenaline);
			w.Write(r.GuardianAdrenaline);
		}

		private static PlayerResourceRules ReadPlayerRules(BinaryReader r)
		{
			return new PlayerResourceRules
			{
				Run = r.ReadSingle(),
				Jump = r.ReadSingle(),
				Dodge = r.ReadSingle(),
				Swim = r.ReadSingle(),
				Sneak = r.ReadSingle(),
				Encumbered = r.ReadSingle(),
				Block = r.ReadSingle(),
				Grapple = r.ReadSingle(),
				PrimaryStamina = r.ReadSingle(),
				SecondaryStamina = r.ReadSingle(),
				DrawStamina = r.ReadSingle(),
				ReloadStamina = r.ReadSingle(),
				HomeStamina = r.ReadSingle(),
				PrimaryEitr = r.ReadSingle(),
				SecondaryEitr = r.ReadSingle(),
				DrawEitr = r.ReadSingle(),
				ReloadEitr = r.ReadSingle(),
				PrimaryAdrenaline = r.ReadSingle(),
				SecondaryAdrenaline = r.ReadSingle(),
				ProjectileAdrenaline = r.ReadSingle(),
				BlockAdrenaline = r.ReadSingle(),
				ParryAdrenaline = r.ReadSingle(),
				PerfectDodgeAdrenaline = r.ReadSingle(),
				StaggerAdrenaline = r.ReadSingle(),
				MissAdrenaline = r.ReadSingle(),
				DamageAdrenaline = r.ReadSingle(),
				GuardianAdrenaline = r.ReadSingle()
			};
		}

		private static byte[] EncodePlayerRulesRequest(bool apply, PlayerResourceRules rules)
		{
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write(1);
			binaryWriter.Write(apply ? ((byte)1) : ((byte)0));
			if (apply)
			{
				WritePlayerRules(binaryWriter, rules);
			}
			return memoryStream.ToArray();
		}

		private static bool DecodePlayerRulesRequest(byte[] bytes, out bool apply, out PlayerResourceRules rules)
		{
			apply = false;
			rules = PlayerResourceRules.Vanilla;
			if (bytes == null || bytes.Length > 256)
			{
				return false;
			}
			try
			{
				using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes));
				if (binaryReader.ReadInt32() != 1)
				{
					return false;
				}
				byte b = binaryReader.ReadByte();
				if (b > 1)
				{
					return false;
				}
				apply = b == 1;
				if (apply)
				{
					rules = ReadPlayerRules(binaryReader);
				}
				return binaryReader.BaseStream.Position == binaryReader.BaseStream.Length && (!apply || ValidPlayerRules(rules));
			}
			catch (Exception ex) when (ex is IOException || ex is EndOfStreamException || ex is ArgumentException)
			{
				return false;
			}
		}

		private static byte[] EncodePlayerRulesState(long revision, PlayerResourceRules rules)
		{
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write(1);
			binaryWriter.Write(revision);
			WritePlayerRules(binaryWriter, rules);
			return memoryStream.ToArray();
		}

		private static bool DecodePlayerRulesState(byte[] bytes, out long revision, out PlayerResourceRules rules)
		{
			revision = 0L;
			rules = PlayerResourceRules.Vanilla;
			if (bytes == null || bytes.Length > 256)
			{
				return false;
			}
			try
			{
				using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes));
				if (binaryReader.ReadInt32() != 1)
				{
					return false;
				}
				revision = binaryReader.ReadInt64();
				rules = ReadPlayerRules(binaryReader);
				return binaryReader.BaseStream.Position == binaryReader.BaseStream.Length && revision >= 0 && ValidPlayerRules(rules);
			}
			catch (Exception ex) when (ex is IOException || ex is EndOfStreamException || ex is ArgumentException)
			{
				return false;
			}
		}

		private void LoadPlayerRules()
		{
			EnsurePlayerRulesConfig();
			playerRules = PlayerResourceRules.Vanilla;
			playerRulesRevision = 1L;
			string text = ((playerRulesStored != null) ? playerRulesStored.Value : "");
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			try
			{
				if (DecodePlayerRulesState(Convert.FromBase64String(text), out var revision, out var rules))
				{
					playerRules = rules;
					playerRulesRevision = Math.Max(1L, revision);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not read stored player rules: " + ex.Message));
			}
		}

		private void SavePlayerRules()
		{
			EnsurePlayerRulesConfig();
			if (playerRulesStored != null)
			{
				playerRulesStored.Value = Convert.ToBase64String(EncodePlayerRulesState(playerRulesRevision, playerRules));
			}
		}

		private void ResetPlayerRulesNetwork()
		{
			foreach (ZRpc item in playerRulesRegistered)
			{
				try
				{
					item.Unregister("DezzyCode.WorldControl.PlayerRules.Request.v1");
					item.Unregister("DezzyCode.WorldControl.PlayerRules.State.v1");
				}
				catch
				{
				}
			}
			playerRulesRegistered.Clear();
			playerRulesRequests.Clear();
			playerRulesEdits.Clear();
			playerRulesNetwork = network;
			playerRulesLoadedForServer = false;
			nextPlayerRulesQuery = 0f;
			playerRulesSynced = session != null && session.Server;
			playerRulesRevision = 0L;
			if (session == null || !session.Server)
			{
				playerRules = PlayerResourceRules.Vanilla;
			}
			playerRulesDraft = playerRules;
			playerRulesDraftDirty = false;
			RestorePlayerRuleTuning();
		}

		private void PlayerRulesTick()
		{
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Expected O, but got Unknown
			EnsurePlayerRulesConfig();
			if (playerRulesNetwork != network)
			{
				ResetPlayerRulesNetwork();
			}
			if ((Object)(object)network == (Object)null || session == null)
			{
				return;
			}
			if (session.Server && !playerRulesLoadedForServer)
			{
				playerRulesLoadedForServer = true;
				LoadPlayerRules();
				playerRulesSynced = true;
				playerRulesDraft = playerRules;
			}
			foreach (ZNetPeer peer in network.GetPeers())
			{
				if (peer != null && peer.m_rpc != null && playerRulesRegistered.Add(peer.m_rpc))
				{
					peer.m_rpc.Register<ZPackage>("DezzyCode.WorldControl.PlayerRules.Request.v1", (Action<ZRpc, ZPackage>)OnPlayerRulesRequest);
					peer.m_rpc.Register<ZPackage>("DezzyCode.WorldControl.PlayerRules.State.v1", (Action<ZRpc, ZPackage>)OnPlayerRulesState);
					if (session.Server && peer.IsReady() && peer.m_rpc.IsConnected())
					{
						SendPlayerRulesState(peer.m_rpc);
					}
				}
			}
			playerRulesStale.Clear();
			foreach (ZRpc item in playerRulesRegistered)
			{
				if (item == null || !item.IsConnected())
				{
					playerRulesStale.Add(item);
				}
			}
			foreach (ZRpc item2 in playerRulesStale)
			{
				playerRulesRegistered.Remove(item2);
				playerRulesRequests.Remove(item2);
				playerRulesEdits.Remove(item2);
				try
				{
					item2.Unregister("DezzyCode.WorldControl.PlayerRules.Request.v1");
					item2.Unregister("DezzyCode.WorldControl.PlayerRules.State.v1");
				}
				catch
				{
				}
			}
			if (!session.Server && !playerRulesSynced && Time.unscaledTime >= nextPlayerRulesQuery)
			{
				ZNetPeer serverPeer = network.GetServerPeer();
				if (serverPeer != null && serverPeer.IsReady() && serverPeer.m_rpc != null && serverPeer.m_rpc.IsConnected())
				{
					nextPlayerRulesQuery = Time.unscaledTime + 1f;
					serverPeer.m_rpc.Invoke("DezzyCode.WorldControl.PlayerRules.Request.v1", new object[1] { (object)new ZPackage(EncodePlayerRulesRequest(apply: false, PlayerResourceRules.Vanilla)) });
				}
			}
			if (playerRulesSynced)
			{
				ApplyPlayerRuleTuning();
			}
		}

		private void OnPlayerRulesRequest(ZRpc rpc, ZPackage package)
		{
			ZNetPeer val = ReadyPeer(rpc);
			if (session == null || !session.Server || rpc == null || val == null || package == null || package.Size() > 256 || !DecodePlayerRulesRequest(package.GetArray(), out var apply, out var rules))
			{
				return;
			}
			Dictionary<ZRpc, float> dictionary = (apply ? playerRulesEdits : playerRulesRequests);
			if (!dictionary.TryGetValue(rpc, out var value) || !(Time.unscaledTime < value))
			{
				dictionary[rpc] = Time.unscaledTime + (apply ? 0.35f : 0.75f);
				if (apply && IsAdmin(rpc))
				{
					playerRules = rules;
					playerRulesRevision = Math.Max(1L, playerRulesRevision + 1);
					SavePlayerRules();
					playerRulesDraft = playerRules;
					playerRulesDraftDirty = false;
					BroadcastPlayerRules();
					controlsDirty = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Player resource rules changed by admin " + val.m_playerName + "."));
				}
				else
				{
					SendPlayerRulesState(rpc);
				}
			}
		}

		private void OnPlayerRulesState(ZRpc rpc, ZPackage package)
		{
			if (session != null && !session.Server && rpc != null && package != null && package.Size() <= 256 && serverConnection != null && rpc == serverConnection && DecodePlayerRulesState(package.GetArray(), out var revision, out var rules) && (!playerRulesSynced || revision >= playerRulesRevision))
			{
				playerRulesRevision = revision;
				playerRules = rules;
				playerRulesSynced = true;
				if (!playerRulesDraftDirty)
				{
					playerRulesDraft = rules;
				}
				controlsDirty = true;
			}
		}

		private void SendPlayerRulesState(ZRpc rpc)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (rpc != null && rpc.IsConnected())
			{
				rpc.Invoke("DezzyCode.WorldControl.PlayerRules.State.v1", new object[1] { (object)new ZPackage(EncodePlayerRulesState(playerRulesRevision, playerRules)) });
			}
		}

		private void BroadcastPlayerRules()
		{
			foreach (ZNetPeer peer in network.GetPeers())
			{
				if (peer != null && peer.IsReady() && peer.m_rpc != null && peer.m_rpc.IsConnected() && playerRulesRegistered.Contains(peer.m_rpc))
				{
					SendPlayerRulesState(peer.m_rpc);
				}
			}
			ApplyPlayerRuleTuning();
		}

		private void SubmitPlayerRules()
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			if (!CanEdit || !ValidPlayerRules(playerRulesDraft))
			{
				return;
			}
			if (session != null && session.Server)
			{
				playerRules = playerRulesDraft;
				playerRulesRevision = Math.Max(1L, playerRulesRevision + 1);
				playerRulesSynced = true;
				playerRulesDraftDirty = false;
				SavePlayerRules();
				BroadcastPlayerRules();
				controlsDirty = true;
			}
			else
			{
				ZNetPeer val = (((Object)(object)network != (Object)null) ? network.GetServerPeer() : null);
				if (val != null && val.IsReady() && val.m_rpc != null && val.m_rpc.IsConnected())
				{
					val.m_rpc.Invoke("DezzyCode.WorldControl.PlayerRules.Request.v1", new object[1] { (object)new ZPackage(EncodePlayerRulesRequest(apply: true, playerRulesDraft)) });
				}
			}
		}

		private static FieldInfo PlayerRuleField(string name)
		{
			Type type = typeof(Player);
			while (type != null)
			{
				FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && field.FieldType == typeof(float))
				{
					return field;
				}
				type = type.BaseType;
			}
			return null;
		}

		private void ApplyPlayerFloat(Player player, string fieldName, float multiplier)
		{
			FieldInfo fieldInfo = PlayerRuleField(fieldName);
			if (fieldInfo == null || (Object)(object)player == (Object)null)
			{
				return;
			}
			if (!playerFieldBaselines.TryGetValue(fieldName, out var value))
			{
				try
				{
					value = (float)fieldInfo.GetValue(player);
					playerFieldBaselines[fieldName] = value;
				}
				catch
				{
					return;
				}
			}
			try
			{
				fieldInfo.SetValue(player, value * multiplier);
			}
			catch
			{
			}
		}

		private void ApplyPlayerRuleTuning()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				bool flag = playerRulesAppliedPlayer != localPlayer;
				bool flag2 = playerRulesObjectDb != ObjectDB.instance;
				if (flag)
				{
					RestorePlayerFields();
					playerRulesAppliedPlayer = localPlayer;
					playerFieldBaselines.Clear();
					playerRulesAppliedRevision = -1L;
				}
				if (flag2)
				{
					RestoreItemRules();
					playerRulesObjectDb = ObjectDB.instance;
					attackBaselines.Clear();
					projectileBaselines.Clear();
					shieldBaselines.Clear();
					playerRulesAppliedRevision = -1L;
				}
				if (playerRulesAppliedRevision != playerRulesRevision || flag || flag2)
				{
					ApplyPlayerFloat(localPlayer, "m_runStaminaDrain", playerRules.Run);
					ApplyPlayerFloat(localPlayer, "m_jumpStaminaUsage", playerRules.Jump);
					ApplyPlayerFloat(localPlayer, "m_dodgeStaminaUsage", playerRules.Dodge);
					ApplyPlayerFloat(localPlayer, "m_swimStaminaDrainMinSkill", playerRules.Swim);
					ApplyPlayerFloat(localPlayer, "m_swimStaminaDrainMaxSkill", playerRules.Swim);
					ApplyPlayerFloat(localPlayer, "m_sneakStaminaDrain", playerRules.Sneak);
					ApplyPlayerFloat(localPlayer, "m_encumberedStaminaDrain", playerRules.Encumbered);
					ApplyPlayerFloat(localPlayer, "m_grapplingStaminaDrain", playerRules.Grapple);
					ApplyPlayerFloat(localPlayer, "m_perfectDodgeAdrenaline", playerRules.PerfectDodgeAdrenaline);
					ApplyPlayerFloat(localPlayer, "m_staggerEnemyAdrenaline", playerRules.StaggerAdrenaline);
					ApplyPlayerFloat(localPlayer, "m_attackMissAdrenaline", playerRules.MissAdrenaline);
					ApplyPlayerFloat(localPlayer, "m_nonBlockDamageAdrenaline", playerRules.DamageAdrenaline);
					ApplyPlayerFloat(localPlayer, "m_adrenalineGuardianPower", playerRules.GuardianAdrenaline);
					TuneItemRules();
					playerRulesAppliedRevision = playerRulesRevision;
				}
			}
		}

		private void TuneItemRules()
		{
			ObjectDB val = ObjectDB.instance;
			if ((Object)(object)val == (Object)null || val.m_items == null)
			{
				return;
			}
			foreach (GameObject item in val.m_items)
			{
				if (!((Object)(object)item == (Object)null))
				{
					ItemDrop component = item.GetComponent<ItemDrop>();
					if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null)
					{
						SharedData shared = component.m_itemData.m_shared;
						TuneAttack(shared.m_attack, primary: true);
						TuneAttack(shared.m_secondaryAttack, primary: false);
						TuneShield(shared);
					}
				}
			}
		}

		private void TuneAttack(Attack attack, bool primary)
		{
			if (attack == null)
			{
				return;
			}
			if (!attackBaselines.TryGetValue(attack, out var value))
			{
				value = new AttackBaseline
				{
					AttackAdrenaline = attack.m_attackAdrenaline
				};
				attackBaselines[attack] = value;
			}
			float num = (primary ? playerRules.PrimaryAdrenaline : playerRules.SecondaryAdrenaline);
			attack.m_attackAdrenaline = value.AttackAdrenaline * num;
			if (!((Object)(object)attack.m_attackProjectile != (Object)null))
			{
				return;
			}
			Projectile component = attack.m_attackProjectile.GetComponent<Projectile>();
			if ((Object)(object)component != (Object)null)
			{
				if (!projectileBaselines.TryGetValue(component, out var value2))
				{
					value2 = component.m_adrenaline;
					projectileBaselines[component] = value2;
				}
				component.m_adrenaline = value2 * playerRules.ProjectileAdrenaline;
			}
		}

		private void TuneShield(SharedData shared)
		{
			if (shared != null)
			{
				if (!shieldBaselines.TryGetValue(shared, out var value))
				{
					value = new ShieldBaseline
					{
						Block = shared.m_blockAdrenaline,
						Parry = shared.m_perfectBlockAdrenaline
					};
					shieldBaselines[shared] = value;
				}
				shared.m_blockAdrenaline = value.Block * playerRules.BlockAdrenaline;
				shared.m_perfectBlockAdrenaline = value.Parry * playerRules.ParryAdrenaline;
			}
		}

		private void RestorePlayerFields()
		{
			Player val = playerRulesAppliedPlayer;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			foreach (KeyValuePair<string, float> playerFieldBaseline in playerFieldBaselines)
			{
				FieldInfo fieldInfo = PlayerRuleField(playerFieldBaseline.Key);
				if (!(fieldInfo == null))
				{
					try
					{
						fieldInfo.SetValue(val, playerFieldBaseline.Value);
					}
					catch
					{
					}
				}
			}
		}

		private void RestoreItemRules()
		{
			foreach (KeyValuePair<Attack, AttackBaseline> attackBaseline in attackBaselines)
			{
				Attack key = attackBaseline.Key;
				AttackBaseline value = attackBaseline.Value;
				if (key != null && value != null)
				{
					key.m_attackAdrenaline = value.AttackAdrenaline;
				}
			}
			foreach (KeyValuePair<Projectile, float> projectileBaseline in projectileBaselines)
			{
				if ((Object)(object)projectileBaseline.Key != (Object)null)
				{
					projectileBaseline.Key.m_adrenaline = projectileBaseline.Value;
				}
			}
			foreach (KeyValuePair<SharedData, ShieldBaseline> shieldBaseline in shieldBaselines)
			{
				if (shieldBaseline.Key != null && shieldBaseline.Value != null)
				{
					shieldBaseline.Key.m_blockAdrenaline = shieldBaseline.Value.Block;
					shieldBaseline.Key.m_perfectBlockAdrenaline = shieldBaseline.Value.Parry;
				}
			}
		}

		private void RestorePlayerRuleTuning()
		{
			RestorePlayerFields();
			RestoreItemRules();
			playerRulesAppliedPlayer = null;
			playerFieldBaselines.Clear();
			playerRulesObjectDb = null;
			attackBaselines.Clear();
			projectileBaselines.Clear();
			shieldBaselines.Clear();
			playerRulesAppliedRevision = -1L;
		}

		private void BuildPlayers(Transform list)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			TMP_Text header = Hint("");
			playerList = list;
			oldServer = ((Component)Hint(Words.T("moderation.old")).transform.parent).gameObject;
			Section(Words.T("players.online"));
			onlineHeading = (RectTransform)list.GetChild(list.childCount - 1);
			Section(Words.T("players.banned"));
			bannedHeading = (RectTransform)list.GetChild(list.childCount - 1);
			noneBanned = ((Component)Hint(Words.T("players.banned.none")).transform.parent).gameObject;
			refresh.Add(delegate
			{
				//IL_0109: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0110: Unknown result type (might be due to invalid IL or missing references)
				//IL_0124: Unknown result type (might be due to invalid IL or missing references)
				//IL_0126: Unknown result type (might be due to invalid IL or missing references)
				//IL_0146: 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_019c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0195: 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)
				//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0279: Unknown result type (might be due to invalid IL or missing references)
				//IL_0272: Unknown result type (might be due to invalid IL or missing references)
				QueryModeration();
				List<PlayerInfo> list2 = Players();
				header.text = Words.T("players.count", list2.Count.ToString()) + "   ·   " + Words.T("players.note");
				bool flag = moderationKnown;
				if (oldServer.activeSelf == flag)
				{
					oldServer.SetActive(!flag);
				}
				while (playerLines.Count < list2.Count)
				{
					playerLines.Add(NewPlayerLine());
				}
				for (int i = 0; i < playerLines.Count; i++)
				{
					PlayerLine playerLine = playerLines[i];
					bool flag2 = i < list2.Count;
					if (playerLine.Row.activeSelf != flag2)
					{
						playerLine.Row.SetActive(flag2);
					}
					if (flag2)
					{
						PlayerInfo val = list2[i];
						bool flag3 = Yourself(val);
						bool flag4 = moderationAdmins.Contains(val.m_characterID);
						playerLine.Name.text = (flag3 ? (val.m_name + " " + Words.T("players.you")) : val.m_name) + (flag4 ? ("  ·  " + Words.T("players.admin")) : "");
						((Graphic)playerLine.Name).color = (flag4 ? Orange : TextWhite);
						playerLine.Where.text = Distance(val, flag3);
						bool flag5 = !flag3 && CanAct();
						((Selectable)playerLine.Bring).interactable = flag5;
						((Selectable)playerLine.Visit).interactable = flag5;
						bool interactable = flag5 && flag && moderationOnline.Contains(val.m_characterID);
						((Selectable)playerLine.Kick).interactable = interactable;
						((Selectable)playerLine.Ban).interactable = interactable;
						((Selectable)playerLine.Admin).interactable = interactable;
						if ((Object)(object)playerLine.AdminText != (Object)null)
						{
							playerLine.AdminText.text = Words.T(flag4 ? "players.admin.remove" : "players.admin.make");
							((Graphic)playerLine.AdminText).color = (flag4 ? Orange : Beige);
						}
					}
				}
				int num = (flag ? moderationBanned.Count : 0);
				if (noneBanned.activeSelf != (flag && num == 0))
				{
					noneBanned.SetActive(flag && num == 0);
				}
				while (bannedLines.Count < num)
				{
					bannedLines.Add(NewBannedLine());
				}
				for (int j = 0; j < bannedLines.Count; j++)
				{
					BannedLine bannedLine = bannedLines[j];
					bool flag6 = j < num;
					if (bannedLine.Row.activeSelf != flag6)
					{
						bannedLine.Row.SetActive(flag6);
					}
					if (flag6)
					{
						BannedPlayer bannedPlayer = moderationBanned[j];
						bannedLine.Name.text = (string.IsNullOrEmpty(bannedPlayer.Name) ? bannedPlayer.Id : bannedPlayer.Name);
						bannedLine.Id.text = (string.IsNullOrEmpty(bannedPlayer.Name) ? "" : bannedPlayer.Id);
						((Selectable)bannedLine.Unban).interactable = CanAct();
					}
				}
			});
		}

		private PlayerLine NewPlayerLine()
		{
			Transform val = rowList;
			int num = rowIndex;
			int index = playerLines.Count;
			rowList = playerList;
			rowIndex = index;
			float[] widths = new float[5] { 84f, 64f, 78f, 78f, 128f };
			PlayerLine playerLine = new PlayerLine();
			RectTransform val2 = Row("", "", Total(widths), out playerLine.Name, out playerLine.Where);
			Button[] array = RowButtons(val2, widths, new string[5]
			{
				Words.T("players.bring"),
				Words.T("players.goto"),
				Words.T("players.kick"),
				Words.T("players.ban"),
				""
			}, new Action[5]
			{
				delegate
				{
					Fetch(index, ActionKind.Bring);
				},
				delegate
				{
					Fetch(index, ActionKind.Goto);
				},
				delegate
				{
					AskModeration(index, ModerationKind.Kick);
				},
				delegate
				{
					AskModeration(index, ModerationKind.Ban);
				},
				delegate
				{
					AskModeration(index, ModerationKind.MakeAdmin);
				}
			});
			playerLine.Row = ((Component)val2).gameObject;
			playerLine.Bring = array[0];
			playerLine.Visit = array[1];
			playerLine.Kick = array[2];
			playerLine.Ban = array[3];
			playerLine.Admin = array[4];
			playerLine.AdminText = ((Component)playerLine.Admin).GetComponentInChildren<TMP_Text>();
			((Transform)val2).SetSiblingIndex(((Transform)onlineHeading).GetSiblingIndex() + 1 + index);
			rowList = val;
			rowIndex = num;
			BetrValheim.Dress(((Component)val2).gameObject);
			return playerLine;
		}

		private BannedLine NewBannedLine()
		{
			Transform val = rowList;
			int num = rowIndex;
			int index = bannedLines.Count;
			rowList = playerList;
			rowIndex = index;
			BannedLine bannedLine = new BannedLine();
			RectTransform val2 = Row("", "", 120f, out bannedLine.Name, out bannedLine.Id);
			bannedLine.Unban = RowButtons(val2, new float[1] { 120f }, new string[1] { Words.T("players.unban") }, new Action[1]
			{
				delegate
				{
					AskUnban(index);
				}
			})[0];
			bannedLine.Row = ((Component)val2).gameObject;
			((Transform)val2).SetSiblingIndex(((Transform)bannedHeading).GetSiblingIndex() + 1 + index);
			rowList = val;
			rowIndex = num;
			BetrValheim.Dress(((Component)val2).gameObject);
			return bannedLine;
		}

		private void AskModeration(int index, ModerationKind kind)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result