Decompiled source of ServerSideMap v1.3.12

ServerSideMap.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ServerSideMap")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ServerSideMap")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("38A5EB8E-7BF4-43B7-9806-9C0DD82AB865")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ServerSideMap;

public static class CommandsPinUpsync
{
	[HarmonyPatch(typeof(Chat), "InputText")]
	private class ChatPatchInputText
	{
		private static bool Prefix(Chat __instance, TMP_InputField ___m_input)
		{
			string text = ___m_input.text;
			if (text.ToLower().Equals("/convertpins ignorelocaldupes"))
			{
				UtilityPin.UploadAllPins(removeDupes: true);
				return false;
			}
			if (text.ToLower().Equals("/convertpins"))
			{
				UtilityPin.UploadAllPins();
				return false;
			}
			if (text.ToLower().Equals("/deletealllocalpins"))
			{
				UtilityPin.DeleteLocalPins();
				return false;
			}
			if (text.ToLower().Equals("/downloadpins"))
			{
				UtilityPin.DownloadPins();
				return false;
			}
			return true;
		}
	}
}
public static class Hotkeys
{
	[HarmonyPatch(typeof(Player), "Update")]
	private class PlayerInputPatch
	{
		private static void Postfix(Player __instance)
		{
			//IL_0007: 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 (Store.HasKeyConvertAll() && Input.GetKeyDown(Store.GetKeyConvertAll()))
			{
				Utility.Log("Hotkey: GetKeyConvertAll");
				UtilityPin.UploadAllPins();
			}
			if (Store.HasKeyConvertIgnoreDupes() && Input.GetKeyDown(Store.GetKeyConvertIgnoreDupes()))
			{
				Utility.Log("Hotkey: GetKeyConvertIgnoreDupes");
				UtilityPin.UploadAllPins(removeDupes: true);
			}
		}
	}
}
public static class Store
{
	public static ConfigEntry<bool> EnableMapShare;

	public static ConfigEntry<bool> EnablePinShare;

	public static ConfigEntry<float> DuplicatePinRadius;

	public static ConfigEntry<string> sKeyConvertAll;

	private static bool hasKeyConvertAll;

	private static KeyCode KeyConvertAll;

	public static ConfigEntry<string> sKeyConvertIgnoreDupes;

	private static bool hasKeyConvertIgnoreDupes;

	private static KeyCode KeyConvertIgnoreDupes;

	public static bool ServerPinShare;

	public static bool IsSharingMap()
	{
		return EnableMapShare.Value;
	}

	public static bool IsSharingPin()
	{
		if (ServerPinShare || _ZNet.IsServer(_ZNet._instance))
		{
			return EnablePinShare.Value;
		}
		return false;
	}

	public static float GetDuplicatePinRadius()
	{
		return DuplicatePinRadius.Value;
	}

	public static void InitHotkeys()
	{
		hasKeyConvertAll = Enum.TryParse<KeyCode>(sKeyConvertAll.Value, out KeyConvertAll);
		hasKeyConvertIgnoreDupes = Enum.TryParse<KeyCode>(sKeyConvertIgnoreDupes.Value, out KeyConvertIgnoreDupes);
	}

	public static bool HasKeyConvertAll()
	{
		return hasKeyConvertAll;
	}

