Decompiled source of SharedMap v0.5.1

SharedMap.dll

Decompiled 5 hours ago
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