Decompiled source of GroundReset v2.8.1

GroundReset.dll

Decompiled a week ago
#define DEBUG
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CodeMonkey;
using GroundReset.Compatibility.WardIsLove;
using GroundReset.Compatibility.kgMarketplace;
using GroundReset.Config;
using GroundReset.Patch;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("GroundReset")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+196ff7e1e163fe682d35d0b4fa48c4ee4d48f623")]
[assembly: AssemblyProduct("GroundReset")]
[assembly: AssemblyTitle("GroundReset")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		public ExtensionMarkerAttribute(string name)
		{
		}
	}
}
namespace CodeMonkey
{
	public class FunctionTimer
	{
		private class MonoBehaviourHook : MonoBehaviour
		{
			public Action? OnUpdate;

			private void Update()
			{
				OnUpdate?.Invoke();
			}
		}

		public class FunctionTimerObject
		{
			private readonly Action callback;

			private float timer;

			public FunctionTimerObject(Action callback, float timer)
			{
				this.callback = callback;
				this.timer = timer;
			}

			public bool Update()
			{
				return Update(Time.deltaTime);
			}

			public bool Update(float deltaTime)
			{
				timer -= deltaTime;
				if (timer <= 0f)
				{
					callback();
					return true;
				}
				return false;
			}
		}

		private static List<FunctionTimer>? TimerList;

		private static GameObject? InitGameObject;

		private readonly string functionName = "NoneNameTimer";

		private readonly GameObject gameObject;

		private readonly Action onEndAction;

		private readonly bool useUnscaledDeltaTime;

		public float Timer { get; private set; }

		public FunctionTimer(GameObject gameObject, Action action, float timer, string functionName, bool useUnscaledDeltaTime)
		{
			this.gameObject = gameObject;
			onEndAction = action;
			Timer = timer;
			this.functionName = functionName;
			this.useUnscaledDeltaTime = useUnscaledDeltaTime;
		}

		private static void InitIfNeeded()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if ((Object)(object)InitGameObject == (Object)null)
			{
				InitGameObject = new GameObject("FunctionTimer_Global");
				TimerList = new List<FunctionTimer>();
			}
		}

		public static FunctionTimer? Create(Action action, float timer)
		{
			return Create(action, timer, "", useUnscaledDeltaTime: false, stopAllWithSameName: false);
		}

		public static FunctionTimer? Create(Action action, float timer, string functionName)
		{
			return Create(action, timer, functionName, useUnscaledDeltaTime: false, stopAllWithSameName: false);
		}

		public static FunctionTimer? Create(Action action, float timer, string functionName, bool useUnscaledDeltaTime)
		{
			return Create(action, timer, functionName, useUnscaledDeltaTime, stopAllWithSameName: false);
		}

		public static FunctionTimer Create(Action? action, float timer, string functionName, bool useUnscaledDeltaTime, bool stopAllWithSameName)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if (TimerList == null)
			{
				throw new NullReferenceException("TimerList");
			}
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			InitIfNeeded();
			if (stopAllWithSameName)
			{
				StopAllTimersWithName(functionName);
			}
			GameObject val = new GameObject("FunctionTimer Object " + functionName, new Type[1] { typeof(MonoBehaviourHook) });
			FunctionTimer functionTimer = new FunctionTimer(val, action, timer, functionName, useUnscaledDeltaTime);
			val.GetComponent<MonoBehaviourHook>().OnUpdate = functionTimer.Update;
			TimerList.Add(functionTimer);
			return functionTimer;
		}

		public static void RemoveTimer(FunctionTimer funcTimer)
		{
			InitIfNeeded();
			TimerList.Remove(funcTimer);
		}

		public static void StopAllTimersWithName(string functionName)
		{
			InitIfNeeded();
			checked
			{
				for (int i = 0; i < TimerList.Count; i++)
				{
					if (TimerList[i].functionName == functionName)
					{
						TimerList[i].DestroySelf();
						i--;
					}
				}
			}
		}

		public static void StopFirstTimerWithName(string functionName)
		{
			InitIfNeeded();
			for (int i = 0; i < TimerList.Count; i = checked(i + 1))
			{
				if (TimerList[i].functionName == functionName)
				{
					TimerList[i].DestroySelf();
					break;
				}
			}
		}

		private void Update()
		{
			if (useUnscaledDeltaTime)
			{
				Timer -= Time.unscaledDeltaTime;
			}
			else
			{
				Timer -= Time.deltaTime;
			}
			if (Timer <= 0f)
			{
				onEndAction();
				DestroySelf();
			}
		}

		private void DestroySelf()
		{
			RemoveTimer(this);
			if ((Object)(object)gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)gameObject);
			}
		}

		public static FunctionTimerObject CreateObject(Action callback, float timer)
		{
			return new FunctionTimerObject(callback, timer);
		}
	}
	public class FunctionUpdater
	{
		private class MonoBehaviourHook : MonoBehaviour
		{
			public Action? OnUpdate;

			private void Update()
			{
				if (OnUpdate != null)
				{
					OnUpdate();
				}
			}
		}

		private static List<FunctionUpdater>? UpdaterList;

		private static GameObject? InitGameObject;

		private readonly string functionName;

		private readonly GameObject gameObject;

		private readonly Func<bool> updateFunc;

		private bool active;

		public FunctionUpdater(GameObject gameObject, Func<bool> updateFunc, string functionName, bool active)
		{
			this.gameObject = gameObject;
			this.updateFunc = updateFunc;
			this.functionName = functionName;
			this.active = active;
		}

		private static void InitIfNeeded()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if ((Object)(object)InitGameObject == (Object)null)
			{
				InitGameObject = new GameObject("FunctionUpdater_Global");
				UpdaterList = new List<FunctionUpdater>();
			}
		}

		public static FunctionUpdater Create(Action updateFunc)
		{
			Action updateFunc2 = updateFunc;
			return Create(delegate
			{
				updateFunc2();
				return false;
			}, "", active: true, stopAllWithSameName: false);
		}

		public static FunctionUpdater Create(Action updateFunc, string functionName)
		{
			Action updateFunc2 = updateFunc;
			return Create(delegate
			{
				updateFunc2();
				return false;
			}, functionName, active: true, stopAllWithSameName: false);
		}

		public static FunctionUpdater Create(Func<bool> updateFunc)
		{
			return Create(updateFunc, "", active: true, stopAllWithSameName: false);
		}

		public static FunctionUpdater Create(Func<bool> updateFunc, string functionName)
		{
			return Create(updateFunc, functionName, active: true, stopAllWithSameName: false);
		}

		public static FunctionUpdater Create(Func<bool> updateFunc, string functionName, bool active)
		{
			return Create(updateFunc, functionName, active, stopAllWithSameName: false);
		}

		public static FunctionUpdater Create(Func<bool> updateFunc, string functionName, bool active, bool stopAllWithSameName)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			InitIfNeeded();
			if (stopAllWithSameName)
			{
				StopAllUpdatersWithName(functionName);
			}
			GameObject val = new GameObject("FunctionUpdater Object " + functionName, new Type[1] { typeof(MonoBehaviourHook) });
			FunctionUpdater functionUpdater = new FunctionUpdater(val, updateFunc, functionName, active);
			val.GetComponent<MonoBehaviourHook>().OnUpdate = functionUpdater.Update;
			UpdaterList.Add(functionUpdater);
			return functionUpdater;
		}

		private static void RemoveUpdater(FunctionUpdater funcUpdater)
		{
			InitIfNeeded();
			UpdaterList.Remove(funcUpdater);
		}

		public static void DestroyUpdater(FunctionUpdater? funcUpdater)
		{
			InitIfNeeded();
			funcUpdater?.DestroySelf();
		}

		public static void StopUpdaterWithName(string functionName)
		{
			InitIfNeeded();
			for (int i = 0; i < UpdaterList.Count; i = checked(i + 1))
			{
				if (UpdaterList[i].functionName == functionName)
				{
					UpdaterList[i].DestroySelf();
					break;
				}
			}
		}

		public static void StopAllUpdatersWithName(string functionName)
		{
			InitIfNeeded();
			checked
			{
				for (int i = 0; i < UpdaterList.Count; i++)
				{
					if (UpdaterList[i].functionName == functionName)
					{
						UpdaterList[i].DestroySelf();
						i--;
					}
				}
			}
		}

		public void Pause()
		{
			active = false;
		}

		public void Resume()
		{
			active = true;
		}

		private void Update()
		{
			if (active && updateFunc())
			{
				DestroySelf();
			}
		}

		public void DestroySelf()
		{
			RemoveUpdater(this);
			if ((Object)(object)gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)gameObject);
			}
		}
	}
}
namespace GroundReset
{
	[Serializable]
	public class ChunkData
	{
		public bool[] m_modifiedHeight;

