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 SharedMap v2.1.0
plugins/TXC.SharedMap.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyCompany("TXC.SharedMap")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.1.0.0")] [assembly: AssemblyInformationalVersion("2.1.0")] [assembly: AssemblyProduct("TXC.SharedMap")] [assembly: AssemblyTitle("TXC.SharedMap")] [assembly: AssemblyVersion("2.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TXC.SharedMap { [BepInPlugin("txc.sharedmap", "TXC Shared Map", "2.1.0")] public class Plugin : BaseUnityPlugin { private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static void RegisterRpcs(ZNet __instance, ZNetPeer peer) { string[] array; if (__instance.IsServer()) { array = new string[3] { "TXCSharedMap_Hello", "TXCSharedMap_ClientExplored", "TXCSharedMap_ClientPins" }; foreach (string method in array) { peer.m_rpc.Register<ZPackage>(method, (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage pkg) { Server?.Handle(peer.m_uid, method, pkg); }); } return; } array = new string[6] { "TXCSharedMap_Welcome", "TXCSharedMap_Band", "TXCSharedMap_PinList", "TXCSharedMap_SyncDone", "TXCSharedMap_ServerExplored", "TXCSharedMap_ServerPins" }; foreach (string method2 in array) { peer.m_rpc.Register<ZPackage>(method2, (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage pkg) { Client?.Handle(method2, pkg); }); } } [HarmonyPostfix] [HarmonyPatch(typeof(ZNet), "RPC_ServerSyncedPlayerData")] private static void ForcePublicRefPos(ZNet __instance, ZRpc rpc) { if (!__instance.IsServer() || !ForcePublicPosition.Value) { return; } foreach (ZNetPeer peer in __instance.GetPeers()) { if (peer.m_rpc == rpc) { peer.m_publicRefPos = true; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "ShowPinNameInput")] private static void PinPlaced(Minimap __instance) { if ((Object)(object)Client?.Minimap == (Object)(object)__instance) { Client.OnPinPlaced(SharedMapClient.NamePin(__instance)); } } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(PinData) })] private static bool RemovePin(Minimap __instance, PinData pin) { if (!((Object)(object)Client?.Minimap != (Object)(object)__instance)) { return Client.AllowRemove(pin); } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(Vector3), typeof(float) })] private static void UserRemoveStart(Minimap __instance) { if ((Object)(object)Client?.Minimap == (Object)(object)__instance) { Client.UserRemoving = true; } } [HarmonyFinalizer] [HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(Vector3), typeof(float) })] private static void UserRemoveEnd() { if (Client != null) { Client.UserRemoving = false; } } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "GetMapData")] private static void ProfileSaveStart(Minimap __instance, out List<PinData> __state) { __state = (((Object)(object)Client?.Minimap == (Object)(object)__instance) ? Client.BeginExcludePublic() : null); } [HarmonyFinalizer] [HarmonyPatch(typeof(Minimap), "GetMapData")] private static void ProfileSaveEnd(List<PinData> __state) { SharedMapClient.EndExcludePublic(__state); } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "GetSharedMapData")] private static void TableWriteStart(Minimap __instance, out List<PinData> __state) { __state = (((Object)(object)Client?.Minimap == (Object)(object)__instance) ? Client.BeginExcludePublic() : null); } [HarmonyFinalizer] [HarmonyPatch(typeof(Minimap), "GetSharedMapData")] private static void TableWriteEnd(List<PinData> __state) { SharedMapClient.EndExcludePublic(__state); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "ResetSharedMapData")] private static void SharedMapDataReset(Minimap __instance) { if ((Object)(object)Client?.Minimap == (Object)(object)__instance) { Client.OnSharedMapDataReset(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "OnMapLeftClick")] private static bool MapLeftClick(Minimap __instance) { if (!((Object)(object)Client?.Minimap != (Object)(object)__instance)) { return Client.OnMapLeftClick(); } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "Update")] private static void MinimapUpdate(Minimap __instance) { if ((Object)(object)Client?.Minimap == (Object)(object)__instance) { Client.ApplySharedFade(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "UpdatePins")] private static void TintPins(Minimap __instance) { if ((Object)(object)Client?.Minimap == (Object)(object)__instance) { Client.TintPublicPins(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "IsExplored")] private static void IsExplored(Minimap __instance, Vector3 worldPos, ref bool __result) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!__result && (Object)(object)Client?.Minimap == (Object)(object)__instance) { __result = Client.IsInShownLayer(worldPos); } } [HarmonyPrefix] [HarmonyPatch(typeof(ZNet), "SaveWorld")] private static void SaveWorld() { Server?.Save(); } [HarmonyPrefix] [HarmonyPatch(typeof(ZNet), "OnDestroy")] private static void ZNetDestroyed() { Server?.Save(); Server = null; } } public const string PluginGuid = "txc.sharedmap"; public const string PluginName = "TXC Shared Map"; public const string PluginVersion = "2.1.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> ShareExploration; internal static ConfigEntry<bool> SharePins; internal static ConfigEntry<bool> ForcePublicPosition; internal static ConfigEntry<float> DuplicateRadius; internal static ConfigEntry<bool> ShowSharedMap; internal static ConfigEntry<KeyCode> PrivateMarkerKey; internal static ConfigEntry<KeyCode> PublishMarkerKey; internal static ConfigEntry<Color> PublicMarkerColor; internal static ConfigEntry<float> SendInterval; internal static ConfigEntry<int> MaxMessagesPerTick; internal static ConfigEntry<int> MaxSendQueueBytes; internal static SharedMapServer Server; internal static SharedMapClient Client; private static ZNet _serverZNet; private Harmony _harmony; private void Awake() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ShareExploration = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShareExploration", true, "Server setting: share explored map areas between all players who have the mod."); SharePins = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SharePins", true, "Server setting: allow public markers (the 5 player pin icons). Anyone can cross them out; only the owner's account or an admin can delete them. Deletions are logged on the server."); ForcePublicPosition = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ForcePublicPosition", false, "Server setting: every player is shown on the map (vanilla 'Visible on map' forced on), including players without the mod. Players with the mod get the checkbox ticked and locked."); DuplicateRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DuplicateRadius", 20f, new ConfigDescription("Server setting: a new public marker with the same icon and name as an existing one within this many metres is deleted (the older one stays). 0 = off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); ShowSharedMap = ((BaseUnityPlugin)this).Config.Bind<bool>("Client", "ShowSharedMap", true, "Show the shared map: everyone's exploration (lighter fog) and public markers. Off hides them without changing your own exploration, private markers or cartography-table data. Also the 'Shared map' checkbox on the large map."); PrivateMarkerKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Client", "PrivateMarkerKey", (KeyCode)306, "Hold this key while double-clicking the map to place a private marker. A plain double-click places a public one."); PublishMarkerKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Client", "PublishMarkerKey", (KeyCode)304, "Hold this key and left-click a private marker, or a greyed-out cartography table marker, to make it public. A plain left-click on a greyed-out marker makes it your own private one (vanilla)."); PublicMarkerColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Client", "PublicMarkerColor", new Color(1f, 0.85f, 0.55f, 1f), "Tint of public marker icons, to tell them apart from private ones (white = no tint)."); SendInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Network", "SendInterval", 0.25f, new ConfigDescription("Seconds between send batches.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), Array.Empty<object>())); MaxMessagesPerTick = ((BaseUnityPlugin)this).Config.Bind<int>("Network", "MaxMessagesPerTick", 4, new ConfigDescription("Max map messages sent per connection per batch.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 64), Array.Empty<object>())); MaxSendQueueBytes = ((BaseUnityPlugin)this).Config.Bind<int>("Network", "MaxSendQueueBytes", 5120, new ConfigDescription("Hold map traffic while a connection's send queue is above this (vanilla stops world sync at 10240), so the map never crowds out gameplay data.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1024, 65536), Array.Empty<object>())); _harmony = new Harmony("txc.sharedmap"); _harmony.PatchAll(typeof(Patches)); } private void Update() { ZNet instance = ZNet.instance; if (!((Object)(object)instance == (Object)null)) { if (instance.IsServer() && (Object)(object)_serverZNet != (Object)(object)instance && ZNet.World != null) { _serverZNet = instance; Server = new SharedMapServer(ZNet.World); } if (!instance.IsDedicated() && (Object)(object)Minimap.instance != (Object)null && (Object)(object)Client?.Minimap != (Object)(object)Minimap.instance) { Client = new SharedMapClient(Minimap.instance); } Server?.Tick(); Client?.Tick(); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class Protocol { public const int Version = 2; public const int MapSize = 2048; public const int Pixels = 4194304; public const int Words = 131072; public const int BandRows = 64; public const int BandCount = 32; public const int BandWords = 4096; public const int BandPixels = 131072; public const int MaxIndicesPerMessage = 16384; public const int MaxPinOpsPerMessage = 200; public const string Hello = "TXCSharedMap_Hello"; public const string ClientExplored = "TXCSharedMap_ClientExplored"; public const string ClientPins = "TXCSharedMap_ClientPins"; public const string Welcome = "TXCSharedMap_Welcome"; public const string Band = "TXCSharedMap_Band"; public const string PinList = "TXCSharedMap_PinList"; public const string SyncDone = "TXCSharedMap_SyncDone"; public const string ServerExplored = "TXCSharedMap_ServerExplored"; public const string ServerPins = "TXCSharedMap_ServerPins"; public static bool IsSharedType(PinType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Invalid comparison between Unknown and I4 //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 if ((int)type != 0 && (int)type != 1 && (int)type != 2 && (int)type != 3) { return (int)type == 6; } return true; } public static bool IsSet(int[] words, int index) { return (words[index >> 5] & (1 << index)) != 0; } public static void Set(int[] words, int index) { words[index >> 5] |= 1 << index; } public static void AddBits(int word, int wordIndex, List<int> into) { int num = 0; while (word != 0) { if ((word & 1) != 0) { into.Add(wordIndex * 32 + num); } num++; word >>>= 1; } } public static string NormalizeName(string name) { return string.Join(" ", (name ?? "").Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries)).ToLowerInvariant(); } public static string NormalizeId(string hostName) { if (string.IsNullOrEmpty(hostName)) { return ""; } for (int i = 0; i < hostName.Length; i++) { if (!char.IsDigit(hostName[i])) { return hostName; } } return "Steam_" + hostName; } public static ZPackage EncodeIndices(List<int> sorted) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_009a: 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_00a8: Expected O, but got Unknown byte[] array = new byte[sorted.Count * 5]; int num = 0; int num2 = -1; foreach (int item in sorted) { uint num3 = (uint)(item - num2); num2 = item; while (num3 >= 128) { array[num++] = (byte)(num3 | 0x80); num3 >>= 7; } array[num++] = (byte)num3; } byte[] array2 = new byte[num]; Buffer.BlockCopy(array, 0, array2, 0, num); ZPackage val = new ZPackage(); val.Write(sorted.Count); val.Write(array2); ZPackage val2 = new ZPackage(); val2.WriteCompressed(val); return val2; } public static List<int> DecodeIndices(ZPackage pkg) { ZPackage obj = pkg.ReadCompressedPackage(); int num = obj.ReadInt(); byte[] array = obj.ReadByteArray(); List<int> list = new List<int>(num); int num2 = 0; int num3 = -1; while (list.Count < num && num2 < array.Length) { uint num4 = 0u; int num5 = 0; byte b; do { b = array[num2++]; num4 |= (uint)((b & 0x7F) << num5); num5 += 7; } while ((b & 0x80) != 0 && num2 < array.Length); num3 += (int)num4; if (num3 < 0 || num3 >= 4194304) { break; } list.Add(num3); } return list; } public static ZPackage EncodePinOps(List<PinOp> ops) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(ops.Count); foreach (PinOp op in ops) { op.Write(val); } ZPackage val2 = new ZPackage(); val2.WriteCompressed(val); return val2; } public static List<PinOp> DecodePinOps(ZPackage pkg) { ZPackage val = pkg.ReadCompressedPackage(); int num = val.ReadInt(); List<PinOp> list = new List<PinOp>(num); for (int i = 0; i < num; i++) { list.Add(PinOp.Read(val)); } return list; } public static List<T> Take<T>(List<T> list, int max) { int count = Math.Min(max, list.Count); List<T> range = list.GetRange(0, count); list.RemoveRange(0, count); return range; } } internal readonly struct PinKey : IEquatable<PinKey> { public readonly int Type; public readonly int X; public readonly int Z; public PinKey(int type, int x, int z) { Type = type; X = x; Z = z; } public PinKey(int type, Vector3 pos) : this(type, Mathf.RoundToInt(pos.x * 2f), Mathf.RoundToInt(pos.z * 2f)) { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) public static PinKey Of(PinData pin) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected I4, but got Unknown return new PinKey((int)pin.m_type, pin.m_pos); } public bool Equals(PinKey other) { if (Type == other.Type && X == other.X) { return Z == other.Z; } return false; } public override bool Equals(object obj) { if (obj is PinKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (((Type * 397) ^ X) * 397) ^ Z; } public static PinKey Read(ZPackage pkg) { return new PinKey(pkg.ReadInt(), pkg.ReadInt(), pkg.ReadInt()); } } internal enum PinOpKind : byte { Upsert, Remove, Check, Duplicate } internal sealed class PinOp { public PinOpKind Kind; public int Type; public Vector3 Pos; public string Name = ""; public bool Checked; public string Author = ""; public string OwnerId = ""; public string OwnerName = ""; public PinKey Key => new PinKey(Type, Pos); public void Write(ZPackage pkg) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) pkg.Write((byte)Kind); pkg.Write(Type); pkg.Write(Pos); pkg.Write(Name ?? ""); pkg.Write(Checked); pkg.Write(Author ?? ""); pkg.Write(OwnerId ?? ""); pkg.Write(OwnerName ?? ""); } public static PinOp Read(ZPackage pkg) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) return new PinOp { Kind = (PinOpKind)pkg.ReadByte(), Type = pkg.ReadInt(), Pos = pkg.ReadVector3(), Name = pkg.ReadString(), Checked = pkg.ReadBool(), Author = pkg.ReadString(), OwnerId = pkg.ReadString(), OwnerName = pkg.ReadString() }; } public PinOp With(PinOpKind kind) { PinOp obj = (PinOp)MemberwiseClone(); obj.Kind = kind; return obj; } } internal sealed class SharedMapClient { private enum Stage { Waiting, HelloSent, Syncing, Live, Disabled } private sealed class PublicPin { public PinOp Data; public PinData Pin; } private const float HelloTimeout = 60f; private const float ScanInterval = 2f; private const float CheckPollInterval = 0.5f; private const int BlockApplyThreshold = 256; private static readonly FieldRef<Minimap, BitArray> ExploredRef = AccessTools.FieldRefAccess<Minimap, BitArray>("m_explored"); private static readonly FieldRef<Minimap, BitArray> ExploredOthersRef = AccessTools.FieldRefAccess<Minimap, BitArray>("m_exploredOthers"); private static readonly FieldRef<Minimap, Texture2D> FogRef = AccessTools.FieldRefAccess<Minimap, Texture2D>("m_fogTexture"); private static readonly FieldRef<Minimap, List<PinData>> PinsRef = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); private static readonly FieldRef<Minimap, PinData> NamePinRef = AccessTools.FieldRefAccess<Minimap, PinData>("m_namePin"); private static readonly FieldRef<Minimap, bool> HasGeneratedRef = AccessTools.FieldRefAccess<Minimap, bool>("m_hasGenerated"); private static readonly Func<Minimap, PinData> ClosestPinToCursor = AccessTools.MethodDelegate<Func<Minimap, PinData>>(AccessTools.Method(typeof(Minimap), "GetClosestPinToCursor", (Type[])null, (Type[])null), (object)null, true); private static readonly FieldRef<Minimap, float> SharedFadeRef = AccessTools.FieldRefAccess<Minimap, float>("m_sharedMapDataFade"); private static readonly FieldRef<Minimap, Material> SmallShaderRef = AccessTools.FieldRefAccess<Minimap, Material>("m_mapSmallShader"); private static readonly FieldRef<Minimap, Material> LargeShaderRef = AccessTools.FieldRefAccess<Minimap, Material>("m_mapLargeShader"); private readonly Minimap _minimap; private Stage _stage; private bool _shareExploration; private bool _sharePins; private bool _forcePublicPosition; private string _myId = ""; private bool _isAdmin; private float _helloTime; private float _nextScan; private float _nextCheckPoll; private float _nextFlush; private readonly int[] _layer = new int[131072]; private readonly int[] _scan = new int[131072]; private readonly int[] _scanOthers = new int[131072]; private bool _fadeForced; private float _duplicateRadius = 20f; private float _nextDedupe; private PinData _lastPlaced; private bool _layerShown = true; private readonly Dictionary<PinKey, PublicPin> _public = new Dictionary<PinKey, PublicPin>(); private readonly List<int> _pendingExplored = new List<int>(); private readonly List<PinOp> _pendingPins = new List<PinOp>(); private int _receivedPixels; private PinData _placedPin; private bool _placedPrivate; private string _typedName = ""; private bool _nameCancelled; private bool _internalRemove; private Toggle _showToggle; internal bool UserRemoving; public Minimap Minimap => _minimap; private bool Live => _stage == Stage.Live; public SharedMapClient(Minimap minimap) { _minimap = minimap; } internal static PinData NamePin(Minimap minimap) { return NamePinRef.Invoke(minimap); } public void Tick() { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown if (_stage == Stage.Disabled || !HasGeneratedRef.Invoke(_minimap) || (Object)(object)Player.m_localPlayer == (Object)null) { return; } if (!ZNet.instance.IsServer()) { ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer == null || !serverPeer.IsReady()) { return; } } if (_forcePublicPosition) { ZNet.instance.SetPublicReferencePosition(true); _minimap.m_publicPosition.isOn = true; ((Selectable)_minimap.m_publicPosition).interactable = false; } FinishPlacement(); float time = Time.time; switch (_stage) { case Stage.Waiting: { if (ExploredRef.Invoke(_minimap).Length != 4194304) { Plugin.Log.LogWarning((object)$"Minimap size is {ExploredRef.Invoke(_minimap).Length} pixels, expected {4194304}; map sharing disabled."); _stage = Stage.Disabled; break; } _stage = Stage.HelloSent; _helloTime = time; ZPackage val = new ZPackage(); val.Write(2); SendToServer("TXCSharedMap_Hello", val); break; } case Stage.HelloSent: if (time - _helloTime > 60f) { Plugin.Log.LogInfo((object)"Server did not answer: it doesn't run TXC SharedMap. Map sharing is off for this session."); _stage = Stage.Disabled; } break; case Stage.Live: EnsureShowToggle(); if (_layerShown != Plugin.ShowSharedMap.Value) { SetLayerShown(Plugin.ShowSharedMap.Value); } if (_shareExploration && time >= _nextScan) { _nextScan = time + 2f; ScanExplored(); } if (time >= _nextDedupe) { _nextDedupe = time + 1f; DedupeLocalPins(); } if (_sharePins && time >= _nextCheckPoll) { _nextCheckPoll = time + 0.5f; PollChecks(); } if (time >= _nextFlush) { _nextFlush = time + Plugin.SendInterval.Value; Flush(); } break; case Stage.Syncing: break; } } public void Handle(string method, ZPackage pkg) { if (_stage == Stage.Disabled || _stage == Stage.Waiting) { return; } try { switch (method) { case "TXCSharedMap_Welcome": OnWelcome(pkg); break; case "TXCSharedMap_Band": OnBand(pkg); break; case "TXCSharedMap_PinList": foreach (PinOp item in Protocol.DecodePinOps(pkg)) { ApplyPinOp(item); } Plugin.Log.LogInfo((object)$"Received {_public.Count} public marker(s)."); break; case "TXCSharedMap_SyncDone": _stage = Stage.Live; Plugin.Log.LogInfo((object)$"Shared map sync complete: {_receivedPixels} shared map pixel(s) received."); break; case "TXCSharedMap_ServerExplored": AddToLayer(Protocol.DecodeIndices(pkg)); break; case "TXCSharedMap_ServerPins": { foreach (PinOp item2 in Protocol.DecodePinOps(pkg)) { ApplyPinOp(item2); } break; } } } catch (Exception arg) { Plugin.Log.LogError((object)$"Error handling {method}: {arg}"); } } private void OnWelcome(ZPackage pkg) { int num = pkg.ReadInt(); if (num != 2) { Plugin.Log.LogWarning((object)$"Server runs TXC SharedMap protocol v{num}, this client v{2}: map sharing disabled. Both need the same mod version."); _stage = Stage.Disabled; return; } int num2 = pkg.ReadInt(); _shareExploration = pkg.ReadBool(); _sharePins = pkg.ReadBool(); _forcePublicPosition = pkg.ReadBool(); _myId = pkg.ReadString(); _isAdmin = pkg.ReadBool(); _duplicateRadius = ((pkg.GetPos() < pkg.Size()) ? pkg.ReadSingle() : 20f); if (num2 != 2048) { Plugin.Log.LogWarning((object)$"Server map size {num2}, expected {2048}: map sharing disabled."); _stage = Stage.Disabled; return; } _layerShown = Plugin.ShowSharedMap.Value; _stage = Stage.Syncing; Plugin.Log.LogInfo((object)string.Format("Server shares exploration: {0}, markers: {1}, forces 'Visible on map': {2}. You: {3}{4}. Receiving shared map...", _shareExploration, _sharePins, _forcePublicPosition, _myId, _isAdmin ? " (admin)" : "")); } private void OnBand(ZPackage pkg) { ZPackage obj = pkg.ReadCompressedPackage(); int num = obj.ReadInt(); byte[] array = obj.ReadByteArray(); if (num < 0 || num >= 32 || array.Length != 16384) { return; } int[] array2 = new int[4096]; Buffer.BlockCopy(array, 0, array2, 0, array.Length); List<int> list = new List<int>(); int num2 = num * 4096; for (int i = 0; i < array2.Length; i++) { if (array2[i] != 0) { Protocol.AddBits(array2[i], num2 + i, list); } } AddToLayer(list); } private void AddToLayer(List<int> indices) { List<int> list = new List<int>(); foreach (int index in indices) { if (!Protocol.IsSet(_layer, index)) { Protocol.Set(_layer, index); list.Add(index); } } _receivedPixels += list.Count; if (_layerShown && list.Count > 0) { PaintFog(list, shown: true); } } private void PaintFog(List<int> indices, bool shown) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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) BitArray bitArray = ExploredOthersRef.Invoke(_minimap); Texture2D val = FogRef.Invoke(_minimap); indices.Sort(); int num = 0; while (num < indices.Count) { int num2 = indices[num] / 131072; int i; for (i = num; i < indices.Count && indices[i] / 131072 == num2; i++) { } if (i - num > 256) { int num3 = num2 * 64; Color[] pixels = val.GetPixels(0, num3, 2048, 64); for (int j = num; j < i; j++) { int num4 = indices[j]; pixels[num4 - num2 * 131072].g = ((shown || bitArray[num4]) ? 0f : 1f); } val.SetPixels(0, num3, 2048, 64, pixels); } else { for (int k = num; k < i; k++) { int num5 = indices[k]; int num6 = num5 % 2048; int num7 = num5 / 2048; Color pixel = val.GetPixel(num6, num7); pixel.g = ((shown || bitArray[num5]) ? 0f : 1f); val.SetPixel(num6, num7, pixel); } } num = i; } val.Apply(); } private void PaintWholeLayer(bool shown) { List<int> list = new List<int>(); for (int i = 0; i < 131072; i++) { if (_layer[i] != 0) { Protocol.AddBits(_layer[i], i, list); } } if (list.Count > 0) { PaintFog(list, shown); } } private void SetLayerShown(bool shown) { _layerShown = shown; PaintWholeLayer(shown); foreach (PublicPin value in _public.Values) { if (shown && value.Pin == null) { value.Pin = AddLocalPin(value.Data); } else if (!shown && value.Pin != null) { RemoveLocalPin(value.Pin); value.Pin = null; } } Plugin.Log.LogInfo((object)(shown ? "Shared map shown." : "Shared map hidden.")); } private void ApplyPinOp(PinOp op) { if (!Protocol.IsSharedType((PinType)op.Type)) { return; } PinKey key = op.Key; _public.TryGetValue(key, out var value); if (op.Kind == PinOpKind.Remove || op.Kind == PinOpKind.Duplicate) { if (value != null) { if (value.Pin != null) { RemoveLocalPin(value.Pin); } _public.Remove(key); } if (op.Kind == PinOpKind.Duplicate) { string text = (string.IsNullOrEmpty(op.Name) ? "this icon" : ("\"" + op.Name + "\"")); Message("A public marker " + text + " with the same icon already exists nearby; yours was removed."); } return; } if (value == null) { value = new PublicPin(); _public[key] = value; RemoveLegacyCopy(key); } else if (value.Pin != null && value.Pin.m_name != op.Name) { RemoveLocalPin(value.Pin); value.Pin = null; } value.Data = op; if (_layerShown) { if (value.Pin == null) { value.Pin = AddLocalPin(op); } else { value.Pin.m_checked = op.Checked; } } } private void RemoveLegacyCopy(PinKey key) { foreach (PinData item in PinsRef.Invoke(_minimap).ToList()) { if (item.m_save && PinKey.Of(item).Equals(key) && !IsPublic(item)) { RemoveLocalPin(item); } } } private PinData AddLocalPin(PinOp op) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0041: Unknown result type (might be due to invalid IL or missing references) PlatformUserID val = (PlatformUserID)(string.IsNullOrEmpty(op.Author) ? PlatformUserID.None : new PlatformUserID(op.Author)); return _minimap.AddPin(op.Pos, (PinType)op.Type, op.Name, true, op.Checked, 0L, val); } private void RemoveLocalPin(PinData pin) { _internalRemove = true; try { _minimap.RemovePin(pin); } finally { _internalRemove = false; } } public void OnPinPlaced(PinData pin) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) FinishPlacement(force: true); _placedPin = pin; _placedPrivate = ZInput.GetKey(Plugin.PrivateMarkerKey.Value, true); _typedName = ""; _nameCancelled = false; } private static bool CancelPressed() { if (!ZInput.GetKeyDown((KeyCode)27, true)) { return ZInput.GetButton("JoyButtonB"); } return true; } private void FinishPlacement(bool force = false) { PinData placedPin = _placedPin; if (placedPin == null) { return; } if (!force && NamePinRef.Invoke(_minimap) == placedPin) { _typedName = ((TMP_InputField)_minimap.m_nameInput).text ?? ""; _nameCancelled |= CancelPressed(); return; } _placedPin = null; placedPin = (_lastPlaced = ApplyTypedName(placedPin, _nameCancelled || CancelPressed())); if (!_placedPrivate && CanPublish(placedPin)) { Publish(placedPin); } } private bool CanPublish(PinData pin) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (Live && _sharePins && _layerShown && pin.m_save && Protocol.IsSharedType(pin.m_type) && PinsRef.Invoke(_minimap).Contains(pin)) { return !_public.ContainsKey(PinKey.Of(pin)); } return false; } private void Publish(PinData pin) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected I4, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0072: Unknown result type (might be due to invalid IL or missing references) pin.m_ownerID = 0L; PinOp obj = new PinOp { Kind = PinOpKind.Upsert, Type = (int)pin.m_type, Pos = pin.m_pos, Name = (pin.m_name ?? ""), Checked = pin.m_checked, Author = ((object)(((PlatformUserID)(ref pin.m_author)).IsValid ? pin.m_author : ((IUser)PlatformManager.DistributionPlatform.LocalUser).PlatformUserID)/*cast due to .constrained prefix*/).ToString(), OwnerId = _myId }; Game instance = Game.instance; object obj2; if (instance == null) { obj2 = null; } else { PlayerProfile playerProfile = instance.GetPlayerProfile(); obj2 = ((playerProfile != null) ? playerProfile.GetName() : null); } if (obj2 == null) { obj2 = ""; } obj.OwnerName = (string)obj2; PinOp pinOp = obj; _public[PinKey.Of(pin)] = new PublicPin { Data = pinOp, Pin = pin }; _pendingPins.Add(pinOp); } public bool OnMapLeftClick() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!ZInput.GetKey(Plugin.PublishMarkerKey.Value, true)) { return true; } PinData val = ClosestPinToCursor(_minimap); if (val == null || IsPublic(val)) { return true; } if (!CanPublish(val)) { if (Live && Protocol.IsSharedType(val.m_type)) { Message((!_layerShown) ? "Turn on \"Server shared map\" to make markers public." : "This marker can't be made public."); } return true; } Publish(val); return false; } private PinData ApplyTypedName(PinData pin, bool cancelled) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) string text = (_typedName ?? "").Replace('$', ' ').Replace('<', ' ').Replace('>', ' '); if (cancelled || !string.IsNullOrEmpty(pin.m_name) || text.Trim().Length == 0 || !PinsRef.Invoke(_minimap).Contains(pin)) { return pin; } RemoveLocalPin(pin); return _minimap.AddPin(pin.m_pos, pin.m_type, text, pin.m_save, pin.m_checked, pin.m_ownerID, pin.m_author); } private void DedupeLocalPins() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (_duplicateRadius <= 0f) { return; } PinData val = NamePinRef.Invoke(_minimap); List<PinData> obj = PinsRef.Invoke(_minimap); List<KeyValuePair<int, PinData>> list = new List<KeyValuePair<int, PinData>>(); foreach (PinData item in obj) { if (item.m_save && item != val && item != _placedPin && Protocol.IsSharedType(item.m_type)) { int key = ((!IsPublic(item)) ? ((item.m_ownerID == 0L) ? 1 : 2) : 0); list.Add(new KeyValuePair<int, PinData>(key, item)); } } if (list.Count < 2) { return; } List<KeyValuePair<string, PinData>> list2 = new List<KeyValuePair<string, PinData>>(); int num = 0; foreach (KeyValuePair<int, PinData> item2 in list.OrderBy((KeyValuePair<int, PinData> c) => c.Key)) { PinData pin = item2.Value; string name = Protocol.NormalizeName(pin.m_name); if (!list2.Any((KeyValuePair<string, PinData> k) => k.Value.m_type == pin.m_type && k.Key == name && Utils.DistanceXZ(k.Value.m_pos, pin.m_pos) <= _duplicateRadius) || item2.Key == 0) { list2.Add(new KeyValuePair<string, PinData>(name, pin)); continue; } RemoveLocalPin(pin); num++; if (pin == _lastPlaced) { _lastPlaced = null; string text = (string.IsNullOrEmpty(pin.m_name) ? "this icon" : ("\"" + pin.m_name + "\"")); Message("A marker " + text + " with the same icon already exists nearby; yours was removed."); } } if (num > 0) { Plugin.Log.LogInfo((object)$"Removed {num} duplicate marker(s) from your map."); } } private void PollChecks() { foreach (PublicPin value in _public.Values) { if (value.Pin != null && value.Pin.m_checked != value.Data.Checked) { value.Data.Checked = value.Pin.m_checked; _pendingPins.Add(value.Data.With(PinOpKind.Check)); } } } public bool AllowRemove(PinData pin) { if (_internalRemove || !IsPublic(pin, out var key, out var entry)) { return true; } if (!UserRemoving) { return false; } if (!CanDelete(entry.Data)) { string text = (string.IsNullOrEmpty(entry.Data.OwnerName) ? "its owner" : entry.Data.OwnerName); Message("Only " + text + " or an admin can delete this marker."); return false; } _public.Remove(key); _pendingPins.Add(entry.Data.With(PinOpKind.Remove)); return true; } private bool CanDelete(PinOp pin) { if (!_isAdmin) { if (!string.IsNullOrEmpty(pin.OwnerId)) { return pin.OwnerId == _myId; } return false; } return true; } private bool IsPublic(PinData pin) { PinKey key; PublicPin entry; return IsPublic(pin, out key, out entry); } private bool IsPublic(PinData pin, out PinKey key, out PublicPin entry) { key = PinKey.Of(pin); if (_public.TryGetValue(key, out entry)) { return entry.Pin == pin; } return false; } public List<PinData> BeginExcludePublic() { List<PinData> list = new List<PinData>(); foreach (PublicPin value in _public.Values) { if (value.Pin != null && value.Pin.m_save) { value.Pin.m_save = false; list.Add(value.Pin); } } return list; } public static void EndExcludePublic(List<PinData> excluded) { if (excluded == null) { return; } foreach (PinData item in excluded) { item.m_save = true; } } public void ApplySharedFade() { bool flag = Live && _layerShown; if (flag || _fadeForced) { float num = (flag ? 1f : SharedFadeRef.Invoke(_minimap)); Material obj = SmallShaderRef.Invoke(_minimap); if (obj != null) { obj.SetFloat("_SharedFade", num); } Material obj2 = LargeShaderRef.Invoke(_minimap); if (obj2 != null) { obj2.SetFloat("_SharedFade", num); } _fadeForced = flag; } } public void OnSharedMapDataReset() { if (Live && _layerShown) { PaintWholeLayer(shown: true); } } public void TintPublicPins() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Color value = Plugin.PublicMarkerColor.Value; foreach (PublicPin value2 in _public.Values) { PinData pin = value2.Pin; if ((Object)(object)pin?.m_iconElement != (Object)null) { ((Graphic)pin.m_iconElement).color = value; } } } public bool IsInShownLayer(Vector3 worldPos) { //IL_0010: 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) if (!_layerShown) { return false; } int num = 1024; int num2 = Utils.RoundToInt(worldPos.x / _minimap.m_pixelSize + (float)num); int num3 = Utils.RoundToInt(worldPos.z / _minimap.m_pixelSize + (float)num); if (num2 >= 0 && num2 < 2048 && num3 >= 0 && num3 < 2048) { return Protocol.IsSet(_layer, num3 * 2048 + num2); } return false; } private void EnsureShowToggle() { //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Expected O, but got Unknown if ((Object)(object)_showToggle != (Object)null || (Object)(object)_minimap.m_publicPosition == (Object)null) { if ((Object)(object)_showToggle != (Object)null && _showToggle.isOn != Plugin.ShowSharedMap.Value) { _showToggle.SetIsOnWithoutNotify(Plugin.ShowSharedMap.Value); } return; } Transform transform = ((Component)_minimap.m_publicPosition).transform; Transform val = FindCartographyControl(); Transform val2 = transform; Transform val3 = val; if ((Object)(object)val != (Object)null) { Transform ancestor = CommonAncestor(transform, val); val2 = ChildOn(ancestor, transform); val3 = ChildOn(ancestor, val); } GameObject val4 = Object.Instantiate<GameObject>(((Component)val2).gameObject, val2.parent); ((Object)val4).name = "TXCSharedMapToggle"; if ((Object)(object)val3 != (Object)null && (Object)(object)((Component)val2.parent).GetComponent<LayoutGroup>() != (Object)null) { val4.transform.SetSiblingIndex(val3.GetSiblingIndex()); } else if ((Object)(object)val3 != (Object)null) { Vector3 val5 = val3.position - val2.position; val4.transform.position = val3.position + val5; } else { RectTransform val6 = (RectTransform)val4.transform; RectTransform val7 = (RectTransform)val2; Vector2 anchoredPosition = val7.anchoredPosition; Rect rect = val7.rect; val6.anchoredPosition = anchoredPosition + new Vector2(0f, 2f * (((Rect)(ref rect)).height + 6f)); } _showToggle = val4.GetComponentInChildren<Toggle>(true); _showToggle.onValueChanged = new ToggleEvent(); ((Selectable)_showToggle).interactable = true; _showToggle.SetIsOnWithoutNotify(Plugin.ShowSharedMap.Value); ((UnityEvent<bool>)(object)_showToggle.onValueChanged).AddListener((UnityAction<bool>)delegate(bool value) { Plugin.ShowSharedMap.Value = value; }); TMP_Text[] componentsInChildren = val4.GetComponentsInChildren<TMP_Text>(true); for (int num = 0; num < componentsInChildren.Length; num++) { componentsInChildren[num].text = "Server shared map"; } } private Transform FindCartographyControl() { Selectable[] componentsInChildren = _minimap.m_largeRoot.GetComponentsInChildren<Selectable>(true); foreach (Selectable val in componentsInChildren) { Button val2 = (Button)(object)((val is Button) ? val : null); UnityEventBase val3 = (UnityEventBase)((val2 != null) ? ((object)val2.onClick) : ((object)((Toggle)(((val is Toggle) ? val : null)?)).onValueChanged)); if (val3 == null) { continue; } for (int j = 0; j < val3.GetPersistentEventCount(); j++) { if (val3.GetPersistentMethodName(j) == "OnToggleSharedMapData") { return ((Component)val).transform; } } } Plugin.Log.LogWarning((object)"Could not find the cartography 'Shared map' control; placing the Server shared map checkbox two rows up."); return null; } private static Transform CommonAncestor(Transform a, Transform b) { Transform val = a; while ((Object)(object)val != (Object)null) { if (b.IsChildOf(val)) { return val; } val = val.parent; } return a.root; } private static Transform ChildOn(Transform ancestor, Transform descendant) { Transform val = descendant; while ((Object)(object)val.parent != (Object)null && (Object)(object)val.parent != (Object)(object)ancestor) { val = val.parent; } return val; } private static void Message(string text) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } } private void ScanExplored() { ExploredRef.Invoke(_minimap).CopyTo(_scan, 0); ExploredOthersRef.Invoke(_minimap).CopyTo(_scanOthers, 0); for (int i = 0; i < 131072; i++) { int num = (_scan[i] | _scanOthers[i]) & ~_layer[i]; if (num != 0) { _layer[i] |= num; Protocol.AddBits(num, i, _pendingExplored); } } } private void Flush() { int num = Plugin.MaxMessagesPerTick.Value; while (num > 0 && CanSendToServer()) { if (_pendingPins.Count > 0) { SendToServer("TXCSharedMap_ClientPins", Protocol.EncodePinOps(Protocol.Take(_pendingPins, 200))); } else { if (_pendingExplored.Count <= 0) { break; } List<int> list = Protocol.Take(_pendingExplored, 16384); list.Sort(); SendToServer("TXCSharedMap_ClientExplored", Protocol.EncodeIndices(list)); } num--; } } private static bool CanSendToServer() { if (ZNet.instance.IsServer()) { return true; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null && serverPeer.IsReady()) { return serverPeer.m_socket.GetSendQueueSize() < Plugin.MaxSendQueueBytes.Value; } return false; } private static void SendToServer(string method, ZPackage pkg) { if (ZNet.instance.IsServer()) { pkg.SetPos(0); Plugin.Server?.Handle(ZNet.GetUID(), method, pkg); return; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null) { serverPeer.m_rpc.Invoke(method, new object[1] { pkg }); } } } internal sealed class SharedMapServer { private sealed class Peer { public long Uid; public string Name; public string Id; public bool IsAdmin; public readonly Queue<KeyValuePair<string, ZPackage>> Initial = new Queue<KeyValuePair<string, ZPackage>>(); public readonly List<int> Explored = new List<int>(); public readonly List<PinOp> PinOps = new List<PinOp>(); } private const string FileMagic = "TXCSharedMap"; private const int FileVersion = 2; private readonly int[] _explored = new int[131072]; private readonly Dictionary<PinKey, PinOp> _pins = new Dictionary<PinKey, PinOp>(); private readonly Dictionary<long, Peer> _peers = new Dictionary<long, Peer>(); private readonly string _savePath; private bool _dirty; private float _nextFlush; public SharedMapServer(World world) { _savePath = GetSavePath(world); Load(); RemoveStoredDuplicates(); } private static string GetSavePath(World world) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)world.m_fileSource == 2) { return Path.ChangeExtension(world.GetDBPath(), ".txcsharedmap"); } string text = Path.Combine(Paths.ConfigPath, "TXC.SharedMap"); Directory.CreateDirectory(text); return Path.Combine(text, $"{world.m_name}_{world.m_uid}.txcsharedmap"); } public void Handle(long uid, string method, ZPackage pkg) { try { switch (method) { case "TXCSharedMap_Hello": OnHello(uid, pkg); break; case "TXCSharedMap_ClientExplored": OnClientExplored(uid, pkg); break; case "TXCSharedMap_ClientPins": OnClientPins(uid, pkg); break; } } catch (Exception arg) { Plugin.Log.LogError((object)$"Error handling {method} from {DescribePeer(uid)}: {arg}"); } } private void OnHello(long uid, ZPackage pkg) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Expected O, but got Unknown //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown int num = pkg.ReadInt(); Peer peer = new Peer { Uid = uid, Name = PlayerName(uid), Id = AccountId(uid), IsAdmin = IsAdmin(uid) }; ZPackage val = new ZPackage(); val.Write(2); val.Write(2048); val.Write(Plugin.ShareExploration.Value); val.Write(Plugin.SharePins.Value); val.Write(Plugin.ForcePublicPosition.Value); val.Write(peer.Id); val.Write(peer.IsAdmin); val.Write(Plugin.DuplicateRadius.Value); Send(uid, "TXCSharedMap_Welcome", val); if (num != 2) { _peers.Remove(uid); Plugin.Log.LogWarning((object)$"{DescribePeer(uid)} runs protocol v{num}, server runs v{2}: not syncing this player."); return; } int num2 = 0; if (Plugin.ShareExploration.Value) { for (int i = 0; i < 32; i++) { int num3 = i * 4096; bool flag = true; for (int j = 0; j < 4096 && flag; j++) { flag = _explored[num3 + j] == 0; } if (!flag) { byte[] array = new byte[16384]; Buffer.BlockCopy(_explored, num3 * 4, array, 0, array.Length); ZPackage val2 = new ZPackage(); val2.Write(i); val2.Write(array); ZPackage val3 = new ZPackage(); val3.WriteCompressed(val2); peer.Initial.Enqueue(new KeyValuePair<string, ZPackage>("TXCSharedMap_Band", val3)); num2++; } } } if (Plugin.SharePins.Value) { peer.Initial.Enqueue(new KeyValuePair<string, ZPackage>("TXCSharedMap_PinList", Protocol.EncodePinOps(_pins.Values.ToList()))); } ZPackage val4 = new ZPackage(); val4.Write(num2); peer.Initial.Enqueue(new KeyValuePair<string, ZPackage>("TXCSharedMap_SyncDone", val4)); _peers[uid] = peer; Plugin.Log.LogInfo((object)string.Format("{0}{1} joined map sharing: sending {2} map band(s), {3} public marker(s).", DescribePeer(uid), peer.IsAdmin ? " [admin]" : "", num2, _pins.Count)); } private void OnClientExplored(long uid, ZPackage pkg) { if (!Plugin.ShareExploration.Value || !_peers.ContainsKey(uid)) { return; } List<int> list = new List<int>(); foreach (int item in Protocol.DecodeIndices(pkg)) { if (!Protocol.IsSet(_explored, item)) { Protocol.Set(_explored, item); list.Add(item); } } if (list.Count == 0) { return; } _dirty = true; foreach (Peer value in _peers.Values) { if (value.Uid != uid) { value.Explored.AddRange(list); } } } private void OnClientPins(long uid, ZPackage pkg) { if (!Plugin.SharePins.Value || !_peers.TryGetValue(uid, out var value)) { return; } foreach (PinOp item in Protocol.DecodePinOps(pkg)) { if (!Protocol.IsSharedType((PinType)item.Type)) { continue; } PinKey key = item.Key; _pins.TryGetValue(key, out var value2); switch (item.Kind) { case PinOpKind.Upsert: { if (value2 != null) { value.PinOps.Add(value2.With(PinOpKind.Upsert)); break; } PinOp pinOp = FindDuplicate(item, null); if (pinOp != null) { Plugin.Log.LogInfo((object)("Duplicate marker removed: " + Describe(item) + " placed by " + value.Name + " duplicates " + Describe(pinOp) + " by " + pinOp.OwnerName + ".")); value.PinOps.Add(item.With(PinOpKind.Duplicate)); } else { value2 = item.With(PinOpKind.Upsert); value2.OwnerId = value.Id; value2.OwnerName = value.Name; _pins[key] = value2; _dirty = true; Broadcast(uid, value2); } break; } case PinOpKind.Check: if (value2 != null) { value2.Checked = item.Checked; _dirty = true; Broadcast(uid, value2.With(PinOpKind.Upsert)); } break; case PinOpKind.Remove: if (value2 != null) { bool flag = !string.IsNullOrEmpty(value2.OwnerId) && value2.OwnerId == value.Id; if (!flag && !value.IsAdmin) { Plugin.Log.LogWarning((object)("Denied: " + value.Name + " tried to delete " + Describe(value2) + ", owned by " + value2.OwnerName + ".")); value.PinOps.Add(value2.With(PinOpKind.Upsert)); } else { _pins.Remove(key); _dirty = true; Plugin.Log.LogInfo((object)("Marker deleted by " + value.Name + (flag ? "" : " (admin)") + ": " + Describe(value2) + ", owned by " + value2.OwnerName + ".")); Broadcast(uid, value2.With(PinOpKind.Remove)); } } break; } } } private PinOp FindDuplicate(PinOp pin, PinOp ignore) { //IL_0062: 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) float value = Plugin.DuplicateRadius.Value; if (value <= 0f) { return null; } string text = NormalizeName(pin.Name); foreach (PinOp value2 in _pins.Values) { if (value2 != ignore && value2.Type == pin.Type && NormalizeName(value2.Name) == text && Utils.DistanceXZ(value2.Pos, pin.Pos) <= value) { return value2; } } return null; } private static string NormalizeName(string name) { return Protocol.NormalizeName(name); } private void RemoveStoredDuplicates() { List<PinOp> list = new List<PinOp>(); foreach (PinOp pin in _pins.Values.ToList()) { float radius = Plugin.DuplicateRadius.Value; string name = NormalizeName(pin.Name); PinOp pinOp = ((radius <= 0f) ? null : list.FirstOrDefault((PinOp k) => k.Type == pin.Type && NormalizeName(k.Name) == name && Utils.DistanceXZ(k.Pos, pin.Pos) <= radius)); if (pinOp == null) { list.Add(pin); continue; } _pins.Remove(pin.Key); _dirty = true; Plugin.Log.LogInfo((object)("Duplicate marker removed on load: " + Describe(pin) + " by " + pin.OwnerName + " duplicates " + Describe(pinOp) + " by " + pinOp.OwnerName + ".")); } } private static string Describe(PinOp pin) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) string text = ((WorldGenerator.instance != null) ? ((object)WorldGenerator.instance.GetBiome(pin.Pos)/*cast due to .constrained prefix*/).ToString() : "?"); string text2 = (string.IsNullOrEmpty(pin.Name) ? "(unnamed)" : ("\"" + pin.Name + "\"")); return $"{text2} [{(object)(PinType)pin.Type}] in {text} at ({pin.Pos.x:0}, {pin.Pos.z:0})"; } private void Broadcast(long senderUid, PinOp op) { foreach (Peer value in _peers.Values) { if (value.Uid != senderUid) { value.PinOps.Add(op); } } } public void Tick() { if (Time.time < _nextFlush) { return; } _nextFlush = Time.time + Plugin.SendInterval.Value; foreach (Peer item in _peers.Values.ToList()) { if (item.Uid != ZNet.GetUID() && ZNet.instance.GetPeer(item.Uid) == null) { _peers.Remove(item.Uid); } else { Flush(item); } } } private void Flush(Peer peer) { int num = Plugin.MaxMessagesPerTick.Value; while (num > 0 && CanSend(peer.Uid)) { if (peer.Initial.Count > 0) { KeyValuePair<string, ZPackage> keyValuePair = peer.Initial.Dequeue(); Send(peer.Uid, keyValuePair.Key, keyValuePair.Value); } else if (peer.PinOps.Count > 0) { Send(peer.Uid, "TXCSharedMap_ServerPins", Protocol.EncodePinOps(Protocol.Take(peer.PinOps, 200))); } else { if (peer.Explored.Count <= 0) { break; } List<int> list = Protocol.Take(peer.Explored, 16384); list.Sort(); Send(peer.Uid, "TXCSharedMap_ServerExplored", Protocol.EncodeIndices(list)); } num--; } } private static bool CanSend(long uid) { if (uid == ZNet.GetUID()) { return true; } ZNetPeer peer = ZNet.instance.GetPeer(uid); if (peer != null && peer.IsReady()) { return peer.m_socket.GetSendQueueSize() < Plugin.MaxSendQueueBytes.Value; } return false; } private static void Send(long uid, string method, ZPackage pkg) { if (uid == ZNet.GetUID()) { pkg.SetPos(0); Plugin.Client?.Handle(method, pkg); return; } ZNetPeer peer = ZNet.instance.GetPeer(uid); if (peer != null) { peer.m_rpc.Invoke(method, new object[1] { pkg }); } } private static string PlayerName(long uid) { if (uid == ZNet.GetUID()) { Game instance = Game.instance; object obj; if (instance == null) { obj = null; } else { PlayerProfile playerProfile = instance.GetPlayerProfile(); obj = ((playerProfile != null) ? playerProfile.GetName() : null); } if (obj == null) { obj = "host"; } return (string)obj; } return ZNet.instance.GetPeer(uid)?.m_playerName ?? uid.ToString(); } private static string AccountId(long uid) { //IL_0012: 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) if (uid == ZNet.GetUID()) { return ((object)((IUser)PlatformManager.DistributionPlatform.LocalUser).PlatformUserID/*cast due to .constrained prefix*/).ToString(); } ZNetPeer peer = ZNet.instance.GetPeer(uid); return Protocol.NormalizeId((peer != null) ? peer.m_socket.GetHostName() : null); } private static bool IsAdmin(long uid) { if (uid == ZNet.GetUID()) { return true; } ZNetPeer peer = ZNet.instance.GetPeer(uid); if (peer != null) { return ZNet.instance.IsAdmin(peer.m_socket.GetHostName()); } return false; } private string DescribePeer(long uid) { if (!_peers.TryGetValue(uid, out var value)) { return PlayerName(uid) + " (" + AccountId(uid) + ")"; } return value.Name + " (" + value.Id + ")"; } public void Save() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown if (!_dirty) { return; } try { ZPackage val = new ZPackage(); val.Write(2048); byte[] array = new byte[524288]; Buffer.BlockCopy(_explored, 0, array, 0, array.Length); val.Write(array); val.Write(_pins.Count); foreach (PinOp value in _pins.Values) { value.Write(val); } ZPackage val2 = new ZPackage(); val2.Write("TXCSharedMap"); val2.Write(2); val2.WriteCompressed(val); string text = _savePath + ".tmp"; File.WriteAllBytes(text, val2.GetArray()); if (File.Exists(_savePath)) { File.Copy(_savePath, _savePath + ".old", overwrite: true); } File.Copy(text, _savePath, overwrite: true); File.Delete(text); _dirty = false; Plugin.Log.LogInfo((object)$"Saved shared map ({_pins.Count} public markers) to {_savePath}"); } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to save shared map to {_savePath}: {arg}"); } } private void Load() { //IL_0039: 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_005b: Unknown result type (might be due to invalid IL or missing references) if (!File.Exists(_savePath)) { Plugin.Log.LogInfo((object)("No shared map saved yet (" + _savePath + "); starting empty.")); return; } try { ZPackage val = new ZPackage(File.ReadAllBytes(_savePath)); if (val.ReadString() != "TXCSharedMap") { throw new InvalidDataException("not a TXC SharedMap file"); } int num = val.ReadInt(); if (num < 1 || num > 2) { throw new InvalidDataException($"unsupported file version {num}"); } ZPackage val2 = val.ReadCompressedPackage(); int num2 = val2.ReadInt(); if (num2 != 2048) { throw new InvalidDataException($"map size {num2}, expected {2048}"); } byte[] array = val2.ReadByteArray(); Buffer.BlockCopy(array, 0, _explored, 0, Math.Min(array.Length, 524288)); int num3 = val2.ReadInt(); for (int i = 0; i < num3; i++) { PinOp pinOp = ((num == 1) ? ReadV1Pin(val2) : PinOp.Read(val2)); pinOp.Kind = PinOpKind.Upsert; _pins[pinOp.Key] = pinOp; } if (num == 1) { _dirty = true; } int num4 = 0; int[] explored = _explored; for (int j = 0; j < explored.Length; j++) { for (int num5 = explored[j]; num5 != 0; num5 &= num5 - 1) { num4++; } } Plugin.Log.LogInfo((object)$"Loaded shared map (file v{num}): {num4} explored pixels, {_pins.Count} public markers."); } catch (Exception ex) { string text = $"{_savePath}.broken-{DateTime.Now:yyyyMMdd-HHmmss}"; Plugin.Log.LogError((object)("Failed to load " + _savePath + " (" + ex.Message + "); moved it to " + text + " and starting empty.")); try { File.Move(_savePath, text); } catch (Exception ex2) { Plugin.Log.LogError((object)("Could not move it: " + ex2.Message)); } Array.Clear(_explored, 0, _explored.Length); _pins.Clear(); } } private static PinOp ReadV1Pin(ZPackage pkg) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) pkg.ReadBool(); return new PinOp { Type = pkg.ReadInt(), Pos = pkg.ReadVector3(), Name = pkg.ReadString(), Checked = pkg.ReadBool(), Author = pkg.ReadString(), OwnerName = pkg.ReadString() }; } } }