Decompiled source of MuckReplayable v0.9.4

MuckReplayable.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[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("MuckReplayable")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MuckReplayable")]
[assembly: AssemblyTitle("MuckReplayable")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MuckReforged;

public sealed class AggroController : MonoBehaviour
{
	private enum AggroState
	{
		Idle,
		Chasing,
		Searching,
		Returning
	}

	private Mob _mob;

	private Vector3 _homePosition;

	private Vector3 _lastSeenPosition;

	private int _currentPlayerId = -1;

	private float _lastSeenAt = float.NegativeInfinity;

	private float _farSince = -1f;

	private float _returnStartedAt = float.NegativeInfinity;

	private float _nextBlockingBuildScanAt;

	private Transform _cachedBlockingBuild;

	private int _lineOfSightFrame = -1;

	private int _lineOfSightPlayerId = -1;

	private bool _lineOfSightResult;

	private AggroState _state;

	private bool IsBoss
	{
		get
		{
			if ((Object)(object)_mob != (Object)null && (Object)(object)_mob.mobType != (Object)null)
			{
				return _mob.mobType.boss;
			}
			return false;
		}
	}

	private bool IsRanged
	{
		get
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			if ((Object)(object)_mob != (Object)null && (Object)(object)_mob.mobType != (Object)null)
			{
				if (!_mob.mobType.ranged)
				{
					return (int)_mob.mobType.behaviour == 2;
				}
				return true;
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		_mob = ((Component)this).GetComponent<Mob>();
		_homePosition = ((Component)this).transform.position;
		_lastSeenPosition = _homePosition;
		_state = AggroState.Idle;
	}

	internal void MarkDamagedBy(int playerId)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		if (TryGetLivingPlayer(playerId, out var player))
		{
			_currentPlayerId = playerId;
			_lastSeenPosition = ((Component)player).transform.position;
			_lastSeenAt = Time.time;
			_farSince = -1f;
			_state = AggroState.Chasing;
			SetPlayerTarget(player);
		}
	}

	internal Vector3 GetNextDestination()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_mob == (Object)null || (Object)(object)_mob.mobType == (Object)null)
		{
			return Vector3.zero;
		}
		if ((_mob.IsAttacking() && _mob.stopOnAttack) || _mob.knocked || !_mob.ready)
		{
			return Vector3.zero;
		}
		return (Vector3)(_state switch
		{
			AggroState.Idle => TickIdle(), 
			AggroState.Chasing => TickChasing(), 
			AggroState.Searching => TickSearching(), 
			AggroState.Returning => TickReturning(), 
			_ => Vector3.zero, 
		});
	}

	internal float GetNextThinkDelay()
	{
		float num;
		switch (_state)
		{
		case AggroState.Chasing:
		case AggroState.Searching:
			num = 0.5f;
			break;
		case AggroState.Returning:
			num = 1f;
			break;
		default:
			num = 0.75f;
			break;
		}
		return num + (float)Mathf.Abs(((Object)this).GetInstanceID() % 23) * 0.011f;
	}

	private Vector3 TickIdle()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		PlayerManager val = FindClosestVisiblePlayer(AcquireDistance());
		if ((Object)(object)val == (Object)null)
		{
			ClearTarget();
			return Vector3.zero;
		}
		BeginChasing(val);
		return DestinationFor(val);
	}

	private Vector3 TickChasing()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		if (!TryGetLivingPlayer(_currentPlayerId, out var player))
		{
			BeginReturning();
			return _homePosition;
		}
		float num = Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position);
		float num2 = Vector3.Distance(_homePosition, ((Component)this).transform.position);
		if (num > DisengageDistance() || num2 > HomeLeashDistance())
		{
			if (_farSince < 0f)
			{
				_farSince = Time.time;
			}
			else if (Time.time - _farSince >= Plugin.Settings.FarTargetGraceSeconds.Value)
			{
				BeginReturning();
				return _homePosition;
			}
		}
		else
		{
			_farSince = -1f;
		}
		if (HasLineOfSight(player) || num <= Plugin.Settings.ProximityAcquireDistance.Value)
		{
			_lastSeenPosition = ((Component)player).transform.position;
			_lastSeenAt = Time.time;
			SetPlayerTarget(player);
			return DestinationFor(player);
		}
		_state = AggroState.Searching;
		ClearTarget();
		return _lastSeenPosition;
	}

	private Vector3 TickSearching()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: 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_0059: Unknown result type (might be due to invalid IL or missing references)
		if (TryGetLivingPlayer(_currentPlayerId, out var player))
		{
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position);
			if (num <= AcquireDistance() && (num <= Plugin.Settings.ProximityAcquireDistance.Value || HasLineOfSight(player)))
			{
				BeginChasing(player);
				return DestinationFor(player);
			}
		}
		if (Time.time - _lastSeenAt <= LostSightSeconds())
		{
			ClearTarget();
			return _lastSeenPosition;
		}
		BeginReturning();
		return _homePosition;
	}

	private Vector3 TickReturning()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		if (Vector3.Distance(((Component)this).transform.position, _homePosition) <= Plugin.Settings.ReturnArrivalDistance.Value)
		{
			_state = AggroState.Idle;
			_currentPlayerId = -1;
			_farSince = -1f;
			ClearTarget();
			if ((Object)(object)_mob.agent != (Object)null && _mob.agent.isOnNavMesh)
			{
				_mob.agent.ResetPath();
			}
			return Vector3.zero;
		}
		if (Time.time - _returnStartedAt >= Plugin.Settings.ReturnReacquireCooldown.Value)
		{
			PlayerManager val = FindClosestVisiblePlayer(AcquireDistance());
			if ((Object)(object)val != (Object)null && Vector3.Distance(_homePosition, ((Component)val).transform.position) <= HomeLeashDistance())
			{
				BeginChasing(val);
				return DestinationFor(val);
			}
		}
		ClearTarget();
		return _homePosition;
	}

	private void BeginChasing(PlayerManager player)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		_state = AggroState.Chasing;
		_currentPlayerId = player.id;
		_lastSeenPosition = ((Component)player).transform.position;
		_lastSeenAt = Time.time;
		_farSince = -1f;
		SetPlayerTarget(player);
	}

	private void BeginReturning()
	{
		_state = AggroState.Returning;
		_returnStartedAt = Time.time;
		_currentPlayerId = -1;
		_farSince = -1f;
		ClearTarget();
	}

	private Vector3 DestinationFor(PlayerManager player)
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		if (Plugin.Settings.AttackBlockingBuildings.Value && TryFindBlockingBuild(player, out var result))
		{
			_mob.target = result;
			_mob.targetPlayerId = -1;
			return result.position;
		}
		SetPlayerTarget(player);
		float num = Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position);
		if (num <= 12f || _mob.mobType.followPlayerAccuracy >= 0.999f)
		{
			return ((Component)player).transform.position;
		}
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f));
		val *= num * (1f - _mob.mobType.followPlayerAccuracy);
		return ((Component)player).transform.position + val;
	}

	private bool TryFindBlockingBuild(PlayerManager player, out Transform result)
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		result = null;
		if (_mob.mobType.ignoreBuilds || HasLineOfSight(player) || (Object)(object)ResourceManager.Instance == (Object)null || ResourceManager.Instance.builds == null)
		{
			_cachedBlockingBuild = null;
			return false;
		}
		float value = Plugin.Settings.BuildingAttackDistance.Value;
		if ((Object)(object)_cachedBlockingBuild != (Object)null)
		{
			Vector3 val = _cachedBlockingBuild.position - ((Component)this).transform.position;
			if (((Vector3)(ref val)).sqrMagnitude <= value * value)
			{
				result = _cachedBlockingBuild;
				return true;
			}
			_cachedBlockingBuild = null;
		}
		if (Time.time < _nextBlockingBuildScanAt)
		{
			return false;
		}
		_nextBlockingBuildScanAt = Time.time + 2.1f + (float)Mathf.Abs(((Object)this).GetInstanceID() % 29) * 0.037f;
		float num = value;
		Vector3 val2 = ((Component)player).transform.position - ((Component)this).transform.position;
		Vector3 normalized = ((Vector3)(ref val2)).normalized;
		foreach (KeyValuePair<int, GameObject> build in ResourceManager.Instance.builds)
		{
			GameObject value2 = build.Value;
			if (!((Object)(object)value2 == (Object)null))
			{
				Vector3 val3 = value2.transform.position - ((Component)this).transform.position;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				if (!(magnitude >= num) && !(Vector3.Dot(normalized, ((Vector3)(ref val3)).normalized) < 0.35f))
				{
					num = magnitude;
					result = value2.transform;
				}
			}
		}
		_cachedBlockingBuild = result;
		return (Object)(object)result != (Object)null;
	}

	private PlayerManager FindClosestVisiblePlayer(float maxDistance)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		if (GameManager.players == null)
		{
			return null;
		}
		PlayerManager result = null;
		float num = maxDistance;
		foreach (PlayerManager value in GameManager.players.Values)
		{
			if (!((Object)(object)value == (Object)null) && !value.dead && !value.disconnected)
			{
				float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)value).transform.position);
				if (!(num2 >= num) && (!(num2 > Plugin.Settings.ProximityAcquireDistance.Value) || HasLineOfSight(value)))
				{
					result = value;
					num = num2;
				}
			}
		}
		return result;
	}

	private bool HasLineOfSight(PlayerManager player)
	{
		//IL_0033: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		if (_lineOfSightFrame == Time.frameCount && _lineOfSightPlayerId == player.id)
		{
			return _lineOfSightResult;
		}
		Vector3 val = ((Component)this).transform.position + Vector3.up * 1.2f;
		Vector3 val2 = ((Component)player).transform.position + Vector3.up * 1.2f - val;
		float magnitude = ((Vector3)(ref val2)).magnitude;
		if (magnitude <= 0.01f)
		{
			return CacheLineOfSight(player.id, result: true);
		}
		int num = -5;
		if ((Object)(object)MobManager.Instance != (Object)null && ((LayerMask)(ref MobManager.Instance.whatIsRaycastable)).value != 0)
		{
			num = ((LayerMask)(ref MobManager.Instance.whatIsRaycastable)).value;
		}
		RaycastHit val3 = default(RaycastHit);
		if (!Physics.Raycast(val, ((Vector3)(ref val2)).normalized, ref val3, magnitude + 0.5f, num, (QueryTriggerInteraction)1))
		{
			return CacheLineOfSight(player.id, result: true);
		}
		PlayerManager componentInParent = ((Component)((RaycastHit)(ref val3)).transform).GetComponentInParent<PlayerManager>();
		return CacheLineOfSight(player.id, (Object)(object)componentInParent == (Object)(object)player);
	}

	private bool CacheLineOfSight(int playerId, bool result)
	{
		_lineOfSightFrame = Time.frameCount;
		_lineOfSightPlayerId = playerId;
		_lineOfSightResult = result;
		return result;
	}

	private bool TryGetLivingPlayer(int playerId, out PlayerManager player)
	{
		player = null;
		if (playerId < 0 || GameManager.players == null || !GameManager.players.TryGetValue(playerId, out player))
		{
			return false;
		}
		if ((Object)(object)player != (Object)null && !player.dead)
		{
			return !player.disconnected;
		}
		return false;
	}

	private void SetPlayerTarget(PlayerManager player)
	{
		_mob.target = ((Component)player).transform;
		_mob.targetPlayerId = player.id;
	}

	private void ClearTarget()
	{
		_mob.target = null;
		_mob.targetPlayerId = -1;
	}

	private float AcquireDistance()
	{
		if (IsBoss)
		{
			return Plugin.Settings.BossAcquireDistance.Value;
		}
		if (!IsRanged)
		{
			return Plugin.Settings.MeleeAcquireDistance.Value;
		}
		return Plugin.Settings.RangedAcquireDistance.Value;
	}

	private float DisengageDistance()
	{
		if (IsBoss)
		{
			return Plugin.Settings.BossDisengageDistance.Value;
		}
		if (!IsRanged)
		{
			return Plugin.Settings.MeleeDisengageDistance.Value;
		}
		return Plugin.Settings.RangedDisengageDistance.Value;
	}

	private float HomeLeashDistance()
	{
		if (IsBoss)
		{
			return Plugin.Settings.BossHomeLeash.Value;
		}
		if (!IsRanged)
		{
			return Plugin.Settings.MeleeHomeLeash.Value;
		}
		return Plugin.Settings.RangedHomeLeash.Value;
	}

	private float LostSightSeconds()
	{
		if (IsBoss)
		{
			return Plugin.Settings.BossLostSightSeconds.Value;
		}
		if (!IsRanged)
		{
			return Plugin.Settings.MeleeLostSightSeconds.Value;
		}
		return Plugin.Settings.RangedLostSightSeconds.Value;
	}
}
[HarmonyPatch(typeof(MobServerEnemy), "FindNextPosition")]
internal static class MobServerEnemyFindNextPositionPatch
{
	private static bool Prefix(MobServerEnemy __instance, ref Vector3 __result)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		if (!Plugin.Settings.EnableAggro.Value)
		{
			return true;
		}
		AggroController aggroController = ((Component)__instance).GetComponent<AggroController>();
		if ((Object)(object)aggroController == (Object)null)
		{
			aggroController = ((Component)__instance).gameObject.AddComponent<AggroController>();
		}
		((MonoBehaviour)__instance).Invoke("SyncFindNextPosition", aggroController.GetNextThinkDelay());
		__result = aggroController.GetNextDestination();
		return false;
	}
}
[HarmonyPatch(typeof(Hitable), "Damage")]
internal static class HitableDamageAggroPatch
{
	private static void Prefix(Hitable __instance, int newHp, int fromClient)
	{
		if (!Plugin.Settings.EnableAggro.Value || !LocalClient.serverOwner || newHp >= __instance.hp)
		{
			return;
		}
		HitableMob val = (HitableMob)(object)((__instance is HitableMob) ? __instance : null);
		if (!((Object)(object)val == (Object)null))
		{
			AggroController aggroController = ((Component)val).GetComponent<AggroController>();
			if ((Object)(object)aggroController == (Object)null)
			{
				aggroController = ((Component)val).gameObject.AddComponent<AggroController>();
			}
			aggroController.MarkDamagedBy(fromClient);
		}
	}
}
[HarmonyPatch(typeof(Mob), "SetTarget")]
internal static class MobSetTargetPatch
{
	private static bool Prefix(Mob __instance, int targetId)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return false;
		}
		if ((Object)(object)__instance.agent != (Object)null && __instance.agent.isOnNavMesh && targetId >= 0 && GameManager.players != null && GameManager.players.TryGetValue(targetId, out var value) && (Object)(object)value != (Object)null)
		{
			__instance.targetPlayerId = targetId;
			__instance.target = ((Component)value).transform;
			return false;
		}
		__instance.targetPlayerId = -1;
		__instance.target = null;
		return false;
	}
}
internal static class ArtifactBalance
{
	private static readonly FieldInfo JuiceSpeed = AccessTools.Field(typeof(PowerupInventory), "juiceSpeed");