	public static KeyCode GetKeyConvertAll()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		return KeyConvertAll;
	}

	public static bool HasKeyConvertIgnoreDupes()
	{
		return hasKeyConvertIgnoreDupes;
	}

	public static KeyCode GetKeyConvertIgnoreDupes()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		return KeyConvertIgnoreDupes;
	}
}
public static class ExplorationDatabase
{
	[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
	{
		typeof(Vector3),
		typeof(float)
	})]
	private class MinimapPatchExploreInterval
	{
		private static void Postfix(Minimap __instance)
		{
			if (_dirty)
			{
				object value = Traverse.Create((object)__instance).Field("m_fogTexture").GetValue();
				((Texture2D)((value is Texture2D) ? value : null)).Apply();
				_dirty = false;
			}
		}
	}

	private static bool _dirty;

	public static bool[] Explored;

	public const int MapSize = 2048;

	public const int MapSizeSquared = 4194304;

	private static List<PinData> ServerPins = new List<PinData>();

	public static List<PinData> ClientPins = new List<PinData>();

	public static ZPackage Default()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		ZPackage val = new ZPackage();
		val.Write(3);
		val.Write(2048);
		for (int i = 0; i < 4194304; i++)
		{
			val.Write(false);
		}
		val.Write(0);
		val.SetPos(0);
		return val;
	}

	public static ZPackage PackPins(List<PinData> pins)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Expected I4, but got Unknown
		ZPackage val = new ZPackage();
		val.Write(pins.Count);
		foreach (PinData pin in pins)
		{
			val.Write(pin.Name);
			val.Write(pin.Pos);
			val.Write((int)pin.Type);
			val.Write(pin.Checked);
		}
		val.SetPos(0);
		Utility.Log("Packing pins: " + pins.Count);
		return val;
	}

	public static List<PinData> UnpackPins(ZPackage z)
	{
		//IL_0024: 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_0035: Unknown result type (might be due to invalid IL or missing references)
		List<PinData> list = new List<PinData>();
		int num = z.ReadInt();
		for (int i = 0; i < num; i++)
		{
			PinData item = new PinData
			{
				Name = z.ReadString(),
				Pos = z.ReadVector3(),
				Type = (PinType)z.ReadInt(),
				Checked = z.ReadBool()
			};
			list.Add(item);
		}
		return list;
	}

	public static ZPackage PackPin(PinData pin, bool skipSetPos = false)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected I4, but got Unknown
		ZPackage val = new ZPackage();
		val.Write(pin.Name);
		val.Write(pin.Pos);
		val.Write((int)pin.Type);
		val.Write(pin.Checked);
		if (!skipSetPos)
		{
			val.SetPos(0);
		}
		return val;
	}

	public static PinData UnpackPin(ZPackage z)
	{
		//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_0024: Unknown result type (might be due to invalid IL or missing references)
		return new PinData
		{
			Name = z.ReadString(),
			Pos = z.ReadVector3(),
			Type = (PinType)z.ReadInt(),
			Checked = z.ReadBool()
		};
	}

	public static List<PinData> GetPins()
	{
		return ServerPins;
	}

	public static void AddPin(PinData pin)
	{
		ServerPins.Add(pin);
	}

	public static void RemovePinEqual(PinData needle)
	{
		foreach (PinData item in ServerPins.ToList())
		{
			if (UtilityPin.ArePinsEqual(item, needle))
			{
				ServerPins.Remove(item);
			}
		}
	}

	public static void SetPinState(PinData needle, bool state)
	{
		foreach (PinData item in ServerPins.ToList())
		{
			if (UtilityPin.ArePinsEqual(item, needle))
			{
				item.Checked = state;
			}
		}
	}

	public static void SetMapData(ZPackage mapData)
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		ServerPins.Clear();
		mapData.ReadInt();
		int num = mapData.ReadInt();
		bool[] array = new bool[num * num];
		for (int i = 0; i < num * num; i++)
		{
			array[i] = mapData.ReadBool();
		}
		int num2 = mapData.ReadInt();
		for (int j = 0; j < num2; j++)
		{
			PinData item = new PinData
			{
				Name = mapData.ReadString(),
				Pos = mapData.ReadVector3(),
				Type = (PinType)mapData.ReadInt(),
				Checked = mapData.ReadBool()
			};
			ServerPins.Add(item);
		}
		Explored = array;
	}

	public static ZPackage GetMapData()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected I4, but got Unknown
		ZPackage val = new ZPackage();
		val.Write(3);
		val.Write(2048);
		bool[] explored = Explored;
		foreach (bool flag in explored)
		{
			val.Write(flag);
		}
		val.Write(ServerPins.Count);
		Utility.Log("Map saved. Pin Count: " + ServerPins.Count);
		foreach (PinData serverPin in ServerPins)
		{
			val.Write(serverPin.Name);
			val.Write(serverPin.Pos);
			val.Write((int)serverPin.Type);
			val.Write(serverPin.Checked);
		}
		return val;
	}

	public static void SetExplored(int x, int y)
	{
		Explored[y * 2048 + x] = true;
	}

	public static bool GetExplored(int x, int y)
	{
		return Explored[y * 2048 + x];
	}

	public static bool GetExplored(int idx)
	{
		return Explored[idx];
	}

	public static bool[] GetExplorationArray()
	{
		return Explored;
	}

	public static void MergeExplorationArray(bool[] arr, int startIndex, int size)
	{
		for (int i = 0; i < size; i++)
		{
			Explored[startIndex + i] = arr[i] || Explored[startIndex + i];
		}
	}

	public static ZPackage PackBoolArray(bool[] arr, int chunkId, int startIndex, int size)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		ZPackage val = new ZPackage();
		val.Write(chunkId);
		byte b = 0;
		int num = 0;
		for (int i = startIndex; i < startIndex + size; i++)
		{
			if (arr[i])
			{
				byte b2 = (byte)(1 << num);
				b |= b2;
			}
			num++;
			if (num >= 8)
			{
				val.Write(b);
				b = 0;
				num = 0;
			}
		}
		if (num > 0)
		{
			val.Write(b);
		}
		return val;
	}

	public static bool[] UnpackBoolArray(ZPackage z, int length)
	{
		bool[] array = new bool[length];
		for (int i = 0; i < length; i += 8)
		{
			byte b = z.ReadByte();
			array[i] = (b & 1) != 0;
			array[i + 1] = (b & 2) != 0;
			array[i + 2] = (b & 4) != 0;
			array[i + 3] = (b & 8) != 0;
			array[i + 4] = (b & 0x10) != 0;
			array[i + 5] = (b & 0x20) != 0;
			array[i + 6] = (b & 0x40) != 0;
			array[i + 7] = (b & 0x80) != 0;
		}
		return array;
	}

	public static void OnReceiveMapData(ZRpc client, ZPackage mapData)
	{
		mapData.SetPos(0);
		int x = mapData.ReadInt();
		int y = mapData.ReadInt();
		object value = Traverse.Create(typeof(Minimap)).Field("m_instance").GetValue();
		_dirty = _Minimap.Explore((Minimap)((value is Minimap) ? value : null), x, y) || _dirty;
	}
}
public class PinData
{
	public string Name;