		public float[] m_levelDelta;

		public float[] m_smoothDelta;

		public bool[] m_modifiedPaint;

		public Color[] m_paintMask;

		public float m_lastOpRadius;

		public Vector3 m_lastOpPoint;

		public int m_operations;

		public ChunkData()
		{
			checked
			{
				int num = Reseter.HeightmapWidth + 1;
				m_modifiedHeight = new bool[num * num];
				m_levelDelta = new float[num * num];
				m_smoothDelta = new float[num * num];
				m_modifiedPaint = new bool[num * num];
				m_paintMask = (Color[])(object)new Color[num * num];
			}
		}
	}
	public static class Consts
	{
		public const string ModName = "GroundReset";

		public const string ModAuthor = "Frogger";

		public const string ModVersion = "2.8.0";

		public const string ModGuid = "com.Frogger.GroundReset";

		public const string TimerId = "JF_GroundReset";

		public const string MainSceneName = "main";

		public const string ThorwardPrefabName = "Thorward";

		public const string ArcaneWardPrefabName = "ArcaneWard";

		public const string ArcaneWardZdoKey = "Radius";

		public const string TerrCompPrefabName = "_TerrainCompiler";

		public static readonly int RadiusNetKey = StringExtensionMethods.GetStableHashCode("wardRadius");

		public const string TimerPassedTimeSaveFileName = "ModName_LastTimerTimePassed.txt";

		public static readonly Lazy<string> TimerPassedTimeSaveFilePath = new Lazy<string>(() => Path.Combine(Paths.ConfigPath, "ModName_LastTimerTimePassed.txt"));
	}
	public static class Helper
	{
		public static bool IsMainScene()
		{
			//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)
			Scene activeScene = SceneManager.GetActiveScene();
			return ((Scene)(ref activeScene)).IsValid() && ((Scene)(ref activeScene)).name == "main";
		}

		public static bool IsServer(bool logIsShouldBeOnServerOnly = false)
		{
			GameServerClientState gameServerClientState = GetGameServerClientState();
			if (logIsShouldBeOnServerOnly && gameServerClientState == GameServerClientState.Client)
			{
				Log.Error("ModName is fully server-side, do not install it on clients");
			}
			return gameServerClientState == GameServerClientState.Server;
		}