	internal static int Stacks(int[] powerups, string name)
	{
		if (powerups == null && (Object)(object)PowerupInventory.Instance != (Object)null)
		{
			powerups = (int[])AccessTools.Field(typeof(PowerupInventory), "powerups")?.GetValue(PowerupInventory.Instance);
		}
		if (powerups == null || ItemManager.Instance?.stringToPowerupId == null || !ItemManager.Instance.stringToPowerupId.TryGetValue(name, out var value) || value < 0 || value >= powerups.Length)
		{
			return 0;
		}
		return Mathf.Max(0, powerups[value]);
	}

	internal static float Curve(int stacks, float speed, float maximum)
	{
		return PowerupInventory.CumulativeDistribution(Mathf.Max(0, stacks), speed, maximum);
	}

	internal static float Defense(int stacks)
	{
		return Curve(stacks, 0.12f, 35f);
	}

	internal static float Dumbbell(int stacks)
	{
		return 1f + Curve(stacks, 0.07f, 1.5f);
	}

	internal static float Berserk(int stacks, float missingHp)
	{
		return 1f + Mathf.Clamp01(missingHp) * Curve(stacks, 0.22f, 1.4f);
	}

	internal static float Stamina(int stacks)
	{
		return 1f + Curve(stacks, 0.13f, 1.5f);
	}

	internal static float Healing(int stacks)
	{
		return Curve(stacks, 0.09f, 0.75f);
	}

	internal static float Resource(int stacks)
	{
		return 1f + Curve(stacks, 0.22f, 2.5f);
	}

	internal static float Loot(int stacks)
	{
		return 1f + Curve(stacks, 0.17f, 0.9f);
	}

	internal static float AttackSpeed(int stacks)
	{
		return 1f + Curve(stacks, 0.13f, 0.85f);
	}

	internal static float Hunger(int stacks)
	{
		return 1f - Curve(stacks, 0.16f, 0.65f);
	}

	internal static float Juice(int stacks)
	{
		return 1f + Curve(stacks, 0.3f, 0.6f);
	}

	internal static float Robin(int stacks)
	{
		return 1f + Curve(stacks, 0.12f, 1f);
	}

	internal static float Speed(int stacks)
	{
		return 1f + Curve(stacks, 0.12f, 0.65f);
	}

	internal static float Adrenaline(int stacks)
	{
		return 1f + Curve(stacks, 0.55f, 0.75f);
	}

	internal static float Crit(int stacks)
	{
		return 0.18f + Curve(stacks, 0.12f, 0.52f);
	}

	internal static float Jump(int stacks)
	{
		return 1f + Curve(stacks, 0.13f, 1.2f);
	}

	internal static float Wings(int stacks)
	{
		if (stacks > 0)
		{
			return 1f + Curve(stacks, 0.32f, 1.5f);
		}
		return 1f;
	}

	internal static float Lifesteal(int stacks)
	{
		return Curve(stacks, 0.11f, 0.35f);
	}

	internal static float KnockbackChance(int stacks)
	{
		return Curve(stacks, 0.2f, 0.65f);
	}

	internal static float SniperChance(int stacks)
	{
		if (stacks > 0)
		{
			return 0.05f + Curve(stacks, 0.13f, 0.23f);
		}
		return 0f;
	}

	internal static float SniperDamage(int stacks)
	{
		if (stacks > 0)
		{
			return 2.2f + Curve(stacks, 0.16f, 2.8f);
		}
		return 1f;
	}

	internal static float LightningChance(int stacks)
	{
		return Curve(stacks, 0.14f, 0.35f);
	}

	internal static float LightningDamage(int stacks)
	{
		return 2f + Curve(stacks, 0.14f, 0.75f);
	}

	internal static float Enforcer(int stacks, float speed)
	{
		if (stacks > 0)
		{
			return 1f + Curve(stacks, 0.3f, 1.2f) * Mathf.Clamp01(Mathf.Max(0f, speed) / 22f);
		}
		return 1f;
	}

	internal static int BonusHp(int stacks)
	{
		return Mathf.Max(0, stacks) * 8;
	}

	internal static int BonusShield(int stacks)
	{
		return Mathf.Max(0, stacks) * 8;
	}

	internal static float JuiceSpeedMultiplier(PowerupInventory instance)
	{
		if (!((Object)(object)instance != (Object)null) || !(JuiceSpeed != null))
		{
			return 1f;
		}
		return Mathf.Max(1f, (float)JuiceSpeed.GetValue(instance));
	}

