Decompiled source of Rewards v1.0.0

plugins/Rewards.dll

Decompiled 2 days ago
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Buffers.Text;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Numerics.Hashing;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BiomeLockAPI;
using FxResources.System.Buffers;
using FxResources.System.Memory;
using FxResources.System.Numerics.Vectors;
using HarmonyLib;
using JetBrains.Annotations;
using LiteDB;
using LiteDB.Client.Shared;
using LiteDB.Engine;
using LiteDB.Utils;
using LiteDB.Utils.Extensions;
using LiteDB.Vector;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using Microsoft.Win32.SafeHandles;
using ServerSync;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyProduct("Rewards")]
[assembly: AssemblyCompany("radamanto")]
[assembly: AssemblyDescription("Recompensas por tempo de jogo ativo para Valheim.")]
[assembly: AssemblyTitle("Rewards")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: <f054822c-6861-4e8c-93d2-160cfbebcb0b>RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<0fcf8a3a-6581-4007-998b-549f183b241f>Embedded]
	internal sealed class <0fcf8a3a-6581-4007-998b-549f183b241f>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[<0fcf8a3a-6581-4007-998b-549f183b241f>Embedded]
	[CompilerGenerated]
	internal sealed class <708e428e-57cb-4a78-8091-80df3604fcfc>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <708e428e-57cb-4a78-8091-80df3604fcfc>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <708e428e-57cb-4a78-8091-80df3604fcfc>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	[<0fcf8a3a-6581-4007-998b-549f183b241f>Embedded]
	internal sealed class <9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	[<0fcf8a3a-6581-4007-998b-549f183b241f>Embedded]
	[CompilerGenerated]
	internal sealed class <f054822c-6861-4e8c-93d2-160cfbebcb0b>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <f054822c-6861-4e8c-93d2-160cfbebcb0b>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		private static BaseUnityPlugin _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		[method: <9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(2)]
		[field: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		public static event Action OnLocalizationComplete;

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out var value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out var value2))
			{
				text = value2.Aggregate(text, [<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null)
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += [<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(0)] (object _, EventArgs _) =>
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value);
				UpdatePlaceholderText(Localization.instance, key);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			_ = plugin;
		}

		public static void LoadLocalizationLater(Localization __instance)
		{
			LoadLocalization(Localization.instance, __instance.GetSelectedLanguage());
		}

		public static void SafeCallLocalizeComplete()
		{
			Localizer.OnLocalizationComplete?.Invoke();
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' });
				if (array.Length >= 2)
				{
					string text = array[1];
					if (dictionary.ContainsKey(text))
					{
						Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
					}
					else
					{
						dictionary[text] = item;
					}
				}
			}
			byte[] array2 = LoadTranslationFromAssembly("English");
			if (array2 == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.TryGetValue(language, out var value))
				{
					text2 = File.ReadAllText(value);
				}
				else
				{
					byte[] array3 = LoadTranslationFromAssembly(language);
					if (array3 != null)
					{
						text2 = Encoding.UTF8.GetString(array3);
					}
				}
			}
			if (text2 == null && dictionary.TryGetValue("English", out var value2))
			{
				text2 = File.ReadAllText(value2);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_004e: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string>(2) { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		[return: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		private static byte[] LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(2)]
		public static byte[] ReadEmbeddedFileBytes([<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(1)] string resourceFileName, Assembly containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(0)] (string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
	public static class LocalizationManagerVersion
	{
		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(1)]
		public const string Version = "1.4.1";
	}
}
namespace Rewards
{
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	internal static class RewardsActivity
	{
		private const float ReportInterval = 60f;

		private static readonly ActivityWindow Window = new ActivityWindow();

		private static float _nextReport = -1f;

		private static Vector3 _lastPosition;

		private static bool _hasPosition;

		private static Quaternion _lastRotation;

		private static bool _hasRotation;

		private static bool LocalReady
		{
			get
			{
				if ((Object)(object)Player.m_localPlayer != (Object)null && !((Character)Player.m_localPlayer).IsDead())
				{
					return RewardsClient.Connected;
				}
				return false;
			}
		}

		internal static void Action(ActivityKind kind)
		{
			if (LocalReady)
			{
				Window.AddAction(kind);
				Window.MarkInput(Time.realtimeSinceStartupAsDouble);
			}
		}

		internal static void Target(Object target)
		{
			if (LocalReady && Object.op_Implicit(target))
			{
				Window.AddTarget(target.GetInstanceID());
			}
		}

		internal static bool FromLocal(HitData hit)
		{
			//IL_0011: 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)
			if ((Object)(object)Player.m_localPlayer != (Object)null && hit != null)
			{
				return hit.m_attacker == ((Character)Player.m_localPlayer).GetZDOID();
			}
			return false;
		}

		internal static void Tick()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_0068: 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_0109: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if (!LocalReady)
			{
				_hasPosition = false;
				_hasRotation = false;
				_nextReport = -1f;
				Window.Reset();
				return;
			}
			double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
			Vector2 mouseDelta = ZInput.GetMouseDelta();
			if (((Vector2)(ref mouseDelta)).sqrMagnitude > 0f)
			{
				Window.MarkInput(realtimeSinceStartupAsDouble);
			}
			Player localPlayer = Player.m_localPlayer;
			Vector3 position = ((Component)localPlayer).transform.position;
			if (_hasPosition)
			{
				float num = Vector3.Distance(position, _lastPosition);
				if (num < 20f)
				{
					Window.AddMove(num);
					bool flag = ((Character)localPlayer).IsAttachedToShip() || (Object)(object)((Character)localPlayer).GetStandingOnShip() != (Object)null;
					if (num > 0.01f && !flag)
					{
						Window.AddAction(ActivityKind.Move);
						Window.MarkInput(realtimeSinceStartupAsDouble);
					}
				}
			}
			_lastPosition = position;
			_hasPosition = true;
			GameCamera instance = GameCamera.instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				Quaternion rotation = ((Component)instance).transform.rotation;
				if (_hasRotation)
				{
					Window.AddCameraTurn(Quaternion.Angle(rotation, _lastRotation));
				}
				_lastRotation = rotation;
				_hasRotation = true;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (_nextReport < 0f)
			{
				_nextReport = realtimeSinceStartup + 60f;
			}
			if (!(realtimeSinceStartup < _nextReport))
			{
				_nextReport = realtimeSinceStartup + 60f;
				bool flag2 = Window.IsValid(RewardsPlugin.CE_ActivityMinCriteria.Value, realtimeSinceStartupAsDouble, (double)RewardsPlugin.CE_IdleMinutes.Value * 60.0) && !RewardsClient.TimeLocked;
				Window.Reset();
				RewardsRpc.ToServer("Rewards_Minute", flag2);
			}
		}
	}
	internal struct Vector3Like
	{
		public float X;

		public float Y;

		public float Z;
	}
	internal sealed class MinuteGate
	{
		private const double MinInterval = 55.0;

		private const double StillRadius = 2.0;

		private double _lastAccepted = double.NegativeInfinity;

		private double _anchorSince;

		private Vector3Like _anchor;

		private bool _hasAnchor;

		internal bool Accept(double now, Vector3Like position, int stillMinutes)
		{
			if (!_hasAnchor || Distance(_anchor, position) >= 2.0)
			{
				_anchor = position;
				_anchorSince = now;
				_hasAnchor = true;
			}
			if (now - _lastAccepted < 55.0)
			{
				return false;
			}
			if (now - _anchorSince >= (double)stillMinutes * 60.0)
			{
				return false;
			}
			_lastAccepted = now;
			return true;
		}

		private static double Distance(Vector3Like a, Vector3Like b)
		{
			double num = a.X - b.X;
			double num2 = a.Y - b.Y;
			double num3 = a.Z - b.Z;
			return Math.Sqrt(num * num + num2 * num2 + num3 * num3);
		}
	}
	[HarmonyPatch(typeof(Character), "Jump")]
	internal static class Character_Jump_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Character __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				RewardsActivity.Action(ActivityKind.Jump);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "StartAttack")]
	internal static class Humanoid_StartAttack_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Humanoid __instance, bool __result)
		{
			if (__result && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				RewardsActivity.Action(ActivityKind.Attack);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "BlockAttack")]
	internal static class Humanoid_BlockAttack_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Humanoid __instance, bool __result)
		{
			if (__result && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				RewardsActivity.Action(ActivityKind.Block);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "Pickup")]
	internal static class Humanoid_Pickup_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Humanoid __instance, GameObject go, bool __result)
		{
			if (__result && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				RewardsActivity.Action(ActivityKind.Pickup);
				RewardsActivity.Target((Object)(object)go);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "PlacePiece")]
	internal static class Player_PlacePiece_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				RewardsActivity.Action(ActivityKind.Build);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Interact")]
	internal static class Player_Interact_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Player __instance, GameObject go)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)go))
			{
				RewardsActivity.Action(ActivityKind.Interact);
				RewardsActivity.Target((Object)(object)go);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "EatFood")]
	internal static class Player_EatFood_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Player __instance, bool __result)
		{
			if (__result && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				RewardsActivity.Action(ActivityKind.Eat);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Show")]
	internal static class InventoryGui_Show_Activity
	{
		private static void Postfix()
		{
			RewardsActivity.Action(ActivityKind.Inventory);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
	internal static class InventoryGui_DoCrafting_Activity
	{
		private static void Postfix()
		{
			RewardsActivity.Action(ActivityKind.Craft);
		}
	}
	[HarmonyPatch(typeof(ShipControlls), "ApplyControlls")]
	internal static class ShipControlls_ApplyControlls_Activity
	{
		private static void Postfix(Vector3 moveDir)
		{
			//IL_0000: 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)
			if (Mathf.Abs(moveDir.x) > 0.1f)
			{
				RewardsActivity.Action(ActivityKind.Steer);
			}
			if (Mathf.Abs(moveDir.z) > 0.1f)
			{
				RewardsActivity.Action(ActivityKind.Sail);
			}
		}
	}
	[HarmonyPatch(typeof(Chat), "SendText")]
	internal static class Chat_SendText_Activity
	{
		private static void Postfix()
		{
			RewardsActivity.Action(ActivityKind.Chat);
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class Character_Damage_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Character __instance, HitData hit)
		{
			if (RewardsActivity.FromLocal(hit))
			{
				RewardsActivity.Target((Object)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Damage")]
	internal static class WearNTear_Damage_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(WearNTear __instance, HitData hit)
		{
			if (RewardsActivity.FromLocal(hit))
			{
				RewardsActivity.Target((Object)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Destructible), "Damage")]
	internal static class Destructible_Damage_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(Destructible __instance, HitData hit)
		{
			if (RewardsActivity.FromLocal(hit))
			{
				RewardsActivity.Target((Object)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(TreeBase), "Damage")]
	internal static class TreeBase_Damage_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(TreeBase __instance, HitData hit)
		{
			if (RewardsActivity.FromLocal(hit))
			{
				RewardsActivity.Target((Object)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(TreeLog), "Damage")]
	internal static class TreeLog_Damage_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(TreeLog __instance, HitData hit)
		{
			if (RewardsActivity.FromLocal(hit))
			{
				RewardsActivity.Target((Object)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(MineRock), "Damage")]
	internal static class MineRock_Damage_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(MineRock __instance, HitData hit)
		{
			if (RewardsActivity.FromLocal(hit))
			{
				RewardsActivity.Target((Object)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(MineRock5), "Damage")]
	internal static class MineRock5_Damage_Activity
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(MineRock5 __instance, HitData hit)
		{
			if (RewardsActivity.FromLocal(hit))
			{
				RewardsActivity.Target((Object)(object)__instance);
			}
		}
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	internal sealed class PresenceState
	{
		private readonly Random _random;

		private long _nextToken;

		internal double NextAt { get; private set; }

		internal long? Token { get; private set; }

		internal double Deadline { get; private set; }

		internal PresenceState(Random random)
		{
			_random = random;
			_nextToken = random.Next(1, int.MaxValue);
		}

		internal void Start(double now, int minMinutes, int maxMinutes)
		{
			Token = null;
			Deadline = 0.0;
			int num = Math.Max(1, Math.Min(minMinutes, maxMinutes));
			int num2 = Math.Max(1, Math.Max(minMinutes, maxMinutes));
			NextAt = now + ((double)num + _random.NextDouble() * (double)(num2 - num)) * 60.0;
		}

		internal long? Due(double now, int responseMinutes)
		{
			if (Token.HasValue || now < NextAt)
			{
				return null;
			}
			Token = (_nextToken += 1L);
			Deadline = now + (double)Math.Max(1, responseMinutes) * 60.0;
			return Token;
		}

		internal bool Ack(long token, double now, int minMinutes, int maxMinutes)
		{
			if (!Token.HasValue || Token.Value != token)
			{
				return false;
			}
			Start(now, minMinutes, maxMinutes);
			return true;
		}

		internal bool Counts(double now)
		{
			if (Token.HasValue)
			{
				return now <= Deadline;
			}
			return true;
		}
	}
	internal enum ActivityKind
	{
		Move,
		Jump,
		Attack,
		Block,
		Build,
		Pickup,
		Interact,
		Inventory,
		Chat,
		Eat,
		Craft,
		Sail,
		Steer
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	internal sealed class ActivityWindow
	{
		private const float MinMove = 8f;

		private const float MinTurn = 90f;

		private readonly HashSet<ActivityKind> _kinds = new HashSet<ActivityKind>();

		private readonly HashSet<int> _targets = new HashSet<int>();

		private float _moved;

		private float _turned;

		private double _lastInput = double.NegativeInfinity;

		internal void AddMove(float meters)
		{
			_moved += meters;
		}

		internal void AddCameraTurn(float degrees)
		{
			_turned += degrees;
		}

		internal void AddAction(ActivityKind kind)
		{
			_kinds.Add(kind);
		}

		internal void AddTarget(int instanceId)
		{
			_targets.Add(instanceId);
		}

		internal void MarkInput(double time)
		{
			_lastInput = time;
		}

		internal bool IsValid(int minCriteria, double now, double idleSeconds)
		{
			if (now - _lastInput >= idleSeconds)
			{
				return false;
			}
			int num = 0;
			if (_moved >= 8f)
			{
				num++;
			}
			if (_turned >= 90f)
			{
				num++;
			}
			if (_kinds.Count >= 2)
			{
				num++;
			}
			if (_targets.Count >= 2)
			{
				num++;
			}
			return num >= minCriteria;
		}

		internal void Reset()
		{
			_kinds.Clear();
			_targets.Clear();
			_moved = 0f;
			_turned = 0f;
		}
	}
	internal static class RewardsBiomeLock
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		internal static bool Has(string key)
		{
			return API.HasProgressionKey(key);
		}
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	internal static class RewardsDatabase
	{
		private const string Collection = "players";

		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		private static LiteDatabase _database;

		private static readonly BsonMapper Mapper = new BsonMapper
		{
			EmptyStringToNull = false,
			TrimWhitespace = false
		};

		private static LiteDatabase Open()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				throw new InvalidOperationException("Database access requires an active server.");
			}
			if (_database != null)
			{
				return _database;
			}
			Directory.CreateDirectory(RewardsPaths.SavedDataFolder);
			if (File.Exists(RewardsPaths.DatabaseFile) && new FileInfo(RewardsPaths.DatabaseFile).Length < 8192)
			{
				throw new InvalidDataException("Existing database is empty or truncated.");
			}
			_database = new LiteDatabase(new ConnectionString
			{
				Filename = RewardsPaths.DatabaseFile
			}, Mapper);
			return _database;
		}

		[return: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		internal static PlayerRecord Load(string id)
		{
			try
			{
				return Open().GetCollection<PlayerRecord>("players").FindById(new BsonValue(id)) ?? new PlayerRecord
				{
					Id = id
				};
			}
			catch (Exception ex)
			{
				RewardsPlugin.Log.LogError((object)("[Database] Failed to load " + id + ": " + ex.Message));
				Close();
				return null;
			}
		}

		internal static bool Save(PlayerRecord record)
		{
			try
			{
				Open().GetCollection<PlayerRecord>("players").Upsert(record);
				return true;
			}
			catch (Exception ex)
			{
				RewardsPlugin.Log.LogError((object)("[Database] Failed to save " + record.Id + ": " + ex.Message));
				Close();
				return false;
			}
		}

		internal static void Close()
		{
			LiteDatabase database = _database;
			_database = null;
			try
			{
				database?.Dispose();
			}
			catch (Exception ex)
			{
				RewardsPlugin.Log.LogError((object)("[Database] Failed to close: " + ex.Message));
			}
		}
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	internal static class RewardsPaths
	{
		internal static string DataFolder => Path.Combine(Paths.ConfigPath, "Rewards");

		internal static string SavedDataFolder => Path.Combine(DataFolder, "SavedData");

		internal static string LevelsFolder => Path.Combine(DataFolder, "Levels");

		internal static string DatabaseFile => Path.Combine(SavedDataFolder, "Rewards.db");
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	public sealed class PlayerRecord
	{
		public string Id { get; set; } = "";

		public string LastName { get; set; } = "";

		public int ActiveMinutes { get; set; }

		public int ClaimedLevel { get; set; }

		public int Cycle { get; set; } = 1;

		public long NextGrantId { get; set; }

		public List<PendingGrant> PendingGrants { get; set; } = new List<PendingGrant>();
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	public sealed class PendingGrant
	{
		public long Id { get; set; }

		public List<GrantItem> Items { get; set; } = new List<GrantItem>();
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	public sealed class GrantItem
	{
		public string Prefab { get; set; } = "";

		public int Amount { get; set; }
	}
	[HarmonyPatch(typeof(ZNet), "Awake")]
	internal static class ZNet_Awake_Reset
	{
		private static void Postfix()
		{
			RewardsDatabase.Close();
			RewardsConfig.Reset();
			RewardsServer.Reset();
			RewardsClient.Reset();
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	internal static class ZNet_OnNewConnection_Register
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			if (__instance.IsServer())
			{
				RewardsServer.Register(peer.m_rpc);
			}
			else
			{
				RewardsClient.Register(peer.m_rpc);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	internal static class ZNet_RPC_PeerInfo_Join
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(ZNet __instance, ZRpc rpc)
		{
			if (__instance.IsServer())
			{
				ZNetPeer peer = __instance.GetPeer(rpc);
				if (peer != null && peer.IsReady())
				{
					RewardsServer.OnJoined(peer);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Disconnect")]
	internal static class ZNet_Disconnect_Save
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Prefix(ZNet __instance, ZNetPeer peer)
		{
			if (__instance.IsServer())
			{
				RewardsServer.OnLeft(peer);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Shutdown")]
	internal static class ZNet_Shutdown_Save
	{
		private static void Prefix()
		{
			if (RewardsRpc.IsServer)
			{
				RewardsServer.SaveAll();
			}
		}

		private static void Finalizer()
		{
			RewardsDatabase.Close();
		}
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	internal static class RewardsRpc
	{
		internal const string Levels = "Rewards_Levels";

		internal const string State = "Rewards_State";

		internal const string Presence = "Rewards_Presence";

		internal const string Grant = "Rewards_Grant";

		internal const string Message = "Rewards_Message";

		internal const string Minute = "Rewards_Minute";

		internal const string PresenceAck = "Rewards_PresenceAck";

		internal const string Claim = "Rewards_Claim";

		internal const string GrantAck = "Rewards_GrantAck";

		internal const string Admin = "Rewards_Admin";

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

		internal static void ToServer(string name, params object[] args)
		{
			ZRpc obj = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerRPC() : null);
			if (obj != null)
			{
				obj.Invoke(name, args);
			}
		}

		internal static void WriteItems(ZPackage pkg, List<GrantItem> items)
		{
			pkg.Write(items.Count);
			foreach (GrantItem item in items)
			{
				pkg.Write(item.Prefab);
				pkg.Write(item.Amount);
			}
		}

		internal static List<GrantItem> ReadItems(ZPackage pkg)
		{
			int num = pkg.ReadInt();
			List<GrantItem> list = new List<GrantItem>(num);
			for (int i = 0; i < num; i++)
			{
				list.Add(new GrantItem
				{
					Prefab = pkg.ReadString(),
					Amount = pkg.ReadInt()
				});
			}
			return list;
		}
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	internal sealed class RewardsSession
	{
		internal ZNetPeer Peer;

		internal PlayerRecord Record;

		internal PresenceState Presence;

		internal MinuteGate Gate = new MinuteGate();

		internal bool SentPaused;

		internal bool Dirty;
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	internal static class RewardsServer
	{
		private const double SaveInterval = 300.0;

		private static readonly Dictionary<long, RewardsSession> Sessions = new Dictionary<long, RewardsSession>();

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

		private static readonly Random Random = new Random();

		private static readonly Platform SteamPlatform = new Platform("Steam");

		private static double _lastSave;

		private static bool _subscribed;

		private static bool _presenceWasOn = true;

		private static double Now => Time.realtimeSinceStartupAsDouble;

		private static bool Restart => RewardsPlugin.CE_RestartAfterLastLevel.Value;

		private static bool PresenceOn => RewardsPlugin.CE_PresenceEnabled.Value;

		internal unsafe static string NormalizeId(string raw)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			PlatformUserID val = default(PlatformUserID);
			if (!PlatformUserID.TryParse(raw, ref val))
			{
				((PlatformUserID)(ref val))..ctor(SteamPlatform, raw);
			}
			return ((object)(*(PlatformUserID*)(&val))/*cast due to .constrained prefix*/).ToString();
		}

		internal static void Reset()
		{
			Sessions.Clear();
			Presences.Clear();
			_lastSave = Now;
			if (!_subscribed)
			{
				_subscribed = true;
				RewardsConfig.Changed += OnLevelsChanged;
			}
		}

		internal static void Register(ZRpc rpc)
		{
			rpc.Register<bool>("Rewards_Minute", (Action<ZRpc, bool>)RPC_Minute);
			rpc.Register<long>("Rewards_PresenceAck", (Action<ZRpc, long>)RPC_PresenceAck);
			rpc.Register<int>("Rewards_Claim", (Action<ZRpc, int>)RPC_Claim);
			rpc.Register<long>("Rewards_GrantAck", (Action<ZRpc, long>)RPC_GrantAck);
			rpc.Register<string>("Rewards_Admin", (Action<ZRpc, string>)RewardsAdmin.RPC_Admin);
		}

		internal static void OnJoined(ZNetPeer peer)
		{
			if (peer.m_socket == null)
			{
				return;
			}
			RewardsConfig.Tick();
			string text = NormalizeId(peer.m_socket.GetHostName());
			PlayerRecord playerRecord = RewardsDatabase.Load(text);
			if (playerRecord == null)
			{
				return;
			}
			playerRecord.LastName = peer.m_playerName;
			RewardProgress.Normalize(playerRecord, RewardsConfig.Levels, Restart);
			if (!Presences.TryGetValue(text, out var value))
			{
				value = new PresenceState(Random);
				value.Start(Now, RewardsPlugin.CE_PresenceMinMinutes.Value, RewardsPlugin.CE_PresenceMaxMinutes.Value);
				Presences[text] = value;
			}
			RewardsSession rewardsSession = new RewardsSession
			{
				Peer = peer,
				Record = playerRecord,
				Presence = value
			};
			Sessions[peer.m_uid] = rewardsSession;
			peer.m_rpc.Invoke("Rewards_Levels", new object[1] { RewardsConfig.SyncText });
			SendState(rewardsSession);
			if (PresenceOn && value.Token.HasValue)
			{
				peer.m_rpc.Invoke("Rewards_Presence", new object[2]
				{
					value.Token.Value,
					Mathf.Max(0, Mathf.CeilToInt((float)(value.Deadline - Now)))
				});
			}
			foreach (PendingGrant pendingGrant in playerRecord.PendingGrants)
			{
				SendGrant(rewardsSession, pendingGrant);
			}
		}

		internal static void OnLeft(ZNetPeer peer)
		{
			if (Sessions.TryGetValue(peer.m_uid, out var value))
			{
				RewardsDatabase.Save(value.Record);
				Sessions.Remove(peer.m_uid);
			}
		}

		internal static void SaveAll()
		{
			foreach (RewardsSession value in Sessions.Values)
			{
				if (value.Dirty && RewardsDatabase.Save(value.Record))
				{
					value.Dirty = false;
				}
			}
			_lastSave = Now;
		}

		internal static void Tick()
		{
			if (!RewardsRpc.IsServer)
			{
				return;
			}
			RewardsConfig.Tick();
			double now = Now;
			foreach (RewardsSession value in Sessions.Values)
			{
				if (value.Peer.m_rpc == null)
				{
					continue;
				}
				if (!PresenceOn)
				{
					if (value.Presence.Token.HasValue)
					{
						value.Presence.Start(now, RewardsPlugin.CE_PresenceMinMinutes.Value, RewardsPlugin.CE_PresenceMaxMinutes.Value);
						SendState(value);
					}
					continue;
				}
				if (!_presenceWasOn)
				{
					value.Presence.Start(now, RewardsPlugin.CE_PresenceMinMinutes.Value, RewardsPlugin.CE_PresenceMaxMinutes.Value);
				}
				long? num = value.Presence.Due(now, RewardsPlugin.CE_PresenceResponseMinutes.Value);
				if (num.HasValue)
				{
					value.Peer.m_rpc.Invoke("Rewards_Presence", new object[2]
					{
						num.Value,
						RewardsPlugin.CE_PresenceResponseMinutes.Value * 60
					});
				}
				if (!value.Presence.Counts(now) != value.SentPaused)
				{
					SendState(value);
				}
			}
			_presenceWasOn = PresenceOn;
			if (now - _lastSave >= 300.0)
			{
				SaveAll();
			}
		}

		[return: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		internal static RewardsSession FindOnline(string name)
		{
			foreach (RewardsSession value in Sessions.Values)
			{
				if (string.Equals(value.Peer.m_playerName, name, StringComparison.OrdinalIgnoreCase))
				{
					return value;
				}
			}
			return null;
		}

		internal static void SendState(RewardsSession session)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if (session.Peer.m_rpc != null)
			{
				session.SentPaused = PresenceOn && !session.Presence.Counts(Now);
				ZPackage val = new ZPackage();
				val.Write(session.Record.ActiveMinutes);
				val.Write(session.Record.ClaimedLevel);
				val.Write(session.Record.Cycle);
				val.Write(session.SentPaused);
				val.Write(PresenceOn && session.Presence.Token.HasValue);
				session.Peer.m_rpc.Invoke("Rewards_State", new object[1] { val });
			}
		}

		internal static void MarkChanged(RewardsSession session)
		{
			session.Dirty = true;
			SendState(session);
		}

		private static void SendGrant(RewardsSession session, PendingGrant grant)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			RewardsRpc.WriteItems(val, grant.Items);
			session.Peer.m_rpc.Invoke("Rewards_Grant", new object[2] { grant.Id, val });
		}

		private static void OnLevelsChanged()
		{
			foreach (RewardsSession value in Sessions.Values)
			{
				if (value.Peer.m_rpc != null)
				{
					value.Peer.m_rpc.Invoke("Rewards_Levels", new object[1] { RewardsConfig.SyncText });
					SendState(value);
				}
			}
		}

		[return: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		private static RewardsSession From(ZRpc rpc)
		{
			ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetPeer(rpc) : null);
			if (val == null || !Sessions.TryGetValue(val.m_uid, out var value))
			{
				return null;
			}
			return value;
		}

		private static bool Alive(ZNetPeer peer, out Vector3 position)
		{
			//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_0020: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			if (((ZDOID)(ref peer.m_characterID)).IsNone())
			{
				return false;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
			if (zDO == null || zDO.GetBool(ZDOVars.s_dead, false) || zDO.GetFloat(ZDOVars.s_health, 1f) <= 0f)
			{
				return false;
			}
			position = zDO.GetPosition();
			return true;
		}

		private static void RPC_Minute(ZRpc rpc, bool valid)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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)
			RewardsSession rewardsSession = From(rpc);
			if (rewardsSession == null || !valid || !Alive(rewardsSession.Peer, out var position))
			{
				return;
			}
			double now = Now;
			if (rewardsSession.Gate.Accept(now, new Vector3Like
			{
				X = position.x,
				Y = position.y,
				Z = position.z
			}, RewardsPlugin.CE_ServerStillMinutes.Value))
			{
				if (RewardProgress.Normalize(rewardsSession.Record, RewardsConfig.Levels, Restart))
				{
					MarkChanged(rewardsSession);
				}
				if ((!PresenceOn || rewardsSession.Presence.Counts(now)) && RewardProgress.CanAccrue(rewardsSession.Record, RewardsConfig.Levels, Restart))
				{
					rewardsSession.Record.ActiveMinutes++;
					MarkChanged(rewardsSession);
				}
			}
		}

		private static void RPC_PresenceAck(ZRpc rpc, long token)
		{
			RewardsSession rewardsSession = From(rpc);
			if (rewardsSession != null && rewardsSession.Presence.Ack(token, Now, RewardsPlugin.CE_PresenceMinMinutes.Value, RewardsPlugin.CE_PresenceMaxMinutes.Value))
			{
				SendState(rewardsSession);
			}
		}

		private static void RPC_Claim(ZRpc rpc, int expected)
		{
			RewardsSession rewardsSession = From(rpc);
			if (rewardsSession != null)
			{
				PendingGrant pendingGrant = RewardProgress.Claim(rewardsSession.Record, RewardsConfig.Levels, Restart, expected);
				if (pendingGrant == null)
				{
					SendState(rewardsSession);
					return;
				}
				rewardsSession.Dirty = true;
				RewardsDatabase.Save(rewardsSession.Record);
				SendState(rewardsSession);
				SendGrant(rewardsSession, pendingGrant);
			}
		}

		private static void RPC_GrantAck(ZRpc rpc, long id)
		{
			RewardsSession rewardsSession = From(rpc);
			if (rewardsSession != null && rewardsSession.Record.PendingGrants.RemoveAll((PendingGrant g) => g.Id == id) > 0)
			{
				RewardsDatabase.Save(rewardsSession.Record);
			}
		}
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	internal static class RewardsAdmin
	{
		internal static void RPC_Admin(ZRpc rpc, string line)
		{
			string text = (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.ListContainsId(ZNet.instance.m_adminList, rpc.GetSocket().GetHostName())) ? Execute(line) : "$rw_cmd_denied");
			rpc.Invoke("Rewards_Message", new object[1] { text });
		}

		internal static string Execute(string line)
		{
			string[] array = line.Trim().Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				return "$rw_cmd_usage";
			}
			switch (array[0].ToLowerInvariant())
			{
			case "rewards_reload":
				RewardsConfig.Tick(force: true);
				return "$rw_cmd_reloaded";
			case "rewards_add":
			{
				if (array.Length < 3 || !int.TryParse(array[^1], out var minutes))
				{
					return "$rw_cmd_usage";
				}
				return Apply(string.Join(" ", array, 1, array.Length - 2), delegate(PlayerRecord r)
				{
					r.ActiveMinutes = Math.Max(0, r.ActiveMinutes + minutes);
				});
			}
			case "rewards_reset":
				if (array.Length < 2)
				{
					return "$rw_cmd_usage";
				}
				return Apply(string.Join(" ", array, 1, array.Length - 1), delegate(PlayerRecord r)
				{
					r.ActiveMinutes = 0;
					r.ClaimedLevel = 0;
					r.Cycle = 1;
				});
			default:
				return "$rw_cmd_usage";
			}
		}

		private static string Apply(string name, Action<PlayerRecord> change)
		{
			RewardsSession rewardsSession = RewardsServer.FindOnline(name);
			if (rewardsSession == null)
			{
				return "$rw_cmd_notfound";
			}
			change(rewardsSession.Record);
			rewardsSession.Dirty = true;
			RewardsDatabase.Save(rewardsSession.Record);
			RewardsServer.SendState(rewardsSession);
			return "$rw_cmd_done";
		}

		internal static void Run(ConsoleEventArgs args)
		{
			if (!((Object)(object)ZNet.instance == (Object)null))
			{
				if (ZNet.instance.IsServer())
				{
					args.Context.AddString(RewardsText.L(Execute(args.FullLine)));
					return;
				}
				RewardsRpc.ToServer("Rewards_Admin", args.FullLine);
			}
		}
	}
	[HarmonyPatch(typeof(Terminal), "InitTerminal")]
	internal static class Terminal_InitTerminal_Commands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__0_0;

			public static ConsoleEvent <>9__0_1;

			public static ConsoleEvent <>9__0_2;

			internal void <Postfix>b__0_0(ConsoleEventArgs args)
			{
				RewardsAdmin.Run(args);
			}

			internal void <Postfix>b__0_1(ConsoleEventArgs args)
			{
				RewardsAdmin.Run(args);
			}

			internal void <Postfix>b__0_2(ConsoleEventArgs args)
			{
				RewardsAdmin.Run(args);
			}
		}

		private static void Postfix()
		{
			//IL_0033: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_006c: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					RewardsAdmin.Run(args);
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("rewards_reload", "Reloads the Levels folder (admin)", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj2 = <>c.<>9__0_1;
			if (obj2 == null)
			{
				ConsoleEvent val2 = delegate(ConsoleEventArgs args)
				{
					RewardsAdmin.Run(args);
				};
				<>c.<>9__0_1 = val2;
				obj2 = (object)val2;
			}
			new ConsoleCommand("rewards_add", "<player> <minutes> adds active minutes (admin)", (ConsoleEvent)obj2, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj3 = <>c.<>9__0_2;
			if (obj3 == null)
			{
				ConsoleEvent val3 = delegate(ConsoleEventArgs args)
				{
					RewardsAdmin.Run(args);
				};
				<>c.<>9__0_2 = val3;
				obj3 = (object)val3;
			}
			new ConsoleCommand("rewards_reset", "<player> resets progress (admin)", (ConsoleEvent)obj3, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("radamanto.Rewards", "Rewards", "1.0.0")]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	public sealed class RewardsPlugin : BaseUnityPlugin
	{
		internal static ConfigSync ConfigSync = null;

		internal static ConfigEntry<bool> CE_LockConfiguration = null;

		internal static ConfigEntry<int> CE_IdleMinutes = null;

		internal static ConfigEntry<int> CE_ActivityMinCriteria = null;

		internal static ConfigEntry<int> CE_ServerStillMinutes = null;

		internal static ConfigEntry<bool> CE_PresenceEnabled = null;

		internal static ConfigEntry<int> CE_PresenceMinMinutes = null;

		internal static ConfigEntry<int> CE_PresenceMaxMinutes = null;

		internal static ConfigEntry<int> CE_PresenceResponseMinutes = null;

		internal static ConfigEntry<bool> CE_RestartAfterLastLevel = null;

		internal static ConfigEntry<Vector2> CE_ButtonPosition = null;

		public const string ModGuid = "radamanto.Rewards";

		public const string ModName = "Rewards";

		public const string ModVersion = "1.0.0";

		internal static RewardsPlugin Instance = null;

		internal static readonly ManualLogSource Log = Logger.CreateLogSource("Rewards");

		private readonly Harmony _harmony = new Harmony("radamanto.Rewards");

		private void SetupConfig()
		{
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			ConfigSync = new ConfigSync("radamanto.Rewards")
			{
				DisplayName = "Rewards",
				CurrentVersion = "1.0.0",
				MinimumRequiredVersion = "1.0.0",
				ModRequired = true
			};
			CE_LockConfiguration = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "LockConfiguration", true, "Locks synchronized configuration to server authority.");
			ConfigSync.AddLockingConfigEntry<bool>(CE_LockConfiguration);
			CE_IdleMinutes = Bind("02 - Activity", "IdleMinutes", 3, "Minutes without any input before time stops counting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60));
			CE_ActivityMinCriteria = Bind("02 - Activity", "ActivityMinCriteria", 2, "How many of the 4 activity criteria a player must meet in each minute for that minute to count.\n1 - Movement: moved at least 8 meters (being carried by a ship also counts).\n2 - Camera: turned the camera at least 90 degrees in total.\n3 - Action variety: did at least 2 different kinds of action. Kinds: walk, jump, attack, block, build, pick up, interact, open inventory, chat, eat, craft, ship sails, ship rudder.\n4 - Target variety: hit or interacted with at least 2 different objects or creatures.\nExample: holding attack on the same rock meets only 1 criterion. Lower values are easier, 4 is the strictest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4));
			CE_ServerStillMinutes = Bind("02 - Activity", "ServerStillMinutes", 5, "Minutes standing on the same spot after which time stops counting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60));
			CE_PresenceEnabled = Bind("03 - Presence", "PresenceEnabled", value: true, "Enables the periodic presence check (the \"Are you still there?\" prompt). When disabled, only the activity checks apply.");
			CE_PresenceMinMinutes = Bind("03 - Presence", "PresenceMinMinutes", 20, "Minimum minutes between presence checks.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 600));
			CE_PresenceMaxMinutes = Bind("03 - Presence", "PresenceMaxMinutes", 40, "Maximum minutes between presence checks.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 600));
			CE_PresenceResponseMinutes = Bind("03 - Presence", "PresenceResponseMinutes", 10, "Minutes the player has to answer a presence check before time stops counting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 120));
			CE_RestartAfterLastLevel = Bind("04 - Levels", "RestartAfterLastLevel", value: true, "After claiming the last level, start again from level 1 in a new cycle.");
			CE_ButtonPosition = Bind<Vector2>("05 - Interface", "ButtonPosition", new Vector2(20f, 72f), "Position of the rewards button (pixels from the left edge, vertical offset from the center). Changed in game with Ctrl + drag.", null, synced: false);
			CE_ButtonPosition.SettingChanged += [<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(0)] (object _, EventArgs _) =>
			{
				RewardsAccessButton.ApplyPosition();
			};
		}

		private ConfigEntry<T> Bind<[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)] T>(string section, string key, T value, string description, [<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)] AcceptableValueBase range = null, bool synced = true)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, value, new ConfigDescription(description + (synced ? " [Synced with server]" : " [Local]"), range, Array.Empty<object>()));
			if (synced)
			{
				ConfigSync.AddConfigEntry<T>(val).SynchronizedConfig = true;
			}
			return val;
		}

		private void Awake()
		{
			Instance = this;
			Localizer.Load();
			SetupConfig();
			RewardsAssets.Load();
			_harmony.PatchAll();
			((MonoBehaviour)this).InvokeRepeating("TickServer", 1f, 1f);
			Log.LogInfo((object)"Rewards 1.0.0 loaded.");
		}

		private void TickServer()
		{
			RewardsServer.Tick();
		}

		private void Update()
		{
			if (!RewardsRpc.IsServer || !ZNet.instance.IsDedicated())
			{
				RewardsClient.Tick();
				RewardsActivity.Tick();
			}
		}

		private void OnDestroy()
		{
			((MonoBehaviour)this).CancelInvoke();
			RewardsUI.Dispose();
			_harmony.UnpatchSelf();
			RewardsAssets.Dispose();
		}
	}
	internal static class RewardsText
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		internal static string L(string text, params string[] args)
		{
			if (Localization.instance == null)
			{
				return text;
			}
			if (args.Length != 0)
			{
				return Localization.instance.Localize(text, args);
			}
			return Localization.instance.Localize(text);
		}
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	internal static class RewardsClient
	{
		private const float DeliveryDelay = 3f;

		private static bool _claiming;

		private static float _readySince = -1f;

		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(new byte[] { 1, 0, 1, 1 })]
		private static readonly List<(long Id, List<GrantItem> Items)> Incoming = new List<(long, List<GrantItem>)>();

		internal static List<RewardLevel> Levels { get; private set; } = new List<RewardLevel>();

		internal static PlayerRecord State { get; private set; } = new PlayerRecord();

		internal static bool Paused { get; private set; }

		internal static bool Connected { get; private set; }

		internal static long? PresenceToken { get; private set; }

		internal static float PresenceDeadline { get; private set; }

		internal static int Unlocked => RewardProgress.Unlocked(State, Levels);

		internal static bool TimeLocked => RewardProgress.TimeLocked(State, Levels, RewardsBiomeLock.Has);

		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		internal static RewardLevel Next
		{
			[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(2)]
			get
			{
				if (State.ClaimedLevel >= Levels.Count)
				{
					return null;
				}
				return Levels[State.ClaimedLevel];
			}
		}

		internal static int ReadyCount
		{
			get
			{
				int unlocked = Unlocked;
				int num = 0;
				for (int i = State.ClaimedLevel; i < unlocked && i < Levels.Count; i++)
				{
					RewardLevel rewardLevel = Levels[i];
					if (RewardProgress.LockApplies(State, rewardLevel) && !RewardsBiomeLock.Has(rewardLevel.RequiredKey))
					{
						break;
					}
					num++;
				}
				return num;
			}
		}

		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		[method: <9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(2)]
		[field: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		internal static event Action Changed;

		internal static void Reset()
		{
			Levels = new List<RewardLevel>();
			State = new PlayerRecord();
			Paused = false;
			Connected = false;
			PresenceToken = null;
			_claiming = false;
			_readySince = -1f;
			Incoming.Clear();
			RewardsClient.Changed?.Invoke();
		}

		internal static void Register(ZRpc rpc)
		{
			rpc.Register<string>("Rewards_Levels", (Action<ZRpc, string>)RPC_Levels);
			rpc.Register<ZPackage>("Rewards_State", (Action<ZRpc, ZPackage>)RPC_State);
			rpc.Register<long, int>("Rewards_Presence", (Action<ZRpc, long, int>)RPC_Presence);
			rpc.Register<long, ZPackage>("Rewards_Grant", (Action<ZRpc, long, ZPackage>)RPC_Grant);
			rpc.Register<string>("Rewards_Message", (Action<ZRpc, string>)RPC_Message);
		}

		internal static bool CanClaimNext(out string reasonToken)
		{
			reasonToken = "";
			RewardLevel next = Next;
			if (next == null || State.ClaimedLevel >= Unlocked)
			{
				reasonToken = "$rw_reason_time";
				return false;
			}
			if (RewardProgress.LockApplies(State, next) && !RewardsBiomeLock.Has(next.RequiredKey))
			{
				reasonToken = "$rw_reason_boss";
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && !HasSpace(localPlayer, next.Items.ConvertAll([<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(0)] ([<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(1)] RewardItem i) => new GrantItem
			{
				Prefab = i.Prefab,
				Amount = i.Amount
			})))
			{
				reasonToken = "$rw_reason_space";
				return false;
			}
			return true;
		}

		internal static bool HasSpace(Player player, List<GrantItem> items)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (GrantItem item in items)
			{
				dictionary[item.Prefab] = (dictionary.TryGetValue(item.Prefab, out var value) ? value : 0) + item.Amount;
			}
			int num = inventory.GetEmptySlots();
			foreach (KeyValuePair<string, int> item2 in dictionary)
			{
				GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(item2.Key) : null);
				ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					SharedData shared = val2.m_itemData.m_shared;
					int freeInStacks = ((shared.m_maxStackSize > 1) ? inventory.FindFreeStackSpace(shared.m_name, (float)Game.m_worldLevel) : 0);
					num -= RewardProgress.SlotsNeeded(item2.Value, freeInStacks, shared.m_maxStackSize);
					if (num < 0)
					{
						return false;
					}
				}
			}
			return true;
		}

		internal static void ClaimNext()
		{
			if (!CanClaimNext(out var reasonToken))
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, RewardsText.L(reasonToken), 0, (Sprite)null, false);
				}
			}
			else if (!_claiming)
			{
				_claiming = true;
				RewardsRpc.ToServer("Rewards_Claim", State.ClaimedLevel);
			}
		}

		internal static void AnswerPresence()
		{
			if (PresenceToken.HasValue)
			{
				RewardsRpc.ToServer("Rewards_PresenceAck", PresenceToken.Value);
				PresenceToken = null;
				RewardsClient.Changed?.Invoke();
			}
		}

		internal static void Tick()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting())
			{
				_readySince = -1f;
				return;
			}
			if (_readySince < 0f)
			{
				_readySince = Time.realtimeSinceStartup;
			}
			if (Incoming.Count == 0 || Time.realtimeSinceStartup - _readySince < 3f)
			{
				return;
			}
			while (Incoming.Count > 0)
			{
				var (id, items) = Incoming[0];
				if (!HasSpace(localPlayer, items))
				{
					break;
				}
				Incoming.RemoveAt(0);
				Deliver(localPlayer, id, items);
			}
		}

		private static void RPC_Levels(ZRpc rpc, string raw)
		{
			Connected = true;
			Levels = RewardLevels.Parse(raw, (string _) => true, delegate(string w)
			{
				RewardsPlugin.Log.LogWarning((object)("[Levels] " + w));
			});
			RewardsClient.Changed?.Invoke();
		}

		private static void RPC_State(ZRpc rpc, ZPackage pkg)
		{
			Connected = true;
			_claiming = false;
			int unlocked = Unlocked;
			State = new PlayerRecord
			{
				ActiveMinutes = pkg.ReadInt(),
				ClaimedLevel = pkg.ReadInt(),
				Cycle = pkg.ReadInt()
			};
			Paused = pkg.ReadBool();
			if (!pkg.ReadBool())
			{
				PresenceToken = null;
			}
			if (Unlocked > unlocked && Unlocked > State.ClaimedLevel)
			{
				RewardsAudio.Play("SkillNode_Select");
			}
			RewardsClient.Changed?.Invoke();
		}

		private static void RPC_Presence(ZRpc rpc, long token, int seconds)
		{
			PresenceToken = token;
			PresenceDeadline = Time.realtimeSinceStartup + (float)seconds;
			RewardsAudio.Play("SkillTree_Click");
			RewardsClient.Changed?.Invoke();
		}

		private static void RPC_Grant(ZRpc rpc, long id, ZPackage pkg)
		{
			List<GrantItem> item = RewardsRpc.ReadItems(pkg);
			if (!Incoming.Exists(([<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(new byte[] { 0, 1, 1 })] (long Id, List<GrantItem> Items) i) => i.Id == id))
			{
				Incoming.Add((id, item));
				Tick();
			}
		}

		private static void RPC_Message(ZRpc rpc, string text)
		{
			string text2 = RewardsText.L(text);
			Console instance = Console.instance;
			if (instance != null)
			{
				instance.Print(text2);
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)1, text2, 0, (Sprite)null, false);
			}
		}

		private static void Deliver(Player player, long id, List<GrantItem> items)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			foreach (GrantItem item in items)
			{
				GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(item.Prefab) : null);
				ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					RewardsPlugin.Log.LogWarning((object)("[Grant] Unknown item '" + item.Prefab + "' skipped."));
					continue;
				}
				int num = item.Amount;
				while (num > 0)
				{
					ItemData val3 = val2.m_itemData.Clone();
					val3.m_dropPrefab = val;
					val3.m_stack = Mathf.Min(num, Mathf.Max(1, val3.m_shared.m_maxStackSize));
					val3.m_worldLevel = (byte)Game.m_worldLevel;
					num -= val3.m_stack;
					inventory.AddItem(val3);
				}
				((Character)player).Message((MessageType)1, "$msg_added " + val2.m_itemData.m_shared.m_name, item.Amount, val2.m_itemData.GetIcon(), false);
			}
			RewardsAudio.PlayReward();
			RewardsRpc.ToServer("Rewards_GrantAck", id);
		}
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	internal static class RewardsConfig
	{
		private static string _stamp = "";

		private static bool _loaded;

		internal static List<RewardLevel> Levels { get; private set; } = new List<RewardLevel>();

		internal static string SyncText { get; private set; } = "";

		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		[method: <9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(2)]
		[field: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		internal static event Action Changed;

		internal static bool PrefabExists(string name)
		{
			GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(name) : null);
			if ((Object)(object)val != (Object)null)
			{
				return (Object)(object)val.GetComponent<ItemDrop>() != (Object)null;
			}
			return false;
		}

		internal static void Reset()
		{
			Levels = new List<RewardLevel>();
			SyncText = "";
			_loaded = false;
			_stamp = "";
		}

		internal static void Tick(bool force = false)
		{
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || ObjectDB.instance.m_items.Count == 0)
			{
				return;
			}
			try
			{
				Directory.CreateDirectory(RewardsPaths.LevelsFolder);
				string[] files = Directory.GetFiles(RewardsPaths.LevelsFolder, "*.cfg", SearchOption.AllDirectories);
				StringBuilder stringBuilder = new StringBuilder();
				string[] array = files;
				foreach (string text in array)
				{
					FileInfo fileInfo = new FileInfo(text);
					stringBuilder.Append(text).Append('|').Append(fileInfo.Length)
						.Append('|')
						.Append(fileInfo.LastWriteTimeUtc.Ticks)
						.Append(';');
				}
				if (!_loaded || force || !(stringBuilder.ToString() == _stamp))
				{
					_stamp = stringBuilder.ToString();
					_loaded = true;
					List<(string, string)> list = new List<(string, string)>();
					array = files;
					foreach (string text2 in array)
					{
						list.Add((text2.Substring(RewardsPaths.LevelsFolder.Length).TrimStart('\\', '/'), File.ReadAllText(text2)));
					}
					Levels = RewardLevels.Merge(list, PrefabExists, delegate(string w)
					{
						RewardsPlugin.Log.LogWarning((object)("[Levels] " + w));
					});
					SyncText = RewardLevels.Serialize(Levels);
					RewardsPlugin.Log.LogInfo((object)("[Levels] Loaded " + Levels.Count + " levels."));
					RewardsConfig.Changed?.Invoke();
				}
			}
			catch (Exception ex)
			{
				RewardsPlugin.Log.LogError((object)("[Levels] Failed to read " + RewardsPaths.LevelsFolder + ": " + ex.Message));
			}
		}
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	internal sealed class RewardItem
	{
		public string Prefab { get; set; } = "";

		public int Amount { get; set; }
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	internal sealed class RewardLevel
	{
		public int Number { get; set; }

		public int Minutes { get; set; }

		public List<RewardItem> Items { get; set; } = new List<RewardItem>();

		public string RequiredKey { get; set; } = "";
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	internal static class RewardLevels
	{
		internal static List<RewardLevel> Parse(string text, Func<string, bool> prefabExists, Action<string> warn)
		{
			List<(int, Dictionary<string, string>)> list = new List<(int, Dictionary<string, string>)>();
			Dictionary<string, string> dictionary = null;
			string[] array = text.Replace("\r", "").Split(new char[1] { '\n' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length == 0 || text2.StartsWith("#") || text2.StartsWith(";"))
				{
					continue;
				}
				if (text2.StartsWith("[") && text2.EndsWith("]"))
				{
					dictionary = null;
					if (int.TryParse(text2.Substring(1, text2.Length - 2).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result > 0)
					{
						dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
						list.Add((result, dictionary));
					}
					else
					{
						warn("Invalid level section " + text2 + ".");
					}
				}
				else
				{
					int num = text2.IndexOf('=');
					if (dictionary != null && num > 0)
					{
						dictionary[text2.Substring(0, num).Trim()] = text2.Substring(num + 1).Trim();
					}
				}
			}
			List<RewardLevel> list2 = new List<RewardLevel>();
			HashSet<int> hashSet = new HashSet<int>();
			foreach (var (num2, values) in list)
			{
				if (!hashSet.Add(num2))
				{
					warn("Level " + num2 + " is duplicated; keeping the first one.");
					continue;
				}
				RewardLevel rewardLevel = Build(num2, values, prefabExists, warn);
				if (rewardLevel != null)
				{
					list2.Add(rewardLevel);
				}
			}
			list2.Sort((RewardLevel a, RewardLevel b) => a.Number.CompareTo(b.Number));
			return list2;
		}

		internal static List<RewardLevel> Merge([<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(new byte[] { 1, 0, 1, 1 })] IEnumerable<(string Name, string Text)> files, Func<string, bool> prefabExists, Action<string> warn)
		{
			List<(string, string)> list = new List<(string, string)>(files);
			list.Sort(([<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(new byte[] { 0, 1, 1 })] (string Name, string Text) a, [<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(new byte[] { 0, 1, 1 })] (string Name, string Text) b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
			List<RewardLevel> list2 = new List<RewardLevel>();
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			foreach (var item in list)
			{
				var (name, _) = item;
				foreach (RewardLevel item2 in Parse(item.Item2, prefabExists, delegate(string w)
				{
					warn(name + ": " + w);
				}))
				{
					if (dictionary.TryGetValue(item2.Number, out var value))
					{
						warn(name + ": level " + item2.Number + " already defined in " + value + "; ignored.");
					}
					else
					{
						dictionary[item2.Number] = name;
						list2.Add(item2);
					}
				}
			}
			list2.Sort((RewardLevel a, RewardLevel b) => a.Number.CompareTo(b.Number));
			return list2;
		}

		internal static string Serialize(IEnumerable<RewardLevel> levels)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (RewardLevel level in levels)
			{
				stringBuilder.Append('[').Append(level.Number.ToString(CultureInfo.InvariantCulture)).Append("]\n");
				stringBuilder.Append("Minutes = ").Append(level.Minutes.ToString(CultureInfo.InvariantCulture)).Append('\n');
				stringBuilder.Append("Items = ");
				for (int i = 0; i < level.Items.Count; i++)
				{
					if (i > 0)
					{
						stringBuilder.Append(", ");
					}
					stringBuilder.Append(level.Items[i].Prefab).Append(':').Append(level.Items[i].Amount.ToString(CultureInfo.InvariantCulture));
				}
				stringBuilder.Append('\n');
				if (level.RequiredKey.Length > 0)
				{
					stringBuilder.Append("RequiredKey = ").Append(level.RequiredKey).Append('\n');
				}
			}
			return stringBuilder.ToString();
		}

		[return: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		private static RewardLevel Build(int number, Dictionary<string, string> values, Func<string, bool> prefabExists, Action<string> warn)
		{
			if (!values.TryGetValue("Minutes", out var value) || !int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 0)
			{
				warn("Level " + number + " has an invalid Minutes value.");
				return null;
			}
			RewardLevel rewardLevel = new RewardLevel
			{
				Number = number,
				Minutes = result
			};
			if (values.TryGetValue("RequiredKey", out var value2))
			{
				rewardLevel.RequiredKey = value2;
			}
			if (!values.TryGetValue("Items", out var value3) || value3.Length == 0)
			{
				warn("Level " + number + " has no Items.");
				return null;
			}
			string[] array = value3.Split(new char[1] { ',' });
			foreach (string text in array)
			{
				string[] array2 = text.Split(new char[1] { ':' });
				string text2 = array2[0].Trim();
				if (array2.Length != 2 || text2.Length == 0 || !int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) || result2 <= 0)
				{
					warn("Level " + number + " has an invalid item entry '" + text.Trim() + "'.");
					return null;
				}
				if (!prefabExists(text2))
				{
					warn("Level " + number + " uses unknown item '" + text2 + "'.");
					return null;
				}
				rewardLevel.Items.Add(new RewardItem
				{
					Prefab = text2,
					Amount = result2
				});
			}
			return rewardLevel;
		}
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	internal static class RewardProgress
	{
		internal static int Unlocked(PlayerRecord r, IReadOnlyList<RewardLevel> levels)
		{
			int i;
			for (i = 0; i < levels.Count && levels[i].Minutes <= r.ActiveMinutes; i++)
			{
			}
			return i;
		}

		internal static bool LockApplies(PlayerRecord r, RewardLevel level)
		{
			if (level.RequiredKey.Length > 0)
			{
				return r.Cycle == 1;
			}
			return false;
		}

		internal static bool TimeLocked(PlayerRecord r, IReadOnlyList<RewardLevel> levels, Func<string, bool> hasKey)
		{
			for (int i = Math.Max(0, r.ClaimedLevel); i < levels.Count; i++)
			{
				RewardLevel rewardLevel = levels[i];
				if (LockApplies(r, rewardLevel) && !hasKey(rewardLevel.RequiredKey))
				{
					return r.ActiveMinutes >= rewardLevel.Minutes;
				}
			}
			return false;
		}

		[return: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		internal static PendingGrant Claim(PlayerRecord r, IReadOnlyList<RewardLevel> levels, bool restart, int expected)
		{
			if (expected != r.ClaimedLevel || r.ClaimedLevel < 0 || r.ClaimedLevel >= Unlocked(r, levels))
			{
				return null;
			}
			RewardLevel rewardLevel = levels[r.ClaimedLevel];
			PendingGrant pendingGrant = new PendingGrant
			{
				Id = ++r.NextGrantId
			};
			foreach (RewardItem item in rewardLevel.Items)
			{
				pendingGrant.Items.Add(new GrantItem
				{
					Prefab = item.Prefab,
					Amount = item.Amount
				});
			}
			r.PendingGrants.Add(pendingGrant);
			r.ClaimedLevel++;
			if (restart && r.ClaimedLevel >= levels.Count)
			{
				r.ActiveMinutes = 0;
				r.ClaimedLevel = 0;
				r.Cycle++;
			}
			return pendingGrant;
		}

		internal static bool CanAccrue(PlayerRecord r, IReadOnlyList<RewardLevel> levels, bool restart)
		{
			if (levels.Count == 0)
			{
				return false;
			}
			if (!restart)
			{
				return r.ClaimedLevel < levels.Count;
			}
			return true;
		}

		internal static int SlotsNeeded(int amount, int freeInStacks, int maxStack)
		{
			int num = amount - Math.Max(0, freeInStacks);
			if (num <= 0)
			{
				return 0;
			}
			int num2 = Math.Max(1, maxStack);
			return (num + num2 - 1) / num2;
		}

		internal static bool Normalize(PlayerRecord r, IReadOnlyList<RewardLevel> levels, bool restart)
		{
			if (!restart || levels.Count == 0 || r.ClaimedLevel < levels.Count)
			{
				return false;
			}
			r.ActiveMinutes = 0;
			r.ClaimedLevel = 0;
			r.Cycle++;
			return true;
		}

		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(0)]
		internal static (int First, int Last) Window(int current, int total, int visible = 6)
		{
			if (total <= visible)
			{
				return (First: 0, Last: Math.Max(0, total - 1));
			}
			int num = Math.Max(0, Math.Min(current - 2, total - visible));
			return (First: num, Last: num + visible - 1);
		}

		internal static float Fill(PlayerRecord r, IReadOnlyList<RewardLevel> levels, int index)
		{
			if (index < 0 || index >= levels.Count)
			{
				return 0f;
			}
			int num = ((index != 0) ? levels[index - 1].Minutes : 0);
			int minutes = levels[index].Minutes;
			if (r.ActiveMinutes >= minutes)
			{
				return 1f;
			}
			if (r.ActiveMinutes <= num || minutes <= num)
			{
				return 0f;
			}
			return (float)(r.ActiveMinutes - num) / (float)(minutes - num);
		}
	}
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(2)]
	internal static class RewardsAccessButton
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
			public static readonly <>c <>9 = new <>c();

			[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
			public static UnityAction <>9__19_0;

			internal void <Create>b__19_0()
			{
				if (!CtrlHeld)
				{
					RewardsWindow.Toggle();
				}
			}
		}

		private const float IconSize = 64f;

		private static readonly Color NormalTint = Color.white;

		private static readonly Color HoverTint = new Color(0.68f, 0.68f, 0.68f, 1f);

		private static readonly Color PressedTint = new Color(0.45f, 0.45f, 0.45f, 1f);

		private static GameObject _root;

		private static RectTransform _button;

		private const float BadgeSize = 20f;

		private static readonly Color BadgeGreen = new Color(0.3f, 0.78f, 0.5f, 1f);

		private static readonly Color BadgeAlert = new Color(0.86f, 0.33f, 0.16f, 1f);

		private static Image _glow;

		private static Image _badgeBody;

		private static RectTransform _badge;

		private static TMP_Text _badgeText;

		private static bool _warned;

		internal static RectTransform Button => _button;

		internal static bool CtrlHeld
		{
			get
			{
				if (!ZInput.GetKey((KeyCode)306, false))
				{
					return ZInput.GetKey((KeyCode)305, false);
				}
				return true;
			}
		}

		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		internal static void Ensure(InventoryGui gui)
		{
			if (!((Object)(object)_root != (Object)null))
			{
				_root = Create(gui);
				if ((Object)(object)_root == (Object)null && !_warned)
				{
					_warned = true;
					RewardsPlugin.Log.LogWarning((object)"[Rewards] Could not create the rewards button.");
				}
			}
		}

		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		[return: <708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		private static GameObject Create(InventoryGui gui)
		{
			//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_009f: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Expected O, but got Unknown
			Canvas componentInParent = ((Component)gui).GetComponentInParent<Canvas>();
			Sprite val = RewardsAssets.Optional("ico_rewards_menu");
			if ((Object)(object)componentInParent == (Object)null || (Object)(object)val == (Object)null)
			{
				return null;
			}
			RewardsArt.Create();
			RectTransform obj = RewardsKit.Stretch(RewardsKit.Rect(((Component)componentInParent.rootCanvas).transform, "RW_AccessButtonRoot"), 0f);
			((Component)obj).gameObject.AddComponent<Canvas>().overrideSorting = false;
			((Component)obj).gameObject.AddComponent<GraphicRaycaster>();
			RectTransform val2 = RewardsKit.Rect((Transform)(object)obj, "RW_AccessButton");
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0f, 0.5f);
			val2.sizeDelta = new Vector2(64f, 64f);
			val2.anchoredPosition = RewardsPlugin.CE_ButtonPosition.Value;
			Image val4 = ((Component)val2).gameObject.AddComponent<Image>();
			val4.sprite = val;
			val4.preserveAspect = true;
			_badge = RewardsKit.Rect((Transform)(object)val2, "Badge", new Vector2(20f, 20f), Vector2.zero);
			RectTransform badge = _badge;
			RectTransform badge2 = _badge;
			((Vector2)(ref val3))..ctor(1f, 1f);
			badge2.anchorMax = val3;
			badge.anchorMin = val3;
			_badge.anchoredPosition = new Vector2(-8f, -8f);
			_glow = RewardsKit.Image((Transform)(object)_badge, "Glow", RewardsArt.Glow, Color.clear, new Vector2(40f, 40f), Vector2.zero);
			RewardsKit.Image((Transform)(object)_badge, "Shadow", RewardsArt.Rounded, new Color(0f, 0f, 0f, 0.6f), new Vector2(23f, 23f), new Vector2(0f, -1f)).pixelsPerUnitMultiplier = 1.7f;
			_badgeBody = RewardsKit.Image((Transform)(object)_badge, "Ring", RewardsArt.Rounded, BadgeGreen, new Vector2(20f, 20f), Vector2.zero);
			_badgeBody.pixelsPerUnitMultiplier = 2f;
			RewardsKit.Image((Transform)(object)_badge, "Body", RewardsArt.Rounded, new Color(0.07f, 0.055f, 0.04f, 1f), new Vector2(16f, 16f), Vector2.zero).pixelsPerUnitMultiplier = 2.5f;
			_badgeText = RewardsKit.Text((Transform)(object)_badge, "Count", "", 11f, RewardsArt.Parchment, (TextAlignmentOptions)514, new Vector2(26f, 20f), new Vector2(0f, 0.5f));
			if ((Object)(object)gui.m_containerName != (Object)null && (Object)(object)gui.m_containerName.font != (Object)null)
			{
				_badgeText.font = gui.m_containerName.font;
			}
			_badgeText.fontStyle = (FontStyles)1;
			_badgeText.textWrappingMode = (TextWrappingModes)0;
			((Component)_badge).gameObject.SetActive(false);
			Button obj2 = ((Component)val2).gameObject.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)val4;
			ColorBlock colors = ((Selectable)obj2).colors;
			((ColorBlock)(ref colors)).normalColor = NormalTint;
			((ColorBlock)(ref colors)).selectedColor = NormalTint;
			((ColorBlock)(ref colors)).highlightedColor = HoverTint;
			((ColorBlock)(ref colors)).pressedColor = PressedTint;
			((ColorBlock)(ref colors)).colorMultiplier = 1f;
			((ColorBlock)(ref colors)).fadeDuration = 0.08f;
			((Selectable)obj2).colors = colors;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)obj2).navigation = navigation;
			ButtonClickedEvent onClick = obj2.onClick;
			object obj3 = <>c.<>9__19_0;
			if (obj3 == null)
			{
				UnityAction val5 = delegate
				{
					if (!CtrlHeld)
					{
						RewardsWindow.Toggle();
					}
				};
				<>c.<>9__19_0 = val5;
				obj3 = (object)val5;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj3);
			((Component)val2).gameObject.AddComponent<RewardsAccessButtonDrag>();
			AddTooltip(gui, ((Component)val2).gameObject);
			_button = val2;
			return ((Component)obj).gameObject;
		}

		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void AddTooltip(InventoryGui gui, GameObject go)
		{
			//IL_003f: 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)
			UITooltip componentInChildren = ((Component)gui).GetComponentInChildren<UITooltip>(true);
			if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren.m_tooltipPrefab == (Object)null))
			{
				UITooltip obj = go.AddComponent<UITooltip>();
				obj.m_tooltipPrefab = componentInChildren.m_tooltipPrefab;
				obj.Set("", "$rw_title", (RectTransform)null, default(Vector2));
			}
		}

		internal static void Tick()
		{
			//IL_0153: 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)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null || (Object)(object)_button == (Object)null)
			{
				return;
			}
			bool flag = (Object)(object)Player.m_localPlayer != (Object)null && !Hud.IsUserHidden() && RewardsClient.Connected;
			if (((Component)_button).gameObject.activeSelf != flag)
			{
				((Component)_button).gameObject.SetActive(flag);
			}
			if (!flag || (Object)(object)_badge == (Object)null || (Object)(object)_glow == (Object)null || (Object)(object)_badgeBody == (Object)null || (Object)(object)_badgeText == (Object)null)
			{
				return;
			}
			bool hasValue = RewardsClient.PresenceToken.HasValue;
			int num = ((!hasValue) ? RewardsClient.ReadyCount : 0);
			bool flag2 = hasValue || num > 0;
			if (((Component)_badge).gameObject.activeSelf != flag2)
			{
				((Component)_badge).gameObject.SetActive(flag2);
			}
			if (flag2)
			{
				string text = (hasValue ? "!" : ((num > 99) ? "99+" : num.ToString()));
				if (_badgeText.text != text)
				{
					_badgeText.text = text;
				}
				_badgeText.fontSize = ((text.Length > 2) ? 8 : ((text.Length > 1) ? 10 : 11));
				((Graphic)_badgeBody).color = (hasValue ? BadgeAlert : BadgeGreen);
				float num2 = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * 6f);
				((Graphic)_glow).color = (Color)(hasValue ? new Color(BadgeAlert.r, BadgeAlert.g, BadgeAlert.b, 0.25f + 0.35f * num2) : Color.clear);
				((Transform)_badge).localScale = Vector3.one * (hasValue ? (1f + 0.08f * num2) : 1f);
			}
		}

		internal static void SavePosition(Vector2 position)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			RewardsPlugin.CE_ButtonPosition.Value = position;
		}

		internal static void ApplyPosition()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_button != (Object)null)
			{
				_button.anchoredPosition = RewardsPlugin.CE_ButtonPosition.Value;
			}
		}

		internal static void Dispose()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
			_button = null;
			_glow = null;
			_badge = null;
			_badgeBody = null;
			_badgeText = null;
		}
	}
	public class RewardsAccessButtonDrag : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(1)]
		private RectTransform _rect;

		[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(2)]
		private Canvas _canvas;

		private bool _dragging;

		private void Awake()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			_rect = (RectTransform)((Component)this).transform;
			_canvas = ((Component)this).GetComponentInParent<Canvas>();
		}

		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		public void OnBeginDrag(PointerEventData eventData)
		{
			_dragging = RewardsAccessButton.CtrlHeld;
			if (!_dragging)
			{
				eventData.pointerDrag = null;
			}
		}

		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		public void OnDrag(PointerEventData eventData)
		{
			//IL_003c: 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_0052: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			if (_dragging)
			{
				float num = (((Object)(object)_canvas != (Object)null) ? _canvas.rootCanvas.scaleFactor : 1f);
				_rect.anchoredPosition = Clamp(_rect.anchoredPosition + eventData.delta / Mathf.Max(0.01f, num));
			}
		}

		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		public void OnEndDrag(PointerEventData eventData)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (_dragging)
			{
				_dragging = false;
				RewardsAccessButton.SavePosition(_rect.anchoredPosition);
			}
		}

		private Vector2 Clamp(Vector2 position)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)_rect).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if ((Object)(object)val == (Object)null)
			{
				return position;
			}
			Rect rect = val.rect;
			Vector2 size = ((Rect)(ref rect)).size;
			rect = _rect.rect;
			Vector2 size2 = ((Rect)(ref rect)).size;
			float num = Mathf.Clamp(position.x, 0f, Mathf.Max(0f, size.x - size2.x));
			float num2 = Mathf.Clamp(position.y, (0f - size.y) * 0.5f + size2.y * 0.5f, size.y * 0.5f - size2.y * 0.5f);
			return new Vector2(num, num2);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	internal static class InventoryGui_Awake_AccessButton
	{
		[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
		private static void Postfix(InventoryGui __instance)
		{
			RewardsAccessButton.Ensure(__instance);
		}
	}
	[<9ceecfe7-7ce3-4635-930c-f9946001ebbf>NullableContext(1)]
	[<708e428e-57cb-4a78-8091-80df3604fcfc>Nullable(0)]
	internal static class RewardsArt
	{
		internal static readonly Color Gold = new Color(50f / 51f, 63f / 85f, 0.36078432f);

		internal static readonly Color GoldDim = new Color(Gold.r * 0.63f, Gold.g * 0.61f, Gold.b * 0.66f);

		internal static readonly Color Parchment = new Color(0.96f, 0.9f, 0.78f);

		internal static readonly Color Grey = new Color(0.7f, 0.64f, 0.55f);

		internal static readonly Color Refund = new Color(0.98f, 0.42f, 0.33f);

		internal static readonly Color Locked = new Color(0.32f, 0.29f, 0.26f);

		internal static Sprite Glow = null;

		internal static Sprite Haze = null;

		internal static Sprite Rounded = null;

		internal static Sprite Diamond = null;

		internal static Sprite Fade = null;

		internal static Sprite Sheen = null;

		internal static Sprite ThinRing = null;

		internal static Sprite Vignette = null;

		internal static Sprite Panel = null;

		internal static Sprite Frame = null;

		internal static Sprite FrameInner = null;

		internal static Sprite InnerShadow = null;

		internal static Sprite Corner = null;

		internal static Texture2D Grain = null;

		internal static readonly Color Iron = new Color(0.27f, 0.25f, 0.23f);

		internal static readonly Color Plate = new Color(0.06f, 0.05f, 0.042f, 0.95f);

		private static readonly List<Object> Owned = new List<Object>();

		private static readonly List<Image> NightLayers = new List<Image>();

		private static float _night;

		private static float _applied = -1f;

		internal static string Hex(Color color)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return "#" + ColorUtility.ToHtmlStringRGB(color);
		}

		internal static Image Night(Transform parent, float roundness)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			Image val = RewardsKit.Fill(parent, "Night", Rounded, new Color(0f, 0f, 0f, Mathf.Max(0f, _applied) * 0.45f), 0f);
			val.pixelsPerUnitMultiplier = roundness;
			NightLayers.Add(val);
			return val;
		}

		internal static void TickNight()
		{
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			if (Object.op_Implicit((Object)(object)EnvMan.instance))
			{
				float dayFraction = EnvMan.instance.GetDayFraction();
				num = 1f - Mathf.Clamp01((Mathf.Sin((dayFraction - 0.25f) * 2f * (float)Math.PI) + 0.3f) / 0.6f);
			}
			_night = Mathf.MoveTowards(_night, num, Time.unscaledDeltaTime * 0.25f);
			if (Mathf.Abs(_night - _applied) < 0.01f)
			{
				return;
			}
			_applied = _night;
			NightLayers.RemoveAll((Image layer) => !Object.op_Implicit((Object)(object)layer));
			foreach (Image nightLayer in NightLayers)
			{
				((Graphic)nightLayer).color = new Color(0f, 0f, 0f, _applied * 0.45f);
			}
		}

		internal static void Create()
		{
			//IL_003c: 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_00b3: 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_0119: 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)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Glow))
			{
				Glow = Build(128, 128, delegate(int x, int y)
				{
					//IL_0004: Unknown result type (might be due to invalid IL or missing references)
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					float num = Mathf.Clamp01(Vector2.Distance(new Vector2((float)x, (float)y), new Vector2(64f, 64f)) / 64f);
					return Mathf.Pow(1f - num, 2.2f);
				}, Vector4.zero);
				Random grain = new Random(7);
				Haze = Build(1024, 1024, delegate(int x, int y)
				{
					//IL_0004: Unknown result type (might be due to invalid IL or missing references)
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					float num = Mathf.Clamp01(Vector2.Distance(new Vector2((float)x, (float)y), new Vector2(511.5f, 511.5f)) / 512f);
					float num2 = (float)(grain.NextDouble() - grain.NextDouble()) * 0.12f * (1f - num);
					return Mathf.Exp((0f - num) * num * 5f) * (1f - num * num) + num2;
				}, Vector4.zero);
				Rounded = Build(64, 64, (int x, int y) => Mathf.Clamp01(0.5f - Box(x, y, 64, 16f)), new Vector4(20f, 20f, 20f, 20f));
				Diamond = Build(32, 32, (int x, int y) => Mathf.Clamp01(15.5f - Mathf.Abs((float)x - 15.5f) - Mathf.Abs((float)y - 15.5f)), Vector4.zero);
				Fade = Build(128, 4, (int x, int y) => Mathf.Sin((float)Math.PI * (float)x / 127f), Vector4.zero);
				Sheen = Build(4, 64, (int x, int y) => Mathf.Pow((float)y / 63f, 2f), Vector4.zero);
				ThinRing = Build(256, 256, delegate(int x, int y)
				{
					//IL_0004: Unknown result type (might be due to invalid IL or missing references)
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					float num = Mathf.Abs(Vector2.Distance(new Vector2((float)x, (float)y), new Vector2(127.5f, 127.5f)) - 126f);
					return Mathf.Clamp01(1.2f - num);
				}, Vector4.zero);
				Panel = Build(64, 64, (int x, int y) => Mathf.Clamp01(0.5f - Box(x, y, 64, 6f)), new Vector4(12f, 12f, 12f, 12f));
				Frame = Build(64, 64, delegate(int x, int y)
				{
					float num = Box(x, y, 64, 6f);
					return Mathf.Clamp01(0.5f - num) * Mathf.Clamp01(num + 2.5f);
				}, new Vector4(12f, 12f, 12f, 12f));
				FrameInner = Build(64, 64, delegate(int x, int y)
				{
					float num = Box(x, y, 64, 6f) + 5f;
					return Mathf.Clamp01(0.5f - num) * Mathf.Clamp01(num + 1.5f);
				}, new Vector4(14f, 14f, 14f, 14f));
				InnerShadow = Build(64, 64, delegate(int x, int y)
				{
					float num = Box(x, y, 64, 6f);
					return Mathf.Clamp01(0.5f - num) * Mathf.Pow(Mathf.Clamp01(1f + num / 22f), 2.2f);
				}, new Vector4(26f, 26f, 26f, 26f));
				Corner = Build(48, 48, delegate(int x, int y)
				{
					float num = (float)x + 0.5f;
					float nu