using System; using System.Buffers; using System.Buffers.Binary; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; 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 System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DG.Tweening; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Steamworks; using Steamworks.Data; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using WKMPMod.Asset; using WKMPMod.Component; using WKMPMod.Core; using WKMPMod.Data; using WKMPMod.MK_Component; using WKMPMod.NetWork; using WKMPMod.RemotePlayer; using WKMPMod.UI; using WKMPMod.Util; using WKMPMod.World; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("WKMultiPlayerMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.5.7.0")] [assembly: AssemblyInformationalVersion("1.5.7+378689d40c0165cb73dd7cb4cbfb68f694489001")] [assembly: AssemblyProduct("WKMultiPlayerMod")] [assembly: AssemblyTitle("WKMultiPlayerMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.7.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 abstract class Singleton where T : Singleton { private static readonly Lazy _instance = new Lazy(CreateInstance, isThreadSafe: true); public static T Instance => _instance.Value; public static bool IsCreated => _instance.IsValueCreated; private static T CreateInstance() { try { ConstructorInfo constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (constructor == null) { throw new InvalidOperationException("Singleton<" + typeof(T).Name + ">: Type must have a parameterless constructor"); } return (T)constructor.Invoke(null); } catch (Exception innerException) { throw new InvalidOperationException("Singleton<" + typeof(T).Name + ">: Failed to create instance", innerException); } } protected Singleton() { if (_instance.IsValueCreated) { throw new InvalidOperationException("Singleton<" + typeof(T).Name + ">: Instance already exists. Use " + typeof(T).Name + ".Instance instead."); } } } namespace WKMPMod.World { public enum PitonSyncAction : byte { Create, Update, Remove } public static class ClimbableItemSyncManager { private const float PeriodicUpdateInterval = 0.15f; private const float PositionEpsilonSqr = 0.0004f; private const float RotationEpsilon = 0.5f; private const float SecureAmountEpsilon = 0.01f; private const string CLONE_SUFFIX = "(Clone)"; public static Stopwatch sw = new Stopwatch(); private static List CapturedPitons = new List(); private static readonly Dictionary _pitons = new Dictionary(); private static readonly Dictionary _prefabLookup = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly FieldInfo _projectileSourceEntityField = typeof(Projectile).GetField("sourceEntity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static ulong _nextLocalId = 1uL; public static bool ApplyingRemoteState { get; private set; } public static void SaveCapturedPiton(GameObject go) { if ((Object)(object)go != (Object)null && (Object)(object)go.GetComponentInChildren(true) != (Object)null) { CapturedPitons.Add(go); } } public static HashSet CaptureExistingHandholds() { HashSet hashSet = new HashSet(); CL_Handhold[] array = Object.FindObjectsOfType(); foreach (CL_Handhold val in array) { GameObject climbableRoot = GetClimbableRoot(((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); if ((Object)(object)climbableRoot != (Object)null) { hashSet.Add(((Object)climbableRoot).GetInstanceID()); } } return hashSet; } public static void RegisterNewLocalPiton(HandItem_Piton source, HashSet knownHandholds) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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 (MPCore.CanSync && !ApplyingRemoteState && !((Object)(object)source == (Object)null) && knownHandholds != null && !((Object)(object)source.pitonWorldObject == (Object)null)) { string text = NormalizePrefabKey(((Object)source.pitonWorldObject).name); RaycastHit aimCircleHit = ((HandItem)source).GetAimCircleHit(); GameObject root = FindBestNewClimbable(((RaycastHit)(ref aimCircleHit)).point, knownHandholds, text, null); RegisterLocalClimbable(root, text); } } public static void RegisterNewLocalPiton(HandItem_Piton source) { if (!MPCore.CanSync || ApplyingRemoteState || (Object)(object)source == (Object)null || CapturedPitons.Count == 0) { CapturedPitons.Clear(); return; } foreach (GameObject capturedPiton in CapturedPitons) { GameObject climbableRoot = GetClimbableRoot(capturedPiton); if (!((Object)(object)climbableRoot == (Object)null)) { RegisterLocalClimbable(climbableRoot, ((Object)source.pitonWorldObject).name); } } CapturedPitons.Clear(); } public static void RegisterNewLocalProjectileClimbable(Projectile source, RaycastHit hit, HashSet knownHandholds) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (MPCore.CanSync && !ApplyingRemoteState && !((Object)(object)source == (Object)null) && knownHandholds != null && IsLocalProjectile(source)) { GameObject climbableRoot = GetClimbableRoot(((Component)source).gameObject); GameObject fallback = (IsNewClimbableRoot(climbableRoot, knownHandholds) ? climbableRoot : null); GameObject val = FindBestNewClimbable(((RaycastHit)(ref hit)).point, knownHandholds, null, fallback); RegisterLocalClimbable(val, ((Object)(object)val != (Object)null) ? ((Object)val).name : ((Object)((Component)source).gameObject).name); } } public static void RegisterNewLocalProjectileClimbable(Projectile source, RaycastHit hit) { if (!MPCore.CanSync || ApplyingRemoteState || (Object)(object)source == (Object)null || !IsLocalProjectile(source)) { CapturedPitons.Clear(); return; } foreach (GameObject capturedPiton in CapturedPitons) { GameObject climbableRoot = GetClimbableRoot(capturedPiton); if (!((Object)(object)climbableRoot == (Object)null)) { RegisterLocalClimbable(climbableRoot, ((Object)(object)climbableRoot != (Object)null) ? ((Object)climbableRoot).name : ((Object)((Component)source).gameObject).name); } } CapturedPitons.Clear(); } public static void BroadcastHammerUpdate(CL_Handhold handhold) { if (MPCore.CanSync && !ApplyingRemoteState && !((Object)(object)handhold == (Object)null)) { NetworkedClimableItem networkedClimableItem = FindIdentity(handhold); if (!((Object)(object)networkedClimableItem == (Object)null) && !string.IsNullOrEmpty(networkedClimableItem.NetworkId)) { Broadcast(networkedClimableItem, PitonSyncAction.Update, force: true); } } } public static void BroadcastPeriodicUpdate(CL_Handhold handhold) { if (!MPCore.CanSync || ApplyingRemoteState || (Object)(object)handhold == (Object)null) { return; } NetworkedClimableItem networkedClimableItem = FindIdentity(handhold); if ((Object)(object)networkedClimableItem == (Object)null || string.IsNullOrEmpty(networkedClimableItem.NetworkId)) { return; } if (!((Component)networkedClimableItem).gameObject.activeSelf) { Broadcast(networkedClimableItem, PitonSyncAction.Remove, force: true); } else if (!(Time.time - networkedClimableItem.LastSentTime < 0.15f)) { CL_Handhold trackedHandhold = GetTrackedHandhold(((Component)networkedClimableItem).gameObject); if (HasMeaningfulStateChange(networkedClimableItem, trackedHandhold)) { Broadcast(networkedClimableItem, PitonSyncAction.Update, force: false); } } } public static void HandlePitonState(ulong senderId, DataReader reader) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) PitonSyncAction @byte = (PitonSyncAction)reader.GetByte(); string @string = reader.GetString(); string string2 = reader.GetString(); Vector3 vector = reader.GetVector3(); Quaternion quaternion = reader.GetQuaternion(); float @float = reader.GetFloat(); bool @bool = reader.GetBool(); bool bool2 = reader.GetBool(); if (string.IsNullOrEmpty(@string)) { return; } ApplyingRemoteState = true; try { switch (@byte) { case PitonSyncAction.Create: ApplyCreate(senderId, @string, string2, vector, quaternion, @float, @bool, bool2); break; case PitonSyncAction.Update: ApplyUpdate(@string, vector, quaternion, @float, @bool, bool2); break; case PitonSyncAction.Remove: ApplyRemove(@string); break; } } catch (Exception ex) { MPMain.LogError($"[MP ClimbableSync] Failed to apply {@byte} for {@string}: {ex.Message}"); } finally { ApplyingRemoteState = false; } } private static void RegisterLocalClimbable(GameObject root, string prefabKey) { if ((Object)(object)root == (Object)null) { return; } string text = NormalizePrefabKey(prefabKey); if (!string.IsNullOrEmpty(text)) { NetworkedClimableItem orCreateIdentity = GetOrCreateIdentity(root); if (string.IsNullOrEmpty(orCreateIdentity.NetworkId)) { orCreateIdentity.NetworkId = $"{MonoSingleton.Instance.UserSteamId}:{_nextLocalId++}"; orCreateIdentity.OwnerId = MonoSingleton.Instance.UserSteamId; orCreateIdentity.IsRemote = false; } orCreateIdentity.PrefabKey = text; _pitons[orCreateIdentity.NetworkId] = orCreateIdentity; Broadcast(orCreateIdentity, PitonSyncAction.Create, force: true); } } private static void ApplyCreate(ulong senderId, string networkId, string prefabKey, Vector3 position, Quaternion rotation, float secureAmount, bool secure, bool active) { //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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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) if (_pitons.TryGetValue(networkId, out NetworkedClimableItem value) && (Object)(object)value != (Object)null) { value.PrefabKey = NormalizePrefabKey(prefabKey); ApplyState(value, position, rotation, secureAmount, secure, active); return; } GameObject val = ResolvePrefab(prefabKey); if ((Object)(object)val == (Object)null) { MPMain.LogError("[MP ClimbableSync] Could not resolve prefab '" + prefabKey + "' for " + networkId + "."); return; } GameObject val2 = Object.Instantiate(val, position, rotation); Transform currentLevelParentRoot = WorldLoader.GetCurrentLevelParentRoot(); if ((Object)(object)currentLevelParentRoot != (Object)null) { val2.transform.SetParent(currentLevelParentRoot); } TryAddPlacedObjectToLevel(val2); NetworkedClimableItem orCreateIdentity = GetOrCreateIdentity(val2); orCreateIdentity.NetworkId = networkId; orCreateIdentity.PrefabKey = NormalizePrefabKey(prefabKey); orCreateIdentity.OwnerId = senderId; orCreateIdentity.IsRemote = true; _pitons[networkId] = orCreateIdentity; ApplyState(orCreateIdentity, position, rotation, secureAmount, secure, active); } private static void ApplyUpdate(string networkId, Vector3 position, Quaternion rotation, float secureAmount, bool secure, bool active) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (_pitons.TryGetValue(networkId, out NetworkedClimableItem value) && !((Object)(object)value == (Object)null)) { ApplyState(value, position, rotation, secureAmount, secure, active); } } private static void ApplyRemove(string networkId) { if (_pitons.TryGetValue(networkId, out NetworkedClimableItem value) && !((Object)(object)value == (Object)null)) { if ((Object)(object)((Component)value).gameObject != (Object)null) { ((Component)value).gameObject.SetActive(false); } _pitons.Remove(networkId); } } private static void ApplyState(NetworkedClimableItem identity, Vector3 position, Quaternion rotation, float secureAmount, bool secure, bool active) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)identity).transform; transform.position = position; transform.rotation = rotation; CL_Handhold trackedHandhold = GetTrackedHandhold(((Component)identity).gameObject); if ((Object)(object)trackedHandhold != (Object)null) { trackedHandhold.Initialize(); trackedHandhold.secureAmount = secureAmount; trackedHandhold.secure = secure; } ((Component)identity).gameObject.SetActive(active); RecordState(identity, trackedHandhold); } private static GameObject FindBestNewClimbable(Vector3 anchor, HashSet knownHandholds, string preferredName, GameObject fallback) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) GameObject result = null; float num = float.MaxValue; HashSet hashSet = new HashSet(); if (IsNewClimbableRoot(fallback, knownHandholds) && NameMatches(((Object)fallback).name, preferredName)) { result = fallback; num = GetAnchorPosition(fallback, anchor); hashSet.Add(((Object)fallback).GetInstanceID()); } CL_Handhold[] array = Object.FindObjectsOfType(); foreach (CL_Handhold val in array) { GameObject climbableRoot = GetClimbableRoot(((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); if (IsNewClimbableRoot(climbableRoot, knownHandholds) && hashSet.Add(((Object)climbableRoot).GetInstanceID()) && NameMatches(((Object)climbableRoot).name, preferredName)) { float anchorPosition = GetAnchorPosition(climbableRoot, anchor); if (anchorPosition < num) { result = climbableRoot; num = anchorPosition; } } } return result; } private static bool IsNewClimbableRoot(GameObject root, HashSet knownHandholds) { return (Object)(object)root != (Object)null && knownHandholds != null && !knownHandholds.Contains(((Object)root).GetInstanceID()) && ContainsTrackedHandhold(root); } private static GameObject GetClimbableRoot(GameObject obj) { if ((Object)(object)obj == (Object)null) { return null; } Transform val = (WorldLoader.initialized ? WorldLoader.GetCurrentLevelParentRoot() : null); Transform val2 = obj.transform; while ((Object)(object)val2.parent != (Object)null && (Object)(object)val2.parent != (Object)(object)val) { val2 = val2.parent; } return ((Component)val2).gameObject; } private static bool ContainsTrackedHandhold(GameObject root) { return (Object)(object)root != (Object)null && (Object)(object)GetTrackedHandhold(root) != (Object)null; } private static CL_Handhold GetTrackedHandhold(GameObject root) { if ((Object)(object)root == (Object)null) { return null; } return root.GetComponent() ?? root.GetComponentInChildren(true); } private static NetworkedClimableItem FindIdentity(CL_Handhold handhold) { return ((Component)handhold).GetComponent() ?? ((Component)handhold).GetComponentInParent(); } private static float GetAnchorPosition(GameObject root, Vector3 anchor) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) CL_Handhold trackedHandhold = GetTrackedHandhold(root); Vector3 val = (((Object)(object)trackedHandhold != (Object)null) ? ((Component)trackedHandhold).transform.position : root.transform.position); Vector3 val2 = val - anchor; return ((Vector3)(ref val2)).sqrMagnitude; } private static bool NameMatches(string name, string preferredName) { if (string.IsNullOrEmpty(preferredName)) { return true; } string text = NormalizePrefabKey(name); string text2 = NormalizePrefabKey(preferredName); if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2)) { return false; } return text.Equals(text2, StringComparison.OrdinalIgnoreCase) || text.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0; } private static GameObject ResolvePrefab(string prefabKey) { string text = NormalizePrefabKey(prefabKey); if (string.IsNullOrEmpty(text)) { return null; } if (_prefabLookup.TryGetValue(text, out GameObject value) && (Object)(object)value != (Object)null) { return value; } RebuildPrefabLookup(); _prefabLookup.TryGetValue(text, out value); return value; } private static void RebuildPrefabLookup() { _prefabLookup.Clear(); HandItem_Piton[] array = Resources.FindObjectsOfTypeAll(); foreach (HandItem_Piton val in array) { if ((Object)(object)val != (Object)null) { TryRegisterPrefab(val.pitonWorldObject); } } HandItem_Shoot[] array2 = Resources.FindObjectsOfTypeAll(); foreach (HandItem_Shoot val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { TryRegisterPrefab(val2.projectile); RegisterProjectileHitPrefabs(val2.projectile); } } } private static void RegisterProjectileHitPrefabs(GameObject projectilePrefab) { if ((Object)(object)projectilePrefab == (Object)null) { return; } Projectile component = projectilePrefab.GetComponent(); if ((Object)(object)component == (Object)null) { return; } TryRegisterPrefab(component.hitEffect); if (component.customHitEffects == null) { return; } foreach (HitEffect customHitEffect in component.customHitEffects) { if (customHitEffect != null) { TryRegisterPrefab(customHitEffect.hitEffect); } } } private static void TryRegisterPrefab(GameObject prefab) { if (!((Object)(object)prefab == (Object)null)) { string text = NormalizePrefabKey(((Object)prefab).name); if (!string.IsNullOrEmpty(text) && !_prefabLookup.ContainsKey(text)) { _prefabLookup[text] = prefab; } } } private static string NormalizePrefabKey(string prefabKey) { if (string.IsNullOrEmpty(prefabKey)) { return string.Empty; } string text = prefabKey.Trim(); if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length); } return text.Trim(); } private static bool IsLocalProjectile(Projectile projectile) { ENT_Player player = ENT_Player.GetPlayer(); if ((Object)(object)projectile == (Object)null || (Object)(object)player == (Object)null || _projectileSourceEntityField == null) { return false; } object? value = _projectileSourceEntityField.GetValue(projectile); GameEntity val = (GameEntity)((value is GameEntity) ? value : null); return (Object)(object)val == (Object)(object)player; } private static void TryAddPlacedObjectToLevel(GameObject climbableObject) { if (!WorldLoader.initialized || (Object)(object)climbableObject == (Object)null) { return; } try { M_Level level = WorldLoader.instance.GetCurrentLevel().GetLevel(); typeof(M_Level).GetMethod("AddPlacedObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(level, new object[1] { climbableObject }); } catch (Exception ex) { MPMain.LogWarning("[MP ClimbableSync] Could not register remote climbable as placed object: " + ex.Message); } } private static NetworkedClimableItem GetOrCreateIdentity(GameObject obj) { NetworkedClimableItem networkedClimableItem = obj.GetComponent(); if ((Object)(object)networkedClimableItem == (Object)null) { networkedClimableItem = obj.AddComponent(); } return networkedClimableItem; } private static void Broadcast(NetworkedClimableItem identity, PitonSyncAction action, bool force) { //IL_0073: 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) if (!((Object)(object)identity == (Object)null) && !string.IsNullOrEmpty(identity.NetworkId)) { CL_Handhold trackedHandhold = GetTrackedHandhold(((Component)identity).gameObject); DataWriter writer = MPWriterPool.GetWriter(MonoSingleton.Instance.UserSteamId, 0uL, PacketType.PitonStateSync); writer.Put((byte)action); writer.Put(identity.NetworkId); writer.Put(identity.PrefabKey ?? string.Empty); writer.Put(((Component)identity).transform.position); writer.Put(((Component)identity).transform.rotation); writer.Put(((Object)(object)trackedHandhold != (Object)null) ? trackedHandhold.secureAmount : 0f); writer.Put((Object)(object)trackedHandhold != (Object)null && trackedHandhold.secure); writer.Put(((Component)identity).gameObject.activeSelf); MonoSingleton.Instance.Broadcast(writer, (SendType)8, 0); RecordState(identity, trackedHandhold); if (force) { MPMain.LogInfo($"[MP ClimbableSync] Sent {action} for {identity.NetworkId} ({identity.PrefabKey})"); } } } private static bool HasMeaningfulStateChange(NetworkedClimableItem identity, CL_Handhold handhold) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (identity.LastActive != ((Component)identity).gameObject.activeSelf) { return true; } Vector3 val = identity.LastPosition - ((Component)identity).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 0.0004f) { return true; } if (Quaternion.Angle(identity.LastRotation, ((Component)identity).transform.rotation) > 0.5f) { return true; } if ((Object)(object)handhold == (Object)null) { return false; } if (Mathf.Abs(identity.LastSecureAmount - handhold.secureAmount) > 0.01f) { return true; } return identity.LastSecure != handhold.secure; } private static void RecordState(NetworkedClimableItem identity, CL_Handhold handhold) { //IL_0014: 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) identity.LastSentTime = Time.time; identity.LastPosition = ((Component)identity).transform.position; identity.LastRotation = ((Component)identity).transform.rotation; identity.LastActive = ((Component)identity).gameObject.activeSelf; if ((Object)(object)handhold != (Object)null) { identity.LastSecureAmount = handhold.secureAmount; identity.LastSecure = handhold.secure; } } } } namespace WKMPMod.Util { public static class Localization { public struct LocalizedValue { private readonly object _data; public string[] AsArray => _data as string[]; public string AsString => _data as string; public bool IsArray => _data is string[]; public LocalizedValue(object data) { _data = data; } public string GetValue(int index = 0) { if (_data is string[] array) { return array[Math.Clamp(index, 0, array.Length - 1)]; } return _data?.ToString() ?? string.Empty; } public string GetValue(Random rand) { if (_data is string[] array) { return array[rand.Next(array.Length)]; } return _data?.ToString() ?? string.Empty; } } private static Dictionary> _table; private static Dictionary _flatCache; private const string FILE_PREFIX = "texts"; private static readonly Random _staticRandom = new Random(); public static void Load() { string path = MPMain.path; string gameLanguage = GetGameLanguage(); string text = "texts_" + gameLanguage.ToLower() + ".json"; string text2 = Path.Combine(path, text); if (!File.Exists(text2)) { MPMain.LogError("[Localization] " + text + " file not found at path: " + text2); text = "texts_en.json"; text2 = Path.Combine(path, text); if (!File.Exists(text2)) { MPMain.LogError("[Localization] Localization file not found, please confirm that texts_en.json file exists"); return; } } try { string text3 = File.ReadAllText(text2); Dictionary> dictionary = JsonConvert.DeserializeObject>>(text3); _table = new Dictionary>(); foreach (KeyValuePair> item in dictionary) { _table[item.Key] = new Dictionary(); foreach (KeyValuePair item2 in item.Value) { object value = item2.Value; JArray val = (JArray)((value is JArray) ? value : null); if (val != null) { _table[item.Key][item2.Key] = new LocalizedValue(((IEnumerable)val).Select((JToken x) => ((object)x).ToString()).ToArray()); } else { _table[item.Key][item2.Key] = new LocalizedValue(item2.Value?.ToString()); } } } BuildFlatCache(); int num = 0; foreach (KeyValuePair> item3 in _table) { num += item3.Value.Count; } MPMain.LogInfo($"[Localization] Successfully loaded {_table.Count} categories with {num} entries"); } catch (Exception ex) { MPMain.LogError("[Localization] Unable to parse localization file: " + ex.Message); } } private static void BuildFlatCache() { _flatCache = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair> item in _table) { foreach (KeyValuePair item2 in item.Value) { string key = item.Key + "." + item2.Key; _flatCache[key] = item2.Value; } } } public static bool TryGetValueSplit(string category, string key, out LocalizedValue value) { if (string.IsNullOrEmpty(category)) { MPMain.LogWarning("[MP Localization] Category is null or empty"); value = new LocalizedValue("[" + category + "." + key + "]"); return false; } if (!_table.TryGetValue(category, out Dictionary value2)) { MPMain.LogWarning("[MP Localization] Category not found: " + category); value = new LocalizedValue("[" + category + "." + key + "]"); return false; } if (!value2.TryGetValue(key, out var value3)) { MPMain.LogWarning("[MP Localization] Key '" + key + "' not found in category '" + category + "'"); value = new LocalizedValue("[" + category + "." + key + "]"); return false; } value = value3; return true; } public static string GetSplit(string category, string key, params object[] args) { if (!TryGetValueSplit(category, key, out var value)) { return value.AsString; } return SafeFormat(value.AsString, args); } public static string GetRandomSplit(string category, string key, params object[] args) { if (!TryGetValueSplit(category, key, out var value)) { return value.AsString; } return SafeFormat(value.GetValue(_staticRandom), args); } public static string GetByIndexSplit(string category, string key, int index, params object[] args) { if (!TryGetValueSplit(category, key, out var value)) { return value.AsString; } return SafeFormat(value.GetValue(index), args); } private static string SafeFormat(string pattern, object[] args) { if (args == null || args.Length == 0) { return pattern; } try { return string.Format(pattern, args); } catch (Exception ex) { MPMain.LogError("[Localization] Format error: " + ex.Message); return pattern; } } public static bool TryGetValue(string key, out LocalizedValue value) { if (!_flatCache.TryGetValue(key, out var value2)) { value = new LocalizedValue("[" + key + "]"); return false; } value = value2; return true; } public static string Get(string key, params object[] args) { if (!TryGetValue(key, out var value)) { return value.AsString; } return SafeFormat(value.AsString, args); } public static string GetRandom(string key, params object[] args) { if (!TryGetValue(key, out var value)) { return value.AsString; } return SafeFormat(value.GetValue(_staticRandom), args); } public static string GetByIndex(string key, int index, params object[] args) { if (!TryGetValue(key, out var value)) { return value.AsString; } return SafeFormat(value.GetValue(index), args); } public static bool HasKey(string key) { return _flatCache.ContainsKey(key); } public static bool HasKey(string category, string key) { if (_table.TryGetValue(category, out Dictionary value)) { return value.ContainsKey(key); } return false; } public static IEnumerable GetAllCategories() { return _table.Keys; } public static IEnumerable GetKeysInCategory(string category) { if (_table.TryGetValue(category, out Dictionary value)) { return value.Keys; } return new List(); } public static string GetGameLanguage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 SystemLanguage systemLanguage = Application.systemLanguage; SystemLanguage val = systemLanguage; if ((int)val <= 22) { if ((int)val <= 14) { if ((int)val == 6) { goto IL_0056; } if ((int)val == 14) { return "fr"; } } else { if ((int)val == 15) { return "de"; } if ((int)val == 22) { return "ja"; } } } else if ((int)val <= 30) { if ((int)val == 23) { return "ko"; } if ((int)val == 30) { return "ru"; } } else { if ((int)val == 34) { return "es"; } if ((int)val == 40) { goto IL_0056; } if ((int)val == 41) { return "zh_tw"; } } return "en"; IL_0056: return "zh"; } } public abstract class MonoSingleton : MonoBehaviour where T : MonoSingleton { private static T _instance; private static readonly object _lock = new object(); private static bool _applicationIsQuitting = false; public static T Instance { get { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown if (_applicationIsQuitting) { return null; } lock (_lock) { if ((Object)(object)_instance == (Object)null) { _instance = Object.FindObjectOfType(); if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject(typeof(T).Name); _instance = val.AddComponent(); Object.DontDestroyOnLoad((Object)(object)val); } } return _instance; } } } protected virtual void Awake() { if ((Object)(object)_instance == (Object)null) { _instance = (T)this; if ((Object)(object)((Component)this).transform.parent == (Object)null) { Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } } else if ((Object)(object)_instance != (Object)(object)this) { Debug.LogWarning((object)("MonoSingleton<" + typeof(T).Name + ">: Duplicate components were found in the scene and have been automatically destroyed")); Object.Destroy((Object)(object)((Component)this).gameObject); } } protected virtual void OnApplicationQuit() { _applicationIsQuitting = true; } protected virtual void OnDestroy() { if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } } public static class ReflectionExtensions { public static T GetFieldValue(this object obj, string fieldName) { if (obj == null) { throw new ArgumentNullException("obj"); } Type type = obj.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; while (type != null) { FieldInfo field = type.GetField(fieldName, bindingAttr); if (field != null) { return (T)field.GetValue(obj); } type = type.BaseType; } throw new Exception($"Field '{fieldName}' not found in type '{obj.GetType()}'"); } public static void SetFieldValue(this object obj, string fieldName, T value) { Type type = obj.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = type.GetField(fieldName, bindingAttr); if (field != null) { field.SetValue(obj, value); } } } } namespace WKMPMod.UI { [HarmonyPatch(typeof(UI_GamemodeScreen), "Initialize")] public class Patch_UI_GamemodeScreen_Initialize { private static void Postfix(UI_GamemodeScreen __instance, M_Gamemode mode) { string id = mode.gamemodePanel.id; if (!__instance.activePanels.TryGetValue(id, out var value) || (Object)(object)((Component)value).gameObject.GetComponentInChildren(true) != (Object)null) { return; } Transform val = ((Component)value).transform.Find("Pages/Gamemode_Info_Screen/Tab Selection Hor/Play"); TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren(); if (((componentInChildren != null) ? ((TMP_Text)componentInChildren).text : null) != "Play") { val = ((Component)value).transform.Find("Pages/Gamemode_NewGame_Screen/Tab Selection Hor/Play"); } if ((Object)(object)val != (Object)null) { GameObject val2 = Object.Instantiate(((Component)val).gameObject, val.parent); ((Object)val2).name = "Multi Play"; val2.transform.SetSiblingIndex(val.GetSiblingIndex() + 1); UI_LobbyCreateButton uI_LobbyCreateButton = val2.AddComponent(); uI_LobbyCreateButton.gamemodePanel = value; TMP_Text componentInChildren2 = val2.GetComponentInChildren(); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.text = "Multi Play"; } value.noSaveObjects.Add(val2); value.hasSaveObjects.Add(val2); } } } [HarmonyPatch(typeof(UI_MenuButton), "Initialize")] public class Patch_UI_MenuButton_Initialize { private static bool Prefix(UI_MenuButton __instance, UI_Menu menu) { if (UI_Manager.IsCloningMultiplayerMenu && ((Object)((Component)__instance).gameObject).name == "Facility Button") { return false; } return true; } } public class UI_LoadingDisplay : MonoBehaviour { [CompilerGenerated] private sealed class d__10 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public UI_LoadingDisplay <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; <>4__this._remainingTime -= Time.deltaTime; break; } if (<>4__this._remainingTime > 0f) { <>2__current = null; <>1__state = 1; return true; } ((Component)<>4__this).gameObject.SetActive(false); <>4__this._hideCoroutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private Coroutine? _hideCoroutine; private float _hideTime = -1f; private float _remainingTime = 0f; private void Awake() { MPEventBusGame.OnShowLoading += HandleLoadingRequest; MPEventBusGame.OnHideLoading += HideImmediately; ((Component)this).gameObject.SetActive(false); } private void OnDestroy() { MPEventBusGame.OnShowLoading -= HandleLoadingRequest; MPEventBusGame.OnHideLoading -= HideImmediately; } private void HandleLoadingRequest(float duration) { if (duration <= 0f) { ShowPermanent(); } else { ShowForSeconds(duration); } } public void ShowPermanent() { if (_hideCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_hideCoroutine); _hideCoroutine = null; } _hideTime = -1f; _remainingTime = 0f; ((Component)this).gameObject.SetActive(true); } public void ShowForSeconds(float seconds) { if (!(seconds <= 0f)) { if (_hideCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_hideCoroutine); _hideCoroutine = null; } _hideTime = seconds; _remainingTime = seconds; ((Component)this).gameObject.SetActive(true); _hideCoroutine = ((MonoBehaviour)this).StartCoroutine(HideAfterDelay()); } } public void ExtendDuration(float seconds) { if (!(_hideTime < 0f) && _hideCoroutine != null) { _remainingTime += seconds; if (_remainingTime <= 0f) { HideImmediately(); } } } public void HideImmediately() { if (_hideCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_hideCoroutine); _hideCoroutine = null; } _hideTime = -1f; _remainingTime = 0f; ((Component)this).gameObject.SetActive(false); } [IteratorStateMachine(typeof(d__10))] private IEnumerator HideAfterDelay() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0) { <>4__this = this }; } public float GetRemainingTime() { return _remainingTime; } public bool IsShowing() { return ((Component)this).gameObject.activeSelf; } public bool IsPermanent() { return _hideTime < 0f && ((Component)this).gameObject.activeSelf; } } public class UI_LobbyCreateButton : MonoBehaviour { public Button? button; public UI_GamemodeScreen_Panel? gamemodePanel; public List