	internal static float LowHpRatio()
	{
		PlayerStatus instance = PlayerStatus.Instance;
		if (!((Object)(object)instance == (Object)null) && instance.maxHp > 0)
		{
			return ((float)instance.maxHp - instance.hp) / (float)instance.maxHp;
		}
		return 0f;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetDefenseMultiplier")]
internal static class BalancedDefenseArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Defense(ArtifactBalance.Stacks(playerPowerups, "Danis Milk"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetStrengthMultiplier")]
internal static class BalancedStrengthArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = 1.3f * ArtifactBalance.Dumbbell(ArtifactBalance.Stacks(playerPowerups, "Dumbbell")) * ArtifactBalance.Berserk(ArtifactBalance.Stacks(playerPowerups, "Berserk"), ArtifactBalance.LowHpRatio());
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetAttackSpeedMultiplier")]
internal static class BalancedAttackSpeedArtifactPatch
{
	private static bool Prefix(PowerupInventory __instance, int[] playerPowerups, ref float __result)
	{
		float num = (((Object)(object)PlayerStatus.Instance != (Object)null && PlayerStatus.Instance.adrenalineBoost) ? ArtifactBalance.Adrenaline(ArtifactBalance.Stacks(playerPowerups, "Adrenaline")) : 1f);
		__result = 1.5f * ArtifactBalance.AttackSpeed(ArtifactBalance.Stacks(playerPowerups, "Orange Juice")) * num * ArtifactBalance.JuiceSpeedMultiplier(__instance);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetStaminaMultiplier")]
internal static class BalancedStaminaArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		float num = (((Object)(object)PlayerStatus.Instance != (Object)null && PlayerStatus.Instance.adrenalineBoost) ? ArtifactBalance.Adrenaline(ArtifactBalance.Stacks(playerPowerups, "Adrenaline")) : 1f);
		__result = ArtifactBalance.Stamina(ArtifactBalance.Stacks(playerPowerups, "Peanut Butter")) * num;
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetHealingMultiplier")]
internal static class BalancedHealingArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Healing(ArtifactBalance.Stacks(playerPowerups, "Broccoli"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetResourceMultiplier")]
internal static class BalancedResourceArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Invalid comparison between Unknown and I4
		__result = ArtifactBalance.Resource(ArtifactBalance.Stacks(playerPowerups, "Checkered Shirt"));
		if (GameManager.gameSettings != null && (int)GameManager.gameSettings.gameMode == 1)
		{
			__result += 1.25f;
		}
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetLootMultiplier")]
internal static class BalancedLootArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Loot(ArtifactBalance.Stacks(playerPowerups, "Piggybank"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetSniperScopeMultiplier")]
internal static class BalancedSniperArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		int num = ArtifactBalance.Stacks(playerPowerups, "Sniper Scope");
		__result = ((num > 0 && Random.value < ArtifactBalance.SniperChance(num)) ? ArtifactBalance.SniperDamage(num) : 1f);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetSniperScopeDamageMultiplier")]
internal static class BalancedSniperDamageArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.SniperDamage(ArtifactBalance.Stacks(playerPowerups, "Sniper Scope"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetLightningMultiplier")]
internal static class BalancedLightningArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		int num = ArtifactBalance.Stacks(playerPowerups, "Knuts Hammer");
		__result = ((num > 0 && Random.value < ArtifactBalance.LightningChance(num)) ? ArtifactBalance.LightningDamage(num) : (-1f));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetHpMultiplier")]
internal static class BalancedHpArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref int __result)
	{
		__result = ArtifactBalance.BonusHp(ArtifactBalance.Stacks(playerPowerups, "Red Pill"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetShield")]
internal static class BalancedShieldArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref int __result)
	{
		__result = ArtifactBalance.BonusShield(ArtifactBalance.Stacks(playerPowerups, "Blue Pill"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetHungerMultiplier")]
internal static class BalancedHungerArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Hunger(ArtifactBalance.Stacks(playerPowerups, "Spooo Bean"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetJuiceMultiplier")]
internal static class BalancedJuiceArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Juice(ArtifactBalance.Stacks(playerPowerups, "Juice"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetRobinMultiplier")]
internal static class BalancedRobinArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Robin(ArtifactBalance.Stacks(playerPowerups, "Robin Hood Hat"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetEnforcerMultiplier")]
internal static class BalancedEnforcerArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, float speed, ref float __result)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		float num;
		if (!(speed >= 0f))
		{
			PlayerMovement instance = PlayerMovement.Instance;
			if (instance == null)
			{
				num = 0f;
			}
			else
			{
				Vector3 velocity = instance.GetVelocity();
				num = ((Vector3)(ref velocity)).magnitude;
			}
		}
		else
		{
			num = speed;
		}
		float speed2 = num;
		__result = ArtifactBalance.Enforcer(ArtifactBalance.Stacks(playerPowerups, "Enforcer"), speed2);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetSpeedMultiplier")]
internal static class BalancedSpeedArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		float num = (((Object)(object)PlayerStatus.Instance != (Object)null && PlayerStatus.Instance.adrenalineBoost) ? ArtifactBalance.Adrenaline(ArtifactBalance.Stacks(playerPowerups, "Adrenaline")) : 1f);
		float num2 = PlayerStatus.Instance?.currentSpeedArmorMultiplier ?? 1f;
		__result = ArtifactBalance.Speed(ArtifactBalance.Stacks(playerPowerups, "Sneaker")) * num * num2;
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetAdrenalineBoost")]
internal static class BalancedAdrenalineArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Adrenaline(ArtifactBalance.Stacks(playerPowerups, "Adrenaline"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetCritChance")]
internal static class BalancedCritArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Crit(ArtifactBalance.Stacks(playerPowerups, "Horseshoe"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetJumpMultiplier")]
internal static class BalancedJumpArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Jump(ArtifactBalance.Stacks(playerPowerups, "Jetpack"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetExtraJumps")]
internal static class BalancedFrogArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref int __result)
	{
		__result = Mathf.Min(3, ArtifactBalance.Stacks(playerPowerups, "Janniks Frog"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetFallWingsMultiplier")]
internal static class BalancedWingsArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Wings(ArtifactBalance.Stacks(playerPowerups, "Wings of Glory"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetKnockbackMultiplier")]
internal static class BalancedBulldozerArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ((Random.value < ArtifactBalance.KnockbackChance(ArtifactBalance.Stacks(playerPowerups, "Bulldozer"))) ? 1f : 0f);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetLifestealMultiplier")]
internal static class BalancedLifestealArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Lifesteal(ArtifactBalance.Stacks(playerPowerups, "Crimson Dagger"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetMaxDraculaStacks")]
internal static class BalancedDraculaCapPatch
{
	private static bool Prefix(ref int __result)
	{
		__result = ArtifactBalance.Stacks(null, "Dracula") * 25;
		return false;
	}
}
internal sealed class ArtifactOffer
{
	internal int ChestId;

	internal int PlayerId;

	internal int[] Choices;

	internal float ExpiresAt;
}
internal static class ArtifactChoiceService
{
	private sealed class DeterministicRoll
	{
		private uint state;

		internal DeterministicRoll(int seed)
		{
			state = ((seed == 0) ? 2738958700u : ((uint)seed));
		}

		internal uint Next()
		{
			state ^= state << 13;
			state ^= state >> 17;
			state ^= state << 5;
			return state;
		}

		internal int Range(int max)
		{
			if (max > 1)
			{
				return (int)(Next() % (uint)max);
			}
			return 0;
		}

		internal float NextFloat()
		{
			return (float)(Next() & 0xFFFFFF) / 16777216f;
		}
	}

	internal const int ChoicePacketId = 240;

	private static readonly Dictionary<long, ArtifactOffer> ServerOffers = new Dictionary<long, ArtifactOffer>();

	private static readonly MethodInfo SendTcp = AccessTools.Method(typeof(ClientSend), "SendTCPData", (Type[])null, (Type[])null);

	private static readonly FieldInfo PowerupsField = AccessTools.Field(typeof(PowerupInventory), "powerups");

	internal static int[] GenerateChoices(LootContainerInteract chest)
	{
		if ((Object)(object)chest == (Object)null || (Object)(object)ItemManager.Instance == (Object)null)
		{
			return Array.Empty<int>();
		}
		int[] array = GenerateChoices(chest.GetId(), chest.white, chest.blue, chest.gold);
		if (chest.testPowerup && (Object)(object)chest.powerupToTest != (Object)null && array.Length == 3 && ItemManager.Instance.allPowerups.ContainsKey(chest.powerupToTest.id))
		{
			int id = chest.powerupToTest.id;
			int num = Array.IndexOf(array, id);
			if (num > 0)
			{
				array[num] = array[0];
			}
			array[0] = id;
		}
		return array;
	}

	internal static int[] GenerateChoices(int chestId, float white, float blue, float gold)
	{
		Dictionary<int, Powerup> all = ItemManager.Instance?.allPowerups;
		if (all == null)
		{
			return Array.Empty<int>();
		}
		List<int> list = (from pair in all
			where (Object)(object)pair.Value != (Object)null
			select pair.Key into value
			orderby value
			select value).ToList();
		if (list.Count < 3)
		{
			return Array.Empty<int>();
		}
		List<int> white2 = list.Where((int id) => (int)all[id].tier == 0).ToList();
		List<int> blue2 = list.Where((int id) => (int)all[id].tier == 1).ToList();
		List<int> orange = list.Where((int id) => (int)all[id].tier == 2).ToList();
		DeterministicRoll deterministicRoll = new DeterministicRoll(GameManager.GetSeed() * 486187739 + chestId * 16777619 + 219671);
		List<int> result = new List<int>(3);
		for (int num = 0; num < 3; num++)
		{
			int num2 = -1;
			for (int num3 = 0; num3 < 20; num3++)
			{
				if (num2 >= 0 && !result.Contains(num2))
				{
					break;
				}
				List<int> list2 = PickTier(deterministicRoll, white2, blue2, orange, white, blue, gold);
				if (list2.Count > 0)
				{
					num2 = list2[deterministicRoll.Range(list2.Count)];
				}
			}
			if (num2 < 0 || result.Contains(num2))
			{
				num2 = list.First((int value) => !result.Contains(value));
			}
			result.Add(num2);
		}
		return result.ToArray();
	}

	private static List<int> PickTier(DeterministicRoll random, List<int> white, List<int> blue, List<int> orange, float whiteWeight, float blueWeight, float orangeWeight)
	{
		whiteWeight = ((white.Count > 0) ? Mathf.Max(0f, whiteWeight) : 0f);
		blueWeight = ((blue.Count > 0) ? Mathf.Max(0f, blueWeight) : 0f);
		orangeWeight = ((orange.Count > 0) ? Mathf.Max(0f, orangeWeight) : 0f);
		float num = whiteWeight + blueWeight + orangeWeight;
		if (num <= 0f)
		{
			whiteWeight = ((white.Count > 0) ? 1f : 0f);
			blueWeight = ((blue.Count > 0) ? 1f : 0f);
			orangeWeight = ((orange.Count > 0) ? 1f : 0f);
			num = whiteWeight + blueWeight + orangeWeight;
		}
		float num2 = random.NextFloat() * num;
		if (num2 < whiteWeight)
		{
			return white;
		}
		if (num2 < whiteWeight + blueWeight)
		{
			return blue;
		}
		return orange;
	}

	internal static bool RegisterServerOffer(LootContainerInteract chest, int fromClient)
	{
		if ((Object)(object)chest == (Object)null || fromClient < 0)
		{
			return false;
		}
		int[] array = GenerateChoices(chest);
		if (array.Length != 3)
		{
			return false;
		}
		long[] array2 = (from pair in ServerOffers
			where pair.Value.PlayerId == fromClient
			select pair.Key).ToArray();
		foreach (long key in array2)
		{
			ServerOffers.Remove(key);
		}
		ArtifactOffer artifactOffer = new ArtifactOffer
		{
			ChestId = chest.GetId(),
			PlayerId = fromClient,
			Choices = array,
			ExpiresAt = Time.unscaledTime + 1800f
		};
		ServerOffers[OfferKey(fromClient, artifactOffer.ChestId)] = artifactOffer;
		Plugin.Log.LogInfo((object)string.Format("Artifact offer chest={0}, player={1}, choices={2}", artifactOffer.ChestId, fromClient, string.Join(",", array)));
		return true;
	}

	internal static void Reset()
	{
		ServerOffers.Clear();
	}

	internal static void ForgetPlayer(int playerId)
	{
		long[] array = (from pair in ServerOffers
			where pair.Value.PlayerId == playerId
			select pair.Key).ToArray();
		foreach (long key in array)
		{
			ServerOffers.Remove(key);
		}
	}

	internal static void SubmitChoice(int chestId, int powerupId)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		if ((Object)(object)LocalClient.instance == (Object)null)
		{
			return;
		}
		if (LocalClient.serverOwner)
		{
			HandleChoice(LocalClient.instance.myId, chestId, powerupId);
			return;
		}
		try
		{
			Packet val = new Packet(240);
			try
			{
				val.Write(chestId);
				val.Write(powerupId);
				SendTcp?.Invoke(null, new object[1] { val });
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Could not send artifact choice: " + ex));
		}
	}

	internal static void HandleChoicePacket(int fromClient, Packet packet)
	{
		try
		{
			HandleChoice(fromClient, packet.ReadInt(true), packet.ReadInt(true));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)$"Rejected malformed artifact choice from {fromClient}: {ex.Message}");
		}
	}

	private static void HandleChoice(int fromClient, int chestId, int powerupId)
	{
		long key = OfferKey(fromClient, chestId);
		Client value2;
		Powerup value3;
		if (!ServerOffers.TryGetValue(key, out var value) || value.ExpiresAt < Time.unscaledTime || value.Choices == null || !value.Choices.Contains(powerupId))
		{
			Plugin.Log.LogWarning((object)$"Rejected unoffered artifact {powerupId} from player {fromClient}, chest {chestId}");
			ServerOffers.Remove(key);
		}
		else if (Server.clients == null || !Server.clients.TryGetValue(fromClient, out value2) || value2?.player == null || ItemManager.Instance?.allPowerups == null || !ItemManager.Instance.allPowerups.TryGetValue(powerupId, out value3))
		{
			ServerOffers.Remove(key);
		}
		else
		{
			ServerOffers.Remove(key);
			Grant(fromClient, value2.player, value3);
		}
	}

	private static void Grant(int fromClient, Player serverPlayer, Powerup powerup)
	{
		//IL_001f: 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_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		PlayerManager value;
		Vector3 val = ((GameManager.players != null && GameManager.players.TryGetValue(fromClient, out value) && (Object)(object)value != (Object)null) ? (((Component)value).transform.position + Vector3.up * 1.2f) : Vector3.zero);
		int nextId = ItemManager.Instance.GetNextId();
		ItemManager.Instance.DropPowerupAtPosition(powerup.id, val, nextId);
		ServerSend.DropPowerupAtPosition(powerup.id, nextId, val);
		if (serverPlayer.powerups != null && powerup.id >= 0 && powerup.id < serverPlayer.powerups.Length)
		{
			serverPlayer.powerups[powerup.id]++;
		}
		if ((Object)(object)GameManager.instance != (Object)null)
		{
			GameManager.instance.powerupsPickedup = true;
		}
		if (serverPlayer.stats != null)
		{
			serverPlayer.stats.TryGetValue("Powerups", out var value2);
			serverPlayer.stats["Powerups"] = value2 + 1;
		}
		if ((Object)(object)LocalClient.instance != (Object)null && fromClient == LocalClient.instance.myId && (Object)(object)PowerupInventory.Instance != (Object)null)
		{
			PowerupInventory.Instance.AddPowerup(powerup.name, powerup.id, nextId);
		}
		ItemManager.Instance.PickupItem(nextId);
		ServerSend.PickupItem(fromClient, nextId);
		Plugin.Log.LogInfo((object)$"Granted chosen artifact {powerup.name} ({powerup.id}) to player {fromClient}");
	}

	internal static int CurrentStacks(int powerupId)
	{
		if ((Object)(object)PowerupInventory.Instance == (Object)null || PowerupsField == null)
		{
			return 0;
		}
		int[] array = (int[])PowerupsField.GetValue(PowerupInventory.Instance);
		if (array == null || powerupId < 0 || powerupId >= array.Length)
		{
			return 0;
		}
		return array[powerupId];
	}

	private static long OfferKey(int playerId, int chestId)
	{
		return ((long)playerId << 32) ^ (uint)chestId;
	}
}
internal sealed class ArtifactChoiceOverlay : MonoBehaviour
{
	private static ArtifactChoiceOverlay instance;

	private int chestId;

	private Powerup[] choices;

	private CursorLockMode previousLock;

	private bool previousCursor;

	private bool previousInputActive;

	private bool inputCaptured;

	private GUIStyle titleStyle;

	private GUIStyle nameStyle;

	private GUIStyle bodyStyle;

	private GUIStyle tierStyle;

	internal static void Show(LootContainerInteract chest)
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		if (!Plugin.Settings.EnableArtifactChoices.Value || (Object)(object)chest == (Object)null || (Object)(object)ItemManager.Instance == (Object)null)
		{
			return;
		}
		int[] array = ArtifactChoiceService.GenerateChoices(chest);
		if (array.Length != 3)
		{
			return;
		}
		if ((Object)(object)instance == (Object)null)
		{
			GameObject val = new GameObject("Muck Replayable Artifact Choice");
			Object.DontDestroyOnLoad((Object)val);
			instance = val.AddComponent<ArtifactChoiceOverlay>();
		}
		Dictionary<int, Powerup> allPowerups = ItemManager.Instance.allPowerups;
		if (allPowerups == null)
		{
			return;
		}
		List<Powerup> list = new List<Powerup>(3);
		int[] array2 = array;
		foreach (int key in array2)
		{
			if (!allPowerups.TryGetValue(key, out var value) || (Object)(object)value == (Object)null)
			{
				return;
			}
			list.Add(value);
		}
		instance.Open(chest.GetId(), list.ToArray());
	}

	private void Open(int id, Powerup[] offered)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		if (offered != null && offered.Length == 3 && !offered.Any((Powerup powerup) => (Object)(object)powerup == (Object)null))
		{
			if (!inputCaptured)
			{
				previousLock = Cursor.lockState;
				previousCursor = Cursor.visible;
				previousInputActive = (Object)(object)PlayerInput.Instance != (Object)null && PlayerInput.Instance.active;
				inputCaptured = true;
			}
			chestId = id;
			choices = offered;
			if ((Object)(object)PlayerInput.Instance != (Object)null)
			{
				PlayerInput.Instance.active = false;
			}
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}
	}

	private void Update()
	{
		if (choices != null && (Object)(object)GameManager.instance == (Object)null)
		{
			Close();
		}
		else if (choices != null && (Object)(object)PlayerInput.Instance != (Object)null && PlayerInput.Instance.active)
		{
			PlayerInput.Instance.active = false;
		}
	}

	private void OnGUI()
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		if (choices != null && choices.Length == 3)
		{
			LocalizationService.ApplyGuiFont();
			ReforgedGuiTheme.Ensure();
			EnsureStyles();
			GUI.depth = -2000;
			ReforgedGuiTheme.DrawDim();
			float num = Mathf.Min((float)Screen.width * 0.9f, 1280f);
			float num2 = Mathf.Min((float)Screen.height * 0.78f, 690f);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2);
			GUI.Box(val, GUIContent.none, ReforgedGuiTheme.Window);
			GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 18f, ((Rect)(ref val)).width - 48f, 44f), Header(), titleStyle);
			GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 59f, ((Rect)(ref val)).width - 48f, 26f), Subtitle(), bodyStyle);
			float num3 = 14f;
			float num4 = (((Rect)(ref val)).width - 40f - num3 * 2f) / 3f;
			Rect card = default(Rect);
			for (int i = 0; i < 3; i++)
			{
				((Rect)(ref card))..ctor(((Rect)(ref val)).x + 20f + (float)i * (num4 + num3), ((Rect)(ref val)).y + 92f, num4, ((Rect)(ref val)).height - 112f);
				DrawCard(card, choices[i]);
			}
		}
	}

	private void DrawCard(Rect card, Powerup powerup)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		Color outlineColor = powerup.GetOutlineColor();
		ReforgedGuiTheme.DrawCard(card, (Color?)new Color(outlineColor.r * 0.35f + 0.65f, outlineColor.g * 0.35f + 0.65f, outlineColor.b * 0.35f + 0.65f, 1f));
		GUI.Label(new Rect(((Rect)(ref card)).x + 12f, ((Rect)(ref card)).y + 8f, ((Rect)(ref card)).width - 24f, 24f), TierName(powerup.tier), tierStyle);
		float num = Mathf.Clamp(((Rect)(ref card)).height * 0.21f, 76f, 116f);
		Rect rect = default(Rect);
		((Rect)(ref rect))..ctor(((Rect)(ref card)).x + (((Rect)(ref card)).width - num) * 0.5f, ((Rect)(ref card)).y + 36f, num, num);
		ReforgedGuiTheme.DrawCard(new Rect(((Rect)(ref rect)).x - 7f, ((Rect)(ref rect)).y - 7f, ((Rect)(ref rect)).width + 14f, ((Rect)(ref rect)).height + 14f));
		DrawSprite(powerup.sprite, rect);
		float num2 = ((Rect)(ref rect)).yMax + 7f;
		GUI.Label(new Rect(((Rect)(ref card)).x + 12f, num2, ((Rect)(ref card)).width - 24f, 48f), ArtifactEffectFormatter.DisplayName(powerup.name), nameStyle);
		int num3 = ArtifactChoiceService.CurrentStacks(powerup.id);
		float num4 = num2 + 49f;
		GUI.Label(new Rect(((Rect)(ref card)).x + 16f, num4, ((Rect)(ref card)).width - 32f, 46f), StackLine(num3), bodyStyle);
		float num5 = num4 + 44f;
		GUI.Label(new Rect(((Rect)(ref card)).x + 16f, num5, ((Rect)(ref card)).width - 32f, 76f), ArtifactEffectFormatter.Describe(powerup.name, num3), bodyStyle);
		float num6 = ((Rect)(ref card)).yMax - 54f;
		float num7 = num5 + 76f;
		GUI.Label(new Rect(((Rect)(ref card)).x + 16f, num7, ((Rect)(ref card)).width - 32f, Mathf.Max(20f, num6 - num7 - 6f)), ArtifactEffectFormatter.Description(powerup.name, powerup.description), bodyStyle);
		if (GUI.Button(new Rect(((Rect)(ref card)).x + 18f, num6, ((Rect)(ref card)).width - 36f, 40f), ChooseText(), ReforgedGuiTheme.PrimaryButton))
		{
			ArtifactChoiceService.SubmitChoice(chestId, powerup.id);
			Close();
		}
	}

	private void Close()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		choices = null;
		if (inputCaptured)
		{
			if ((Object)(object)PlayerInput.Instance != (Object)null)
			{
				PlayerInput.Instance.active = previousInputActive;
			}
			Cursor.lockState = previousLock;
			Cursor.visible = previousCursor;
			inputCaptured = false;
		}
	}

	private void OnDestroy()
	{
		Close();
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
		}
	}

	private void EnsureStyles()
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Expected O, but got Unknown
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Expected O, but got Unknown
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Expected O, but got Unknown
		if (titleStyle != null)
		{
			LocalizationService.ApplyGuiFont(titleStyle, nameStyle, bodyStyle, tierStyle);
			return;
		}
		ReforgedGuiTheme.Ensure();
		titleStyle = new GUIStyle(ReforgedGuiTheme.Title)
		{
			alignment = (TextAnchor)4,
			fontSize = 28
		};
		nameStyle = new GUIStyle(ReforgedGuiTheme.Heading)
		{
			alignment = (TextAnchor)4,
			fontSize = 22
		};
		bodyStyle = new GUIStyle(ReforgedGuiTheme.Label)
		{
			alignment = (TextAnchor)1,
			fontSize = 15
		};
		tierStyle = new GUIStyle(ReforgedGuiTheme.Muted)
		{
			alignment = (TextAnchor)4,
			fontSize = 14,
			fontStyle = (FontStyle)1
		};
		LocalizationService.ApplyGuiFont(titleStyle, nameStyle, bodyStyle, tierStyle);
	}

	private static void DrawSprite(Sprite sprite, Rect rect)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)sprite == (Object)null) && !((Object)(object)sprite.texture == (Object)null))
		{
			Rect textureRect = sprite.textureRect;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)sprite.texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)sprite.texture).height);
			GUI.DrawTextureWithTexCoords(rect, (Texture)(object)sprite.texture, val, true);
		}
	}

	private static string Header()
	{
		return LocalizationService.T("artifact_header");
	}

	private static string Subtitle()
	{
		return LocalizationService.T("artifact_subtitle");
	}

	private static string StackLine(int stacks)
	{
		return string.Format(LocalizationService.T("artifact_stack"), stacks, stacks + 1);
	}

	private static string ChooseText()
	{
		return LocalizationService.T("artifact_choose");
	}

	private static string TierName(PowerTier tier)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Invalid comparison between Unknown and I4
		if ((int)tier != 0)
		{
			if ((int)tier != 1)
			{
				return LocalizationService.T("tier_legendary");
			}
			return LocalizationService.T("tier_rare");
		}
		return LocalizationService.T("tier_common");
	}
}
internal static class ArtifactEffectFormatter
{
	internal static string DisplayName(string name)
	{
		return name ?? string.Empty;
	}

	internal static string Description(string name, string original)
	{
		return original ?? string.Empty;
	}

	internal static string Describe(string name, int current)
	{
		int num = current + 1;
		return name switch
		{
			"Red Pill" => $"Max HP: {100 + ArtifactBalance.BonusHp(current)} → {100 + ArtifactBalance.BonusHp(num)}", 
			"Blue Pill" => $"Shield: {ArtifactBalance.BonusShield(current)} → {ArtifactBalance.BonusShield(num)}", 
			"Dumbbell" => Bonus("Base damage", ArtifactBalance.Dumbbell(current), ArtifactBalance.Dumbbell(num)), 
			"Peanut Butter" => Bonus("Stamina efficiency", ArtifactBalance.Stamina(current), ArtifactBalance.Stamina(num)), 
			"Broccoli" => Percent("Healing factor", ArtifactBalance.Healing(current), ArtifactBalance.Healing(num)), 
			"Dracula" => $"+1 max HP per kill · cap {current * 25} → {num * 25}", 
			"Janniks Frog" => $"Extra jumps: {Mathf.Min(3, current)} → {Mathf.Min(3, num)} (cap 3)", 
			"Berserk" => Bonus("Damage at 1 HP", ArtifactBalance.Berserk(current, 1f), ArtifactBalance.Berserk(num, 1f)), 
			"Crimson Dagger" => Percent("Lifesteal", ArtifactBalance.Lifesteal(current), ArtifactBalance.Lifesteal(num)), 
			"Horseshoe" => Percent("Critical chance", ArtifactBalance.Crit(current), ArtifactBalance.Crit(num)), 
			"Orange Juice" => Bonus("Attack speed", ArtifactBalance.AttackSpeed(current), ArtifactBalance.AttackSpeed(num)), 
			"Sneaker" => Bonus("Move speed", ArtifactBalance.Speed(current), ArtifactBalance.Speed(num)), 
			"Piggybank" => Bonus("Bonus loot", ArtifactBalance.Loot(current), ArtifactBalance.Loot(num)), 
			"Checkered Shirt" => Bonus("Resource yield", ArtifactBalance.Resource(current), ArtifactBalance.Resource(num)), 
			"Spooo Bean" => Percent("Hunger drain reduction", 1f - ArtifactBalance.Hunger(current), 1f - ArtifactBalance.Hunger(num)), 
			"Juice" => Bonus("Post-kill speed", ArtifactBalance.Juice(current), ArtifactBalance.Juice(num)), 
			"Robin Hood Hat" => Bonus("Ranged damage", ArtifactBalance.Robin(current), ArtifactBalance.Robin(num)), 
			"Jetpack" => Bonus("Jump height", ArtifactBalance.Jump(current), ArtifactBalance.Jump(num)), 
			"Wings of Glory" => Bonus("Falling attack damage", ArtifactBalance.Wings(current), ArtifactBalance.Wings(num)), 
			"Bulldozer" => Percent("Knockback chance", ArtifactBalance.KnockbackChance(current), ArtifactBalance.KnockbackChance(num)), 
			"Adrenaline" => Bonus("Low-HP speed", ArtifactBalance.Adrenaline(current), ArtifactBalance.Adrenaline(num)), 
			"Enforcer" => Bonus("Damage at full momentum", ArtifactBalance.Enforcer(current, 22f), ArtifactBalance.Enforcer(num, 22f)), 
			"Danis Milk" => Value("Defense", ArtifactBalance.Defense(current), ArtifactBalance.Defense(num)), 
			"Sniper Scope" => Percent("Snipe chance", ArtifactBalance.SniperChance(current), ArtifactBalance.SniperChance(num)) + "\n" + Value("Snipe damage", ArtifactBalance.SniperDamage(current), ArtifactBalance.SniperDamage(num), "x"), 
			"Knuts Hammer" => Percent("Lightning chance", ArtifactBalance.LightningChance(current), ArtifactBalance.LightningChance(num)) + "\n" + Value("Lightning damage", ArtifactBalance.LightningDamage(current), ArtifactBalance.LightningDamage(num), "x"), 
			_ => $"Effect stack {current} → {num}", 
		};
	}

	private static string Bonus(string label, float before, float after)
	{
		return $"{label}: +{Mathf.Max(0f, before - 1f) * 100f:0.#}% → +{Mathf.Max(0f, after - 1f) * 100f:0.#}%";
	}

	private static string Percent(string label, float before, float after)
	{
		return $"{label}: {before * 100f:0.#}% → {after * 100f:0.#}%";
	}

	private static string Value(string label, float before, float after, string suffix = "")
	{
		return $"{label}: {before:0.##}{suffix} → {after:0.##}{suffix}";
	}
}
[HarmonyPatch(typeof(LootContainerInteract), "ServerExecute")]
internal static class ThreeChoiceArtifactServerPatch
{
	private static bool Prefix(LootContainerInteract __instance, int fromClient)
	{
		if (!Plugin.Settings.EnableArtifactChoices.Value || !LocalClient.serverOwner)
		{
			return true;
		}
		return !ArtifactChoiceService.RegisterServerOffer(__instance, fromClient);
	}
}
[HarmonyPatch(typeof(LootContainerInteract), "LocalExecute")]
internal static class ThreeChoiceArtifactUiPatch
{
	private static void Postfix(LootContainerInteract __instance)
	{
		ArtifactChoiceOverlay.Show(__instance);
	}
}
[HarmonyPatch(typeof(Server), "InitializeServerPackets")]
internal static class ArtifactChoicePacketRegistrationPatch
{
	private static void Postfix()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		if (Server.PacketHandlers != null)
		{
			Server.PacketHandlers[240] = new PacketHandler(ArtifactChoiceService.HandleChoicePacket);
		}
	}
}
[HarmonyPatch(typeof(GameManager), "Awake")]
internal static class ResetArtifactOffersPatch
{
	private static void Prefix()
	{
		ArtifactChoiceService.Reset();
	}
}
[HarmonyPatch(typeof(ServerHandle), "DisconnectPlayer")]
internal static class RemoveDisconnectedArtifactOffersPatch
{
	private static void Prefix(int fromClient)
	{
		ArtifactChoiceService.ForgetPlayer(fromClient);
	}
}
internal static class BalanceCurves
{
	internal static float EnemyHealth(Difficulty difficulty, int day)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		day = Mathf.Max(0, day);
		if (day > 20)
		{
			return EnemyHealthBeforeSoftCap(difficulty, 20) * (1f + PostTwentyGrowth(difficulty) * (float)(day - 20));
		}
		return EnemyHealthBeforeSoftCap(difficulty, day);
	}

	internal static float EnemyDamage(Difficulty difficulty, int day)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		day = Mathf.Max(0, day);
		if (day > 20)
		{
			return EnemyDamageBeforeSoftCap(difficulty, 20) * (1f + PostTwentyGrowth(difficulty) * (float)(day - 20));
		}
		return EnemyDamageBeforeSoftCap(difficulty, day);
	}

	internal static float ChestPriceCap(Difficulty difficulty)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Invalid comparison between Unknown and I4
		if ((int)difficulty != 0)
		{
			if ((int)difficulty == 2)
			{
				return Plugin.Settings.GamerChestPriceCap.Value;
			}
			return Plugin.Settings.NormalChestPriceCap.Value;
		}
		return Plugin.Settings.EasyChestPriceCap.Value;
	}

	private static float EnemyHealthBeforeSoftCap(Difficulty difficulty, int day)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Invalid comparison between Unknown and I4
		float num = day;
		if ((int)difficulty != 0)
		{
			if ((int)difficulty == 2)
			{
				return 1.3f + 0.22f * num + 0.013f * num * num;
			}
			return 1.05f + 0.14f * num + 0.0048f * num * num;
		}
		return 0.9f + 0.1f * num + 0.0015f * num * num;
	}

	private static float EnemyDamageBeforeSoftCap(Difficulty difficulty, int day)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Invalid comparison between Unknown and I4
		float num = day;
		if ((int)difficulty != 0)
		{
			if ((int)difficulty == 2)
			{
				return 1.65f + 0.2f * num + 0.016f * num * num;
			}
			return 0.9f + 0.12f * num + 0.005f * num * num;
		}
		return 0.4f + 0.07f * num + 0.00075f * num * num;
	}

	private static float PostTwentyGrowth(Difficulty difficulty)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Invalid comparison between Unknown and I4
		if ((int)difficulty != 0)
		{
			if ((int)difficulty == 2)
			{
				return 0.035f;
			}
			return 0.025f;
		}
		return 0.015f;
	}
}
[HarmonyPatch(typeof(PlayerMovement), "Awake")]
internal static class PlayerMovementSpeedPatch
{
	private static readonly FieldInfo MoveSpeed = AccessTools.Field(typeof(PlayerMovement), "moveSpeed");

	private static readonly FieldInfo MaxWalkSpeed = AccessTools.Field(typeof(PlayerMovement), "maxWalkSpeed");

	private static readonly FieldInfo MaxRunSpeed = AccessTools.Field(typeof(PlayerMovement), "maxRunSpeed");

	private static readonly FieldInfo MaxSpeed = AccessTools.Field(typeof(PlayerMovement), "maxSpeed");

	private static readonly FieldInfo SwimSpeed = AccessTools.Field(typeof(PlayerMovement), "swimSpeed");

	private static void Postfix(PlayerMovement __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			float multiplier = Mathf.Clamp(Plugin.Settings.PlayerMoveSpeedMultiplier.Value, 0.5f, 3f);
			Scale(__instance, MoveSpeed, multiplier);
			Scale(__instance, MaxWalkSpeed, multiplier);
			Scale(__instance, MaxRunSpeed, multiplier);
			Scale(__instance, MaxSpeed, multiplier);
			Scale(__instance, SwimSpeed, multiplier);
		}
	}

	private static void Scale(PlayerMovement instance, FieldInfo field, float multiplier)
	{
		if (field != null)
		{
			field.SetValue(instance, (float)field.GetValue(instance) * multiplier);
		}
	}
}
[HarmonyPatch(typeof(PlayerStatus), "Awake")]
internal static class StaminaEconomyPatch
{
	private static readonly FieldInfo DrainRate = AccessTools.Field(typeof(PlayerStatus), "staminaDrainRate");

	private static readonly FieldInfo JumpDrain = AccessTools.Field(typeof(PlayerStatus), "jumpDrain");

	private static readonly FieldInfo RegenRate = AccessTools.Field(typeof(PlayerStatus), "staminaRegenRate");

	private static readonly FieldInfo HungerDrainRate = AccessTools.Field(typeof(PlayerStatus), "hungerDrainRate");

	private static void Postfix(PlayerStatus __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			float num = Mathf.Clamp(Plugin.Settings.StaminaDrainMultiplier.Value, 0f, 2f);
			if (DrainRate != null)
			{
				DrainRate.SetValue(__instance, (float)DrainRate.GetValue(__instance) * num);
			}
			if (JumpDrain != null)
			{
				JumpDrain.SetValue(__instance, (float)JumpDrain.GetValue(__instance) * Mathf.Clamp(Plugin.Settings.JumpStaminaMultiplier.Value, 0f, 2f));
			}
			if (RegenRate != null)
			{
				RegenRate.SetValue(__instance, (float)RegenRate.GetValue(__instance) * Mathf.Clamp(Plugin.Settings.StaminaRegenMultiplier.Value, 0.1f, 5f));
			}
			if (HungerDrainRate != null)
			{
				float num2 = Mathf.Clamp(Plugin.Settings.HungerDrainMultiplier.Value, 0f, 2f);
				HungerDrainRate.SetValue(__instance, (float)HungerDrainRate.GetValue(__instance) * num2);
			}
		}
	}
}
[HarmonyPatch(typeof(HitableResource), "Hit")]
internal static class ResourceDamagePatch
{
	private static bool Prefix(HitableResource __instance, ref int damage, int hitEffect, int hitWeaponType)
	{
		if (damage <= 0)
		{
			return true;
		}
		if (hitWeaponType != -1 && StructureUpgradeService.TryUseHammer(__instance))
		{
			return false;
		}
		switch (hitWeaponType)
		{
		case -1:
			if ((((Object)(object)__instance != (Object)null && ResourceManager.Instance?.builds != null && ResourceManager.Instance.builds.ContainsKey(((Hitable)__instance).GetId())) || ((Object)(object)__instance != (Object)null && ((Component)((Component)__instance).transform.root).CompareTag("Build"))) && hitEffect != 1)
			{
				damage = Mathf.Max(1, Mathf.RoundToInt((float)damage * Mathf.Clamp(Plugin.Settings.BuildDamageMultiplier.Value, 0.05f, 1f)));
			}
			return true;
		case 1:
			return true;
		default:
			damage = Mathf.Max(1, Mathf.RoundToInt((float)damage * Plugin.Settings.ResourceDamageMultiplier.Value));
			return true;
		}
	}
}
[HarmonyPatch(typeof(GameManager), "MobHpMultiplier")]
internal static class MobHealthCurvePatch
{
	private static void Postfix(GameManager __instance, ref float __result)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (Plugin.Settings.EnableDifficultyCurves.Value && GameManager.gameSettings != null)
		{
			__result = BalanceCurves.EnemyHealth(GameManager.gameSettings.difficulty, __instance.currentDay);
		}
	}
}
[HarmonyPatch(typeof(GameManager), "MobDamageMultiplier")]
internal static class MobDamageCurvePatch
{
	private static void Postfix(GameManager __instance, ref float __result)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (Plugin.Settings.EnableDifficultyCurves.Value && GameManager.gameSettings != null)
		{
			__result = BalanceCurves.EnemyDamage(GameManager.gameSettings.difficulty, __instance.currentDay);
		}
	}
}
[HarmonyPatch(typeof(GameManager), "ChestPriceMultiplier")]
internal static class ChestPriceCapPatch
{
	private static void Postfix(ref float __result)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (Plugin.Settings.EnableDifficultyCurves.Value && GameManager.gameSettings != null)
		{
			__result = Mathf.Min(__result, BalanceCurves.ChestPriceCap(GameManager.gameSettings.difficulty));
		}
	}
}
[HarmonyPatch(typeof(GameSettings), "DayLength")]
internal static class DayLengthPatch
{
	private static void Postfix(GameSettings __instance, ref int __result)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Invalid comparison between Unknown and I4
		if (!Plugin.Settings.EnableDifficultyCurves.Value)
		{
			return;
		}
		Difficulty difficulty = __instance.difficulty;
		if ((int)difficulty != 0)
		{
			if ((int)difficulty == 2)
			{
				__result = Mathf.RoundToInt((float)Plugin.Settings.GamerDayLength.Value * 1.3f);
			}
			else
			{
				__result = Mathf.RoundToInt((float)Plugin.Settings.NormalDayLength.Value * 1.3f);
			}
		}
		else
		{
			__result = Mathf.RoundToInt((float)Plugin.Settings.EasyDayLength.Value * 1.3f);
		}
	}
}
[HarmonyPatch(typeof(ItemManager), "InitAllItems")]
internal static class ItemEconomyPatch
{
	private static readonly HashSet<int> PatchedItems = new HashSet<int>();

