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 MerchantSignposts v0.2.0
BepInEx/plugins/MerchantSignposts/MerchantSignposts.dll
Decompiled 2 weeks 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.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] namespace MerchantSignposts; internal static class BuildGround { private static readonly HashSet<int> CompilerPrefabs = new HashSet<int> { StringExtensionMethods.GetStableHashCode("_TerrainCompiler") }; internal static float Height(Vector3 position) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) ZoneSystem zones = ZoneSystem.instance; WorldGenerator world = WorldGenerator.instance; Vector2s zone = ZoneSystem.GetZone(position); Vector3 zonePos = ZoneSystem.GetZonePos(zone); float x0 = zonePos.x - zones.m_zoneSize * 0.5f; float z0 = zonePos.z - zones.m_zoneSize * 0.5f; List<ZDO> list = new List<ZDO>(); ZdoSweep.CollectZone(zone, CompilerPrefabs, list); List<byte[]> list2 = new List<byte[]>(list.Count); foreach (ZDO item in list) { if (ZoneSystem.GetZone(item.GetPosition()) == zone) { list2.Add(item.GetByteArray(ZDOVars.s_TCData, (byte[])null)); } } return TerrainEdits.Height(list2, position.x - x0, position.z - z0, zones.m_zoneSize, (float num, float num2) => SignpostPlan.TerrainHeight(world, zones, new Vector3(x0 + num, 0f, z0 + num2)), delegate { MerchantSignpostsPlugin.Log.LogWarning((object)$"[MerchantSignposts] invalid terrain edits in zone ({zone.x}, {zone.y}); using generated ground"); }, SignpostPlan.TerrainHeight(world, zones, position)); } internal static void CheckMirrors() { MethodInfo[] array = new MethodInfo[5] { AccessTools.Method(typeof(TerrainComp), "Save", (Type[])null, (Type[])null), AccessTools.Method(typeof(TerrainComp), "Load", (Type[])null, (Type[])null), AccessTools.Method(typeof(TerrainComp), "ApplyToHeightmap", (Type[])null, (Type[])null), AccessTools.Method(typeof(HeightmapBuilder), "Build", (Type[])null, (Type[])null), AccessTools.Method(typeof(Heightmap), "RebuildCollisionMesh", (Type[])null, (Type[])null) }; for (int i = 0; i < array.Length; i++) { if (array[i] == null) { MerchantSignpostsPlugin.Log.LogWarning((object)"[MerchantSignposts] a mirrored terrain method is missing; review terrain height compatibility"); break; } } } } internal static class Commitment { internal static void Observe(List<ZDO> boards) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) ZNet instance = ZNet.instance; if (!MerchantSignpostsPlugin.CommitmentEnabled.Value || !MerchantSignpostsPlugin.WorldPlacement.Value || (Object)(object)instance == (Object)null || !instance.IsServer() || ZDOMan.instance == null) { return; } List<(Vector3, string)> list = new List<(Vector3, string)>(); foreach (ZNetPeer peer in instance.GetPeers()) { if (peer.IsReady()) { list.Add((peer.m_refPos, peer.m_playerName)); } } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { list.Add((((Component)localPlayer).transform.position, localPlayer.GetPlayerName())); } if (list.Count == 0 || SignpostPlan.Get() == null) { return; } float value = MerchantSignpostsPlugin.CommitDistance.Value; if (float.IsNaN(value) || float.IsInfinity(value) || value < 0f) { return; } Vector3 val = default(Vector3); foreach (ZDO board in boards) { string text = board.GetString("MerchantSignposts.location", ""); if (text.Length == 0 || board.GetBool("MerchantSignposts.manual", false) || !board.GetVec3("MerchantSignposts.origin", ref val) || board.GetBool("MerchantSignposts.retired", false) || board.GetBool("MerchantSignposts.seen", false)) { continue; } foreach (var item in list) { Vector3 val2 = board.GetPosition() - item.Item1; if (!(val2.x * val2.x + val2.z * val2.z > value * value)) { Mark(board, "MerchantSignposts.seen"); Reconciler.RequestExtendingSweep(); Commit(text, board.GetVec3("MerchantSignposts.target", Vector3.zero), item.Item2); break; } } } } internal static void Commit(string location, Vector3 target, string player) { //IL_004b: 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_005b: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)instance == (Object)null) { return; } List<Vector2s> list = new List<Vector2s>(); bool flag = false; foreach (KeyValuePair<Vector2s, LocationInstance> locationInstance in instance.m_locationInstances) { LocationInstance value = locationInstance.Value; if (value.m_location != null && !(value.m_location.m_prefabName != location)) { if (value.m_placed) { return; } if (Reconciler.Near(value.m_position, target)) { flag = true; } else { list.Add(locationInstance.Key); } } } if (!flag || list.Count == 0) { return; } foreach (Vector2s item in list) { instance.m_locationInstances.Remove(item); } Prune(instance.m_locationIDCache.Values, location, target); Prune(instance.m_locationGroupCache.Values, location, target); Prune(instance.m_locationMaxGroupCache.Values, location, target); Merchants.Merchant merchant; string text = (Merchants.TryFind(location, out merchant) ? merchant.Label : location); MerchantSignpostsPlugin.Log.LogInfo((object)$"[MerchantSignposts] committed {text} at {DateTime.UtcNow:O} on {player}'s sighting, {list.Count} candidates discarded"); Reconciler.RequestExtendingSweep(); } private static void Prune(IEnumerable<List<LocationInstance>> caches, string location, Vector3 target) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) foreach (List<LocationInstance> cache in caches) { cache.RemoveAll((LocationInstance instance) => instance.m_location != null && instance.m_location.m_prefabName == location && !instance.m_placed && !Reconciler.Near(instance.m_position, target)); } } internal static void Mark(ZDO zdo, string key) { if (!zdo.GetBool(key, false)) { zdo.SetOwner(ZDOMan.GetSessionID()); zdo.Set(key, true); } } } internal enum Restoration { Never, NextServerStart, AfterDelay } internal sealed class DestroyedMarker { internal string Identity; internal string LocationPrefab; internal Vector3 Target; internal Vector3 Origin; internal double Time; } internal static class DestroyedStore { private const string RecordsKey = "MerchantSignposts.destroyedRecords.v1"; private static readonly Dictionary<string, DestroyedMarker> ByIdentity = new Dictionary<string, DestroyedMarker>(StringComparer.Ordinal); private static readonly List<DestroyedMarker> Unidentified = new List<DestroyedMarker>(); private static IReadOnlyDictionary<Vector2s, ZDO> Controllers = new Dictionary<Vector2s, ZDO>(); private static readonly HashSet<Vector2s> Dirty = new HashSet<Vector2s>(); private static readonly HashSet<Vector2s> KnownZones = new HashSet<Vector2s>(); private static ZNet _session; private static bool _sessionStart = true; internal static int Count => ByIdentity.Count + Unidentified.Count; internal static bool IsMarked(string identity) { return ByIdentity.ContainsKey(identity); } internal static void BeginSession() { ByIdentity.Clear(); Unidentified.Clear(); Controllers = new Dictionary<Vector2s, ZDO>(); Dirty.Clear(); KnownZones.Clear(); _sessionStart = true; } private static void Sync() { if (_session != ZNet.instance) { _session = ZNet.instance; BeginSession(); } } internal static bool Record(ZDO piece, double now) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) Sync(); DestroyedMarker destroyedMarker = new DestroyedMarker { Identity = piece.GetString("MerchantSignposts.identity", ""), LocationPrefab = piece.GetString("MerchantSignposts.location", ""), Target = piece.GetVec3("MerchantSignposts.target", Vector3.zero), Origin = piece.GetVec3("MerchantSignposts.origin", piece.GetPosition()), Time = now }; if (!Add(destroyedMarker)) { return false; } string arg = LogLabel(destroyedMarker); MerchantSignpostsPlugin.Log.LogInfo((object)$"[MerchantSignposts] destroyed signpost {arg} withheld; restoration={MerchantSignpostsPlugin.DestroyedSignRestoration.Value}"); Write(ZoneSystem.GetZone(destroyedMarker.Origin)); return true; } internal static string LogLabel(DestroyedMarker marker) { Merchants.Merchant merchant; string text = (Merchants.TryFind(marker.LocationPrefab, out merchant) ? merchant.Label : marker.LocationPrefab); string[] array = (marker.Identity ?? "").Split(new char[1] { '/' }); if (array.Length != 3) { return text; } string[] array2 = array[0].Split(new char[1] { ':' }); if (array2.Length != 3 || array2[0] != marker.LocationPrefab || !int.TryParse(array2[1], NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out var result) || !int.TryParse(array2[2], NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out result) || !int.TryParse(array[1], NumberStyles.None, CultureInfo.InvariantCulture, out var result2) || result2 <= 0 || !int.TryParse(array[2], NumberStyles.None, CultureInfo.InvariantCulture, out var result3) || result3 <= 0) { return text; } return text + " spoke " + result2.ToString(CultureInfo.InvariantCulture) + " point " + result3.ToString(CultureInfo.InvariantCulture); } private static bool Add(DestroyedMarker marker) { if (marker.Identity.Length > 0) { if (ByIdentity.ContainsKey(marker.Identity)) { return false; } ByIdentity[marker.Identity] = marker; return true; } if (Unidentified.Exists((DestroyedMarker other) => other.LocationPrefab == marker.LocationPrefab && Reconciler.Near(other.Target, marker.Target) && Reconciler.Near(other.Origin, marker.Origin))) { return false; } Unidentified.Add(marker); return true; } internal static void Prepare(IReadOnlyDictionary<Vector2s, ZDO> controllers, SignpostPlan terrain, out int restored, out int pruned) { Sync(); restored = 0; pruned = 0; Controllers = controllers; Restoration value = MerchantSignpostsPlugin.DestroyedSignRestoration.Value; if (_sessionStart) { _sessionStart = false; Load(); if (value == Restoration.NextServerStart) { restored += RemoveAll((DestroyedMarker marker) => true); } } if (value == Restoration.AfterDelay) { double now = ZNet.instance.GetTimeSeconds(); double delay = (double)MerchantSignpostsPlugin.DestroyedSignRestorationDelayHours.Value * 3600.0; restored += RemoveAll((DestroyedMarker marker) => now >= marker.Time + delay); } pruned += RemoveAll((DestroyedMarker marker) => !Reconciler.CampExists(terrain, marker.LocationPrefab, marker.Target)); Flush(); } internal static bool IsWithheld(SignpostPlan.Planned point, Vector3 anchor) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0075: Unknown result type (might be due to invalid IL or missing references) string text = SignpostPlan.Identity(point); if (ByIdentity.ContainsKey(text)) { return true; } DestroyedMarker destroyedMarker = Unidentified.Find((DestroyedMarker candidate) => Matches(candidate, point, anchor)); if (destroyedMarker == null) { return false; } Unidentified.Remove(destroyedMarker); destroyedMarker.Identity = text; ByIdentity[text] = destroyedMarker; Dirty.Add(ZoneSystem.GetZone(destroyedMarker.Origin)); return true; } private static bool Matches(DestroyedMarker marker, SignpostPlan.Planned point, Vector3 anchor) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (marker.LocationPrefab == point.LocationPrefab && Reconciler.Near(marker.Target, point.Target)) { if (!Reconciler.Near(marker.Origin, point.Position)) { return Reconciler.Near(marker.Origin, anchor); } return true; } return false; } private static int RemoveAll(Predicate<DestroyedMarker> match) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) List<DestroyedMarker> list = new List<DestroyedMarker>(); foreach (DestroyedMarker value in ByIdentity.Values) { if (match(value)) { list.Add(value); } } foreach (DestroyedMarker item in Unidentified) { if (match(item)) { list.Add(item); } } foreach (DestroyedMarker item2 in list) { if (item2.Identity.Length > 0) { ByIdentity.Remove(item2.Identity); } else { Unidentified.Remove(item2); } Dirty.Add(ZoneSystem.GetZone(item2.Origin)); } return list.Count; } private static void Load() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) List<DestroyedMarker> list = new List<DestroyedMarker>(); foreach (DestroyedMarker value in ByIdentity.Values) { if (Dirty.Contains(ZoneSystem.GetZone(value.Origin))) { list.Add(value); } } foreach (DestroyedMarker item in Unidentified) { if (Dirty.Contains(ZoneSystem.GetZone(item.Origin))) { list.Add(item); } } ByIdentity.Clear(); Unidentified.Clear(); foreach (KeyValuePair<Vector2s, ZDO> controller in Controllers) { string text = controller.Value.GetString("MerchantSignposts.destroyedRecords.v1", ""); if (text.Length > 0) { KnownZones.Add(controller.Key); } string[] array = text.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (TryParse(array[i], out var marker)) { Add(marker); } } } foreach (DestroyedMarker item2 in list) { Add(item2); } } internal static void Flush() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) foreach (Vector2s item in new List<Vector2s>(Dirty)) { Write(item); } } internal static void RecheckBeforeSave() { //IL_005b: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) Sync(); if ((Object)(object)ZoneSystem.instance == (Object)null || ZDOMan.instance == null) { return; } Controllers = PieceIndex.ZoneControllers(ZoneSystem.instance); HashSet<Vector2s> hashSet = new HashSet<Vector2s>(KnownZones); hashSet.UnionWith(Dirty); foreach (DestroyedMarker value in ByIdentity.Values) { hashSet.Add(ZoneSystem.GetZone(value.Origin)); } foreach (DestroyedMarker item in Unidentified) { hashSet.Add(ZoneSystem.GetZone(item.Origin)); } int num = 0; foreach (Vector2s item2 in hashSet) { if (Write(item2)) { num++; } } MerchantSignpostsPlugin.Log.LogInfo((object)$"[MerchantSignposts] destroyed save recheck: zones checked={hashSet.Count}, zones rewritten={num}"); } private static bool Write(Vector2s zone) { //IL_0005: 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_0033: 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_005f: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) KnownZones.Add(zone); if (!Controllers.TryGetValue(zone, out var value) || ZDOMan.instance.GetZDO(value.m_uid) != value) { Dirty.Add(zone); return false; } List<string> list = new List<string>(); foreach (DestroyedMarker value2 in ByIdentity.Values) { if (ZoneSystem.GetZone(value2.Origin) == zone) { list.Add(Serialize(value2)); } } foreach (DestroyedMarker item in Unidentified) { if (ZoneSystem.GetZone(item.Origin) == zone) { list.Add(Serialize(item)); } } list.Sort(StringComparer.Ordinal); string text = string.Join("\n", list); Dirty.Remove(zone); if (value.GetString("MerchantSignposts.destroyedRecords.v1", "") == text) { return false; } value.SetOwner(ZDOMan.GetSessionID()); value.Set("MerchantSignposts.destroyedRecords.v1", text); return true; } private static string Serialize(DestroyedMarker marker) { //IL_002a: 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) return string.Join("|", Encode(marker.Identity), Encode(marker.LocationPrefab), Point(marker.Target), Point(marker.Origin), marker.Time.ToString("R", CultureInfo.InvariantCulture)); } private static bool TryParse(string line, out DestroyedMarker marker) { //IL_006f: 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_0076: 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) marker = null; string[] array = line.Split(new char[1] { '|' }); if (array.Length != 5 || !TryPoint(array[2], out var point) || !TryPoint(array[3], out var point2) || !double.TryParse(array[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return false; } try { marker = new DestroyedMarker { Identity = Decode(array[0]), LocationPrefab = Decode(array[1]), Target = point, Origin = point2, Time = result }; return marker.LocationPrefab.Length != 0; } catch (FormatException) { return false; } } private static string Point(Vector3 value) { return string.Join(",", value.x.ToString("R", CultureInfo.InvariantCulture), value.y.ToString("R", CultureInfo.InvariantCulture), value.z.ToString("R", CultureInfo.InvariantCulture)); } private static bool TryPoint(string value, out Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) point = default(Vector3); string[] array = value.Split(new char[1] { ',' }); if (array.Length != 3 || !float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { return false; } point = new Vector3(result, result2, result3); return true; } private static string Encode(string value) { return Convert.ToBase64String(Encoding.UTF8.GetBytes(value ?? "")); } private static string Decode(string value) { return Encoding.UTF8.GetString(Convert.FromBase64String(value)); } } [HarmonyPatch] internal static class DestructionAttribution { private static readonly HashSet<ZDOID> Own = new HashSet<ZDOID>(); private static ZNet _session; internal static void Destroy(ZDO zdo) { Expect(zdo); zdo.SetOwner(ZDOMan.GetSessionID()); ZDOMan.instance.DestroyZDO(zdo); } internal static void Expect(GameObject go) { ZNetView val = (((Object)(object)go != (Object)null) ? go.GetComponent<ZNetView>() : null); ZDO val2 = (((Object)(object)val != (Object)null) ? val.GetZDO() : null); if (val2 != null) { Expect(val2); } } private static void Expect(ZDO zdo) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Sync(); Own.Add(zdo.m_uid); } private static void Sync() { if (_session != ZNet.instance) { _session = ZNet.instance; Own.Clear(); } } [HarmonyPrefix] [HarmonyPatch(typeof(ZDOMan), "RPC_DestroyZDO")] private static void BeforeDestroyZDO(long sender, ZPackage pkg) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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) ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || !instance.IsServer() || ZDOMan.instance == null) { return; } Sync(); int pos = pkg.GetPos(); bool flag = false; try { int num = pkg.ReadInt(); for (int i = 0; i < num; i++) { ZDOID val = pkg.ReadZDOID(); if (sender != ZDOMan.GetSessionID() || !Own.Contains(val)) { ZDO zDO = ZDOMan.instance.GetZDO(val); if (zDO != null && Reconciler.PlannedPiece(zDO) && !zDO.GetBool("MerchantSignposts.retired", false)) { flag |= DestroyedStore.Record(zDO, instance.GetTimeSeconds()); } } } } catch (Exception ex) { MerchantSignpostsPlugin.Log.LogWarning((object)("[MerchantSignposts] could not attribute a destruction: " + ex.Message)); } finally { pkg.SetPos(pos); } if (flag) { Reconciler.RequestSweep(); } } } internal sealed class GameDependencies { internal bool IsOff { get; private set; } = true; internal bool Start(Harmony harmony, Action<string> logOff, IEnumerable<(Type Type, string Name)> extraNames = null, Action afterPatch = null) { IsOff = true; string text; try { List<string> list = new List<string>(); Type[] array = Check(list); if (extraNames != null) { foreach (var extraName in extraNames) { Resolve(extraName.Type, extraName.Name, null, list); } } if (list.Count == 0) { Type[] array2 = array; foreach (Type type in array2) { harmony.CreateClassProcessor(type, true).Patch(); } afterPatch?.Invoke(); IsOff = false; return true; } text = "this game build lacks " + string.Join(", ", list.Distinct()); } catch (Exception ex) { text = "startup failed: " + ex.Message; try { Unpatch(harmony); } catch (Exception ex2) { text = text + "; rollback failed: " + ex2.Message; } } logOff("[MerchantSignposts] off: " + text.Replace('\r', ' ').Replace('\n', ' ')); return false; } internal static void Unpatch(Harmony harmony) { MethodBase[] array = harmony.GetPatchedMethods().ToArray(); foreach (MethodBase methodBase in array) { harmony.Unpatch(methodBase, (HarmonyPatchType)0, harmony.Id); } } private static Type[] Check(List<string> misses) { //IL_01d4: 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_01dd: Unknown result type (might be due to invalid IL or missing references) Type[] array = (from t in typeof(MerchantSignpostsPlugin).Assembly.GetTypes() where t.IsDefined(typeof(HarmonyPatch), inherit: true) || AccessTools.GetDeclaredMethods(t).Any((MethodInfo m) => m.IsDefined(typeof(HarmonyPatch), inherit: true)) select t).OrderBy<Type, string>((Type t) => t.FullName, StringComparer.Ordinal).ToArray(); Type[] array2 = array; foreach (Type type in array2) { HarmonyMethod mergedFromType = HarmonyMethodExtensions.GetMergedFromType(type); foreach (MethodInfo patch in AccessTools.GetDeclaredMethods(type)) { object[] attributes = patch.GetCustomAttributes(inherit: true); if (!new string[6] { "Prefix", "Postfix", "Transpiler", "Finalizer", "ReversePatch", "ILManipulator" }.Any((string k) => patch.Name == k || attributes.Any((object a) => a.GetType().FullName == "HarmonyLib.Harmony" + k))) { if (patch.IsDefined(typeof(HarmonyPatch), inherit: true)) { misses.Add(type.Name + "." + patch.Name + " (no patch kind)"); } continue; } List<HarmonyMethod> fromMethod = HarmonyMethodExtensions.GetFromMethod((MethodBase)patch); if (fromMethod.Count((HarmonyMethod a) => a.methodName != null) > 1) { misses.Add(type.Name + "." + patch.Name + " (multiple targets unsupported)"); continue; } HarmonyMethod val = HarmonyMethodExtensions.Merge(mergedFromType, HarmonyMethod.Merge(fromMethod)); if ((val.methodType.HasValue && val.methodType != (MethodType?)0) || val.declaringType == null || val.methodName == null) { misses.Add(type.Name + "." + patch.Name + " (unsupported target)"); continue; } MethodInfo methodInfo = Resolve(val.declaringType, val.methodName, val.argumentTypes, misses); if (methodInfo != null) { CheckBindings(methodInfo, patch, misses); } } } try { GameFields.Sectors = AccessTools.FieldRefAccess<ZDOMan, List<ZDO>[]>("m_objectsBySector"); } catch (Exception) { misses.Add("ZDOMan.m_objectsBySector"); } try { GameFields.Portals = AccessTools.FieldRefAccess<ZDOMan, Dictionary<SectorIndex, List<ZDO>>>("m_portalObjects"); } catch (Exception) { misses.Add("ZDOMan.m_portalObjects"); } try { GameFields.GeneratedZones = AccessTools.FieldRefAccess<ZoneSystem, HashSet<Vector2s>>("m_generatedZones"); } catch (Exception) { misses.Add("ZoneSystem.m_generatedZones"); } return array; } private static MethodInfo Resolve(Type type, string name, Type[] arguments, List<string> misses) { try { MethodInfo methodInfo = AccessTools.DeclaredMethod(type, name, arguments, (Type[])null); if (methodInfo == null) { misses.Add(type.Name + "." + name); } return methodInfo; } catch (AmbiguousMatchException) { misses.Add(type.Name + "." + name + " (ambiguous)"); return null; } } internal static void CheckBindings(MethodInfo original, MethodInfo patch, List<string> misses) { ParameterInfo[] parameters = original.GetParameters(); ParameterInfo[] parameters2 = patch.GetParameters(); foreach (ParameterInfo parameterInfo in parameters2) { string name = parameterInfo.Name; if (name == "__state" || name.StartsWith("___", StringComparison.Ordinal)) { continue; } Type type = null; int result; if (name == "__instance") { type = (original.IsStatic ? null : original.DeclaringType); } else if (name == "__result") { type = ((original.ReturnType == typeof(void)) ? null : original.ReturnType); } else if (name.StartsWith("__", StringComparison.Ordinal) && int.TryParse(name.Substring(2), out result)) { if (result >= 0 && result < parameters.Length) { type = parameters[result].ParameterType; } } else { type = parameters.FirstOrDefault((ParameterInfo p) => p.Name == name)?.ParameterType; } Type type2 = parameterInfo.ParameterType; bool isByRef = type2.IsByRef; if (type2.IsByRef) { type2 = type2.GetElementType(); } if (type != null && type.IsByRef) { type = type.GetElementType(); } if (type == null || (isByRef ? (type2 != type) : (!type2.IsAssignableFrom(type)))) { misses.Add(original.DeclaringType.Name + "." + original.Name + ":" + name + " (missing or incompatible parameter for " + patch.DeclaringType.Name + "." + patch.Name + ")"); } } } } internal static class GameFields { internal static FieldRef<ZDOMan, List<ZDO>[]> Sectors; internal static FieldRef<ZDOMan, Dictionary<SectorIndex, List<ZDO>>> Portals; internal static FieldRef<ZoneSystem, HashSet<Vector2s>> GeneratedZones; } internal static class InvariantNumbers { internal static string Format(float value) { return value.ToString("R", CultureInfo.InvariantCulture); } internal static string InstanceIdentity(string prefab, int x, int z) { return prefab + ":" + x.ToString(CultureInfo.InvariantCulture) + ":" + z.ToString(CultureInfo.InvariantCulture); } internal static bool IsSubcommand(string word, string command) { return string.Equals(word, command, StringComparison.OrdinalIgnoreCase); } internal static bool TryCoordinates(string[] words, out float x, out float z) { x = (z = 0f); if (words.Length == 0) { return true; } if (words.Length == 2 && float.TryParse(words[0], NumberStyles.Float, CultureInfo.InvariantCulture, out x) && float.TryParse(words[1], NumberStyles.Float, CultureInfo.InvariantCulture, out z) && !float.IsNaN(x) && !float.IsInfinity(x) && !float.IsNaN(z)) { return !float.IsInfinity(z); } return false; } } internal static class Merchants { internal struct Merchant { public string LocationPrefab; public string Label; } private static MerchantSettings _settings = NewSettings(); private static List<Merchant> _merchants; private static readonly Dictionary<string, string> PlacementTables = new Dictionary<string, string>(); private static readonly HashSet<string> ParserWarnings = new HashSet<string>(); private static MerchantSettings NewSettings() { return new MerchantSettings(delegate(string message) { MerchantSignpostsPlugin.Log.LogWarning((object)message); }); } internal static void WarnOnce(string message) { if (ParserWarnings.Add(message)) { MerchantSignpostsPlugin.Log.LogWarning((object)message); } } internal static void Reset() { _settings = NewSettings(); _merchants = null; PlacementTables.Clear(); ParserWarnings.Clear(); } private static IEnumerable<string> Names() { if (_merchants == null) { yield break; } foreach (Merchant merchant in _merchants) { yield return merchant.LocationPrefab; } } internal static void Refresh() { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null || !instance.LocationsGenerated) { return; } if (_merchants == null) { List<string> list = new List<string>(); foreach (ZoneLocation location in instance.m_locations) { list.Add(location.m_prefabName); } _merchants = new List<Merchant>(); foreach (KeyValuePair<string, string> item in _settings.Pairs(MerchantSignpostsPlugin.MerchantTable.Value, "Merchants.Table", list)) { _merchants.Add(new Merchant { LocationPrefab = item.Key, Label = item.Value }); } PlacementTables["trail"] = MerchantSignpostsPlugin.Trails.Value; PlacementTables["water margin"] = MerchantSignpostsPlugin.WaterMargins.Value; PlacementTables["same-merchant keep-out"] = MerchantSignpostsPlugin.SameMerchantKeepOuts.Value; PlacementTables["biome"] = MerchantSignpostsPlugin.Biomes.Value; foreach (KeyValuePair<string, string> placementTable in PlacementTables) { ParsePairs(placementTable.Value, placementTable.Key); } } ParsePairs(MerchantSignpostsPlugin.TextColors.Value, "TextColors"); List<KeyValuePair<string, string>> overrides = ParsePairs(MerchantSignpostsPlugin.PolePrefabs.Value, "PolePrefabs"); _settings.ValidatePosts(MerchantSignpostsPlugin.PolePrefab.Value, overrides, Names(), ((Object)(object)ZNetScene.instance == (Object)null) ? null : ((Func<string, bool>)((string name) => (Object)(object)ZNetScene.instance.GetPrefab(name) != (Object)null))); } internal static List<Merchant> Parse(string table) { Refresh(); if (_merchants != null) { return new List<Merchant>(_merchants); } return new List<Merchant>(); } internal static List<KeyValuePair<string, string>> ParsePairs(string table, string what) { if (PlacementTables.TryGetValue(what, out var value)) { table = value; } return _settings.Pairs(table, what switch { "biome" => "Biomes", "same-merchant keep-out" => "SameMerchantKeepOuts", "water margin" => "WaterMargins", "trail" => "Trails", _ => what, }, (_merchants == null) ? null : Names(), what == "TextColors" || what == "PolePrefabs", what == "TextColors"); } private static string Lookup(string table, string what, string locationPrefab) { Refresh(); foreach (KeyValuePair<string, string> item in ParsePairs(table, what)) { if (string.Equals(item.Key, locationPrefab, StringComparison.OrdinalIgnoreCase)) { return item.Value; } } return null; } internal static string PoleFor(string locationPrefab) { return Lookup(MerchantSignpostsPlugin.PolePrefabs.Value, "PolePrefabs", locationPrefab) ?? MerchantSignpostsPlugin.PolePrefab.Value; } internal static HashSet<string> PolePrefabs() { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal) { MerchantSignpostsPlugin.PolePrefab.Value }; foreach (KeyValuePair<string, string> item in ParsePairs(MerchantSignpostsPlugin.PolePrefabs.Value, "PolePrefabs")) { hashSet.Add(item.Value); } return hashSet; } internal static string SignText(string locationPrefab, string label) { return ColoredText(locationPrefab, label, MerchantSignpostsPlugin.TextTemplate.Value); } internal static string RetiredText(string locationPrefab, string label) { return ColoredText(locationPrefab, label, MerchantSignpostsPlugin.RetiredTextTemplate.Value); } private static string ColoredText(string locationPrefab, string label, string template) { string text = template.Replace("{merchant}", label); string text2 = Lookup(MerchantSignpostsPlugin.TextColors.Value, "TextColors", locationPrefab); if (!string.IsNullOrEmpty(text2)) { return "<color=" + text2 + ">" + text + "</color>"; } return text; } internal static bool TryLabel(string locationPrefab, out string label) { label = null; foreach (Merchant item in Parse(MerchantSignpostsPlugin.MerchantTable.Value)) { if (item.LocationPrefab == locationPrefab) { label = item.Label; } } return label != null; } internal static string ExpectedText(ZDO board) { string text = board.GetString("MerchantSignposts.location", ""); string label; bool flag = TryLabel(text, out label); if (board.GetBool("MerchantSignposts.retired", false)) { return RetiredText(text, label ?? text); } if (!flag) { return null; } return SignText(text, label); } internal static bool TryFind(string nameOrLabel, out Merchant merchant) { foreach (Merchant item in Parse(MerchantSignpostsPlugin.MerchantTable.Value)) { if (string.Equals(item.LocationPrefab, nameOrLabel, StringComparison.OrdinalIgnoreCase) || string.Equals(item.Label, nameOrLabel, StringComparison.OrdinalIgnoreCase)) { merchant = item; return true; } } merchant = default(Merchant); return false; } internal static bool TryNearestInstance(string locationPrefab, Vector3 from, out Vector3 position, out bool placed, out int remaining) { //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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0054: 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_0071: 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) //IL_0088: 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_008f: 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) position = Vector3.zero; placed = false; remaining = 0; ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return false; } float num = float.MaxValue; bool result = false; foreach (KeyValuePair<Vector2s, LocationInstance> locationInstance in instance.m_locationInstances) { LocationInstance value = locationInstance.Value; if (value.m_location != null && !(value.m_location.m_prefabName != locationPrefab)) { remaining++; float num2 = Vector3.Distance(from, value.m_position); if (num2 < num) { num = num2; position = value.m_position; placed = value.m_placed; result = true; } } } return result; } } internal sealed class MerchantSettings { private readonly Action<string> _warning; private readonly HashSet<string> _warned = new HashSet<string>(StringComparer.Ordinal); private readonly Dictionary<string, List<KeyValuePair<string, string>>> _cache = new Dictionary<string, List<KeyValuePair<string, string>>>(StringComparer.Ordinal); private string _lastPosts; internal MerchantSettings(Action<string> warning) { _warning = warning; } internal void Reset() { _warned.Clear(); _cache.Clear(); _lastPosts = null; } internal List<KeyValuePair<string, string>> Pairs(string raw, string table, IEnumerable<string> known, bool firstWins = false, bool colors = false) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); if (known != null) { foreach (string item in known) { if (!dictionary.ContainsKey(item)) { dictionary.Add(item, item); } } } List<string> list = new List<string>(dictionary.Values); list.Sort(StringComparer.Ordinal); string key = table + "\0" + raw + "\0" + firstWins + "\0" + colors + "\0" + ((known == null) ? "*" : string.Join("\0", list)); if (_cache.TryGetValue(key, out var value)) { return new List<KeyValuePair<string, string>>(value); } List<KeyValuePair<string, string>> list2 = new List<KeyValuePair<string, string>>(); Dictionary<string, int> dictionary2 = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); string[] array = (raw ?? "").Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0) { continue; } int num = text.IndexOf('='); string text2 = ((num < 0) ? "" : text.Substring(0, num).Trim()); string text3 = ((num < 0) ? "" : text.Substring(num + 1).Trim()); if (text2.Length == 0 || text3.Length == 0) { Warn(raw, table, "ignoring malformed " + table + " entry '" + text + "'"); continue; } if (known != null) { if (!dictionary.TryGetValue(text2, out var value2)) { Warn(raw, table, "ignoring " + table + " name '" + text2 + "': no matching " + ((table == "Merchants.Table") ? "game location" : "merchant")); continue; } text2 = value2; } int value3; bool flag = dictionary2.TryGetValue(text2, out value3); if (flag) { Warn(raw, table, "duplicate " + table + " name '" + text2 + "': " + (firstWins ? "first entry wins" : "last entry wins")); if (firstWins) { continue; } } if (colors && !ValidColor(text3)) { Warn(raw, table, "ignoring invalid " + table + " colour '" + text3 + "' for '" + text2 + "'; using vanilla colour"); if (firstWins && !flag) { dictionary2.Add(text2, -1); } } else { KeyValuePair<string, string> keyValuePair = new KeyValuePair<string, string>(text2, text3); if (flag && value3 >= 0) { list2[value3] = keyValuePair; continue; } dictionary2[text2] = list2.Count; list2.Add(keyValuePair); } } _cache.Add(key, list2); return new List<KeyValuePair<string, string>>(list2); } private void Warn(string raw, string table, string message) { if (_warned.Add(table + "\0" + raw + "\0" + message)) { _warning("[MerchantSignposts] " + message); } } internal void ValidatePosts(string defaultPost, List<KeyValuePair<string, string>> overrides, IEnumerable<string> merchants, Func<string, bool> exists) { if (exists == null) { return; } Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.Ordinal); dictionary[defaultPost] = new List<string>(); Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); string text = defaultPost; foreach (KeyValuePair<string, string> @override in overrides) { dictionary2[@override.Key] = @override.Value; text = text + "\0" + @override.Key + "=" + @override.Value; if (!dictionary.ContainsKey(@override.Value)) { dictionary[@override.Value] = new List<string>(); } } foreach (string merchant in merchants) { string value; string key = (dictionary2.TryGetValue(merchant, out value) ? value : defaultPost); dictionary[key].Add(merchant); text = text + "\0merchant=" + merchant; } if (_lastPosts == text) { return; } _lastPosts = text; foreach (KeyValuePair<string, List<string>> item in dictionary) { if (!exists(item.Key)) { Warn(text, "PolePrefab/PolePrefabs", "unknown post prefab '" + item.Key + "' in PolePrefab/PolePrefabs; affected merchants: " + ((item.Value.Count == 0) ? "none" : string.Join(", ", item.Value)) + ". Existing signposts stay standing; no new signposts will be built for these merchants until corrected."); } } } internal static bool ValidColor(string value) { if (string.IsNullOrEmpty(value)) { return false; } if (value[0] == '#') { int num = value.Length - 1; if (num != 3 && num != 4 && num != 6 && num != 8) { return false; } for (int i = 1; i < value.Length; i++) { char c = value[i]; if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F')) { return false; } } return true; } switch (value.ToLowerInvariant()) { case "blue": case "grey": case "black": case "green": case "white": case "orange": case "purple": case "yellow": case "red": case "lightblue": return true; default: return false; } } } internal sealed class ObstacleIndex { private sealed class Disc { private readonly float _x; private readonly float _z; private readonly float _radius; internal Disc(float x, float z, float radius) { _x = x; _z = z; _radius = radius; } internal bool Covers(Bounds sign) { //IL_0008: 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) //IL_0032: 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) float num = Mathf.Clamp(_x, ((Bounds)(ref sign)).min.x, ((Bounds)(ref sign)).max.x) - _x; float num2 = Mathf.Clamp(_z, ((Bounds)(ref sign)).min.z, ((Bounds)(ref sign)).max.z) - _z; return num * num + num2 * num2 < _radius * _radius; } internal IEnumerable<(int, int)> Cells() { for (int x = Cell(_x - _radius); x <= Cell(_x + _radius); x++) { for (int z = Cell(_z - _radius); z <= Cell(_z + _radius); z++) { yield return (x, z); } } } } internal const float BaseReach = 5f; private readonly Dictionary<(int, int), List<Bounds>> _cells = new Dictionary<(int, int), List<Bounds>>(); private const float CellSize = 64f; private readonly HashSet<string> _unnetworked = new HashSet<string>(StringComparer.Ordinal); private readonly List<(int Hash, Bounds Local)> _measured = new List<(int, Bounds)>(); private readonly HashSet<int> _hashes = new HashSet<int>(); private readonly Dictionary<ZDOID, List<Bounds>> _byObject = new Dictionary<ZDOID, List<Bounds>>(); private readonly HashSet<Vector2s> _indexed = new HashSet<Vector2s>(); private readonly Dictionary<int, float> _stations = new Dictionary<int, float>(); private readonly Dictionary<(int, int), List<Disc>> _stationCells = new Dictionary<(int, int), List<Disc>>(); private readonly Dictionary<ZDOID, Disc> _discs = new Dictionary<ZDOID, Disc>(); private float _maximumReach; private int _count; internal int Count => _count; internal int StationCount => _discs.Count; internal int UnnetworkedCount => _unnetworked.Count; internal IEnumerable<string> UnnetworkedNames => _unnetworked; internal string Maintenance { get; private set; } = "full"; internal int Removed { get; private set; } internal int ExtendedZones { get; private set; } internal static ObstacleIndex Refresh(ObstacleIndex live, bool rebuild, ZoneSystem zones, HashSet<Vector2s> generated) { if (rebuild || live == null) { ObstacleIndex obstacleIndex = Build(zones); obstacleIndex.MarkIndexed(generated); return obstacleIndex; } live.Extend(generated); return live; } internal static ObstacleIndex Build(ZoneSystem zones) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) ObstacleIndex obstacleIndex = new ObstacleIndex(); if ((Object)(object)zones == (Object)null || ZDOMan.instance == null) { return obstacleIndex; } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); List<(int, Bounds)> measured = obstacleIndex._measured; foreach (ZoneVegetation item in zones.m_vegetation) { GameObject prefab = item.m_prefab; if (item.m_enable && !((Object)(object)prefab == (Object)null) && hashSet.Add(((Object)prefab).name) && SignpostBuilder.TryMeasure(prefab, out var local)) { if ((Object)(object)prefab.GetComponent<ZNetView>() == (Object)null) { obstacleIndex._unnetworked.Add(((Object)prefab).name); continue; } float num = Mathf.Sqrt(Mathf.Max(((Bounds)(ref local)).min.x * ((Bounds)(ref local)).min.x, ((Bounds)(ref local)).max.x * ((Bounds)(ref local)).max.x) + Mathf.Max(((Bounds)(ref local)).min.z * ((Bounds)(ref local)).min.z, ((Bounds)(ref local)).max.z * ((Bounds)(ref local)).max.z)); obstacleIndex._maximumReach = Mathf.Max(obstacleIndex._maximumReach, num * Mathf.Max(Mathf.Abs(item.m_scaleMin), Mathf.Abs(item.m_scaleMax))); measured.Add((StringExtensionMethods.GetStableHashCode(((Object)prefab).name), local)); } } obstacleIndex.MeasureStations(); foreach (var item2 in measured) { obstacleIndex._hashes.Add(item2.Item1); } foreach (int key in obstacleIndex._stations.Keys) { obstacleIndex._hashes.Add(key); } Dictionary<int, List<ZDO>> dictionary = ZdoSweep.CollectMany(obstacleIndex._hashes); foreach (var item3 in measured) { foreach (ZDO item4 in dictionary[item3.Item1]) { obstacleIndex.Add(item4, item3.Item2); } } foreach (int key2 in obstacleIndex._stations.Keys) { foreach (ZDO item5 in dictionary[key2]) { obstacleIndex.AddStation(item5); } } return obstacleIndex; } private void MeasureStations() { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return; } foreach (GameObject prefab in instance.m_prefabs) { if ((Object)(object)prefab == (Object)null) { continue; } CraftingStation component = prefab.GetComponent<CraftingStation>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)prefab.GetComponent<ZNetView>() == (Object)null)) { float num = component.m_rangeBuild + 5f; if (!(num <= 0f)) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); _stations[stableHashCode] = (_stations.TryGetValue(stableHashCode, out var value) ? Mathf.Max(value, num) : num); } } } } internal void MarkIndexed(IEnumerable<Vector2s> zones) { Maintenance = "full"; ExtendedZones = 0; if (zones != null) { _indexed.UnionWith(zones); } } internal void Extend(HashSet<Vector2s> generated) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) Maintenance = "extend"; ExtendedZones = 0; if (generated == null || ZDOMan.instance == null) { return; } List<ZDO> list = new List<ZDO>(); foreach (Vector2s item in generated) { if (!_indexed.Add(item)) { continue; } ExtendedZones++; ZdoSweep.CollectZone(item, _hashes, list); foreach (ZDO item2 in list) { AddStation(item2); if (_byObject.ContainsKey(item2.m_uid)) { continue; } foreach (var item3 in _measured) { if (item3.Hash == item2.GetPrefab()) { Add(item2, item3.Local); } } } } } internal void Remove(ZDOID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_00f1: 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) //IL_011e: Unknown result type (might be due to invalid IL or missing references) if (_discs.TryGetValue(id, out var value)) { _discs.Remove(id); Removed++; foreach (var item in value.Cells()) { if (_stationCells.TryGetValue(item, out var value2)) { value2.Remove(value); if (value2.Count == 0) { _stationCells.Remove(item); } } } } if (!_byObject.TryGetValue(id, out var value3)) { return; } _byObject.Remove(id); Removed++; foreach (Bounds item2 in value3) { Bounds current2 = item2; _count--; for (int i = Cell(((Bounds)(ref current2)).min.x); i <= Cell(((Bounds)(ref current2)).max.x); i++) { for (int j = Cell(((Bounds)(ref current2)).min.z); j <= Cell(((Bounds)(ref current2)).max.z); j++) { if (_cells.TryGetValue((i, j), out var value4)) { value4.Remove(current2); if (value4.Count == 0) { _cells.Remove((i, j)); } } } } } } private void Add(ZDO zdo, Bounds local) { //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_0010: 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_0012: 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_003b: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_007b: 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_0069: Unknown result type (might be due to invalid IL or missing references) Vector3 vec = zdo.GetVec3(ZDOVars.s_scaleHash, Vector3.zero); if (vec == Vector3.zero) { float num = zdo.GetFloat(ZDOVars.s_scaleScalarHash, 1f); ((Vector3)(ref vec))..ctor(num, num, num); } Bounds val = Transform(local, zdo.GetPosition(), zdo.GetRotation(), vec); if (!_byObject.TryGetValue(zdo.m_uid, out var value)) { _byObject.Add(zdo.m_uid, value = new List<Bounds>()); } value.Add(val); Add(val); } internal void AddStation(ZDO zdo) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_004a: Unknown result type (might be due to invalid IL or missing references) if (!_stations.TryGetValue(zdo.GetPrefab(), out var value) || _discs.ContainsKey(zdo.m_uid)) { return; } Vector3 position = zdo.GetPosition(); Disc disc = new Disc(position.x, position.z, value); _discs.Add(zdo.m_uid, disc); foreach (var item in disc.Cells()) { if (!_stationCells.TryGetValue(item, out var value2)) { _stationCells.Add(item, value2 = new List<Disc>()); } value2.Add(disc); } } internal bool TryClear(Bounds sign, HashSet<Vector2s> generated, bool keepOutOfBases, out bool clear) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) clear = false; if (generated == null) { return false; } foreach (Vector2s item in RequiredZones(sign)) { if (!generated.Contains(item)) { return false; } } for (int i = Cell(((Bounds)(ref sign)).min.x); i <= Cell(((Bounds)(ref sign)).max.x); i++) { for (int j = Cell(((Bounds)(ref sign)).min.z); j <= Cell(((Bounds)(ref sign)).max.z); j++) { if (!_cells.TryGetValue((i, j), out var value)) { continue; } foreach (Bounds item2 in value) { Bounds current2 = item2; if (((Bounds)(ref current2)).Intersects(sign)) { return true; } } } } if (keepOutOfBases) { for (int k = Cell(((Bounds)(ref sign)).min.x); k <= Cell(((Bounds)(ref sign)).max.x); k++) { for (int l = Cell(((Bounds)(ref sign)).min.z); l <= Cell(((Bounds)(ref sign)).max.z); l++) { if (!_stationCells.TryGetValue((k, l), out var value2)) { continue; } foreach (Disc item3 in value2) { if (item3.Covers(sign)) { return true; } } } } } clear = true; return true; } private static int Cell(float position) { return Mathf.FloorToInt(position / 64f); } private void Add(Bounds obstacle) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0073: 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) _count++; for (int i = Cell(((Bounds)(ref obstacle)).min.x); i <= Cell(((Bounds)(ref obstacle)).max.x); i++) { for (int j = Cell(((Bounds)(ref obstacle)).min.z); j <= Cell(((Bounds)(ref obstacle)).max.z); j++) { if (!_cells.TryGetValue((i, j), out var value)) { _cells.Add((i, j), value = new List<Bounds>()); } value.Add(obstacle); } } } internal List<Vector2s> RequiredZones(Bounds sign) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_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_0058: 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_0062: 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_0071: Unknown result type (might be due to invalid IL or missing references) List<Vector2s> list = new List<Vector2s>(); Vector3 val = ((Bounds)(ref sign)).min - new Vector3(_maximumReach, 0f, _maximumReach); Vector3 val2 = ((Bounds)(ref sign)).max + new Vector3(_maximumReach, 0f, _maximumReach); Vector2s zone = ZoneSystem.GetZone(val); Vector2s zone2 = ZoneSystem.GetZone(val2); for (short num = zone.x; num <= zone2.x; num++) { for (short num2 = zone.y; num2 <= zone2.y; num2++) { list.Add(new Vector2s(num, num2)); } } return list; } internal static Bounds Transform(Bounds local, Vector3 position, Quaternion rotation, Vector3 scale) { //IL_0004: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) //IL_0085: 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_00a3: 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_0093: Unknown result type (might be due to invalid IL or missing references) bool flag = true; Bounds result = default(Bounds); Vector3 val = default(Vector3); for (int i = 0; i < 8; i++) { ((Vector3)(ref val))..ctor(((i & 1) == 0) ? ((Bounds)(ref local)).min.x : ((Bounds)(ref local)).max.x, ((i & 2) == 0) ? ((Bounds)(ref local)).min.y : ((Bounds)(ref local)).max.y, ((i & 4) == 0) ? ((Bounds)(ref local)).min.z : ((Bounds)(ref local)).max.z); val = Vector3.Scale(val, scale); Vector3 val2 = position + rotation * val; if (flag) { ((Bounds)(ref result))..ctor(val2, Vector3.zero); flag = false; } else { ((Bounds)(ref result)).Encapsulate(val2); } } return result; } } internal static class PieceIndex { private static ZNet _session; private static readonly HashSet<int> Walked = new HashSet<int>(); private static readonly HashSet<ZDOID> Pieces = new HashSet<ZDOID>(); private static readonly Dictionary<Vector2s, ZDO> Controllers = new Dictionary<Vector2s, ZDO>(); private static readonly Dictionary<ZDOID, Vector2s> ControllerZones = new Dictionary<ZDOID, Vector2s>(); private static int _controllerHash; internal static int Walks { get; private set; } internal static int ZoneReads { get; private set; } internal static int Count => Pieces.Count; internal static int ControllerCount => Controllers.Count; private static void Sync() { if (_session != ZNet.instance) { _session = ZNet.instance; Walked.Clear(); Pieces.Clear(); Controllers.Clear(); ControllerZones.Clear(); _controllerHash = 0; Walks = 0; ZoneReads = 0; } } internal static void Add(ZDO zdo) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Sync(); Pieces.Add(zdo.m_uid); } internal static void Remove(ZDOID id) { //IL_0005: 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_0021: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) Pieces.Remove(id); if (ControllerZones.TryGetValue(id, out var value)) { ControllerZones.Remove(id); if (Controllers.TryGetValue(value, out var value2) && value2.m_uid == id) { Controllers.Remove(value); } } } internal static List<ZDO> Find(IEnumerable<string> prefabs) { //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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) Sync(); HashSet<int> hashSet = new HashSet<int>(); foreach (string prefab in prefabs) { hashSet.Add(StringExtensionMethods.GetStableHashCode(prefab)); } Walk(hashSet); List<ZDO> list = new List<ZDO>(); List<ZDOID> list2 = new List<ZDOID>(); foreach (ZDOID piece in Pieces) { ZDO zDO = ZDOMan.instance.GetZDO(piece); if (zDO == null) { list2.Add(piece); } else if (zDO.IsValid() && hashSet.Contains(zDO.GetPrefab())) { list.Add(zDO); } } foreach (ZDOID item in list2) { Pieces.Remove(item); } list.Sort(delegate(ZDO a, ZDO b) { int num = ((ZDOID)(ref a.m_uid)).UserID.CompareTo(((ZDOID)(ref b.m_uid)).UserID); return (num == 0) ? ((ZDOID)(ref a.m_uid)).ID.CompareTo(((ZDOID)(ref b.m_uid)).ID) : num; }); return list; } internal static IReadOnlyDictionary<Vector2s, ZDO> ZoneControllers(ZoneSystem zones) { //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_005b: 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) Sync(); Walk(new HashSet<int>()); ZoneReads = 0; if (_controllerHash == 0) { return Controllers; } HashSet<Vector2s> obj = Reconciler.GeneratedZones.Invoke(zones); List<ZDO> list = new List<ZDO>(); HashSet<int> prefabs = new HashSet<int> { _controllerHash }; foreach (Vector2s item in obj) { if (Controllers.ContainsKey(item)) { continue; } ZoneReads++; ZdoSweep.CollectZone(item, prefabs, list); foreach (ZDO item2 in list) { AddController(item2); } } return Controllers; } private static void Walk(HashSet<int> needed) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) HashSet<int> hashSet = new HashSet<int>(); foreach (int item in needed) { if (!Walked.Contains(item)) { hashSet.Add(item); } } ZoneSystem instance = ZoneSystem.instance; bool flag = _controllerHash == 0 && (Object)(object)instance != (Object)null && (Object)(object)instance.m_zoneCtrlPrefab != (Object)null; if (flag) { _controllerHash = StringExtensionMethods.GetStableHashCode(((Object)instance.m_zoneCtrlPrefab).name); } if (hashSet.Count == 0 && !flag) { return; } HashSet<int> hashSet2 = new HashSet<int>(hashSet); if (flag) { hashSet2.Add(_controllerHash); } Walks++; foreach (KeyValuePair<int, List<ZDO>> item2 in ZdoSweep.CollectMany(hashSet2)) { foreach (ZDO item3 in item2.Value) { if (flag && item2.Key == _controllerHash) { AddController(item3); } if (hashSet.Contains(item2.Key) && item3.GetString("MerchantSignposts.location", "").Length > 0) { Pieces.Add(item3.m_uid); } } } Walked.UnionWith(hashSet); } private static void AddController(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_000b: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Vector2s zone = ZoneSystem.GetZone(zdo.GetPosition()); if (Controllers.TryGetValue(zone, out var value)) { ControllerZones.Remove(value.m_uid); } Controllers[zone] = zdo; ControllerZones[zdo.m_uid] = zone; } } internal static class PlacementSearch { internal enum Probe { Rejected, Obstructed, Unknown, Clear } internal enum Outcome { Placed, Pending, Omitted } internal struct Result { internal Outcome Outcome; internal Vector3 Position; } internal static Result Select(Vector3 anchor, float radius, Func<Vector3, Probe> evaluate) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0060: 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_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) foreach (Vector3 item in Offsets(radius, includeOrigin: true)) { Vector3 val = anchor + item; switch (evaluate(val)) { case Probe.Clear: return new Result { Outcome = Outcome.Placed, Position = val }; case Probe.Unknown: return new Result { Outcome = Outcome.Pending, Position = val }; } } return new Result { Outcome = Outcome.Omitted, Position = anchor }; } internal static List<Vector3> Offsets(float radius, bool includeOrigin) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = new List<Vector3>(); if (!FiniteNonNegative(radius) || radius > 50f) { return list; } if (includeOrigin) { list.Add(Vector3.zero); } for (int i = -50; i <= 50; i += 10) { for (int j = -50; j <= 50; j += 10) { if ((i != 0 || j != 0) && (float)(i * i + j * j) <= radius * radius) { list.Add(new Vector3((float)i, 0f, (float)j)); } } } list.Sort(delegate(Vector3 a, Vector3 b) { //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_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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_003a: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_008e: Unknown result type (might be due to invalid IL or missing references) if (a == Vector3.zero) { if (!(b == Vector3.zero)) { return -1; } return 0; } if (b == Vector3.zero) { return 1; } int num = (a.x * a.x + a.z * a.z).CompareTo(b.x * b.x + b.z * b.z); if (num != 0) { return num; } int num2 = a.x.CompareTo(b.x); return (num2 == 0) ? a.z.CompareTo(b.z) : num2; }); return list; } private static bool FiniteNonNegative(float value) { if (!float.IsNaN(value) && !float.IsInfinity(value)) { return value >= 0f; } return false; } } internal enum ResolvedOutcome { Placed, Pending, Omitted, RetainedObstructed } internal sealed class PlacementDecision { internal string Identity; internal string LocationPrefab; internal string Fingerprint; internal Vector3 Target; internal Vector3 Anchor; internal Vector3 Position; internal ResolvedOutcome Outcome; internal bool Found; internal bool Retired; } internal sealed class PlacementStore { private const string RecordsKey = "MerchantSignposts.placementRecords.v1"; private IReadOnlyDictionary<Vector2s, ZDO> _controllers = new Dictionary<Vector2s, ZDO>(); private readonly Dictionary<string, PlacementDecision> _records = new Dictionary<string, PlacementDecision>(StringComparer.Ordinal); private static ZNet _session; private static Dictionary<Vector2s, string> _values; internal IReadOnlyDictionary<Vector2s, ZDO> Controllers => _controllers; internal IEnumerable<PlacementDecision> Records => _records.Values; internal static PlacementStore Load(ZoneSystem zones) { //IL_00c2: 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) PlacementStore placementStore = new PlacementStore(); if ((Object)(object)zones == (Object)null || (Object)(object)zones.m_zoneCtrlPrefab == (Object)null || ZDOMan.instance == null) { return placementStore; } placementStore._controllers = PieceIndex.ZoneControllers(zones); Sync(); if (_values == null) { _values = new Dictionary<Vector2s, string>(); foreach (KeyValuePair<Vector2s, ZDO> controller in placementStore._controllers) { string text = controller.Value.GetString("MerchantSignposts.placementRecords.v1", ""); if (text.Length > 0) { _values[controller.Key] = text; } } } foreach (KeyValuePair<Vector2s, string> value in _values) { Write(placementStore._controllers, value.Key, value.Value); string[] array = value.Value.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (TryParse(array[i], out var record)) { placementStore._records[record.Identity] = record; } } } return placementStore; } internal bool HasController(Vector3 anchor) { //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) return _controllers.ContainsKey(ZoneSystem.GetZone(anchor)); } internal bool TryGet(string identity, out PlacementDecision decision) { return _records.TryGetValue(identity, out decision); } internal void Put(PlacementDecision decision) { _records[decision.Identity] = decision; } internal void PruneExcept(HashSet<string> identities) { List<string> list = new List<string>(); foreach (string key in _records.Keys) { if (!identities.Contains(key)) { list.Add(key); } } foreach (string item in list) { _records.Remove(item); } } internal void Flush() { //IL_0022: 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_002c: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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) Dictionary<Vector2s, List<string>> dictionary = new Dictionary<Vector2s, List<string>>(); foreach (PlacementDecision value5 in _records.Values) { Vector2s zone = ZoneSystem.GetZone(value5.Anchor); if (!dictionary.TryGetValue(zone, out var value)) { value = (dictionary[zone] = new List<string>()); } value.Add(Serialize(value5)); } HashSet<Vector2s> hashSet = new HashSet<Vector2s>(dictionary.Keys); if (_values != null) { hashSet.UnionWith(_values.Keys); } foreach (Vector2s item in hashSet) { if (_controllers.TryGetValue(item, out var _)) { List<string> value3; List<string> list2 = (dictionary.TryGetValue(item, out value3) ? value3 : new List<string>()); list2.Sort(StringComparer.Ordinal); string value4 = string.Join("\n", list2); _values[item] = value4; Write(_controllers, item, value4); } } } private static void Sync() { if (_session != ZNet.instance) { _session = ZNet.instance; _values = null; } } internal static void RecheckBeforeSave() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) Sync(); if (_values == null || (Object)(object)ZoneSystem.instance == (Object)null || ZDOMan.instance == null) { return; } IReadOnlyDictionary<Vector2s, ZDO> controllers = PieceIndex.ZoneControllers(ZoneSystem.instance); int num = 0; foreach (KeyValuePair<Vector2s, string> value in _values) { if (Write(controllers, value.Key, value.Value)) { num++; } } MerchantSignpostsPlugin.Log.LogInfo((object)$"[MerchantSignposts] placement save recheck: zones checked={_values.Count}, zones rewritten={num}"); } private static bool Write(IReadOnlyDictionary<Vector2s, ZDO> controllers, Vector2s zone, string value) { //IL_0001: 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) if (!controllers.TryGetValue(zone, out var value2) || ZDOMan.instance.GetZDO(value2.m_uid) != value2 || value2.GetString("MerchantSignposts.placementRecords.v1", "") == value) { return false; } value2.SetOwner(ZDOMan.GetSessionID()); value2.Set("MerchantSignposts.placementRecords.v1", value); return true; } private static string Serialize(PlacementDecision record) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) string[] obj = new string[9] { Encode(record.Identity), Encode(record.LocationPrefab), Encode(record.Fingerprint), null, null, null, null, null, null }; int outcome = (int)record.Outcome; obj[3] = outcome.ToString(CultureInfo.InvariantCulture); obj[4] = (record.Found ? "1" : "0"); obj[5] = (record.Retired ? "1" : "0"); obj[6] = Point(record.Target); obj[7] = Point(record.Anchor); obj[8] = Point(record.Position); return string.Join("|", obj); } private static bool TryParse(string line, out PlacementDecision record) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) record = null; string[] array = line.Split(new char[1] { '|' }); if (array.Length != 9 || !int.TryParse(array[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !TryPoint(array[6], out var point) || !TryPoint(array[7], out var point2) || !TryPoint(array[8], out var point3) || result < 0 || result > 3) { return false; } try { record = new PlacementDecision { Identity = Decode(array[0]), LocationPrefab = Decode(array[1]), Fingerprint = Decode(array[2]), Outcome = (ResolvedOutcome)result, Found = (array[4] == "1"), Retired = (array[5] == "1"), Target = point, Anchor = point2, Position = point3 }; return record.Identity.Length != 0; } catch (FormatException) { return false; } } private static string Point(Vector3 value) { return string.Join(",", value.x.ToString("R", CultureInfo.InvariantCulture), value.y.ToString("R", CultureInfo.InvariantCulture), value.z.ToString("R", CultureInfo.InvariantCulture)); } private static bool TryPoint(string value, out Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) point = default(Vector3); string[] array = value.Split(new char[1] { ',' }); if (array.Length != 3 || !float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { return false; } point = new Vector3(result, result2, result3); return true; } private static string Encode(string value) { return Convert.ToBase64String(Encoding.UTF8.GetBytes(value ?? "")); } private static string Decode(string value) { return Encoding.UTF8.GetString(Convert.FromBase64String(value)); } } internal static class PlanExport { internal const string DirectoryVariable = "MERCHANT_SIGNPOSTS_EXPORT_DIR"; internal const string QuitVariable = "MERCHANT_SIGNPOSTS_EXPORT_QUIT"; private const float CellSize = 8f; private static readonly HashSet<string> DisposableSeeds = new HashSet<string>(StringComparer.Ordinal) { "FhZHKQBUUB", "UIFZxRKyGb", "0pzVMReYkJ", "5Egn5b4FJt" }; private static readonly string[] BiomeLegend = new string[10] { "None", "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands", "DeepNorth", "Ocean" }; private static string _directory; private static bool _quit; private static bool _finished; internal static void Initialize() { _directory = Environment.GetEnvironmentVariable("MERCHANT_SIGNPOSTS_EXPORT_DIR"); string environmentVariable = Environment.GetEnvironmentVariable("MERCHANT_SIGNPOSTS_EXPORT_QUIT"); _quit = string.IsNullOrEmpty(environmentVariable) || environmentVariable == "1" || environmentVariable.Equals("true", StringComparison.OrdinalIgnoreCase); _finished = false; } internal static void Update() { if (_directory == null || _finished || (Object)(object)ZNet.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null || WorldGenerator.instance == null) { return; } if (!ZNet.instance.IsServer()) { _finished = true; MerchantSignpostsPlugin.Log.LogWarning((object)"Signpost export ignored: not a server"); } else if (ZoneSystem.instance.LocationsGenerated) { _finished = true; bool flag = Export(); if (_quit) { Application.Quit((!flag) ? 1 : 0); } } } private static bool Export() { //IL_017c: 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_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0233: 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_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) string text = null; try { World world = ZNet.instance.GetWorld(); if (world == null || !DisposableSeeds.Contains(world.m_seedName) || string.Equals(world.m_name, "Brews", StringComparison.OrdinalIgnoreCase) || world.m_seed != WorldGenerator.instance.GetSeed()) { MerchantSignpostsPlugin.Log.LogWarning((object)"Signpost export refused: not an admitted disposable test world"); return false; } if (string.IsNullOrWhiteSpace(_directory) || string.IsNullOrEmpty(world.m_name) || world.m_name != Path.GetFileName(world.m_name) || world.m_name == "." || world.m_name == "..") { throw new InvalidOperationException("Invalid export path"); } Stopwatch stopwatch = Stopwatch.StartNew(); SignpostPlan signpostPlan = SignpostPlan.Get(); if (signpostPlan == null) { throw new InvalidOperationException("Plan unavailable"); } ZoneSystem instance = ZoneSystem.instance; List<object> list = new List<object>(); List<SignpostPlan.Instance> list2 = new List<SignpostPlan.Instance>(signpostPlan.Instances); list2.Sort((SignpostPlan.Instance a, SignpostPlan.Instance b) => StringComparer.Ordinal.Compare(a.Id, b.Id)); foreach (SignpostPlan.Instance item in list2) { float num = item.Trail.Outer + MerchantSignpostsPlugin.SidewaysJitter.Value + item.Trail.Step * 0.25f; List<object> list3 = new List<object>(); foreach (KeyValuePair<Vector2s, LocationInstance> locationInstance in instance.m_locationInstances) { LocationInstance value = locationInstance.Value; if (value.m_location != null && !(InvariantNumbers.InstanceIdentity(value.m_location.m_prefabName, locationInstance.Key.x, locationInstance.Key.y) == item.Id)) { float num2 = ((value.m_location.m_prefabName == item.Prefab) ? item.SameMerchantKeepOut : (Math.Max(value.m_location.m_exteriorRadius, value.m_location.m_interiorRadius) + MerchantSignpostsPlugin.LocationMargin.Value)); double num3 = (double)value.m_position.x - (double)item.Position.x; double num4 = (double)value.m_position.z - (double)item.Position.z; if (!(num3 * num3 + num4 * num4 > (double)(num + num2) * (double)(num + num2))) { list3.Add(Object("prefab", value.m_location.m_prefabName, "position", Point(value.m_position), "radius", num2)); } } } list.Add(Object("id", item.Id, "prefab", item.Prefab, "label", item.Label, "position", Point(item.Position), "exteriorRadius", item.ExteriorRadius, "interiorRadius", item.InteriorRadius, "allowedBiomes", ((object)Unsafe.As<Biome, Biome>(ref item.Biomes)/*cast due to .constrained prefix*/).ToString(), "trail", Object("spokes", item.Trail.Spokes, "outer", item.Trail.Outer, "inner", item.Trail.Inner, "step", item.Trail.Step), "waterMargin", item.WaterMargin, "sameMerchantKeepOut", item.SameMerchantKeepOut, "radius", num, "raster", Raster(item.Position, num), "clearances", list3)); } List<object> list4 = new List<object>(); foreach (SignpostPlan.Planned item2 in signpostPlan.All) { Dictionary<string, object> dictionary = Candidate(item2); dictionary.Add("pointingTarget", Point(item2.PointingTarget)); list4.Add(dictionary); } List<object> list5 = new List<object>(); foreach (SignpostPlan.Rejected rejection in signpostPlan.Rejections) { Dictionary<string, object> dictionary2 = Candidate(rejection.Candidate); dictionary2.Add("reason", rejection.Reason); dictionary2["submerged"] = rejection.Submerged; list5.Add(dictionary2); } Dictionary<string, object> value2 = Object("schemaVersion", 1, "world", Object("name", world.m_name, "seed", world.m_seed, "seedName", world.m_seedName, "waterLevel", instance.m_waterLevel), "pluginVersion", "0.2.0", "settings", Settings(), "instances", list, "planned", list4, "rejected", list5); long elapsedMilliseconds = stopwatch.ElapsedMilliseconds; Directory.CreateDirectory(_directory); string text2 = Path.Combine(_directory, world.m_name + ".signposts.json"); text = text2 + ".tmp"; using (StreamWriter writer = new StreamWriter(text, append: false, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false))) { Write(writer, value2); } if (File.Exists(text2)) { File.Replace(text, text2, null); } else { File.Move(text, text2); } MerchantSignpostsPlugin.Log.LogInfo((object)($"Signpost export complete: schema=1 instances={list.Count} " + $"planned={list4.Count} rejected={list5.Count} captureMs={elapsedMilliseconds} totalMs={stopwatch.ElapsedMilliseconds}")); return true; } catch (Exception ex) { if (text != null) { try { File.Delete(text); } catch (Exception) { } } MerchantSignpostsPlugin.Log.LogError((object)("Signpost export failed: " + ex.GetType().Name)); return false; } } private static Dictionary<string, object> Candidate(SignpostPlan.Planned point) { //IL_004f: 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_00c4: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, object> dictionary = Object("instanceId", point.InstanceId, "spoke", point.Spoke, "index", point.Index, "position", Point(point.Position), "target", Point(point.Target), "height", point.Height, "biome", point.Biome, "submerged", false); if (point.OriginalRejection != null) { dictionary.Add("originalPosition", Point(point.OriginalPosition)); dictionary.Add("originalRejection", point.OriginalRejection); } return dictionary; } private static Dictionary<string, object> Settings() { return Object("WorldPlacement", MerchantSignpostsPlugin.WorldPlacement.Value, "Spokes", MerchantSignpostsPlugin.Spokes.Value, "OuterRadius", MerchantSignpostsPlugin.OuterRadius.Value, "InnerRadius", MerchantSignpostsPlugin.InnerRadius.Value, "Step", MerchantSignpostsPlugin.Step.Value, "SidewaysJitter", MerchantSignpostsPlugin.SidewaysJitter.Value, "LocationMargin", MerchantSignpostsPlugin.LocationMargin.Value, "SearchRadius", MerchantSignpostsPlugin.SearchRadius.Value, "MinimumSignDistance", MerchantSignpostsPlugin.MinimumSignDistance.Value, "SameMerchantKeepOut", MerchantSignpostsPlugin.SameMerchantKeepOut.Value, "SameMerchantKeepOuts", MerchantSignpostsPlugin.SameMerchantKeepOuts.Value, "WaterMargin", MerchantSignpostsPlugin.WaterMargin.Value, "WaterMargins", MerchantSignpostsPlugin.WaterMargins.Value, "Biomes", MerchantSignpostsPlugin.Biomes.Value, "Trails", MerchantSignpostsPlugin.Trails.Value, "MerchantTable", MerchantSignpostsPlugin.MerchantTable.Value); } private static Dictionary<string, object> Raster(Vector3 position, float radius) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) if (float.IsNaN(radius) || float.IsInfinity(radius) || radius <= 0f || radius > 16000f) { throw new InvalidOperationException("Invalid raster extent"); } double num = Math.Floor((position.x - radius) / 8f) * 8.0; double num2 = Math.Floor((position.z - radius) / 8f) * 8.0; int num3 = (int)Math.Ceiling(Math.Max((double)(position.x + radius) - num, (double)(position.z + radius) - num2) / 8.0); if ((long)num3 * (long)num3 > 4000000) { throw new InvalidOperationException("Raster too large"); } int[] array = new int[num3 * num3]; int[] array2 = new int[array.Length]; Vector3 val = default(Vector3); for (int i = 0; i < num3; i++) { for (int j = 0; j < num3; j++) { ((Vector3)(ref val))..ctor((float)(num + ((double)j + 0.5) * 8.0), 0f, (float)(num2 + ((double)i + 0.5) * 8.0)); int num4 = i * num3 + j; array[num4] = checked((int)Math.Round((double)SignpostPlan.TerrainHeight(WorldGenerator.instance, ZoneSystem.instance, val) * 10.0, MidpointRounding.AwayFromZero)); array2[num4] = Math.Max(0, Array.IndexOf<string>(BiomeLegend, ((object)WorldGenerator.instance.GetBiome(val.x, val.z, 0.02f, false)/*cast due to .constrained prefix*/).ToString())); } } return Object("origin", new double[2] { num, num2 }, "cellSize", 8f, "size", num3, "layout", "row-major from the south-west corner; values are cell centres", "heightDecimetres", array, "biome", array2, "biomeLegend", BiomeLegend); } private static double[] Point(Vector3 point) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) return new double[3] { Round(point.x), Round(point.y), Round(point.z) }; } private static double Round(float value) { return Math.Round(value, 1, MidpointRounding.AwayFromZero); } private static Dictionary<string, object> Object(params object[] pairs) { Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.Ordinal); for (int i = 0; i < pairs.Length; i += 2) { dictionary.Add((string)pairs[i], pairs[i + 1]); } return dictionary; } private static void Write(TextWriter writer, object value) { if (value is string text) { writer.Write('"'); string text2 = text; foreach (char c in text2) { switch (c) { case '"': writer.Write("\\\""); continue; case '\\': writer.Write("\\\\"); continue; case '\n': writer.Write("\\n"); continue; case '\r': writer.Write("\\r"); co