		public static GameServerClientState GetGameServerClientState()
		{
			ZNet instance = ZNet.instance;
			bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null);
			if (1 == 0)
			{
			}
			GameServerClientState result = (flag.HasValue ? ((!flag.GetValueOrDefault()) ? GameServerClientState.Client : GameServerClientState.Server) : GameServerClientState.Unknown);
			if (1 == 0)
			{
			}
			return result;
		}
	}
	public enum GameServerClientState
	{
		Unknown,
		Client,
		Server
	}
	public static class Log
	{
		private static ManualLogSource? _logger;

		private static BaseUnityPlugin _plugin;

		public static void InitializeConfiguration(BaseUnityPlugin plugin)
		{
			_plugin = plugin;
			_logger = GetProtectedLogger(_plugin);
		}

		private static ManualLogSource GetProtectedLogger(object instance)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			if (instance == null)
			{
				throw new ArgumentNullException("instance");
			}
			Type type = instance.GetType();
			PropertyInfo property = type.GetProperty("Logger", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property == null)
			{
				throw new MissingMemberException(type.FullName, "Logger");
			}
			MethodInfo getMethod = property.GetGetMethod(nonPublic: true);
			if (getMethod == null)
			{
				throw new MissingMethodException("Property " + type.FullName + ".Logger does not have a getter");
			}
			ManualLogSource val = (ManualLogSource)getMethod.Invoke(instance, null);
			return val ?? throw new Exception("Failed to get Logger");
		}

		public static void Info(string message, bool insertTimestamp = false)
		{
			if (_logger != null)
			{
				if (insertTimestamp)
				{
					message = DateTime.Now.ToString("G") + message;
				}
				_logger.LogInfo((object)message);
			}
		}

		public static void Error(Exception ex, string message = "", bool insertTimestamp = false)
		{
			if (_logger != null)
			{
				if (insertTimestamp)
				{
					message = DateTime.Now.ToString("G") + message;
				}
				if (string.IsNullOrEmpty(message))
				{
					message += Environment.NewLine;
				}
				_logger.LogError((object)(message + ex));
			}
		}

		public static void Error(string message, bool insertTimestamp = false)
		{
			if (_logger != null)
			{
				if (insertTimestamp)
				{
					message = DateTime.Now.ToString("G") + message;
				}
				_logger.LogError((object)message);
			}
		}

		public static void Warning(Exception ex, string message, bool insertTimestamp = false)
		{
			if (_logger != null)
			{
				if (insertTimestamp)
				{
					message = DateTime.Now.ToString("G") + message;
				}
				if (string.IsNullOrEmpty(message))
				{
					message += Environment.NewLine;
				}
				_logger.LogWarning((object)(message + ex));
			}
		}

		public static void Warning(string message, bool insertTimestamp = false)
		{
			if (_logger != null)
			{
				if (insertTimestamp)
				{
					message = DateTime.Now.ToString("G") + message;
				}
				_logger.LogWarning((object)message);
			}
		}
	}
	[BepInPlugin("com.Frogger.GroundReset", "GroundReset", "2.8.0")]
	public class Plugin : BaseUnityPlugin
	{
		private void Awake()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Log.InitializeConfiguration((BaseUnityPlugin)(object)this);
			new Harmony("com.Frogger.GroundReset").PatchAll();
			ConfigsContainer.InitializeConfiguration((BaseUnityPlugin)(object)this);
		}
	}
	public static class Reseter
	{
		public static readonly int HeightmapWidth = 64;

		public static readonly int HeightmapScale = 1;

		private static List<ZDO> wards = new List<ZDO>();

		public static List<WardSettings> wardsSettingsList = new List<WardSettings>();

		public static Stopwatch watch = new Stopwatch();

		public static async Task ResetAll(bool checkIfNeed = true, bool checkWards = true, bool ranFromConsole = false)
		{
			try
			{
				await FindWards();
				await Terrains.ResetTerrains(checkWards);
				if (ranFromConsole)
				{
					((Terminal)Console.instance).AddString("<color=green> Done </color>");
				}
				wards.Clear();
			}
			catch (Exception ex)
			{
				Exception e = ex;
				Log.Error($"ResetAll failed with exception: {e}");
			}
		}

		private static async Task FindWards()
		{
			watch.Restart();
			wards.Clear();
			for (int i = 0; i < wardsSettingsList.Count; i = checked(i + 1))
			{
				wards = Enumerable.Concat(second: await ZoneSystemExtension.GetWorldObjectsAsync(prefabName: wardsSettingsList[i].PrefabName, zdoMan: ZDOMan.instance, customFilters: Array.Empty<Func<ZDO, bool>>()), first: wards).ToList();
			}
			Log.Warning(string.Format(arg1: TimeSpan.FromMilliseconds(watch.ElapsedMilliseconds).TotalSeconds, format: "Wards count: {0}. Took {1} seconds", arg0: wards.Count));
			watch.Restart();
		}

		public static Vector3 HmapToWorld(Vector3 heightmapPos, int x, int y)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			float num = ((float)x - (float)(HeightmapWidth / 2)) * (float)HeightmapScale;
			float num2 = ((float)y - (float)(HeightmapWidth / 2)) * (float)HeightmapScale;
			return heightmapPos + new Vector3(num, 0f, num2);
		}

		public static void WorldToVertex(Vector3 worldPos, Vector3 heightmapPos, out int x, out int y)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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)
			Vector3 val = worldPos - heightmapPos;
			checked
			{
				x = Mathf.FloorToInt((float)((double)val.x / (double)HeightmapScale + 0.5)) + unchecked(HeightmapWidth / 2);
				y = Mathf.FloorToInt((float)((double)val.z / (double)HeightmapScale + 0.5)) + unchecked(HeightmapWidth / 2);
			}
		}

		public static bool IsInWard(Vector3 pos, float checkRadius = 0f)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			return wards.Exists(delegate(ZDO searchWard)
			{
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				ZDO searchWard2 = searchWard;
				WardSettings wardSettings = wardsSettingsList.Find((WardSettings s) => StringExtensionMethods.GetStableHashCode(s.PrefabName) == searchWard2.GetPrefab());
				if (!searchWard2.GetBool(ZDOVars.s_enabled, true))
				{
					return false;
				}
				float num = (wardSettings.DynamicRadius ? wardSettings.GetDynamicRadius(searchWard2) : wardSettings.Radius);
				return Utils.DistanceXZ(pos, searchWard2.GetPosition()) <= num + checkRadius;
			}) || MarketplaceTerritorySystem.PointInTerritory(pos);
		}

		public static bool IsInWard(Vector3 zoneCenter, int w, int h)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return IsInWard(HmapToWorld(zoneCenter, w, h));
		}
	}
	public enum ResetOrder
	{
		HeightAndSmoothingAndColor,
		HeightAndSmoothing_Color,
		Height_Smoothing_Color,
		Height_Color_Smoothing
	}
	public static class ResetTerrainTimer
	{
		private static TimeSpan LastTimerTimePassed = TimeSpan.Zero;

		private static readonly Action? _onTimer = async delegate
		{
			try
			{
				Log.Info("Timer Triggered, starting chunks reset", insertTimestamp: true);
				await Reseter.ResetAll();
				Log.Info("Timer Triggered, chunks have been reset, restarting the timer", insertTimestamp: true);
				RestartTimer();
			}
			catch (Exception ex)
			{
				Exception exception1 = ex;
				Log.Error($"OnTimer event failed with exception: {exception1}");
				RestartTimer();
			}
		};

		private static FunctionTimer? Timer { get; set; } = null;


		public static void RestartTimer()
		{
			try
			{
				Log.Info("ResetTerrainTimer.RestartTimer");
				if (!Helper.IsMainScene() || !Helper.IsServer(logIsShouldBeOnServerOnly: true))
				{
					return;
				}
				Log.Info("Stopping existing timers");
				FunctionTimer.StopAllTimersWithName("JF_GroundReset");
				Timer = null;
				TimeSpan timeSpan = TimeSpan.FromMinutes(ConfigsContainer.TriggerIntervalInMinutes);
				if (LastTimerTimePassed != TimeSpan.Zero)
				{
					try
					{
						timeSpan -= LastTimerTimePassed;
					}
					catch
					{
						timeSpan = TimeSpan.FromSeconds(1.0);
					}
					if (timeSpan.TotalSeconds <= 0.0)
					{
						timeSpan = TimeSpan.FromSeconds(1.0);
					}
				}
				Log.Info($"Creating new timer for {timeSpan:hh\\:mm\\:ss}", insertTimestamp: true);
				try
				{
					Timer = FunctionTimer.Create(_onTimer, (float)timeSpan.TotalSeconds, "JF_GroundReset", useUnscaledDeltaTime: true, stopAllWithSameName: true);
				}
				catch (Exception arg)
				{
					Log.Error($"FunctionTimer.Create failed with exception: {arg}");
				}
				LastTimerTimePassed = TimeSpan.Zero;
			}
			catch (Exception arg2)
			{
				Log.Error(string.Format("{0} failed with exception: {1}", "RestartTimer", arg2));
			}
		}

		public static void LoadTimePassedFromFile()
		{
			string value = Consts.TimerPassedTimeSaveFilePath.Value;
			if (!File.Exists(value))
			{
				File.Create(value);
				File.WriteAllText(value, 0f.ToString(NumberFormatInfo.InvariantInfo));
				LastTimerTimePassed = TimeSpan.Zero;
				return;
			}
			string s = File.ReadAllText(value);
			if (!float.TryParse(s, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var result))
			{
				Log.Warning("Failed to read invalid value from timer save file, overwritten with zero");
				File.WriteAllText(value, 0f.ToString(NumberFormatInfo.InvariantInfo));
				LastTimerTimePassed = TimeSpan.Zero;
			}
			else
			{
				LastTimerTimePassed = TimeSpan.FromSeconds(result);
				Log.Info($"Loaded last timer passed time: {LastTimerTimePassed:hh\\:mm\\:ss}");
			}
		}

		public static void SavePassedTimerTimeToFile()
		{
			Debug.Assert(Timer != null);
			if (Timer == null)
			{
				Log.Warning("Can not save timer passed time before its creation");
				return;
			}
			string value = Consts.TimerPassedTimeSaveFilePath.Value;
			if (!File.Exists(value))
			{
				File.Create(value);
			}
			float timer = Timer.Timer;
			LastTimerTimePassed = TimeSpan.FromSeconds(timer);
			File.WriteAllText(value, timer.ToString(NumberFormatInfo.InvariantInfo));
			Log.Info($"Saved timer passed time to file: {LastTimerTimePassed:hh\\:mm\\:ss}");
		}
	}
	public static class Terrains
	{
		public static async Task<int> ResetTerrains(bool checkWards, int? maxDegreeOfParallelism = null)
		{
			MessageHud.instance.MessageAll((MessageType)1, "Идёт сброс ландшафта...");
			Reseter.watch.Restart();
			List<ZDO> zdos = await ZDOMan.instance.GetWorldObjectsAsync("_TerrainCompiler");
			if (zdos.Count == 0)
			{
				Log.Info("0 chunks have been reset. Took 0.0 seconds");
				Reseter.watch.Stop();
				return 0;
			}
			Log.Info($"Found {zdos.Count} chunks to reset", insertTimestamp: true);
			checked
			{
				int dop = maxDegreeOfParallelism ?? Math.Max(1, Environment.ProcessorCount - 1);
				SemaphoreSlim semaphore = new SemaphoreSlim(dop, dop);
				ConcurrentBag<(ZDO zdo, ChunkData data)> results = new ConcurrentBag<(ZDO, ChunkData)>();
				int completed = 0;
				int currentBatchIndex = 0;
				for (int i = 0; i < zdos.Count; i += 32)
				{
					int count = Math.Min(32, zdos.Count - i);
					List<Task> batchTasks = new List<Task>(count);
					for (int j = 0; j < count; j++)
					{
						ZDO zdo = zdos[i + j];
						await semaphore.WaitAsync();
						Task t = Task.Run(async delegate
						{
							try
							{
								ChunkData newChunkData = await ResetTerrainComp(zdo, checkWards);
								if (newChunkData != null)
								{
									results.Add((zdo, newChunkData));
									Interlocked.Increment(ref completed);
								}
							}
							catch (Exception ex3)
							{
								Exception ex2 = ex3;
								Log.Warning($"ResetTerrainComp failed for zdo {zdo.m_uid}: {ex2}");
							}
							finally
							{
								try
								{
									semaphore?.Release();
								}
								catch (ObjectDisposedException)
								{
									semaphore = null;
									Log.Error("ObjectDisposedException from ResetTerrains for SemaphoreSlim");
								}
							}
						});
						batchTasks.Add(t);
					}
					Log.Info($"Processing batch {currentBatchIndex}");
					await Task.WhenAll(batchTasks);
					currentBatchIndex++;
					await Task.Yield();
				}
				semaphore.Dispose();
				Log.Info($"New data been generated for {completed} chunks. Applying each to game world...", insertTimestamp: true);
				int saved = 0;
				foreach (var (zdo2, data) in results)
				{
					try
					{
						SaveData(zdo2, data);
						saved++;
					}
					catch (Exception ex)
					{
						Log.Warning($"SaveData failed for zdo {zdo2.m_uid}: {ex}");
					}
				}
				foreach (TerrainComp comp in TerrainComp.s_instances)
				{
					Heightmap hmap = comp.m_hmap;
					if (hmap != null)
					{
						hmap.Poke(false);
					}
				}
				Log.Info(string.Format(arg2: TimeSpan.FromMilliseconds(Reseter.watch.ElapsedMilliseconds).TotalSeconds, format: "{0} chunks have been reset, {1} saved. Took {2} seconds", arg0: completed, arg1: saved), insertTimestamp: true);
				Reseter.watch.Stop();
				MessageHud.instance.MessageAll((MessageType)1, "Сброс ландшафта завершён");
				return completed;
			}
		}

		private static async Task<ChunkData?> ResetTerrainComp(ZDO zdo, bool checkWards)
		{
			float divider = ConfigsContainer.Divider;
			bool resetSmooth = ConfigsContainer.ResetSmoothing;
			bool resetSmoothingLast = ConfigsContainer.ResetSmoothing;
			float minHeightToSteppedReset = ConfigsContainer.MinHeightToSteppedReset;
			Vector3 zoneCenter = ZoneSystem.GetZonePos(ZoneSystem.GetZone(zdo.GetPosition()));
			ChunkData data;
			try
			{
				data = LoadOldData(zdo);
			}
			catch (Exception ex)
			{
				Exception e = ex;
				Log.Error(e);
				return null;
			}
			if (data == null)
			{
				return null;
			}
			checked
			{
				int num = Reseter.HeightmapWidth + 1;
				for (int h = 0; h < num; h++)
				{
					for (int w = 0; w < num; w++)
					{
						int idx = h * num + w;
						if (!data.m_modifiedHeight[idx] || (checkWards && Reseter.IsInWard(zoneCenter, w, h)))
						{
							continue;
						}
						data.m_levelDelta[idx] /= divider;
						if (Mathf.Abs(data.m_levelDelta[idx]) < minHeightToSteppedReset)
						{
							data.m_levelDelta[idx] = 0f;
						}
						if (resetSmooth && (!resetSmoothingLast || data.m_levelDelta[idx] == 0f))
						{
							data.m_smoothDelta[idx] /= divider;
							if (Mathf.Abs(data.m_smoothDelta[idx]) < minHeightToSteppedReset)
							{
								data.m_smoothDelta[idx] = 0f;
							}
						}
						bool flag_b = resetSmooth && data.m_smoothDelta[idx] != 0f;
						unchecked
						{
							data.m_modifiedHeight[idx] = data.m_levelDelta[idx] != 0f || flag_b;
							if (idx % 1000 == 0)
							{
								await Task.Yield();
							}
						}
					}
				}
				int paintLenMun1 = data.m_modifiedPaint.Length - 1;
				for (int h2 = 0; h2 < num; h2++)
				{
					for (int w2 = 0; w2 < num; w2++)
					{
						int idx2 = h2 * num + w2;
						if (idx2 > paintLenMun1 || !data.m_modifiedPaint[idx2])
						{
							continue;
						}
						Color currentPaint = data.m_paintMask[idx2];
						if (IsPaintIgnored(currentPaint))
						{
							continue;
						}
						if (checkWards || ConfigsContainer.ResetPaintResetLastly)
						{
							Vector3 worldPos = Reseter.HmapToWorld(zoneCenter, w2, h2);
							if (checkWards && Reseter.IsInWard(worldPos))
							{
								continue;
							}
							if (ConfigsContainer.ResetPaintResetLastly)
							{
								Reseter.WorldToVertex(worldPos, zoneCenter, out var _, out var _);
								int heightIdx = idx2;
								if (data.m_modifiedHeight.Length > heightIdx && data.m_modifiedHeight[heightIdx])
								{
									continue;
								}
							}
						}
						data.m_modifiedPaint[idx2] = false;
						data.m_paintMask[idx2] = Heightmap.m_paintMaskNothing;
						if (unchecked(idx2 % 1000) == 0)
						{
							await Task.Yield();
						}
					}
				}
				return data;
			}
		}

		private static bool IsPaintIgnored(Color color)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return ConfigsContainer.PaintsToIgnore.Exists((Color x) => Mathf.Abs(x.r - color.r) < ConfigsContainer.PaintsCompareTolerance && Mathf.Abs(x.b - color.b) < ConfigsContainer.PaintsCompareTolerance && Mathf.Abs(x.g - color.g) < ConfigsContainer.PaintsCompareTolerance && Mathf.Abs(x.a - color.a) < ConfigsContainer.PaintsCompareTolerance);
		}

		private static void SaveData(ZDO zdo, ChunkData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(1);
			val.Write(data.m_operations);
			val.Write(data.m_lastOpPoint);
			val.Write(data.m_lastOpRadius);
			val.Write(data.m_modifiedHeight.Length);
			checked
			{
				for (int i = 0; i < data.m_modifiedHeight.Length; i++)
				{
					val.Write(data.m_modifiedHeight[i]);
					if (data.m_modifiedHeight[i])
					{
						val.Write(data.m_levelDelta[i]);
						val.Write(data.m_smoothDelta[i]);
					}
				}
				val.Write(data.m_modifiedPaint.Length);
				for (int j = 0; j < data.m_modifiedPaint.Length; j++)
				{
					val.Write(data.m_modifiedPaint[j]);
					if (data.m_modifiedPaint[j])
					{
						val.Write(data.m_paintMask[j].r);
						val.Write(data.m_paintMask[j].g);
						val.Write(data.m_paintMask[j].b);
						val.Write(data.m_paintMask[j].a);
					}
				}
				byte[] array = Utils.Compress(val.GetArray());
				zdo.Set(ZDOVars.s_TCData, array);
			}
		}

		private static ChunkData? LoadOldData(ZDO zdo)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			ChunkData chunkData = new ChunkData();
			byte[] byteArray = zdo.GetByteArray(ZDOVars.s_TCData, (byte[])null);
			if (byteArray == null)
			{
				Log.Warning("ByteArray is null, aborting chunk load");
				return null;
			}
			ZPackage val = new ZPackage(Utils.Decompress(byteArray));
			val.ReadInt();
			chunkData.m_operations = val.ReadInt();
			chunkData.m_lastOpPoint = val.ReadVector3();
			chunkData.m_lastOpRadius = val.ReadSingle();
			int num = val.ReadInt();
			if (num != chunkData.m_modifiedHeight.Length)
			{
				Log.Warning("Terrain data load error, height array missmatch");
				return null;
			}
			checked
			{
				for (int i = 0; i < num; i++)
				{
					chunkData.m_modifiedHeight[i] = val.ReadBool();
					if (chunkData.m_modifiedHeight[i])
					{
						chunkData.m_levelDelta[i] = val.ReadSingle();
						chunkData.m_smoothDelta[i] = val.ReadSingle();
					}
					else
					{
						chunkData.m_levelDelta[i] = 0f;
						chunkData.m_smoothDelta[i] = 0f;
					}
				}
				int num2 = val.ReadInt();
				if (num2 != chunkData.m_modifiedPaint.Length)
				{
					Log.Warning($"Terrain data load error, paint array missmatch, num2={num2}, modifiedPaint.Length={chunkData.m_modifiedPaint.Length}, paintMask.Length={chunkData.m_paintMask.Length}");
					num2 = Mathf.Max(new int[3]
					{
						num2,
						chunkData.m_modifiedPaint.Length,
						chunkData.m_paintMask.Length
					});
					if (chunkData.m_modifiedPaint.Length != num2)
					{
						Array.Resize(ref chunkData.m_modifiedPaint, num2);
					}
					if (chunkData.m_paintMask.Length != num2)
					{
						Array.Resize(ref chunkData.m_paintMask, num2);
					}
				}
				for (int j = 0; j < num2; j++)
				{
					chunkData.m_modifiedPaint[j] = val.ReadBool();
					if (chunkData.m_modifiedPaint[j])
					{
						chunkData.m_paintMask[j] = new Color
						{
							r = val.ReadSingle(),
							g = val.ReadSingle(),
							b = val.ReadSingle(),
							a = val.ReadSingle()
						};
					}
					else
					{
						chunkData.m_paintMask[j] = Color.black;
					}
				}
				if (num2 == Reseter.HeightmapWidth * Reseter.HeightmapWidth)
				{
					Color[] array = (Color[])(object)new Color[chunkData.m_paintMask.Length];
					chunkData.m_paintMask.CopyTo(array, 0);
					bool[] array2 = new bool[chunkData.m_modifiedPaint.Length];
					chunkData.m_modifiedPaint.CopyTo(array2, 0);
					int num3 = Reseter.HeightmapWidth + 1;
					for (int k = 0; k < chunkData.m_paintMask.Length; k++)
					{
						int num4;
						int num5;
						unchecked
						{
							num4 = k / num3;
							num5 = checked(k + 1) / num3;
						}
						int num6 = k - num4;
						if (num4 == Reseter.HeightmapWidth)
						{
							num6 -= Reseter.HeightmapWidth;
						}
						if (unchecked(k > 0 && checked(k - num4) % Reseter.HeightmapWidth == 0 && checked(k + 1 - num5) % Reseter.HeightmapWidth == 0))
						{
							num6--;
						}
						chunkData.m_paintMask[k] = array[num6];
						chunkData.m_modifiedPaint[k] = array2[num6];
					}
				}
				return chunkData;
			}
		}
	}
	public readonly struct WardSettings
	{
		public readonly string PrefabName;

		public readonly float Radius;

		public readonly bool DynamicRadius;

		public readonly Func<ZDO, float>? GetDynamicRadius;

		public WardSettings(string prefabName, float radius)
		{
			PrefabName = prefabName;
			Radius = radius;
			DynamicRadius = false;
			GetDynamicRadius = null;
		}

		public WardSettings(string prefabName, Func<ZDO, float> getDynamicRadius)
			: this(prefabName, 0f)
		{
			DynamicRadius = true;
			GetDynamicRadius = getDynamicRadius;
		}
	}
	public static class ZoneSystemExtension
	{
		[SpecialName]
		public sealed class <G>$3E211C4942004AED17A96F7003432F95
		{
			[SpecialName]
			public static class <M>$F0FDFD622C638468FB396627F45BD4C6
			{
			}

			[ExtensionMarker("<M>$F0FDFD622C638468FB396627F45BD4C6")]
			public Task<List<ZDO>> GetWorldObjectsAsync(params Func<ZDO, bool>[] customFilters)
			{
				throw null;
			}

			[ExtensionMarker("<M>$F0FDFD622C638468FB396627F45BD4C6")]
			public Task<List<ZDO>> GetWorldObjectsAsync()
			{
				throw null;
			}

			[ExtensionMarker("<M>$F0FDFD622C638468FB396627F45BD4C6")]
			public Task<List<ZDO>> GetWorldObjectsAsync(string prefabName, params Func<ZDO, bool>[] customFilters)
			{
				throw null;
			}
		}

		public static Task<List<ZDO>> GetWorldObjectsAsync(this ZDOMan zdoMan, params Func<ZDO, bool>[] customFilters)
		{
			Func<ZDO, bool>[] customFilters2 = customFilters;
			List<ZDO> zdos = new List<ZDO>(zdoMan.m_objectsByID.Values);
			return Task.Run(delegate
			{
				if (customFilters2.Length == 0)
				{
					return zdos;
				}
				zdos = zdos.Where((ZDO x) => customFilters2.All((Func<ZDO, bool> filter) => filter?.Invoke(x) ?? true)).ToList();
				return zdos;
			});
		}

		public static Task<List<ZDO>> GetWorldObjectsAsync(this ZDOMan zdoMan)
		{
			return zdoMan.GetWorldObjectsAsync(Array.Empty<Func<ZDO, bool>>());
		}

		public static Task<List<ZDO>> GetWorldObjectsAsync(this ZDOMan zdoMan, string prefabName, params Func<ZDO, bool>[] customFilters)
		{
			int prefabHash = StringExtensionMethods.GetStableHashCode(prefabName);
			Func<ZDO, bool> func = (ZDO zdo) => zdo.GetPrefab() == prefabHash;
			return zdoMan.GetWorldObjectsAsync(CollectionExtensions.AddItem<Func<ZDO, bool>>((IEnumerable<Func<ZDO, bool>>)customFilters, func).ToArray());
		}
	}
}
namespace GroundReset.Patch
{
	[HarmonyPatch]
	[HarmonyWrapSafe]
	public static class InitWardsSettings
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static void Init(ZNetScene __instance)
		{
			if (Helper.IsMainScene() && Helper.IsServer(logIsShouldBeOnServerOnly: true))
			{
				RegisterWards();
			}
		}