	private static readonly HashSet<int> PatchedFuels = new HashSet<int>();

	private static void Postfix(ItemManager __instance)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Invalid comparison between Unknown and I4
		if (__instance.allScriptableItems == null)
		{
			return;
		}
		InventoryItem[] allScriptableItems = __instance.allScriptableItems;
		foreach (InventoryItem val in allScriptableItems)
		{
			if (!((Object)(object)val == (Object)null) && PatchedItems.Add(((Object)val).GetInstanceID()))
			{
				if (val.stackable && (int)val.type == 0)
				{
					val.max = Mathf.Max(val.max, Plugin.Settings.MaterialStackSize.Value);
				}
				if (val.stackable && (int)val.tag == 8)
				{
					val.max = Mathf.Max(val.max, Plugin.Settings.ArrowStackSize.Value);
				}
				if (val.processable && val.processTime > 0f)
				{
					val.processTime = Mathf.Max(0.1f, val.processTime * Plugin.Settings.SmeltTimeMultiplier.Value);
				}
				if ((Object)(object)val.fuel != (Object)null && PatchedFuels.Add(((Object)val.fuel).GetInstanceID()))
				{
					val.fuel.maxUses = Mathf.Max(1, Mathf.RoundToInt((float)val.fuel.maxUses * Plugin.Settings.FuelUseMultiplier.Value));
				}
			}
		}
		Plugin.Log.LogInfo((object)"Applied stack, smelting, and fuel economy changes.");
	}
}
internal static class BedRegistry
{
	private const string AssetName = "MuckReplayable_Bed";

