Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Resource Regrowth v0.8.5
plugins/SarkasticGG_Resource_Regrowth.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; 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: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: IgnoresAccessChecksTo("SoftReferenceableAssets")] [assembly: AssemblyCompany("SarkasticGG_Resource_Regrowth")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.8.0.0")] [assembly: AssemblyInformationalVersion("0.8.0+9880842f4713491b39245f19faa7ee7e012bdce4")] [assembly: AssemblyProduct("SarkasticGG_Resource_Regrowth")] [assembly: AssemblyTitle("SarkasticGG_Resource_Regrowth")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.8.0.0")] [module: UnverifiableCode] [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 ResourceRegrowth { internal class LocationObjects { public struct Slot { public int prefab; public Vector3 position; public Quaternion rotation; public string source; public List<(int prefab, Vector3 position)> supports; } private struct Template { public ZNetView view; public Vector3 local; public Quaternion rotation; public bool random; public List<ZNetView> supports; } private const float SupportRadius = 3f; private readonly HashSet<int> wanted; private readonly HashSet<int> remains; private readonly int proxyPrefab; private readonly Dictionary<int, DungeonGenerator> generatorPrefabs = new Dictionary<int, DungeonGenerator>(); private readonly Dictionary<int, ZoneLocation> locations = new Dictionary<int, ZoneLocation>(); private readonly Dictionary<int, bool> locationHasSlots = new Dictionary<int, bool>(); private readonly Dictionary<int, bool> roomHasSlots = new Dictionary<int, bool>(); private readonly Dictionary<string, List<Slot>> slots = new Dictionary<string, List<Slot>>(); private const float LoadTimeoutSeconds = 30f; public int SourceCount => slots.Count; public LocationObjects(IEnumerable<string> prefabNames) { List<string> source = prefabNames.ToList(); wanted = new HashSet<int>(source.Select((string n) => StringExtensionMethods.GetStableHashCode(n))); remains = new HashSet<int>(source.Select((string n) => StringExtensionMethods.GetStableHashCode(n + "_frac"))); proxyPrefab = StringExtensionMethods.GetStableHashCode(((Object)ZoneSystem.instance.m_locationProxyPrefab).name); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { DungeonGenerator val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<DungeonGenerator>() : null); if (Object.op_Implicit((Object)(object)val)) { generatorPrefabs[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = val; } } foreach (ZoneLocation location in ZoneSystem.instance.m_locations) { if (location != null && location.m_enable && location.m_prefab.IsValid) { locations[StringExtensionMethods.GetStableHashCode(location.m_prefab.Name)] = location; } } } public bool IsSource(int prefab) { if (prefab != proxyPrefab) { return generatorPrefabs.ContainsKey(prefab); } return true; } public bool IsWanted(int prefab) { return wanted.Contains(prefab); } public bool IsRemains(int prefab) { return remains.Contains(prefab); } public static bool Supported(Slot slot, Dictionary<Vector2s, List<ZDO>> pieces) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (slot.supports == null || slot.supports.Count == 0) { return true; } foreach (var (num, val) in slot.supports) { if (!pieces.TryGetValue(ZoneSystem.GetZone(val), out var value)) { continue; } foreach (ZDO item in value) { if (item.GetPrefab() == num) { Vector3 val2 = item.GetPosition() - val; if (((Vector3)(ref val2)).sqrMagnitude < 0.25f) { return true; } } } } return false; } public IEnumerator Refresh(List<ZDO> sources, Action<int> onLoaded) { Dictionary<int, List<ZDO>> dictionary = new Dictionary<int, List<ZDO>>(); Dictionary<int, List<(ZDO generator, Vector3 position, Quaternion rotation)>> newRooms = new Dictionary<int, List<(ZDO, Vector3, Quaternion)>>(); byte[] data = default(byte[]); foreach (ZDO source in sources) { if (source.GetPrefab() == proxyPrefab) { int num = source.GetInt(ZDOVars.s_location, 0); if ((!locationHasSlots.TryGetValue(num, out var value) || value) && !slots.ContainsKey(ProxyKey(source, num))) { if (!dictionary.TryGetValue(num, out var value2)) { value2 = (dictionary[num] = new List<ZDO>()); } value2.Add(source); } } else { if (!source.GetByteArray(ZDOVars.s_roomData, ref data)) { continue; } foreach (var (num2, val, item) in ReadRooms(data)) { if ((!roomHasSlots.TryGetValue(num2, out var value3) || value3) && !slots.ContainsKey(RoomKey(num2, val))) { if (!newRooms.TryGetValue(num2, out List<(ZDO, Vector3, Quaternion)> value4)) { value4 = (newRooms[num2] = new List<(ZDO, Vector3, Quaternion)>()); } value4.Add((source, val, item)); } } } } foreach (KeyValuePair<int, List<ZDO>> entry in dictionary) { if (!locations.TryGetValue(entry.Key, out var location)) { locationHasSlots[entry.Key] = false; continue; } bool loaded = false; IEnumerator load = LoadAsync(location.m_prefab, delegate(bool ok) { loaded = ok; }); while (load.MoveNext()) { yield return null; } try { if (loaded) { ReplayLocation(location, entry.Value); onLoaded(1); } } finally { location.m_prefab.Release(); } yield return null; location = null; } foreach (KeyValuePair<int, List<(ZDO, Vector3, Quaternion)>> entry2 in newRooms) { RoomData room = DungeonDB.instance.GetRoom(entry2.Key); if (room == null || !room.m_prefab.IsValid) { roomHasSlots[entry2.Key] = false; continue; } bool loaded2 = false; IEnumerator load = LoadAsync(room.m_prefab, delegate(bool ok) { loaded2 = ok; }); while (load.MoveNext()) { yield return null; } try { if (loaded2) { ReplayRooms(entry2.Key, room, entry2.Value); onLoaded(1); } } finally { room.m_prefab.Release(); } yield return null; } } private static IEnumerator LoadAsync(SoftReference<GameObject> prefab, Action<bool> done) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) bool finished = false; LoadResult result = (LoadResult)1; prefab.LoadAsync((LoadedHandler)delegate(AssetID id, LoadResult r) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) finished = true; result = r; }); float until = Time.realtimeSinceStartup + 30f; while (!finished && Time.realtimeSinceStartup < until) { yield return null; } done(finished && (int)result == 0 && (Object)(object)prefab.Asset != (Object)null); } public IEnumerable<Slot> AllSlots() { return slots.Values.SelectMany((List<Slot> list) => list); } private static string ProxyKey(ZDO proxy, int location) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0039: Unknown result type (might be due to invalid IL or missing references) Vector3 position = proxy.GetPosition(); return $"L{location}:{position.x:0.0}:{position.y:0.0}:{position.z:0.0}"; } private static string RoomKey(int hash, Vector3 p) { //IL_0016: 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) //IL_0032: Unknown result type (might be due to invalid IL or missing references) return $"R{hash}:{p.x:0.0}:{p.y:0.0}:{p.z:0.0}"; } private static List<(int, Vector3, Quaternion)> ReadRooms(byte[] data) { //IL_0050: 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_005a: 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) List<(int, Vector3, Quaternion)> list = new List<(int, Vector3, Quaternion)>(); BinaryReader binaryReader = new BinaryReader(new MemoryStream(data)); int num = binaryReader.ReadInt32(); Vector3 item2 = default(Vector3); for (int i = 0; i < num; i++) { int item = binaryReader.ReadInt32(); ((Vector3)(ref item2))..ctor(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); Quaternion item3 = Quaternion.Euler(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); list.Add((item, item2, item3)); } return list; } private List<Template> Templates(GameObject asset, ZNetView[] views) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) List<Template> list = new List<Template>(); foreach (ZNetView view in views) { if (!wanted.Contains(StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Component)view).gameObject)))) { continue; } Vector3 at = ((Component)view).gameObject.transform.position; list.Add(new Template { view = view, local = at, rotation = ((Component)view).gameObject.transform.rotation, random = ((Object)(object)((Component)view).GetComponentInParent<RandomSpawn>(true) != (Object)null || (Object)(object)((Component)view).GetComponentInParent<RandomObject>(true) != (Object)null), supports = views.Where(delegate(ZNetView other) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)other != (Object)(object)view && Object.op_Implicit((Object)(object)((Component)other).GetComponent<WearNTear>())) { Vector2 val = new Vector2(((Component)other).transform.position.x - at.x, ((Component)other).transform.position.z - at.z); if (((Vector2)(ref val)).magnitude <= 3f) { return ((Component)other).transform.position.y <= at.y + 0.5f; } } return false; }).ToList() }); } return list; } private void ReplayLocation(ZoneLocation location, List<ZDO> proxies) { //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_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_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0169: 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) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: 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_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) int stableHashCode = StringExtensionMethods.GetStableHashCode(location.m_prefab.Name); GameObject asset = location.m_prefab.Asset; Vector3 position = asset.transform.position; Quaternion rotation = asset.transform.rotation; Location component = asset.GetComponent<Location>(); Biome biome = (Biome)(Object.op_Implicit((Object)(object)component) ? ((int)component.m_biome) : 0); State state = Random.state; try { asset.transform.position = Vector3.zero; asset.transform.rotation = Quaternion.identity; ZNetView[] enabledComponentsInChildren = Utils.GetEnabledComponentsInChildren<ZNetView>(asset); List<Template> list = Templates(asset, enabledComponentsInChildren); locationHasSlots[stableHashCode] = list.Count > 0; if (list.Count == 0) { return; } RandomSpawn[] enabledComponentsInChildren2 = Utils.GetEnabledComponentsInChildren<RandomSpawn>(asset); RandomObject[] enabledComponentsInChildren3 = Utils.GetEnabledComponentsInChildren<RandomObject>(asset); string name = location.m_prefab.Name; foreach (ZDO proxy in proxies) { Vector3 position2 = proxy.GetPosition(); Quaternion rotation2 = proxy.GetRotation(); bool[] array = new bool[list.Count]; List<ZNetView>[] array2 = new List<ZNetView>[list.Count]; try { RandomSpawn[] array3 = enabledComponentsInChildren2; for (int i = 0; i < array3.Length; i++) { array3[i].Prepare(); } Random.InitState(proxy.GetInt(ZDOVars.s_seed, 0)); array3 = enabledComponentsInChildren2; foreach (RandomSpawn val in array3) { val.Randomize(position2 + rotation2 * ((Component)val).gameObject.transform.position, component, (DungeonGenerator)null); } RandomObject[] array4 = enabledComponentsInChildren3; foreach (RandomObject val2 in array4) { val2.Randomize(position2 + rotation2 * ((Component)val2).gameObject.transform.position, component, (DungeonGenerator)null); } for (int j = 0; j < list.Count; j++) { array[j] = ((Component)list[j].view).gameObject.activeSelf; array2[j] = list[j].supports.Where((ZNetView v) => ((Component)v).gameObject.activeSelf).ToList(); } } finally { Restore(enabledComponentsInChildren2, enabledComponentsInChildren3, enabledComponentsInChildren); if (Object.op_Implicit((Object)(object)component)) { component.m_biome = biome; } } List<Slot> list2 = new List<Slot>(); for (int num = 0; num < list.Count; num++) { if (array[num]) { list2.Add(new Slot { prefab = StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Component)list[num].view).gameObject)), position = position2 + rotation2 * list[num].local, rotation = rotation2 * list[num].rotation, source = name, supports = array2[num].Select((ZNetView v) => (StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Component)v).gameObject)), position2 + rotation2 * ((Component)v).transform.position)).ToList() }); } } slots[ProxyKey(proxy, stableHashCode)] = list2; } } finally { asset.transform.position = position; asset.transform.rotation = rotation; Random.state = state; } } private void ReplayRooms(int hash, RoomData room, List<(ZDO generator, Vector3 position, Quaternion rotation)> placed) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: 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) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0238: 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_024b: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) GameObject asset = room.m_prefab.Asset; State state = Random.state; try { ZNetView[] enabledComponentsInChildren = Utils.GetEnabledComponentsInChildren<ZNetView>(asset); List<Template> list = Templates(asset, enabledComponentsInChildren); roomHasSlots[hash] = list.Count > 0; if (list.Count == 0) { return; } RandomSpawn[] enabledComponentsInChildren2 = Utils.GetEnabledComponentsInChildren<RandomSpawn>(asset); RandomObject[] enabledComponentsInChildren3 = Utils.GetEnabledComponentsInChildren<RandomObject>(asset); Room component = asset.GetComponent<Room>(); Vector3 origin = ((Component)component).transform.position; Quaternion inverse = Quaternion.Inverse(((Component)component).transform.rotation); string name = room.m_prefab.Name; foreach (var item in placed) { var (val, position, rotation) = item; if (!generatorPrefabs.TryGetValue(val.GetPrefab(), out var value)) { continue; } Vector3 val2 = (value.m_useCustomInteriorTransform ? (position - val.GetPosition()) : position); int num = (int)val2.x * 4271 + (int)val2.y * 9187 + (int)val2.z * 2134; if (value.m_addBaseSeedToRandomSpawn) { num += GeneratorSeed(val.GetPosition()); } bool[] array = new bool[list.Count]; List<ZNetView>[] array2 = new List<ZNetView>[list.Count]; try { RandomSpawn[] array3 = enabledComponentsInChildren2; for (int i = 0; i < array3.Length; i++) { array3[i].Prepare(); } Random.InitState(num); array3 = enabledComponentsInChildren2; foreach (RandomSpawn val3 in array3) { val3.Randomize(position + rotation * (inverse * (((Component)val3).gameObject.transform.position - origin)), (Location)null, value); } RandomObject[] array4 = enabledComponentsInChildren3; foreach (RandomObject val4 in array4) { val4.Randomize(position + rotation * (inverse * (((Component)val4).gameObject.transform.position - origin)), (Location)null, value); } for (int j = 0; j < list.Count; j++) { array[j] = ((Component)list[j].view).gameObject.activeSelf; array2[j] = list[j].supports.Where((ZNetView v) => ((Component)v).gameObject.activeSelf).ToList(); } } finally { Restore(enabledComponentsInChildren2, enabledComponentsInChildren3, enabledComponentsInChildren); } List<Slot> list2 = new List<Slot>(); for (int num2 = 0; num2 < list.Count; num2++) { if (array[num2]) { list2.Add(new Slot { prefab = StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Component)list[num2].view).gameObject)), position = position + rotation * (inverse * (list[num2].local - origin)), rotation = rotation * (inverse * list[num2].rotation), source = name, supports = array2[num2].Select((ZNetView v) => (StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Component)v).gameObject)), position + rotation * (inverse * (((Component)v).transform.position - origin)))).ToList() }); } } slots[RoomKey(hash, position)] = list2; } } finally { Random.state = state; } } private static int GeneratorSeed(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Vector2s zone = ZoneSystem.GetZone(position); return WorldGenerator.instance.GetSeed() + zone.x * 4271 + zone.y * -7187 + (int)position.x * -4271 + (int)position.y * 9187 + (int)position.z * -2134; } private static void Restore(RandomSpawn[] randomSpawns, RandomObject[] randomObjects, ZNetView[] views) { for (int i = 0; i < randomSpawns.Length; i++) { randomSpawns[i].Reset(); } for (int i = 0; i < randomObjects.Length; i++) { randomObjects[i].Reset(); } for (int i = 0; i < views.Length; i++) { ((Component)views[i]).gameObject.SetActive(true); } } public static ZDO Create(int prefabHash, Vector3 position, Quaternion rotation) { //IL_0016: 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_004a: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ZNetScene.instance.GetPrefab(prefabHash).GetComponent<ZNetView>(); ZDO val = ZDOMan.instance.CreateNewZDO(position, prefabHash); val.Persistent = component.m_persistent; val.Type = component.m_type; val.Distant = component.m_distant; val.SetPrefab(prefabHash); val.SetRotation(rotation); ZDOMan.instance.SetDirtySector(val); return val; } } internal static class PlayersItems { public static bool InContainer(ZDO zdo) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null); if (byteArray == null) { return false; } try { Inventory val = new Inventory("regrowth", (Sprite)null, 16, 16); val.Load(new ZPackage(byteArray)); return val.GetAllItems().Any((ItemData item) => item.m_pickedUp); } catch (Exception) { return true; } } public static bool Carried(ZDO zdo) { byte[] byteArray = zdo.GetByteArray(ZDOVars.s_itemData, (byte[])null); if (byteArray == null) { return false; } if (byteArray.Length < 9 || byteArray[0] != 109) { return true; } return (byteArray[8] & 1) != 0; } } internal class Regrowth { private enum Kind { Core, Chest, Spawner, Terrain, LocationObject } private class Tally { public int depleted; public int waiting; public int blocked; public int unsupported; public int inUse; public int regrown; public int logged; } private struct Candidate { public Kind kind; public ZDO zdo; public ZDOID uid; public int prefab; } private class Group { public string name; public Vector3 position; public bool dungeon; public readonly List<Candidate> members = new List<Candidate>(); } private struct Place { public Vector2s zone; public string name; public Vector3 position; public float radius; public float interior; } private enum Reach { Surface, Interior, Generator } private const float PresenceIntervalSeconds = 10f; private const int ScanBatch = 4096; private readonly MonoBehaviour host; private readonly Settings settings; private RegrowthState state; private readonly Dictionary<int, bool> corePrefabs = new Dictionary<int, bool>(); private readonly Dictionary<int, Container> chestPrefabs = new Dictionary<int, Container>(); private readonly HashSet<int> spawnerPrefabs = new HashSet<int>(); private readonly HashSet<int> generatorPrefabs = new HashSet<int>(); private readonly HashSet<int> piecePrefabs = new HashSet<int>(); private readonly HashSet<int> tombstonePrefabs = new HashSet<int>(); private readonly int terrainPrefab = StringExtensionMethods.GetStableHashCode("_TerrainCompiler"); private Dictionary<int, float> protectorPrefabs = new Dictionary<int, float>(); private readonly Dictionary<int, string> prefabNames = new Dictionary<int, string>(); private LocationObjects locationObjects; private ZoneReset zones; private float presenceTimer; private float passTimer; private Coroutine running; private Dictionary<Vector2s, List<Terrain.Protector>> protectors = new Dictionary<Vector2s, List<Terrain.Protector>>(); private int s_waitingLogged; private bool terrainStepped; private const float SlotTolerance = 1.5f; private const float RemainsRadius = 1.5f; private readonly HashSet<ZDOID> remainsGone = new HashSet<ZDOID>(); private const float InteriorHeight = 2500f; public Regrowth(MonoBehaviour host, Settings settings) { this.host = host; this.settings = settings; } public void Start() { BuildPrefabSets(); protectorPrefabs = Terrain.ProtectorPrefabs(settings.TerrainProtectMultiplier.Value, out var names); RegrowthPlugin.Log.LogInfo((object)string.Format("Terrain{0}: ground is protected around {1} kinds of base object and ward: {2}", settings.TerrainEnabled.Value ? "" : " (off)", protectorPrefabs.Count, string.Join(", ", names))); if (settings.LocationObjectsEnabled.Value) { locationObjects = new LocationObjects(SplitList(settings.LocationObjectsPrefabs.Value)); } state = new RegrowthState(StatePath()); DateTime dateTime = Now(); state.Load(dateTime); if (!state.PresenceKnownLoaded) { state.PresenceKnownSince = dateTime.AddHours(0f - Math.Max(0f, settings.IdleHours.Value)); } if (settings.ZonesEnabled.Value) { if (RegrowthPlugin.SpawnLocationPatched) { zones = new ZoneReset(settings, state, Name, WorldLoaded); } else { RegrowthPlugin.Log.LogWarning((object)"Zones: switched on after the server started; they need a restart (the game method that keeps a location's rotation is patched at startup only)."); } } passTimer = 60f; RegrowthPlugin.Log.LogInfo((object)("Active" + (settings.DryRun.Value ? " (dry run: nothing will be changed)" : "") + ". " + $"Surtling core stands: {corePrefabs.Count} prefab(s), treasure chests: {chestPrefabs.Count}, one-time spawners: {spawnerPrefabs.Count}, " + "location objects: " + ((locationObjects != null) ? settings.LocationObjectsPrefabs.Value : "off") + ". " + $"Tracking since {state.FirstRun.ToLocalTime():yyyy-MM-dd HH:mm} ({Hours(state.FirstRun, dateTime):0.#} h ago). State: {state.FilePath}")); } public void Stop() { if (running != null) { host.StopCoroutine(running); running = null; } zones?.Stop(); SaveState(); } public void Tick(float dt) { presenceTimer -= dt; if (presenceTimer <= 0f) { presenceTimer = 10f; RecordPresence(); } passTimer -= dt; if (passTimer <= 0f && running == null) { bool value = settings.DryRun.Value; settings.Reload(); if (settings.DryRun.Value != value) { RegrowthPlugin.Log.LogInfo((object)(settings.DryRun.Value ? "Dry run switched on: nothing will be changed." : "Dry run switched off: regrowth is live.")); } passTimer = Mathf.Max(1f, settings.CheckIntervalMinutes.Value) * 60f; running = host.StartCoroutine(Pass()); } } private static DateTime Now() { return DateTime.UtcNow; } private static double Hours(DateTime from, DateTime to) { return (to - from).TotalHours; } private static string StatePath() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) World world = ZNet.World; return Path.Combine(SaveSystem.GetWorldsSaveRootPath(world.m_fileSource), world.m_name + ".regrowth.txt"); } private void SaveState() { try { state?.Save(); } catch (Exception ex) { RegrowthPlugin.Log.LogWarning((object)("Could not save state to " + state.FilePath + ": " + ex.Message)); } } private void BuildPrefabSets() { HashSet<string> hashSet = SplitList(settings.CorePrefabs.Value); HashSet<string> hashSet2 = SplitList(settings.ChestsExclude.Value); HashSet<string> hashSet3 = SplitList(settings.SpawnersExclude.Value); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if (!Object.op_Implicit((Object)(object)prefab)) { continue; } int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); prefabNames[stableHashCode] = ((Object)prefab).name; if (Object.op_Implicit((Object)(object)prefab.GetComponent<Piece>())) { piecePrefabs.Add(stableHashCode); } if (Object.op_Implicit((Object)(object)prefab.GetComponent<TombStone>())) { tombstonePrefabs.Add(stableHashCode); } if (hashSet.Contains(((Object)prefab).name)) { Pickable component = prefab.GetComponent<Pickable>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_hideWhenPicked) && component.m_respawnTimeMinutes <= 0f) { corePrefabs[stableHashCode] = component.m_defaultPicked; } else { RegrowthPlugin.Log.LogWarning((object)(((Object)prefab).name + " is not a non-respawning hide-when-picked pickable; ignored.")); } } if (((Object)prefab).name.StartsWith("TreasureChest_", StringComparison.Ordinal) && !hashSet2.Contains(((Object)prefab).name)) { Container component2 = prefab.GetComponent<Container>(); if (Object.op_Implicit((Object)(object)component2) && !Object.op_Implicit((Object)(object)component2.m_rootObjectOverride) && component2.m_defaultItems.m_drops.Count > 0) { chestPrefabs[stableHashCode] = component2; } else { RegrowthPlugin.Log.LogInfo((object)(((Object)prefab).name + " has no container with a loot table of its own; ignored.")); } } if (Object.op_Implicit((Object)(object)prefab.GetComponent<DungeonGenerator>())) { generatorPrefabs.Add(stableHashCode); } CreatureSpawner component3 = prefab.GetComponent<CreatureSpawner>(); if (Object.op_Implicit((Object)(object)component3) && component3.m_respawnTimeMinuts <= 0f && !hashSet3.Contains(((Object)prefab).name)) { spawnerPrefabs.Add(stableHashCode); } } } private static HashSet<string> SplitList(string value) { return new HashSet<string>(from s in value.Split(new char[1] { ',' }) select s.Trim() into s where s.Length > 0 select s); } private void RecordPresence() { //IL_0050: 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_005a: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) DateTime now = Now(); int num = Mathf.Max(0, settings.PresenceRadiusZones.Value); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (!peer.IsReady() || ((ZDOID)(ref peer.m_characterID)).IsNone()) { continue; } Vector2s zone = ZoneSystem.GetZone(peer.GetRefPos()); zones?.MarkVisited(zone, now); for (int i = -num; i <= num; i++) { for (int j = -num; j <= num; j++) { state.MarkSeen(new Vector2s(zone.x + j, zone.y + i), now); } } } } private static bool WorldLoaded() { if (Object.op_Implicit((Object)(object)ZNet.instance) && ((Behaviour)ZNet.instance).enabled && ZDOMan.instance != null) { return ZDOMan.instance.m_objectsByID.Count > 0; } return false; } private IEnumerator Pass() { try { DateTime now = Now(); bool dryRun = settings.DryRun.Value; Stopwatch wall = Stopwatch.StartNew(); Stopwatch work = Stopwatch.StartNew(); int frames = 1; List<ZDO> zdos = new List<ZDO>(ZDOMan.instance.m_objectsByID.Values); Dictionary<Vector2s, List<Vector3>> blockers = new Dictionary<Vector2s, List<Vector3>>(); Dictionary<Vector2s, List<Terrain.Protector>> protectors = new Dictionary<Vector2s, List<Terrain.Protector>>(); List<Candidate> candidates = new List<Candidate>(); List<ZDO> sources = new List<ZDO>(); Dictionary<Vector2s, List<ZDO>> standing = new Dictionary<Vector2s, List<ZDO>>(); Dictionary<Vector2s, List<ZDO>> remains = new Dictionary<Vector2s, List<ZDO>>(); Dictionary<Vector2s, List<ZDO>> worldPieces = new Dictionary<Vector2s, List<ZDO>>(); Dictionary<Vector2s, List<ZDO>> generators = new Dictionary<Vector2s, List<ZDO>>(); zones?.Clear(); for (int i = 0; i < zdos.Count; i++) { ZDO val = zdos[i]; int prefab = val.GetPrefab(); zones?.Note(val, prefab); if (tombstonePrefabs.Contains(prefab) || (piecePrefabs.Contains(prefab) && val.GetLong(ZDOVars.s_creator, 0L) != 0L)) { AddBlocker(blockers, val.GetPosition()); } else if (locationObjects != null && piecePrefabs.Contains(prefab)) { Vector2s zone = ZoneSystem.GetZone(val.GetPosition()); if (!worldPieces.TryGetValue(zone, out var value)) { value = (worldPieces[zone] = new List<ZDO>()); } value.Add(val); } if (generatorPrefabs.Contains(prefab)) { Vector2s zone2 = ZoneSystem.GetZone(val.GetPosition()); if (!generators.TryGetValue(zone2, out var value2)) { value2 = (generators[zone2] = new List<ZDO>()); } value2.Add(val); } if (protectorPrefabs.TryGetValue(prefab, out var value3) && val.GetLong(ZDOVars.s_creator, 0L) != 0L && val.GetBool(ZDOVars.s_enabled, true)) { AddProtector(protectors, val.GetPosition(), value3); } if (settings.CoresEnabled.Value && corePrefabs.ContainsKey(prefab)) { candidates.Add(new Candidate { kind = Kind.Core, zdo = val, uid = val.m_uid, prefab = prefab }); } else if (settings.ChestsEnabled.Value && chestPrefabs.ContainsKey(prefab)) { candidates.Add(new Candidate { kind = Kind.Chest, zdo = val, uid = val.m_uid, prefab = prefab }); } else if (settings.SpawnersEnabled.Value && spawnerPrefabs.Contains(prefab)) { candidates.Add(new Candidate { kind = Kind.Spawner, zdo = val, uid = val.m_uid, prefab = prefab }); } else if (settings.TerrainEnabled.Value && prefab == terrainPrefab) { candidates.Add(new Candidate { kind = Kind.Terrain, zdo = val, uid = val.m_uid, prefab = prefab }); } else if (locationObjects != null && locationObjects.IsSource(prefab)) { sources.Add(val); } else if (locationObjects != null && locationObjects.IsWanted(prefab)) { Vector2s zone3 = ZoneSystem.GetZone(val.GetPosition()); if (!standing.TryGetValue(zone3, out var value4)) { value4 = (standing[zone3] = new List<ZDO>()); } value4.Add(val); } else if (locationObjects != null && settings.LocationObjectsClearRemains.Value && locationObjects.IsRemains(prefab)) { Vector2s zone4 = ZoneSystem.GetZone(val.GetPosition()); if (!remains.TryGetValue(zone4, out var value5)) { value5 = (remains[zone4] = new List<ZDO>()); } value5.Add(val); } if (i % 4096 == 4095) { frames++; work.Stop(); yield return null; work.Start(); } } if (!WorldLoaded()) { yield break; } int loadedPrefabs = 0; if (locationObjects != null) { IEnumerator refresh = locationObjects.Refresh(sources, delegate(int n) { loadedPrefabs += n; }); while (refresh.MoveNext()) { frames++; work.Stop(); yield return null; work.Start(); } if (!WorldLoaded()) { yield break; } } Dictionary<Kind, Tally> tallies = new Dictionary<Kind, Tally> { { Kind.Core, new Tally() }, { Kind.Chest, new Tally() }, { Kind.Spawner, new Tally() }, { Kind.Terrain, new Tally() } }; if (locationObjects != null) { tallies[Kind.LocationObject] = new Tally(); } this.protectors = protectors; HashSet<string> hashSet = new HashSet<string>(); HashSet<string> regrown = new HashSet<string>(); int errors = 0; Dictionary<string, Group> dictionary = new Dictionary<string, Group>(); Dictionary<Vector2s, List<Place>> places = Places(); foreach (Candidate item in candidates) { try { if (ZDOMan.instance.GetZDO(item.uid) != item.zdo || item.zdo.GetPrefab() != item.prefab) { continue; } if (item.kind == Kind.Terrain) { if (IsDepleted(item.kind, item.zdo, null, now)) { DecideTerrain(item.zdo, now, dryRun, blockers, tallies[item.kind], hashSet); } } else { GroupOf(item, dictionary, places, generators).members.Add(item); } } catch (Exception arg) { if (errors++ == 0) { RegrowthPlugin.Log.LogWarning((object)$"Skipped {Describe(item.kind)} {Name(item.prefab)}: {arg}"); } } } int locationsRegrown = 0; s_waitingLogged = 0; foreach (Group value6 in dictionary.Values) { try { if (DecideGroup(value6, now, dryRun, blockers, tallies, hashSet, regrown) && value6.name != null) { locationsRegrown++; } } catch (Exception ex) { if (errors++ == 0) { RegrowthPlugin.Log.LogWarning((object)string.Format("Skipped {0} at {1:0},{2:0}: {3}", value6.name ?? "an object", value6.position.x, value6.position.z, ex)); } } } if (locationObjects != null) { remainsGone.Clear(); foreach (LocationObjects.Slot item2 in locationObjects.AllSlots()) { try { DecideSlot(item2, now, dryRun, blockers, standing, remains, worldPieces, tallies[Kind.LocationObject], hashSet, regrown); } catch (Exception ex2) { if (errors++ == 0) { RegrowthPlugin.Log.LogWarning((object)$"Skipped {Describe(Kind.LocationObject)} {Name(item2.prefab)} at {item2.position.x:0},{item2.position.z:0}: {ex2}"); } } } } foreach (string item3 in regrown) { state.Forget(item3); hashSet.Remove(item3); } state.KeepOnly(hashSet); ZoneReset.Tally zoneTally = null; if (zones != null && WorldLoaded()) { zoneTally = new ZoneReset.Tally(); IEnumerator refresh = zones.Run(now, blockers, zoneTally); while (refresh.MoveNext()) { frames++; work.Stop(); yield return null; work.Start(); } if (!WorldLoaded()) { yield break; } } bool flag = zoneTally != null && zoneTally.reset > 0 && !settings.ZonesDryRun.Value && !dryRun; bool flag2 = default(bool); if ((regrown.Count > 0 || terrainStepped || flag) && ZNet.instance.EnoughDiskSpaceAvailable(ref flag2, false, (Action<bool>)null)) { ZNet.instance.Save(false, true, true); } DateTime dateTime = now.AddHours(0f - Math.Max(Math.Max(0f, settings.IdleHours.Value), Math.Max(0f, settings.ZonesIdleHours.Value))); state.ForgetZonesSeenBefore(dateTime); if (dateTime > state.PresenceKnownSince) { state.PresenceKnownSince = dateTime; } RegrowthPlugin.Log.LogInfo((object)("Pass" + (dryRun ? " (dry run)" : "") + ": " + string.Join("; ", tallies.Select((KeyValuePair<Kind, Tally> t) => (t.Key != Kind.Terrain) ? ((t.Key != Kind.LocationObject) ? ($"{Describe(t.Key)}s {t.Value.depleted} depleted ({t.Value.waiting} waiting, {t.Value.blocked} near player builds, {t.Value.inUse} in use, " + string.Format("{0} {1})", t.Value.regrown, dryRun ? "would regrow" : "regrown")) : ($"location objects {t.Value.depleted} missing ({t.Value.waiting} waiting, {t.Value.blocked} near player builds, {t.Value.unsupported} with what held them gone, {t.Value.inUse} in use, " + string.Format("{0} {1})", t.Value.regrown, dryRun ? "would put back" : "put back"))) : string.Format("terrain zones {0} modified ({1} waiting, {2} all protected, {3} in use, {4} {5})", t.Value.depleted, t.Value.waiting, t.Value.blocked, t.Value.inUse, t.Value.regrown, dryRun ? "would step" : "stepped"))) + ((locationObjects != null) ? string.Format(" ({0} locations and rooms known{1})", locationObjects.SourceCount, (loadedPrefabs > 0) ? $", {loadedPrefabs} prefab(s) read this pass" : "") : "") + (settings.LocationsTogether.Value ? string.Format("; {0} location(s) {1} as a whole", locationsRegrown, dryRun ? "would regrow" : "regrew") : "") + ((zoneTally != null) ? (string.Format("; zones {0} visited ({1} waiting, {2} due, {3} kept{4}, ", zoneTally.visited, zoneTally.waiting, zoneTally.due, zoneTally.blocked, (zoneTally.why.Count > 0) ? (": " + string.Join(", ", from w in zoneTally.why orderby w.Value descending select $"{w.Value} {w.Key}")) : "") + string.Format("{0} {1}{2})", zoneTally.reset, (settings.ZonesDryRun.Value || dryRun) ? "would be generated again" : "generated again", (zoneTally.failed > 0) ? $", {zoneTally.failed} failed and undone" : "")) : "") + $". Scanned {zdos.Count} objects: {work.ElapsedMilliseconds} ms of work spread over {frames} frames ({wall.ElapsedMilliseconds} ms wall)." + ((errors > 0) ? $" {errors} object(s) skipped after errors." : "") + ((regrown.Count > 0 || terrainStepped || flag) ? " World save requested." : ""))); terrainStepped = false; if (zones != null && zones.RefreshDone) { zones.RefreshDone = false; settings.ZonesRefreshNow.Value = false; RegrowthPlugin.Log.LogInfo((object)"Zones: RefreshNow is done and switched off in the config; the zones and the ground it left follow the usual clocks again."); } SaveState(); } finally { running = null; } } private static Dictionary<Vector2s, List<Place>> Places() { //IL_0025: 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_002b: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) Dictionary<Vector2s, List<Place>> dictionary = new Dictionary<Vector2s, List<Place>>(); foreach (KeyValuePair<Vector2s, LocationInstance> locationInstance in ZoneSystem.instance.m_locationInstances) { LocationInstance value = locationInstance.Value; if (value.m_placed && value.m_location != null) { Vector2s zone = ZoneSystem.GetZone(value.m_position); if (!dictionary.TryGetValue(zone, out var value2)) { value2 = (dictionary[zone] = new List<Place>()); } value2.Add(new Place { zone = locationInstance.Key, name = value.m_location.m_prefabName, position = value.m_position, radius = value.m_location.m_exteriorRadius, interior = value.m_location.m_interiorRadius }); } } return dictionary; } private Group GroupOf(Candidate candidate, Dictionary<string, Group> groups, Dictionary<Vector2s, List<Place>> places, Dictionary<Vector2s, List<ZDO>> generators) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) Vector3 position = candidate.zdo.GetPosition(); bool flag = position.y > 3000f; string text = null; string name = null; Vector3 position2 = position; if (settings.LocationsTogether.Value) { ZDO val = (flag ? Nearest(generators, position, 96f) : null); Vector3 val2 = ((val != null) ? val.GetPosition() : position); if (NearestPlace(places, val2, (val != null) ? Reach.Generator : (flag ? Reach.Interior : Reach.Surface), out var found)) { text = $"location {found.zone.x},{found.zone.y}"; name = found.name; position2 = found.position; } else if (val != null) { text = $"dungeon {val.m_uid}"; name = Name(val.GetPrefab()); position2 = val2; } } if (text == null) { text = Key(candidate.kind, candidate.zdo); } if (!groups.TryGetValue(text, out var value)) { string key = text; Group obj = new Group { name = name, position = position2 }; value = obj; groups[key] = obj; } value.dungeon |= flag; return value; } private static string Summary(List<Candidate> members, List<Candidate> depleted) { return string.Join(", ", (from m in members group m by m.kind).Select(delegate(IGrouping<Kind, Candidate> g) { int num = depleted.Count((Candidate d) => d.kind == g.Key); return string.Format("{0} {1}{2} ({3} {4})", g.Count(), Describe(g.Key), (g.Count() == 1) ? "" : "s", num, (g.Key == Kind.Chest) ? "used" : "used up"); })); } private static ZDO Nearest(Dictionary<Vector2s, List<ZDO>> byZone, Vector3 position, float within) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) ZDO result = null; float num = within * within; Vector2s zone = ZoneSystem.GetZone(position); int num2 = Mathf.CeilToInt(within / 64f); for (int i = -num2; i <= num2; i++) { for (int j = -num2; j <= num2; j++) { if (!byZone.TryGetValue(new Vector2s(zone.x + j, zone.y + i), out var value)) { continue; } foreach (ZDO item in value) { Vector3 val = item.GetPosition() - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude <= num) { num = sqrMagnitude; result = item; } } } } return result; } private static bool NearestPlace(Dictionary<Vector2s, List<Place>> places, Vector3 position, Reach reach, out Place found) { //IL_000f: 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_0015: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) found = default(Place); bool result = false; float num = float.MaxValue; Vector2s zone = ZoneSystem.GetZone(position); for (int i = -2; i <= 2; i++) { for (int j = -2; j <= 2; j++) { if (!places.TryGetValue(new Vector2s(zone.x + j, zone.y + i), out var value)) { continue; } foreach (Place item in value) { float num2 = item.position.x - position.x; float num3 = item.position.z - position.z; float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3); if (num4 <= reach switch { Reach.Interior => (item.interior > 0f) ? (item.interior + 16f) : (-1f), Reach.Generator => 64f, _ => Mathf.Max(item.radius, 16f) + 8f, } && num4 < num) { num = num4; found = item; result = true; } } } } return result; } private bool DecideGroup(Group group, DateTime now, bool dryRun, Dictionary<Vector2s, List<Vector3>> blockers, Dictionary<Kind, Tally> tallies, HashSet<string> stillDepleted, HashSet<string> regrown) { //IL_01b2: 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) List<Candidate> list = new List<Candidate>(); string text = null; double num = double.MinValue; double num2 = double.MinValue; foreach (Candidate member in group.members) { string text2 = Key(member.kind, member.zdo); if (IsDepleted(member.kind, member.zdo, text2, now)) { list.Add(member); tallies[member.kind].depleted++; stillDepleted.Add(text2); double num3 = Hours(state.DepletedSince(text2, now), now); double num4 = num3 - (double)AfterHours(member.kind); num2 = Math.Max(num2, num4); if (num4 >= 0.0 && num4 > num) { num = num4; text = string.Format("{0} {1} {2} {3:0.##} h ago", Describe(member.kind), Name(member.prefab), (member.kind == Kind.Chest) ? "used" : "used up", num3); } } } if (list.Count == 0) { return false; } if (text == null) { num = num2; } double num5 = double.MaxValue; foreach (Candidate member2 in group.members) { num5 = Math.Min(num5, Hours(state.LastSeen(ZoneSystem.GetZone(member2.zdo.GetPosition())), now)); } if (text == null || num5 < (double)settings.IdleHours.Value) { list.ForEach(delegate(Candidate member) { tallies[member.kind].waiting++; }); if (dryRun && s_waitingLogged++ < settings.LogDetailsPerPass.Value) { RegrowthPlugin.Log.LogInfo((object)(string.Format("Waiting: {0} at {1:0},{2:0}{3}: {4}; ", group.name ?? "a lone object", group.position.x, group.position.z, group.dungeon ? " (dungeon)" : "", Summary(group.members, list)) + ((text != null) ? ("due (" + text + ")") : $"due in {0.0 - num:0.#} h") + string.Format(", area idle {0} (needs {1:0.#}).", (num5 > 1000000.0) ? "always" : (num5.ToString("0.##") + " h"), settings.IdleHours.Value))); } return false; } if (group.members.Any((Candidate member) => IsBlocked(blockers, member.zdo.GetPosition()))) { list.ForEach(delegate(Candidate member) { tallies[member.kind].blocked++; }); return false; } if (group.members.Any((Candidate member) => InUse(member.zdo))) { list.ForEach(delegate(Candidate member) { tallies[member.kind].inUse++; }); return false; } Dictionary<Kind, int> dictionary = new Dictionary<Kind, int>(); foreach (Candidate member3 in group.members) { if (list.Contains(member3) || (member3.kind == Kind.Chest && IsRestockable(member3.zdo))) { tallies[member3.kind].regrown++; dictionary[member3.kind] = (dictionary.TryGetValue(member3.kind, out var value) ? value : 0) + 1; if (!dryRun) { Apply(member3.kind, member3.zdo); regrown.Add(Key(member3.kind, member3.zdo)); } } } Tally tally = tallies[list[0].kind]; if (tally.logged < settings.LogDetailsPerPass.Value) { tally.logged++; string text3 = string.Join(", ", dictionary.Select((KeyValuePair<Kind, int> c) => string.Format("{0} {1}{2}", c.Value, Describe(c.Key), (c.Value == 1) ? "" : "s"))); RegrowthPlugin.Log.LogInfo((object)(string.Format("{0} {1} at {2:0},{3:0}{4}: {5}; ", dryRun ? "Would regrow" : "Regrew", group.name ?? "a lone object", group.position.x, group.position.z, group.dungeon ? " (dungeon)" : "", text3) + $"due: {text}, area idle {num5:0.##} h.")); } return true; } private string Key(Kind kind, ZDO zdo) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0056: Unknown result type (might be due to invalid IL or missing references) Vector3 position = zdo.GetPosition(); return string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2:0.0}:{3:0.0}:{4:0.0}", kind, Name(zdo.GetPrefab()).Replace(' ', '_'), position.x, position.y, position.z); } private void DecideTerrain(ZDO zdo, DateTime now, bool dryRun, Dictionary<Vector2s, List<Vector3>> blockers, Tally tally, HashSet<string> stillDepleted) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: 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_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: 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_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) tally.depleted++; string text = Key(Kind.Terrain, zdo); string text2 = "step" + text; stillDepleted.Add(text); Vector3 position = zdo.GetPosition(); double num = Hours(state.DepletedSince(text, now), now); double num2 = Hours(state.LastSeen(ZoneSystem.GetZone(position)), now); bool flag = settings.ZonesRefreshNow.Value && settings.ZonesEnabled.Value && !settings.ZonesDryRun.Value && !dryRun; bool num3; if (!flag) { if (num < (double)settings.TerrainAfterHours.Value) { goto IL_00e1; } num3 = num2 < (double)settings.IdleHours.Value; } else { num3 = num2 < 0.5; } if (!num3) { if (!flag && state.HasKey(text2)) { stillDepleted.Add(text2); if (Hours(state.DepletedSince(text2, now), now) < (double)settings.TerrainStepHours.Value) { tally.waiting++; return; } } if (InUse(zdo)) { tally.inUse++; return; } List<Terrain.Protector> list = ProtectorsNear(position); float value = settings.TerrainProtectPiecesRadius.Value; if (value > 0f) { foreach (Vector3 item in BlockersNear(blockers, position, value + 64f)) { list.Add(new Terrain.Protector { position = item, radius = value }); } } Terrain.Data d = Terrain.Decode(zdo.GetByteArray(ZDOVars.s_TCData, (byte[])null)); Terrain.Stats stats = new Terrain.Stats(); Terrain.Data data = Terrain.Step(d, position, list, settings, stats, flag); if (data == null) { tally.blocked++; return; } tally.regrown++; if (tally.logged < settings.LogDetailsPerPass.Value) { tally.logged++; RegrowthPlugin.Log.LogInfo((object)(string.Format("{0} terrain of zone {1:0},{2:0}: height changes {3} -> {4} vertices, ", dryRun ? "Would step" : "Stepped", position.x, position.z, stats.modifiedBefore, stats.modifiedAfter) + $"paint {stats.paintedBefore} -> {stats.paintedAfter}, {stats.protectedVertices} protected; modified {num:0.#} h ago, area idle {num2:0.##} h.")); } if (!dryRun) { zdo.Set(ZDOVars.s_TCData, Terrain.Encode(data)); state.Forget(text2); state.DepletedSince(text2, now); stillDepleted.Add(text2); terrainStepped = true; } return; } goto IL_00e1; IL_00e1: tally.waiting++; } private List<Terrain.Protector> ProtectorsNear(Vector3 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) List<Terrain.Protector> list = new List<Terrain.Protector>(); Vector2s zone = ZoneSystem.GetZone(position); for (int i = -2; i <= 2; i++) { for (int j = -2; j <= 2; j++) { if (protectors.TryGetValue(new Vector2s(zone.x + j, zone.y + i), out var value)) { list.AddRange(value); } } } return list; } private static IEnumerable<Vector3> BlockersNear(Dictionary<Vector2s, List<Vector3>> blockers, Vector3 position, float radius) { //IL_000f: 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) int zones = Mathf.CeilToInt(radius / 64f); Vector2s zone = ZoneSystem.GetZone(position); for (int dy = -zones; dy <= zones; dy++) { for (int dx = -zones; dx <= zones; dx++) { if (!blockers.TryGetValue(new Vector2s(zone.x + dx, zone.y + dy), out var value)) { continue; } foreach (Vector3 item in value) { yield return item; } } } } private static void AddProtector(Dictionary<Vector2s, List<Terrain.Protector>> protectors, Vector3 position, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_002c: 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) Vector2s zone = ZoneSystem.GetZone(position); if (!protectors.TryGetValue(zone, out var value)) { value = (protectors[zone] = new List<Terrain.Protector>()); } value.Add(new Terrain.Protector { position = position, radius = radius }); } private void DecideSlot(LocationObjects.Slot slot, DateTime now, bool dryRun, Dictionary<Vector2s, List<Vector3>> blockers, Dictionary<Vector2s, List<ZDO>> standing, Dictionary<Vector2s, List<ZDO>> remains, Dictionary<Vector2s, List<ZDO>> worldPieces, Tally tally, HashSet<string> stillDepleted, HashSet<string> regrown) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: 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_02df: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) Vector2s zone = ZoneSystem.GetZone(slot.position); for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (!standing.TryGetValue(new Vector2s(zone.x + j, zone.y + i), out var value)) { continue; } foreach (ZDO item in value) { Vector3 position = item.GetPosition(); float num = position.x - slot.position.x; float num2 = position.z - slot.position.z; if (item.GetPrefab() == slot.prefab && num * num + num2 * num2 <= 2.25f) { return; } } } } tally.depleted++; string text = string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2:0.0}:{3:0.0}:{4:0.0}", Kind.LocationObject, Name(slot.prefab).Replace(' ', '_'), slot.position.x, slot.position.y, slot.position.z); stillDepleted.Add(text); double num3 = Hours(state.DepletedSince(text, now), now); double num4 = Hours(state.LastSeen(zone), now); if (num3 < (double)settings.LocationObjectsAfterHours.Value || num4 < (double)settings.IdleHours.Value) { tally.waiting++; return; } if (IsBlocked(blockers, slot.position)) { tally.blocked++; return; } if (!LocationObjects.Supported(slot, worldPieces)) { tally.unsupported++; return; } if (ZoneSystem.instance.m_zones.ContainsKey(zone)) { tally.inUse++; return; } List<ZDO> list = (settings.LocationObjectsClearRemains.Value ? RemainsNear(remains, slot.position) : new List<ZDO>()); tally.regrown++; if (tally.logged < settings.LogDetailsPerPass.Value) { tally.logged++; RegrowthPlugin.Log.LogInfo((object)(string.Format("{0} {1} of {2} at {3:0},{4:0},{5:0}: ", dryRun ? "Would put back" : "Put back", Name(slot.prefab), slot.source, slot.position.x, slot.position.y, slot.position.z) + $"missing {num3:0.##} h, area idle {num4:0.##} h" + ((list.Count > 0) ? string.Format("; {0} fractured remain(s) {1} with it.", list.Count, dryRun ? "would go" : "go") : "."))); } if (dryRun) { return; } foreach (ZDO item2 in list) { item2.SetOwner(ZDOMan.GetSessionID()); ZDOMan.instance.DestroyZDO(item2); remainsGone.Add(item2.m_uid); } LocationObjects.Create(slot.prefab, slot.position, slot.rotation); regrown.Add(text); } private List<ZDO> RemainsNear(Dictionary<Vector2s, List<ZDO>> remains, Vector3 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0024: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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) List<ZDO> list = new List<ZDO>(); Vector2s zone = ZoneSystem.GetZone(position); for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (!remains.TryGetValue(new Vector2s(zone.x + j, zone.y + i), out var value)) { continue; } foreach (ZDO item in value) { Vector3 position2 = item.GetPosition(); float num = position2.x - position.x; float num2 = position2.z - position.z; if (num * num + num2 * num2 <= 2.25f && Mathf.Abs(position2.y - position.y) < 2f && !remainsGone.Contains(item.m_uid) && !ZoneSystem.instance.m_zones.ContainsKey(ZoneSystem.GetZone(position2))) { list.Add(item); } } } } return list; } private float AfterHours(Kind kind) { return kind switch { Kind.Core => settings.CoresAfterHours.Value, Kind.Chest => settings.ChestsAfterHours.Value, Kind.LocationObject => settings.LocationObjectsAfterHours.Value, _ => settings.SpawnersAfterHours.Value, }; } private static string Describe(Kind kind) { return kind switch { Kind.Core => "surtling core stand", Kind.Chest => "treasure chest", Kind.Terrain => "terrain zone", Kind.LocationObject => "location object", _ => "creature spawner", }; } private string Name(int prefab) { if (!prefabNames.TryGetValue(prefab, out var value)) { return prefab.ToString(); } return value; } private bool IsDepleted(Kind kind, ZDO zdo, string key, DateTime now) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Invalid comparison between Unknown and I4 //IL_00bf: 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) switch (kind) { case Kind.Core: return zdo.GetBool(ZDOVars.s_picked, corePrefabs[zdo.GetPrefab()]); case Kind.Chest: if (IsRestockable(zdo)) { if (!IsEmpty(zdo) && !state.HasKey(key)) { return state.SeenSince(ZoneSystem.GetZone(zdo.GetPosition()), now.AddHours(0f - Math.Max(0f, settings.IdleHours.Value))); } return true; } return false; case Kind.Terrain: return Terrain.IsModified(zdo.GetByteArray(ZDOVars.s_TCData, (byte[])null)); default: { ZDOConnection connection = zdo.GetConnection(); if (connection != null && (int)connection.m_type == 3) { return ZDOMan.instance.GetZDO(connection.m_target) == null; } return false; } } } private static bool IsRestockable(ZDO zdo) { if (zdo.GetLong(ZDOVars.s_creator, 0L) == 0L && zdo.GetBool(ZDOVars.s_addedDefaultItems, false) && !zdo.GetBool(ZDOVars.s_cheated, false)) { return !PlayersItems.InContainer(zdo); } return false; } private static bool IsEmpty(ZDO zdo) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null); if (byteArray == null) { return true; } ZPackage val = new ZPackage(byteArray); return ((val.ReadInt() >= 108) ? val.ReadUShort() : val.ReadInt()) == 0; } private void Apply(Kind kind, ZDO zdo) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) switch (kind) { case Kind.Core: zdo.Set(ZDOVars.s_picked, false); break; case Kind.Chest: Refill(zdo, chestPrefabs[zdo.GetPrefab()]); break; default: zdo.SetConnection((ConnectionType)0, ZDOID.None); break; } } private static void Refill(ZDO zdo, Container prefab) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown Inventory val = new Inventory(prefab.m_name, prefab.m_bkg, prefab.m_width, prefab.m_height); foreach (ItemData dropListItem in prefab.m_defaultItems.GetDropListItems()) { val.AddItem(dropListItem); } ZPackage val2 = new ZPackage(); val.Save(val2); zdo.Set(ZDOVars.s_items, val2.GetArray()); zdo.Set(ZDOVars.s_addedDefaultItems, true); } private static bool InUse(ZDO zdo) { if (Object.op_Implicit((Object)(object)ZNetScene.instance.FindInstance(zdo))) { return true; } long owner = zdo.GetOwner(); if (owner != 0L && owner != ZDOMan.GetSessionID()) { return ZNet.instance.GetPeer(owner) != null; } return false; } private static void AddBlocker(Dictionary<Vector2s, List<Vector3>> blockers, Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0019: Unknown result type (might be due to invalid IL or missing references) Vector2s zone = ZoneSystem.GetZone(position); if (!blockers.TryGetValue(zone, out var value)) { value = (blockers[zone] = new List<Vector3>()); } value.Add(position); } private bool IsBlocked(Dictionary<Vector2s, List<Vector3>> blockers, Vector3 position) { //IL_0028: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0062: 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_0082: 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_0095: 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_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) float num = Mathf.Max(0f, settings.PlayerBuildRadius.Value); int num2 = Mathf.CeilToInt(num / 64f); bool flag = position.y > 2500f; Vector2s zone = ZoneSystem.GetZone(position); for (int i = -num2; i <= num2; i++) { for (int j = -num2; j <= num2; j++) { if (!blockers.TryGetValue(new Vector2s(zone.x + j, zone.y + i), out var value)) { continue; } foreach (Vector3 item in value) { if (item.y > 2500f == flag) { float num3 = item.x - position.x; float num4 = item.z - position.z; if (num3 * num3 + num4 * num4 <= num * num) { return true; } } } } } return false; } } [BepInPlugin("sarkasticeu.resource_regrowth", "Sarkastic.gg Resource Regrowth", "0.8.5")] public class RegrowthPlugin : BaseUnityPlugin { public const string GUID = "sarkasticeu.resource_regrowth"; public const string PluginName = "Sarkastic.gg Resource Regrowth"; public const string PluginVersion = "0.8.5"; internal static ManualLogSource Log; internal static bool SpawnLocationPatched; private Settings settings; private Regrowth regrowth; private void Awake() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; settings = new Settings(((BaseUnityPlugin)this).Config); if (settings.ZonesEnabled.Value) { new Harmony("sarkasticeu.resource_regrowth").CreateClassProcessor(typeof(ZoneSystem_SpawnLocation_Patch)).Patch(); SpawnLocationPatched = true; } } private void Update() { bool flag = settings.Enabled.Value && WorldReady(); if (regrowth == null && flag) { regrowth = new Regrowth((MonoBehaviour)(object)this, settings); regrowth.Start(); } else if (regrowth != null && !flag) { regrowth.Stop(); regrowth = null; } regrowth?.Tick(Time.unscaledDeltaTime); } private void OnDestroy() { regrowth?.Stop(); } private static bool WorldReady() { if (Object.op_Implicit((Object)(object)ZNet.instance) && ((Behaviour)ZNet.instance).enabled && ZNet.instance.IsDedicated() && ZNet.instance.IsServer() && ZNet.World != null && ZDOMan.instance != null && Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)ObjectDB.instance) && Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return ZoneSystem.instance.LocationsGenerated; } return false; } } internal class RegrowthState { private const string TimeFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private readonly string path; private readonly Dictionary<Vector2s, DateTime> lastSeen = new Dictionary<Vector2s, DateTime>(); private readonly Dictionary<string, DateTime> depletedSince = new Dictionary<string, DateTime>(); private readonly Dictionary<Vector2s, DateTime> visited = new Dictionary<Vector2s, DateTime>(); private readonly Dictionary<Vector2s, KeyValuePair<int, Quaternion>> keepRotation = new Dictionary<Vector2s, KeyValuePair<int, Quaternion>>(); public DateTime? ZonesFirstRun { get; set; } public DateTime PresenceKnownSince { get; set; } public bool PresenceKnownLoaded { get; private set; } public DateTime FirstRun { get; private set; } public string FilePath => path; public IEnumerable<KeyValuePair<Vector2s, DateTime>> Visited => visited; public int VisitedCount => visited.Count; public RegrowthState(string path) { this.path = path; } public void Load(DateTime now) { //IL_0198: 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) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) FirstRun = now; string text = path; if (!File.Exists(text)) { text = path + ".tmp"; if (!File.Exists(text)) { return; } } string[] array = File.ReadAllLines(text); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ' ' }); try { string text2 = array2[0]; if (text2 == null) { continue; } switch (text2.Length) { case 8: switch (text2[0]) { case 'f': if (text2 == "firstrun") { FirstRun = Parse(array2[1]); } break; case 'd': if (text2 == "depleted") { depletedSince[array2[1]] = Parse(array2[2]); } break; } break; case 13: switch (text2[0]) { case 'z': if (text2 == "zonesfirstrun") { ZonesFirstRun = Parse(array2[1]); } break; case 'p': if (text2 == "presencesince") { PresenceKnownSince = Parse(array2[1]); PresenceKnownLoaded = true; } break; } break; case 4: if (text2 == "zone") { lastSeen[new Vector2s(int.Parse(array2[1], CultureInfo.InvariantCulture), int.Parse(array2[2], CultureInfo.InvariantCulture))] = Parse(array2[3]); } break; case 7: if (text2 == "visited") { visited[new Vector2s(int.Parse(array2[1], CultureInfo.InvariantCulture), int.Parse(array2[2], CultureInfo.InvariantCulture))] = Parse(array2[3]); } break; case 12: if (text2 == "keeprotation") { keepRotation[new Vector2s(int.Parse(array2[1], CultureInfo.InvariantCulture), int.Parse(array2[2], CultureInfo.InvariantCulture))] = new KeyValuePair<int, Quaternion>(int.Parse(array2[3], CultureInfo.InvariantCulture), new Quaternion(float.Parse(array2[4], CultureInfo.InvariantCulture), float.Parse(array2[5], CultureInfo.InvariantCulture), float.Parse(array2[6], CultureInfo.InvariantCulture), float.Parse(array2[7], CultureInfo.InvariantCulture))); } break; } } catch (Exception) { } } ClampToNow(now); } private void ClampToNow(DateTime now) { //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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_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_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) if (FirstRun > now) { FirstRun = now; } foreach (Vector2s item in new List<Vector2s>(lastSeen.Keys)) { if (lastSeen[item] > now) { lastSeen[item] = now; } } foreach (string item2 in new List<string>(depletedSince.Keys)) { if (depletedSince[item2] > now) { depletedSince[item2] = now; } } if (ZonesFirstRun.HasValue && ZonesFirstRun.Value > now) { ZonesFirstRun = now; } if (PresenceKnownSince > now) { PresenceKnownSince = now; } foreach (Vector2s item3 in new List<Vector2s>(visited.Keys)) { if (visited[item3] > now) { visited[item3] = now; } } } public void Save() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: 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_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string> { "# Sarkastic.gg Resource Regrowth state. Real time, UTC. Edit only while the server is stopped.", "firstrun " + Format(FirstRun) }; foreach (KeyValuePair<Vector2s, DateTime> item in lastSeen) { list.Add($"zone {item.Key.x} {item.Key.y} {Format(item.Value)}"); } foreach (KeyValuePair<string, DateTime> item2 in depletedSince) { list.Add("depleted " + item2.Key + " " + Format(item2.Value)); } if (ZonesFirstRun.HasValue) { list.Add("zonesfirstrun " + Format(ZonesFirstRun.Value)); } list.Add("presencesince " + Format(PresenceKnownSince)); foreach (KeyValuePair<Vector2s, DateTime> item3 in visited) { list.Add($"visited {item3.Key.x} {item3.Key.y} {Format(item3.Value)}"); } foreach (KeyValuePair<Vector2s, KeyValuePair<int, Quaternion>> item4 in keepRotation) { Quaternion value = item4.Value.Value; list.Add(string.Format(CultureInfo.InvariantCulture, "keeprotation {0} {1} {2} {3:R} {4:R} {5:R} {6:R}", item4.Key.x, item4.Key.y, item4.Value.Key, value.x, value.y, value.z, value.w)); } string sourceFileName = path + ".tmp"; File.WriteAllLines(sourceFileName, list); if (File.Exists(path)) { File.Delete(path); } File.Move(sourceFileName, path); } public void MarkSeen(Vector2s zone, DateTime now) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!lastSeen.TryGetValue(zone, out var value) || value < now) { lastSeen[zone] = now; } } public bool SeenSince(Vector2s zone, DateTime since) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (lastSeen.TryGetValue(zone, out var value)) { return value >= since; } return false; } public void MarkVisited(Vector2s zone, DateTime now) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!visited.ContainsKey(zone)) { visited[zone] = now; } } public bool TryLastSeen(Vector2s zone, out DateTime time) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return lastSeen.TryGetValue(zone, out time); } public void ForgetVisit(Vector2s zone) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) visited.Remove(zone); } public void KeepRotation(Vector2s zone, int location, Quaternion rotation) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) keepRotation[zone] = new KeyValuePair<int, Quaternion>(location, rotation); } public bool TakeRotation(Vector2s zone, int location, out Quaternion rotation) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) rotation = Quaternion.identity; if (!keepRotation.TryGetValue(zone, out var value) || value.Key != location) { return false; } keepRotation.Remove(zone); rotation = value.Value; return true; } public DateTime LastSeen(Vector2s zone) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!lastSeen.TryGetValue(zone, out var value)) { return FirstRun; } return value; } public DateTime DepletedSince(string key, DateTime now) { if (!depletedSince.TryGetValue(key, out var value)) { value = now; depletedSince[key] = value; } return value; } public void Forget(string key) { depletedSince.Remove(key); } public bool HasKey(string key) { return depletedSince.ContainsKey(key); } public void ForgetZonesSeenBefore(DateTime cutoff) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) foreach (Vector2s item in new List<Vector2s>(lastSeen.Keys)) { if (lastSeen[item] < cutoff) { lastSeen.Remove(item); } } } public void KeepOnly(HashSet<string> keys) { List<string> list = new List<string>(); foreach (string key in depletedSince.Keys) { if (!keys.Contains(key)) { list.Add(key); } } foreach (string item in list) { depletedSince.Remove(item); } } private static DateTime Parse(string s) { return DateTime.ParseExact(s, "yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); } private static string Format(DateTime time) { return time.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.InvariantCulture); } } internal class Settings { private readonly ConfigFile file; public readonly ConfigEntry<bool> Enabled; public readonly ConfigEntry<bool> DryRun; public readonly ConfigEntry<float> CheckIntervalMinutes; public readonly ConfigEntry<int> LogDetailsPerPass; public readonly ConfigEntry<float> IdleHours; public readonly ConfigEntry<int> PresenceRadiusZones; public readonly ConfigEntry<float> PlayerBuildRadius; public readonly ConfigEntry<bool> LocationsTogether; public readonly ConfigEntry<bool> CoresEnabled; public readonly ConfigEntry<float> CoresAfterHours; public readonly ConfigEntry<string> CorePrefabs; public readonly ConfigEntry<bool> ChestsEnabled; public readonly ConfigEntry<float> ChestsAfterHours; public readonly ConfigEntry<string> ChestsExclude; public readonly ConfigEntry<bool> SpawnersEnabled; public readonly ConfigEntry<float> SpawnersAfterHours; public readonly ConfigEntry<string> SpawnersExclude; public readonly ConfigEntry<bool> LocationObjectsEnabled; public readonly ConfigEntry<float> LocationObjectsAfterHours; public readonly ConfigEntry<string> LocationObjectsPrefabs; public readonly ConfigEntry<bool> LocationObjectsClearRemains; public readonly ConfigEntry<bool> ZonesEnabled; public readonly ConfigEntry<bool> ZonesDryRun; public readonly ConfigEntry<float> ZonesIdleHours; public readonly ConfigEntry<int> ZonesPerPass; public readonly ConfigEntry<float> ZonesGraceMinutes; public readonly ConfigEntry<string> ZonesProtected; public readonly ConfigEntry<bool> ZonesRefreshNow; public readonly ConfigEntry<bool> TerrainEnabled; public readonly ConfigEntry<float> TerrainAfterHours; public readonly ConfigEntry<float> TerrainStepHours; public readonly ConfigEntry<float> TerrainDivider; public readonly ConfigEntry<float> TerrainMinDelta; public readonly ConfigEntry<bool> TerrainKeepPaved; public readonly ConfigEntry<bool> TerrainKeepCultivated; public readonly ConfigEntry<float> TerrainProtectMultiplier; public readonly ConfigEntry<float> TerrainProtectPiecesRadius; public Settings(ConfigFile config) { file = config; Enabled = config.Bind<bool>("General", "Enabled", true, "Enable or disable the plugin."); DryRun = config.Bind<bool>("General", "DryRun", true, "Only log what would be regrown, change nothing. Leave on until the log looks right."); CheckIntervalMinutes = config.Bind<float>("General", "CheckIntervalMinutes", 10f, "How often (real minutes) to look for things to regrow."); LogDetailsPerPass = config.Bind<int>("General", "LogDetailsPerPass", 20, "How many individual objects to log per category and pass; the rest are only counted."); IdleHours = config.Bind<float>("Safety", "IdleHours", 5f, "Nothing is regrown in an area a player has been near within this many real hours. Areas are only tracked from the plugin's first run."); PresenceRadiusZones = config.Bind<int>("Safety", "PresenceRadiusZones", 2, "A player counts as near every zone (64 m square) within this many zones of their own."); PlayerBuildRadius = config.Bind<float>("Safety", "PlayerBuildRadius", 48f, "Nothing within this many metres (horizontally) of a player-built piece or a tombstone is regrown."); LocationsTogether = config.Bind<bool>("Locations", "Together", true, "Everything a location holds regrows together -- a dungeon's interior with its entrance, a camp, a village, a ruin: as soon as one thing in it is due (each kind after its own AfterHours), every surtling core taken, every creature killed and every treasure chest in it come back at once. Off: each object on its own clock."); CoresEnabled = config.Bind<bool>("SurtlingCores", "Enabled", true, "Put taken surtling cores back on their stands (burial chambers and similar)."); CoresAfterHours = config.Bind<float>("SurtlingCores", "AfterHours", 10f, "Real hours after a core was taken (or after the plugin first saw it taken)."); CorePrefabs = config.Bind<string>("SurtlingCores", "Prefabs", "Pickable_SurtlingCoreStand", "Pickables that stay in place when taken (hide-when-picked) and should come back. Comma separated."); ChestsEnabled = config.Bind<bool>("TreasureChests", "Enabled", true, "Restock treasure chests (never player-built ch