	public PinType Type;

	public Vector3 Pos;

	public bool Checked;
}
public static class ExplorationMapSync
{
	[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
	{
		typeof(int),
		typeof(int)
	})]
	private class MinimapPatchExplore
	{
		private static void Postfix(int x, int y, bool __result)
		{
			if (__result && !_blockExplore && Store.IsSharingMap())
			{
				if (_ZNet.IsServer(_ZNet._instance))
				{
					OnClientExplore(null, x, y);
					return;
				}
				object value = Traverse.Create(typeof(ZNet)).Field("m_instance").GetValue();
				_ZNet.GetServerRPC((ZNet)((value is ZNet) ? value : null)).Invoke("OnClientExplore", new object[2] { x, y });
			}
		}
	}

	[HarmonyPatch(typeof(Minimap), "SetMapData", new Type[] { typeof(byte[]) })]
	private class MinimapPatchSetMapData
	{
		private static void Prefix()
		{
			_blockExplore = true;
		}

		private static void Postfix(Minimap __instance)
		{
			_blockExplore = false;
		}
	}

	private static bool _blockExplore;

	public static void OnClientExplore(ZRpc client, int x, int y)
	{
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Expected O, but got Unknown
		if (!Store.IsSharingMap())
		{
			return;
		}
		ExplorationDatabase.SetExplored(x, y);
		object value = Traverse.Create(typeof(ZNet)).Field("m_instance").GetValue();
		foreach (ZNetPeer item in Traverse.Create((value is ZNet) ? value : null).Field("m_peers").GetValue() as List<ZNetPeer>)
		{
			if (item.IsReady() && item.m_rpc != client)
			{
				ZPackage val = new ZPackage();
				val.Write(x);
				val.Write(y);
				item.m_rpc.Invoke("OnReceiveMapData", new object[1] { val });
			}
		}
		ZPackage val2 = new ZPackage();
		val2.Write(x);
		val2.Write(y);
		ExplorationDatabase.OnReceiveMapData(null, val2);
	}
}
public class InitialMapSync
{
	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	private class ZnetPatchRPC_PeerInfo
	{
		private static void Postfix(ZRpc rpc, ZNet __instance)
		{
			if (Store.IsSharingMap() && __instance.IsServer())
			{
				SendChunkToClient(rpc, 0);
			}
		}
	}

	[HarmonyPatch(typeof(Minimap), "SetMapData", new Type[] { typeof(byte[]) })]
	private class MinimapPatchSetMapData
	{
		private static void Postfix(Minimap __instance)
		{
			if (Store.IsSharingMap() && _ZNet.IsServer(_ZNet._instance))
			{
				SendChunkToClient(null, 0);
			}
		}
	}

	private static int CHUNKS = 64;

	public static void OnReceiveMapDataInitial(ZRpc client, ZPackage mapData)
	{
		if (!Store.IsSharingMap())
		{
			return;
		}
		mapData.SetPos(0);
		int num = mapData.ReadInt();
		bool[] array = ExplorationDatabase.UnpackBoolArray(mapData, 4194304 / CHUNKS);
		int num2 = num * (4194304 / CHUNKS);
		for (int i = 0; i < array.Length; i++)
		{
			if (array[i])
			{
				_Minimap.Explore(_Minimap._instance, (num2 + i) % 2048, (num2 + i) / 2048);
			}
		}
		object value = Traverse.Create((object)_Minimap._instance).Field("m_fogTexture").GetValue();
		((Texture2D)((value is Texture2D) ? value : null)).Apply();
		((MonoBehaviour)_ZNet._instance).StartCoroutine(SendChunkToServer(client, num));
	}

	public static void OnClientInitialData(ZRpc client, ZPackage mapData)
	{
		if (Store.IsSharingMap())
		{
			mapData.SetPos(0);
			int num = mapData.ReadInt();
			int startIndex = num * (4194304 / CHUNKS);
			int num2 = 4194304 / CHUNKS;
			ExplorationDatabase.MergeExplorationArray(ExplorationDatabase.UnpackBoolArray(mapData, num2), startIndex, num2);
			SendChunkToClient(client, num + 1);
		}
	}

	private static void SendChunkToClient(ZRpc client, int chunk)
	{
		if (chunk < CHUNKS)
		{
			int size = 4194304 / CHUNKS;
			int startIndex = chunk * (4194304 / CHUNKS);
			ZPackage val = ExplorationDatabase.PackBoolArray(ExplorationDatabase.GetExplorationArray(), chunk, startIndex, size);
			if (client == null)
			{
				OnReceiveMapDataInitial(null, val);
				return;
			}
			client.Invoke("OnReceiveMapDataInitial", new object[1] { val });
		}
	}