		public static void RegisterWards()
		{
			Reseter.wardsSettingsList.Clear();
			AddWard("guard_stone");
			AddWardThorward();
			AddWardArcaneWard();
			if (Object.op_Implicit((Object)(object)ZNetScene.instance) && ZNetScene.instance.m_prefabs != null && ZNetScene.instance.m_prefabs.Count > 0)
			{
				List<GameObject> list = ZNetScene.instance.m_prefabs.Where((GameObject x) => Object.op_Implicit((Object)(object)x.GetComponent<PrivateArea>())).ToList();
				foreach (GameObject item in list)
				{
					AddWard(((Object)item).name);
				}
			}
			Log.Info(string.Format("Found {0} wards: {1}", Reseter.wardsSettingsList.Count, string.Join(",", Reseter.wardsSettingsList.Select((WardSettings x) => x.PrefabName).ToArray())));
		}

		private static void AddWard(string name)
		{
			string name2 = name;
			GameObject prefab = ZNetScene.instance.GetPrefab(StringExtensionMethods.GetStableHashCode(name2));
			if (Object.op_Implicit((Object)(object)prefab))
			{
				PrivateArea component = prefab.GetComponent<PrivateArea>();
				if (!Reseter.wardsSettingsList.Any((WardSettings x) => x.PrefabName == name2))
				{
					Reseter.wardsSettingsList.Add(new WardSettings(name2, component.m_radius));
				}
			}
		}