	private static Mesh mesh;

	internal static InventoryItem Item { get; private set; }

	internal static void Install(ItemManager manager)
	{
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Expected O, but got Unknown
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Unknown result type (might be due to invalid IL or missing references)
		if (manager?.allItems == null || manager.allScriptableItems == null)
		{
			return;
		}
		Item = ((IEnumerable<InventoryItem>)manager.allItems.Values).FirstOrDefault((Func<InventoryItem, bool>)((InventoryItem value) => (Object)(object)value != (Object)null && ((Object)value).name == "MuckReplayable_Bed"));
		if ((Object)(object)Item != (Object)null)
		{
			return;
		}
		InventoryItem val = ((IEnumerable<InventoryItem>)manager.allItems.Values).FirstOrDefault((Func<InventoryItem, bool>)((InventoryItem value) => (Object)(object)value != (Object)null && value.name == "Wood Floor"));
		InventoryItem val2 = ((IEnumerable<InventoryItem>)manager.allItems.Values).FirstOrDefault((Func<InventoryItem, bool>)((InventoryItem value) => (Object)(object)value != (Object)null && value.name == "Wood"));
		InventoryItem val3 = ((IEnumerable<InventoryItem>)manager.allItems.Values).FirstOrDefault((Func<InventoryItem, bool>)((InventoryItem value) => (Object)(object)value != (Object)null && value.name == "Workbench"));
		if ((Object)(object)val?.prefab == (Object)null || (Object)(object)val.material == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Bed registration skipped because a vanilla source asset was unavailable.");
			return;
		}
		mesh = (((Object)(object)mesh != (Object)null) ? mesh : CreateBedMesh());
		InventoryItem val4 = ScriptableObject.CreateInstance<InventoryItem>();
		((Object)val4).name = "MuckReplayable_Bed";
		val4.id = manager.allItems.Keys.Max() + 1;
		val4.name = "Bed";
		val4.description = "Sleep at night. When every living player is in a bed, night passes seven times faster.";
		val4.type = (ItemType)0;
		val4.tag = (ItemTag)0;
		val4.tier = 1;
		val4.stackable = true;
		val4.max = 20;
		val4.amount = 1;
		val4.craftable = true;
		val4.craftAmount = 1;
		val4.stationRequirement = val3;
		val4.requirements = (CraftRequirement[])(object)new CraftRequirement[1]
		{
			new CraftRequirement
			{
				item = val2,
				amount = 15
			}
		};
		val4.mesh = mesh;
		val4.material = Object.Instantiate<Material>(val.material);
		((Object)val4.material).name = "Muck Replayable Bed Material";
		if (val4.material.HasProperty("_Color"))
		{
			val4.material.color = new Color(0.63f, 0.25f, 0.18f);
		}
		val4.sprite = CreateIcon();
		val4.rotationOffset = new Vector3(12f, 35f, -8f);
		val4.positionOffset = new Vector3(-0.05f, -0.34f, 0.48f);
		val4.scale = 0.32f;
		val4.buildable = true;
		val4.grid = true;
		val4.buildRotation = val.buildRotation;
		val4.prefab = CreatePrefab(val.prefab, manager, val4.material);
		val4.attackTypes = Array.Empty<Weakness>();
		Object.DontDestroyOnLoad((Object)(object)val4);
		Object.DontDestroyOnLoad((Object)(object)val4.material);
		manager.allItems[val4.id] = val4;
		manager.allScriptableItems = manager.allScriptableItems.Concat((IEnumerable<InventoryItem>)(object)new InventoryItem[1] { val4 }).ToArray();
		Item = val4;
		Plugin.Log.LogInfo((object)$"Registered craftable Bed (item ID {val4.id}).");
	}

