Decompiled source of RegeneratingWorld v0.5.0

RegeneratingWorld.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using JG224.ModCore.API;
using JG224.RegeneratingWorld.Core;
using JG224.RegeneratingWorld.Runtime;
using Microsoft.CodeAnalysis;
using SoftReferenceableAssets;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("RegeneratingWorld")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyInformationalVersion("0.5.0")]
[assembly: AssemblyProduct("RegeneratingWorld")]
[assembly: AssemblyTitle("RegeneratingWorld")]
[assembly: AssemblyVersion("0.5.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace JG224.RegeneratingWorld
{
	[BepInPlugin("jg224.RegeneratingWorld", "RegeneratingWorld", "0.5.0")]
	[BepInDependency("com.jg224.modcore", "0.5.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "jg224.RegeneratingWorld";

		public const string PluginName = "RegeneratingWorld";

		public const string PluginVersion = "0.5.0";

		public const string ModCoreGuid = "com.jg224.modcore";

		public const int ProtocolVersion = 1;

		public static readonly ModuleId ModuleId = new ModuleId("regeneratingworld");

		private readonly List<IDisposable> _leases = new List<IDisposable>();

		private Harmony _harmony;

		private ICoreServices _core;

		internal static RegenerationRuntime Runtime { get; private set; }

		private void Awake()
		{
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!ModCoreApi.IsAvailable)
				{
					throw new InvalidOperationException("ModCore must initialize first.");
				}
				_core = ModCoreApi.Services;
				SemanticVersion val = default(SemanticVersion);
				if (!SemanticVersion.TryParse("0.5.0", ref val))
				{
					throw new InvalidOperationException("Invalid plugin version.");
				}
				_leases.Add(_core.Modules.Register(new ModuleDescriptor(ModuleId, "jg224.RegeneratingWorld", "RegeneratingWorld", val, 1, (ModuleSide)3, (ModuleRequirement)4, 0uL, 1, 1)));
				Settings settings = new Settings((BaseUnityPlugin)(object)this);
				_leases.AddRange(settings.Register(_core));
				_leases.Add(_core.Namespaces.Register(ModuleId, (NamespaceKind)1, "jg224.rw.", 1, Array.Empty<string>()));
				_leases.Add(_core.Namespaces.Register(ModuleId, (NamespaceKind)4, "regeneratingworld", 1, Array.Empty<string>()));
				Runtime = new RegenerationRuntime(settings, _core, delegate(string message)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)message);
				});
				_leases.Add(_core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)3, (Action<LifecycleEvent>)delegate
				{
					Runtime?.Stop();
				}, 0));
				_leases.Add(_core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)9, (Action<LifecycleEvent>)delegate
				{
					Runtime?.Stop();
				}, 0));
				_harmony = new Harmony("jg224.RegeneratingWorld");
				_harmony.PatchAll(Assembly.GetExecutingAssembly());
				_core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Server restoration scheduler ready.");
				Game.isModded = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"RegeneratingWorld 0.5.0 loaded. Server settings control regeneration.");
			}
			catch (Exception ex)
			{
				ICoreServices core = _core;
				if (core != null)
				{
					core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message);
				}
				((BaseUnityPlugin)this).Logger.LogError((object)("RegeneratingWorld failed safely: " + ex));
				Shutdown();
				throw;
			}
		}

		private void Update()
		{
			Runtime?.Tick();
		}

		private void OnDestroy()
		{
			Shutdown();
		}

		private void Shutdown()
		{
			Runtime?.Stop();
			Runtime = null;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			for (int num = _leases.Count - 1; num >= 0; num--)
			{
				_leases[num].Dispose();
			}
			_leases.Clear();
		}
	}
	internal sealed class Settings
	{
		private readonly List<ConfigEntryBase> _entries = new List<ConfigEntryBase>();

		internal readonly ConfigEntry<bool> Enabled;

		internal readonly ConfigEntry<bool> Terrain;

		internal readonly ConfigEntry<bool> Locations;

		internal readonly ConfigEntry<bool> Resources;

		internal readonly ConfigEntry<float> TerrainDays;

		internal readonly ConfigEntry<float> LocationDays;

		internal readonly ConfigEntry<float> ResourceDays;

		internal readonly ConfigEntry<float> StationRadius;

		internal readonly ConfigEntry<float> PlayerRadius;

		internal readonly ConfigEntry<int> ScanSeconds;

		internal Settings(BaseUnityPlugin plugin)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Expected O, but got Unknown
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			ConfigFile val = PluginConfigFiles.Attach(plugin, new ConfigFile(Path.Combine(Paths.ConfigPath, "jg224.RegeneratingWorld.cfg"), true, plugin.Info.Metadata));
			Enabled = Add<bool>(val.Bind<bool>("General", "Enabled", true, "Server-owned master switch. Disabling retains restoration records."));
			Terrain = Add<bool>(val.Bind<bool>("Terrain", "Enabled", true, "Restore unprotected digging, raising, flattening and ground paint."));
			Locations = Add<bool>(val.Bind<bool>("Locations", "Enabled", true, "Restore dungeons, Fuling camps, Dvergr sites and Ashlands fortresses."));
			Resources = Add<bool>(val.Bind<bool>("Resources", "Enabled", true, "Regrow tracked natural vegetation and mined resources."));
			TerrainDays = Days(val, "Terrain", "ResetDays", 30f);
			LocationDays = Days(val, "Locations", "ResetDays", 30f);
			ResourceDays = Days(val, "Resources", "FallbackResetDays", 30f);
			StationRadius = Add<float>(val.Bind<float>("Protection", "CraftingStationRadius", 40f, new ConfigDescription("Meters protected around every crafting station, including unloaded stations. Independent of crafting range mods.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f), Array.Empty<object>())));
			PlayerRadius = Add<float>(val.Bind<float>("Protection", "PlayerSafetyRadius", 100f, new ConfigDescription("Additional meters around a reset area in which online players postpone restoration.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(32f, 500f), Array.Empty<object>())));
			ScanSeconds = Add<int>(val.Bind<int>("General", "ScanIntervalSeconds", 60, new ConfigDescription("Time between bounded server scans. Timers use world time, including sleep, and survive saves.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 600), Array.Empty<object>())));
		}

		private ConfigEntry<float> Days(ConfigFile file, string section, string key, float value)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			return Add<float>(file.Bind<float>(section, key, value, new ConfigDescription("In-game days before this restoration becomes due.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 1000f), Array.Empty<object>())));
		}

		private ConfigEntry<T> Add<T>(ConfigEntry<T> entry)
		{
			_entries.Add((ConfigEntryBase)(object)entry);
			return entry;
		}

		internal IEnumerable<IDisposable> Register(ICoreServices core)
		{
			foreach (ConfigEntryBase entry in _entries)
			{
				yield return core.Configuration.Register(new ConfigSettingDescriptor(Plugin.ModuleId, entry.Definition.Section, entry.Definition.Key, (ConfigScope)2, (Func<string>)(() => Convert.ToString(entry.BoxedValue, CultureInfo.InvariantCulture)), 1));
			}
		}
	}
}
namespace JG224.RegeneratingWorld.Runtime
{
	[HarmonyPatch(typeof(Container), "Save")]
	internal static class LocationChestProtection
	{
		internal const string DepositKey = "jg224.rw.chest.deposit.v1";

		internal static bool IsSensitive(ZDO zdo, GameObject prefab)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (zdo == null || (Object)(object)prefab == (Object)null)
			{
				return true;
			}
			Container component = prefab.GetComponent<Container>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			try
			{
				ChestInventoryEntry[] array = Read(zdo.GetString(ZDOVars.s_items, ""));
				if (array.Length == 0)
				{
					return false;
				}
				if (zdo.GetBool("jg224.rw.chest.deposit.v1", false))
				{
					return true;
				}
				Dictionary<string, ItemData> dictionary = new Dictionary<string, ItemData>(StringComparer.Ordinal);
				foreach (DropData drop in component.m_defaultItems.m_drops)
				{
					if (!((Object)(object)drop.m_item == (Object)null))
					{
						ItemDrop component2 = drop.m_item.GetComponent<ItemDrop>();
						if ((Object)(object)component2 != (Object)null)
						{
							dictionary[((Object)drop.m_item).name] = component2.m_itemData;
						}
					}
				}
				ChestInventoryEntry[] array2 = array;
				foreach (ChestInventoryEntry chestInventoryEntry in array2)
				{
					if (!dictionary.TryGetValue(chestInventoryEntry.Name, out var value) || chestInventoryEntry.HasPlayerMetadata || chestInventoryEntry.Quality != value.m_quality || chestInventoryEntry.Variant != value.m_variant)
					{
						return true;
					}
				}
				return false;
			}
			catch
			{
				return true;
			}
		}

		private static void Prefix(Container __instance)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			ZNetView val = (((Object)(object)__instance.m_rootObjectOverride != (Object)null) ? __instance.m_rootObjectOverride : ((Component)__instance).GetComponent<ZNetView>());
			if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner())
			{
				return;
			}
			ZDO zDO = val.GetZDO();
			if (zDO.GetLong(ZDOVars.s_creator, 0L) != 0L || !zDO.GetBool(ZDOVars.s_addedDefaultItems, false))
			{
				return;
			}
			try
			{
				ZPackage val2 = new ZPackage();
				__instance.GetInventory().Save(val2);
				ChestInventoryEntry[] array = Read(val2);
				if (array.Length == 0)
				{
					if (zDO.GetBool("jg224.rw.chest.deposit.v1", false))
					{
						zDO.Set("jg224.rw.chest.deposit.v1", false);
					}
				}
				else if (!zDO.GetBool("jg224.rw.chest.deposit.v1", false) && ChestInventoryCodec.HasAdditions(Read(zDO.GetString(ZDOVars.s_items, "")), array))
				{
					zDO.Set("jg224.rw.chest.deposit.v1", true);
				}
			}
			catch
			{
				zDO.Set("jg224.rw.chest.deposit.v1", true);
			}
		}

		private static ChestInventoryEntry[] Read(string encoded)
		{
			if (string.IsNullOrEmpty(encoded))
			{
				return Array.Empty<ChestInventoryEntry>();
			}
			if (encoded.Length > 4194304)
			{
				throw new FormatException("Inventory payload exceeds limit.");
			}
			return ChestInventoryCodec.Decode(Convert.FromBase64String(encoded));
		}

		private static ChestInventoryEntry[] Read(ZPackage package)
		{
			return ChestInventoryCodec.Decode(package.GetArray());
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "CreateNewZDO", new Type[]
	{
		typeof(Vector3),
		typeof(int)
	})]
	internal static class LocationCreationCapture
	{
		private sealed class Scope : IDisposable
		{
			public void Dispose()
			{
				_created = null;
				_transaction = null;
				_maximum = 0;
				_staged = null;
				_recording = false;
			}
		}

		private static List<ZDO> _created;

		private static string _transaction;

		private static int _maximum;

		private static HashSet<ZDOID> _staged;

		private static bool _recording;

		internal static IDisposable Begin(List<ZDO> created, string transaction, int maximum)
		{
			if (_created != null)
			{
				throw new InvalidOperationException("Location regeneration cannot be nested.");
			}
			_created = created;
			_transaction = transaction;
			_maximum = maximum;
			_staged = new HashSet<ZDOID>();
			_recording = true;
			return new Scope();
		}

		internal static bool IsStaged(ZDO zdo)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (zdo != null && _staged != null)
			{
				return _staged.Contains(zdo.m_uid);
			}
			return false;
		}

		internal static void FinishGeneration()
		{
			_recording = false;
		}

		private static void Postfix(ZDO __result)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (_recording && _created != null && __result != null)
			{
				_created.Add(__result);
				_staged.Add(__result.m_uid);
				__result.Set("jg224.rw.location.transaction.v1", _transaction);
				if (_created.Count > _maximum)
				{
					throw new InvalidOperationException("Location regeneration exceeded the network object limit.");
				}
			}
		}
	}
	internal static class LocationLookup
	{
		internal static ZoneLocation Find(IEnumerable<ZoneLocation> locations, int hash)
		{
			if (locations == null)
			{
				return null;
			}
			foreach (ZoneLocation location in locations)
			{
				if (location != null && location.m_prefab.IsValid && location.Hash == hash)
				{
					return location;
				}
			}
			return null;
		}
	}
	internal sealed class LocationRegenerator
	{
		private sealed class PrefabState
		{
			private readonly Transform _root;

			private readonly Vector3 _position;

			private readonly Quaternion _rotation;

			private readonly Transform _interior;

			private readonly Vector3 _interiorPosition;

			private readonly Quaternion _interiorRotation;

			private readonly Transform _generator;

			private readonly Vector3 _generatorPosition;

			private readonly Dictionary<GameObject, bool> _active = new Dictionary<GameObject, bool>();

			private readonly bool _randomDamage;

			internal PrefabState(GameObject prefab)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				_root = prefab.transform;
				_position = _root.position;
				_rotation = _root.rotation;
				Location component = prefab.GetComponent<Location>();
				_interior = (((Object)(object)component == (Object)null) ? null : component.m_interiorTransform);
				_generator = (((Object)(object)component == (Object)null || (Object)(object)component.m_generator == (Object)null) ? null : ((Component)component.m_generator).transform);
				if ((Object)(object)_interior != (Object)null)
				{
					_interiorPosition = _interior.localPosition;
					_interiorRotation = _interior.localRotation;
				}
				if ((Object)(object)_generator != (Object)null)
				{
					_generatorPosition = _generator.localPosition;
				}
				Transform[] componentsInChildren = prefab.GetComponentsInChildren<Transform>(true);
				foreach (Transform val in componentsInChildren)
				{
					_active[((Component)val).gameObject] = ((Component)val).gameObject.activeSelf;
				}
				RandomSpawn[] componentsInChildren2 = prefab.GetComponentsInChildren<RandomSpawn>(true);
				foreach (RandomSpawn val2 in componentsInChildren2)
				{
					if ((Object)(object)val2.m_OffObject != (Object)null)
					{
						_active[val2.m_OffObject] = val2.m_OffObject.activeSelf;
					}
				}
				_randomDamage = WearNTear.m_randomInitialDamage;
			}

			internal void Restore()
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				_root.position = _position;
				_root.rotation = _rotation;
				if ((Object)(object)_interior != (Object)null)
				{
					_interior.localPosition = _interiorPosition;
					_interior.localRotation = _interiorRotation;
				}
				if ((Object)(object)_generator != (Object)null)
				{
					_generator.localPosition = _generatorPosition;
				}
				foreach (KeyValuePair<GameObject, bool> item in _active)
				{
					if ((Object)(object)item.Key != (Object)null)
					{
						item.Key.SetActive(item.Value);
					}
				}
				WearNTear.m_randomInitialDamage = _randomDamage;
			}
		}

		internal const string ClockKey = "jg224.rw.location.clock.v1";

		internal const string OwnerKey = "jg224.rw.location.owner.v1";

		internal const string TransactionKey = "jg224.rw.location.transaction.v1";

		private const int MaximumObjects = 20000;

		private static readonly MethodInfo SpawnLocationMethod = AccessTools.Method(typeof(ZoneSystem), "SpawnLocation", new Type[7]
		{
			typeof(ZoneLocation),
			typeof(int),
			typeof(Vector3),
			typeof(Quaternion),
			typeof(SpawnMode),
			typeof(List<GameObject>),
			typeof(bool)
		}, (Type[])null);

		private static readonly MethodInfo SpawnZoneMethod = AccessTools.Method(typeof(ZoneSystem), "SpawnZone", new Type[3]
		{
			typeof(Vector2s),
			typeof(SpawnMode),
			typeof(GameObject).MakeByRefType()
		}, (Type[])null);

		private static readonly MethodInfo SendDestroyedMethod = AccessTools.Method(typeof(ZDOMan), "SendDestroyed", Type.EmptyTypes, (Type[])null);

		private readonly Func<Vector3, float, bool> _isProtected;

		private readonly Func<ZDO, bool> _isSensitive;

		private readonly Action<IReadOnlyList<ZDO>, string> _backup;

		private readonly Action<string> _log;

		private readonly List<ZDO> _discovered = new List<ZDO>();

		private readonly Queue<ZDOID> _pending = new Queue<ZDOID>();

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

		private readonly Dictionary<int, bool> _supported = new Dictionary<int, bool>();

		private int _scanIndex;

		private bool _blocked;

		internal LocationRegenerator(Func<Vector3, float, bool> isProtected, Func<ZDO, bool> isSensitive, Action<IReadOnlyList<ZDO>, string> backupBeforeMutation, Action<string> log)
		{
			_isProtected = isProtected ?? throw new ArgumentNullException("isProtected");
			_isSensitive = isSensitive ?? throw new ArgumentNullException("isSensitive");
			_backup = backupBeforeMutation ?? throw new ArgumentNullException("backupBeforeMutation");
			_log = log ?? throw new ArgumentNullException("log");
			if (SpawnLocationMethod == null)
			{
				throw new MissingMethodException("Valheim ZoneSystem.SpawnLocation signature changed.");
			}
			if (SpawnZoneMethod == null)
			{
				throw new MissingMethodException("Valheim ZoneSystem.SpawnZone signature changed.");
			}
			if (SendDestroyedMethod == null)
			{
				throw new MissingMethodException("Valheim ZDOMan.SendDestroyed signature changed.");
			}
		}

		internal void Tick(double now, double delay)
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			if (_blocked || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)ZoneSystem.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || !Finite(now) || !Finite(delay) || delay <= 0.0)
			{
				return;
			}
			if (_pending.Count == 0)
			{
				string prefabName = Utils.GetPrefabName(ZoneSystem.instance.m_locationProxyPrefab);
				if (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(prefabName, _discovered, ref _scanIndex))
				{
					return;
				}
				foreach (ZDO item in _discovered)
				{
					if (item.IsValid())
					{
						_pending.Enqueue(item.m_uid);
					}
				}
				_discovered.Clear();
				_scanIndex = 0;
			}
			for (int i = 0; i < 32; i++)
			{
				if (_pending.Count == 0)
				{
					break;
				}
				ZDO zDO = ZDOMan.instance.GetZDO(_pending.Dequeue());
				if (zDO == null || !zDO.IsValid())
				{
					continue;
				}
				ZoneLocation val = FindLocation(zDO.GetInt(ZDOVars.s_location, 0));
				if (val == null || !Supports(val))
				{
					continue;
				}
				string text = zDO.GetString("jg224.rw.location.transaction.v1", "");
				if (!string.IsNullOrEmpty(text))
				{
					if (_reportedIncomplete.Add(zDO.m_uid))
					{
						_log("Location " + val.m_prefab.Name + " is paused after an interrupted transaction (" + text + "). Preserve the world and recovery snapshots before investigating.");
					}
				}
				else
				{
					long num = zDO.GetLong("jg224.rw.location.clock.v1", -1L);
					if (num < 0 || (double)num > now * 1000.0)
					{
						Own(zDO);
						zDO.Set("jg224.rw.location.clock.v1", Milliseconds(now));
					}
					else if (!(now - (double)num / 1000.0 < delay) && TryRegenerate(zDO, val, now))
					{
						break;
					}
				}
			}
		}

		private bool Supports(ZoneLocation location)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (_supported.TryGetValue(location.Hash, out var value))
			{
				return value;
			}
			string name = location.m_prefab.Name;
			if (name.IndexOf("StartTemple", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Vendor", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Haldor", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Hildir_camp", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("BogWitch", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return _supported[location.Hash] = false;
			}
			location.m_prefab.Load();
			try
			{
				GameObject asset = location.m_prefab.Asset;
				Location val = (((Object)(object)asset == (Object)null) ? null : asset.GetComponent<Location>());
				value = (Object)(object)val != (Object)null && (val.m_hasInterior || (Object)(object)val.m_interiorTransform != (Object)null || (Object)(object)val.m_generator != (Object)null || (Object)(object)asset.GetComponentInChildren<DungeonGenerator>(true) != (Object)null);
				value |= name.StartsWith("GoblinCamp", StringComparison.OrdinalIgnoreCase) || name.StartsWith("FulingVillage", StringComparison.OrdinalIgnoreCase) || name.StartsWith("Dvergr", StringComparison.OrdinalIgnoreCase) || name.StartsWith("Fortress", StringComparison.OrdinalIgnoreCase);
				_supported[location.Hash] = value;
				return value;
			}
			finally
			{
				location.m_prefab.Release();
			}
		}

		private bool TryRegenerate(ZDO proxy, ZoneLocation location, double now)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_05db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0664: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			using (ResourceRegenerator.SuppressCapture())
			{
				location.m_prefab.Load();
				List<GameObject> list = new List<GameObject>();
				try
				{
					GameObject asset = location.m_prefab.Asset;
					if ((Object)(object)asset == (Object)null)
					{
						return false;
					}
					Vector3 position = proxy.GetPosition();
					Quaternion rotation = proxy.GetRotation();
					List<Bounds> footprint = BuildFootprint(asset, location, position, rotation);
					if (!SafeFootprint(footprint))
					{
						return false;
					}
					if (!PrepareTerrain(footprint, list))
					{
						return false;
					}
					List<ZDO> list2 = FindObjects(footprint);
					if (list2.Count > 20000 || HasSensitiveObject(list2, footprint))
					{
						return false;
					}
					string text = proxy.GetString("jg224.rw.location.owner.v1", "");
					if (string.IsNullOrEmpty(text))
					{
						text = ((object)Unsafe.As<ZDOID, ZDOID>(ref proxy.m_uid)/*cast due to .constrained prefix*/).ToString();
					}
					string text2 = text + ":" + Milliseconds(now);
					ZDOID uid = proxy.m_uid;
					_backup(list2, "location-intent:" + text2);
					Own(proxy);
					proxy.Set("jg224.rw.location.transaction.v1", text2);
					List<ZDO> list3 = new List<ZDO>();
					List<GameObject> list4 = new List<GameObject>();
					State state = Random.state;
					int forceSeed = DungeonGenerator.m_forceSeed;
					PrefabState prefabState = new PrefabState(asset);
					List<PrefabState> list5 = new List<PrefabState>();
					List<SoftReference<GameObject>> list6 = new List<SoftReference<GameObject>>();
					IDisposable disposable = null;
					bool flag = false;
					bool flag2 = false;
					try
					{
						CaptureRoomStates(asset, list5, list6);
						disposable = LocationCreationCapture.Begin(list3, text2, 20000);
						try
						{
							DungeonGenerator.m_forceSeed = int.MinValue;
							SpawnLocationMethod.Invoke(ZoneSystem.instance, new object[7]
							{
								location,
								proxy.GetInt(ZDOVars.s_seed, 0),
								position,
								rotation,
								(object)(SpawnMode)2,
								list4,
								false
							});
						}
						finally
						{
							LocationCreationCapture.FinishGeneration();
						}
						ZDO val = ValidateGenerated(list3, proxy, footprint);
						if (val == null || !SafeFootprint(footprint))
						{
							throw new InvalidOperationException("Generated location failed its identity or footprint checks.");
						}
						list2 = FindObjects(footprint);
						HashSet<ZDOID> createdIds = new HashSet<ZDOID>();
						foreach (ZDO item in list3)
						{
							createdIds.Add(item.m_uid);
						}
						list2.RemoveAll((ZDO zdo) => createdIds.Contains(zdo.m_uid));
						if (list2.Count > 20000 || HasSensitiveObject(list2, footprint))
						{
							throw new InvalidOperationException("A protected object is inside the generated location footprint.");
						}
						List<ZDO> list7 = SelectOldObjects(list2, list3, proxy, text, footprint);
						ValidateDungeonLayouts(list7, list3);
						if (!list7.Contains(proxy))
						{
							throw new InvalidOperationException("Original location anchor was not selected.");
						}
						foreach (ZDO item2 in list3)
						{
							Own(item2);
							item2.Set("jg224.rw.location.owner.v1", text);
							item2.Set("jg224.rw.location.transaction.v1", text2);
						}
						val.Set("jg224.rw.location.clock.v1", Milliseconds(now));
						_backup(list3, "location-created:" + text2);
						_backup(list7, "location-commit:" + text2);
						flag2 = true;
						foreach (ZDO item3 in list7)
						{
							Destroy(item3);
						}
						FlushDestroyed();
						_backup(list3, "location-complete:" + text2);
						foreach (ZDO item4 in list3)
						{
							item4.Set("jg224.rw.location.transaction.v1", "");
						}
						flag = true;
						_log("Regenerated " + location.m_prefab.Name + ": restored " + list3.Count + " native objects and replaced " + list7.Count + " old objects.");
						return true;
					}
					catch (Exception ex)
					{
						Exception ex2 = ((ex is TargetInvocationException { InnerException: not null } ex3) ? ex3.InnerException : ex);
						if (!flag2)
						{
							try
							{
								foreach (ZDO item5 in list3)
								{
									Destroy(item5);
								}
								FlushDestroyed();
								_backup(Array.Empty<ZDO>(), "location-rollback:" + text2);
								proxy.Set("jg224.rw.location.transaction.v1", "");
								proxy.Set("jg224.rw.location.clock.v1", Milliseconds(now));
							}
							catch (Exception ex4)
							{
								_blocked = true;
								_log("Location rollback is incomplete for " + text2 + ": " + ex4.Message);
							}
						}
						else
						{
							_blocked = true;
						}
						_log("Location " + location.m_prefab.Name + " regeneration " + (flag2 ? "requires recovery" : "was rolled back") + ": " + ex2.Message);
						return true;
					}
					finally
					{
						disposable?.Dispose();
						ZNetView.FinishGhostInit();
						DungeonGenerator.m_forceSeed = forceSeed;
						foreach (PrefabState item6 in list5)
						{
							item6.Restore();
						}
						prefabState.Restore();
						Random.state = state;
						foreach (SoftReference<GameObject> item7 in list6)
						{
							item7.Release();
						}
						foreach (GameObject item8 in list4)
						{
							if ((Object)(object)item8 != (Object)null)
							{
								Object.Destroy((Object)(object)item8);
							}
						}
						if (!flag && flag2)
						{
							_reportedIncomplete.Add(uid);
						}
					}
				}
				finally
				{
					foreach (GameObject item9 in list)
					{
						if ((Object)(object)item9 != (Object)null)
						{
							Object.Destroy((Object)(object)item9);
						}
					}
					location.m_prefab.Release();
				}
			}
		}

		private static bool PrepareTerrain(List<Bounds> footprint, List<GameObject> temporary)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_011a: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			HashSet<Vector2s> hashSet = new HashSet<Vector2s>();
			foreach (Bounds item in footprint)
			{
				Bounds current = item;
				Vector2s zone = ZoneSystem.GetZone(((Bounds)(ref current)).min);
				Vector2s zone2 = ZoneSystem.GetZone(((Bounds)(ref current)).max);
				if (zone2.x < zone.x || zone2.y < zone.y || zone2.x - zone.x > 8 || zone2.y - zone.y > 8)
				{
					throw new InvalidOperationException("Location terrain footprint exceeds supported bounds.");
				}
				for (int i = zone.x; i <= zone2.x; i++)
				{
					for (int j = zone.y; j <= zone2.y; j++)
					{
						hashSet.Add(new Vector2s(i, j));
					}
				}
			}
			bool flag = true;
			foreach (Vector2s item2 in hashSet)
			{
				if (!((Object)(object)Heightmap.FindHeightmap(ZoneSystem.GetZonePos(item2)) != (Object)null))
				{
					object[] array = new object[3]
					{
						item2,
						(object)(SpawnMode)1,
						null
					};
					bool num = (bool)SpawnZoneMethod.Invoke(ZoneSystem.instance, array);
					object obj = array[2];
					GameObject val = (GameObject)((obj is GameObject) ? obj : null);
					if (val != null)
					{
						temporary.Add(val);
					}
					if (!num)
					{
						flag = false;
					}
				}
			}
			if (flag)
			{
				Physics.SyncTransforms();
			}
			return flag;
		}

		private static void CaptureRoomStates(GameObject prefab, List<PrefabState> states, List<SoftReference<GameObject>> held)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			//IL_003b: 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)
			HashSet<AssetID> hashSet = new HashSet<AssetID>();
			DungeonGenerator[] componentsInChildren = prefab.GetComponentsInChildren<DungeonGenerator>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				SoftReference<GameObject>[] availableRoomPrefabs = componentsInChildren[i].GetAvailableRoomPrefabs();
				for (int j = 0; j < availableRoomPrefabs.Length; j++)
				{
					SoftReference<GameObject> item = availableRoomPrefabs[j];
					if (hashSet.Add(item.m_assetID))
					{
						item.Load();
						held.Add(item);
						if ((Object)(object)item.Asset == (Object)null)
						{
							throw new InvalidOperationException("A dungeon room asset could not be loaded.");
						}
						states.Add(new PrefabState(item.Asset));
					}
				}
			}
		}

		private ZDO ValidateGenerated(List<ZDO> created, ZDO oldProxy, List<Bounds> footprint)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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)
			if (created.Count < 2 || created.Count > 20000)
			{
				return null;
			}
			ZDO val = null;
			foreach (ZDO item in created)
			{
				if (item == null || !item.IsValid() || item.GetPrefab() == 0 || !Finite(item.GetPosition().x) || !Finite(item.GetPosition().y) || !Finite(item.GetPosition().z))
				{
					return null;
				}
				if (item.GetPrefab() == oldProxy.GetPrefab() && item.GetInt(ZDOVars.s_location, 0) == oldProxy.GetInt(ZDOVars.s_location, 0))
				{
					if (val != null || Vector3.Distance(item.GetPosition(), oldProxy.GetPosition()) > 0.1f)
					{
						return null;
					}
					val = item;
				}
				if (!Inside(footprint, item.GetPosition()))
				{
					footprint.Add(new Bounds(item.GetPosition(), Vector3.one * 4f));
				}
			}
			return val;
		}

		private static void ValidateDungeonLayouts(List<ZDO> removed, List<ZDO> created)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			foreach (ZDO item in created)
			{
				byte[] byteArray = item.GetByteArray(ZDOVars.s_roomData, (byte[])null);
				if (byteArray == null || byteArray.Length == 0)
				{
					continue;
				}
				foreach (ZDO item2 in removed)
				{
					if (item2.GetPrefab() != item.GetPrefab() || Vector3.SqrMagnitude(item2.GetPosition() - item.GetPosition()) > 0.01f)
					{
						continue;
					}
					byte[] array = item2.GetByteArray(ZDOVars.s_roomData, (byte[])null);
					if (array == null)
					{
						int num = item2.GetInt(ZDOVars.s_rooms, 0);
						if (num < 0 || num > 10000)
						{
							throw new InvalidOperationException("Invalid legacy dungeon room count.");
						}
						using MemoryStream memoryStream = new MemoryStream();
						using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
						binaryWriter.Write(num);
						for (int i = 0; i < num; i++)
						{
							string text = "room" + i;
							binaryWriter.Write(item2.GetInt(text, 0));
							Vector3 vec = item2.GetVec3(text + "_pos", Vector3.zero);
							Quaternion quaternion = item2.GetQuaternion(text + "_rot", Quaternion.identity);
							binaryWriter.Write(vec.x);
							binaryWriter.Write(vec.y);
							binaryWriter.Write(vec.z);
							binaryWriter.Write(quaternion.x);
							binaryWriter.Write(quaternion.y);
							binaryWriter.Write(quaternion.z);
							binaryWriter.Write(quaternion.w);
						}
						array = memoryStream.ToArray();
					}
					if (array.Length != byteArray.Length)
					{
						throw new InvalidOperationException("Native generation changed the saved dungeon layout; existing rooms were preserved.");
					}
					for (int j = 0; j < array.Length; j++)
					{
						if (array[j] != byteArray[j])
						{
							throw new InvalidOperationException("Native generation changed the saved dungeon layout; existing rooms were preserved.");
						}
					}
				}
			}
		}

		private List<ZDO> SelectOldObjects(List<ZDO> nearby, List<ZDO> created, ZDO proxy, string token, List<Bounds> footprint)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<int, List<Vector3>> dictionary = new Dictionary<int, List<Vector3>>();
			HashSet<int> hashSet = new HashSet<int>();
			foreach (ZDO item in created)
			{
				if (!dictionary.TryGetValue(item.GetPrefab(), out var value))
				{
					value = (dictionary[item.GetPrefab()] = new List<Vector3>());
				}
				value.Add(item.GetPosition());
				GameObject prefab = ZNetScene.instance.GetPrefab(item.GetPrefab());
				if ((Object)(object)prefab == (Object)null)
				{
					continue;
				}
				CreatureSpawner component = prefab.GetComponent<CreatureSpawner>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.m_creaturePrefab != (Object)null)
				{
					hashSet.Add(StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(component.m_creaturePrefab)));
				}
				SpawnArea component2 = prefab.GetComponent<SpawnArea>();
				if (!((Object)(object)component2 != (Object)null))
				{
					continue;
				}
				foreach (SpawnData prefab4 in component2.m_prefabs)
				{
					if ((Object)(object)prefab4.m_prefab != (Object)null)
					{
						hashSet.Add(StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(prefab4.m_prefab)));
					}
				}
			}
			List<ZDO> list2 = new List<ZDO>();
			HashSet<ZDOID> hashSet2 = new HashSet<ZDOID>();
			foreach (ZDO item2 in nearby)
			{
				if (!Inside(footprint, item2.GetPosition()))
				{
					continue;
				}
				bool flag = item2 == proxy || item2.GetString("jg224.rw.location.owner.v1", "") == token || hashSet.Contains(item2.GetPrefab());
				GameObject prefab2 = ZNetScene.instance.GetPrefab(item2.GetPrefab());
				if ((Object)(object)prefab2 == (Object)null)
				{
					throw new InvalidOperationException("An unknown network prefab is inside the location.");
				}
				if (!flag && dictionary.TryGetValue(item2.GetPrefab(), out var value2))
				{
					flag = (Object)(object)prefab2.GetComponent<Character>() != (Object)null;
					int num = 0;
					while (!flag && num < value2.Count)
					{
						flag = Vector3.SqrMagnitude(item2.GetPosition() - value2[num]) <= 0.5625f;
						num++;
					}
				}
				if (flag && hashSet2.Add(item2.m_uid))
				{
					list2.Add(item2);
				}
			}
			for (int i = 0; i < list2.Count; i++)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(list2[i].GetConnectionZDOID((ConnectionType)3));
				if (zDO != null && zDO.IsValid() && !hashSet2.Contains(zDO.m_uid))
				{
					GameObject prefab3 = ZNetScene.instance.GetPrefab(zDO.GetPrefab());
					if ((Object)(object)prefab3 == (Object)null || (Object)(object)prefab3.GetComponent<Character>() == (Object)null || _isSensitive(zDO) || _isProtected(zDO.GetPosition(), 2f))
					{
						throw new InvalidOperationException("A linked spawned creature is protected or no longer recognized.");
					}
					hashSet2.Add(zDO.m_uid);
					list2.Add(zDO);
				}
			}
			return list2;
		}

		private bool HasSensitiveObject(List<ZDO> nearby, List<Bounds> footprint)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			foreach (ZDO item in nearby)
			{
				if (Inside(footprint, item.GetPosition()) && _isSensitive(item))
				{
					return true;
				}
			}
			return false;
		}

		private bool SafeFootprint(List<Bounds> footprint)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			foreach (Bounds item in footprint)
			{
				Bounds current = item;
				Func<Vector3, float, bool> isProtected = _isProtected;
				Vector3 center = ((Bounds)(ref current)).center;
				Vector3 extents = ((Bounds)(ref current)).extents;
				if (isProtected(center, ((Vector3)(ref extents)).magnitude))
				{
					return false;
				}
			}
			return true;
		}

		private static List<Bounds> BuildFootprint(GameObject prefab, ZoneLocation location, Vector3 position, Quaternion rotation)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(8f, location.m_exteriorRadius);
			List<Bounds> list = new List<Bounds>
			{
				new Bounds(position, Vector3.one * (num * 2f + 4f))
			};
			PrefabState prefabState = new PrefabState(prefab);
			try
			{
				Location component = prefab.GetComponent<Location>();
				Vector3 val = (((Object)(object)component != (Object)null && (Object)(object)component.m_generator != (Object)null) ? ((Component)component.m_generator).transform.localPosition : Vector3.zero);
				Vector3 val2 = (((Object)(object)component != (Object)null && (Object)(object)component.m_interiorTransform != (Object)null) ? component.m_interiorTransform.localPosition : Vector3.zero);
				prefab.transform.position = Vector3.zero;
				prefab.transform.rotation = Quaternion.identity;
				bool flag = (Object)(object)component != (Object)null && component.m_useCustomInteriorTransform && (Object)(object)component.m_generator != (Object)null && (Object)(object)component.m_interiorTransform != (Object)null;
				if (flag)
				{
					((Component)component.m_generator).transform.localPosition = Vector3.zero;
					Vector3 val3 = ZoneSystem.GetZonePos(ZoneSystem.GetZone(position)) + val2 + val - position;
					Vector3 localPosition = Quaternion.Inverse(rotation) * val3;
					localPosition.y = val2.y;
					component.m_interiorTransform.localPosition = localPosition;
					component.m_interiorTransform.localRotation = Quaternion.Inverse(rotation);
				}
				ZNetView[] componentsInChildren = prefab.GetComponentsInChildren<ZNetView>(true);
				foreach (ZNetView val4 in componentsInChildren)
				{
					Vector3 val5 = position + rotation * ((Component)val4).transform.position;
					DungeonGenerator component2 = ((Component)val4).GetComponent<DungeonGenerator>();
					if ((Object)(object)component2 != (Object)null)
					{
						Vector3 zonePos = ZoneSystem.GetZonePos(ZoneSystem.GetZone(val5));
						zonePos.y = val5.y - (flag ? val.y : 0f);
						list.Add(new Bounds(zonePos, component2.m_zoneSize + Vector3.one * 4f));
					}
					else if (!Inside(list, val5))
					{
						list.Add(new Bounds(val5, Vector3.one * 4f));
					}
				}
				return list;
			}
			finally
			{
				prefabState.Restore();
			}
		}

		private static List<ZDO> FindObjects(List<Bounds> footprint)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			List<ZDO> list = new List<ZDO>();
			HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
			HashSet<Vector2s> hashSet2 = new HashSet<Vector2s>();
			List<ZDO> list2 = new List<ZDO>();
			Vector2s val = default(Vector2s);
			foreach (Bounds item in footprint)
			{
				Bounds current = item;
				Vector2s zone = ZoneSystem.GetZone(((Bounds)(ref current)).min);
				Vector2s zone2 = ZoneSystem.GetZone(((Bounds)(ref current)).max);
				if (zone2.x < zone.x || zone2.y < zone.y || zone2.x - zone.x > 32 || zone2.y - zone.y > 32)
				{
					throw new InvalidOperationException("Location footprint exceeds supported bounds.");
				}
				for (int i = zone.x; i <= zone2.x; i++)
				{
					for (int j = zone.y; j <= zone2.y; j++)
					{
						((Vector2s)(ref val))..ctor(i, j);
						if (!hashSet2.Add(val))
						{
							continue;
						}
						list2.Clear();
						WorldAccess.FindSectorObjects(val, 0, list2);
						foreach (ZDO item2 in list2)
						{
							if (item2.IsValid() && hashSet.Add(item2.m_uid))
							{
								list.Add(item2);
							}
						}
					}
				}
			}
			return list;
		}

		private static bool Inside(List<Bounds> bounds, Vector3 position)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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)
			foreach (Bounds bound in bounds)
			{
				Bounds current = bound;
				if (((Bounds)(ref current)).Contains(position))
				{
					return true;
				}
			}
			return false;
		}

		private static ZoneLocation FindLocation(int hash)
		{
			return LocationLookup.Find(ZoneSystem.instance.m_locations, hash);
		}

		private static void Own(ZDO zdo)
		{
			zdo.SetOwner(ZDOMan.GetSessionID());
		}

		private static long Milliseconds(double seconds)
		{
			return checked((long)(seconds * 1000.0));
		}

		private static bool Finite(double value)
		{
			if (!double.IsNaN(value))
			{
				return !double.IsInfinity(value);
			}
			return false;
		}

		private static void Destroy(ZDO zdo)
		{
			if (zdo != null && zdo.IsValid())
			{
				Own(zdo);
				ZNetView val = ZNetScene.instance.FindInstance(zdo);
				if ((Object)(object)val != (Object)null)
				{
					ZNetScene.instance.Destroy(((Component)val).gameObject);
				}
				else
				{
					ZDOMan.instance.DestroyZDO(zdo);
				}
			}
		}

		private static void FlushDestroyed()
		{
			SendDestroyedMethod.Invoke(ZDOMan.instance, null);
		}
	}
	internal sealed class RegenerationRuntime
	{
		private readonly Settings _settings;

		private readonly ICoreServices _core;

		private readonly Action<string> _log;

		private long _world;

		private bool _started;

		private bool _faulted;

		private double _nextScan;

		private WorldAccess _access;

		private TerrainRegenerator _terrain;

		private ResourceRegenerator _resources;

		private LocationRegenerator _locations;

		private ZDOID[] _scan;

		private int _cursor;

		internal RegenerationRuntime(Settings settings, ICoreServices core, Action<string> log)
		{
			_settings = settings;
			_core = core;
			_log = log;
		}

		internal void Tick()
		{
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			if (!WorldAccess.Server)
			{
				if (_started)
				{
					Stop();
				}
				return;
			}
			try
			{
				long worldUID = ZNet.instance.GetWorldUID();
				if (_started && worldUID != _world)
				{
					Stop();
				}
				if (!_started)
				{
					_world = worldUID;
					_started = true;
					_faulted = false;
					_access = new WorldAccess(_settings, _core, worldUID, _log);
					_terrain = new TerrainRegenerator(_access, _log);
					_resources = new ResourceRegenerator(_access, worldUID, _log, () => !_faulted && _settings.Enabled.Value && _settings.Resources.Value);
					_locations = new LocationRegenerator(_access.Protected, _access.Sensitive, _access.Backup, _log);
					_resources.Load();
					_core.Modules.SetState(Plugin.ModuleId, (ModuleRuntimeState)2, "World restoration records loaded.");
					_log("Regeneration records loaded for world " + worldUID + ". Default terrain/location cycle: 30 in-game days.");
				}
				if (_faulted || !_settings.Enabled.Value)
				{
					return;
				}
				double now = WorldAccess.Now;
				if (_resources.HasPendingWork)
				{
					if (_settings.Resources.Value)
					{
						_resources.RunPending(now, (double)_settings.ResourceDays.Value * WorldAccess.DaySeconds);
					}
					else
					{
						_resources.CancelPendingWork();
					}
					return;
				}
				if (_scan == null)
				{
					if (Time.unscaledTimeAsDouble < _nextScan)
					{
						return;
					}
					_scan = WorldAccess.Objects.Keys.ToArray();
					_cursor = 0;
					if (_settings.Resources.Value)
					{
						_resources.PrepareScan();
					}
				}
				int num = Math.Min(_scan.Length, _cursor + 128);
				while (_cursor < num)
				{
					ZDO zDO = ZDOMan.instance.GetZDO(_scan[_cursor]);
					if (zDO != null)
					{
						if (_settings.Terrain.Value)
						{
							_terrain.Visit(zDO, now, (double)_settings.TerrainDays.Value * WorldAccess.DaySeconds);
						}
						if (_settings.Resources.Value)
						{
							_resources.Observe(zDO);
						}
					}
					_cursor++;
				}
				if (_cursor >= _scan.Length)
				{
					_scan = null;
					_nextScan = Time.unscaledTimeAsDouble + (double)_settings.ScanSeconds.Value;
					if (_settings.Resources.Value)
					{
						_resources.Tick(now, (double)_settings.ResourceDays.Value * WorldAccess.DaySeconds);
					}
					if (_settings.Locations.Value)
					{
						_locations.Tick(now, (double)_settings.LocationDays.Value * WorldAccess.DaySeconds);
					}
				}
			}
			catch (Exception ex)
			{
				_faulted = true;
				_core.Modules.SetState(Plugin.ModuleId, (ModuleRuntimeState)5, ex.Message);
				_log("Regeneration paused to preserve world state: " + ex);
			}
		}

		internal void Stop()
		{
			try
			{
				if (_started && !_faulted)
				{
					_resources?.Save();
				}
			}
			catch (Exception ex)
			{
				_log("Could not save regeneration records: " + ex.Message);
			}
			_resources?.Dispose();
			_scan = null;
			_terrain = null;
			_resources = null;
			_locations = null;
			_access = null;
			_started = false;
			_nextScan = 0.0;
		}
	}
	internal sealed class ResourceRegenerator : IDisposable
	{
		private sealed class CaptureScope : IDisposable
		{
			private bool _ended;

			public void Dispose()
			{
				if (!_ended)
				{
					_ended = true;
					_suppression--;
				}
			}
		}

		internal const string PlantedKey = "jg224.rw.player-planted.v1";

		internal const string ResourceKey = "jg224.rw.resource.v1";

		private readonly WorldAccess _access;

		private readonly long _world;

		private readonly Action<string> _log;

		private readonly Func<bool> _trackingEnabled;

		private static readonly HashSet<ResourceRegenerator> Active = new HashSet<ResourceRegenerator>();

		private static readonly HashSet<ZDOID> MutationIds = new HashSet<ZDOID>();

		private static readonly MethodInfo SendDestroyed = AccessTools.Method(typeof(ZDOMan), "SendDestroyed", Type.EmptyTypes, (Type[])null) ?? throw new MissingMethodException("ZDOMan.SendDestroyed");

		private static int _suppression;

		private ZDOMan _manager;

		private Exception _captureFailure;

		private bool _scanComplete;

		private bool _disposed;

		private bool _limitReported;

		private int _restoredThisCycle;

		private readonly Dictionary<string, ResourceRecord> _records = new Dictionary<string, ResourceRecord>(StringComparer.Ordinal);

		private readonly Queue<string> _capacityCandidates = new Queue<string>();

		private readonly HashSet<string> _untouchedOriginals = new HashSet<string>(StringComparer.Ordinal);

		private readonly Dictionary<ZDOID, ResourceRecord> _byId = new Dictionary<ZDOID, ResourceRecord>();

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

		private readonly Dictionary<int, Plant> _plants = new Dictionary<int, Plant>();

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

		private readonly Dictionary<string, ResourceRecord> _byPosition = new Dictionary<string, ResourceRecord>(StringComparer.Ordinal);

		private IAtomicStore _store;

		private bool _dirty;

		private bool _catalogued;

		private string[] _pendingScan;

		private int _pendingCursor;

		internal bool HasPendingWork => _pendingScan != null;

		internal ResourceRegenerator(WorldAccess access, long world, Action<string> log, Func<bool> trackingEnabled = null)
		{
			_access = access;
			_world = world;
			_log = log;
			_trackingEnabled = trackingEnabled ?? ((Func<bool>)(() => true));
		}

		internal void Load()
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			_store = _access.OpenStore("resources.bin", 33554432);
			AtomicStoreRecord val = default(AtomicStoreRecord);
			string error = default(string);
			if (_store.TryLoad(ref val, ref error))
			{
				if (val.OwnerId != _world || val.SchemaVersion != 1 || !ResourceRecordCodec.TryDecode(val.Payload, out var records, out error))
				{
					throw new InvalidDataException("Resource ledger rejected: " + error);
				}
				foreach (ResourceRecord item in records)
				{
					_records.Add(item.Key, item);
					_byId[new ZDOID(item.UserId, item.ObjectId)] = item;
					_byPosition[PositionKey(item.Prefab, Position(item))] = item;
					if (ResourceStateRules.IsUntouchedOriginal(item))
					{
						_capacityCandidates.Enqueue(item.Key);
						_untouchedOriginals.Add(item.Key);
					}
				}
				if (val.RecoveredFromBackup)
				{
					_log("Resource records recovered from bounded backup; pending spawns remain guarded.");
				}
			}
			else if (File.Exists(_store.Path) || File.Exists(_store.Path + ".bak"))
			{
				throw new InvalidDataException("Resource ledger could not be loaded: " + error);
			}
			Catalog();
			_manager = ZDOMan.instance;
			ZDOMan manager = _manager;
			manager.m_onZDODestroyed = (Action<ZDO>)Delegate.Combine(manager.m_onZDODestroyed, new Action<ZDO>(OnNativeDestroyed));
			Active.Add(this);
		}

		internal void PrepareScan()
		{
			if (_captureFailure != null)
			{
				throw new InvalidDataException("Resource capture failed; regeneration is paused.", _captureFailure);
			}
			_scanComplete = false;
			Catalog();
		}

		private void Catalog()
		{
			if (_catalogued)
			{
				return;
			}
			foreach (ZoneVegetation item in ZoneSystem.instance.m_vegetation)
			{
				if (Object.op_Implicit((Object)(object)item.m_prefab) && Object.op_Implicit((Object)(object)item.m_prefab.GetComponent<ZNetView>()))
				{
					_natural.Add(StringExtensionMethods.GetStableHashCode(((Object)item.m_prefab).name));
				}
			}
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				Plant val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<Plant>() : null);
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				GameObject[] grownPrefabs = val.m_grownPrefabs;
				foreach (GameObject val2 in grownPrefabs)
				{
					if (Object.op_Implicit((Object)(object)val2) && val.m_growTime > 0f && val.m_growTimeMax >= val.m_growTime)
					{
						_plants[StringExtensionMethods.GetStableHashCode(((Object)val2).name)] = val;
					}
				}
			}
			_catalogued = true;
		}

		internal void Observe(ZDO zdo, bool destroying = false)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: 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_0397: Unknown result type (might be due to invalid IL or missing references)
			if (!_natural.Contains(zdo.GetPrefab()))
			{
				return;
			}
			PrefabInfo prefabInfo = _access.Info(zdo.GetPrefab());
			if (!Object.op_Implicit((Object)(object)prefabInfo.Prefab) || (!prefabInfo.Tree && !prefabInfo.Rock && !Object.op_Implicit((Object)(object)prefabInfo.Pickable) && !Object.op_Implicit((Object)(object)prefabInfo.Prefab.GetComponent<Destructible>())) || prefabInfo.Piece || prefabInfo.Character || prefabInfo.Container || prefabInfo.Item || prefabInfo.Terrain || zdo.GetBool("jg224.rw.player-planted.v1", false) || zdo.GetLong(ZDOVars.s_creator, 0L) != 0L || zdo.GetString("jg224.rw.location.owner.v1", "").Length != 0 || zdo.GetString("jg224.rw.location.transaction.v1", "").Length != 0)
			{
				return;
			}
			if (_byId.TryGetValue(zdo.m_uid, out var value))
			{
				if (destroying)
				{
					_untouchedOriginals.Remove(value.Key);
				}
				if (!destroying && ResourceStateRules.CanRetireIntact(value, VerifiedPresence(value)))
				{
					RetireIntact(value);
				}
				return;
			}
			string text = zdo.GetString("jg224.rw.resource.v1", "");
			ResourceRecord value3;
			if (text.Length > 0 && _records.TryGetValue(text, out var value2))
			{
				if (!value2.Pending && ZDOMan.instance.GetZDO(new ZDOID(value2.UserId, value2.ObjectId)) == null && value2.Prefab == zdo.GetPrefab() && PositionKey(value2.Prefab, Position(value2)) == PositionKey(zdo.GetPrefab(), zdo.GetPosition()))
				{
					Attach(value2, zdo);
				}
			}
			else if (_byPosition.TryGetValue(PositionKey(zdo.GetPrefab(), zdo.GetPosition()), out value3))
			{
				if (!value3.Pending && ZDOMan.instance.GetZDO(new ZDOID(value3.UserId, value3.ObjectId)) == null)
				{
					Attach(value3, zdo);
				}
			}
			else
			{
				if (!ResourceStateRules.ShouldTrackObservation(destroying ? ResourcePresence.Missing : Presence(zdo), destroying))
				{
					return;
				}
				if (!EnsureCapacity())
				{
					if (!_limitReported)
					{
						_limitReported = true;
						_log("Resource ledger holds 100,000 harvested or protected records after intact-original reclamation; additional depleted resources cannot be tracked until capacity is available. Existing records are preserved.");
					}
					return;
				}
				Vector3 position = zdo.GetPosition();
				Quaternion rotation = zdo.GetRotation();
				Vector3 vec = zdo.GetVec3(ZDOVars.s_scaleHash, Vector3.one * zdo.GetFloat(ZDOVars.s_scaleScalarHash, 1f));
				text = OriginalKey(((ZDOID)(ref zdo.m_uid)).UserID, ((ZDOID)(ref zdo.m_uid)).ID);
				ResourceRecord resourceRecord = new ResourceRecord
				{
					Key = text,
					UserId = ((ZDOID)(ref zdo.m_uid)).UserID,
					ObjectId = ((ZDOID)(ref zdo.m_uid)).ID,
					Prefab = zdo.GetPrefab(),
					X = position.x,
					Y = position.y,
					Z = position.z,
					RotX = rotation.x,
					RotY = rotation.y,
					RotZ = rotation.z,
					RotW = rotation.w,
					ScaleX = vec.x,
					ScaleY = vec.y,
					ScaleZ = vec.z,
					GrowSeconds = GrowthTime(zdo),
					MissingSince = -1.0
				};
				_records.Add(text, resourceRecord);
				_byId[zdo.m_uid] = resourceRecord;
				_byPosition[PositionKey(resourceRecord.Prefab, position)] = resourceRecord;
				_dirty = true;
			}
		}

		private ResourcePresence VerifiedPresence(ResourceRecord record)
		{
			//IL_0026: 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: 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)
			if (!_untouchedOriginals.Contains(record.Key))
			{
				return ResourcePresence.Unknown;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(new ZDOID(record.UserId, record.ObjectId));
			if (zDO == null)
			{
				return ResourcePresence.Missing;
			}
			if (zDO.GetPrefab() != record.Prefab || zDO.GetString("jg224.rw.resource.v1", "").Length != 0 || Vector3.SqrMagnitude(zDO.GetPosition() - Position(record)) > 0.25f)
			{
				return ResourcePresence.Unknown;
			}
			return Presence(zDO);
		}

		private bool EnsureCapacity()
		{
			if (_records.Count < 100000)
			{
				return true;
			}
			if (!ResourceStateRules.TryTakeIntactCandidate(_records, _capacityCandidates, VerifiedPresence, out var retired))
			{
				return false;
			}
			RetireIntact(retired);
			return true;
		}

		private void RetireIntact(ResourceRecord record)
		{
			//IL_0036: 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)
			_records.Remove(record.Key);
			_untouchedOriginals.Remove(record.Key);
			_byId.Remove(new ZDOID(record.UserId, record.ObjectId));
			_byPosition.Remove(PositionKey(record.Prefab, Position(record)));
			_dirty = true;
			_limitReported = false;
		}

		private double GrowthTime(ZDO zdo)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (!_plants.TryGetValue(zdo.GetPrefab(), out var value))
			{
				return 0.0;
			}
			State state = Random.state;
			try
			{
				Random.InitState((int)(((ZDOID)(ref zdo.m_uid)).UserID + ((ZDOID)(ref zdo.m_uid)).ID));
				return Mathf.Lerp(value.m_growTime, value.m_growTimeMax, Random.value);
			}
			finally
			{
				Random.state = state;
			}
		}

		private void Attach(ResourceRecord record, ZDO zdo)
		{
			//IL_0024: 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)
			_untouchedOriginals.Remove(record.Key);
			_byId.Remove(new ZDOID(record.UserId, record.ObjectId));
			record.UserId = ((ZDOID)(ref zdo.m_uid)).UserID;
			record.ObjectId = ((ZDOID)(ref zdo.m_uid)).ID;
			record.Pending = false;
			record.MissingSince = -1.0;
			_byId[zdo.m_uid] = record;
			_dirty = true;
		}

		internal void Tick(double now, double fallbackDelay)
		{
			_scanComplete = true;
			if (_pendingScan != null)
			{
				throw new InvalidOperationException("Resource scan cycles cannot overlap.");
			}
			_pendingScan = _records.Keys.ToArray();
			_pendingCursor = 0;
			_restoredThisCycle = 0;
			RunPending(now, fallbackDelay);
		}

		internal void CancelPendingWork()
		{
			_pendingScan = null;
			_scanComplete = false;
		}

		internal void RunPending(double now, double fallbackDelay)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: 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_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_0427: Unknown result type (might be due to invalid IL or missing references)
			if (_captureFailure != null)
			{
				throw new InvalidDataException("Resource capture failed; regeneration is paused.", _captureFailure);
			}
			if (_pendingScan == null || !_scanComplete || !WorldAccess.Server)
			{
				return;
			}
			int num = Math.Min(_pendingScan.Length, _pendingCursor + 256);
			ZDOID key = default(ZDOID);
			while (_pendingCursor < num)
			{
				if (_records.TryGetValue(_pendingScan[_pendingCursor], out var value))
				{
					ZDO val = ZDOMan.instance.GetZDO(new ZDOID(value.UserId, value.ObjectId));
					if (val != null && (val.GetPrefab() != value.Prefab || Vector3.SqrMagnitude(val.GetPosition() - Position(value)) > 0.25f))
					{
						val = null;
					}
					if (val == null || (!val.GetBool("jg224.rw.player-planted.v1", false) && !_access.Sensitive(val)))
					{
						ResourcePresence resourcePresence = Presence(val);
						if (resourcePresence != ResourcePresence.Unknown)
						{
							if (resourcePresence != ResourcePresence.Intact)
							{
								_untouchedOriginals.Remove(value.Key);
							}
							if (value.Pending)
							{
								ReconcilePending(value, val, resourcePresence);
							}
							else
							{
								if (ResourceStateRules.ObservePresence(value, resourcePresence, now))
								{
									_dirty = true;
								}
								double delaySeconds;
								if (ResourceStateRules.CanRetireIntact(value, VerifiedPresence(value)))
								{
									RetireIntact(value);
								}
								else if (resourcePresence != ResourcePresence.Intact && _restoredThisCycle < 8 && ResetRules.TryGetResourceDelaySeconds((value.GrowSeconds > 0.0) ? new double?(value.GrowSeconds) : ((double?)null), fallbackDelay, out delaySeconds) && ResetRules.IsDue(now, value.MissingSince, delaySeconds) && !_access.Protected(Position(value), 8f) && (val == null || !val.HasOwner() || val.IsOwner()))
								{
									if (FindReplacements(value, val).Count != 0)
									{
										value.Pending = true;
										_dirty = true;
										Save();
									}
									else
									{
										PrefabInfo prefabInfo = _access.Info(value.Prefab);
										if (Object.op_Implicit((Object)(object)prefabInfo.Prefab))
										{
											List<ZDO> list = OriginalObjects(value, val, prefabInfo);
											ZDOID[] array = list.Select((ZDO z) => z.m_uid).ToArray();
											if (list.Count != 0)
											{
												_access.Backup(list, "resource");
											}
											value.Pending = true;
											_dirty = true;
											Save();
											ZDO val2 = ZDOMan.instance.CreateNewZDO(Position(value), value.Prefab);
											val2.SetPrefab(value.Prefab);
											WorldAccess.Own(val2);
											val2.Persistent = true;
											ZNetView component = prefabInfo.Prefab.GetComponent<ZNetView>();
											val2.Type = component.m_type;
											val2.Distant = component.m_distant;
											val2.SetRotation(new Quaternion(value.RotX, value.RotY, value.RotZ, value.RotW));
											val2.Set(ZDOVars.s_scaleHash, new Vector3(value.ScaleX, value.ScaleY, value.ScaleZ));
											val2.Set("jg224.rw.resource.v1", value.Key);
											DeleteOriginals(list, array);
											((ZDOID)(ref key))..ctor(value.UserId, value.ObjectId);
											if (!ResourceStateRules.TryCompleteReplacement(value, val2.IsValid() && val2.GetPrefab() == value.Prefab && val2.GetString("jg224.rw.resource.v1", "") == value.Key, array.All((ZDOID id) => ZDOMan.instance.GetZDO(id) == null), ((ZDOID)(ref val2.m_uid)).UserID, ((ZDOID)(ref val2.m_uid)).ID))
											{
												throw new InvalidOperationException("Resource replacement could not be verified; reservation retained.");
											}
											ZDOID[] array2 = array;
											foreach (ZDOID key2 in array2)
											{
												_byId.Remove(key2);
											}
											_byId.Remove(key);
											_byId[val2.m_uid] = value;
											_dirty = true;
											Save();
											_restoredThisCycle++;
										}
									}
								}
							}
						}
					}
				}
				_pendingCursor++;
			}
			if (_pendingCursor >= _pendingScan.Length)
			{
				_pendingScan = null;
				Save();
				if (_restoredThisCycle > 0)
				{
					_log("Regrew " + _restoredThisCycle + " natural resources.");
				}
			}
		}

		private List<ZDO> FindReplacements(ResourceRecord record, ZDO current)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			List<ZDO> list = new List<ZDO>();
			WorldAccess.FindSectorObjects(ZoneSystem.GetZone(Position(record)), 1, list);
			return list.Where((ZDO zdo) => zdo != current && zdo.GetPrefab() == record.Prefab && Vector3.SqrMagnitude(zdo.GetPosition() - Position(record)) < 0.25f).ToList();
		}

		private void ReconcilePending(ResourceRecord record, ZDO current, ResourcePresence presence)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			if (_restoredThisCycle >= 8 || _access.Protected(Position(record), 8f) || (current != null && current.HasOwner() && !current.IsOwner()))
			{
				return;
			}
			List<ZDO> list = FindReplacements(record, current);
			bool conflictingIdentity = list.Any((ZDO z) => _access.Sensitive(z) || Presence(z) != ResourcePresence.Intact || (z.GetString("jg224.rw.resource.v1", "").Length > 0 && z.GetString("jg224.rw.resource.v1", "") != record.Key) || z.GetString("jg224.rw.location.owner.v1", "").Length > 0 || z.GetString("jg224.rw.location.transaction.v1", "").Length > 0);
			ResourceRecoveryAction resourceRecoveryAction = ResourceStateRules.PlanPendingRecovery(_scanComplete, presence, list.Count, conflictingIdentity);
			switch (resourceRecoveryAction)
			{
			case ResourceRecoveryAction.Wait:
				return;
			case ResourceRecoveryAction.KeepIntactOriginal:
			case ResourceRecoveryAction.RetryCreation:
				record.Pending = false;
				if (resourceRecoveryAction == ResourceRecoveryAction.KeepIntactOriginal)
				{
					record.MissingSince = -1.0;
				}
				_dirty = true;
				Save();
				return;
			}
			ZDO val = list[0];
			List<ZDO> list2 = OriginalObjects(record, current, _access.Info(record.Prefab));
			ZDOID[] array = list2.Select((ZDO z) => z.m_uid).ToArray();
			if (list2.Count > 0)
			{
				_access.Backup(list2, "resource-recovery");
			}
			ZDOID key = default(ZDOID);
			((ZDOID)(ref key))..ctor(record.UserId, record.ObjectId);
			DeleteOriginals(list2, array);
			if (!ResourceStateRules.TryCompleteReplacement(record, val.IsValid() && val.GetPrefab() == record.Prefab, array.All((ZDOID id) => ZDOMan.instance.GetZDO(id) == null), ((ZDOID)(ref val.m_uid)).UserID, ((ZDOID)(ref val.m_uid)).ID))
			{
				throw new InvalidOperationException("Resource recovery could not verify replacement; reservation retained.");
			}
			_byId.Remove(key);
			_byId[val.m_uid] = record;
			_dirty = true;
			Save();
			_restoredThisCycle++;
		}

		private List<ZDO> OriginalObjects(ResourceRecord record, ZDO current, PrefabInfo info)
		{
			//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_008a: 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)
			List<ZDO> list = new List<ZDO>();
			if (current != null)
			{
				list.Add(current);
			}
			if (!Object.op_Implicit((Object)(object)info.Prefab))
			{
				return list;
			}
			TreeBase component = info.Prefab.GetComponent<TreeBase>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.m_stubPrefab))
			{
				return list;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)component.m_stubPrefab).name);
			List<ZDO> list2 = new List<ZDO>();
			WorldAccess.FindSectorObjects(ZoneSystem.GetZone(Position(record)), 1, list2);
			foreach (ZDO item in list2)
			{
				if (item.GetPrefab() == stableHashCode && Vector3.SqrMagnitude(item.GetPosition() - Position(record)) < 0.25f && !_access.Sensitive(item))
				{
					if (item.HasOwner() && !item.IsOwner())
					{
						throw new InvalidOperationException("A stump changed ownership during resource restoration.");
					}
					list.Add(item);
				}
			}
			return list;
		}

		private static void DeleteOriginals(List<ZDO> originals, ZDOID[] originalIds)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			ZDOID[] array = originalIds;
			foreach (ZDOID item in array)
			{
				MutationIds.Add(item);
			}
			try
			{
				foreach (ZDO original in originals)
				{
					WorldAccess.Destroy(original);
				}
				SendDestroyed.Invoke(ZDOMan.instance, null);
				if (originalIds.Any((ZDOID id) => ZDOMan.instance.GetZDO(id) != null))
				{
					throw new InvalidOperationException("Native resource deletion did not complete; reservation retained.");
				}
			}
			finally
			{
				array = originalIds;
				foreach (ZDOID item2 in array)
				{
					MutationIds.Remove(item2);
				}
			}
		}

		private ResourcePresence Presence(ZDO zdo)
		{
			if (zdo == null)
			{
				return ResourcePresence.Missing;
			}
			PrefabInfo prefabInfo = _access.Info(zdo.GetPrefab());
			if (!Object.op_Implicit((Object)(object)prefabInfo.Prefab))
			{
				return ResourcePresence.Unknown;
			}
			if (Object.op_Implicit((Object)(object)prefabInfo.Pickable))
			{
				if (!(prefabInfo.Pickable.m_respawnTimeMinutes <= 0f) || !zdo.GetBool(ZDOVars.s_picked, false))
				{
					return ResourcePresence.Intact;
				}
				return ResourcePresence.Depleted;
			}
			MineRock5 component = prefabInfo.Prefab.GetComponent<MineRock5>();
			MineRock component2 = prefabInfo.Prefab.GetComponent<MineRock>();
			if (!Object.op_Implicit((Object)(object)component) && !Object.op_Implicit((Object)(object)component2))
			{
				return ResourcePresence.Intact;
			}
			if (!_rockAreas.TryGetValue(zdo.GetPrefab(), out var value))
			{
				value = ((Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.m_areaRoot)) ? component2.m_areaRoot : prefabInfo.Prefab).GetComponentsInChildren<Collider>().Length;
				_rockAreas.Add(zdo.GetPrefab(), value);
			}
			if (value < 1 || value > 10000)
			{
				return ResourcePresence.Unknown;
			}
			bool depleted;
			if (Object.op_Implicit((Object)(object)component))
			{
				string text = zdo.GetString(ZDOVars.s_health, "");
				if (text.Length == 0)
				{
					return ResourcePresence.Intact;
				}
				if (text.Length > 53340)
				{
					return ResourcePresence.Unknown;
				}
				try
				{
					if (!NativeRockHealth.TryReadMineRock5(Convert.FromBase64String(text), value, out depleted))
					{
						return ResourcePresence.Unknown;
					}
				}
				catch (FormatException)
				{
					return ResourcePresence.Unknown;
				}
			}
			else
			{
				float[] array = new float[value];
				for (int i = 0; i < value; i++)
				{
					array[i] = zdo.GetFloat("Health" + i, 1f);
				}
				if (!NativeRockHealth.TryGetDepletion(array, out depleted))
				{
					return ResourcePresence.Unknown;
				}
			}
			if (!depleted)
			{
				return ResourcePresence.Intact;
			}
			return ResourcePresence.Depleted;
		}

		internal void Save()
		{
			if (_captureFailure != null)
			{
				throw new InvalidDataException("Resource capture failed; records preserved for recovery.", _captureFailure);
			}
			if (_dirty && _store != null)
			{
				_store.Save(1, _world, ResourceRecordCodec.Encode(_records.Values));
				_dirty = false;
			}
		}

		private void OnNativeDestroyed(ZDO zdo)
		{
			//IL_0015: 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_00ba: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			if (_disposed || !WorldAccess.Server || MutationIds.Contains(zdo.m_uid))
			{
				return;
			}
			try
			{
				if (_suppression > 0)
				{
					if (_byId.TryGetValue(zdo.m_uid, out var value))
					{
						_untouchedOriginals.Remove(value.Key);
						_byId.Remove(zdo.m_uid);
						_records.Remove(value.Key);
						_byPosition.Remove(PositionKey(value.Prefab, Position(value)));
						_dirty = true;
					}
				}
				else if (_trackingEnabled())
				{
					Observe(zdo, destroying: true);
					if (_byId.TryGetValue(zdo.m_uid, out var value2) && !value2.Pending)
					{
						value2.MissingSince = WorldAccess.Now;
						_dirty = true;
					}
				}
			}
			catch (Exception error)
			{
				CaptureFailure(error);
			}
		}

		private void CaptureFailure(Exception error)
		{
			if (_captureFailure == null)
			{
				_captureFailure = error;
				_log("Resource capture failed; automatic restoration will pause: " + error.Message);
			}
		}

		internal static void FlushCaptured()
		{
			ResourceRegenerator[] array = Active.ToArray();
			foreach (ResourceRegenerator resourceRegenerator in array)
			{
				if (resourceRegenerator._captureFailure == null)
				{
					try
					{
						resourceRegenerator.Save();
					}
					catch (Exception error)
					{
						resourceRegenerator.CaptureFailure(error);
					}
				}
			}
		}

		internal static IDisposable SuppressCapture()
		{
			if (_suppression == 0 && WorldAccess.Server)
			{
				SendDestroyed.Invoke(ZDOMan.instance, null);
			}
			_suppression++;
			return new CaptureScope();
		}

		public void Dispose()
		{
			if (!_disposed)
			{
				_disposed = true;
				if (_manager != null)
				{
					ZDOMan manager = _manager;
					manager.m_onZDODestroyed = (Action<ZDO>)Delegate.Remove(manager.m_onZDODestroyed, new Action<ZDO>(OnNativeDestroyed));
				}
				Active.Remove(this);
				_pendingScan = null;
			}
		}

		private static Vector3 Position(ResourceRecord record)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(record.X, record.Y, record.Z);
		}

		private static string OriginalKey(long userId, uint objectId)
		{
			return userId.ToString(CultureInfo.InvariantCulture) + ":" + objectId.ToString(CultureInfo.InvariantCulture);
		}

		private static string PositionKey(int prefab, Vector3 position)
		{
			return prefab.ToString(CultureInfo.InvariantCulture) + ":" + position.x.ToString("R", CultureInfo.InvariantCulture) + ":" + position.y.ToString("R", CultureInfo.InvariantCulture) + ":" + position.z.ToString("R", CultureInfo.InvariantCulture);
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "RPC_DestroyZDO", new Type[]
	{
		typeof(long),
		typeof(ZPackage)
	})]
	internal static class ResourceDestructionCapture
	{
		private static Exception Finalizer(Exception __exception)
		{
			ResourceRegenerator.FlushCaptured();
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Plant), "Grow")]
	internal static class PlayerPlantOwnership
	{
		private static void Prefix(Plant __instance, out long __state)
		{
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			__state = ((Object.op_Implicit((Object)(object)component) && component.IsValid()) ? component.GetZDO().GetLong(ZDOVars.s_creator, 0L) : 0);
		}

		private static void Postfix(GameObject __result, long __state)
		{
			if (!Object.op_Implicit((Object)(object)__result))
			{
				return;
			}
			ZNetView component = __result.GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner())
			{
				component.GetZDO().Set("jg224.rw.player-planted.v1", true);
				if (__state != 0L)
				{
					component.GetZDO().Set(ZDOVars.s_creator, __state);
				}
			}
		}
	}
	internal sealed class TerrainRegenerator
	{
		private const string Stamp = "jg224.rw.terrain.time";

		private const string Fingerprint = "jg224.rw.terrain.hash";

		private const string Schema = "jg224.rw.terrain.schema";

		private readonly WorldAccess _access;

		private readonly Action<string> _log;

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

		internal TerrainRegenerator(WorldAccess access, Action<string> log)
		{
			_access = access;
			_log = log;
		}

		internal unsafe void Visit(ZDO zdo, double now, double delay)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			PrefabInfo prefabInfo = _access.Info(zdo.GetPrefab());
			if ((!prefabInfo.Terrain && (!Object.op_Implicit((Object)(object)prefabInfo.LegacyTerrain) || !prefabInfo.LegacyTerrain.m_playerModifiction || prefabInfo.LegacyTerrain.m_useTerrainCompiler)) || (zdo.HasOwner() && !zdo.IsOwner()) || zdo.GetInt("jg224.rw.terrain.schema", 0) > 1)
			{
				return;
			}
			if (!prefabInfo.Terrain)
			{
				if (!StartOrChanged(zdo, now, 1L))
				{
					float num = Math.Max(prefabInfo.LegacyTerrain.m_levelRadius, Math.Max(prefabInfo.LegacyTerrain.m_smoothRadius, prefabInfo.LegacyTerrain.m_paintRadius));
					if (prefabInfo.LegacyTerrain.m_square)
					{
						num *= (float)Math.Sqrt(2.0);
					}
					if (ResetRules.IsDue(now, zdo.GetFloat("jg224.rw.terrain.time", -1f), delay) && !_access.Protected(zdo.GetPosition(), num))
					{
						_access.Backup((IReadOnlyList<ZDO>)(object)new ZDO[1] { zdo }, "legacy-terrain");
						WorldAccess.Destroy(zdo);
					}
				}
				return;
			}
			byte[] byteArray = zdo.GetByteArray(ZDOVars.s_TCData, (byte[])null);
			if (byteArray == null || byteArray.Length == 0 || byteArray.Length > 1782842)
			{
				return;
			}
			long hash = Hash(byteArray);
			if (StartOrChanged(zdo, now, hash) || !ResetRules.IsDue(now, zdo.GetFloat("jg224.rw.terrain.time", -1f), delay))
			{
				return;
			}
			Vector3 center = zdo.GetPosition();
			if (!WorldAccess.Finite(center))
			{
				return;
			}
			float scale;
			Func<Vector3, bool> protectedPoint;
			if (!TerrainPayload.TryInflate(byteArray, out var raw) || !TerrainData.TryDecode(raw, out var data, out var _))
			{
				if (_reported.Add(zdo.m_uid))
				{
					Action<string> log = _log;
					ZDOID uid = zdo.m_uid;
					log("Skipping unsupported/corrupt terrain compiler " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString() + ".");
				}
			}
			else
			{
				if (data.PaintStride != data.Width + 1)
				{
					return;
				}
				if (!TryGetGeometry(center, data.Width, out scale, out var extent, out var cellMargin))
				{
					if (_reported.Add(zdo.m_uid))
					{
						Action<string> log2 = _log;
						ZDOID uid = zdo.m_uid;
						log2("Skipping terrain compiler whose geometry differs from the current zone prefab: " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString() + ".");
					}
				}
				else if (!_access.PlayersNear(center, extent + cellMargin))
				{
					protectedPoint = _access.PointProtection(center, extent, cellMargin);
					int num2 = data.ClearWhere((int i) => Allowed(i, data.Width + 1), (int i) => Allowed(i, data.PaintStride));
					if (num2 != 0)
					{
						byte[] array = Utils.Compress(data.Encode());
						_access.Backup((IReadOnlyList<ZDO>)(object)new ZDO[1] { zdo }, "terrain");
						WorldAccess.Own(zdo);
						zdo.Set(ZDOVars.s_TCData, array);
						zdo.Set("jg224.rw.terrain.hash", Hash(array));
						zdo.Set("jg224.rw.terrain.time", (float)now);
						ZDOMan.instance.ForceSendZDO(zdo.m_uid);
						Action<string> log3 = _log;
						string[] obj = new string[5]
						{
							"Restored ",
							num2.ToString(),
							" unprotected terrain cells at ",
							null,
							null
						};
						Vector3 val = center;
						obj[3] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString();
						obj[4] = ".";
						log3(string.Concat(obj));
					}
				}
			}
			bool Allowed(int index, int stride)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				Vector3 arg = center + new Vector3(((float)(index % stride) - (float)data.Width / 2f) * scale, 0f, ((float)(index / stride) - (float)data.Width / 2f) * scale);
				return !protectedPoint(arg);
			}
		}

		private static bool StartOrChanged(ZDO zdo, double now, long hash)
		{
			if (zdo.GetInt("jg224.rw.terrain.schema", 0) == 1 && zdo.GetLong("jg224.rw.terrain.hash", 0L) == hash && zdo.GetFloat("jg224.rw.terrain.time", -1f) >= 0f && (double)zdo.GetFloat("jg224.rw.terrain.time", 0f) <= now)
			{
				return false;
			}
			WorldAccess.Own(zdo);
			zdo.Set("jg224.rw.terrain.schema", 1);
			zdo.Set("jg224.rw.terrain.hash", hash);
			zdo.Set("jg224.rw.terrain.time", (float)now);
			return true;
		}

		private static long Hash(byte[] bytes)
		{
			long num = 1469598103934665603L;
			foreach (byte b in bytes)
			{
				num = (num ^ b) * 1099511628211L;
			}
			return num;
		}

		private static bool TryGetGeometry(Vector3 center, int width, out float scale, out float extent, out float cellMargin)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			scale = 0f;
			extent = 0f;
			cellMargin = 0f;
			GameObject zonePrefab = ZoneSystem.instance.m_zonePrefab;
			if (!Object.op_Implicit((Object)(object)zonePrefab))
			{
				return false;
			}
			Heightmap componentInChildren = zonePrefab.GetComponentInChildren<Heightmap>();
			if (!Object.op_Implicit((Object)(object)componentInChildren) || componentInChildren.m_width != width || !WorldAccess.IsFinite(componentInChildr