		private static void AddWardThorward()
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(StringExtensionMethods.GetStableHashCode("Thorward"));
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return;
			}
			Reseter.wardsSettingsList.Add(new WardSettings("Thorward", delegate(ZDO zdo)
			{
				float num = zdo.GetFloat(AzuWardZdoKeys.wardRadius, 0f);
				if (num == 0f)
				{
					num = WardIsLovePlugin.WardRange().Value;
				}
				return num;
			}));
		}

		private static void AddWardArcaneWard()
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(StringExtensionMethods.GetStableHashCode("ArcaneWard"));
			if (Object.op_Implicit((Object)(object)prefab))
			{
				Reseter.wardsSettingsList.Add(new WardSettings("ArcaneWard", delegate(ZDO zdo)
				{
					int @int = zdo.GetInt("Radius", 0);
					return @int;
				}));
			}
		}
	}
	[HarmonyPatch]
	internal static class <SaveTimeTime>F89BC5C220AA90407393A274ECD38C850BA046FF448EF2BFDB09729394C9F3AE8__SaveTimerTimePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZNet), "Save")]
		private static void SaveTime()
		{
			if (Helper.IsServer(logIsShouldBeOnServerOnly: true))
			{
				ResetTerrainTimer.SavePassedTimerTimeToFile();
			}
		}
	}
	[HarmonyPatch]
	internal static class <StartTimer>F453AA1323802C7D6CD495C20FF7170F1EADCB006C45B75DB34A29DD1E760F698__StartTimerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static void StartTimer()
		{
			if (Helper.IsMainScene() && Helper.IsServer(logIsShouldBeOnServerOnly: true))
			{
				ResetTerrainTimer.RestartTimer();
			}
		}
	}
}
namespace GroundReset.Config
{
	public class ConfigsContainer
	{
		private readonly ConfigEntry<float> _triggerIntervalInMinutesConfig;

