using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using GameData; using Gear; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using MTFO.API; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Mapper")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+66f3615c5d2fb24259bccfdb342828c4fcf59bf1")] [assembly: AssemblyProduct("Mapper")] [assembly: AssemblyTitle("Mapper")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class ChargeRatioRelay { private static float s_pendingRatio = -1f; private static int s_pendingPlayerID = -1; public static void Stash(int playerID, float ratio) { s_pendingPlayerID = playerID; s_pendingRatio = ratio; } public static bool TryConsume(int expectedPlayerID, out float ratio) { ratio = 0f; if (s_pendingRatio < 0f) { return false; } if (s_pendingPlayerID != expectedPlayerID) { return false; } ratio = s_pendingRatio; s_pendingRatio = -1f; s_pendingPlayerID = -1; return true; } } [HarmonyPatch(typeof(MapperDataCloud), "Activate")] public class MapperDataCloudActivatePatch { [HarmonyPrefix] private static void Prefix(MapperDataCloud __instance) { //IL_000f: 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_0031: Unknown result type (might be due to invalid IL or missing references) ((Behaviour)__instance).enabled = true; ((Component)__instance).transform.position = Vector3.zero; ((Component)__instance).transform.rotation = Quaternion.identity; ((Component)__instance).transform.localScale = Vector3.one; __instance.CountX = MapperFixSettings.DummyCountX; __instance.CountY = MapperFixSettings.DummyCountY; MethodInfo methodInfo = AccessTools.Method(typeof(MapperDataCloud), "InitParticles", (Type[])null, (Type[])null); methodInfo.Invoke(__instance, null); } [HarmonyPostfix] private static void Postfix(MapperDataCloud __instance) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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) if ((Object)(object)__instance.m_mapVisibilityTrans == (Object)null) { Camera main = Camera.main; if ((Object)(object)main != (Object)null) { __instance.m_mapVisibilityTrans = ((Component)main).transform; } } LayerMask maskMapperDataObject = __instance.m_maskMapperDataObject; if (((LayerMask)(ref maskMapperDataObject)).value == 0) { __instance.m_maskMapperDataObject = LayerMask.op_Implicit(-1); } } } [HarmonyPatch(typeof(MapperDataCloud), "Update")] public class MapperDataCloudCleanupPatch { private static Dictionary s_deactivateStartTime = new Dictionary(); [HarmonyPostfix] private static void Postfix(MapperDataCloud __instance) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 int instanceID = ((Object)__instance).GetInstanceID(); if ((int)__instance.m_state == 3) { if (!s_deactivateStartTime.ContainsKey(instanceID)) { s_deactivateStartTime[instanceID] = Time.time; } else if (Time.time - s_deactivateStartTime[instanceID] > MapperFixSettings.DeactivatingTimeout) { s_deactivateStartTime.Remove(instanceID); Object.Destroy((Object)(object)((Component)__instance).gameObject); } } else { s_deactivateStartTime.Remove(instanceID); } } } [HarmonyPatch(typeof(MapperDataCloudManager), "DoSpawnMapperDataCloud")] public class MapperDataCloudManagerPatch { [HarmonyPatch(typeof(MapperDataCloudManager), "DoSpawnMapperDataCloud")] public class MapperDataCloudManagerStackTracePatch { [HarmonyPrefix] private static void Prefix(pSpawnMapperDataCloud data) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (MapperFixSettings.VerboseLogging) { StackTrace stackTrace = new StackTrace(1, fNeedFileInfo: true); ManualLogSource log = MapperFixPlugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(63, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[CallStack diag] DoSpawnMapperDataCloud playerID="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.playerID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", cloudDepth="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.cloudDepth); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\n"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(stackTrace); } log.LogInfo(val); } } } private static readonly Dictionary s_lastSpawnTime = new Dictionary(); [HarmonyPrefix] private static void Prefix(MapperDataCloudManager __instance, ref pSpawnMapperDataCloud data) { if (!((Object)(object)__instance.m_mapperCloudPrefab != (Object)null) || !((Object)(object)__instance.m_mapperDataScanPointPrefab != (Object)null)) { if ((Object)(object)MapperFixPlugin.CachedCloudTemplate != (Object)null && (Object)(object)MapperFixPlugin.CachedScanPointTemplate != (Object)null) { __instance.m_mapperCloudPrefab = MapperFixPlugin.CachedCloudTemplate; __instance.m_mapperDataScanPointPrefab = MapperFixPlugin.CachedScanPointTemplate; return; } GameObject val = BuildDummyCloud(); Object.DontDestroyOnLoad((Object)(object)val); MapperFixPlugin.CachedCloudTemplate = val; GameObject val2 = BuildDummyScanPoint(); Object.DontDestroyOnLoad((Object)(object)val2); MapperFixPlugin.CachedScanPointTemplate = val2; __instance.m_mapperCloudPrefab = val; __instance.m_mapperDataScanPointPrefab = val2; } } [HarmonyPostfix] private static void Postfix(pSpawnMapperDataCloud data) { //IL_0001: 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) //IL_0031: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: 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_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) int playerID = data.playerID; float time = Time.time; if (MapperFixSettings.VerboseLogging) { ManualLogSource log = MapperFixPlugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(110, 9, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[pSpawnMapperDataCloud diag] shape="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.shape); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" playerID="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.playerID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("scanPos="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.scanPos); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" dirFwd="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.dirFwd); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" cloudDepth="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.cloudDepth); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("corner1="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.frustrumCorner1); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" corner2="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.frustrumCorner2); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("corner3="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.frustrumCorner3); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" corner4="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(data.frustrumCorner4); } log.LogInfo(val); } if (s_lastSpawnTime.TryGetValue(playerID, out var value) && time - value < MapperFixSettings.SequenceCooldown) { s_lastSpawnTime[playerID] = time; return; } s_lastSpawnTime[playerID] = time; Quaternion rot = ((data.dirFwd != Vector3.zero) ? Quaternion.LookRotation(data.dirFwd) : Quaternion.identity); float? chargeRatio = (MapperFixSettings.EnableChargeBasedScaling ? new float?(Mathf.Clamp01(data.cloudDepth)) : ((float?)null)); MapperFixPlugin.SpawnXRayEffectAt(data.scanPos, rot, chargeRatio); } private static GameObject BuildDummyCloud() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DummyMapperCloud"); MapperDataCloud val2 = ((Il2CppObjectBase)val.AddComponent(Il2CppType.Of())).Cast(); ParticleSystem val3 = val.AddComponent(); val3.Stop(true, (ParticleSystemStopBehavior)0); EmissionModule emission = val3.emission; emission.enabled = false; emission.rateOverTime = MinMaxCurve.op_Implicit(0f); Component component = val.GetComponent(Il2CppType.Of()); ParticleSystemRenderer val4 = ((component != null) ? ((Il2CppObjectBase)component).Cast() : null); if ((Object)(object)val4 != (Object)null) { ((Renderer)val4).enabled = false; } val2.m_particleSystem = val3; val2.CountX = MapperFixSettings.DummyCountX; val2.CountY = MapperFixSettings.DummyCountY; val2.ScansPerUpdate = 4; val2.ParticleLifeTime = MapperFixSettings.DummyParticleLifeTime; val2.ParticleLifeTimeResource = MapperFixSettings.DummyParticleLifeTime; val.transform.position = new Vector3(0f, -10000f, 0f); ((Behaviour)val2).enabled = false; return val; } private static GameObject BuildDummyScanPoint() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DummyMapperScanPoint"); MapperDataScanPoint val2 = ((Il2CppObjectBase)val.AddComponent(Il2CppType.Of())).Cast(); ParticleSystem val3 = val.AddComponent(); val3.Stop(true, (ParticleSystemStopBehavior)0); EmissionModule emission = val3.emission; emission.enabled = false; emission.rateOverTime = MinMaxCurve.op_Implicit(0f); val2.m_particleSystem = val3; val.transform.position = new Vector3(0f, -10000f, 0f); ((Behaviour)val2).enabled = false; return val; } } [HarmonyPatch(typeof(MapperDataCloudManager), "Setup")] public class MapperDataCloudManagerSNetDiagPatch { private static bool s_alreadyLogged; [HarmonyPostfix] private static void Postfix(MapperDataCloudManager __instance) { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Expected O, but got Unknown //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Expected O, but got Unknown if (s_alreadyLogged) { return; } s_alreadyLogged = true; try { object spawnMapperDataCloud = __instance.m_spawnMapperDataCloud; if (spawnMapperDataCloud == null) { MapperFixPlugin.Log.LogWarning((object)"[SNetDiag] m_spawnMapperDataCloud is null at Setup time."); return; } Type type = spawnMapperDataCloud.GetType(); MapperFixPlugin.Log.LogInfo((object)("[SNetDiag] broadcastAction runtime type: " + type.FullName)); FieldInfo fieldInfo = null; Type type2 = type; while (type2 != null && fieldInfo == null) { fieldInfo = type2.GetField("m_packet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); type2 = type2.BaseType; } object obj = null; if (fieldInfo != null) { obj = fieldInfo.GetValue(spawnMapperDataCloud); MapperFixPlugin.Log.LogInfo((object)"[SNetDiag] found m_packet via FIELD."); } else { PropertyInfo propertyInfo = null; type2 = type; while (type2 != null && propertyInfo == null) { propertyInfo = type2.GetProperty("m_packet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); type2 = type2.BaseType; } if (propertyInfo != null) { obj = propertyInfo.GetValue(spawnMapperDataCloud); MapperFixPlugin.Log.LogInfo((object)"[SNetDiag] found m_packet via PROPERTY."); } } bool flag = default(bool); if (obj == null) { MapperFixPlugin.Log.LogWarning((object)"[SNetDiag] m_packet not found directly. Dumping all members instead:"); type2 = type; while (type2 != null) { ManualLogSource log = MapperFixPlugin.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SNetDiag] -- members of "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(type2.FullName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" --"); } log.LogInfo(val); FieldInfo[] fields = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields) { ManualLogSource log2 = MapperFixPlugin.Log; val = new BepInExInfoLogInterpolatedStringHandler(19, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SNetDiag] field: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(fieldInfo2.FieldType.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(fieldInfo2.Name); } log2.LogInfo(val); } PropertyInfo[] properties = type2.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo2 in properties) { ManualLogSource log3 = MapperFixPlugin.Log; val = new BepInExInfoLogInterpolatedStringHandler(22, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SNetDiag] property: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(propertyInfo2.PropertyType.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(propertyInfo2.Name); } log3.LogInfo(val); } type2 = type2.BaseType; } return; } Type type3 = obj.GetType(); MapperFixPlugin.Log.LogInfo((object)("[SNetDiag] packet runtime type: " + type3.FullName)); MethodInfo[] methods = type3.GetMethods(BindingFlags.Instance | BindingFlags.Public); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { ParameterInfo[] parameters = methodInfo.GetParameters(); string text = string.Join(", ", Array.ConvertAll(parameters, (ParameterInfo p) => p.ParameterType.Name + " " + p.Name)); ManualLogSource log4 = MapperFixPlugin.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(32, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SNetDiag] packet method: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(methodInfo.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") -> "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(methodInfo.ReturnType.Name); } log4.LogInfo(val); } } catch (Exception ex) { MapperFixPlugin.Log.LogError((object)("[SNetDiag] threw: " + ex)); } } } [HarmonyPatch(typeof(MapperDataCloudManager), "WantSpawnMapperDataCloud")] public class MapperDataCloudManagerWantSpawnPatch { [HarmonyPrefix] private static void Prefix(int playerID, ref float cloudDepth) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown if (!ChargeRatioRelay.TryConsume(playerID, out var ratio)) { return; } cloudDepth = ratio; if (MapperFixSettings.VerboseLogging) { ManualLogSource log = MapperFixPlugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(46, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[ChargeRelay] Overwrote cloudDepth with ratio="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ratio, "F2"); } log.LogInfo(val); } } } [HarmonyPatch(typeof(MapperDataCloudScanner), "Scan")] public class MapperDataCloudScannerGatePatch { [HarmonyPrefix] private static bool Prefix(MapperDataCloudScanner __instance, int scanDepthStep) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown bool flag = MapperFixPlugin.IsTargetGear(__instance); if (flag && scanDepthStep == 0) { MapperTool parentTool = __instance.m_parentTool; bool flag2 = default(bool); if ((Object)(object)parentTool != (Object)null && MapperFixSettings.VerboseLogging) { ManualLogSource log = MapperFixPlugin.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(116, 5, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[ChargeFields RAW] m_currentChargeUp="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(parentTool.m_currentChargeUp); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("m_lastFireChargeUp="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(parentTool.m_lastFireChargeUp); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("m_chargeUpMaxTime="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(parentTool.m_chargeUpMaxTime); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("m_minChargeUpToFire="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(parentTool.m_minChargeUpToFire); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ScanStepsToMaxDis="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(__instance.ScanStepsToMaxDis); } log.LogInfo(val); } if ((Object)(object)parentTool != (Object)null && MapperFixSettings.EnableChargeBasedScaling) { float num = Mathf.Clamp01(parentTool.m_lastFireChargeUp); int playerSlotIndex = ((Item)parentTool).Owner.PlayerSlotIndex; ChargeRatioRelay.Stash(playerSlotIndex, num); if (MapperFixSettings.VerboseLogging) { ManualLogSource log2 = MapperFixPlugin.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(40, 2, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[LocalCharge] m_lastFireChargeUp="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(parentTool.m_lastFireChargeUp); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ratio="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num, "F2"); } log2.LogInfo(val); } } } return flag; } } [HarmonyPatch(typeof(MapperDataCloud), "ScanParticle")] public class MapperDataCloudScanParticlePatch { [HarmonyPrefix] private static void Prefix(MapperDataCloud __instance, int index) { if (__instance.m_currentIndex <= index) { __instance.m_currentIndex = index + 1; } } [HarmonyFinalizer] private static Exception Finalizer(Exception __exception) { return null; } } [BepInPlugin("DarkEmperor.mapperfix", "Mapper Cloud Fix", "1.0.0")] public class MapperFixPlugin : BasePlugin { public static GameObject CachedCloudTemplate; public static GameObject CachedScanPointTemplate; private static AssetBundle s_cachedBundle; private static GameObject s_cachedXraysPrefab; internal static ManualLogSource Log = Logger.CreateLogSource("MapperFix"); private FileSystemWatcher _configWatcher; private static DateTime s_lastReloadUtc = DateTime.MinValue; public override void Load() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown MapperFixSettings.LoadOrCreate(); SetupConfigHotReload(); Harmony val = new Harmony("DarkEmperor.mapperfix"); try { val.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception ex) { Log.LogError((object)("PatchAll threw: " + ex)); } foreach (MethodBase patchedMethod in val.GetPatchedMethods()) { Log.LogInfo((object)("Patched: " + patchedMethod.DeclaringType?.ToString() + "." + patchedMethod.Name)); } ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Mapper cloud fix loaded. Settings: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(MapperFixSettings.FilePath); } log.LogInfo(val2); } private void SetupConfigHotReload() { try { string directoryName = Path.GetDirectoryName(MapperFixSettings.FilePath); string fileName = Path.GetFileName(MapperFixSettings.FilePath); _configWatcher = new FileSystemWatcher(directoryName, fileName); _configWatcher.NotifyFilter = NotifyFilters.LastWrite; _configWatcher.Changed += OnConfigFileChanged; _configWatcher.EnableRaisingEvents = true; Log.LogInfo((object)"Config hot-reload enabled — settings.jsonc 파일을 저장하면 즉시 반영됩니다."); } catch (Exception ex) { Log.LogWarning((object)("Failed to set up config hot-reload: " + ex.Message)); } } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { DateTime utcNow = DateTime.UtcNow; if ((utcNow - s_lastReloadUtc).TotalMilliseconds < 500.0) { return; } s_lastReloadUtc = utcNow; Thread.Sleep(150); try { MapperFixSettings.Load(); Log.LogInfo((object)"settings.jsonc hot-reloaded from disk."); } catch (Exception ex) { Log.LogWarning((object)("settings.jsonc reload failed: " + ex.Message)); } } public static AssetBundle FindLoadedBundle(string nameContains) { Il2CppReferenceArray val = Resources.FindObjectsOfTypeAll(Il2CppType.Of()); for (int i = 0; i < ((Il2CppArrayBase)(object)val).Length; i++) { Object val2 = ((Il2CppArrayBase)(object)val)[i]; if (!(val2 == (Object)null)) { AssetBundle val3 = ((Il2CppObjectBase)val2).Cast(); if ((Object)(object)val3 != (Object)null && ((Object)val3).name.ToLower().Contains(nameContains.ToLower())) { return val3; } } } return null; } public static bool IsTargetGear(MapperDataCloudScanner scanner) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown try { MapperTool parentTool = scanner.m_parentTool; if ((Object)(object)parentTool == (Object)null) { Log.LogWarning((object)"IsTargetGear: m_parentTool is null, allowing by default."); return true; } GearCategoryDataBlock gearCategoryData = ((ItemEquippable)parentTool).GearCategoryData; if (gearCategoryData == null) { Log.LogWarning((object)"IsTargetGear: GearCategoryData is null, allowing by default."); return true; } if (TryGetPersistentID(gearCategoryData, out var persistentID)) { bool flag = persistentID == MapperFixSettings.TargetGearPersistentID; if (MapperFixSettings.VerboseLogging) { ManualLogSource log = Log; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(51, 3, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[IsTargetGear] found persistentID="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(persistentID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", target="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(MapperFixSettings.TargetGearPersistentID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", match="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(flag); } log.LogInfo(val); } return flag; } Log.LogWarning((object)"IsTargetGear: couldn't read persistentID, allowing by default."); return true; } catch (Exception ex) { Log.LogWarning((object)("IsTargetGear check threw: " + ex)); return true; } } private static bool TryGetPersistentID(object dataBlock, out uint persistentID) { persistentID = 0u; if (dataBlock == null) { return false; } try { Type type = dataBlock.GetType(); PropertyInfo propertyInfo = type.GetProperty("persistentID") ?? type.GetProperty("PersistentID") ?? type.GetProperty("PersistentId"); if (propertyInfo != null) { persistentID = Convert.ToUInt32(propertyInfo.GetValue(dataBlock)); return true; } FieldInfo fieldInfo = type.GetField("persistentID") ?? type.GetField("PersistentID"); if (fieldInfo != null) { persistentID = Convert.ToUInt32(fieldInfo.GetValue(dataBlock)); return true; } } catch (Exception ex) { Log.LogWarning((object)("TryGetPersistentID reflection failed: " + ex.Message)); } return false; } public static void SpawnXRayEffectAt(Vector3 pos, Quaternion rot, float? chargeRatio = null) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Expected O, but got Unknown //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Expected O, but got Unknown //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_cachedXraysPrefab == (Object)null) { if ((Object)(object)s_cachedBundle == (Object)null) { s_cachedBundle = FindLoadedBundle(MapperFixSettings.BundleNameFilter); if ((Object)(object)s_cachedBundle == (Object)null) { Log.LogWarning((object)"Bundle not loaded, can't spawn XRay effect."); return; } } Object obj = s_cachedBundle.LoadAsset(MapperFixSettings.XraysPrefabPath, Il2CppType.Of()); s_cachedXraysPrefab = ((obj != null) ? ((Il2CppObjectBase)obj).Cast() : null); if ((Object)(object)s_cachedXraysPrefab == (Object)null) { Log.LogWarning((object)"xrays.prefab not found in bundle."); return; } } GameObject val = Object.Instantiate(s_cachedXraysPrefab, pos, rot); ((Object)val).name = "XRayEffect_Live"; Il2CppReferenceArray componentsInChildren = val.GetComponentsInChildren(Il2CppType.Of()); for (int i = 0; i < ((Il2CppArrayBase)(object)componentsInChildren).Length; i++) { Component obj2 = ((Il2CppArrayBase)(object)componentsInChildren)[i]; LineRenderer val2 = ((obj2 != null) ? ((Il2CppObjectBase)obj2).Cast() : null); if ((Object)(object)val2 != (Object)null) { ((Renderer)val2).enabled = false; } } Component component = val.GetComponent(Il2CppType.Of()); XRays xraysComp = ((component != null) ? ((Il2CppObjectBase)component).Cast() : null); if (MapperFixSettings.EnableXRaysCustomization) { ApplyXRaysCustomization(val); } bool flag = default(bool); if (MapperFixSettings.EnableChargeBasedScaling && (Object)(object)xraysComp != (Object)null && chargeRatio.HasValue) { float value = chargeRatio.Value; float range = Mathf.Lerp(MapperFixSettings.MinRangeAtNoCharge, MapperFixSettings.MaxRangeAtFullCharge, value); float square = Mathf.Lerp(MapperFixSettings.MinSquareAtNoCharge, MapperFixSettings.MaxSquareAtFullCharge, value); float fov = Mathf.Lerp(MapperFixSettings.MinFieldOfViewAtNoCharge, MapperFixSettings.MaxFieldOfViewAtFullCharge, value); TrySet(delegate { xraysComp.maxDistance = range; }, "XRays.maxDistance (charge scaling)"); TrySet(delegate { xraysComp.square = square; }, "XRays.square (charge scaling)"); TrySet(delegate { xraysComp.fieldOfView = fov; }, "XRays.fieldOfView (charge scaling)"); if (MapperFixSettings.VerboseLogging) { ManualLogSource log = Log; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(42, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[ChargeScaling] ratio="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(value, "F2"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" range="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(range, "F1"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" square="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(square, "F2"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" fov="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(fov, "F1"); } log.LogInfo(val3); } } float emitDuration = MapperFixSettings.EmitDuration; if ((Object)(object)xraysComp != (Object)null) { Object.Destroy((Object)(object)xraysComp, emitDuration); } Object.Destroy((Object)(object)val, emitDuration + MapperFixSettings.CleanupSafetyBuffer); if (MapperFixSettings.VerboseLogging) { ManualLogSource log2 = Log; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(33, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Spawned xrays.prefab at pos="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(pos); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" rot="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(((Quaternion)(ref rot)).eulerAngles); } log2.LogInfo(val3); } } private static void ApplyXRaysCustomization(GameObject instance) { Component component = instance.GetComponent(Il2CppType.Of()); XRays xraysComp = ((component != null) ? ((Il2CppObjectBase)component).Cast() : null); if ((Object)(object)xraysComp != (Object)null) { TrySet(delegate { //IL_000c: Unknown result type (might be due to invalid IL or missing references) xraysComp.scanMode = ParseEnum(MapperFixSettings.ScanMode, (ScanMode)0); }, "XRays.scanMode"); TrySet(delegate { //IL_000c: Unknown result type (might be due to invalid IL or missing references) xraysComp.scanDirection = ParseEnum(MapperFixSettings.ScanDirection, (ScanDirection)0); }, "XRays.scanDirection"); TrySet(delegate { xraysComp.swipeSpeed = MapperFixSettings.SwipeSpeed; }, "XRays.swipeSpeed"); TrySet(delegate { xraysComp.raysPerSecond = MapperFixSettings.RaysPerSecond; }, "XRays.raysPerSecond"); TrySet(delegate { xraysComp.fieldOfView = MapperFixSettings.FieldOfView; }, "XRays.fieldOfView"); TrySet(delegate { xraysComp.fieldOfViewFocused = MapperFixSettings.FieldOfViewFocused; }, "XRays.fieldOfViewFocused"); TrySet(delegate { xraysComp.square = MapperFixSettings.Square; }, "XRays.square"); TrySet(delegate { xraysComp.maxDistance = MapperFixSettings.MaxDistance; }, "XRays.maxDistance"); TrySet(delegate { xraysComp.forwardStepSize = MapperFixSettings.ForwardStepSize; }, "XRays.forwardStepSize"); TrySet(delegate { //IL_000b: Unknown result type (might be due to invalid IL or missing references) xraysComp.defaultColor = MapperFixSettings.ParseColor(MapperFixSettings.DefaultColor); }, "XRays.defaultColor"); TrySet(delegate { xraysComp.defaultSize = MapperFixSettings.DefaultSize; }, "XRays.defaultSize"); TrySet(delegate { //IL_000b: Unknown result type (might be due to invalid IL or missing references) xraysComp.enemyColor = MapperFixSettings.ParseColor(MapperFixSettings.EnemyColor); }, "XRays.enemyColor"); TrySet(delegate { xraysComp.enemySize = MapperFixSettings.EnemySize; }, "XRays.enemySize"); TrySet(delegate { //IL_000b: Unknown result type (might be due to invalid IL or missing references) xraysComp.interactionColor = MapperFixSettings.ParseColor(MapperFixSettings.InteractionColor); }, "XRays.interactionColor"); TrySet(delegate { xraysComp.interactionSize = MapperFixSettings.InteractionSize; }, "XRays.interactionSize"); } Component componentInChildren = instance.GetComponentInChildren(Il2CppType.Of()); XRayRenderer rendererComp = ((componentInChildren != null) ? ((Il2CppObjectBase)componentInChildren).Cast() : null); if (!((Object)(object)rendererComp != (Object)null)) { return; } TrySet(delegate { rendererComp.castShadows = MapperFixSettings.CastShadows; }, "XRayRenderer.castShadows"); TrySet(delegate { rendererComp.updateBounds = MapperFixSettings.UpdateBounds; }, "XRayRenderer.updateBounds"); TrySet(delegate { rendererComp.alignToView = MapperFixSettings.AlignToView; }, "XRayRenderer.alignToView"); TrySet(delegate { rendererComp.alignToVelocity = MapperFixSettings.AlignToVelocity; }, "XRayRenderer.alignToVelocity"); TrySet(delegate { rendererComp.range = MapperFixSettings.Range; }, "XRayRenderer.range"); TrySet(delegate { rendererComp.mode = MapperFixSettings.RendererMode; }, "XRayRenderer.mode"); TrySet(delegate { rendererComp.duration = MapperFixSettings.Duration; }, "XRayRenderer.duration"); TrySet(delegate { rendererComp.timescale = MapperFixSettings.Timescale; }, "XRayRenderer.timescale"); TrySet(delegate { rendererComp.playOnAwake = MapperFixSettings.PlayOnAwake; }, "XRayRenderer.playOnAwake"); TrySet(delegate { rendererComp.loop = MapperFixSettings.Loop; }, "XRayRenderer.loop"); TrySet(delegate { rendererComp.simulateInPlayer = MapperFixSettings.SimulateInPlayer; }, "XRayRenderer.simulateInPlayer"); if (MapperFixSettings.InstanceCount >= 0) { TrySet(delegate { rendererComp.instanceCount = MapperFixSettings.InstanceCount; }, "XRayRenderer.instanceCount"); } } private static T ParseEnum(string value, T fallback) where T : struct { T result; return Enum.TryParse(value, ignoreCase: true, out result) ? result : fallback; } private static void TrySet(Action setter, string fieldName) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown try { setter(); } catch (Exception ex) { if (MapperFixSettings.VerboseLogging) { ManualLogSource log = Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(16, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to set "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(fieldName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogWarning(val); } } } } public static class MapperFixSettings { public static float EmitDuration = 2f; public static float CleanupSafetyBuffer = 5f; public static float DeactivatingTimeout = 3f; public static int DummyCountX = 4; public static int DummyCountY = 4; public static float DummyParticleLifeTime = 0.5f; public static string BundleNameFilter = "xrays"; public static string XraysPrefabPath = "Assets/XRays/XRays.prefab"; public static bool VerboseLogging = false; public static uint TargetGearPersistentID = 10u; public static float SequenceCooldown = 1.5f; public static bool EnableXRaysCustomization = false; public static bool EnableChargeBasedScaling = false; public static float MinRangeAtNoCharge = 10f; public static float MaxRangeAtFullCharge = 30f; public static float MinSquareAtNoCharge = 0.3f; public static float MaxSquareAtFullCharge = 1f; public static float MinFieldOfViewAtNoCharge = 20f; public static float MaxFieldOfViewAtFullCharge = 60f; public static string ScanMode = "Random"; public static string ScanDirection = "X"; public static float SwipeSpeed = 4f; public static int RaysPerSecond = 10000; public static float FieldOfView = 55f; public static float FieldOfViewFocused = 15f; public static float Square = 0.2f; public static float MaxDistance = 20f; public static float ForwardStepSize = 3f; public static string DefaultColor = "0,1,0.972549,0.16"; public static float DefaultSize = 1f; public static string EnemyColor = "1,0,0,0.501"; public static float EnemySize = 1f; public static string InteractionColor = "1,0.490196,0,0.078"; public static float InteractionSize = 1f; public static bool CastShadows = false; public static bool UpdateBounds = false; public static bool AlignToView = true; public static bool AlignToVelocity = false; public static float Range = 50f; public static int RendererMode = 0; public static float Duration = 5f; public static float Timescale = 1f; public static bool PlayOnAwake = false; public static bool Loop = false; public static bool SimulateInPlayer = true; public static int InstanceCount = -1; private static readonly Regex LinePattern = new Regex("^\\s*\"(?\\w+)\"\\s*:\\s*(?\"(?:[^\"\\\\]|\\\\.)*\"|true|false|-?\\d+(?:\\.\\d+)?)\\s*,?\\s*$", RegexOptions.Compiled); public static string FilePath { get; private set; } public static void LoadOrCreate() { string text; if (MTFOPathAPI.HasCustomPath) { text = Path.Combine(MTFOPathAPI.CustomPath, "mapper"); MapperFixPlugin.Log.LogInfo((object)("Using MTFO custom path: " + MTFOPathAPI.CustomPath)); } else { text = Path.Combine(Paths.ConfigPath, "custom", "mapper"); MapperFixPlugin.Log.LogWarning((object)("MTFOPathAPI.HasCustomPath is false. Falling back to: " + text)); } Directory.CreateDirectory(text); FilePath = Path.Combine(text, "mappersettings.jsonc"); if (File.Exists(FilePath)) { Load(); } else { Save(); } } public static void Load() { if (FilePath != null && File.Exists(FilePath)) { Dictionary values = ParseJsonc(File.ReadAllText(FilePath)); EmitDuration = GetFloat(values, "EmitDuration", EmitDuration); CleanupSafetyBuffer = GetFloat(values, "CleanupSafetyBuffer", CleanupSafetyBuffer); DeactivatingTimeout = GetFloat(values, "DeactivatingTimeout", DeactivatingTimeout); DummyCountX = GetInt(values, "DummyCountX", DummyCountX); DummyCountY = GetInt(values, "DummyCountY", DummyCountY); DummyParticleLifeTime = GetFloat(values, "DummyParticleLifeTime", DummyParticleLifeTime); BundleNameFilter = GetString(values, "BundleNameFilter", BundleNameFilter); XraysPrefabPath = GetString(values, "XraysPrefabPath", XraysPrefabPath); VerboseLogging = GetBool(values, "VerboseLogging", VerboseLogging); TargetGearPersistentID = (uint)GetInt(values, "TargetGearPersistentID", (int)TargetGearPersistentID); SequenceCooldown = GetFloat(values, "SequenceCooldown", SequenceCooldown); EnableXRaysCustomization = GetBool(values, "EnableXRaysCustomization", EnableXRaysCustomization); EnableChargeBasedScaling = GetBool(values, "EnableChargeBasedScaling", EnableChargeBasedScaling); MinRangeAtNoCharge = GetFloat(values, "MinRangeAtNoCharge", MinRangeAtNoCharge); MaxRangeAtFullCharge = GetFloat(values, "MaxRangeAtFullCharge", MaxRangeAtFullCharge); MinSquareAtNoCharge = GetFloat(values, "MinSquareAtNoCharge", MinSquareAtNoCharge); MaxSquareAtFullCharge = GetFloat(values, "MaxSquareAtFullCharge", MaxSquareAtFullCharge); MinFieldOfViewAtNoCharge = GetFloat(values, "MinFieldOfViewAtNoCharge", MinFieldOfViewAtNoCharge); MaxFieldOfViewAtFullCharge = GetFloat(values, "MaxFieldOfViewAtFullCharge", MaxFieldOfViewAtFullCharge); ScanMode = GetString(values, "ScanMode", ScanMode); ScanDirection = GetString(values, "ScanDirection", ScanDirection); SwipeSpeed = GetFloat(values, "SwipeSpeed", SwipeSpeed); RaysPerSecond = GetInt(values, "RaysPerSecond", RaysPerSecond); FieldOfView = GetFloat(values, "FieldOfView", FieldOfView); FieldOfViewFocused = GetFloat(values, "FieldOfViewFocused", FieldOfViewFocused); Square = GetFloat(values, "Square", Square); MaxDistance = GetFloat(values, "MaxDistance", MaxDistance); ForwardStepSize = GetFloat(values, "ForwardStepSize", ForwardStepSize); DefaultColor = GetString(values, "DefaultColor", DefaultColor); DefaultSize = GetFloat(values, "DefaultSize", DefaultSize); EnemyColor = GetString(values, "EnemyColor", EnemyColor); EnemySize = GetFloat(values, "EnemySize", EnemySize); InteractionColor = GetString(values, "InteractionColor", InteractionColor); InteractionSize = GetFloat(values, "InteractionSize", InteractionSize); CastShadows = GetBool(values, "CastShadows", CastShadows); UpdateBounds = GetBool(values, "UpdateBounds", UpdateBounds); AlignToView = GetBool(values, "AlignToView", AlignToView); AlignToVelocity = GetBool(values, "AlignToVelocity", AlignToVelocity); Range = GetFloat(values, "Range", Range); RendererMode = GetInt(values, "RendererMode", RendererMode); Duration = GetFloat(values, "Duration", Duration); Timescale = GetFloat(values, "Timescale", Timescale); PlayOnAwake = GetBool(values, "PlayOnAwake", PlayOnAwake); Loop = GetBool(values, "Loop", Loop); SimulateInPlayer = GetBool(values, "SimulateInPlayer", SimulateInPlayer); InstanceCount = GetInt(values, "InstanceCount", InstanceCount); } } public static void Save() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("{"); AppendSectionHeader(stringBuilder, "Identity"); AppendField(stringBuilder, "TargetGearPersistentID", (int)TargetGearPersistentID, "Works only when fired from the Gear with this persistentID (default 10 = Mapper)"); AppendSectionHeader(stringBuilder, "Advanced"); AppendField(stringBuilder, "BundleNameFilter", BundleNameFilter, "Search keyword for the name of the AssetBundle containing xrays.prefab"); AppendField(stringBuilder, "XraysPrefabPath", XraysPrefabPath, "The exact path to xrays.prefab in the bundle"); AppendSectionHeader(stringBuilder, "Effect"); AppendField(stringBuilder, "EmitDuration", EmitDuration, "Time (seconds) during which the xrays effect continues to shoot new particles when the mapper is fired"); AppendField(stringBuilder, "CleanupSafetyBuffer", CleanupSafetyBuffer, "Additional waiting time (in seconds) after EmitDuration until the object is completely destroyed"); AppendField(stringBuilder, "SequenceCooldown", SequenceCooldown, "If the same player signal arrives again within this time (seconds), it is considered the same firing sequence and does not respawn."); AppendSectionHeader(stringBuilder, "ChargeBasedScaling"); AppendField(stringBuilder, "EnableChargeBasedScaling", EnableChargeBasedScaling, "Whether to adjust range/area proportional to charge amount (number of scan steps). Accurately reflected only on the shooter's own screen (remote players may see the default value)."); AppendField(stringBuilder, "MinRangeAtNoCharge", MinRangeAtNoCharge, "Range (maxDistance) when charge is 0%"); AppendField(stringBuilder, "MaxRangeAtFullCharge", MaxRangeAtFullCharge, "Range (maxDistance) when charged to 100%"); AppendField(stringBuilder, "MinSquareAtNoCharge", MinSquareAtNoCharge, "Scan range ratio at 0% charge (square, 0~1)"); AppendField(stringBuilder, "MaxSquareAtFullCharge", MaxSquareAtFullCharge, "Scan range ratio at 100% charge (square, 0~1)"); AppendField(stringBuilder, "MinFieldOfViewAtNoCharge", MinFieldOfViewAtNoCharge, "Scan field of view (fieldOfView, 0~90) when charge is 0%"); AppendField(stringBuilder, "MaxFieldOfViewAtFullCharge", MaxFieldOfViewAtFullCharge, "Scan field of view (fieldOfView, 0~90) when charge is 0%"); AppendSectionHeader(stringBuilder, "XRaysCustomization"); AppendField(stringBuilder, "EnableXRaysCustomization", EnableXRaysCustomization, "It must be true for the XRays/XRayRenderer settings below to be actually applied (if false, the original prefab is used)."); AppendSectionHeader(stringBuilder, "XRays"); AppendField(stringBuilder, "ScanMode", ScanMode, "ScanMode: Random / SwipeLoop / SwipePingPong"); AppendField(stringBuilder, "ScanDirection", ScanDirection, "ScanDirection: X / Y"); AppendField(stringBuilder, "SwipeSpeed", SwipeSpeed, "SwipeSpeed"); AppendField(stringBuilder, "RaysPerSecond", RaysPerSecond, "Number of rays fired per second"); AppendField(stringBuilder, "FieldOfView", FieldOfView, "Scan field of view (0~90)"); AppendField(stringBuilder, "FieldOfViewFocused", FieldOfViewFocused, "Narrowing field of view when aiming (0~90)"); AppendField(stringBuilder, "Square", Square, "Scan range aspect ratio correction (0~1)"); AppendField(stringBuilder, "MaxDistance", MaxDistance, "Maximum scan distance"); AppendField(stringBuilder, "ForwardStepSize", ForwardStepSize, "Forward scan step interval"); AppendField(stringBuilder, "DefaultColor", DefaultColor, "General surface particle color \"R,G,B,A\" (0~1)"); AppendField(stringBuilder, "DefaultSize", DefaultSize, "General surface particle size"); AppendField(stringBuilder, "EnemyColor", EnemyColor, "Enemy indicator particle color \"R,G,B,A\""); AppendField(stringBuilder, "EnemySize", EnemySize, "Enemy display particle size"); AppendField(stringBuilder, "InteractionColor", InteractionColor, "Interaction object display color \"R,G,B,A\""); AppendField(stringBuilder, "InteractionSize", InteractionSize, "Interaction object display size"); AppendSectionHeader(stringBuilder, "XRayRenderer"); AppendField(stringBuilder, "CastShadows", CastShadows, "Whether or not to have particle shadows"); AppendField(stringBuilder, "UpdateBounds", UpdateBounds, "Whether to update rendering bounds every frame"); AppendField(stringBuilder, "AlignToView", AlignToView, "Whether the billboard is always aligned facing the camera"); AppendField(stringBuilder, "AlignToVelocity", AlignToVelocity, "Whether to draw by stretching in the direction of movement"); AppendField(stringBuilder, "Range", Range, "Maximum rendering range"); AppendField(stringBuilder, "RendererMode", RendererMode, "Internal rendering mode value (default recommended)"); AppendField(stringBuilder, "Duration", Duration, "Total effect duration (seconds)"); AppendField(stringBuilder, "Timescale", Timescale, "Effect playback speed scale"); AppendField(stringBuilder, "PlayOnAwake", PlayOnAwake, "Whether to autoplay immediately after creation"); AppendField(stringBuilder, "Loop", Loop, "Loop"); AppendField(stringBuilder, "SimulateInPlayer", SimulateInPlayer, "Whether to simulate based on the player's perspective"); AppendField(stringBuilder, "InstanceCount", InstanceCount, "Force number of instances (-1 means not applied)"); AppendSectionHeader(stringBuilder, "Performance"); AppendField(stringBuilder, "DeactivatingTimeout", DeactivatingTimeout, "Wait time (seconds) until forced cleanup when MapperDataCloud dummy is stuck in Deactivating state"); AppendField(stringBuilder, "DummyCountX", DummyCountX, "Horizontal grid density of crash prevention dummies (lower values \u200b\u200breduce lag)"); AppendField(stringBuilder, "DummyCountY", DummyCountY, "Vertical grid density of crash prevention dummies (lower values \u200b\u200breduce lag)"); AppendField(stringBuilder, "DummyParticleLifeTime", DummyParticleLifeTime, "Lifespan (seconds) of crash prevention dummy particles"); AppendSectionHeader(stringBuilder, "Debug"); AppendField(stringBuilder, "VerboseLogging", VerboseLogging, "If true, output detailed logs related to spawn/cleanup", isLast: true); stringBuilder.AppendLine("}"); Directory.CreateDirectory(Path.GetDirectoryName(FilePath)); File.WriteAllText(FilePath, stringBuilder.ToString()); } private static void AppendSectionHeader(StringBuilder sb, string sectionName) { sb.AppendLine(); StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(51, 1, sb); handler.AppendLiteral(" // ===================== ["); handler.AppendFormatted(sectionName); handler.AppendLiteral("] ====================="); sb.AppendLine(ref handler); } public static Color ParseColor(string value) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) try { string[] array = value.Split(','); if (array.Length >= 3) { float num = float.Parse(array[0].Trim(), CultureInfo.InvariantCulture); float num2 = float.Parse(array[1].Trim(), CultureInfo.InvariantCulture); float num3 = float.Parse(array[2].Trim(), CultureInfo.InvariantCulture); float num4 = ((array.Length >= 4) ? float.Parse(array[3].Trim(), CultureInfo.InvariantCulture) : 1f); return new Color(num, num2, num3, num4); } } catch { } return Color.white; } private static void AppendField(StringBuilder sb, string key, object value, string comment, bool isLast = false) { string text; string value2; if (value is bool flag) { text = (flag ? "true" : "false"); value2 = "Boolean"; } else if (value is string text2) { text = "\"" + text2.Replace("\"", "\\\"") + "\""; value2 = "String"; } else if (value is float num) { text = num.ToString(CultureInfo.InvariantCulture); value2 = "Single"; } else { text = Convert.ToString(value, CultureInfo.InvariantCulture); value2 = "Int32"; } StringBuilder stringBuilder = sb; StringBuilder stringBuilder2 = stringBuilder; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(5, 1, stringBuilder); handler.AppendLiteral(" // "); handler.AppendFormatted(comment); stringBuilder2.AppendLine(ref handler); stringBuilder = sb; StringBuilder stringBuilder3 = stringBuilder; handler = new StringBuilder.AppendInterpolatedStringHandler(19, 1, stringBuilder); handler.AppendLiteral(" // Setting type: "); handler.AppendFormatted(value2); stringBuilder3.AppendLine(ref handler); stringBuilder = sb; StringBuilder stringBuilder4 = stringBuilder; handler = new StringBuilder.AppendInterpolatedStringHandler(20, 1, stringBuilder); handler.AppendLiteral(" // Default value: "); handler.AppendFormatted(text.Trim('"')); stringBuilder4.AppendLine(ref handler); stringBuilder = sb; StringBuilder stringBuilder5 = stringBuilder; handler = new StringBuilder.AppendInterpolatedStringHandler(6, 3, stringBuilder); handler.AppendLiteral(" \""); handler.AppendFormatted(key); handler.AppendLiteral("\": "); handler.AppendFormatted(text); handler.AppendFormatted(isLast ? "" : ","); stringBuilder5.AppendLine(ref handler); } private static Dictionary ParseJsonc(string text) { Dictionary dictionary = new Dictionary(); string[] array = text.Split('\n'); foreach (string text2 in array) { string text3 = text2.Trim(); if (text3.Length == 0 || text3.StartsWith("//") || text3 == "{" || text3 == "}") { continue; } Match match = LinePattern.Match(text3); if (match.Success) { string value = match.Groups["key"].Value; string text4 = match.Groups["value"].Value; if (text4.StartsWith("\"") && text4.EndsWith("\"")) { text4 = text4.Substring(1, text4.Length - 2).Replace("\\\"", "\""); } dictionary[value] = text4; } } return dictionary; } private static string GetString(Dictionary values, string key, string fallback) { string value; return values.TryGetValue(key, out value) ? value : fallback; } private static bool GetBool(Dictionary values, string key, bool fallback) { string value; bool result; return (values.TryGetValue(key, out value) && bool.TryParse(value, out result)) ? result : fallback; } private static int GetInt(Dictionary values, string key, int fallback) { string value; int result; return (values.TryGetValue(key, out value) && int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) ? result : fallback; } private static float GetFloat(Dictionary values, string key, float fallback) { string value; float result; return (values.TryGetValue(key, out value) && float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out result)) ? result : fallback; } }