	private static IEnumerator SendChunkToServer(ZRpc client, int chunk)
	{
		if (chunk >= CHUNKS)
		{
			yield break;
		}
		int size = 4194304 / CHUNKS;
		int startIndex = chunk * (4194304 / CHUNKS);
		bool[] arr = Traverse.Create((object)_Minimap._instance).Field("m_explored").GetValue() as bool[];
		ZPackage z = ExplorationDatabase.PackBoolArray(arr, chunk, startIndex, size);
		if (client == null)
		{
			OnClientInitialData(null, z);
			yield break;
		}
		yield return (object)new WaitUntil((Func<bool>)(() => _ZNet.GetServerRPC(_ZNet._instance) != null));
		_ZNet.GetServerRPC(_ZNet._instance).Invoke("OnClientInitialData", new object[1] { z });
	}
}
public class InitialPinSync
{
	[HarmonyPatch(typeof(Minimap), "ClearPins")]
	private class MinimapPatchClearPins
	{
		private static void Postfix(Minimap __instance)
		{
			ClientAppendPins();
		}
	}

	[HarmonyPatch(typeof(ZNet), "Shutdown")]
	private class ZNetPatchShutdown
	{
		private static void Postfix(ZNet __instance)
		{
			ExplorationDatabase.ClientPins.Clear();
		}
	}

	[HarmonyPatch(typeof(Minimap), "SetMapData", new Type[] { typeof(byte[]) })]
	private class MinimapPatchSetMapData
	{
		private static void Postfix(Minimap __instance)
		{
			if (_ZNet.IsServer(_ZNet._instance))
			{
				SendPinsToClient(null);
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	private class ZnetPatchRPC_PeerInfo
	{
		private static void Postfix(ZRpc rpc, ZNet __instance)
		{
			if (__instance.IsServer())
			{
				SendPinsToClient(rpc);
			}
		}
	}

	public static void OnReceiveInitialDataPin(ZRpc client, ZPackage pinData)
	{
		Store.ServerPinShare = true;
		if (Store.IsSharingPin())
		{
			List<PinData> list = ExplorationDatabase.UnpackPins(pinData);
			Utility.Log("Client received initial pin data by server. Pins: " + list.Count);
			ExplorationDatabase.ClientPins = list;
			ClientAppendPins();
		}
	}

	private static void ClientAppendPins()
	{
		//IL_0059: 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)
		if (!Store.IsSharingPin())
		{
			return;
		}
		Utility.Log("ClientAppendPins " + ExplorationDatabase.ClientPins.Count);
		foreach (PinData clientPin in ExplorationDatabase.ClientPins)
		{
			PinData mapPin = UtilityPin.GetMapPin(clientPin);
			if (mapPin != null)
			{
				_Minimap.RemovePin(_Minimap._instance, mapPin);
			}
			_Minimap.AddPin(_Minimap._instance, clientPin.Pos, clientPin.Type, clientPin.Name, save: false, clientPin.Checked, 0L, "");
		}
	}

	public static void OnClientInitialDataPin(ZRpc client, ZPackage pinData)
	{
		Utility.Log("Server received initial pin data by client");
	}

	private static void SendPinsToClient(ZRpc client)
	{
		if (Store.IsSharingPin())
		{
			ZPackage val = ExplorationDatabase.PackPins(ExplorationDatabase.GetPins());
			if (client == null)
			{
				OnReceiveInitialDataPin(null, val);
				return;
			}
			client.Invoke("OnReceiveInitialDataPin", new object[1] { val });
		}
	}

	private static void SendPinsToServer(ZRpc client)
	{
		List<PinData> obj = Traverse.Create((object)_Minimap._instance).Field("m_pins").GetValue() as List<PinData>;
		List<PinData> list = new List<PinData>();
		foreach (PinData item in obj)
		{
			if (item.m_save)
			{
				list.Add(UtilityPin.ConvertPin(item));
			}
		}
		ZPackage val = ExplorationDatabase.PackPins(list);
		if (client == null)
		{
			OnClientInitialDataPin(null, val);
			return;
		}
		object value = Traverse.Create(typeof(ZNet)).Field("m_instance").GetValue();
		_ZNet.GetServerRPC((ZNet)((value is ZNet) ? value : null)).Invoke("OnClientInitialDataPin", new object[1] { val });
	}
}
public class PinSync
{
	[HarmonyPatch(typeof(Minimap), "OnMapLeftClick")]
	private class MinimapPatchOnMapLeftClick
	{
		private static void Postfix(Minimap __instance)
		{
			if (LatestClosestPin != null)
			{
				PinData clientPin = UtilityPin.GetClientPin(LatestClosestPin);
				if (clientPin != null)
				{
					clientPin.Checked = LatestClosestPin.m_checked;
					CheckPinOnServer(clientPin, clientPin.Checked);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Minimap), "OnMapRightClick")]
	private class MinimapPatchOnMapRightClick
	{
		private static void Postfix(Minimap __instance)
		{
			if (LatestClosestPin != null)
			{
				PinData clientPin = UtilityPin.GetClientPin(LatestClosestPin);
				if (clientPin != null)
				{
					RemovePinFromServer(clientPin);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Minimap), "GetClosestPin", new Type[]
	{
		typeof(Vector3),
		typeof(float),
		typeof(bool)
	})]
	private class MinimapPatchGetClosestPin
	{
		private static void Postfix(Minimap __instance, ref PinData __result, Vector3 pos, float radius, bool mustBeVisible = true)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!Store.IsSharingPin())
			{
				return;
			}
			LatestClosestPin = __result;
			PinData pinData = null;
			float num = 999999f;
			foreach (PinData clientPin in ExplorationDatabase.ClientPins)
			{
				float num2 = Utils.DistanceXZ(pos, clientPin.Pos);
				if ((double)num2 < (double)radius && ((double)num2 < (double)num || pinData == null))
				{
					pinData = clientPin;
					num = num2;
				}
			}
			if (pinData != null)
			{
				PinData mapPin = UtilityPin.GetMapPin(pinData);
				if (__result == null)
				{
					__result = mapPin;
					LatestClosestPin = mapPin;
				}
				else if (Utils.DistanceXZ(pos, __result.m_pos) > num)
				{
					__result = mapPin;
					LatestClosestPin = mapPin;
				}
			}
		}
	}

	[HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(PinData) })]
	private class MinimapPatchRemovePin
	{
		private static void Postfix(Minimap __instance, PinData pin)
		{
		}
	}

