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 LiveSeedMap v1.5.3
plugins/LiveSeedMap.dll
Decompiled 2 days 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.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LiveSeedMap")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.5.3.0")] [assembly: AssemblyInformationalVersion("1.5.3+a973e3a1dffdbcab6bfd2b2ac1932f1d87dbe731")] [assembly: AssemblyProduct("LiveSeedMap")] [assembly: AssemblyTitle("LiveSeedMap")] [assembly: AssemblyVersion("1.5.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LiveSeedMap { public struct PieceRow { public int Prefab; public int Creator; public float X; public float Y; public float Z; public float QX; public float QY; public float QZ; public float QW; public bool Same(PieceRow other) { if (other.Prefab == Prefab && other.Creator == Creator && other.X == X && other.Y == Y && other.Z == Z && other.QX == QX && other.QY == QY && other.QZ == QZ) { return other.QW == QW; } return false; } } public readonly struct PieceKey : IEquatable<PieceKey> { public readonly int Prefab; public readonly int X; public readonly int Y; public readonly int Z; public PieceKey(int prefab, float x, float y, float z) { Prefab = prefab; X = (int)Math.Round(x * 100f); Y = (int)Math.Round(y * 100f); Z = (int)Math.Round(z * 100f); } public bool Equals(PieceKey other) { if (Prefab == other.Prefab && X == other.X && Y == other.Y) { return Z == other.Z; } return false; } public override bool Equals(object obj) { if (obj is PieceKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (((((Prefab * 397) ^ X) * 397) ^ Y) * 397) ^ Z; } } public sealed class FrozenBuildings { public string World; public int Version; public string[] Prefabs; public long[] Creators; public PieceRow[] Rows; } public sealed class BuildingBook { public const float MissingSeconds = 10f; private readonly List<string> prefabs = new List<string>(); private readonly Dictionary<string, int> prefabIndex = new Dictionary<string, int>(StringComparer.Ordinal); private readonly List<long> creators = new List<long>(); private readonly Dictionary<long, int> creatorIndex = new Dictionary<long, int>(); private readonly Dictionary<PieceKey, PieceRow> pieces = new Dictionary<PieceKey, PieceRow>(); private readonly Dictionary<PieceKey, float> missing = new Dictionary<PieceKey, float>(); private bool changed; public string World { get; } public int Count => pieces.Count; public int Version { get; private set; } public BuildingBook(string world) { World = world; Version = Environment.TickCount; } public int PrefabIndex(string prefab) { if (prefabIndex.TryGetValue(prefab, out var value)) { return value; } prefabs.Add(prefab); return prefabIndex[prefab] = prefabs.Count - 1; } private int CreatorIndex(long creator) { if (creatorIndex.TryGetValue(creator, out var value)) { return value; } creators.Add(creator); return creatorIndex[creator] = creators.Count - 1; } public PieceKey Observe(string prefab, float x, float y, float z, float qx, float qy, float qz, float qw, long creator) { PieceRow pieceRow = new PieceRow { Prefab = PrefabIndex(prefab), Creator = CreatorIndex(creator), X = x, Y = y, Z = z, QX = qx, QY = qy, QZ = qz, QW = qw }; PieceKey pieceKey = new PieceKey(pieceRow.Prefab, x, y, z); missing.Remove(pieceKey); if (pieces.TryGetValue(pieceKey, out var value) && value.Same(pieceRow)) { return pieceKey; } pieces[pieceKey] = pieceRow; Changed(); return pieceKey; } public bool Remove(string prefab, float x, float y, float z) { if (!prefabIndex.TryGetValue(prefab, out var value)) { return false; } PieceKey key = new PieceKey(value, x, y, z); missing.Remove(key); if (!pieces.Remove(key)) { return false; } Changed(); return true; } public bool Sweep(HashSet<PieceKey> present, Func<float, float, bool> loaded, float elapsed, bool complete) { List<PieceKey> list = new List<PieceKey>(); foreach (KeyValuePair<PieceKey, PieceRow> piece in pieces) { if (present.Contains(piece.Key)) { continue; } if (complete) { list.Add(piece.Key); continue; } if (!loaded(piece.Value.X, piece.Value.Z)) { missing.Remove(piece.Key); continue; } missing.TryGetValue(piece.Key, out var value); value += elapsed; if (value >= 10f) { list.Add(piece.Key); } else { missing[piece.Key] = value; } } foreach (PieceKey item in list) { pieces.Remove(item); missing.Remove(item); } if (list.Count > 0) { Changed(); } return list.Count > 0; } public bool TakeChanged() { bool result = changed; changed = false; return result; } private void Changed() { changed = true; Version++; } public FrozenBuildings Freeze() { return new FrozenBuildings { World = World, Version = Version, Prefabs = prefabs.ToArray(), Creators = creators.ToArray(), Rows = pieces.Values.ToArray() }; } public static void WritePieces(JsonWriter w, PieceRow[] rows) { w.WriteStartArray(); for (int i = 0; i < rows.Length; i++) { PieceRow pieceRow = rows[i]; w.WriteStartArray(); w.WriteValue(pieceRow.Prefab); w.WriteValue(pieceRow.Creator); w.WriteValue(Math.Round(pieceRow.X, 2)); w.WriteValue(Math.Round(pieceRow.Y, 2)); w.WriteValue(Math.Round(pieceRow.Z, 2)); w.WriteValue(Math.Round(pieceRow.QX, 4)); w.WriteValue(Math.Round(pieceRow.QY, 4)); w.WriteValue(Math.Round(pieceRow.QZ, 4)); w.WriteValue(Math.Round(pieceRow.QW, 4)); w.WriteEndArray(); } w.WriteEndArray(); } public static string ToFile(FrozenBuildings frozen) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("world"); ((JsonWriter)val).WriteValue(frozen.World); ((JsonWriter)val).WritePropertyName("prefabs"); ((JsonWriter)val).WriteStartArray(); string[] array = frozen.Prefabs; foreach (string text in array) { ((JsonWriter)val).WriteValue(text); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WritePropertyName("creators"); ((JsonWriter)val).WriteStartArray(); long[] array2 = frozen.Creators; foreach (long num in array2) { ((JsonWriter)val).WriteValue(num.ToString(CultureInfo.InvariantCulture)); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WritePropertyName("pieces"); WritePieces((JsonWriter)(object)val, frozen.Rows); ((JsonWriter)val).WriteEndObject(); } finally { ((IDisposable)val)?.Dispose(); } return stringWriter.ToString(); } public static BuildingBook Load(string text, string world) { BuildingBook buildingBook = new BuildingBook(world); if (string.IsNullOrEmpty(text)) { return buildingBook; } try { JObject val = JObject.Parse(text); if ((string)val["world"] != world) { goto IL_006f; } JToken obj = val["prefabs"]; JArray val2 = (JArray)(object)((obj is JArray) ? obj : null); if (val2 == null) { goto IL_006f; } JToken obj2 = val["creators"]; JArray val3 = (JArray)(object)((obj2 is JArray) ? obj2 : null); if (val3 == null) { goto IL_006f; } JToken obj3 = val["pieces"]; JArray val4 = (JArray)(object)((obj3 is JArray) ? obj3 : null); if (val4 == null) { goto IL_006f; } string[] array = ((IEnumerable<JToken>)val2).Select((JToken n) => (string)n).ToArray(); long result; long[] array2 = ((IEnumerable<JToken>)val3).Select((JToken i) => (!long.TryParse((string)i, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) ? 0 : result).ToArray(); foreach (JArray item in ((IEnumerable)val4).OfType<JArray>()) { if (((JContainer)item).Count >= 9) { int num = (int)item[0]; int num2 = (int)item[1]; if (num >= 0 && num < array.Length && !string.IsNullOrEmpty(array[num]) && num2 >= 0 && num2 < array2.Length) { buildingBook.Observe(array[num], (float)item[2], (float)item[3], (float)item[4], (float)item[5], (float)item[6], (float)item[7], (float)item[8], array2[num2]); } } } goto end_IL_0012; IL_006f: return buildingBook; end_IL_0012:; } catch (Exception ex) when (ex is JsonException || ex is FormatException || ex is InvalidCastException || ex is OverflowException) { return new BuildingBook(world); } buildingBook.changed = false; return buildingBook; } } public static class Buildings { private const float ScanEvery = 3f; private const float SaveEvery = 30f; private static readonly FieldInfo ObjectsField = AccessTools.Field(typeof(ZDOMan), "m_objectsByID"); private static BuildingBook book; private static long worldUid; private static ZDOMan hooked; private static ZNetScene piecesOf; private static readonly Dictionary<int, string> pieceNames = new Dictionary<int, string>(); private static readonly HashSet<int> crops = new HashSet<int>(); private static readonly Dictionary<string, string> types = new Dictionary<string, string>(StringComparer.Ordinal); private static readonly HashSet<PieceKey> present = new HashSet<PieceKey>(); private static float nextScan; private static float nextSave; private static bool unsaved; private static volatile FrozenBuildings frozen; private static volatile string[] frozenTypes; private static volatile string self; private static string cachedJson; private static int cachedVersion; private static readonly object cacheGate = new object(); private static ManualLogSource log; public static int? Version => book?.Version; public static void Tick(float now, ManualLogSource logger) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) log = logger; World val = ((!Object.op_Implicit((Object)(object)ZNet.instance)) ? ((World)null) : ((World)Capture.WorldField.GetValue(null))); ZDOMan instance = ZDOMan.instance; if (val == null || instance == null || !Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)ZoneSystem.instance)) { Leave(); return; } if (book == null || val.m_uid != worldUid) { Join(val.m_uid); } if (hooked != instance) { if (hooked != null) { ZDOMan obj = hooked; obj.m_onZDODestroyed = (Action<ZDO>)Delegate.Remove(obj.m_onZDODestroyed, new Action<ZDO>(Destroyed)); } instance.m_onZDODestroyed = (Action<ZDO>)Delegate.Combine(instance.m_onZDODestroyed, new Action<ZDO>(Destroyed)); hooked = instance; } if (now >= nextScan) { nextScan = now + 3f; Scan(instance); } if (book.TakeChanged()) { Publish(); unsaved = true; } if (unsaved && now >= nextSave) { Save(); nextSave = now + 30f; } } public static void Flush() { Save(wait: true); } private static void Join(long uid) { Leave(); worldUid = uid; string world = uid.ToString(CultureInfo.InvariantCulture); string text = null; try { if (File.Exists(FileOf(world))) { text = File.ReadAllText(FileOf(world)); } } catch (Exception ex) { ManualLogSource obj = log; if (obj != null) { obj.LogWarning((object)("Could not read the saved buildings: " + ex.Message)); } } book = BuildingBook.Load(text, world); Publish(); nextScan = 0f; } private static void Leave() { if (book != null) { Save(); if (hooked != null) { ZDOMan obj = hooked; obj.m_onZDODestroyed = (Action<ZDO>)Delegate.Remove(obj.m_onZDODestroyed, new Action<ZDO>(Destroyed)); } hooked = null; book = null; frozen = null; frozenTypes = null; } } private static string FileOf(string world) { return Path.Combine(Path.Combine(Paths.ConfigPath, "LiveSeedMap"), "buildings-" + world + ".json"); } private static void Publish() { FrozenBuildings frozenBuildings = book.Freeze(); string[] array = new string[frozenBuildings.Prefabs.Length]; for (int i = 0; i < array.Length; i++) { array[i] = TypeOf(frozenBuildings.Prefabs[i]); } Player localPlayer = Player.m_localPlayer; self = (Object.op_Implicit((Object)(object)localPlayer) ? localPlayer.GetPlayerID().ToString(CultureInfo.InvariantCulture) : null); frozenTypes = array; frozen = frozenBuildings; } private static void Save(bool wait = false) { if (book == null || !unsaved) { return; } unsaved = false; FrozenBuildings copy = book.Freeze(); if (wait) { Write(); return; } ThreadPool.QueueUserWorkItem(delegate { lock (cacheGate) { Write(); } }); void Write() { try { string text = FileOf(copy.World); Directory.CreateDirectory(Path.GetDirectoryName(text)); string text2 = text + ".tmp"; File.WriteAllText(text2, BuildingBook.ToFile(copy)); if (File.Exists(text)) { File.Delete(text); } File.Move(text2, text); } catch (Exception ex) { ManualLogSource obj = log; if (obj != null) { obj.LogWarning((object)("Could not save the buildings: " + ex.Message)); } } } } private static Dictionary<int, string> PieceNames() { if ((Object)(object)piecesOf == (Object)(object)ZNetScene.instance) { return pieceNames; } pieceNames.Clear(); crops.Clear(); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab.GetComponent<Piece>())) { continue; } pieceNames[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = ((Object)prefab).name; Plant component = prefab.GetComponent<Plant>(); if ((Object)(object)component == (Object)null) { continue; } GameObject[] grownPrefabs = component.m_grownPrefabs; foreach (GameObject val in grownPrefabs) { if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.GetComponent<Pickable>())) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val).name); pieceNames[stableHashCode] = ((Object)val).name; crops.Add(stableHashCode); } } } piecesOf = ZNetScene.instance; return pieceNames; } private static void Scan(ZDOMan zdos) { //IL_0117: 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_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_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_00ac: 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_00ba: 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) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) if (!(ObjectsField?.GetValue(zdos) is Dictionary<ZDOID, ZDO> dictionary)) { return; } Dictionary<int, string> dictionary2 = PieceNames(); present.Clear(); foreach (ZDO value2 in dictionary.Values) { if (value2 != null && dictionary2.TryGetValue(value2.GetPrefab(), out var value)) { long num = value2.GetLong(ZDOVars.s_creator, 0L); if (num != 0L || crops.Contains(value2.GetPrefab())) { Vector3 position = value2.GetPosition(); Quaternion rotation = value2.GetRotation(); present.Add(book.Observe(value, position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w, num)); } } } Player player = Player.m_localPlayer; float reach = Capture.Reach(ZNet.instance.GetSyncedSimulationDistance(), ZoneSystem.instance.m_zoneSize) * 0.9f; Vector3 here = (Object.op_Implicit((Object)(object)player) ? ((Component)player).transform.position : Vector3.zero); book.Sweep(present, (float x, float z) => Object.op_Implicit((Object)(object)player) && (x - here.x) * (x - here.x) + (z - here.z) * (z - here.z) <= reach * reach, 3f, ZNet.instance.IsServer()); } private static void Destroyed(ZDO zdo) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_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_0039: Unknown result type (might be due to invalid IL or missing references) try { if (book != null && zdo != null && PieceNames().TryGetValue(zdo.GetPrefab(), out var value)) { Vector3 position = zdo.GetPosition(); book.Remove(value, position.x, position.y, position.z); } } catch (Exception ex) { ManualLogSource obj = log; if (obj != null) { obj.LogError((object)ex); } } } public static string Json() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown FrozenBuildings frozenBuildings = frozen; string[] array = frozenTypes; if (frozenBuildings == null || array == null) { return null; } lock (cacheGate) { if (cachedJson != null && cachedVersion == frozenBuildings.Version) { return cachedJson; } StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("v"); ((JsonWriter)val).WriteValue(1); ((JsonWriter)val).WritePropertyName("world"); ((JsonWriter)val).WriteValue(frozenBuildings.World); ((JsonWriter)val).WritePropertyName("version"); ((JsonWriter)val).WriteValue(frozenBuildings.Version); ((JsonWriter)val).WritePropertyName("self"); if (self == null) { ((JsonWriter)val).WriteNull(); } else { ((JsonWriter)val).WriteValue(self); } ((JsonWriter)val).WritePropertyName("creators"); ((JsonWriter)val).WriteStartArray(); long[] creators = frozenBuildings.Creators; foreach (long num in creators) { ((JsonWriter)val).WriteValue(num.ToString(CultureInfo.InvariantCulture)); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WritePropertyName("prefabs"); ((JsonWriter)val).WriteStartArray(); for (int j = 0; j < frozenBuildings.Prefabs.Length; j++) { if (j < array.Length && array[j] != null) { ((JsonWriter)val).WriteRawValue(array[j]); continue; } ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("id"); ((JsonWriter)val).WriteValue(frozenBuildings.Prefabs[j]); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WritePropertyName("pieces"); BuildingBook.WritePieces((JsonWriter)(object)val, frozenBuildings.Rows); ((JsonWriter)val).WriteEndObject(); } finally { ((IDisposable)val)?.Dispose(); } cachedJson = stringWriter.ToString(); cachedVersion = frozenBuildings.Version; return cachedJson; } } private static string TypeOf(string name) { if (types.TryGetValue(name, out var value)) { return value; } GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(name) : null); string text = null; if (Object.op_Implicit((Object)(object)val)) { try { text = Describe(name, val); } catch (Exception ex) { ManualLogSource obj = log; if (obj != null) { obj.LogWarning((object)("Could not read the shape of " + name + ": " + ex.Message)); } } } if (text != null || !Object.op_Implicit((Object)(object)val)) { types[name] = text; } return text; } private static string Describe(string name, GameObject prefab) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0197: 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_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: 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_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) Piece component = prefab.GetComponent<Piece>(); WearNTear component2 = prefab.GetComponent<WearNTear>(); StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("id"); ((JsonWriter)val).WriteValue(name); ((JsonWriter)val).WritePropertyName("name"); ((JsonWriter)val).WriteValue((Object.op_Implicit((Object)(object)component) && Localization.instance != null) ? Localization.instance.Localize(component.m_name) : name); string text = GroupOf(name, prefab, component); ((JsonWriter)val).WritePropertyName("group"); ((JsonWriter)val).WriteValue(text); ((JsonWriter)val).WritePropertyName("material"); if (Object.op_Implicit((Object)(object)component2)) { ((JsonWriter)val).WriteValue(((object)Unsafe.As<MaterialType, MaterialType>(ref component2.m_materialType)/*cast due to .constrained prefix*/).ToString()); } else { ((JsonWriter)val).WriteNull(); } if (BaseArea(prefab, out var area)) { ((JsonWriter)val).WritePropertyName("base"); ((JsonWriter)val).WriteStartArray(); ((JsonWriter)val).WriteValue(Math.Round(area.x, 2)); ((JsonWriter)val).WriteValue(Math.Round(area.y, 2)); ((JsonWriter)val).WriteValue(Math.Round(area.z, 2)); ((JsonWriter)val).WriteEndArray(); } ((JsonWriter)val).WritePropertyName("boxes"); ((JsonWriter)val).WriteStartArray(); Matrix4x4 worldToLocalMatrix = prefab.transform.worldToLocalMatrix; int num = 0; float num2 = SeenExtent(prefab, worldToLocalMatrix); Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren) { if (!Object.op_Implicit((Object)(object)val2) || (val2.isTrigger && text != "plant") || !BoundsOf(val2, out var bounds)) { continue; } Matrix4x4 m = worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix; if (!(num2 > 0f) || !(GroundExtent(bounds, m) > num2 + 2f)) { num++; ((JsonWriter)val).WriteStartArray(); for (int j = 0; j < 8; j++) { Vector3 val3 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1)))); Vector3 val4 = ((Matrix4x4)(ref m)).MultiplyPoint3x4(val3); ((JsonWriter)val).WriteValue(Math.Round(val4.x, 3)); ((JsonWriter)val).WriteValue(Math.Round(val4.y, 3)); ((JsonWriter)val).WriteValue(Math.Round(val4.z, 3)); } MeshCollider val5 = (MeshCollider)(object)((val2 is MeshCollider) ? val2 : null); if (val5 != null && SlopeOf(val5.sharedMesh, m, out var rise)) { ((JsonWriter)val).WriteValue(Math.Round(rise.x, 3)); ((JsonWriter)val).WriteValue(Math.Round(rise.y, 3)); } ((JsonWriter)val).WriteEndArray(); } } if (num == 0 && text == "plant") { ((JsonWriter)val).WriteStartArray(); for (int k = 0; k < 8; k++) { ((JsonWriter)val).WriteValue(((k & 1) == 0) ? (-0.25) : 0.25); ((JsonWriter)val).WriteValue(((k & 2) == 0) ? 0.0 : 0.5); ((JsonWriter)val).WriteValue(((k & 4) == 0) ? (-0.25) : 0.25); } ((JsonWriter)val).WriteEndArray(); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WriteEndObject(); } finally { ((IDisposable)val)?.Dispose(); } return stringWriter.ToString(); } private static bool SlopeOf(Mesh mesh, Matrix4x4 m, out Vector2 rise) { //IL_0001: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_006a: 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_006f: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) rise = default(Vector2); if (!Object.op_Implicit((Object)(object)mesh) || !mesh.isReadable) { return false; } Vector3[] vertices = mesh.vertices; if (vertices.Length < 4) { return false; } Vector3[] array = (Vector3[])(object)new Vector3[vertices.Length]; float num = float.MaxValue; float num2 = float.MaxValue; float num3 = float.MinValue; float num4 = float.MinValue; for (int i = 0; i < vertices.Length; i++) { Vector3 val = (array[i] = ((Matrix4x4)(ref m)).MultiplyPoint3x4(vertices[i])); num = Mathf.Min(num, val.x); num3 = Mathf.Max(num3, val.x); num2 = Mathf.Min(num2, val.z); num4 = Mathf.Max(num4, val.z); } float[] array2 = new float[64]; for (int j = 0; j < array2.Length; j++) { array2[j] = float.NaN; } float num5 = Mathf.Max(0.001f, num3 - num) / 8f; float num6 = Mathf.Max(0.001f, num4 - num2) / 8f; Vector3[] array3 = array; foreach (Vector3 val2 in array3) { int num7 = Mathf.Min(7, (int)((val2.x - num) / num5)) + 8 * Mathf.Min(7, (int)((val2.z - num2) / num6)); if (float.IsNaN(array2[num7]) || val2.y > array2[num7]) { array2[num7] = val2.y; } } double num8 = 0.0; double num9 = 0.0; double num10 = 0.0; double num11 = 0.0; double num12 = 0.0; double num13 = 0.0; double num14 = 0.0; double num15 = 0.0; double num16 = 0.0; for (int l = 0; l < array2.Length; l++) { if (!float.IsNaN(array2[l])) { double num17 = (double)num + ((double)(l % 8) + 0.5) * (double)num5; double num18 = (double)num2 + ((double)(l / 8) + 0.5) * (double)num6; double num19 = array2[l]; num8 += 1.0; num9 += num17; num10 += num18; num11 += num19; num12 += num17 * num17; num13 += num18 * num18; num14 += num17 * num18; num15 += num17 * num19; num16 += num18 * num19; } } if (num8 < 4.0) { return false; } double num20 = num12 - num9 * num9 / num8; double num21 = num13 - num10 * num10 / num8; double num22 = num14 - num9 * num10 / num8; double num23 = num15 - num9 * num11 / num8; double num24 = num16 - num10 * num11 / num8; double num25 = num20 * num21 - num22 * num22; if (Math.Abs(num25) < 1E-09) { return false; } double num26 = (num23 * num21 - num24 * num22) / num25; double num27 = (num24 * num20 - num23 * num22) / num25; if (num26 * num26 + num27 * num27 < 0.04) { return false; } rise = new Vector2((float)num26, (float)num27); return true; } private static bool BaseArea(GameObject prefab, out Vector3 area) { //IL_0001: 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_0012: 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_0038: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_0095: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) area = default(Vector3); Matrix4x4 worldToLocalMatrix = prefab.transform.worldToLocalMatrix; EffectArea[] componentsInChildren = prefab.GetComponentsInChildren<EffectArea>(true); foreach (EffectArea val in componentsInChildren) { if (!Object.op_Implicit((Object)(object)val) || (val.m_type & 4) == 0) { continue; } Collider[] components = ((Component)val).GetComponents<Collider>(); foreach (Collider val2 in components) { if (Object.op_Implicit((Object)(object)val2) && BoundsOf(val2, out var bounds)) { Vector3 lossyScale = ((Component)val).transform.lossyScale; SphereCollider val3 = (SphereCollider)(object)((val2 is SphereCollider) ? val2 : null); float num = ((val3 != null) ? (val3.radius * Mathf.Max(new float[3] { Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z) })) : Mathf.Max(((Bounds)(ref bounds)).extents.x * Mathf.Abs(lossyScale.x), ((Bounds)(ref bounds)).extents.z * Mathf.Abs(lossyScale.z))); if (!(num <= area.z)) { Vector3 val4 = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(((Component)val).transform.TransformPoint(((Bounds)(ref bounds)).center)); area = new Vector3(val4.x, val4.z, num); } } } if (!(area.z <= 0f)) { continue; } ManualLogSource obj = log; if (obj != null) { obj.LogWarning((object)(((Object)prefab).name + ": its PlayerBase area has no collider the map can read (" + string.Join(", ", from c in ((Component)val).GetComponents<Component>() select (!Object.op_Implicit((Object)(object)c)) ? "null" : ((object)c).GetType().Name) + ")")); } } return area.z > 0f; } private static float SeenExtent(GameObject prefab, Matrix4x4 toRoot) { //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_0031: 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_0042: Unknown result type (might be due to invalid IL or missing references) float num = 0f; Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (val is MeshRenderer || val is SkinnedMeshRenderer) { Bounds bounds = val.bounds; num = Mathf.Max(num, GroundExtent(new Bounds(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).size), toRoot)); } } return num; } private static float GroundExtent(Bounds bounds, Matrix4x4 m) { //IL_0024: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0092: Unknown result type (might be due to invalid IL or missing references) float num = float.MaxValue; float num2 = float.MinValue; float num3 = float.MaxValue; float num4 = float.MinValue; for (int i = 0; i < 8; i++) { Vector3 val = ((Matrix4x4)(ref m)).MultiplyPoint3x4(((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((i & 1) != 0) ? 1 : (-1)), (float)(((i & 2) != 0) ? 1 : (-1)), (float)(((i & 4) != 0) ? 1 : (-1))))); num = Mathf.Min(num, val.x); num2 = Mathf.Max(num2, val.x); num3 = Mathf.Min(num3, val.z); num4 = Mathf.Max(num4, val.z); } return Mathf.Max(num2 - num, num4 - num3); } private static bool BoundsOf(Collider collider, out Bounds bounds) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //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_0084: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00ec: 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_00f2: 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) BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null); if (val == null) { MeshCollider val2 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null); if (val2 == null) { SphereCollider val3 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null); if (val3 != null) { bounds = new Bounds(val3.center, Vector3.one * val3.radius * 2f); return true; } CapsuleCollider val4 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null); if (val4 != null) { Vector3 val5 = Vector3.one * val4.radius * 2f; ((Vector3)(ref val5))[Mathf.Clamp(val4.direction, 0, 2)] = Mathf.Max(val4.height, val4.radius * 2f); bounds = new Bounds(val4.center, val5); return true; } } else if (Object.op_Implicit((Object)(object)val2.sharedMesh)) { bounds = val2.sharedMesh.bounds; return true; } bounds = default(Bounds); return false; } bounds = new Bounds(val.center, val.size); return true; } private static string GroupOf(string name, GameObject prefab, Piece piece) { //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Invalid comparison between Unknown and I4 //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Invalid comparison between Unknown and I4 string text = name.ToLowerInvariant(); if (Object.op_Implicit((Object)(object)prefab.GetComponent<TeleportWorld>())) { return "portal"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<Ship>())) { return "ship"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<PrivateArea>())) { return "ward"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<CraftingStation>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<StationExtension>())) { return "station"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<Smelter>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<Fermenter>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<CookingStation>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<Beehive>())) { return "production"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<Bed>())) { return "bed"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<Container>())) { return "chest"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<Plant>()) || (!Object.op_Implicit((Object)(object)piece) && Object.op_Implicit((Object)(object)prefab.GetComponent<Pickable>()))) { return "plant"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<Door>())) { return "door"; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<Fireplace>())) { if (!text.Contains("torch") && !text.Contains("sconce") && !text.Contains("brazier") && !text.Contains("lantern") && !text.Contains("candle")) { return "fire"; } return "light"; } if (text.Contains("roof")) { return "roof"; } if (text.Contains("stake") || text.Contains("sharp") || text.Contains("palisade") || text.Contains("spike")) { return "defense"; } if (Object.op_Implicit((Object)(object)piece)) { PieceCategory category = piece.m_category; if (piece.m_comfort > 0 || (int)category == 4 || ((int)category == 0 && !Object.op_Implicit((Object)(object)prefab.GetComponent<WearNTear>()))) { return "furniture"; } if ((int)category == 1) { return "production"; } } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<WearNTear>())) { return "furniture"; } return "structure"; } } public sealed class WorldInfo { public string Name; public string Seed; public int Hash; public int Generation; public long Uid; } public sealed class SelfInfo { public string Name; public float X; public float Y; public float Z; public float Heading; public bool Dead; } public sealed class PlayerSpot { public string Name; public float X; public float Z; } public sealed class Creature { public string Prefab; public string Name; public int Level; public float Health; public float MaxHealth; public float X; public float Z; public bool Tamed; public bool Boss; public bool Hostile; } public sealed class Pin { public int Type; public string Name; public float X; public float Z; public bool Checked; public bool Shared; } public sealed class Icon { public string Prefab; public float X; public float Z; } public sealed class ShipInfo { public string Prefab; public string Name; public string Sail; public float X; public float Z; public float Heading; public float Speed; } public sealed class WindInfo { public float Angle; public float Intensity; } public sealed class Snapshot { public WorldInfo World; public SelfInfo Self; public float Reach; public PlayerSpot[] Players = new PlayerSpot[0]; public Creature[] Creatures = new Creature[0]; public Pin[] Pins = new Pin[0]; public Icon[] Icons = new Icon[0]; public bool PinWrites; public string FocusKey; public ShipInfo Ship; public WindInfo Wind; public int? ExploredVersion; public int? PortalsVersion; public int? BuildingsVersion; public bool Tracking; public TrackInfo Track; } public static class Capture { internal static readonly FieldInfo WorldField = AccessTools.Field(typeof(ZNet), "m_world"); internal static readonly FieldInfo PinsField = AccessTools.Field(typeof(Minimap), "m_pins"); public static Snapshot Take() { //IL_0026: 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_00c9: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) Snapshot snapshot = new Snapshot(); World val = ((!Object.op_Implicit((Object)(object)ZNet.instance)) ? ((World)null) : ((World)WorldField.GetValue(null))); if (val == null || !Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return snapshot; } snapshot.World = new WorldInfo { Name = val.m_name, Seed = val.m_seedName, Hash = val.m_seed, Uid = val.m_uid, Generation = val.m_worldGenVersion }; snapshot.Reach = Reach(ZNet.instance.GetSyncedSimulationDistance(), ZoneSystem.instance.m_zoneSize); Player player = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)player)) { Vector3 position = ((Component)player).transform.position; SelfInfo obj = new SelfInfo { Name = player.GetPlayerName(), X = position.x, Y = position.y, Z = position.z }; Quaternion rotation = ((Component)player).transform.rotation; obj.Heading = ((Quaternion)(ref rotation)).eulerAngles.y; obj.Dead = ((Character)player).IsDead(); snapshot.Self = obj; snapshot.Ship = ShipOf(player); } snapshot.Wind = Wind(); snapshot.ExploredVersion = Explored.Version(Time.unscaledTime); snapshot.PortalsVersion = Portals.Version; snapshot.BuildingsVersion = Buildings.Version; snapshot.Track = Track.Current; List<PlayerInfo> list = new List<PlayerInfo>(); ZNet.instance.GetOtherPublicPlayers(list); snapshot.Players = list.Select((PlayerInfo info) => new PlayerSpot { Name = CensorShittyWords.FilterUGC(info.m_name, (UGCType)2, ((ZDOID)(ref info.m_characterID)).UserID), X = info.m_position.x, Z = info.m_position.z }).ToArray(); snapshot.Creatures = (from character in Character.GetAllCharacters() where Object.op_Implicit((Object)(object)character) && !character.IsPlayer() && !character.IsDead() select character).Select(delegate(Character character) { //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_0053: 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) Vector3 position2 = ((Component)character).transform.position; return new Creature { Prefab = Utils.GetPrefabName(((Component)character).gameObject), Name = character.m_name, Level = character.GetLevel(), Health = character.GetHealth(), MaxHealth = character.GetMaxHealth(), X = position2.x, Z = position2.z, Tamed = character.IsTamed(), Boss = character.IsBoss(), Hostile = (Object.op_Implicit((Object)(object)player) && BaseAI.IsEnemy(character, (Character)(object)player) && character.GetBaseAI() is MonsterAI) }; }).ToArray(); if (Object.op_Implicit((Object)(object)Minimap.instance)) { snapshot.Pins = (from pin in (List<PinData>)PinsField.GetValue(Minimap.instance) where pin.m_save select new Pin { Type = (int)pin.m_type, Name = pin.m_name, X = pin.m_pos.x, Z = pin.m_pos.z, Checked = pin.m_checked, Shared = (pin.m_ownerID != 0) }).ToArray(); } Dictionary<Vector3, string> dictionary = new Dictionary<Vector3, string>(); ZoneSystem.instance.GetLocationIcons(dictionary); snapshot.Icons = dictionary.Select((KeyValuePair<Vector3, string> icon) => new Icon { Prefab = icon.Value, X = icon.Key.x, Z = icon.Key.z }).ToArray(); return snapshot; } private static ShipInfo ShipOf(Player player) { //IL_0060: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_00a7: 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) Ship val = player.GetControlledShip(); if (!Object.op_Implicit((Object)(object)val)) { val = Ship.GetLocalShip(); } if (!Object.op_Implicit((Object)(object)val)) { return null; } Transform transform = ((Component)val).transform; Piece component = ((Component)val).GetComponent<Piece>(); ShipInfo obj = new ShipInfo { Prefab = Utils.GetPrefabName(((Component)val).gameObject), Name = (Object.op_Implicit((Object)(object)component) ? component.m_name : ""), X = transform.position.x, Z = transform.position.z }; Quaternion rotation = transform.rotation; obj.Heading = ((Quaternion)(ref rotation)).eulerAngles.y; obj.Speed = val.GetSpeed(); obj.Sail = ((object)val.GetSpeedSetting()/*cast due to .constrained prefix*/).ToString().ToLowerInvariant(); return obj; } private static WindInfo Wind() { //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_001d: Unknown result type (might be due to invalid IL or missing references) EnvMan instance = EnvMan.instance; if (!Object.op_Implicit((Object)(object)instance)) { return null; } Vector3 windDir = instance.GetWindDir(); float num = Mathf.Atan2(windDir.x, windDir.z) * 57.29578f; return new WindInfo { Angle = ((num < 0f) ? (num + 360f) : num), Intensity = Mathf.Clamp01(instance.GetWindIntensity()) }; } public static float Reach(SimulationDistance distance, float zone) { if (!((SimulationDistance)(ref distance)).IsClassic) { return Mathf.Max(0f, ((float)((SimulationDistance)(ref distance)).NearSimulationDistance + 0.5f) * zone - zone * Mathf.Sqrt(2f)); } return (float)((SimulationDistance)(ref distance)).NearSimulationDistance * zone; } } public static class Explored { private static readonly FieldInfo ExploredField = AccessTools.Field(typeof(Minimap), "m_explored"); private static readonly FieldInfo OthersField = AccessTools.Field(typeof(Minimap), "m_exploredOthers"); private const float HashEvery = 2f; private static int[] words; private static Minimap owner; private static float next; private static int? version; public static int? Version(float now, bool force = false) { Minimap instance = Minimap.instance; if (!Object.op_Implicit((Object)(object)instance)) { owner = null; version = null; return null; } if (!force && (Object)(object)owner == (Object)(object)instance && version.HasValue && now < next) { return version; } owner = instance; next = now + 2f; BitArray bitArray = ExploredField?.GetValue(instance) as BitArray; BitArray bitArray2 = OthersField?.GetValue(instance) as BitArray; version = ((bitArray == null || bitArray2 == null) ? ((int?)null) : new int?(Hash(bitArray) * 31 + Hash(bitArray2))); return version; } public static ExploredPlanes Read(float now) { Minimap instance = Minimap.instance; if (!Object.op_Implicit((Object)(object)instance)) { return null; } BitArray bitArray = ExploredField?.GetValue(instance) as BitArray; BitArray bitArray2 = OthersField?.GetValue(instance) as BitArray; if (bitArray == null || bitArray2 == null) { return null; } return new ExploredPlanes { Size = instance.m_textureSize, Explored = Pack(bitArray), Others = Pack(bitArray2), Version = Version(now, force: true).GetValueOrDefault() }; } private static byte[] Pack(BitArray bits) { byte[] array = new byte[(bits.Length + 7) / 8]; bits.CopyTo(array, 0); return array; } private static int Hash(BitArray bits) { int num = (bits.Length + 31) / 32; if (words == null || words.Length != num) { words = new int[num]; } bits.CopyTo(words, 0); int num2 = -2128831035; int[] array = words; foreach (int num3 in array) { num2 = (num2 ^ num3) * 16777619; } return num2; } } public sealed class FocusTarget { public string Kind; public string Prefab; } public static class Focus { private static readonly FieldInfo SelectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe"); private static readonly FieldInfo AvailableRecipesField = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); private static readonly FieldInfo ContainerGridField = AccessTools.Field(typeof(InventoryGui), "m_containerGrid"); public static bool Typing() { if ((!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Minimap.InTextInput()) { return Menu.IsVisible(); } return true; } public static FocusTarget Find() { //IL_002b: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return null; } InventoryGui instance = InventoryGui.instance; if (Object.op_Implicit((Object)(object)instance) && InventoryGui.IsVisible()) { Vector3 pointerPosition = ZInput.pointerPosition; Vector2i val = default(Vector2i); ((Vector2i)(ref val))..ctor((int)pointerPosition.x, (int)pointerPosition.y); bool flag = ZInput.IsExclusiveGamepadActive(); InventoryGrid[] array = (InventoryGrid[])(object)new InventoryGrid[2] { instance.m_playerGrid, (InventoryGrid)(instance.IsContainerOpen() ? /*isinst with value type is only supported in some contexts*/: null) }; foreach (InventoryGrid val2 in array) { if (Object.op_Implicit((Object)(object)val2)) { string text = ItemPrefab((!flag) ? val2.GetItem(val) : ((Object.op_Implicit((Object)(object)val2.m_uiGroup) && val2.m_uiGroup.IsActive) ? val2.GetGamepadSelectedItem() : null)); if (text != null) { return new FocusTarget { Kind = "item", Prefab = text }; } } } Recipe val3 = (flag ? null : HoveredRecipe(instance, pointerPosition)) ?? RecipeOf(SelectedRecipeField?.GetValue(instance)); if (Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val3.m_item)) { return new FocusTarget { Kind = "item", Prefab = ((Object)((Component)val3.m_item).gameObject).name }; } return null; } Character hoverCreature = localPlayer.GetHoverCreature(); if (Object.op_Implicit((Object)(object)hoverCreature) && !hoverCreature.IsPlayer()) { return new FocusTarget { Kind = "creature", Prefab = Utils.GetPrefabName(((Component)hoverCreature).gameObject) }; } GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject(); ItemDrop val4 = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<ItemDrop>() : null); if (Object.op_Implicit((Object)(object)val4)) { return new FocusTarget { Kind = "item", Prefab = Utils.GetPrefabName(((Component)val4).gameObject) }; } return null; } private static Recipe HoveredRecipe(InventoryGui gui, Vector3 pointer) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (!(AvailableRecipesField?.GetValue(gui) is IList list)) { return null; } foreach (object item in list) { object obj = Property(item, "InterfaceElement"); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (Object.op_Implicit((Object)(object)val) && val.activeInHierarchy) { Transform transform = val.transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (Object.op_Implicit((Object)(object)val2) && RectTransformUtility.RectangleContainsScreenPoint(val2, Vector2.op_Implicit(pointer))) { return RecipeOf(item); } } } return null; } private static Recipe RecipeOf(object pair) { if (pair != null) { object obj = Property(pair, "Recipe"); return (Recipe)((obj is Recipe) ? obj : null); } return null; } private static object Property(object row, string name) { return row?.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(row); } private static string ItemPrefab(ItemData item) { if (item == null) { return null; } if (Object.op_Implicit((Object)(object)item.m_dropPrefab)) { return ((Object)item.m_dropPrefab).name; } GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ((IEnumerable<GameObject>)ObjectDB.instance.m_items).FirstOrDefault((Func<GameObject, bool>)delegate(GameObject go) { if (Object.op_Implicit((Object)(object)go)) { ItemDrop component = go.GetComponent<ItemDrop>(); if (component != null) { return component.m_itemData.m_shared.m_name == item.m_shared.m_name; } } return false; }) : null); if (!Object.op_Implicit((Object)(object)val)) { return null; } return ((Object)val).name; } } public static class Json { public const int Protocol = 1; public static string Write(Snapshot s, float range) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("v"); ((JsonWriter)val).WriteValue(1); Field((JsonWriter)(object)val, "mod", "1.5.3"); ((JsonWriter)val).WritePropertyName("world"); if (s.World == null) { ((JsonWriter)val).WriteNull(); } else { ((JsonWriter)val).WriteStartObject(); Field((JsonWriter)(object)val, "name", s.World.Name); Field((JsonWriter)(object)val, "seed", s.World.Seed); ((JsonWriter)val).WritePropertyName("hash"); ((JsonWriter)val).WriteValue(s.World.Hash); Field((JsonWriter)(object)val, "uid", s.World.Uid.ToString(CultureInfo.InvariantCulture)); ((JsonWriter)val).WritePropertyName("gen"); ((JsonWriter)val).WriteValue(s.World.Generation); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WritePropertyName("reach"); ((JsonWriter)val).WriteValue(Round(s.Reach)); ((JsonWriter)val).WritePropertyName("self"); if (s.Self == null) { ((JsonWriter)val).WriteNull(); } else { ((JsonWriter)val).WriteStartObject(); Field((JsonWriter)(object)val, "name", s.Self.Name); Number((JsonWriter)(object)val, "x", s.Self.X); Number((JsonWriter)(object)val, "y", s.Self.Y); Number((JsonWriter)(object)val, "z", s.Self.Z); Number((JsonWriter)(object)val, "heading", s.Self.Heading); ((JsonWriter)val).WritePropertyName("dead"); ((JsonWriter)val).WriteValue(s.Self.Dead); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WritePropertyName("players"); ((JsonWriter)val).WriteStartArray(); PlayerSpot[] players = s.Players; foreach (PlayerSpot playerSpot in players) { ((JsonWriter)val).WriteStartObject(); Field((JsonWriter)(object)val, "name", playerSpot.Name); Number((JsonWriter)(object)val, "x", playerSpot.X); Number((JsonWriter)(object)val, "z", playerSpot.Z); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WritePropertyName("creatures"); ((JsonWriter)val).WriteStartArray(); Creature[] creatures = s.Creatures; foreach (Creature creature in creatures) { if (s.Self != null && Within(creature.X - s.Self.X, creature.Z - s.Self.Z, range)) { ((JsonWriter)val).WriteStartObject(); Field((JsonWriter)(object)val, "prefab", creature.Prefab); Field((JsonWriter)(object)val, "name", creature.Name); ((JsonWriter)val).WritePropertyName("level"); ((JsonWriter)val).WriteValue(creature.Level); Number((JsonWriter)(object)val, "hp", creature.Health); Number((JsonWriter)(object)val, "max", creature.MaxHealth); Number((JsonWriter)(object)val, "x", creature.X); Number((JsonWriter)(object)val, "z", creature.Z); ((JsonWriter)val).WritePropertyName("tamed"); ((JsonWriter)val).WriteValue(creature.Tamed); ((JsonWriter)val).WritePropertyName("boss"); ((JsonWriter)val).WriteValue(creature.Boss); ((JsonWriter)val).WritePropertyName("hostile"); ((JsonWriter)val).WriteValue(creature.Hostile); ((JsonWriter)val).WriteEndObject(); } } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WritePropertyName("pins"); ((JsonWriter)val).WriteStartArray(); Pin[] pins = s.Pins; foreach (Pin pin in pins) { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("type"); ((JsonWriter)val).WriteValue(pin.Type); Field((JsonWriter)(object)val, "name", pin.Name); Number((JsonWriter)(object)val, "x", pin.X); Number((JsonWriter)(object)val, "z", pin.Z); ((JsonWriter)val).WritePropertyName("checked"); ((JsonWriter)val).WriteValue(pin.Checked); ((JsonWriter)val).WritePropertyName("shared"); ((JsonWriter)val).WriteValue(pin.Shared); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WritePropertyName("pinWrites"); ((JsonWriter)val).WriteValue(s.PinWrites); ((JsonWriter)val).WritePropertyName("focusKey"); if (s.FocusKey == null) { ((JsonWriter)val).WriteNull(); } else { ((JsonWriter)val).WriteValue(s.FocusKey); } ((JsonWriter)val).WritePropertyName("ship"); if (s.Ship == null) { ((JsonWriter)val).WriteNull(); } else { ((JsonWriter)val).WriteStartObject(); Field((JsonWriter)(object)val, "prefab", s.Ship.Prefab); Field((JsonWriter)(object)val, "name", s.Ship.Name); Number((JsonWriter)(object)val, "x", s.Ship.X); Number((JsonWriter)(object)val, "z", s.Ship.Z); Number((JsonWriter)(object)val, "heading", s.Ship.Heading); Number((JsonWriter)(object)val, "speed", s.Ship.Speed); Field((JsonWriter)(object)val, "sail", s.Ship.Sail); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WritePropertyName("wind"); if (s.Wind == null) { ((JsonWriter)val).WriteNull(); } else { ((JsonWriter)val).WriteStartObject(); Number((JsonWriter)(object)val, "angle", s.Wind.Angle); ((JsonWriter)val).WritePropertyName("intensity"); ((JsonWriter)val).WriteValue(Math.Round(s.Wind.Intensity, 2)); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WritePropertyName("exploredVersion"); if (s.ExploredVersion.HasValue) { ((JsonWriter)val).WriteValue(s.ExploredVersion.Value); } else { ((JsonWriter)val).WriteNull(); } ((JsonWriter)val).WritePropertyName("portalsVersion"); if (s.PortalsVersion.HasValue) { ((JsonWriter)val).WriteValue(s.PortalsVersion.Value); } else { ((JsonWriter)val).WriteNull(); } ((JsonWriter)val).WritePropertyName("buildingsVersion"); if (s.BuildingsVersion.HasValue) { ((JsonWriter)val).WriteValue(s.BuildingsVersion.Value); } else { ((JsonWriter)val).WriteNull(); } ((JsonWriter)val).WritePropertyName("tracking"); ((JsonWriter)val).WriteValue(s.Tracking); ((JsonWriter)val).WritePropertyName("track"); if (s.Track == null) { ((JsonWriter)val).WriteNull(); } else { ((JsonWriter)val).WriteStartObject(); Number((JsonWriter)(object)val, "x", s.Track.X); Number((JsonWriter)(object)val, "z", s.Track.Z); Field((JsonWriter)(object)val, "label", s.Track.Label); Number((JsonWriter)(object)val, "clearWithin", s.Track.ClearWithin); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WritePropertyName("icons"); ((JsonWriter)val).WriteStartArray(); Icon[] icons = s.Icons; foreach (Icon icon in icons) { ((JsonWriter)val).WriteStartObject(); Field((JsonWriter)(object)val, "prefab", icon.Prefab); Number((JsonWriter)(object)val, "x", icon.X); Number((JsonWriter)(object)val, "z", icon.Z); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WriteEndObject(); } finally { ((IDisposable)val)?.Dispose(); } return stringWriter.ToString(); } public static string Focus(FocusTarget target) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("v"); ((JsonWriter)val).WriteValue(1); Field((JsonWriter)(object)val, "type", "focus"); Field((JsonWriter)(object)val, "kind", target.Kind); Field((JsonWriter)(object)val, "prefab", target.Prefab); ((JsonWriter)val).WriteEndObject(); } finally { ((IDisposable)val)?.Dispose(); } return stringWriter.ToString(); } public static string Explored(ExploredPlanes planes) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("v"); ((JsonWriter)val).WriteValue(1); ((JsonWriter)val).WritePropertyName("size"); ((JsonWriter)val).WriteValue(planes.Size); ((JsonWriter)val).WritePropertyName("version"); ((JsonWriter)val).WriteValue(planes.Version); Field((JsonWriter)(object)val, "explored", Convert.ToBase64String(planes.Explored)); Field((JsonWriter)(object)val, "others", Convert.ToBase64String(planes.Others)); ((JsonWriter)val).WriteEndObject(); } finally { ((IDisposable)val)?.Dispose(); } return stringWriter.ToString(); } public static string Error(string code, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).WriteStartObject(); Field((JsonWriter)(object)val, "error", code); Field((JsonWriter)(object)val, "message", message); ((JsonWriter)val).WriteEndObject(); } finally { ((IDisposable)val)?.Dispose(); } return stringWriter.ToString(); } public unsafe static string KeyLabel(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_002d: 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_0063: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0) { return null; } List<string> list = new List<string>(); foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if ((int)modifier != 0 && modifier != ((KeyboardShortcut)(ref shortcut)).MainKey) { list.Add(((object)(*(KeyCode*)(&modifier))/*cast due to .constrained prefix*/).ToString()); } } list.Add(((object)((KeyboardShortcut)(ref shortcut)).MainKey/*cast due to .constrained prefix*/).ToString()); return string.Join(" + ", list); } private static bool Within(float dx, float dz, float range) { return dx * dx + dz * dz <= range * range; } private static double Round(float value) { return Math.Round(value, 1); } private static void Field(JsonWriter w, string name, string value) { w.WritePropertyName(name); w.WriteValue(value); } private static void Number(JsonWriter w, string name, float value) { w.WritePropertyName(name); w.WriteValue(Round(value)); } } public sealed class LiveServer { private sealed class Request { public string Method; public string Path; public float Range = float.PositiveInfinity; public readonly Dictionary<string, string> Headers = new Dictionary<string, string>(); public int Length = -1; public byte[] Body = new byte[0]; public bool ReadBody(Stream stream) { if (!Headers.TryGetValue("content-length", out var value)) { return true; } if (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out Length) || Length > 65536) { return false; } byte[] array = new byte[Length]; int num; for (int i = 0; i < Length; i += num) { num = stream.Read(array, i, Length - i); if (num == 0) { return false; } } Body = ((Length <= 4096) ? array : null); return true; } public static Request Read(Stream stream) { List<byte> list = new List<byte>(); byte[] array = new byte[1]; while (!EndsWithBlankLine(list)) { if (list.Count >= 16384 || stream.Read(array, 0, 1) == 0) { return null; } list.Add(array[0]); } string[] array2 = Encoding.ASCII.GetString(list.ToArray()).Split(new string[1] { "\r\n" }, StringSplitOptions.None); string[] array3 = array2[0].Split(' '); if (array3.Length < 2) { return null; } string[] array4 = array3[1].Split(new char[1] { '?' }, 2); Request request = new Request { Method = array3[0], Path = array4[0] }; if (array4.Length == 2) { string[] array5 = array4[1].Split('&'); for (int i = 0; i < array5.Length; i++) { string[] array6 = array5[i].Split(new char[1] { '=' }, 2); if (array6.Length == 2 && array6[0] == "range" && float.TryParse(Uri.UnescapeDataString(array6[1]), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result >= 0f) { request.Range = result; } } } foreach (string item in array2.Skip(1)) { int num = item.IndexOf(':'); if (num > 0) { request.Headers[item.Substring(0, num).Trim().ToLowerInvariant()] = item.Substring(num + 1).Trim(); } } return request; } private static bool EndsWithBlankLine(List<byte> b) { if (b.Count >= 4 && b[b.Count - 4] == 13 && b[b.Count - 3] == 10 && b[b.Count - 2] == 13) { return b[b.Count - 1] == 10; } return false; } } private const int MaxHeaderBytes = 16384; private const int MaxBodyBytes = 4096; private const int MaxDiscardBytes = 65536; private const int WriteTimeoutMs = 5000; private readonly int port; private readonly HashSet<string> origins; private readonly ManualLogSource log; private readonly object gate = new object(); private TcpListener listener; private volatile bool running; private Snapshot latest = new Snapshot(); private long revision; private string focus; private long focusRevision; private int clients; private readonly ConcurrentQueue<PinCommand> commands = new ConcurrentQueue<PinCommand>(); private readonly ConcurrentQueue<ExploredRequest> exploredRequests = new ConcurrentQueue<ExploredRequest>(); private readonly ConcurrentQueue<NearbyRequest> nearbyRequests = new ConcurrentQueue<NearbyRequest>(); private readonly ConcurrentQueue<TrackCommand> trackCommands = new ConcurrentQueue<TrackCommand>(); public Func<bool> PinWritesAllowed = () => false; public Func<string> PortalsJson = () => (string)null; public Func<string> BuildingsJson = () => (string)null; public Func<bool> TrackingAllowed = () => false; public bool HasClients => Volatile.Read(in clients) > 0; public LiveServer(int port, IEnumerable<string> origins, ManualLogSource log) { this.port = port; this.origins = new HashSet<string>(from o in origins select o.Trim().TrimEnd('/') into o where o.Length > 0 select o, StringComparer.OrdinalIgnoreCase); this.log = log; } public void Start() { listener = new TcpListener(IPAddress.Loopback, port); listener.Start(); running = true; Thread thread = new Thread(Accept); thread.IsBackground = true; thread.Name = "LiveSeedMap accept"; thread.Start(); log.LogInfo((object)$"Listening on http://127.0.0.1:{port}"); } public void Stop() { running = false; listener?.Stop(); lock (gate) { Monitor.PulseAll(gate); } } public void Publish(Snapshot snapshot) { lock (gate) { latest = snapshot; revision++; Monitor.PulseAll(gate); } } public void PublishFocus(FocusTarget target) { string text = Json.Focus(target); lock (gate) { focus = text; focusRevision++; Monitor.PulseAll(gate); } } public bool TryTakeCommand(out PinCommand command) { return commands.TryDequeue(out command); } public bool TryTakeExplored(out ExploredRequest request) { return exploredRequests.TryDequeue(out request); } public bool TryTakeNearby(out NearbyRequest request) { return nearbyRequests.TryDequeue(out request); } public bool TryTakeTrack(out TrackCommand command) { return trackCommands.TryDequeue(out command); } private void Accept() { while (running) { TcpClient client; try { client = listener.AcceptTcpClient(); } catch (SocketException) { if (running) { continue; } break; } catch (ObjectDisposedException) { break; } Thread thread = new Thread((ThreadStart)delegate { Serve(client); }); thread.IsBackground = true; thread.Name = "LiveSeedMap client"; thread.Start(); } } private void Serve(TcpClient client) { using (client) { try { client.NoDelay = true; NetworkStream stream = client.GetStream(); Request request = Request.Read(stream); if (request != null && request.ReadBody(stream)) { Respond(stream, request); } } catch (IOException) { } catch (SocketException) { } catch (ObjectDisposedException) { } } } private void Respond(Stream stream, Request request) { request.Headers.TryGetValue("origin", out var value); request.Headers.TryGetValue("host", out var value2); if ((!(value2 == $"127.0.0.1:{port}") && !(value2 == $"localhost:{port}")) || (value != null && !origins.Contains(value))) { Write(stream, "403 Forbidden", null, "text/plain", "Forbidden"); return; } if (request.Method == "OPTIONS") { Write(stream, "204 No Content", value, null, null, "Access-Control-Allow-Methods: GET, POST, DELETE\r\nAccess-Control-Allow-Headers: Content-Type\r\nAccess-Control-Allow-Private-Network: true\r\nAccess-Control-Max-Age: 600\r\n"); return; } if ((request.Path == "/v1/pins" && (request.Method == "POST" || request.Method == "DELETE")) || (request.Path == "/v1/pins/checked" && request.Method == "POST")) { PinWrite(stream, request, value); return; } if (request.Path == "/v1/track" && (request.Method == "POST" || request.Method == "DELETE")) { TrackWrite(stream, request, value); return; } float range = request.Range; if (request.Method == "GET" && request.Path == "/v1/state") { Interlocked.Increment(ref clients); try { long seen; lock (gate) { seen = revision; } Snapshot snapshot = Next(ref seen); if (snapshot != null) { Write(stream, "200 OK", value, "application/json", Json.Write(snapshot, range)); } return; } finally { Interlocked.Decrement(ref clients); } } if (request.Method == "GET" && request.Path == "/v1/stream") { Stream(stream, value, range); } else if (request.Method == "GET" && request.Path == "/v1/explored") { ExploredRead(stream, value); } else if (request.Method == "GET" && request.Path == "/v1/nearby") { NearbyRead(stream, value, range); } else if (request.Method == "GET" && request.Path == "/v1/buildings") { string text = BuildingsJson(); if (text == null) { Write(stream, "409 Conflict", value, "application/json", Json.Error("no-world", "No world is loaded.")); } else { Write(stream, "200 OK", value, "application/json", text); } } else if (request.Method == "GET" && request.Path == "/v1/portals") { string text2 = PortalsJson(); if (text2 == null) { Write(stream, "409 Conflict", value, "application/json", Json.Error("no-world", "No world is loaded.")); } else { Write(stream, "200 OK", value, "application/json", text2); } } else { Write(stream, "404 Not Found", value, "text/plain", "Not found"); } } private void Stream(Stream stream, string origin, float range) { string s = "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\nCache-Control: no-store\r\nConnection: keep-alive\r\n" + Cors(origin) + "\r\n"; byte[] bytes = Encoding.ASCII.GetBytes(s); stream.Write(bytes, 0, bytes.Length); stream.Flush(); Interlocked.Increment(ref clients); try { long num; long num2; lock (gate) { num = revision; num2 = focusRevision; } while (true) { Snapshot s2 = null; string text; lock (gate) { while (running && revision == num && focusRevision == num2) { Monitor.Wait(gate); } if (!running) { break; } if (focusRevision != num2) { num2 = focusRevision; text = "event: focus\ndata: " + focus + "\n\n"; } else { num = revision; s2 = latest; text = null; } } byte[] bytes2 = Encoding.UTF8.GetBytes(text ?? ("data: " + Json.Write(s2, range) + "\n\n")); stream.Write(bytes2, 0, bytes2.Length); stream.Flush(); } } finally { Interlocked.Decrement(ref clients); } } private void PinWrite(Stream stream, Request request, string origin) { if (!PinWritesAllowed()) { Write(stream, "403 Forbidden", origin, "application/json", Json.Error("pin-writes-off", "Pin writes are off in this game. Set AllowPinWrites = true in BepInEx/config/wiki.thevalheim.liveseedmap.cfg to let the seed map change your pins.")); return; } request.Headers.TryGetValue("content-type", out var value); if (value == null || !value.Split(';')[0].Trim().Equals("application/json", StringComparison.OrdinalIgnoreCase)) { Write(stream, "415 Unsupported Media Type", origin, "application/json", Json.Error("unsupported-media", "Send the pin as application/json.")); return; } if (request.Length < 0) { Write(stream, "411 Length Required", origin, "application/json", Json.Error("length-required", "Content-Length is required.")); return; } if (request.Body == null) { Write(stream, "413 Payload Too Large", origin, "application/json", Json.Error("too-large", "A pin is at most " + 4096 + " bytes.")); return; } string body = Encoding.UTF8.GetString(request.Body); PinCommand.Kind kind = ((request.Method == "DELETE") ? PinCommand.Kind.Remove : ((request.Path == "/v1/pins/checked") ? PinCommand.Kind.Check : PinCommand.Kind.Add)); string problem; PinArgs pinArgs = PinArgs.Parse(body, out problem); if (pinArgs == null || (kind == PinCommand.Kind.Check && !pinArgs.Checked.HasValue)) { Write(stream, "400 Bad Request", origin, "application/json", problem ?? Json.Error("bad-request", "\"checked\" must be true or false.")); return; } PinCommand pinCommand = new PinCommand { Action = kind, Body = body }; commands.Enqueue(pinCommand); if (!pinCommand.Done.Wait(5000)) { pinCommand.Abandoned = true; Write(stream, "503 Service Unavailable", origin, "application/json", Json.Error("busy", "The game did not answer in time; try again.")); } else { string status = ((pinCommand.Status == 200) ? "200 OK" : ((pinCommand.Status == 400) ? "400 Bad Request" : ((pinCommand.Status == 409) ? "409 Conflict" : "500 Internal Server Error"))); Write(stream, status, origin, "application/json", pinCommand.Response); } } private void TrackWrite(Stream stream, Request request, string origin) { if (!TrackingAllowed()) { Write(stream, "403 Forbidden", origin, "application/json", Json.Error("tracking-off", "Tracking is off in this game. Set AllowTracking = true in BepInEx/config/wiki.thevalheim.liveseedmap.cfg to let the seed map show a target in the game.")); return; } TrackCommand trackCommand = new TrackCommand(); if (request.Method == "POST") { request.Headers.TryGetValue("content-type", out var value); if (value == null || !value.Split(';')[0].Trim().Equals("application/json", StringComparison.OrdinalIgnoreCase)) { Write(stream, "415 Unsupported Media Type", origin, "application/json", Json.Error("unsupported-media", "Send the target as application/json.")); return; } if (request.Length < 0) { Write(stream, "411 Length Required", origin, "application/json", Json.Error("length-required", "Content-Length is required.")); return; } if (request.Body == null) { Write(stream, "413 Payload Too Large", origin, "application/json", Json.Error("too-large", "A target is at most " + 4096 + " bytes.")); return; } trackCommand.Target = TrackArgs.Parse(Encoding.UTF8.GetString(request.Body), out var problem); if (trackCommand.Target == null) { Write(stream, "400 Bad Request", origin, "application/json", problem); return; } } trackCommands.Enqueue(trackCommand); if (!trackCommand.Done.Wait(5000)) { trackCommand.Abandoned = true; Write(stream, "503 Service Unavailable", origin, "application/json", Json.Error("busy", "The game did not answer in time; try again.")); } else { string status = ((trackCommand.Status == 200) ? "200 OK" : ((trackCommand.Status == 409) ? "409 Conflict" : "500 Internal Server Error")); Write(stream, status, origin, "application/json", trackCommand.Response); } } private void ExploredRead(Stream stream, string origin) { ExploredRequest exploredRequest = new ExploredRequest(); exploredRequests.Enqueue(exploredRequest); if (!exploredRequest.Done.Wait(5000)) { exploredRequest.Abandoned = true; Write(stream, "503 Service Unavailable", origin, "application/json", Json.Error("busy", "The game did not answer in time; try again.")); } else if (exploredRequest.Planes == null) { Write(stream, "409 Conflict", origin, "application/json", Json.Error("no-world", "No world is loaded.")); } else { Write(stream, "200 OK", origin, "application/json", Json.Explored(exploredRequest.Planes)); } } private void NearbyRead(Stream stream, string origin, float range) { NearbyRequest nearbyRequest = new NearbyRequest { Range = range }; nearbyRequests.Enqueue(nearbyRequest); if (!nearbyRequest.Done.Wait(5000)) { nearbyRequest.Abandoned = true; Write(stream, "503 Service Unavailable", origin, "application/json", Json.Error("busy", "The game did not answer in time; try again.")); } else if (nearbyRequest.Json == null) { Write(stream, "409 Conflict", origin, "application/json", Json.Error("no-player", "No character is in a world.")); } else { Write(stream, "200 OK", origin, "application/json", nearbyRequest.Json); } } private Snapshot Next(ref long seen) { lock (gate) { while (running && revision == seen) { Monitor.Wait(gate); } if (!running) { return null; } seen = revision; return latest; } } private static string Cors(string origin) { if (origin != null) { return "Access-Control-Allow-Origin: " + origin + "\r\nVary: Origin\r\n"; } return ""; } private static void Write(Stream stream, string status, string origin, string type, string body, string extra = "") { byte[] array = ((body == null) ? new byte[0] : Encoding.UTF8.GetBytes(body)); string s = "HTTP/1.1 " + status + "\r\n" + Cors(origin) + extra + ((type == null) ? "" : ("Content-Type: " + type + "; charset=utf-8\r\nCache-Control: no-store\r\n")) + $"Content-Length: {array.Length}\r\nConnection: close\r\n\r\n"; byte[] bytes = Encoding.ASCII.GetBytes(s); stream.Write(bytes, 0, bytes.Length); stream.Write(array, 0, array.Length); stream.Flush(); } } public sealed class ExploredPlanes { public int Size; public int Version; public byte[] Explored; public byte[] Others; } public sealed class ExploredRequest { public ExploredPlanes Planes; public volatile bool Abandoned; public readonly ManualResetEventSlim Done = new ManualResetEventSlim(initialState: false); } public sealed class NearbyRequest { public float Range; public string Json; public volatile bool Abandoned; public readonly ManualResetEventSlim Done = new ManualResetEventSlim(initialState: false); } public static class Nearby { private static readonly FieldInfo InstancesField = AccessTools.Field(typeof(ZNetScene), "m_instances"); public const float MaxRange = 400f; public static string Read(float range) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; ZNetScene instance = ZNetScene.instance; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)instance) || !(InstancesField?.GetValue(instance) is Dictionary<ZDO, ZNetView> dictionary)) { return null; } float num = ((Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)ZoneSystem.instance)) ? Capture.Reach(ZNet.instance.GetSyncedSimulationDistance(), ZoneSystem.instance.m_zoneSize) : 400f); float num2 = Mathf.Min(float.IsInfinity(range) ? num : range, 400f); Vector3 position = ((Component)localPlayer).transform.position; List<(string, string, Vector3)> list = new List<(string, string, Vector3)>(); foreach (KeyValuePair<ZDO, ZNetView> item in dictionary) { ZNetView value = item.Value; if (!Object.op_Implicit((Object)(object)value) || item.Key == null) { continue; } Vector3 position2 = item.Key.GetPosition(); float num3 = position2.x - position.x; float num4 = position2.z - position.z; if (!(num3 * num3 + num4 * num4 > num2 * num2)) { string text = KindOf(((Component)value).gameObject); GameObject prefab = instance.GetPrefab(item.Key.GetPrefab()); if (text != null) { list.Add((Object.op_Implicit((Object)(object)prefab) ? ((Object)prefab).name : Utils.GetPrefabName(((Component)value).gameObject), text, position2)); } } } StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("v"); ((JsonWriter)val).WriteValue(1); ((JsonWriter)val).WritePropertyName("x"); ((JsonWriter)val).WriteValue(Math.Round(position.x, 1)); ((JsonWriter)val).WritePropertyName("z"); ((JsonWriter)val).WriteValue(Math.Round(position.z, 1)); ((JsonWriter)val).WritePropertyName("radius"); ((JsonWriter)val).WriteValue(Math.Round(num2, 1)); ((JsonWriter)val).WritePropertyName("objects"); ((JsonWriter)val).WriteStartArray(); foreach (var item2 in list.OrderBy<(string, string, Vector3), string>(((string Prefab, string Kind, Vector3 At) r) => r.Prefab, StringComparer.Ordinal)) { ((JsonWriter)val).WriteStartObject(); ((JsonWriter)val).WritePropertyName("prefab"); ((JsonWriter)val).WriteValue(item2.Item1); ((JsonWriter)val).WritePropertyName("kind"); ((JsonWriter)val).WriteValue(item2.Item2); ((JsonWriter)val).WritePropertyName("x"); ((JsonWriter)val).WriteValue(Math.Round(item2.Item3.x, 2)); ((JsonWriter)val).WritePropertyName("y"); ((JsonWriter)val).WriteValue(Math.Round(item2.Item3.y, 2)); ((JsonWriter)val).WritePropertyName("z"); ((JsonWriter)val).WriteValue(Math.Round(item2.Item3.z, 2)); ((JsonWriter)val).WriteEndObject(); } ((JsonWriter)val).WriteEndArray(); ((JsonWriter)val).WriteEndObject(); } finally { ((IDisposable)val)?.Dispose(); } return stringWriter.ToString(); } private static string KindOf(GameObject go) { if (Object.op_Implicit((Object)(object)go.GetComponent<Pickable>()) || Object.op_Implicit((Object)(object)go.GetComponent<PickableItem>())) { return "pickable"; } if (Object.op_Implicit((Object)(object)go.GetComponent<TreeBase>())) { return "tree"; } if (Object.op_Implicit((Object)(object)go.GetComponent<MineRock>()) || Object.op_Implicit((Object)(object)go.GetComponent<MineRock5>())) { return "rock"; } if (Object.op_Implicit((Object)(object)go.GetComponent<Destructible>())) { return "destructible"; } return null; } } public sealed class PinCommand { public enum Kind { Add, Remove, Check } public Kind Action; public string Body; public int Status = 500; public string Response = ""; public volatile bool Abandoned; public readonly ManualResetEventSlim Done = new ManualResetEventSlim(initialState: false); } public sealed class PinArgs { public static readonly int[] Placeable = new int[5] { 0, 1, 2, 3, 6 }; public const int MaxName = 64; public const float MaxCoordinate = 10500f; public int Type; public string Name; public float X; public float Z; public bool? Checked; public static PinArgs Parse(string body, out string problem) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Invalid comparison between Unknown and I4 //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Invalid comparison between Unknown and I4 //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Invalid comparison between Unknown and I4 //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Invalid comparison between Unknown and I4 problem = null; JObject val; try { val = JObject.Parse(body ?? ""); } catch (Exception) { problem = Json.Error("bad-request", "The body is not a JSON object."); return null; } if (val["type"] == null || (int)val["type"].Type != 6) { problem = Json.Error("bad-request", "\"type\" must be a whole number."); return null; } long num = Extensions.Value<long>((IEnumerable<JToken>)val["type"]); if (num < 0 || num > 64 || Array.IndexOf(Placeable, (int)num) < 0) { problem = Json.Error("pin-type", "Only fire, house, hammer, dot and portal pins (types 0, 1, 2, 3, 6) can be written."); return null; } string text = ""; JToken val2 = val["name"]; if (val2 != null && (int)val2.Type != 10) { if ((int)val2.Type != 8) { problem = Json.Error("bad-request", "\"name\" must be a string."); return null; } text = new string((from c in Extensions.Value<string>((IEnumerable<JToken>)val2) where !char.IsControl(c) select c).ToArray()); if (text.Length > 64) { problem = Json.Error("bad-request", $"\"name\" is longer than {64} characters."); return null; } } if (!Coordinate(val["x"], out var value) || !Coordinate(val["z"], out var value2)) { problem = Json.Error("bad-request", $"\"x\" and \"z\" must be numbers within {10500f} m of the world centre."); return null; } bool? flag = null; JToken val3 = val["checked"]; if (val3 != null && (int)val3.Type != 10) { if ((int)val3.Type != 9) { problem = Json.Error("bad-request", "\"checked\" must be true or false."); return null; } flag = Extensions.Value<bool>((IEnumerable<JToken>)val3); } return new PinArgs { Type = (int)num, Name = text, X = value, Z = value2, Checked = flag }; } private static bool Coordinate(JToken token, out float value) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 value = 0f; if (token == null || ((int)token.Type != 6 && (int)token.Type != 7)) { return false; } double num = Extensions.Value<double>((IEnumerable<JToken>)token); if (double.IsNaN(num) || double.IsInfinity(num) || Math.Abs(num) > 10500.0) { return false; } value = (float)num; return true; } } public static class PinWrites { public const float MatchRadius = 1f; private static readonly FieldInfo UpdateField = AccessTools.Field(typeof(Minimap), "m_pinUpdateRequired"); public static void Execute(PinCommand command) { try { Run(command); } catch (Exception ex) { command.Status = 500; command.Response = Json.Error("failed", ex.Message); } } private static void Run(PinCommand command) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Minimap.instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { command.Status = 409; command.Response = Json.Error("no-world", "Load a world first; the game has no map open."); return; } string problem; PinArgs args = PinArgs.Parse(command.Body, out problem); if (args == null) { command.Status = 400; command.Response = problem; return; } if (command.Action == PinCommand.Kind.Check && !args.Checked.HasValue) { command.Status = 400; command.Response = Json.Error("bad-request", "\"checked\" must be true or false."); return; } Minimap instance = Minimap.instance; Vector3 at = new Vector3(args.X, 0f, args.Z); List<PinData> list = ((List<PinData>)Capture.PinsField.GetValue(instance)).Where((PinData pin) => pin.m_save && pin.m_ownerID == 0L && (int)pin.m_type == args.Type && pin.m_name == args.Name && Utils.DistanceXZ(pin.m_pos, at) <= 1f).ToList(); command.Status = 200; switch (command.Action) { case PinCommand.