	internal static void InjectCrafting(CraftingUI crafting)
	{
		if ((Object)(object)Item == (Object)null || crafting?.tabs == null || ((object)OtherInput.Instance?.workbench != crafting && !crafting.tabs.Any((Tab tab) => (tab?.items ?? Array.Empty<InventoryItem>()).Any((InventoryItem value) => (Object)(object)value != (Object)null && value.name == "Wood Axe"))))
		{
			return;
		}
		for (int num = 0; num < crafting.tabs.Length; num++)
		{
			InventoryItem[] array = crafting.tabs[num]?.items ?? Array.Empty<InventoryItem>();
			if (array.Any((InventoryItem value) => (Object)(object)value != (Object)null && value.name == "Wood Floor") && array.Any((InventoryItem value) => (Object)(object)value != (Object)null && (value.name == "Wood Wall" || value.name == "Workbench")))
			{
				crafting.tabs[num].items = (from value in array.Concat((IEnumerable<InventoryItem>)(object)new InventoryItem[1] { Item })
					where (Object)(object)value != (Object)null
					group value by value.id into @group
					select @group.First()).ToArray();
				return;
			}
		}
		if (crafting.tabs.Length != 0)
		{
			int num2 = crafting.tabs.Length - 1;
			InventoryItem[] first = crafting.tabs[num2]?.items ?? Array.Empty<InventoryItem>();
			crafting.tabs[num2].items = (from value in first.Concat((IEnumerable<InventoryItem>)(object)new InventoryItem[1] { Item })
				where (Object)(object)value != (Object)null
				group value by value.id into @group
				select @group.First()).ToArray();
		}
	}