	[HarmonyPatch(typeof(Minimap), "OnPinTextEntered")]
	private class MinimapPatchOnPinTextEntered
	{
		private static void Prefix(Minimap __instance, out PinData __state, PinData ___m_namePin)
		{
			__state = null;
			if (___m_namePin != null)
			{
				__state = ___m_namePin;
			}
		}

		private static void Postfix(Minimap __instance, PinData __state)
		{
			if (__state != null)
			{
				SendPinToServer(__state);
			}
		}
	}

	private static PinData CurrentPin;

	private static PinData LatestClosestPin;

	public static void OnClientAddPin(ZRpc client, ZPackage pinData)
	{
		if (!Store.IsSharingPin())
		{
			return;
		}
		pinData.SetPos(0);
		object value = Traverse.Create(typeof(ZNet)).Field("m_instance").GetValue();
		List<ZNetPeer> obj = Traverse.Create((value is ZNet) ? value : null).Field("m_peers").GetValue() as List<ZNetPeer>;
		PinData pin = ExplorationDatabase.UnpackPin(pinData);
		ExplorationDatabase.AddPin(pin);
		Utility.Log("Server received pin by client");
		foreach (ZNetPeer item in obj)
		{
			if (item.IsReady() && item.m_rpc != client)
			{
				item.m_rpc.Invoke("OnServerAddPin", new object[1] { ExplorationDatabase.PackPin(pin) });
			}
		}
		if (client != null)
		{
			OnServerAddPin(null, ExplorationDatabase.PackPin(pin));
		}
	}

	public static void OnServerAddPin(ZRpc client, ZPackage pinData)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (Store.IsSharingPin())
		{
			pinData.SetPos(0);
			PinData pinData2 = ExplorationDatabase.UnpackPin(pinData);
			_Minimap.AddPin(_Minimap._instance, pinData2.Pos, pinData2.Type, pinData2.Name, save: false, pinData2.Checked, 0L, "");
			ExplorationDatabase.ClientPins.Add(pinData2);
			Utility.Log("Client received pin by server");
		}
	}

	public static void OnClientRemovePin(ZRpc client, ZPackage pinData)
	{
		if (!Store.IsSharingPin())
		{
			return;
		}
		pinData.SetPos(0);
		object value = Traverse.Create(typeof(ZNet)).Field("m_instance").GetValue();
		List<ZNetPeer> obj = Traverse.Create((value is ZNet) ? value : null).Field("m_peers").GetValue() as List<ZNetPeer>;
		PinData pinData2 = ExplorationDatabase.UnpackPin(pinData);
		ExplorationDatabase.RemovePinEqual(pinData2);
		Utility.Log("Server deleted pin by client");
		foreach (ZNetPeer item in obj)
		{
			if (item.IsReady() && item.m_rpc != client)
			{
				item.m_rpc.Invoke("OnServerRemovePin", new object[1] { ExplorationDatabase.PackPin(pinData2) });
			}
		}
		if (client != null)
		{
			OnServerRemovePin(null, ExplorationDatabase.PackPin(pinData2));
		}
	}

	public static void OnServerRemovePin(ZRpc _, ZPackage pinData)
	{
		if (!Store.IsSharingPin())
		{
			return;
		}
		pinData.SetPos(0);
		Utility.Log("Client deleted pin by server");
		PinData pinData2 = ExplorationDatabase.UnpackPin(pinData);
		foreach (PinData item in ExplorationDatabase.ClientPins.ToList())
		{
			if (UtilityPin.ArePinsEqual(item, pinData2))
			{
				ExplorationDatabase.ClientPins.Remove(item);
			}
		}
		PinData mapPin = UtilityPin.GetMapPin(pinData2);
		if (mapPin != null)
		{
			_Minimap.RemovePin(_Minimap._instance, mapPin);
		}
	}