		private readonly ConfigEntry<float> _dividerConfig;

		private readonly ConfigEntry<float> _minHeightToSteppedResetConfig;

		private readonly ConfigEntry<float> _paintsCompareToleranceConfig;

		private readonly ConfigEntry<string> _paintsToIgnoreConfig;

		private readonly ConfigEntry<bool> _resetSmoothingConfig;

		private readonly ConfigEntry<bool> _resetPaintResetLastlyConfig;

		private float _lastTriggerIntervalInMinutes = -1f;

		private readonly List<Color> _paintsToIgnore = new List<Color>();

		private readonly Dictionary<string, Color> vanillaPresets = new Dictionary<string, Color>
		{
			{
				"Dirt",
				Heightmap.m_paintMaskDirt
			},
			{
				"Cultivated",
				Heightmap.m_paintMaskCultivated
			},
			{
				"Paved",
				Heightmap.m_paintMaskPaved
			},
			{
				"Nothing",
				Heightmap.m_paintMaskNothing
			}
		};

		[CompilerGenerated]
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private static ConfigsContainer <Instance>k__BackingField = null;

		private static bool _isInitialized = false;

		private static BaseUnityPlugin _plugin = null;

		private static Action? OnConfigurationChanged;

		private static DateTime _lastConfigChange = DateTime.MinValue;

		private static readonly HashSet<string> _configFilesToWatch = new HashSet<string>();

		public static float TriggerIntervalInMinutes => Instance._triggerIntervalInMinutesConfig.Value;

		public static float Divider => Instance._dividerConfig.Value;

		public static float MinHeightToSteppedReset => Instance._minHeightToSteppedResetConfig.Value;

		public static float PaintsCompareTolerance => Instance._paintsCompareToleranceConfig.Value;

		public static List<Color> PaintsToIgnore => Instance._paintsToIgnore;

		public static bool ResetSmoothing => Instance._resetSmoothingConfig.Value;

		public static bool ResetPaintResetLastly => Instance._resetPaintResetLastlyConfig.Value;

		private static ConfigsContainer Instance
		{
			get
			{
				if (!_isInitialized)
				{
					throw new NullReferenceException("ConfigsContainer is not yet initialized");
				}
				return <Instance>k__BackingField;
			}
			[CompilerGenerated]
			set
			{
				<Instance>k__BackingField = value;
			}
		}

		private ConfigsContainer()
		{
			//IL_0022: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			_triggerIntervalInMinutesConfig = config("General", "TheTriggerTime", 4320f, "Time in real minutes between reset steps.");
			_dividerConfig = config("General", "Divider", 1.7f, "The divider for the terrain restoration. Current value will be divided by this value. Learn more on mod page.");
			_minHeightToSteppedResetConfig = config("General", "Min Height To Stepped Reset", 0.2f, "If the height delta is lower than this value, it will be counted as zero.");
			_paintsToIgnoreConfig = config("General", "Paint To Ignore", "(Paved), (Cultivated)", "This paints will be ignored in the reset process.\n" + string.Join(",", vanillaPresets.Keys));
			_paintsCompareToleranceConfig = config("General", "Paints Compair Tolerance", 0.3f, "The accuracy of the comparison of colors. Since the current values of the same paint may differ from the reference in different situations, they have to be compared with the difference in this value.");
			_resetSmoothingConfig = config("General", "Reset Smoothing", value: true, "Should the terrain smoothing be reset");
			_resetPaintResetLastlyConfig = config("General", "Process Paint Lastly", value: true, "Set to true so that the paint is reset only after the ground height delta and smoothing is completely reset. Otherwise, the paint will be reset at each reset step along with the height delta.");
		}