	internal static bool IsCraftingReady()
	{
		if ((Object)(object)Item != (Object)null)
		{
			return Resources.FindObjectsOfTypeAll<CraftingUI>().Any((CraftingUI crafting) => (crafting?.tabs ?? Array.Empty<Tab>()).Any(delegate(Tab tab)
			{
				InventoryItem[] source = tab?.items ?? Array.Empty<InventoryItem>();
				return source.Any((InventoryItem value) => (Object)(object)value != (Object)null && value.id == Item.id) && source.Any((InventoryItem value) => (Object)(object)value != (Object)null && value.name == "Wood Floor");
			}));
		}
		return false;
	}

	private static GameObject CreatePrefab(GameObject source, ItemManager manager, Material material)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(source);
		((Object)val).name = "Muck Replayable Bed Prefab";
		Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			componentsInChildren[i].enabled = false;
		}
		GameObject val2 = new GameObject("Bed Visual");
		val2.transform.SetParent(val.transform, false);
		val2.AddComponent<MeshFilter>().sharedMesh = mesh;
		((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterial = material;
		GameObject val3 = new GameObject("Bed Interaction");
		val3.transform.SetParent(val.transform, false);
		val3.transform.localPosition = new Vector3(0f, 0.55f, 0f);
		BoxCollider obj = val3.AddComponent<BoxCollider>();
		((Collider)obj).isTrigger = true;
		obj.size = new Vector3(1.8f, 1.2f, 3.2f);
		InventoryItem? obj2 = ((IEnumerable<InventoryItem>)manager.allItems.Values).FirstOrDefault((Func<InventoryItem, bool>)((InventoryItem value) => (Object)(object)value != (Object)null && value.name == "Chest"));
		object obj3;
		if (obj2 == null)
		{
			obj3 = null;
		}
		else
		{
			GameObject prefab = obj2.prefab;
			obj3 = ((prefab != null) ? prefab.GetComponentInChildren<ChestInteract>(true) : null);
		}
		ChestInteract val4 = (ChestInteract)obj3;
		val3.layer = (((Object)(object)val4 != (Object)null) ? ((Component)val4).gameObject.layer : val.layer);
		val3.AddComponent<BedInteract>();
		val.transform.position = Vector3.down * 10000f;
		val.SetActive(false);
		Object.DontDestroyOnLoad((Object)(object)val);
		return val;
	}

	private static Mesh CreateBedMesh()
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Expected O, but got Unknown
		//IL_0103: Expected O, but got Unknown
		List<Vector3> list = new List<Vector3>();
		List<int> list2 = new List<int>();
		AddBox(list, list2, new Vector3(0f, 0.35f, 0f), new Vector3(1.8f, 0.35f, 3.2f));
		AddBox(list, list2, new Vector3(0f, 0.72f, -1.32f), new Vector3(1.9f, 1.15f, 0.22f));
		AddBox(list, list2, new Vector3(-0.72f, 0.12f, 0f), new Vector3(0.18f, 0.65f, 3.1f));
		AddBox(list, list2, new Vector3(0.72f, 0.12f, 0f), new Vector3(0.18f, 0.65f, 3.1f));
		Mesh val = new Mesh
		{
			name = "Muck Replayable Bed Mesh",
			vertices = list.ToArray(),
			triangles = list2.ToArray()
		};
		val.RecalculateNormals();
		val.RecalculateBounds();
		Object.DontDestroyOnLoad((Object)val);
		return val;
	}

	private static void AddBox(List<Vector3> vertices, List<int> triangles, Vector3 center, Vector3 size)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: 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_0117: 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_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		int start = vertices.Count;
		Vector3 val = size * 0.5f;
		vertices.AddRange((IEnumerable<Vector3>)(object)new Vector3[8]
		{
			center + new Vector3(0f - val.x, 0f - val.y, 0f - val.z),
			center + new Vector3(val.x, 0f - val.y, 0f - val.z),
			center + new Vector3(val.x, val.y, 0f - val.z),
			center + new Vector3(0f - val.x, val.y, 0f - val.z),
			center + new Vector3(0f - val.x, 0f - val.y, val.z),
			center + new Vector3(val.x, 0f - val.y, val.z),
			center + new Vector3(val.x, val.y, val.z),
			center + new Vector3(0f - val.x, val.y, val.z)
		});
		int[] source = new int[36]
		{
			0, 2, 1, 0, 3, 2, 4, 5, 6, 4,
			6, 7, 0, 1, 5, 0, 5, 4, 3, 7,
			6, 3, 6, 2, 1, 2, 6, 1, 6, 5,
			0, 4, 7, 0, 7, 3
		};
		triangles.AddRange(source.Select((int value) => start + value));
	}

	private static Sprite CreateIcon()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
		{
			name = "Bed Icon",
			filterMode = (FilterMode)0
		};
		Color[] array = Enumerable.Repeat<Color>(Color.clear, 4096).ToArray();
		for (int i = 16; i < 46; i++)
		{
			for (int j = 8; j < 56; j++)
			{
				array[i * 64 + j] = ((i > 38) ? new Color(0.34f, 0.18f, 0.09f) : new Color(0.75f, 0.24f, 0.18f));
			}
		}
		for (int k = 38; k < 50; k++)
		{
			for (int l = 8; l < 20; l++)
			{
				array[k * 64 + l] = new Color(0.92f, 0.83f, 0.65f);
			}
		}
		val.SetPixels(array);
		val.Apply(false, true);
		Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
		Object.DontDestroyOnLoad((Object)(object)val);
		Object.DontDestroyOnLoad((Object)(object)obj);
		return obj;
	}
}
internal sealed class BedInteract : MonoBehaviour, Interactable
{
	public void Interact()
	{
		HitableResource componentInChildren = ((Component)((Component)this).transform.root).GetComponentInChildren<HitableResource>();
		if ((Object)(object)componentInChildren != (Object)null)
		{
			SleepService.RequestLocal(((Hitable)componentInChildren).GetId());
		}
	}