	public static void OnClientCheckPin(ZRpc client, ZPackage data)
	{
		if (!Store.IsSharingPin())
		{
			return;
		}
		data.SetPos(0);
		Utility.Log("Server checked pin by client");
		PinData pinData = ExplorationDatabase.UnpackPin(data);
		bool flag = data.ReadBool();
		ExplorationDatabase.SetPinState(pinData, flag);
		object value = Traverse.Create(typeof(ZNet)).Field("m_instance").GetValue();
		foreach (ZNetPeer item in Traverse.Create((value is ZNet) ? value : null).Field("m_peers").GetValue() as List<ZNetPeer>)
		{
			if (item.IsReady() && item.m_rpc != client)
			{
				ZPackage val = ExplorationDatabase.PackPin(pinData, skipSetPos: true);
				val.Write(flag);
				item.m_rpc.Invoke("OnServerCheckPin", new object[1] { val });
			}
		}
		if (client != null)
		{
			ZPackage val2 = ExplorationDatabase.PackPin(pinData, skipSetPos: true);
			val2.Write(flag);
			OnServerCheckPin(null, val2);
		}
	}

	public static void OnServerCheckPin(ZRpc client, ZPackage data)
	{
		if (!Store.IsSharingPin())
		{
			return;
		}
		data.SetPos(0);
		Utility.Log("Client checked pin by server");
		PinData pin = ExplorationDatabase.UnpackPin(data);
		bool @checked = data.ReadBool();
		foreach (PinData item in ExplorationDatabase.ClientPins.ToList())
		{
			if (UtilityPin.ArePinsEqual(item, pin))
			{
				item.Checked = @checked;
				PinData mapPin = UtilityPin.GetMapPin(item);
				if (mapPin != null)
				{
					mapPin.m_checked = @checked;
				}
			}
		}
	}

	public static void SendPinToServer(PinData pin, bool deletePin = true)
	{
		if (Store.IsSharingPin())
		{
			PinData pinData = UtilityPin.ConvertPin(pin);
			ZPackage val = ExplorationDatabase.PackPin(pinData);
			pin.m_save = !deletePin && pin.m_save;
			ExplorationDatabase.ClientPins.Add(pinData);
			if (!_ZNet.IsServer(_ZNet._instance))
			{
				_ZNet.GetServerRPC(_ZNet._instance).Invoke("OnClientAddPin", new object[1] { val });
			}
			else
			{
				OnClientAddPin(null, val);
			}
		}
	}

	public static void RemovePinFromServer(PinData pin)
	{
		if (Store.IsSharingPin())
		{
			ZPackage val = ExplorationDatabase.PackPin(pin);
			ExplorationDatabase.ClientPins.Remove(pin);
			if (!_ZNet.IsServer(_ZNet._instance))
			{
				_ZNet.GetServerRPC(_ZNet._instance).Invoke("OnClientRemovePin", new object[1] { val });
			}
			else
			{
				OnClientRemovePin(null, val);
			}
		}
	}

	public static void CheckPinOnServer(PinData pin, bool state)
	{
		if (Store.IsSharingPin())
		{
			ZPackage val = ExplorationDatabase.PackPin(pin, skipSetPos: true);
			val.Write(state);
			val.SetPos(0);
			if (!_ZNet.IsServer(_ZNet._instance))
			{
				_ZNet.GetServerRPC(_ZNet._instance).Invoke("OnClientCheckPin", new object[1] { val });
			}
			else
			{
				OnClientCheckPin(null, val);
			}
		}
	}
}
public class SaveWorld
{
	[HarmonyPatch(typeof(ZNet), "LoadWorld")]
	private class ZnetPatchLoadMap
	{
		private static void Postfix(ZNet __instance)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			object value = Traverse.Create(typeof(ZNet)).Field("m_world").GetValue();
			string text = Path.ChangeExtension(((World)((value is World) ? value : null)).GetDBPath(), null);
			Utility.Log("World .explored save path: " + text);
			string text2 = text + ".mod.serversidemap.explored";
			string text3 = text2 + ".beforehs";
			if (File.Exists(text2) && !File.Exists(text3))
			{
				File.Copy(text2, text3);
			}
			FileStream input;
			try
			{
				input = File.OpenRead(text2);
			}
			catch
			{
				GenerateDefaultExploredFile(__instance);
				return;
			}
			BinaryReader binaryReader = new BinaryReader(input);
			byte[] array = binaryReader.ReadAllBytes();
			binaryReader.Dispose();
			if (array.Length == 0)
			{
				Utility.Log("Existing explored file is 0 bytes. Generating new one.");
				GenerateDefaultExploredFile(__instance);
			}
			else
			{
				ExplorationDatabase.SetMapData(new ZPackage(array));
				Utility.Log("loaded from existing explore file");
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "SaveWorldThread")]
	private class ZnetPatchSaveWorldThread
	{
		private static void Postfix()
		{
			byte[] array = ExplorationDatabase.GetMapData().GetArray();
			if (array.Length == 0)
			{
				Utility.Log("Explored data is zero bytes. Refusing to save.");
				return;
			}
			object value = Traverse.Create(typeof(ZNet)).Field("m_world").GetValue();
			string text = Path.ChangeExtension(((World)((value is World) ? value : null)).GetDBPath(), null);
			string path = text + ".mod.serversidemap.explored";
			Utility.Log("World .explored save path: " + text);
			FileStream fileStream = File.Create(path);
			BinaryWriter binaryWriter = new BinaryWriter(fileStream);
			binaryWriter.Write(array);
			binaryWriter.Flush();
			fileStream.Flush(flushToDisk: true);
			fileStream.Close();
			fileStream.Dispose();
		}
	}