		private void ApplyConfiguration()
		{
			float num = Math.Abs(_lastTriggerIntervalInMinutes - TriggerIntervalInMinutes);
			bool flag = Helper.IsMainScene();
			if (num > 1f && flag)
			{
				ResetTerrainTimer.RestartTimer();
			}
			_lastTriggerIntervalInMinutes = TriggerIntervalInMinutes;
			ResetTerrainTimer.LoadTimePassedFromFile();
			ParsePaints(_paintsToIgnoreConfig.Value);
			if (Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				InitWardsSettings.RegisterWards();
			}
			Log.Info("PaintsToIgnore = " + string.Join(",", PaintsToIgnore));
		}

		private void ParsePaints(string str)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			PaintsToIgnore.Clear();
			string[] array = str.Split(new string[1] { "), (" }, StringSplitOptions.RemoveEmptyEntries);
			PaintsToIgnore.Capacity = array.Length;
			string[] array2 = array;
			foreach (string text in array2)
			{
				string text2 = text.Trim('(', ')');
				if (vanillaPresets.TryGetValue(text2.Replace(" ", ""), out var value))
				{
					PaintsToIgnore.Add(value);
					continue;
				}
				string[] array3 = text2.Split(new string[1] { ", " }, StringSplitOptions.RemoveEmptyEntries);
				if (array3.Length != 4)
				{
					Log.Error("Could not parse color: '" + string.Join(",", array3) + "', expected format: (r, b, g, alpha)\n" + string.Join(",", vanillaPresets.Keys));
					continue;
				}
				string text3 = array3[0];
				string text4 = array3[1];
				string text5 = array3[2];
				string text6 = array3[3];
				if (!float.TryParse(text3, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					Log.Error("Could not parse a value: '" + text3 + "'");
					continue;
				}
				if (!float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
				{
					Log.Error("Could not parse b value: '" + text4 + "'");
					continue;
				}
				if (!float.TryParse(text5, NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
				{
					Log.Error("Could not parse g value: '" + text5 + "'");
					continue;
				}
				if (!float.TryParse(text6, NumberStyles.Float, CultureInfo.InvariantCulture, out var result4))
				{
					Log.Error("Could not parse alpha value: '" + text6 + "'");
					continue;
				}
				((Color)(ref value))..ctor(result, result2, result3, result4);
				PaintsToIgnore.Add(value);
			}
		}

		public static void InitializeConfiguration(BaseUnityPlugin plugin)
		{
			if (_isInitialized)
			{
				Log.Error("ConfigsContainer is already initialized");
				return;
			}
			_plugin = plugin;
			plugin.Config.SaveOnConfigSet = false;
			Instance = new ConfigsContainer();
			_configFilesToWatch.Add(_plugin.Info.Metadata.GUID + ".cfg");
			SetupWatcher();
			plugin.Config.SaveOnConfigSet = true;
			plugin.Config.ConfigReloaded += delegate
			{
				UpdateConfiguration();
			};
			plugin.Config.Save();
			OnConfigurationChanged = (Action)Delegate.Combine(OnConfigurationChanged, (Action)delegate
			{
				Log.Info("Configuration Received");
				Instance.ApplyConfiguration();
				Log.Info("Configuration applied");
			});
			_isInitialized = true;
		}

		private static void SetupWatcher()
		{
			foreach (string item in _configFilesToWatch.Where((string x) => !string.IsNullOrEmpty(x)))
			{
				FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, item);
				fileSystemWatcher.Changed += ConfigChanged;
				fileSystemWatcher.Created += ConfigChanged;
				fileSystemWatcher.IncludeSubdirectories = true;
				fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
				fileSystemWatcher.EnableRaisingEvents = true;
			}
		}

		private static void ConfigChanged(object sender, FileSystemEventArgs e)
		{
			if ((DateTime.Now - _lastConfigChange).TotalSeconds <= 2.0)
			{
				return;
			}
			_lastConfigChange = DateTime.Now;
			try
			{
				_plugin.Config.Reload();
			}
			catch
			{
				Log.Error("Unable reload config");
			}
		}

		private static void UpdateConfiguration()
		{
			try
			{
				OnConfigurationChanged?.Invoke();
			}
			catch (Exception ex)
			{
				Log.Error(ex, "Configuration error");
			}
		}

		public static ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description)
		{
			return _plugin.Config.Bind<T>(group, name, value, description);
		}

		public static ConfigEntry<T> config<T>(string group, string name, T value, string description)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}
	}
}
namespace GroundReset.Compatibility
{
	public class ModCompat
	{
		public static T? InvokeMethod<T>(Type type, object? instance, string methodName, object[] parameter)
		{
			return (T)(type.GetMethod(methodName)?.Invoke(instance, parameter));
		}

		public static T? GetField<T>(Type type, object? instance, string fieldName)
		{
			return (T)(type.GetField(fieldName)?.GetValue(instance));
		}
	}
}
namespace GroundReset.Compatibility.WardIsLove
{
	public static class AzuWardZdoKeys
	{
		public static readonly int wardRadius = StringExtensionMethods.GetStableHashCode("wardRadius");

		public static readonly int accessMode = StringExtensionMethods.GetStableHashCode("accessMode");

		public static readonly int bubbleMode = StringExtensionMethods.GetStableHashCode("bubbleMode");

		public static readonly int damageType = StringExtensionMethods.GetStableHashCode("damageType");

		public static readonly int healthRegen = StringExtensionMethods.GetStableHashCode("healthRegen");

		public static readonly int staminaBoost = StringExtensionMethods.GetStableHashCode("staminaBoost");

		public static readonly int bubbleOn = StringExtensionMethods.GetStableHashCode("bubbleOn");

		public static readonly int weatherDmgOn = StringExtensionMethods.GetStableHashCode("weatherDmgOn");

		public static readonly int autoPickupOn = StringExtensionMethods.GetStableHashCode("autoPickupOn");

		public static readonly int autoCloseDoorsOn = StringExtensionMethods.GetStableHashCode("autoCloseDoorsOn");

		public static readonly int fireplaceUnlimOn = StringExtensionMethods.GetStableHashCode("fireplaceUnlimOn");

		public static readonly int bathingUnlimOn = StringExtensionMethods.GetStableHashCode("bathingUnlimOn");

		public static readonly int cookingUnlimOn = StringExtensionMethods.GetStableHashCode("cookingUnlimOn");

		public static readonly int wardFireplaceList = StringExtensionMethods.GetStableHashCode("wardFireplaceList");

		public static readonly int noDeathPenOn = StringExtensionMethods.GetStableHashCode("noDeathPenOn");

		public static readonly int noFoodDrainOn = StringExtensionMethods.GetStableHashCode("noFoodDrainOn");

		public static readonly int pushoutPlayersOn = StringExtensionMethods.GetStableHashCode("pushoutPlayersOn");

		public static readonly int pushoutCreaturesOn = StringExtensionMethods.GetStableHashCode("pushoutCreaturesOn");

