Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ServerSideMap v1.3.13
ServerSideMap.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Splatform; 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) //IL_0078: 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, new PlatformUserID("")); } } 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) //IL_003b: 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, new PlatformUserID("")); 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.13.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) //IL_0079: 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, new PlatformUserID("")); 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(PlatformUserID) })] public static PinData AddPin(Minimap instance, Vector3 pos, PinType type, string name, bool save, bool isChecked, long owner, PlatformUserID 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(); } }