	public static void GenerateDefaultExploredFile(ZNet __instance)
	{
		ExplorationDatabase.SetMapData(ExplorationDatabase.Default());
		Utility.Log("new explore file generated");
		__instance.Save(true, false, false);
	}
}
[BepInPlugin("eu.mydayyy.plugins.serversidemap", "ServerSideMap", "1.3.12.0")]
public class ServerSideMap : BaseUnityPlugin
{
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	private class ZnetPatchOnNewConnection
	{
		private static void Postfix(ZNetPeer peer, ZNet __instance)
		{
			if (__instance.IsServer())
			{
				Utility.Log("Registered Server Events");
				if (Store.IsSharingMap())
				{
					peer.m_rpc.Register<int, int>("OnClientExplore", (Action<ZRpc, int, int>)ExplorationMapSync.OnClientExplore);
					peer.m_rpc.Register<ZPackage>("OnClientInitialData", (Action<ZRpc, ZPackage>)InitialMapSync.OnClientInitialData);
				}
				peer.m_rpc.Register<ZPackage>("OnClientInitialDataPin", (Action<ZRpc, ZPackage>)InitialPinSync.OnClientInitialDataPin);
				peer.m_rpc.Register<ZPackage>("OnClientAddPin", (Action<ZRpc, ZPackage>)PinSync.OnClientAddPin);
				peer.m_rpc.Register<ZPackage>("OnClientRemovePin", (Action<ZRpc, ZPackage>)PinSync.OnClientRemovePin);
				peer.m_rpc.Register<ZPackage>("OnClientCheckPin", (Action<ZRpc, ZPackage>)PinSync.OnClientCheckPin);
			}
			else
			{
				Utility.Log("Registered Client Events");
				if (Store.IsSharingMap())
				{
					peer.m_rpc.Register<ZPackage>("OnReceiveMapData", (Action<ZRpc, ZPackage>)ExplorationDatabase.OnReceiveMapData);
					peer.m_rpc.Register<ZPackage>("OnReceiveMapDataInitial", (Action<ZRpc, ZPackage>)InitialMapSync.OnReceiveMapDataInitial);
				}
				peer.m_rpc.Register<ZPackage>("OnReceiveInitialDataPin", (Action<ZRpc, ZPackage>)InitialPinSync.OnReceiveInitialDataPin);
				peer.m_rpc.Register<ZPackage>("OnServerAddPin", (Action<ZRpc, ZPackage>)PinSync.OnServerAddPin);
				peer.m_rpc.Register<ZPackage>("OnServerRemovePin", (Action<ZRpc, ZPackage>)PinSync.OnServerRemovePin);
				peer.m_rpc.Register<ZPackage>("OnServerCheckPin", (Action<ZRpc, ZPackage>)PinSync.OnServerCheckPin);
			}
		}
	}

	private void Awake()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		new Harmony("eu.mydayyy.plugins.serversidemap");
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		Store.EnableMapShare = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMapShare", true, "Client: Whether or not to participate in sharing the map. Server: Whether or not to allow map sharing");
		Store.EnablePinShare = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMarkerShare", false, "Client: Whether or not to participate in sharing markers. Server: Whether or not to allow marker sharing");
		Store.DuplicatePinRadius = ((BaseUnityPlugin)this).Config.Bind<float>("PinShare", "DuplicatePinRadius", 15f, "A local pin will not be uploaded if a pin exists in the given radius on the server (when using /convertpins ignorelocaldupes)");
		Store.sKeyConvertAll = ((BaseUnityPlugin)this).Config.Bind<string>("Hotkeys", "KeyConvertAll", "", "Hotkey to run /convertpins");
		Store.sKeyConvertIgnoreDupes = ((BaseUnityPlugin)this).Config.Bind<string>("Hotkeys", "KeyConvertIgnoreDupes", "", "Hotkey to run /convertpins ignorelocaldupes");
		Store.InitHotkeys();
		Utility.Log("Store1: " + Store.HasKeyConvertAll());
		Utility.Log("Store2: " + Store.HasKeyConvertIgnoreDupes());
	}
}
public static class Utility
{
	private static ManualLogSource _logInstance = Logger.CreateLogSource("ServerSideMap");

	public static void Log(object data)
	{
		_logInstance.Log((LogLevel)16, data);
	}