		public static readonly int pvpOn = StringExtensionMethods.GetStableHashCode("pvpOn");

		public static readonly int pveOn = StringExtensionMethods.GetStableHashCode("pveOn");

		public static readonly int teleportOn = StringExtensionMethods.GetStableHashCode("teleportOn");

		public static readonly int showFlashOn = StringExtensionMethods.GetStableHashCode("showFlashOn");

		public static readonly int showMarkerOn = StringExtensionMethods.GetStableHashCode("showMarkerOn");

		public static readonly int wardNotificationsOn = StringExtensionMethods.GetStableHashCode("wardNotificationsOn");

		public static readonly int wardNotifyMessageEntry = StringExtensionMethods.GetStableHashCode("wardNotifyMessageEntry");

		public static readonly int wardNotifyMessageExit = StringExtensionMethods.GetStableHashCode("wardNotifyMessageExit");

		public static readonly int wardDamageAmount = StringExtensionMethods.GetStableHashCode("wardDamageAmount");

		public static readonly int itemstandInteractOn = StringExtensionMethods.GetStableHashCode("itemstandInteractOn");

		public static readonly int indestructibleOn = StringExtensionMethods.GetStableHashCode("indestructibleOn");

		public static readonly int indestructList = StringExtensionMethods.GetStableHashCode("indestructList");

		public static readonly int CreatDamageIncreaseAmount = StringExtensionMethods.GetStableHashCode("CreatDamageIncreaseAmount");

		public static readonly int structDamageReducAmount = StringExtensionMethods.GetStableHashCode("structDamageReducAmount");

		public static readonly int itemInteractOn = StringExtensionMethods.GetStableHashCode("itemInteractOn");

		public static readonly int doorInteractOn = StringExtensionMethods.GetStableHashCode("doorInteractOn");

		public static readonly int chestInteractOn = StringExtensionMethods.GetStableHashCode("chestInteractOn");

		public static readonly int portalInteractOn = StringExtensionMethods.GetStableHashCode("portalInteractOn");

		public static readonly int pickableInteractOn = StringExtensionMethods.GetStableHashCode("pickableInteractOn");

		public static readonly int shipInteractOn = StringExtensionMethods.GetStableHashCode("shipInteractOn");

		public static readonly int signInteractOn = StringExtensionMethods.GetStableHashCode("signInteractOn");

		public static readonly int craftingStationInteractOn = StringExtensionMethods.GetStableHashCode("craftingStationInteractOn");

		public static readonly int smelterInteractOn = StringExtensionMethods.GetStableHashCode("smelterInteractOn");

		public static readonly int beehiveInteractOn = StringExtensionMethods.GetStableHashCode("beehiveInteractOn");

		public static readonly int maptableInteractOn = StringExtensionMethods.GetStableHashCode("maptableInteractOn");

		public static readonly int OnlyPermOn = StringExtensionMethods.GetStableHashCode("OnlyPermOn");

		public static readonly int NotPermOn = StringExtensionMethods.GetStableHashCode("NotPermOn");

		public static readonly int ctaMessage = StringExtensionMethods.GetStableHashCode("ctaMessage");

		public static readonly int autoRepairOn = StringExtensionMethods.GetStableHashCode("autoRepairOn");

		public static readonly int autoRepairAmount = StringExtensionMethods.GetStableHashCode("autoRepairAmount");

		public static readonly int autoRepairTime = StringExtensionMethods.GetStableHashCode("autoRepairTime");

		public static readonly int raidProtectionOn = StringExtensionMethods.GetStableHashCode("raidProtectionOn");

		public static readonly int raidablePlayersNeeded = StringExtensionMethods.GetStableHashCode("raidablePlayersNeeded");

		public static readonly int wardIsLoveOn = StringExtensionMethods.GetStableHashCode("wardIsLoveOn");

		public static readonly int WILLimitedWard = StringExtensionMethods.GetStableHashCode("WILLimitedWard");

		public static readonly int WILLimitedWardTime = StringExtensionMethods.GetStableHashCode("WILLimitedWardTime");

		public static readonly int steamID = StringExtensionMethods.GetStableHashCode("steamID");

		public static readonly int steamName = StringExtensionMethods.GetStableHashCode("steamName");

		public static readonly int wardFresh = StringExtensionMethods.GetStableHashCode("wardFresh");

		public static readonly int wardColorCount = StringExtensionMethods.GetStableHashCode("wardColorCount");

		public static readonly int wardAlphaCount = StringExtensionMethods.GetStableHashCode("wardAlphaCount");

		public static readonly int wardModelKey = StringExtensionMethods.GetStableHashCode("wardModelKey");
	}
	public class CustomCheck : ModCompat
	{
		public static Type ClassType()
		{
			return Type.GetType("WardIsLove.Util.CustomCheck, WardIsLove") ?? throw new Exception("Looks like WardIsLove is not installed or its API changed");
		}

		public static bool CheckAccess(long playerID, Vector3 point, float radius = 0f, bool flash = true)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			return ModCompat.InvokeMethod<bool>(ClassType(), null, "CheckAccess", new object[4] { playerID, point, radius, flash });
		}
	}
	public class WardIsLovePlugin : ModCompat
	{
		private const string GUID = "Azumatt.WardIsLove";

		private static readonly Version _minVersion = new Version(2, 3, 3);

		public static Type ClassType()
		{
			return Type.GetType("WardIsLove.WardIsLovePlugin, WardIsLove") ?? throw new Exception("Looks like WardIsLove is not installed or its API changed");
		}

		public static bool IsLoaded()
		{
			return Chainloader.PluginInfos.ContainsKey("Azumatt.WardIsLove") && Chainloader.PluginInfos["Azumatt.WardIsLove"].Metadata.Version >= _minVersion;
		}

		public static ConfigEntry<bool> WardEnabled()
		{
			return ModCompat.GetField<ConfigEntry<bool>>(ClassType(), null, "WardEnabled") ?? throw new Exception("Looks like WardIsLove is not installed or its API changed");
		}

		public static ConfigEntry<float> WardRange()
		{
			return ModCompat.GetField<ConfigEntry<float>>(ClassType(), null, "WardRange") ?? throw new Exception("Looks like WardIsLove is not installed or its API changed");
		}
	}
}
namespace GroundReset.Compatibility.kgMarketplace
{
	public static class MarketplaceTerritorySystem
	{
		private const string MarketModGuid = "MarketplaceAndServerNPCs";

		private static readonly Lazy<MethodInfo?> GetCurrentTerritoryMethod = new Lazy<MethodInfo>(delegate
		{
			Type type = AccessTools.TypeByName("Marketplace.Modules.TerritorySystem.TerritorySystem_DataTypes+Territory");
			return (type == null) ? null : AccessTools.Method(type, "GetCurrentTerritory", (Type[])null, (Type[])null);
		});

		public static bool IsLoaded()
		{
			return Chainloader.PluginInfos.ContainsKey("MarketplaceAndServerNPCs");
		}

		public static bool PointInTerritory(Vector3 pos)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (!IsLoaded())
			{
				return false;
			}
			return PointInTerritoryApi(pos).GetValueOrDefault();
		}

		private static bool? PointInTerritoryApi(Vector3 pos)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			object obj = GetCurrentTerritoryMethod.Value?.Invoke(null, new object[1] { pos });
			return obj != null;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}