Decompiled source of VBMapPingSmooth v0.0.1

VBMapPingSmooth.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: Guid("d9c87954-ce20-459d-81ec-96599caed427")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyProduct("VBMapPingSmooth")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("VBMapPingSmooth")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	[CompilerGenerated]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	[Embedded]
	[CompilerGenerated]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VBMapPingSmooth
{
	[HarmonyPatch(typeof(Minimap), "UpdatePlayerPins")]
	public static class Minimap_UpdatePlayerPins_Patch
	{
		private class PlayerTrackData
		{
			public Vector3 lastRealPosition;

			public Vector3 lastRealVelocity;

			public Vector3 smoothPosition;

			public Vector3 smoothVelocity;

			public float lastUpdateTime;

			public float predictedTimeout;

			public bool wasTeleporting;

			public float teleportEndTime;
		}

		public static float InterpolationSpeed;

		public static float SmoothTime;

		public static float TeleportThreshold;

		public static float MaxPredictionTime;

		private static bool? serverModDetected;

		private static float serverLastUpdateTime;

		private static Dictionary<long, PlayerTrackData> playerData;

		private static FieldInfo m_characterIDField;

		private static FieldInfo m_userIDField;

		static Minimap_UpdatePlayerPins_Patch()
		{
			InterpolationSpeed = 2000f;
			SmoothTime = 0.033f;
			TeleportThreshold = 50f;
			MaxPredictionTime = 0.3f;
			serverModDetected = null;
			serverLastUpdateTime = 0f;
			playerData = new Dictionary<long, PlayerTrackData>();
			Type typeFromHandle = typeof(PlayerInfo);
			m_characterIDField = typeFromHandle.GetField("m_characterID");
			if (m_characterIDField != null)
			{
				Type fieldType = m_characterIDField.FieldType;
				m_userIDField = fieldType.GetField("m_userID");
			}
		}

		[HarmonyPrefix]
		private static void Prefix()
		{
			if (Time.frameCount % 600 == 0)
			{
				CleanupOldData();
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Minimap __instance, float dt)
		{
			//IL_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			DetectServerMod(time);
			for (int i = 0; i < __instance.m_playerPins.Count && i < __instance.m_tempPlayerInfo.Count; i++)
			{
				PinData val = __instance.m_playerPins[i];
				PlayerInfo val2 = __instance.m_tempPlayerInfo[i];
				long playerId = GetPlayerId(val2);
				if (playerId == 0)
				{
					continue;
				}
				Vector3 position = val2.m_position;
				if (!playerData.TryGetValue(playerId, out var value))
				{
					value = new PlayerTrackData();
					playerData[playerId] = value;
					value.smoothPosition = position;
					value.lastRealPosition = position;
					value.lastUpdateTime = time;
				}
				float num = time - value.lastUpdateTime;
				if (num > 0.001f && num < 1f)
				{
					Vector3 val3 = position - value.lastRealPosition;
					float magnitude = ((Vector3)(ref val3)).magnitude;
					if (magnitude > TeleportThreshold)
					{
						value.wasTeleporting = true;
						value.teleportEndTime = time + 0.2f;
						value.lastRealVelocity = Vector3.zero;
					}
					else
					{
						value.lastRealVelocity = val3 / num;
						if (((Vector3)(ref value.lastRealVelocity)).magnitude > 100f)
						{
							value.lastRealVelocity = ((Vector3)(ref value.lastRealVelocity)).normalized * 100f;
						}
					}
				}
				value.lastRealPosition = position;
				value.lastUpdateTime = time;
				if (value.teleportEndTime > time)
				{
					val.m_pos = position;
					value.smoothPosition = position;
					value.smoothVelocity = Vector3.zero;
					continue;
				}
				if (value.wasTeleporting)
				{
					value.wasTeleporting = false;
				}
				Vector3 val4 = position;
				float num2 = time - value.lastUpdateTime;
				bool flag = serverModDetected == true;
				if (num2 > 0.033f && ((Vector3)(ref value.lastRealVelocity)).magnitude > 0.1f && !flag)
				{
					float num3 = Mathf.Min(num2, MaxPredictionTime);
					val4 = position + value.lastRealVelocity * num3;
				}
				float num4 = SmoothTime;
				float num5 = InterpolationSpeed;
				float num6 = Vector3.Distance(value.smoothPosition, val4);
				if (num6 > 30f)
				{
					num4 = 0.01f;
				}
				else if (num6 > 10f)
				{
					num4 = 0.02f;
				}
				if (flag)
				{
					num5 = InterpolationSpeed * 1.5f;
				}
				value.smoothPosition = Vector3.SmoothDamp(value.smoothPosition, val4, ref value.smoothVelocity, num4, num5, dt);
				val.m_pos = value.smoothPosition;
			}
		}

		private static void DetectServerMod(float now)
		{
			if (!serverModDetected.HasValue && (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer() && now - serverLastUpdateTime > 0.5f)
			{
				serverLastUpdateTime = now;
				List<ZNetPeer> peers = ZNet.instance.GetPeers();
				if (peers.Count > 0 && peers[0].m_rpc != null)
				{
					serverModDetected = false;
				}
			}
		}

		private static long GetPlayerId(PlayerInfo info)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (m_characterIDField != null)
				{
					object value = m_characterIDField.GetValue(info);
					if (value != null && m_userIDField != null)
					{
						return (long)m_userIDField.GetValue(value);
					}
				}
			}
			catch
			{
			}
			try
			{
				FieldInfo field = typeof(PlayerInfo).GetField("m_name");
				if (field != null)
				{
					string text = field.GetValue(info) as string;
					if (!string.IsNullOrEmpty(text))
					{
						return text.GetHashCode();
					}
				}
			}
			catch
			{
			}
			return 0L;
		}

		private static void CleanupOldData()
		{
			float time = Time.time;
			List<long> list = new List<long>();
			foreach (KeyValuePair<long, PlayerTrackData> playerDatum in playerData)
			{
				if (time - playerDatum.Value.lastUpdateTime > 10f)
				{
					list.Add(playerDatum.Key);
				}
			}
			foreach (long item in list)
			{
				playerData.Remove(item);
			}
		}
	}
	[BepInPlugin("VitByr.VBMapPingSmooth", "VBMapPingSmooth", "0.0.1")]
	public class VBMapPingSmooth : BaseUnityPlugin
	{
		private const string ModName = "VBMapPingSmooth";

		private const string ModVersion = "0.0.1";

		private const string ModGUID = "VitByr.VBMapPingSmooth";

		public static ConfigEntry<Language> ConfigLanguage;

		public static ConfigEntry<float> ConfigInterpolationSpeed;

		public static ConfigEntry<float> ConfigSmoothTime;

		public static ConfigEntry<float> ConfigTeleportThreshold;

		public static ConfigEntry<float> ConfigMaxPredictionTime;

		public static ConfigEntry<float> ConfigUpdateInterval;

		public static VBMapPingSmooth Instance { get; private set; }

		public void Awake()
		{
			Instance = this;
			InitConfig();
			Minimap_UpdatePlayerPins_Patch.InterpolationSpeed = ConfigInterpolationSpeed.Value;
			Minimap_UpdatePlayerPins_Patch.SmoothTime = ConfigSmoothTime.Value;
			Minimap_UpdatePlayerPins_Patch.TeleportThreshold = ConfigTeleportThreshold.Value;
			Minimap_UpdatePlayerPins_Patch.MaxPredictionTime = ConfigMaxPredictionTime.Value;
			ZNet_SendPeriodicData_Patch.UpdateInterval = ConfigUpdateInterval.Value;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "VitByr.VBMapPingSmooth");
		}

		private void InitConfig()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			ConfigLanguage = ((BaseUnityPlugin)this).Config.Bind<Language>("0 - General", "Language", Language.Russian, new ConfigDescription("Select interface language / Выберите язык интерфейса \nRequired Restart / Требуется рестарт", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigInterpolationSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Client", "InterpolationSpeed", 1000f, GetConfigDescription("Скорость интерполяции маркера (единиц/сек)\nЧем выше, тем быстрее маркер догоняет реальную позицию", "Marker interpolation speed (units/sec)\nHigher = faster marker catches up to real position", (AcceptableValueBase)(object)new AcceptableValueRange<float>(100f, 10000f)));
			ConfigSmoothTime = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Client", "SmoothTime", 0.033f, GetConfigDescription("Время сглаживания движения (сек)\nМеньше значение = быстрее реакция, но может быть дёргано\nРекомендуется: 0.016-0.066", "Smooth time (sec)\nLower = faster response, but may be jittery\nRecommended: 0.016-0.066", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.005f, 0.2f)));
			ConfigTeleportThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Client", "TeleportThreshold", 50f, GetConfigDescription("Дистанция для определения телепорта (метров)\nЕсли игрок переместился дальше этого значения за один кадр — считаем телепортом", "Distance for teleport detection (meters)\nIf player moves beyond this value in one frame - consider it a teleport", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f)));
			ConfigMaxPredictionTime = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Client", "MaxPredictionTime", 0.3f, GetConfigDescription("Максимальное время предсказания движения (сек)\nПри задержках маркер будет двигаться по инерции", "Maximum movement prediction time (sec)\nDuring lag, marker will move by inertia", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f)));
			ConfigUpdateInterval = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Server", "UpdateInterval", 0.5f, GetConfigDescription("Интервал отправки позиций игроков (сек)\nМеньше = плавнее, но больше нагрузка на сеть\nВаниль: 2.0, Рекомендуется: 0.1-0.5", "Player position update interval (sec)\nLower = smoother, but more network load\nVanilla: 2.0, Recommended: 0.1-0.5", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f)));
		}

		private ConfigDescription GetConfigDescription(string russianDesc, string englishDesc, AcceptableValueBase acceptableValues = null)
		{
			//IL_0034: 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_003a: Expected O, but got Unknown
			ConfigEntry<Language> configLanguage = ConfigLanguage;
			string text = ((configLanguage != null && configLanguage.Value == Language.English) ? englishDesc : russianDesc);
			return (acceptableValues != null) ? new ConfigDescription(text, acceptableValues, Array.Empty<object>()) : new ConfigDescription(text, (AcceptableValueBase)null, Array.Empty<object>());
		}
	}
	public enum Language
	{
		Russian,
		English
	}
	[HarmonyPatch(typeof(ZNet), "SendPeriodicData")]
	public static class ZNet_SendPeriodicData_Patch
	{
		private const float ORIGINAL_INTERVAL = 2f;

		public static float UpdateInterval = 0.1f;

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
			val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)2f, (string)null)
			});
			if (val.IsValid)
			{
				val.SetInstruction(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(ZNet_SendPeriodicData_Patch), "UpdateInterval")));
			}
			return val.InstructionEnumeration();
		}
	}
}