	public void LocalExecute()
	{
	}

	public void AllExecute()
	{
	}

	public void ServerExecute(int fromClient = -1)
	{
	}

	public void RemoveObject()
	{
	}

	public string GetName()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		if (!SleepService.IsNight)
		{
			return "Bed\n<size=50%>(Can only sleep at night)";
		}
		return $"Sleep\n<size=50%>(Press \"{InputManager.interact}\")";
	}

	public bool IsStarted()
	{
		return false;
	}
}
internal static class SleepService
{
	internal const int RequestPacketId = 248;

	internal const int SyncPacketId = 249;

	private static readonly HashSet<int> Sleeping = new HashSet<int>();

	private static readonly Dictionary<int, int> Beds = new Dictionary<int, int>();

	private static readonly MethodInfo ClientSendTcp = AccessTools.Method(typeof(ClientSend), "SendTCPData", new Type[1] { typeof(Packet) }, (Type[])null);

	private static readonly MethodInfo ServerSendAll = AccessTools.Method(typeof(ServerSend), "SendTCPDataToAll", new Type[1] { typeof(Packet) }, (Type[])null);

	internal static bool IsNight
	{
		get
		{
			if (DayCycle.time > 0.5f)
			{
				return DayCycle.time < 0.99f;
			}
			return false;
		}
	}

	internal static bool LocalSleeping
	{
		get
		{
			if ((Object)(object)LocalClient.instance != (Object)null)
			{
				return Sleeping.Contains(LocalClient.instance.myId);
			}
			return false;
		}
	}

	internal static bool FastNight
	{
		get
		{
			if (!IsNight || GameManager.players == null)
			{
				return false;
			}
			int[] array = (from player in GameManager.players.Values
				where (Object)(object)player != (Object)null && !player.dead && !player.disconnected
				select player.id).ToArray();
			if (array.Length != 0)
			{
				return array.All(Sleeping.Contains);
			}
			return false;
		}
	}

	internal static void Reset()
	{
		Sleeping.Clear();
		Beds.Clear();
	}

	internal static void RequestLocal(int bedId)
	{
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Expected O, but got Unknown
		if ((Object)(object)LocalClient.instance == (Object)null || (Object)(object)GameManager.instance == (Object)null)
		{
			return;
		}
		bool flag = !LocalSleeping;
		if (flag && !IsNight)
		{
			ReforgedRuntime.Instance?.Notify("Beds can only be used at night.", 3f);
			return;
		}
		if (LocalClient.serverOwner)
		{
			SetServer(LocalClient.instance.myId, bedId, flag);
			return;
		}
		Packet val = new Packet(248);
		try
		{
			val.Write(bedId);
			val.Write(flag);
			ClientSendTcp?.Invoke(null, new object[1] { val });
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	internal static void ReceiveRequest(int fromClient, Packet packet)
	{
		try
		{
			SetServer(fromClient, packet.ReadInt(true), packet.ReadBool(true));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Rejected bed request: " + ex.Message));
		}
	}

	private static void SetServer(int playerId, int bedId, bool sleep)
	{
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		if (sleep)
		{
			if (!IsNight || !GameManager.players.TryGetValue(playerId, out var value) || (Object)(object)value == (Object)null || value.dead || ResourceManager.Instance?.list == null || !ResourceManager.Instance.list.TryGetValue(bedId, out var value2) || (Object)(object)value2.GetComponentInChildren<BedInteract>() == (Object)null || Beds.Any((KeyValuePair<int, int> pair) => pair.Key != playerId && pair.Value == bedId) || (Server.clients.TryGetValue(playerId, out var value3) && value3?.player != null && Vector3.Distance(value3.player.pos, value2.transform.position) > 8f))
			{
				return;
			}
			Sleeping.Add(playerId);
			Beds[playerId] = bedId;
		}
		else
		{
			Sleeping.Remove(playerId);
			Beds.Remove(playerId);
		}
		Broadcast(playerId, bedId, sleep);
	}

	private static void Broadcast(int playerId, int bedId, bool sleeping)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		Packet val = new Packet(249);
		try
		{
			val.Write(playerId);
			val.Write(bedId);
			val.Write(sleeping);
			ServerSendAll?.Invoke(null, new object[1] { val });
			ApplyState(playerId, bedId, sleeping);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	internal static void ReceiveSync(Packet packet)
	{
		try
		{
			ApplyState(packet.ReadInt(true), packet.ReadInt(true), packet.ReadBool(true));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Rejected bed state: " + ex.Message));
		}
	}

	private static void ApplyState(int playerId, int bedId, bool sleeping)
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		if (sleeping)
		{
			Sleeping.Add(playerId);
			Beds[playerId] = bedId;
		}
		else
		{
			Sleeping.Remove(playerId);
			Beds.Remove(playerId);
		}
		if (sleeping && (Object)(object)LocalClient.instance != (Object)null && playerId == LocalClient.instance.myId && ResourceManager.Instance?.list != null && ResourceManager.Instance.list.TryGetValue(bedId, out var value) && (Object)(object)PlayerMovement.Instance != (Object)null)
		{
			((Component)PlayerMovement.Instance).transform.position = value.transform.position + Vector3.up * 1.05f;
			PlayerMovement.Instance.GetRb().velocity = Vector3.zero;
		}
	}

	internal static void WakeLocal()
	{
		if (LocalSleeping && Beds.TryGetValue(LocalClient.instance.myId, out var value))
		{
			RequestLocal(value);
		}
	}

	internal static void ValidateServerState()
	{
		if (!LocalClient.serverOwner)
		{
			return;
		}
		int[] array = Sleeping.ToArray();
		foreach (int num in array)
		{
			if (!IsNight || !GameManager.players.TryGetValue(num, out var value) || !((Object)(object)value != (Object)null) || value.dead || !Beds.TryGetValue(num, out var value2) || ResourceManager.Instance?.list == null || !ResourceManager.Instance.list.ContainsKey(value2))
			{
				SetServer(num, Beds.TryGetValue(num, out var value3) ? value3 : (-1), sleep: false);
			}
		}
	}

	internal static void ApplyRemotePose()
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		if (GameManager.players == null)
		{
			return;
		}
		foreach (PlayerManager value in GameManager.players.Values)
		{
			if (!((Object)(object)value?.onlinePlayer?.upperBody == (Object)null))
			{
				Vector3 localEulerAngles = value.onlinePlayer.upperBody.localEulerAngles;
				localEulerAngles.z = (Sleeping.Contains(value.id) ? 88f : 0f);
				value.onlinePlayer.upperBody.localEulerAngles = localEulerAngles;
			}
		}
	}
}
[DefaultExecutionOrder(11000)]
internal sealed class SleepController : MonoBehaviour
{
	private bool inputSuppressed;

	private float nextValidation;

	private void Update()
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: 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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		if (Time.unscaledTime >= nextValidation)
		{
			nextValidation = Time.unscaledTime + 0.25f;
			SleepService.ValidateServerState();
		}
		bool localSleeping = SleepService.LocalSleeping;
		if (localSleeping && !inputSuppressed && (Object)(object)PlayerInput.Instance != (Object)null)
		{
			inputSuppressed = true;
			PlayerInput.Instance.active = false;
			ReforgedRuntime.Instance?.Notify("Sleeping… everyone asleep makes night pass ×7. Press E or a movement key to wake.", 5f);
		}
		if (localSleeping && (Input.GetKeyDown(InputManager.interact) || Input.GetKeyDown(InputManager.forward) || Input.GetKeyDown(InputManager.backwards) || Input.GetKeyDown(InputManager.left) || Input.GetKeyDown(InputManager.right) || Input.GetKeyDown(InputManager.jump)))
		{
			SleepService.WakeLocal();
		}
		if (!localSleeping && inputSuppressed)
		{
			inputSuppressed = false;
			if ((Object)(object)PlayerInput.Instance != (Object)null)
			{
				PlayerInput.Instance.active = true;
			}
		}
		SleepService.ApplyRemotePose();
	}

	private void LateUpdate()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		if (SleepService.LocalSleeping && !((Object)(object)MoveCamera.Instance == (Object)null))
		{
			((Component)MoveCamera.Instance).transform.position = ((Component)PlayerMovement.Instance).transform.position + Vector3.up * 0.65f;
			Transform transform = ((Component)MoveCamera.Instance).transform;
			transform.rotation *= Quaternion.Euler(0f, 0f, 78f);
		}
	}
}
[HarmonyPatch(typeof(Server), "InitializeServerPackets")]
internal static class BedServerPacketPatch
{
	private static void Postfix()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		if (Server.PacketHandlers != null)
		{
			Server.PacketHandlers[248] = new PacketHandler(SleepService.ReceiveRequest);
		}
	}
}
[HarmonyPatch(typeof(LocalClient), "InitializeClientData")]
internal static class BedClientPacketPatch
{
	private static void Postfix()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown