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 v0.5.1
SharedMap.dll
Decompiled 5 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading; using BepInEx; using BepInEx.Logging; using HarmonyLib; using JG224.ModCore.API; 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: AssemblyFileVersion("0.5.1.0")] [assembly: AssemblyInformationalVersion("0.5.1")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.5.1.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 SharedMap { internal static class MapAccess { private static readonly FieldInfo ExploredField = AccessTools.Field(typeof(Minimap), "m_explored"); private static readonly FieldInfo HasGeneratedField = AccessTools.Field(typeof(Minimap), "m_hasGenerated"); private static readonly FieldInfo ExploredOthersField = AccessTools.Field(typeof(Minimap), "m_exploredOthers"); private static readonly FieldInfo FogTextureField = AccessTools.Field(typeof(Minimap), "m_fogTexture"); private static readonly FieldInfo ShowSharedField = AccessTools.Field(typeof(Minimap), "m_showSharedMapData"); private static readonly FieldInfo SharedFadeField = AccessTools.Field(typeof(Minimap), "m_sharedMapDataFade"); private static readonly FieldInfo LargeMaterialField = AccessTools.Field(typeof(Minimap), "m_mapLargeShader"); private static readonly FieldInfo SmallMaterialField = AccessTools.Field(typeof(Minimap), "m_mapSmallShader"); private static readonly FieldInfo LargeZoomField = AccessTools.Field(typeof(Minimap), "m_largeZoom"); private static readonly FieldInfo NamePinField = AccessTools.Field(typeof(Minimap), "m_namePin"); private static readonly FieldInfo PinUpdateRequiredField = AccessTools.Field(typeof(Minimap), "m_pinUpdateRequired"); private static readonly MethodInfo ScreenToWorldMethod = AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", new Type[1] { typeof(Vector3) }, (Type[])null); private static readonly MethodInfo GetClosestPinMethod = AccessTools.Method(typeof(Minimap), "GetClosestPin", new Type[3] { typeof(Vector3), typeof(float), typeof(bool) }, (Type[])null); private static readonly MethodInfo SelectIconMethod = AccessTools.Method(typeof(Minimap), "SelectIcon", new Type[1] { typeof(PinType) }, (Type[])null); private static Minimap _fogMap; private static Texture2D _fogTexture; private static Material _largeMaterial; private static Material _smallMaterial; private static SharedMapFogMask _sharedFog; private static BitArray _vanillaOthers; private static bool _vanillaVisible; private static float _lastVanillaFade; internal static bool IsReady(Minimap map) { bool flag = default(bool); int num; if ((Object)(object)map != (Object)null && HasGeneratedField != null) { object value = HasGeneratedField.GetValue(map); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0 && ExploredField.GetValue(map) is BitArray bitArray) { return bitArray.Length == map.m_textureSize * map.m_textureSize; } return false; } internal static BitArray GetExplored(Minimap map) { return (BitArray)ExploredField.GetValue(map); } internal static byte[] PackLocalExploration(Minimap map) { return SharedMapExploration.Pack(GetExplored(map)); } internal static bool ApplyFullSharedExploration(Minimap map, int mapSize, byte[] packed) { if (!IsReady(map) || map.m_textureSize != mapSize || packed == null || packed.Length != PackedLength(mapSize)) { return false; } if (!EnsureSharedLayer(map)) { return false; } _sharedFog.Replace(packed); RecomposeSharedFog(map); return true; } internal static bool ApplySharedDelta(Minimap map, int mapSize, IReadOnlyList<int> indices) { if (!IsReady(map) || map.m_textureSize != mapSize || indices == null) { return false; } if (!EnsureSharedLayer(map)) { return false; } bool flag = false; for (int i = 0; i < indices.Count; i++) { int index = indices[i]; if (_sharedFog.Add(index)) { flag |= ComposePixel(index); } } if (!flag) { return false; } _fogTexture.Apply(); return true; } internal static void SetShowShared(Minimap map, bool show) { if (!show) { ClearSharedExploration(); } else { EnsureSharedLayer(map); } } internal static void RefreshSharedPresentation(Minimap map, bool visible, float fade) { if (map == _fogMap && _sharedFog != null) { if (visible != _vanillaVisible) { RecomposeSharedFog(map); } if (fade != _lastVanillaFade) { _lastVanillaFade = fade; SetMaterialFade(1f); } } } internal static void RecomposeSharedFog(Minimap map) { if (map != _fogMap || _sharedFog == null || (Object)(object)_fogTexture == (Object)null) { return; } BitArray bitArray = (BitArray)ExploredOthersField.GetValue(map); if (bitArray == null || bitArray.Length != _sharedFog.PixelCount) { return; } _vanillaOthers = bitArray; _vanillaVisible = (bool)ShowSharedField.GetValue(map); Color32[] pixels = _fogTexture.GetPixels32(); if (pixels.Length == bitArray.Length) { for (int i = 0; i < pixels.Length; i++) { pixels[i].g = (byte)((!_sharedFog.Reveals(i, bitArray[i], _vanillaVisible)) ? byte.MaxValue : 0); } _fogTexture.SetPixels32(pixels); _fogTexture.Apply(); _lastVanillaFade = (float)SharedFadeField.GetValue(map); SetMaterialFade(1f); } } internal static void AfterVanillaSharedPixel(Minimap map, int x, int y) { if (map == _fogMap && _sharedFog != null && x >= 0 && y >= 0 && x < map.m_textureSize && y < map.m_textureSize) { ComposePixel(y * map.m_textureSize + x); } } internal static void ClearSharedExploration() { if ((Object)(object)_fogMap != (Object)null && (Object)(object)_fogTexture != (Object)null) { BitArray bitArray = (BitArray)ExploredOthersField.GetValue(_fogMap); Color32[] pixels = _fogTexture.GetPixels32(); if (bitArray != null && bitArray.Length == pixels.Length) { for (int i = 0; i < pixels.Length; i++) { pixels[i].g = (byte)((!bitArray[i]) ? byte.MaxValue : 0); } _fogTexture.SetPixels32(pixels); _fogTexture.Apply(); } SetMaterialFade((float)SharedFadeField.GetValue(_fogMap)); } _fogMap = null; _fogTexture = null; _largeMaterial = null; _smallMaterial = null; _sharedFog = null; _vanillaOthers = null; } private static bool EnsureSharedLayer(Minimap map) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown if (!IsReady(map)) { return false; } if (map == _fogMap && _sharedFog != null) { return true; } ClearSharedExploration(); Texture2D val = (Texture2D)FogTextureField.GetValue(map); BitArray bitArray = (BitArray)ExploredOthersField.GetValue(map); if ((Object)(object)val == (Object)null || bitArray == null || bitArray.Length != map.m_textureSize * map.m_textureSize) { return false; } _fogMap = map; _fogTexture = val; _largeMaterial = (Material)LargeMaterialField.GetValue(map); _smallMaterial = (Material)SmallMaterialField.GetValue(map); _sharedFog = new SharedMapFogMask(bitArray.Length); _vanillaOthers = bitArray; RecomposeSharedFog(map); return true; } private static bool ComposePixel(int index) { //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_0051: 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) int num = index % _fogMap.m_textureSize; int num2 = index / _fogMap.m_textureSize; Color pixel = _fogTexture.GetPixel(num, num2); float num3 = (_sharedFog.Reveals(index, _vanillaOthers[index], _vanillaVisible) ? 0f : 1f); if (pixel.g == num3) { return false; } pixel.g = num3; _fogTexture.SetPixel(num, num2, pixel); return true; } private static void SetMaterialFade(float fade) { if ((Object)(object)_largeMaterial != (Object)null) { _largeMaterial.SetFloat("_SharedFade", fade); } if ((Object)(object)_smallMaterial != (Object)null) { _smallMaterial.SetFloat("_SharedFade", fade); } } internal static PinData GetNamePin(Minimap map) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (!((Object)(object)map == (Object)null)) { return (PinData)NamePinField.GetValue(map); } return null; } internal static void RequirePinUpdate(Minimap map) { if ((Object)(object)map != (Object)null) { PinUpdateRequiredField.SetValue(map, true); } } internal static void SelectIcon(Minimap map, PinType type) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) SelectIconMethod.Invoke(map, new object[1] { type }); } internal static PinData GetClosestVisiblePin(Minimap map, Vector3 worldPosition, float radius) { //IL_000e: 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_0032: Expected O, but got Unknown return (PinData)GetClosestPinMethod.Invoke(map, new object[3] { worldPosition, radius, true }); } internal static Vector3 ScreenToWorld(Minimap map, Vector3 screenPosition) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return (Vector3)ScreenToWorldMethod.Invoke(map, new object[1] { screenPosition }); } internal static float GetClickRadius(Minimap map) { return map.m_removeRadius * (float)LargeZoomField.GetValue(map) * 2f; } internal static int PackedLength(int mapSize) { return checked(mapSize * mapSize + 7) / 8; } internal static bool IsSet(byte[] packed, int index) { return (packed[index >> 3] & (1 << (index & 7))) != 0; } } internal sealed class PublicMarker { internal string Id = string.Empty; internal long OwnerPlayerId; internal string OwnerAccountKey = string.Empty; internal string OwnerName = string.Empty; internal Vector3 Position; internal PinType Type; internal string Name = string.Empty; internal bool Checked; internal long Revision; internal PublicMarker Copy() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_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) return new PublicMarker { Id = Id, OwnerPlayerId = OwnerPlayerId, OwnerAccountKey = OwnerAccountKey, OwnerName = OwnerName, Position = Position, Type = Type, Name = Name, Checked = Checked, Revision = Revision }; } } internal static class SharedMapClient { internal readonly struct MarkerCheckState { internal string MarkerId { get; } internal bool WasChecked { get; } internal bool IsValid => !string.IsNullOrEmpty(MarkerId); internal MarkerCheckState(string markerId, bool wasChecked) { MarkerId = markerId; WasChecked = wasChecked; } } internal sealed class PinSaveState { internal readonly List<KeyValuePair<PinData, bool>> Pins = new List<KeyValuePair<PinData, bool>>(); internal bool Restored; } private const double DeltaIntervalSeconds = 10.0; private const double ParticipationRetrySeconds = 30.0; private const int MaximumDeltaEntries = 16384; private static readonly Color PublicMarkerColor = new Color(0.3f, 0.95f, 0.36f, 1f); private static readonly Dictionary<string, PublicMarker> Markers = new Dictionary<string, PublicMarker>(StringComparer.Ordinal); private static readonly Dictionary<string, PinData> PinsById = new Dictionary<string, PinData>(StringComparer.Ordinal); private static readonly Dictionary<PinData, string> IdsByPin = new Dictionary<PinData, string>(); private static readonly HashSet<int> PendingExploration = new HashSet<int>(); private static Minimap _pinMap; private static string _preferenceKey; private static long _worldUid; private static long _playerId; private static bool _sharing; private static bool _participationSent; private static bool _snapshotReceived; private static double _nextParticipationRetry; private static double _nextDelta; private static PinData _pendingNamePin; private static PinType _pendingPublicType; private static bool _committingPublicPin; internal static bool Sharing => _sharing; internal static bool ReadyForPublicMarkers => SharedMapUiRules.CanUsePublicMarkers(_sharing, _snapshotReceived); internal static long CurrentWorldUid => _worldUid; internal static IEnumerable<string> MarkerDescriptions() { return from marker in Markers.Values.OrderBy<PublicMarker, string>((PublicMarker marker) => marker.Name, StringComparer.OrdinalIgnoreCase) select marker.Id + " | " + marker.Name + " | " + marker.OwnerName + " (" + marker.OwnerPlayerId + ")"; } internal static void Tick(double now) { SharedMapNetwork.Tick(now); if (Application.isBatchMode) { return; } ZNet instance = ZNet.instance; Player localPlayer = Player.m_localPlayer; Minimap instance2 = Minimap.instance; if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null || (Object)(object)instance2 == (Object)null || !MapAccess.IsReady(instance2)) { return; } InitializePreference(instance.GetWorldUID(), localPlayer.GetPlayerID()); SharedMapUi.Ensure(instance2); SharedMapUi.Refresh(_sharing, ReadyForPublicMarkers); EnsurePinMap(instance2); MapAccess.SetShowShared(instance2, _sharing); if (!_sharing) { return; } if (_participationSent && !_snapshotReceived && now >= _nextParticipationRetry && SharedMapNetwork.CanRetryParticipation(now)) { _participationSent = false; } if (!_participationSent) { byte[] snapshot = MapAccess.PackLocalExploration(instance2); if (SharedMapNetwork.SendParticipation(enabled: true, instance2.m_textureSize, snapshot)) { _participationSent = true; PendingExploration.Clear(); _nextParticipationRetry = now + 30.0; _nextDelta = now + 10.0; } } else if (_snapshotReceived && now >= _nextDelta) { FlushExploration(instance2); _nextDelta = now + 10.0; } } internal static void SetSharing(bool enabled) { if (_sharing == enabled) { SharedMapUi.Refresh(_sharing, ReadyForPublicMarkers); return; } _sharing = enabled; if (!string.IsNullOrEmpty(_preferenceKey)) { PlayerPrefs.SetInt(_preferenceKey, enabled ? 1 : 0); PlayerPrefs.Save(); } Minimap instance = Minimap.instance; MapAccess.SetShowShared(instance, enabled); if (!enabled) { if (_participationSent) { SharedMapNetwork.SendParticipation(enabled: false, 0, Array.Empty<byte>()); } SharedMapNetwork.ResetClientTransfer(); _participationSent = false; _snapshotReceived = false; PendingExploration.Clear(); ClearRenderedPins(); SharedMapUi.ClearPublicSelection(); } else { _participationSent = false; _snapshotReceived = false; EnsurePinMap(instance); RenderAllMarkers(); } SharedMapUi.Refresh(_sharing, ReadyForPublicMarkers); } internal static void RecordLocalExploration(Minimap map, int x, int y, bool newlyExplored) { if (newlyExplored && _sharing && !((Object)(object)map == (Object)null) && !((Object)(object)map != (Object)(object)Minimap.instance) && x >= 0 && y >= 0 && x < map.m_textureSize && y < map.m_textureSize) { PendingExploration.Add(y * map.m_textureSize + x); } } internal static void ReceiveSnapshot(long worldUid, int mapSize, byte[] exploration, IReadOnlyList<PublicMarker> markers) { if (!_sharing || worldUid != _worldUid) { return; } Minimap instance = Minimap.instance; if (!((Object)(object)instance == (Object)null) && MapAccess.IsReady(instance) && instance.m_textureSize == mapSize) { MapAccess.ApplyFullSharedExploration(instance, mapSize, exploration); _snapshotReceived = true; ClearRenderedPins(); Markers.Clear(); for (int i = 0; i < markers.Count; i++) { PublicMarker publicMarker = markers[i]; Markers[publicMarker.Id] = publicMarker.Copy(); } EnsurePinMap(instance); RenderAllMarkers(); SharedMapUi.Refresh(_sharing, ReadyForPublicMarkers); ManualLogSource log = SharedMapPlugin.Log; if (log != null) { log.LogInfo((object)$"Received SharedMap snapshot: {markers.Count} public marker(s), map {mapSize}x{mapSize}."); } } } internal static void ReceiveExplorationDelta(long worldUid, int mapSize, IReadOnlyList<int> indices) { if (_sharing && worldUid == _worldUid) { MapAccess.ApplySharedDelta(Minimap.instance, mapSize, indices); } } internal static void ReceiveExplorationSnapshot(long worldUid, int mapSize, byte[] exploration) { if (_sharing && worldUid == _worldUid) { Minimap instance = Minimap.instance; if (!((Object)(object)instance == (Object)null) && MapAccess.IsReady(instance) && instance.m_textureSize == mapSize) { MapAccess.ApplyFullSharedExploration(instance, mapSize, exploration); } } } internal static void UpsertMarker(PublicMarker marker) { if (marker != null && !string.IsNullOrEmpty(marker.Id) && (!Markers.TryGetValue(marker.Id, out var value) || value.Revision <= marker.Revision)) { Markers[marker.Id] = marker.Copy(); if (_sharing) { EnsurePinMap(Minimap.instance); RemoveRenderedPin(marker.Id); RenderMarker(marker); } } } internal static void RemoveMarker(string markerId) { if (!string.IsNullOrEmpty(markerId)) { Markers.Remove(markerId); RemoveRenderedPin(markerId); } } internal static void TintPublicPins(Minimap map) { //IL_0052: 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) if (!_sharing || (Object)(object)map == (Object)null || (Object)(object)map != (Object)(object)_pinMap) { return; } foreach (PinData value in PinsById.Values) { if ((Object)(object)value?.m_iconElement != (Object)null) { ((Graphic)value.m_iconElement).color = PublicMarkerColor; } object obj; if (value == null) { obj = null; } else { PinNameData namePinData = value.m_NamePinData; obj = ((namePinData != null) ? namePinData.PinNameText : null); } if ((Object)obj != (Object)null) { ((Graphic)value.m_NamePinData.PinNameText).color = PublicMarkerColor; } } } internal static MarkerCheckState CaptureClosestPublicCheck(Minimap map, Vector3 screenPosition) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!_sharing || (Object)(object)map == (Object)null) { return default(MarkerCheckState); } Vector3 worldPosition = MapAccess.ScreenToWorld(map, screenPosition); PinData closestVisiblePin = MapAccess.GetClosestVisiblePin(map, worldPosition, MapAccess.GetClickRadius(map)); if (closestVisiblePin == null || !IdsByPin.TryGetValue(closestVisiblePin, out var value)) { return default(MarkerCheckState); } return new MarkerCheckState(value, closestVisiblePin.m_checked); } internal static void SubmitCheckChange(MarkerCheckState state) { if (state.IsValid && PinsById.TryGetValue(state.MarkerId, out var value) && value != null && value.m_checked != state.WasChecked) { bool isChecked = value.m_checked; value.m_checked = state.WasChecked; MapAccess.RequirePinUpdate(_pinMap); SharedMapNetwork.RequestMarkerChecked(state.MarkerId, isChecked); } } internal static bool TryHandleRemoveAt(Minimap map, Vector3 worldPosition, float radius, out bool result) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) result = false; if (!_sharing || (Object)(object)map == (Object)null) { return false; } PinData closestVisiblePin = MapAccess.GetClosestVisiblePin(map, worldPosition, radius); if (closestVisiblePin == null || !IdsByPin.TryGetValue(closestVisiblePin, out var value)) { return false; } result = true; if (!Markers.ContainsKey(value)) { return true; } SharedMapNetwork.RequestMarkerDelete(value); return true; } internal static void AfterShowPinNameInput(Minimap map) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) CancelPendingPublicPin(map); if (!_sharing || !SharedMapUi.PublicMarkerSelected) { return; } PinData namePin = MapAccess.GetNamePin(map); if (namePin != null) { _pendingNamePin = namePin; _pendingPublicType = SharedMapUi.SelectedPublicType; namePin.m_save = false; if (!ReadyForPublicMarkers) { ShowMessage("SharedMap is still syncing. This public marker will not be created."); } } } internal static PinData BeforePinTextEntered(Minimap map) { if (_pendingNamePin == null || MapAccess.GetNamePin(map) != _pendingNamePin) { return null; } _committingPublicPin = true; return _pendingNamePin; } internal static void AfterPinTextEntered(Minimap map, PinData pending) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_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_003b: 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) _committingPublicPin = false; if (pending != null) { Vector3 pos = pending.m_pos; string name = pending.m_name ?? string.Empty; PinType pendingPublicType = _pendingPublicType; map.RemovePin(pending); _pendingNamePin = null; if (ReadyForPublicMarkers) { SharedMapNetwork.RequestMarkerCreate(pendingPublicType, pos, name); } else { ShowMessage("SharedMap is still syncing. Try placing the public marker again in a moment."); } } } internal static void BeforeHidePinTextInput(Minimap map) { if (!_committingPublicPin && _pendingNamePin != null) { CancelPendingPublicPin(map); } } internal static PinSaveState SuspendPublicPinsForSerialization() { PinSaveState pinSaveState = new PinSaveState(); foreach (PinData value in PinsById.Values) { if (value != null) { pinSaveState.Pins.Add(new KeyValuePair<PinData, bool>(value, value.m_save)); value.m_save = false; } } return pinSaveState; } internal static void RestorePublicPinsAfterSerialization(PinSaveState state) { if (state == null || state.Restored) { return; } state.Restored = true; for (int i = 0; i < state.Pins.Count; i++) { KeyValuePair<PinData, bool> keyValuePair = state.Pins[i]; if (keyValuePair.Key != null) { keyValuePair.Key.m_save = keyValuePair.Value; } } } internal static void OnMinimapDestroyed(Minimap map) { if (_pinMap == map) { MapAccess.ClearSharedExploration(); PinsById.Clear(); IdsByPin.Clear(); _pinMap = null; _pendingNamePin = null; _committingPublicPin = false; ResetConnection(clearOutgoing: false); SharedMapUi.Destroy(map); } } internal static void ShowMessage(string message) { if (!string.IsNullOrWhiteSpace(message)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false); } } } internal static void ResetConnection(bool clearOutgoing = true) { MapAccess.ClearSharedExploration(); if (clearOutgoing) { SharedMapNetwork.ResetConnectionTransfers(); } else { SharedMapNetwork.ResetClientTransfer(); } _participationSent = false; _snapshotReceived = false; _nextParticipationRetry = 0.0; PendingExploration.Clear(); CancelPendingPublicPin(Minimap.instance); SharedMapUi.ClearPublicSelection(); SharedMapUi.Refresh(_sharing, ReadyForPublicMarkers); } internal static void ResetSession() { MapAccess.ClearSharedExploration(); SharedMapNetwork.ResetConnectionTransfers(); ClearRenderedPins(); Markers.Clear(); PendingExploration.Clear(); _preferenceKey = null; _worldUid = 0L; _playerId = 0L; _sharing = false; _participationSent = false; _snapshotReceived = false; _nextParticipationRetry = 0.0; _nextDelta = 0.0; _pendingNamePin = null; _committingPublicPin = false; SharedMapUi.Destroy(null); } private static void InitializePreference(long worldUid, long playerId) { string text = "com.jg224.sharedmap.share." + worldUid + "." + playerId; if (!string.Equals(_preferenceKey, text, StringComparison.Ordinal)) { MapAccess.ClearSharedExploration(); ClearRenderedPins(); SharedMapNetwork.ResetConnectionTransfers(); Markers.Clear(); PendingExploration.Clear(); _worldUid = worldUid; _playerId = playerId; _preferenceKey = text; _sharing = PlayerPrefs.GetInt(text, 0) == 1; _participationSent = false; _snapshotReceived = false; _nextParticipationRetry = 0.0; _nextDelta = 0.0; } } private static void FlushExploration(Minimap map) { while (PendingExploration.Count > 0) { List<int> list = PendingExploration.OrderBy((int index) => index).Take(16384).ToList(); if (!SharedMapNetwork.SendExplorationDelta(map.m_textureSize, list)) { break; } for (int num = 0; num < list.Count; num++) { PendingExploration.Remove(list[num]); } } } private static void EnsurePinMap(Minimap map) { if (!((Object)(object)map == (Object)null) && _pinMap != map) { PinsById.Clear(); IdsByPin.Clear(); _pinMap = map; if (_sharing) { RenderAllMarkers(); } } } internal static void AfterVanillaMapLoaded(Minimap map) { if (map == _pinMap) { ClearRenderedPins(); if (_sharing) { RenderAllMarkers(); } MapAccess.RecomposeSharedFog(map); } } private static void RenderAllMarkers() { if (!_sharing || (Object)(object)_pinMap == (Object)null) { return; } foreach (PublicMarker item in Markers.Values.OrderBy<PublicMarker, string>((PublicMarker marker) => marker.Id, StringComparer.Ordinal)) { if (!PinsById.ContainsKey(item.Id)) { RenderMarker(item); } } } private static void RenderMarker(PublicMarker marker) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (_sharing && !((Object)(object)_pinMap == (Object)null) && marker != null) { PinData val = _pinMap.AddPin(marker.Position, marker.Type, marker.Name, true, marker.Checked, 0L, PlatformUserID.None); val.m_save = true; PinsById[marker.Id] = val; IdsByPin[val] = marker.Id; MapAccess.RequirePinUpdate(_pinMap); } } private static void RemoveRenderedPin(string markerId) { if (!PinsById.TryGetValue(markerId, out var value)) { return; } PinsById.Remove(markerId); if (value != null) { IdsByPin.Remove(value); if ((Object)(object)_pinMap != (Object)null) { _pinMap.RemovePin(value); } } } private static void ClearRenderedPins() { if ((Object)(object)_pinMap != (Object)null) { PinData[] array = PinsById.Values.ToArray(); foreach (PinData val in array) { if (val != null) { _pinMap.RemovePin(val); } } } PinsById.Clear(); IdsByPin.Clear(); } private static void CancelPendingPublicPin(Minimap map) { if (_pendingNamePin != null && (Object)(object)map != (Object)null) { map.RemovePin(_pendingNamePin); } _pendingNamePin = null; _committingPublicPin = false; } } internal static class SharedMapCommands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; internal void <Register>b__0_0(ConsoleEventArgs args) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) string[] args2 = args.Args; if (args2.Length < 2 || args2[1] == "list") { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { SharedMapServer.ManageMarker(0L, host: true, "list", string.Empty, string.Empty, Vector3.zero); } else { foreach (string item in SharedMapClient.MarkerDescriptions()) { args.Context.AddString(item); } } args.Context.AddString("sharedmap rename <id> <name> | move <id> <x> <z> | delete <id> | cleanup <playerID> | peers | bind <legacyPlayerID> <peerUID> (admin)"); return; } string text = args2[1].ToLowerInvariant(); if (text == "peers") { SharedMapNetwork.ManageMarker(text, string.Empty, string.Empty, Vector3.zero); return; } if (args2.Length < 3) { args.Context.AddString("A public marker ID or character owner ID is required."); return; } if (text == "bind" && args2.Length != 4) { args.Context.AddString("Use sharedmap bind <legacyPlayerID> <connectedPeerUID>; inspect sharedmap peers first."); return; } Vector3 zero = Vector3.zero; if (text == "move") { if (args2.Length != 5 || !float.TryParse(args2[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(args2[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { args.Context.AddString("Use sharedmap move <id> <x> <z>."); return; } ((Vector3)(ref zero))..ctor(result, 0f, result2); } SharedMapNetwork.ManageMarker(text, args2[2], string.Join(" ", args2.Skip(3)), zero); } } internal static void Register() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) string[] args2 = args.Args; if (args2.Length < 2 || args2[1] == "list") { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { SharedMapServer.ManageMarker(0L, host: true, "list", string.Empty, string.Empty, Vector3.zero); } else { foreach (string item in SharedMapClient.MarkerDescriptions()) { args.Context.AddString(item); } } args.Context.AddString("sharedmap rename <id> <name> | move <id> <x> <z> | delete <id> | cleanup <playerID> | peers | bind <legacyPlayerID> <peerUID> (admin)"); } else { string text = args2[1].ToLowerInvariant(); if (text == "peers") { SharedMapNetwork.ManageMarker(text, string.Empty, string.Empty, Vector3.zero); } else if (args2.Length < 3) { args.Context.AddString("A public marker ID or character owner ID is required."); } else if (text == "bind" && args2.Length != 4) { args.Context.AddString("Use sharedmap bind <legacyPlayerID> <connectedPeerUID>; inspect sharedmap peers first."); } else { Vector3 zero = Vector3.zero; if (text == "move") { if (args2.Length != 5 || !float.TryParse(args2[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(args2[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { args.Context.AddString("Use sharedmap move <id> <x> <z>."); return; } ((Vector3)(ref zero))..ctor(result, 0f, result2); } SharedMapNetwork.ManageMarker(text, args2[2], string.Join(" ", args2.Skip(3)), zero); } } }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("sharedmap", "Public markers: list; rename <id> <name>; move <id> <x> <z>; delete <id>; cleanup <playerID>; peers; bind <legacyPlayerID> <peerUID> (last three require admin).", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } internal static class SharedMapExploration { internal static byte[] Pack(BitArray explored) { if (explored == null) { throw new ArgumentNullException("explored"); } byte[] array = new byte[(explored.Length + 7) / 8]; explored.CopyTo(array, 0); return array; } } internal sealed class SharedMapFogMask { private byte[] _pixels; internal int PixelCount { get; } internal SharedMapFogMask(int pixelCount) { if (pixelCount <= 0) { throw new ArgumentOutOfRangeException("pixelCount"); } PixelCount = pixelCount; _pixels = new byte[(pixelCount + 7) / 8]; } internal void Replace(byte[] pixels) { if (pixels == null || pixels.Length != _pixels.Length) { throw new ArgumentException("SharedMap exploration dimensions must match.", "pixels"); } _pixels = (byte[])pixels.Clone(); } internal bool Add(int index) { if (index < 0 || index >= PixelCount) { return false; } int num = index >> 3; byte b = (byte)(1 << (index & 7)); if ((_pixels[num] & b) != 0) { return false; } _pixels[num] |= b; return true; } internal bool Reveals(int index, bool vanillaExplored, bool vanillaVisible) { if (index < 0 || index >= PixelCount) { return false; } if (!(vanillaExplored && vanillaVisible)) { return (_pixels[index >> 3] & (1 << (index & 7))) != 0; } return true; } } internal static class SharedMapNetwork { private const int MaximumPackageBytes = 131072; private const int MaximumParticipationPayloadBytes = 2097160; private const int MaximumDeltaEntries = 16384; private const int MaximumMarkers = 5000; private const string ParticipationRpc = "com.jg224.sharedmap.Participation"; private const string DeltaRequestRpc = "com.jg224.sharedmap.ExplorationDeltaRequest"; private const string SnapshotRequestRpc = "com.jg224.sharedmap.SnapshotRequest"; private const string SnapshotRpc = "com.jg224.sharedmap.Snapshot"; private const string ExplorationSnapshotRpc = "com.jg224.sharedmap.ExplorationSnapshot"; private const string DeltaRpc = "com.jg224.sharedmap.ExplorationDelta"; private const string MarkerCreateRpc = "com.jg224.sharedmap.MarkerCreate"; private const string MarkerCheckedRpc = "com.jg224.sharedmap.MarkerChecked"; private const string MarkerDeleteRpc = "com.jg224.sharedmap.MarkerDelete"; private const string MarkerManageRpc = "com.jg224.sharedmap.MarkerManage"; private const string MarkerEventRpc = "com.jg224.sharedmap.MarkerEvent"; private const string NoticeRpc = "com.jg224.sharedmap.Notice"; private static readonly HashSet<int> ClientRequestHashes = new HashSet<int> { StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.Participation"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.ExplorationDeltaRequest"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.SnapshotRequest"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.MarkerCreate"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.MarkerChecked"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.MarkerDelete"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.MarkerManage") }; private static readonly HashSet<int> ServerEventHashes = new HashSet<int> { StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.Snapshot"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.ExplorationSnapshot"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.ExplorationDelta"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.MarkerEvent"), StringExtensionMethods.GetStableHashCode("com.jg224.sharedmap.Notice") }; private static readonly Dictionary<long, SharedMapTransfer> ParticipationTransfers = new Dictionary<long, SharedMapTransfer>(); private static readonly SharedMapTransfer SnapshotTransfer = new SharedMapTransfer(); private static readonly SharedMapTransfer ExplorationTransfer = new SharedMapTransfer(); private static readonly SharedMapSendQueue Outgoing = new SharedMapSendQueue(); private static readonly SharedMapContributionBudget Contributions = new SharedMapContributionBudget(); private static readonly List<long> ExpiredParticipationPeers = new List<long>(); private static readonly Func<long, int> SocketQueueReader = ReadSocketQueue; private static readonly Func<long, SharedMapOutboundFrame, bool> FrameSender = SendQueuedFrame; private static double _lastClientTransportActivity; private static double _nextResync; private static double _nextTransportWarning; private static double _nextSnapshotRequest; private static ZRoutedRpc _registeredInstance; private static long _nextTransferId; internal static bool TryGetRpcDirection(int methodHash, out bool serverToClient) { serverToClient = ServerEventHashes.Contains(methodHash); if (!serverToClient) { return ClientRequestHashes.Contains(methodHash); } return true; } internal static bool HasBoundedRoutedParameters(ZPackage package) { if (package.Size() - package.GetPos() < 4) { return false; } int num = package.ReadInt(); if (num < 4 || num > 131076 || num != package.Size() - package.GetPos()) { return false; } int num2 = package.ReadInt(); if (num2 >= 4 && SharedMapPayloadBounds.Allows(num2, package.Size() - package.GetPos(), 131072)) { return num2 == package.Size() - package.GetPos(); } return false; } internal static void Register(ZRoutedRpc rpc) { if (rpc != null && _registeredInstance != rpc) { ResetTransfers(); rpc.Register<ZPackage>("com.jg224.sharedmap.Participation", (Action<long, ZPackage>)OnParticipation); rpc.Register<ZPackage>("com.jg224.sharedmap.ExplorationDeltaRequest", (Action<long, ZPackage>)OnDeltaRequest); rpc.Register<ZPackage>("com.jg224.sharedmap.SnapshotRequest", (Action<long, ZPackage>)OnSnapshotRequest); rpc.Register<ZPackage>("com.jg224.sharedmap.Snapshot", (Action<long, ZPackage>)OnSnapshot); rpc.Register<ZPackage>("com.jg224.sharedmap.ExplorationSnapshot", (Action<long, ZPackage>)OnExplorationSnapshot); rpc.Register<ZPackage>("com.jg224.sharedmap.ExplorationDelta", (Action<long, ZPackage>)OnDelta); rpc.Register<ZPackage>("com.jg224.sharedmap.MarkerCreate", (Action<long, ZPackage>)OnMarkerCreate); rpc.Register<ZPackage>("com.jg224.sharedmap.MarkerChecked", (Action<long, ZPackage>)OnMarkerChecked); rpc.Register<ZPackage>("com.jg224.sharedmap.MarkerDelete", (Action<long, ZPackage>)OnMarkerDelete); rpc.Register<ZPackage>("com.jg224.sharedmap.MarkerManage", (Action<long, ZPackage>)OnMarkerManage); rpc.Register<ZPackage>("com.jg224.sharedmap.MarkerEvent", (Action<long, ZPackage>)OnMarkerEvent); rpc.Register<ZPackage>("com.jg224.sharedmap.Notice", (Action<long, ZPackage>)OnNotice); _registeredInstance = rpc; ManualLogSource log = SharedMapPlugin.Log; if (log != null) { log.LogInfo((object)$"Registered SharedMap routed RPC protocol {3}."); } } } internal static void Shutdown() { ResetTransfers(); _registeredInstance = null; } internal static void Tick(double now) { FlushOutgoing(now); if (SnapshotTransfer.Expire(now)) { ManualLogSource log = SharedMapPlugin.Log; if (log != null) { log.LogWarning((object)"Discarded an incomplete SharedMap snapshot transfer after a timeout."); } RequestResync(); } if (ExplorationTransfer.Expire(now)) { RequestResync(); } if (ParticipationTransfers.Count == 0) { return; } ExpiredParticipationPeers.Clear(); foreach (KeyValuePair<long, SharedMapTransfer> participationTransfer in ParticipationTransfers) { if (participationTransfer.Value.Expire(now)) { ExpiredParticipationPeers.Add(participationTransfer.Key); } } for (int i = 0; i < ExpiredParticipationPeers.Count; i++) { long num = ExpiredParticipationPeers[i]; ParticipationTransfers.Remove(num); ManualLogSource log2 = SharedMapPlugin.Log; if (log2 != null) { log2.LogWarning((object)$"Discarded an incomplete SharedMap participation transfer from peer {num} after a timeout."); } } } internal static void ForgetPeer(long peerUid) { if (peerUid != 0L) { ParticipationTransfers.Remove(peerUid); Contributions.Remove(peerUid); Outgoing.Remove(peerUid); } } internal static void ResetClientTransfer() { SnapshotTransfer.Reset(); ExplorationTransfer.Reset(); _lastClientTransportActivity = 0.0; } internal static void ResetConnectionTransfers() { ResetClientTransfer(); if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { Outgoing.Clear(); } _nextSnapshotRequest = 0.0; } internal static void ResetServerTransfers() { ParticipationTransfers.Clear(); Contributions.Clear(); Outgoing.Clear(); } internal static bool CanRetryParticipation(double now) { ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetServerPeer() : null); return SharedMapRetryPolicy.Allows(now, _lastClientTransportActivity, val != null && Outgoing.HasPending(val.m_uid), SnapshotTransfer.HasActiveTransfer); } internal static bool SendParticipation(bool enabled, int mapSize, byte[] snapshot) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown if (!TryPrepareClient(out var znet, out var rpc)) { return false; } if (znet.IsServer()) { SharedMapServer.SetHostParticipation(enabled, mapSize, snapshot); return true; } ZNetPeer serverPeer = znet.GetServerPeer(); if (serverPeer == null) { return false; } try { if (!enabled) { Outgoing.Remove(serverPeer.m_uid); ZPackage val = NewPackage(); val.Write(false); return InvokeBounded(rpc, serverPeer.m_uid, "com.jg224.sharedmap.Participation", val); } if (mapSize < 256 || mapSize > 4096 || snapshot == null || snapshot.Length != MapAccess.PackedLength(mapSize)) { throw new InvalidOperationException("Invalid local exploration snapshot dimensions."); } ZPackage val2 = new ZPackage(); val2.Write(mapSize); val2.Write(snapshot); Outgoing.RemoveMethod(serverPeer.m_uid, "com.jg224.sharedmap.Participation"); bool num = SendTransfer(rpc, serverPeer.m_uid, "com.jg224.sharedmap.Participation", val2.GetArray(), writeParticipationFlag: true); if (num) { _lastClientTransportActivity = Time.unscaledTimeAsDouble; } return num; } catch (Exception ex) { ManualLogSource log = SharedMapPlugin.Log; if (log != null) { log.LogWarning((object)("Could not send SharedMap participation to the server: " + ex.Message)); } return false; } } internal static bool SendExplorationDelta(int mapSize, IReadOnlyList<int> indices) { if (indices == null || indices.Count == 0 || indices.Count > 16384 || !TryPrepareClient(out var znet, out var rpc)) { return false; } if (znet.IsServer()) { SharedMapServer.ReceiveHostDelta(mapSize, indices); return true; } ZNetPeer serverPeer = znet.GetServerPeer(); if (serverPeer == null) { return false; } ZPackage package = NewPackage(); WriteIndices(package, mapSize, indices); return InvokeBounded(rpc, serverPeer.m_uid, "com.jg224.sharedmap.ExplorationDeltaRequest", package); } internal static void RequestMarkerCreate(PinType type, Vector3 position, string name) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected I4, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!TryPrepareClient(out var znet, out var rpc)) { return; } if (znet.IsServer()) { SharedMapServer.RequestCreateHost(type, position, name); return; } ZNetPeer serverPeer = znet.GetServerPeer(); if (serverPeer != null) { ZPackage val = NewPackage(); val.Write((int)type); val.Write(position); val.Write(name ?? string.Empty); InvokeBounded(rpc, serverPeer.m_uid, "com.jg224.sharedmap.MarkerCreate", val); } } internal static void RequestMarkerChecked(string markerId, bool isChecked) { if (!TryPrepareClient(out var znet, out var rpc)) { return; } if (znet.IsServer()) { SharedMapServer.RequestCheckedHost(markerId, isChecked); return; } ZNetPeer serverPeer = znet.GetServerPeer(); if (serverPeer != null) { ZPackage val = NewPackage(); val.Write(markerId ?? string.Empty); val.Write(isChecked); InvokeBounded(rpc, serverPeer.m_uid, "com.jg224.sharedmap.MarkerChecked", val); } } internal static void RequestMarkerDelete(string markerId) { if (!TryPrepareClient(out var znet, out var rpc)) { return; } if (znet.IsServer()) { SharedMapServer.RequestDeleteHost(markerId); return; } ZNetPeer serverPeer = znet.GetServerPeer(); if (serverPeer != null) { ZPackage val = NewPackage(); val.Write(markerId ?? string.Empty); InvokeBounded(rpc, serverPeer.m_uid, "com.jg224.sharedmap.MarkerDelete", val); } } internal static void ManageMarker(string action, string id, string value, Vector3 position) { //IL_001a: 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) if (!TryPrepareClient(out var znet, out var rpc)) { return; } if (znet.IsServer()) { SharedMapServer.ManageMarker(0L, host: true, action, id, value, position); return; } ZNetPeer serverPeer = znet.GetServerPeer(); if (serverPeer != null) { ZPackage val = NewPackage(); val.Write(Bound(action, 16)); val.Write(Bound(id, 32)); val.Write(Bound(value, 64)); val.Write(position); InvokeBounded(rpc, serverPeer.m_uid, "com.jg224.sharedmap.MarkerManage", val); } } private static void OnMarkerManage(long sender, ZPackage package) { //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_0038: Unknown result type (might be due to invalid IL or missing references) if (!IsServerRequest(sender, package)) { return; } try { string action = ReadBoundedString(package, 16); string id = ReadBoundedString(package, 32); string value = ReadBoundedString(package, 64); Vector3 position = package.ReadVector3(); RequireConsumed(package); SharedMapServer.ManageMarker(sender, host: false, action, id, value, position); } catch (Exception exception) { Reject("marker management", sender, exception); } } internal static bool BroadcastSnapshot(IEnumerable<long> peers, long worldUid, int mapSize, byte[] exploration, IReadOnlyList<PublicMarker> markers) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown if (ZRoutedRpc.instance == null) { return false; } SharedMapOutboundMessage message; try { ZPackage val = new ZPackage(); val.Write(worldUid); val.Write(mapSize); val.Write(exploration ?? Array.Empty<byte>()); val.Write(markers.Count); for (int i = 0; i < markers.Count; i++) { WriteMarker(val, markers[i]); } message = new SharedMapOutboundMessage("com.jg224.sharedmap.Snapshot", val.GetArray(), NextTransferId()); } catch (Exception ex) { ManualLogSource log = SharedMapPlugin.Log; if (log != null) { log.LogWarning((object)("Could not prepare a bounded SharedMap snapshot: " + ex.Message)); } return false; } bool flag = true; foreach (long item in SnapshotPeers(peers)) { try { flag &= Outgoing.Enqueue(item, message, authoritativeSnapshot: true, resyncOnOverflow: true); } catch (Exception ex2) { ManualLogSource log2 = SharedMapPlugin.Log; if (log2 != null) { log2.LogWarning((object)$"Could not send SharedMap snapshot to peer {item}: {ex2.Message}"); } flag = false; } } return flag; } internal static void BroadcastExplorationSnapshot(IEnumerable<long> peers, long worldUid, int mapSize, byte[] exploration) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if (ZRoutedRpc.instance == null || exploration == null) { return; } ZPackage val = new ZPackage(); val.Write(worldUid); val.Write(mapSize); val.Write(exploration); SharedMapOutboundMessage message = new SharedMapOutboundMessage("com.jg224.sharedmap.ExplorationSnapshot", val.GetArray(), NextTransferId()); foreach (long item in SnapshotPeers(peers)) { Outgoing.Enqueue(item, message, authoritativeSnapshot: false, resyncOnOverflow: true); } } internal static void BroadcastExplorationDelta(IEnumerable<long> peers, long worldUid, int mapSize, IReadOnlyList<int> indices) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null || indices == null || indices.Count == 0) { return; } foreach (long item in SnapshotPeers(peers)) { ZPackage val = NewPackage(); val.Write(worldUid); WriteIndices(val, mapSize, indices); InvokeBounded(instance, item, "com.jg224.sharedmap.ExplorationDelta", val); } } internal static void BroadcastMarker(IEnumerable<long> peers, PublicMarker marker) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null || marker == null) { return; } foreach (long item in SnapshotPeers(peers)) { ZPackage val = NewPackage(); val.Write(1); WriteMarker(val, marker); InvokeBounded(instance, item, "com.jg224.sharedmap.MarkerEvent", val); } } internal static void BroadcastMarkerRemoval(IEnumerable<long> peers, string markerId, long revision) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return; } foreach (long item in SnapshotPeers(peers)) { ZPackage val = NewPackage(); val.Write(2); val.Write(markerId ?? string.Empty); val.Write(revision); InvokeBounded(instance, item, "com.jg224.sharedmap.MarkerEvent", val); } } internal static void SendNotice(long peerUid, string message) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { ZPackage val = NewPackage(); val.Write(Bound(message, 256)); InvokeBounded(instance, peerUid, "com.jg224.sharedmap.Notice", val); } } private static void OnParticipation(long sender, ZPackage package) { //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_0173: Expected O, but got Unknown if (!IsServerRequest(sender, package)) { return; } try { if (!package.ReadBool()) { RequireConsumed(package); ParticipationTransfers.Remove(sender); Outgoing.Remove(sender); SharedMapServer.SetRemoteParticipation(sender, enabled: false, 0, Array.Empty<byte>()); return; } long transferId = package.ReadLong(); int num = package.ReadInt(); int chunkCount = package.ReadInt(); int chunkIndex = package.ReadInt(); if (!Contributions.Accept(sender, transferId, package.Size(), Time.unscaledTimeAsDouble)) { return; } byte[] data = ReadBoundedBytes(package, 32768); RequireConsumed(package); if (num > 2097160) { throw new InvalidOperationException("SharedMap participation payload exceeds its limit."); } if (!ParticipationTransfers.TryGetValue(sender, out var value)) { if (ParticipationTransfers.Count >= 128) { return; } value = new SharedMapTransfer(); ParticipationTransfers.Add(sender, value); } long num2 = num; foreach (KeyValuePair<long, SharedMapTransfer> participationTransfer in ParticipationTransfers) { if (participationTransfer.Key != sender) { num2 += participationTransfer.Value.ExpectedLength; } } if (num2 <= 33554432 && value.Accept(transferId, num, chunkCount, chunkIndex, data, Time.unscaledTimeAsDouble, out var payload) == SharedMapTransferResult.Completed) { ZPackage val = new ZPackage(payload); int mapSize = val.ReadInt(); byte[] snapshot = ReadBoundedBytes(val, 2097152); RequireConsumed(val); SharedMapServer.SetRemoteParticipation(sender, enabled: true, mapSize, snapshot); } } catch (Exception exception) { ParticipationTransfers.Remove(sender); Reject("participation", sender, exception); } } private static void OnDeltaRequest(long sender, ZPackage package) { if (!IsServerRequest(sender, package) || !Contributions.Accept(sender, 0L, package.Size(), Time.unscaledTimeAsDouble, delta: true)) { return; } try { ReadIndices(package, out var mapSize, out var indices); RequireConsumed(package); SharedMapServer.ReceiveRemoteDelta(sender, mapSize, indices); } catch (Exception exception) { Reject("exploration delta", sender, exception); } } private static void OnSnapshot(long sender, ZPackage package) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown if (!IsTrustedServer(sender, package)) { return; } try { ReadTransferChunk(package, out var transferId, out var totalLength, out var chunkCount, out var chunkIndex, out var data); RequireConsumed(package); byte[] payload; SharedMapTransferResult num = SnapshotTransfer.Accept(transferId, totalLength, chunkCount, chunkIndex, data, Time.unscaledTimeAsDouble, out payload); if (num != SharedMapTransferResult.Duplicate) { _lastClientTransportActivity = Time.unscaledTimeAsDouble; } if (num != SharedMapTransferResult.Completed) { return; } ZPackage val = new ZPackage(payload); long worldUid = val.ReadLong(); int num2 = val.ReadInt(); byte[] array = ReadBoundedBytes(val, 2097152); if (num2 < 256 || num2 > 4096 || array.Length != MapAccess.PackedLength(num2)) { throw new InvalidOperationException("Invalid exploration snapshot dimensions."); } int num3 = val.ReadInt(); if (num3 < 0 || num3 > 5000) { throw new InvalidOperationException("Invalid marker count."); } List<PublicMarker> list = new List<PublicMarker>(num3); HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); for (int i = 0; i < num3; i++) { PublicMarker publicMarker = ReadMarker(val); if (!hashSet.Add(publicMarker.Id)) { throw new InvalidOperationException("Duplicate public marker ID."); } list.Add(publicMarker); } RequireConsumed(val); ExplorationTransfer.Reset(); SharedMapClient.ReceiveSnapshot(worldUid, num2, array, list); } catch (Exception exception) { SnapshotTransfer.Reset(); Reject("snapshot", sender, exception); RequestResync(); } } private static void OnExplorationSnapshot(long sender, ZPackage package) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0075: Expected O, but got Unknown //IL_007c: Expected O, but got Unknown if (!IsTrustedServer(sender, package)) { return; } try { ReadTransferChunk(package, out var transferId, out var totalLength, out var chunkCount, out var chunkIndex, out var data); RequireConsumed(package); if (totalLength > 2097168) { throw new InvalidOperationException("SharedMap exploration payload exceeds its limit."); } if (ExplorationTransfer.Accept(transferId, totalLength, chunkCount, chunkIndex, data, Time.unscaledTimeAsDouble, out var payload) == SharedMapTransferResult.Completed) { ZPackage val = new ZPackage(payload); long worldUid = val.ReadLong(); int num = val.ReadInt(); byte[] array = ReadBoundedBytes(val, 2097152); RequireConsumed(val); if (num < 256 || num > 4096 || array.Length != MapAccess.PackedLength(num)) { throw new InvalidOperationException("Invalid exploration snapshot dimensions."); } SharedMapClient.ReceiveExplorationSnapshot(worldUid, num, array); } } catch (Exception exception) { ExplorationTransfer.Reset(); Reject("exploration snapshot", sender, exception); RequestResync(); } } private static void OnSnapshotRequest(long sender, ZPackage package) { if (!IsServerRequest(sender, package)) { return; } try { RequireConsumed(package); if (Contributions.Accept(sender, 0L, package.Size(), Time.unscaledTimeAsDouble, delta: false, restart: true)) { SharedMapServer.TrySendResync(sender); } } catch (Exception exception) { Reject("snapshot request", sender, exception); } } private static void RequestResync() { double unscaledTimeAsDouble = Time.unscaledTimeAsDouble; ZNet instance = ZNet.instance; ZNetPeer val = (((Object)(object)instance == (Object)null || instance.IsServer()) ? null : instance.GetServerPeer()); if (val != null && SharedMapClient.Sharing && !(unscaledTimeAsDouble < _nextSnapshotRequest) && InvokeBounded(ZRoutedRpc.instance, val.m_uid, "com.jg224.sharedmap.SnapshotRequest", NewPackage())) { _nextSnapshotRequest = unscaledTimeAsDouble + 120.0; } } private static void OnDelta(long sender, ZPackage package) { if (!IsTrustedServer(sender, package)) { return; } try { long worldUid = package.ReadLong(); ReadIndices(package, out var mapSize, out var indices); RequireConsumed(package); SharedMapClient.ReceiveExplorationDelta(worldUid, mapSize, indices); } catch (Exception exception) { Reject("server exploration delta", sender, exception); } } private static void OnMarkerCreate(long sender, ZPackage package) { //IL_0011: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!IsServerRequest(sender, package)) { return; } try { PinType type = (PinType)package.ReadInt(); Vector3 position = package.ReadVector3(); string name = ReadBoundedString(package, 64); RequireConsumed(package); SharedMapServer.RequestCreateRemote(sender, type, position, name); } catch (Exception exception) { Reject("marker creation", sender, exception); } } private static void OnMarkerChecked(long sender, ZPackage package) { if (!IsServerRequest(sender, package)) { return; } try { string markerId = ReadMarkerId(package); bool isChecked = package.ReadBool(); RequireConsumed(package); SharedMapServer.RequestCheckedRemote(sender, markerId, isChecked); } catch (Exception exception) { Reject("marker X update", sender, exception); } } private static void OnMarkerDelete(long sender, ZPackage package) { if (!IsServerRequest(sender, package)) { return; } try { string markerId = ReadMarkerId(package); RequireConsumed(package); SharedMapServer.RequestDeleteRemote(sender, markerId); } catch (Exception exception) { Reject("marker deletion", sender, exception); } } private static void OnMarkerEvent(long sender, ZPackage package) { if (!IsTrustedServer(sender, package)) { return; } try { switch (package.ReadInt()) { case 1: SharedMapClient.UpsertMarker(ReadMarker(package)); break; case 2: { string markerId = ReadMarkerId(package); package.ReadLong(); SharedMapClient.RemoveMarker(markerId); break; } default: throw new InvalidOperationException("Invalid marker event operation."); } RequireConsumed(package); } catch (Exception exception) { Reject("marker event", sender, exception); } } private static void OnNotice(long sender, ZPackage package) { if (!IsTrustedServer(sender, package)) { return; } try { string message = ReadBoundedString(package, 256); RequireConsumed(package); SharedMapClient.ShowMessage(message); } catch (Exception exception) { Reject("notice", sender, exception); } } private static ZPackage NewPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(3); return val; } private static bool IsServerRequest(long sender, ZPackage package) { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || !instance.IsServer() || !IsBounded(package)) { return false; } ZNetPeer peer = instance.GetPeer(sender); if (peer != null && peer.m_uid == sender) { return ReadProtocol(package); } return false; } private static bool IsTrustedServer(long sender, ZPackage package) { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || instance.IsServer() || !IsBounded(package)) { return false; } ZNetPeer serverPeer = instance.GetServerPeer(); if (serverPeer != null && sender == serverPeer.m_uid) { return ReadProtocol(package); } return false; } private static bool ReadProtocol(ZPackage package) { try { int num = package.ReadInt(); if (num == 3) { return true; } ManualLogSource log = SharedMapPlugin.Log; if (log != null) { log.LogWarning((object)$"Ignored SharedMap protocol {num}; expected {3}."); } } catch (Exception ex) { ManualLogSource log2 = SharedMapPlugin.Log; if (log2 != null) { log2.LogWarning((object)("Ignored malformed SharedMap protocol header: " + ex.Message)); } } return false; } private static bool IsBounded(ZPackage package) { if (package != null && package.Size() > 0) { return package.Size() <= 131072; } return false; } private static bool SendTransfer(ZRoutedRpc rpc, long peerUid, string rpcName, byte[] payload, bool writeParticipationFlag) { if (rpc == null) { return false; } return Outgoing.Enqueue(peerUid, new SharedMapOutboundMessage(rpcName, payload, NextTransferId(), writeParticipationFlag)); } private static void WriteTransferChunk(ZPackage package, SharedMapTransferChunk chunk) { package.Write(chunk.TransferId); package.Write(chunk.TotalLength); package.Write(chunk.ChunkCount); package.Write(chunk.ChunkIndex); package.Write(chunk.Data); } private static void ReadTransferChunk(ZPackage package, out long transferId, out int totalLength, out int chunkCount, out int chunkIndex, out byte[] data) { transferId = package.ReadLong(); totalLength = package.ReadInt(); chunkCount = package.ReadInt(); chunkIndex = package.ReadInt(); data = ReadBoundedBytes(package, 32768); } private static byte[] ReadBoundedBytes(ZPackage package, int maximum) { if (package.Size() - package.GetPos() < 4) { throw new InvalidOperationException("SharedMap byte-array length is missing."); } int num = package.ReadInt(); if (!SharedMapPayloadBounds.Allows(num, package.Size() - package.GetPos(), maximum)) { throw new InvalidOperationException("SharedMap byte-array length exceeds its payload or limit."); } return package.ReadByteArray(num); } private static bool InvokeBounded(ZRoutedRpc rpc, long peerUid, string rpcName, ZPackage package) { if (rpc == null) { throw new InvalidOperationException("SharedMap routed RPC is unavailable."); } if (!IsBounded(package)) { throw new InvalidOperationException($"SharedMap refused to enqueue an RPC larger than {131072} bytes."); } return Outgoing.Enqueue(peerUid, new SharedMapOutboundMessage(rpcName, package.GetArray(), 0L), authoritativeSnapshot: false, (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()); } private static void FlushOutgoing(double now) { ZNet instance = ZNet.instance; ZRoutedRpc instance2 = ZRoutedRpc.instance; if ((Object)(object)instance == (Object)null || instance2 == null) { return; } if (now >= _nextResync) { _nextResync = now + 1.0; long[] array = Outgoing.PeerIds(); foreach (long num in array) { if (instance.GetPeer(num) == null) { ForgetPeer(num); } } if (instance.IsServer()) { array = Outgoing.ResyncPeers(); for (int i = 0; i < array.Length; i++) { SharedMapServer.TrySendResync(array[i]); } } } Outgoing.Flush(now, SocketQueueReader, FrameSender); } private static int ReadSocketQueue(long peerUid) { try { ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetPeer(peerUid) : null); object obj = val?.m_socket; if (obj == null) { if (val == null) { obj = null; } else { ZRpc rpc = val.m_rpc; obj = ((rpc != null) ? rpc.GetSocket() : null); } } ISocket val2 = (ISocket)obj; if (val2 == null || !val2.IsConnected()) { return -1; } return SharedMapSocketBudget.ActualBytes(val2.GetSendQueueSize(), val2 is ZPlayFabSocket); } catch { return -1; } } private static bool SendQueuedFrame(long peerUid, SharedMapOutboundFrame frame) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown double unscaledTimeAsDouble = Time.unscaledTimeAsDouble; ZNet instance = ZNet.instance; ZRoutedRpc instance2 = ZRoutedRpc.instance; if ((Object)(object)instance == (Object)null || instance2 == null) { return false; } try { ZPackage val; if (frame.Message.TransferId == 0L) { val = new ZPackage(frame.Message.Payload); } else { val = NewPackage(); if (frame.Message.Participation) { val.Write(true); } byte[] array = new byte[frame.Length]; Buffer.BlockCopy(frame.Message.Payload, frame.Offset, array, 0, array.Length); WriteTransferChunk(val, new SharedMapTransferChunk(frame.Message.TransferId, frame.Message.Payload.Length, frame.Message.FrameCount, frame.Index, array)); } if (!IsBounded(val)) { throw new InvalidOperationException("SharedMap queued frame exceeds its limit."); } instance2.InvokeRoutedRPC(peerUid, frame.Message.Method, new object[1] { val }); if (!instance.IsServer()) { _lastClientTransportActivity = unscaledTimeAsDouble; } return true; } catch (Exception ex) { if (unscaledTimeAsDouble >= _nextTransportWarning) { _nextTransportWarning = unscaledTimeAsDouble + 30.0; ManualLogSource log = SharedMapPlugin.Log; if (log != null) { log.LogWarning((object)("SharedMap transport is waiting to retry: " + ex.Message)); } } return false; } } private static long NextTransferId() { long num = Interlocked.Increment(ref _nextTransferId); if (num > 0) { return num; } Interlocked.Exchange(ref _nextTransferId, 0L); return Interlocked.Increment(ref _nextTransferId); } private static void ResetTransfers() { ParticipationTransfers.Clear(); SnapshotTransfer.Reset(); ExplorationTransfer.Reset(); Contributions.Clear(); Outgoing.Clear(); _lastClientTransportActivity = 0.0; _nextResync = 0.0; _nextSnapshotRequest = 0.0; _nextTransportWarning = 0.0; } private static bool TryPrepareClient(out ZNet znet, out ZRoutedRpc rpc) { znet = ZNet.instance; rpc = ZRoutedRpc.instance; if ((Object)(object)znet != (Object)null) { return rpc != null; } return false; } private static void WriteIndices(ZPackage package, int mapSize, IReadOnlyList<int> indices) { package.Write(mapSize); package.Write(indices.Count); for (int i = 0; i < indices.Count; i++) { package.Write(indices[i]); } } private static void ReadIndices(ZPackage package, out int mapSize, out List<int> indices) { mapSize = package.ReadInt(); if (mapSize < 256 || mapSize > 4096) { throw new InvalidOperationException("Invalid map size."); } int num = package.ReadInt(); if (num < 0 || num > 16384) { throw new InvalidOperationException("Invalid exploration delta count."); } int num2 = checked(mapSize * mapSize); indices = new List<int>(num); for (int i = 0; i < num; i++) { int num3 = package.ReadInt(); if (num3 < 0 || num3 >= num2) { throw new InvalidOperationException("Invalid map index."); } indices.Add(num3); } } private static void WriteMarker(ZPackage package, PublicMarker marker) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected I4, but got Unknown package.Write(marker.Id); package.Write(marker.OwnerPlayerId); package.Write(marker.OwnerName ?? string.Empty); package.Write(marker.Position); package.Write((int)marker.Type); package.Write(marker.Name ?? string.Empty); package.Write(marker.Checked); package.Write(marker.Revision); } private static PublicMarker ReadMarker(ZPackage package) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) PublicMarker publicMarker = new PublicMarker { Id = ReadMarkerId(package), OwnerPlayerId = package.ReadLong(), OwnerName = ReadBoundedString(package, 64), Position = package.ReadVector3(), Type = (PinType)package.ReadInt(), Name = ReadBoundedString(package, 64), Checked = package.ReadBool(), Revision = package.ReadLong() }; if (publicMarker.OwnerPlayerId == 0L || !IsPublicMarkerType(publicMarker.Type) || !IsFinite(publicMarker.Position)) { throw new InvalidOperationException("Invalid public marker record."); } return publicMarker; } private static string ReadMarkerId(ZPackage package) { string obj = package.ReadString() ?? string.Empty; if (obj.Length != 32) { throw new InvalidOperationException("Invalid public marker ID."); } return obj; } private static string ReadBoundedString(ZPackage package, int maximum) { string obj = package.ReadString() ?? string.Empty; if (obj.Length > maximum) { throw new InvalidOperationException("SharedMap string exceeds its limit."); } return obj; } private static bool IsPublicMarkerType(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; } private static bool IsFinite(Vector3 value) { //IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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) if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z)) { return !float.IsInfinity(value.z); } return false; } private static List<long> SnapshotPeers(IEnumerable<long> peers) { if (peers != null) { return new List<long>(peers); } return new List<long>(); } private static string Bound(string value, int maximum) { value = value ?? string.Empty; if (value.Length > maximum) { return value.Substring(0, maximum); } return value; } private static void RequireConsumed(ZPackage package) { if (package.GetPos() != package.Size()) { throw new InvalidOperationException("Unexpected trailing SharedMap data."); } } private static void Reject(string label, long sender, Exception exception) { ManualLogSource log = SharedMapPlugin.Log; if (log != null) { log.LogWarning((object)$"Rejected SharedMap {label} from peer {sender}: {exception.Message}"); } } } internal static class SharedMapOwnership { internal const int MaximumCharacters = 100000; internal const int MaximumCharactersPerAccount = 128; internal const string LocalHostAccount = "local-host"; internal static bool TryAccountKey(string transport, string authenticatedHost, out string key) { key = string.Empty; string text = ((transport == "ZSteamSocket") ? "steam:" : ((transport == "ZPlayFabSocket") ? "playfab:" : null)); if (text == null || string.IsNullOrWhiteSpace(authenticatedHost) || authenticatedHost.Length > 256 || string.Equals(authenticatedHost, "None", StringComparison.OrdinalIgnoreCase)) { return false; } if (transport == "ZSteamSocket" && (!ulong.TryParse(authenticatedHost, out var result) || result == 0L)) { return false; } if (transport == "ZPlayFabSocket" && (!authenticatedHost.StartsWith("playfab/", StringComparison.Ordinal) || authenticatedHost.Length <= 8)) { return false; } foreach (char c in authenticatedHost) { if (char.IsControl(c) || char.IsWhiteSpace(c)) { return false; } } using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(authenticatedHost)); key = text + BitConverter.ToString(array).Replace("-", string.Empty).ToLowerInvariant(); return true; } internal static bool IsAccountKey(string key) { if (key == "local-host") { return true; } if (key == null) { return false; } int num = (key.StartsWith("steam:", StringComparison.Ordinal) ? 6 : (key.StartsWith("playfab:", StringComparison.Ordinal) ? 8 : 0)); if (num == 0 || key.Length != num + 64) { return false; } for (int i = num; i < key.Length; i++) { if ((key[i] < '0' || key[i] > '9') && (key[i] < 'a' || key[i] > 'f')) { return false; } } return true; } internal static bool CanManage(string owner, string actor, bool administrator) { if (!administrator) { if (IsAccountKey(actor)) { return string.Equals(owner, actor, StringComparison.Ordinal); } return false; } return true; } internal static bool CanCreateMarker(IEnumerable<string> markerOwners, string account) { if (!IsAccountKey(account)) { return false; } int num = 0; int num2 = 0; foreach (string markerOwner in markerOwners) { num++; if (markerOwner == account) { num2++; } if (num >= 5000 || num2 >= 200) { return false; } } return true; } internal static bool IsAdministrator(string transport, bool platformClaimIsAdmin, bool authenticatedEndpointIsAdmin) { if (!(transport == "ZSteamSocket")) { return transport == "ZPlayFabSocket" && authenticatedEndpointIsAdmin; } return platformClaimIsAdmin; } internal static bool TryClaimCharacter(SharedMapPlayerClaims claims, Dictionary<long, string> registry, long peer, long player, long hostPlayer, string account) { if (!IsAccountKey(account) || (registry.TryGetValue(player, out var value) && value.Length != 0 && value != account)) { return false; } return claims.Accept(peer, player, hostPlayer); } internal static bool TryRegister(Dictionary<long, string> registry, long playerId, string account, out bool changed, out bool legacy, out string error) { changed = false; legacy = false; error = string.Empty; if (playerId == 0L || !IsAccountKey(account)) { error = "SharedMap requires an authenticated Steam or PlayFab account."; return false; } if (registry.TryGetValue(playerId, out var value)) { legacy = value.Length == 0; if (legacy || string.Equals(value, account, StringComparison.Ordinal)) { return true; } error = "This SharedMap character ID is registered to a different authenticated account. Ask a server administrator for help."; return false; } int num = 0; foreach (string value2 in registry.Values) { if (value2 == account) { num++; } } if (registry.Count >= 100000 || num >= 128) { error = "The SharedMap character registration limit has been reached."; return false; } registry.Add(playerId, account); changed = true; return true; } internal static bool TryBindLegacy(Dictionary<long, string> registry, long playerId, string account, bool administrator, out string error) { error = string.Empty; if (!administrator || !IsAccountKey(account)) { error = "Legacy ownership binding requires a server administrator and an authenticated connected account."; return false; } if (!registry.TryGetValue(playerId, out var value) || value.Length != 0) { error = "Only an unbound legacy character ID can be bound; existing account ownership cannot be reassigned."; return false; } registry[playerId] = account; return true; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class SharedMapZNetAwakePatch { [HarmonyPostfix] private static void Postfix() { SharedMapClient.ResetConnection(); SharedMapNetwork.Register(ZRoutedRpc.instance); } } [HarmonyPatch(typeof(Game), "Awake")] internal static class SharedMapGameAwakePatch { [HarmonyPostfix] private static void Postfix() { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { SharedMapServer.LoadForCurrentWorld(); } } } [HarmonyPatch(typeof(Game), "OnDestroy")] internal static class SharedMapGameDestroyPatch { [HarmonyPrefix] private static void Prefix() { SharedMapServer.Shutdown(); SharedMapClient.ResetSession(); } } [HarmonyPatch(typeof(ZNet), "Shutdown", new Type[] { typeof(bool) })] internal static class SharedMapZNetShutdownPatch { [HarmonyPrefix] private static void Prefix(ZNet __instance) { if (__instance.IsServer()) { SharedMapServer.Shutdown(); } } } [HarmonyPatch(typeof(ZNet), "Disconnect", new Type[] { typeof(ZNetPeer) })] internal static class SharedMapDisconnectPatch { [HarmonyPrefix] private static void Prefix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { SharedMapServer.RemoveParticipant(peer?.m_uid ?? 0); } else { SharedMapClient.ResetConnection(); } } } [HarmonyPatch(typeof(Minimap), "Start")] internal static class SharedMapMinimapStartPatch { [HarmonyPostfix] private static void Postfix(Minimap __instance) { SharedMapUi.Ensure(__instance); } } [HarmonyPatch(typeof(Minimap), "OnDestroy")] internal static class SharedMapMinimapDestroyPatch { [HarmonyPrefix] private static void Prefix(Minimap __instance) { SharedMapClient.OnMinimapDestroyed(__instance); } } [HarmonyPatch(typeof(Minimap), "UpdatePins")] internal static class SharedMapUpdatePinsPatch { [HarmonyPostfix] private static void Postfix(Minimap __instance) { SharedMapClient.TintPublicPins(__instance); } } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(int), typeof(int) })] internal static class SharedMapExplorePixelPatch { [HarmonyPostfix] private static void Postfix(Minimap __instance, int x, int y, bool __result) { SharedMapClient.RecordLocalExploration(__instance, x, y, __result); } } [HarmonyPatch(typeof(Minimap), "ExploreOthers", new Type[] { typeof(int), typeof(int) })] internal static class SharedMapVanillaSharedPixelPatch { [HarmonyPostfix] private static void Postfix(Minimap __instance, int x, int y) { MapAccess.AfterVanillaSharedPixel(__instance, x, y); } } [HarmonyPatch(typeof(Minimap), "Update")] internal static class SharedMapFogPresentationPatch { [HarmonyPostfix] private static void Postfix(Minimap __instance, bool ___m_showSharedMapData, float ___m_sharedMapDataFade) { MapAccess.RefreshSharedPresentation(__instance, ___m_showSharedMapData, ___m_sharedMapDataFade); } } [HarmonyPatch] internal static class SharedMapFogResetPatch { [HarmonyTargetMethods] private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Minimap), "Reset", Type.EmptyTypes, (Type[])null); yield return AccessTools.Method(typeof(Minimap), "ResetSharedMapData", Type.EmptyTypes, (Type[])null); yield return AccessTools.Method(typeof(Minimap), "ResetAndExplore", new Type[2] { typeof(byte[]), typeof(byte[]) }, (Type[])null); yield return AccessTools.Method(typeof(Minimap), "OnToggleSharedMapData", Type.EmptyTypes, (Type[])null); } [HarmonyPostfix] private static void Postfix(Minimap __instance) { MapAccess.RecomposeSharedFog(__instance); } } [HarmonyPatch(typeof(Minimap), "SetMapData", new Type[] { typeof(byte[]) })] internal static class SharedMapVanillaMapLoadedPatch { [HarmonyPostfix] private static void Postfix(Minimap __instance) { SharedMapClient.AfterVanillaMapLoaded(__instance); } } [HarmonyPatch(typeof(Minimap), "SelectIcon", new Type[] { typeof(PinType) })] internal static class SharedMapSelectIconPatch { [HarmonyPostfix] private static void Postfix() { SharedMapUi.OnVanillaIconSelected(); } } [HarmonyPatch(typeof(Minimap), "ShowPinNameInput", new Type[] { typeof(Vector3) })] internal static class SharedMapShowPinNamePatch { [HarmonyPostfix] private static void Postfix(Minimap __instance) { SharedMapClient.AfterShowPinNameInput(__instance); } } [HarmonyPatch(typeof(Minimap), "OnPinTextEntered", new Type[] { typeof(string) })] internal static class SharedMapPinTextPatch { [HarmonyPrefix] private static void Prefix(Minimap __instance, out PinData __state) { __state = SharedMapClient.BeforePinTextEntered(__instance); } [HarmonyPostfix] private static void Postfix(Minimap __instance, PinData __state) { SharedMapClient.AfterPinTextEntered(__instance, __state); } } [HarmonyPatch(typeof(Minimap), "HidePinTextInput", new Type[] { typeof(bool) })] internal static class SharedMapHidePinTextPatch { [HarmonyPrefix] private static void Prefix(Minimap __instance) { SharedMapClient.BeforeHidePinTextInput(__instance); } } [HarmonyPatch(typeof(Minimap), "OnMapLeftClick")] internal static class SharedMapLeftClickPatch { [HarmonyPrefix] private static void Prefix(Minimap __instance, out SharedMapClient.MarkerCheckState __state) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) __state = SharedMapClient.CaptureClosestPublicCheck(__instance, ZInput.pointerPosition); } [HarmonyPostfix] private static void Postfix(SharedMapClient.MarkerCheckState __state) { SharedMapClient.SubmitCheckChange(__state); } } [HarmonyPatch(typeof(Minimap), "UpdateMap", new Type[] { typeof(Player), typeof(float), typeof(bool) })] internal static class SharedMapUpdateMapPatch { [HarmonyPrefix] private static void Prefix(Minimap __instance, bool takeInput, out SharedMapClient.MarkerCheckState __state) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) __state = ((takeInput && (int)__instance.m_mode == 2 && ZInput.GetButtonDown("JoyTabLeft")) ? SharedMapClient.CaptureClosestPublicCheck(__instance, new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2))) : default(SharedMapClient.MarkerCheckState)); } [HarmonyPostfix] private static void Postfix(SharedMapClient.MarkerCheckState __state) { SharedMapClient.SubmitCheckChange(__state); } } [HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(Vector3), typeof(float) })] internal static class SharedMapRemovePinAtPatch { [HarmonyPrefix] private static bool Prefix(Minimap __instance, Vector3 pos, float radius, ref bool __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (!SharedMapClient.TryHandleRemoveAt(__instance, pos, radius, out var result)) { return true; } __result = result; return false; } } [HarmonyPatch(typeof(Minimap), "GetMapData")] internal static class SharedMapPrivateSerializationPatch { [HarmonyPrefix] private static void Prefix(out SharedMapClient.PinSaveState __state) { __state = SharedMapClient.SuspendPublicPinsForSerialization(); } [HarmonyPostfix] private static void Postfix(SharedMapClient.PinSaveState __state) { SharedMapClient.RestorePublicPinsAfterSerialization(__state); } [HarmonyFinalizer] private static Exception Finalizer(Exception __exception, SharedMapClient.PinSaveState __state) { SharedMapClient.RestorePublicPinsAfterSerialization(__state); return __exception; } } [HarmonyPatch(typeof(Minimap), "GetSharedMapData", new Type[] { typeof(byte[]) })] internal static class SharedMapSharedSerializationPatch { [HarmonyPrefix] private static void Prefix(out SharedMapClient.PinSaveState __state) { __state = SharedMapClient.SuspendPublicPinsForSerialization(); } [HarmonyPostfix] private static void Postfix(SharedMapClient.PinSaveState __state) { SharedMapClient.RestorePublicPinsAfterSerialization(__state); } [HarmonyFinalizer] private static Exception Finalizer(Exception __exception, SharedMapClient.PinSaveState __state) { SharedMapClient.RestorePublicPinsAfterSerialization(__state); return __exception; } } [BepInPlugin("com.jg224.sharedmap", "SharedMap", "0.5.1")] [BepInDependency("com.jg224.modcore", "0.5.0")] public sealed class SharedMapPlugin : BaseUnityPlugin { public const string PluginGuid = "com.jg224.sharedmap"; public const string PluginName = "SharedMap"; public const string PluginVersion = "0.5.1"; public const string ModCoreGuid = "com.jg224.modcore"; public const int ProtocolVersion = 3; public static readonly ModuleId ModuleId = new ModuleId("sharedmap"); private Harmony _harmony; private readonly List<IDisposable> _registrations = new List<IDisposable>(); private bool _shutDown; internal static ManualLogSource Log { get; private set; } internal static ICoreServices Core { get; private set; } private void Awake() { //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown //IL_0153: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; try { if (!ModCoreApi.IsAvailable) { throw new InvalidOperationException("ModCore did not initialize before SharedMap."); } Core = ModCoreApi.Services; SemanticVersion val = default(SemanticVersion); if (!SemanticVersion.TryParse("0.5.1", ref val)) { throw new InvalidOperationException("Invalid SharedMap plugin version."); } _registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "com.jg224.sharedmap", "SharedMap", val, 3, (ModuleSide)3, (ModuleRequirement)4, 0uL, 1, 1))); _registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)6, "com.jg224.sharedmap.", 1, Array.Empty<string>())); _registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)4, "SharedMap", 1, Array.Empty<string>())); _registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)8, "sharedmap.", 1, Array.Empty<string>())); _registrations.Add(Core.Ui.Reserve(new UiReservation(ModuleId, (UiSurface)6, "minimap.public-markers", 20, true))); _harmony = new Harmony("com.jg224.sharedmap"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); SharedMapCommands.Register(); Core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Required server-authoritative map synchronization ready."); Game.isModded = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"SharedMap 0.5.1 loaded."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)string.Format("{0} failed to initialize safely: {1}", "SharedMap", ex)); if (Core != null) { Core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message); } Shutdown(); throw; } } private void Update() { SharedMapClient.Tick(Time.unscaledTimeAsDouble); SharedMapServer.Tick(Time.unscaledTimeAsDouble); } private void OnDestroy() { Shutdown(); } private void Shutdown() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (_shutDown) { return; } _shutDown = true; SharedMapServer.Shutdown(); SharedMapClient.ResetSession(); SharedMapNetwork.Shutdown(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; for (int num = _registrations.Count - 1; num >= 0; num--) { try { _registrations[num].Dispose(); } catch (Exception ex) { ManualLogSource logger = ((BaseUnityPlugin)this).Logger; if (logger != null) { logger.LogWarning((object)("Registration cleanup failed: " + ex.Message)); } } } _registrations.Clear(); if (Core != null) { Core.Metrics.RemoveOwner(ModuleId); } Core = null; Log = null; } } [HarmonyPatch(typeof(ZRoutedRpc), "RPC_RoutedRPC")] internal static class SharedMapRpcIngress { private const int RoutingHeaderBytes = 40; [HarmonyPrefix] private static bool Prefix(ZRpc rpc, ZPackage pkg) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if (pkg == null || pkg.Size() - pkg.GetPos() < 40) { return true; } int pos = pkg.GetPos(); try { pkg.ReadLong(); long claimedSender = pkg.ReadLong(); long target = pkg.ReadLong(); ZDOID val = pkg.ReadZDOID(); if (!SharedMapNetwork.TryGetRpcDirection(pkg.ReadInt(), out var serverToClient)) { return true; } if (!SharedMapNetwork.HasBoundedRoutedParameters(pkg)) { return false; } ZNet instance = ZNet.instance; PlayerIdentity val2 = default(PlayerIdentity); if ((Object)(object)instance == (Object)null || SharedMapPlugin.Core == null || !SharedMapPlugin.Core.Identity.TryGetByConnection((object)rpc, ref val2)) { return false; } return SharedMapIngressPolicy.Allows(serverPeer: (instance.IsServer() ? null : instance.GetServerPeer())?.m_uid ?? 0, isServer: instance.IsServer(), serverToClient: serverToClient, connectionPeer: val2.PeerId, claimedSender: claimedSender, target: target, localPeer: ZNet.GetUID(), hasTargetObject: val != ZDOID.None); } finally { pkg.SetPos(pos); } } } internal static class SharedMapPayloadBounds { internal static bool Allows(int declared, int remaining, int maximum) { if (declared >= 0 && declared <= remaining) { return declared <= maximum; } return false; } } internal static class SharedMapIngressPolicy { internal static bool Allows(bool isServer, bool serverToClient, long connectionPeer, long claimedSender, long target, long localPeer, long serverPeer, bool hasTargetObject) { if (connectionPeer == 0L || connectionPeer != claimedSender || hasTargetObject || target != localPeer) { return false; } if (!isServer) { if (serverToClient) { return connectionPeer == serverPeer; } return false; } return !serverToClient; } } internal sealed class SharedMapPlayerClaims { private readonly Dictionary<long, long> _claims = new Dictionary<long, long>(); internal bool Accept(long peer, long player, long hostPlayer) { if (peer == 0L || player == 0L || player == hostPlayer) { return false; } if (_claims.TryGetValue(peer, out var value)) { return value == player; } foreach (long value2 in _claims.Values) { if (value2 == player) { return false; } } _claims.Add(peer, player); return true; } internal void Remove(long peer) { _claims.Remove(peer); } internal void Clear() { _claims.Clear(); } } internal sealed class MarkerRequestBudget { internal const int PerPlayerMarkerLimit = 200; private readonly Dictionary<long, Queue<double>> _requests = new Dictionary<long, Queue<double>>(); internal bool Accept(long peer, double now) { if (double.IsNaN(now) || double.IsInfinity(now)) { return false; } if (!_requests.TryGetValue(peer, out var value)) { _requests.Add(peer, value = new Queue<double>()); } while (value.Count > 0 && now - value.Peek() >= 10.0) { value.Dequeue(); } if (value.Count >= 20) { return false; } value.Enqueue(now); return true; } internal void Remove(long peer) { _requests.Remove(peer); } internal void Clear() { _requests.Clear(); } internal static bool CanManage(long owner, long actor, bool administrator) { return owner == actor || administrator; } } internal static class SharedMapRecovery { internal static bool Load(string path, Action<string> loader, out string status) { if (!File.Exists(path) && !File.Exists(path + ".bak")) { status = "New world store."; return true; } Exception ex2; try { loader(path); status = "Loaded primary store."; return true; } catch (Exception ex) { ex2 = ex; } string text = path + ".recovering"; try { loader(path + ".bak"); File.Copy(path + ".bak", text, overwrite: true); if (File.Exists(path)) { File.Replace(text, path, path + ".corrupt", ignoreMetadataErrors: true); } else { File.Move(text, path); } status = "Recovered validated backup; damaged primary retained as .corrupt."; return true; } catch (Exception ex3) { status = "Store is read-only: " + ex2.Message + "; backup recovery: " + ex3.Message; return false; } finally { try { if (File.Exists(text)) { File.Delete(text); } } catch (IOException) { } } } } internal static class ExplorationMerge { internal static IEnumerable<List<int>> Merge(byte[] target, byte[] incoming, int batchSize) { if (target == null || incoming == null || target.Length != incoming.Length) { throw new ArgumentException("Exploration dimensions must match