	public static byte[] ReadAllBytes(this BinaryReader reader)
	{
		using MemoryStream memoryStream = new MemoryStream();
		byte[] array = new byte[4096];
		int count;
		while ((count = reader.Read(array, 0, array.Length)) != 0)
		{
			memoryStream.Write(array, 0, count);
		}
		return memoryStream.ToArray();
	}
}
public class UtilityPin
{
	public static bool ArePinsEqual(PinData pin1, PinData pin2)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if (pin1.Name == pin2.m_name && pin1.Type == pin2.m_type)
		{
			return ((Vector3)(ref pin1.Pos)).Equals(pin2.m_pos);
		}
		return false;
	}

	public static bool ArePinsEqual(PinData pin1, PinData pin2)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if (pin1.Name == pin2.Name && pin1.Type == pin2.Type)
		{
			return ((Vector3)(ref pin1.Pos)).Equals(pin2.Pos);
		}
		return false;
	}

	public static bool ArePinsDupes(PinData pin1, PinData pin2, float radius)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		return Utils.DistanceXZ(pin1.m_pos, pin2.Pos) < radius;
	}

	public static bool LocalPinIsDupe(PinData pin)
	{
		foreach (PinData clientPin in ExplorationDatabase.ClientPins)
		{
			if (ArePinsDupes(pin, clientPin, Store.GetDuplicatePinRadius()))
			{
				return true;
			}
		}
		return false;
	}

	public static PinData GetMapPin(PinData needle)
	{
		foreach (PinData item in Traverse.Create((object)_Minimap._instance).Field("m_pins").GetValue() as List<PinData>)
		{
			if (ArePinsEqual(needle, item))
			{
				return item;
			}
		}
		return null;
	}

	public static PinData GetClientPin(PinData needle)
	{
		foreach (PinData clientPin in ExplorationDatabase.ClientPins)
		{
			if (ArePinsEqual(clientPin, needle))
			{
				return clientPin;
			}
		}
		return null;
	}

	public static PinData ConvertPin(PinData pin)
	{
		//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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		return new PinData
		{
			Name = pin.m_name,
			Pos = pin.m_pos,
			Type = pin.m_type,
			Checked = pin.m_checked
		};
	}

	public static void UploadAllPins(bool removeDupes = false)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		foreach (PinData item in (Traverse.Create((object)_Minimap._instance).Field("m_pins").GetValue() as List<PinData>).ToList())
		{
			if (item.m_save && (!removeDupes || !LocalPinIsDupe(item)))
			{
				PinSync.SendPinToServer(item, deletePin: false);
				PinData pinData = ConvertPin(item);
				_Minimap.AddPin(_Minimap._instance, pinData.Pos, pinData.Type, pinData.Name, save: false, pinData.Checked, 0L, "");
				ExplorationDatabase.ClientPins.Add(pinData);
			}
		}
	}

	public static void DeleteLocalPins()
	{
		foreach (PinData item in (Traverse.Create((object)_Minimap._instance).Field("m_pins").GetValue() as List<PinData>).ToList())
		{
			if (item.m_save)
			{
				_Minimap.RemovePin(_Minimap._instance, item);
			}
		}
	}

	public static void DownloadPins()
	{
		foreach (PinData item in ExplorationDatabase.ClientPins.ToList())
		{
			GetMapPin(item).m_save = true;
		}
	}
}
[HarmonyPatch]
public class _Minimap
{
	[HarmonyPatch(typeof(Minimap), "Awake")]
	public static class Awake
	{
		private static void Postfix(Minimap __instance)
		{
			_instance = __instance;
			Logger.CreateLogSource("ServerSideMap").LogInfo((object)"Minimap awake");
		}
	}

	public static Minimap _instance;

	[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
	{
		typeof(int),
		typeof(int)
	})]
	public static bool Explore(Minimap instance, int x, int y)
	{
		throw new NotImplementedException();
	}

	[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPatch(typeof(Minimap), "AddPin", new Type[]
	{
		typeof(Vector3),
		typeof(PinType),
		typeof(string),
		typeof(bool),
		typeof(bool),
		typeof(long),
		typeof(string)
	})]
	public static PinData AddPin(Minimap instance, Vector3 pos, PinType type, string name, bool save, bool isChecked, long owner, string author)
	{
		throw new NotImplementedException();
	}

	[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(PinData) })]
	public static void RemovePin(Minimap instance, PinData pin)
	{
		throw new NotImplementedException();
	}
}
[HarmonyPatch]
public class _ZNet
{
	[HarmonyPatch(typeof(ZNet), "Awake")]
	public static class Awake
	{
		private static void Postfix(ZNet __instance)
		{
			_instance = __instance;
			Logger.CreateLogSource("ServerSideMap").LogInfo((object)"ZNet awake");
			Store.ServerPinShare = false;
		}
	}

	public static ZNet _instance;

	[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPatch(typeof(ZNet), "GetServerRPC")]
	public static ZRpc GetServerRPC(ZNet instance)
	{
		throw new NotImplementedException();
	}

	[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPatch(typeof(ZNet), "IsServer")]
	public static bool IsServer(ZNet instance)
	{
		throw new NotImplementedException();
	}
}