Decompiled source of Simple Multi Player v1.7.3
WKMultiPlayerMod.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
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.Text; using System.Text.RegularExpressions; 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 Unity.VisualScripting; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; 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.Patch; 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.7.3.0")] [assembly: AssemblyInformationalVersion("1.7.3+b98d64200e307c3673484e728fc0fe1c77208fc9")] [assembly: AssemblyProduct("WKMultiPlayerMod")] [assembly: AssemblyTitle("WKMultiPlayerMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.7.3.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 abstract class Singleton<T> where T : Singleton<T> { private static readonly Lazy<T> _instance = new Lazy<T>(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 static List<GameObject> CapturedPitons = new List<GameObject>(); private static readonly FieldRef<Projectile, GameEntity> _projectileSourceEntityField = AccessTools.FieldRefAccess<Projectile, GameEntity>("sourceEntity"); private static readonly Dictionary<string, NetworkedClimableItem> _pitons = new Dictionary<string, NetworkedClimableItem>(); 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<CL_Handhold>(true) != (Object)null) { CapturedPitons.Add(go); } } 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) { 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 pitonSyncAction = (PitonSyncAction)reader.GetByte(); string text = reader.GetString(); string prefabKey = reader.GetString(); Vector3 vector = reader.GetVector3(); Quaternion quaternion = reader.GetQuaternion(); float secureAmount = reader.GetFloat(); bool secure = reader.GetBool(); bool active = reader.GetBool(); if (string.IsNullOrEmpty(text)) { return; } ApplyingRemoteState = true; try { switch (pitonSyncAction) { case PitonSyncAction.Create: ApplyCreate(senderId, text, prefabKey, vector, quaternion, secureAmount, secure, active); break; case PitonSyncAction.Update: ApplyUpdate(text, vector, quaternion, secureAmount, secure, active); break; case PitonSyncAction.Remove: ApplyRemove(text); break; } } catch (Exception ex) { MPMain.LogError($"[MP ClimbableSync] Failed to apply {pitonSyncAction} for {text}: {ex.Message}"); } finally { ApplyingRemoteState = false; } } private static void RegisterLocalClimbable(GameObject root, string prefabKey) { if ((Object)(object)root == (Object)null) { return; } string text = MPUtil.CleanCloneName(prefabKey); if (!string.IsNullOrEmpty(text)) { NetworkedClimableItem orCreateIdentity = GetOrCreateIdentity(root); if (string.IsNullOrEmpty(orCreateIdentity.NetworkId)) { orCreateIdentity.NetworkId = $"{MPSteamworks.UserSteamId}:{_nextLocalId++}"; orCreateIdentity.OwnerId = MPSteamworks.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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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 = MPUtil.CleanCloneName(prefabKey); ApplyState(value, position, rotation, secureAmount, secure, active); return; } GameObject handholdPrefab = MPAssetManager.GetHandholdPrefab(prefabKey); if ((Object)(object)handholdPrefab == (Object)null) { MPMain.LogError("[MP ClimbableSync] Could not resolve prefab '" + prefabKey + "' for " + networkId + "."); return; } GameObject val = Object.Instantiate<GameObject>(handholdPrefab, position, rotation); Transform currentLevelParentRoot = WorldLoader.GetCurrentLevelParentRoot(); if ((Object)(object)currentLevelParentRoot != (Object)null) { val.transform.SetParent(currentLevelParentRoot); } TryAddPlacedObjectToLevel(val); NetworkedClimableItem orCreateIdentity = GetOrCreateIdentity(val); orCreateIdentity.NetworkId = networkId; orCreateIdentity.PrefabKey = MPUtil.CleanCloneName(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) { Object.Destroy((Object)(object)((Component)value).gameObject); } _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 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 CL_Handhold GetTrackedHandhold(GameObject root) { if ((Object)(object)root == (Object)null) { return null; } return root.GetComponent<CL_Handhold>() ?? root.GetComponentInChildren<CL_Handhold>(true); } private static NetworkedClimableItem FindIdentity(CL_Handhold handhold) { return ((Component)handhold).GetComponent<NetworkedClimableItem>() ?? ((Component)handhold).GetComponentInParent<NetworkedClimableItem>(); } 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; } GameEntity val = _projectileSourceEntityField.Invoke(projectile); 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<NetworkedClimableItem>(); if ((Object)(object)networkedClimableItem == (Object)null) { networkedClimableItem = obj.AddComponent<NetworkedClimableItem>(); } return networkedClimableItem; } private static void Broadcast(NetworkedClimableItem identity, PitonSyncAction action, bool force) { //IL_006e: 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) //IL_0122: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)identity == (Object)null || string.IsNullOrEmpty(identity.NetworkId)) { return; } CL_Handhold trackedHandhold = GetTrackedHandhold(((Component)identity).gameObject); DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.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); if (action == PitonSyncAction.Create || action == PitonSyncAction.Remove) { MonoSingleton<MPSteamworks>.Instance.Broadcast(writer, (SendType)8, 0); } else if (action == PitonSyncAction.Update) { foreach (ulong item in MonoSingleton<LocalPlayer>.Instance._nearPlayersBuffer) { MonoSingleton<MPSteamworks>.Instance.SendToPeer(SteamId.op_Implicit(item), writer, (SendType)0, 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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; } } } public enum ItemSyncAction : byte { SnapshotReset, SnapshotFinalize, Create, PickupRequest, DropRequest, Remove } public static class ItemSyncManager { private sealed class PendingLocalDrop { public Item_Object ItemObject { get; } public string PrefabKey { get; } public float CreatedAt { get; } public PendingLocalDrop(Item_Object itemObject, string prefabKey, float createdAt) { ItemObject = itemObject; PrefabKey = prefabKey; CreatedAt = createdAt; } } private const float CandidateMatchDistanceSqr = 0.5f; private const float LocalDropMatchDistanceSqr = 25f; private const float LocalDropMaxAge = 3f; private const float LocalDropPickupSuppressWindow = 0.2f; private const float VelocityEpsilonSqr = 0.0025f; private const float WorldReadyTimeout = 12f; private const float StableIdPositionPrecision = 20f; private const float StableIdRotationPrecision = 5f; private const int SnapshotItemsPerFrame = 10; private static readonly FieldRef<Item, Item_Object> _dropObjectField = AccessTools.FieldRefAccess<Item, Item_Object>("dropObject"); private static readonly Dictionary<string, NetworkedItem> _items = new Dictionary<string, NetworkedItem>(); private static readonly List<Item_Object> _clientCandidates = new List<Item_Object>(); private static readonly List<PendingLocalDrop> _pendingLocalDrops = new List<PendingLocalDrop>(); private static readonly List<Item_Object> _snapshotCandidates = new List<Item_Object>(); private static readonly Dictionary<ulong, Coroutine> _snapshotRoutines = new Dictionary<ulong, Coroutine>(); private static readonly Dictionary<int, float> _suppressedPickupObjects = new Dictionary<int, float>(); private static ulong _nextHostItemId = 1uL; private static Coroutine _prepareRoutine; private static Coroutine _hostDiscoveryRoutine; private static bool _hostSceneItemsRegistered; private static readonly HashSet<string> _blacklistedPrefabNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Item_Flashlight", "Item_Flaregun", "Item_Cryogun" }; private static readonly HashSet<string> _blacklistedItemTags = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "artifact", "disk" }; public static bool ApplyingRemoteState { get; private set; } public static void NotifyWorldInitialized() { ResetState(); if ((Object)(object)MonoSingleton<MPCore>.Instance == (Object)null) { MPMain.LogWarning("[MP ItemSync] Prepare skipped: MPCore.Instance is null."); } else { _prepareRoutine = ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StartCoroutine(PrepareWorldRoutine()); } } public static void ResetState() { if (_prepareRoutine != null && (Object)(object)MonoSingleton<MPCore>.Instance != (Object)null) { ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StopCoroutine(_prepareRoutine); _prepareRoutine = null; } if (_hostDiscoveryRoutine != null && (Object)(object)MonoSingleton<MPCore>.Instance != (Object)null) { ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StopCoroutine(_hostDiscoveryRoutine); _hostDiscoveryRoutine = null; } if ((Object)(object)MonoSingleton<MPCore>.Instance != (Object)null) { foreach (Coroutine value in _snapshotRoutines.Values) { if (value != null) { ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StopCoroutine(value); } } } _snapshotRoutines.Clear(); foreach (NetworkedItem value2 in _items.Values) { if (!((Object)(object)value2 == (Object)null) && !((Object)(object)((Component)value2).gameObject == (Object)null) && value2.WasInstantiatedBySync) { Object.Destroy((Object)(object)((Component)value2).gameObject); } } _items.Clear(); _clientCandidates.Clear(); _pendingLocalDrops.Clear(); _snapshotCandidates.Clear(); _suppressedPickupObjects.Clear(); _hostSceneItemsRegistered = false; ApplyingRemoteState = false; MPMain.LogInfo("[MP ItemSync] ResetState completed."); } public static void SendSnapshotToClient(ulong clientId) { if (MPCore.CanSync && MonoSingleton<MPSteamworks>.Instance.IsHost && !((Object)(object)MonoSingleton<MPCore>.Instance == (Object)null) && clientId != 0L && clientId != MPSteamworks.UserSteamId) { if (_snapshotRoutines.TryGetValue(clientId, out Coroutine value) && value != null) { ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StopCoroutine(value); } _snapshotRoutines[clientId] = ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StartCoroutine(SendSnapshotToClientRoutine(clientId)); } } public static void NotifyLocalPickup(Item_Object itemObject) { if (ApplyingRemoteState || (Object)(object)itemObject == (Object)null || !MPCore.CanSync) { return; } if (IsPendingLocalDrop(itemObject)) { MPMain.LogInfo("[MP ItemSync] Suppressed pickup for pending local drop. Item=" + ((Object)itemObject).name); } else { if (ShouldSuppressLocalPickup(itemObject)) { return; } NetworkedItem component = ((Component)itemObject).GetComponent<NetworkedItem>(); if ((Object)(object)component == (Object)null || string.IsNullOrEmpty(component.NetworkId)) { MPMain.LogWarning("[MP ItemSync] Pickup ignored: missing NetworkedItem or NetworkId. Item=" + ((Object)itemObject).name + ", PrefabKey=" + GetPrefabKey(itemObject) + ", " + $"HasIdentity={(Object)(object)component != (Object)null}"); return; } MPMain.LogInfo("[MP ItemSync] Local pickup. " + $"Host={MonoSingleton<MPSteamworks>.Instance.IsHost}, " + "Item=" + ((Object)itemObject).name + ", NetworkId=" + component.NetworkId + ", PrefabKey=" + component.PrefabKey); if (MonoSingleton<MPSteamworks>.Instance.IsHost) { BroadcastRemove(component.NetworkId); Forget(component.NetworkId); } else { SendPickupRequest(component.NetworkId); } } } public static void NotifyLocalDrop(Item item) { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (ApplyingRemoteState || item == null || !MPCore.CanSync) { return; } Item_Object val = _dropObjectField.Invoke(item); if (!IsSyncableWorldItem(val)) { return; } string prefabKey = GetPrefabKey(val); if (!string.IsNullOrEmpty(prefabKey)) { if (MonoSingleton<MPSteamworks>.Instance.IsHost) { NetworkedItem networkedItem = RegisterHostItem(val, prefabKey); Vector3 velocity = GetVelocity(val); RememberSuppressedPickup(val); MPMain.LogInfo("[MP ItemSync] Host local drop. Item=" + ((Object)val).name + ", NetworkId=" + networkedItem.NetworkId + ", PrefabKey=" + prefabKey); BroadcastCreate(networkedItem, val, velocity, isDropSpawn: true); } else { RememberCandidate(val, snapshotCandidate: false); RememberPendingLocalDrop(val, prefabKey); RememberSuppressedPickup(val); MPMain.LogInfo("[MP ItemSync] Client local drop request. Item=" + ((Object)val).name + ", PrefabKey=" + prefabKey); SendDropRequest(prefabKey, ((Component)val).transform.position, ((Component)val).transform.rotation, GetVelocity(val)); } } } public static void SpawnSyncedWorldDrop(string prefabKey, Vector3 position, Quaternion rotation, Vector3 velocity) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //IL_0089: 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_0095: Unknown result type (might be due to invalid IL or missing references) if (ApplyingRemoteState || !MPCore.CanSync || string.IsNullOrWhiteSpace(prefabKey)) { return; } if (!MonoSingleton<MPSteamworks>.Instance.IsHost) { SendDropRequest(prefabKey, position, rotation, velocity); return; } Item_Object val = InstantiateWorldItem(prefabKey, position, rotation); if ((Object)(object)val == (Object)null) { MPMain.LogWarning("[MP ItemSync] Could not instantiate synced drop '" + prefabKey + "'."); return; } NetworkedItem identity = RegisterHostItem(val, prefabKey); RememberSuppressedPickup(val); ApplyCreate(identity, position, rotation, velocity, isDropSpawn: true, skipDropCallbacks: false); BroadcastCreate(identity, val, velocity, isDropSpawn: true); } public static void HandleItemState(ulong senderId, DataReader reader) { ItemSyncAction itemSyncAction = (ItemSyncAction)reader.GetByte(); try { switch (itemSyncAction) { case ItemSyncAction.SnapshotReset: HandleSnapshotReset(); break; case ItemSyncAction.SnapshotFinalize: HandleSnapshotFinalize(); break; case ItemSyncAction.Create: HandleCreate(senderId, reader); break; case ItemSyncAction.PickupRequest: HandlePickupRequest(reader); break; case ItemSyncAction.DropRequest: HandleDropRequest(senderId, reader); break; case ItemSyncAction.Remove: HandleRemove(reader); break; } } catch (Exception ex) { MPMain.LogError($"[MP ItemSync] Failed to apply {itemSyncAction}: {ex.Message}"); } } private static IEnumerator PrepareWorldRoutine() { MPMain.LogInfo("[MP ItemSync] PrepareWorldRoutine started. " + $"IsHost={MonoSingleton<MPSteamworks>.Instance.IsHost}, IsInLobby={MPCore.IsInLobby}, CanSync={MPCore.CanSync}, " + $"WorldInitialized={WorldLoader.initialized}, WorldLoaded={WorldLoader.isLoaded}"); yield return WaitForWorldReady(); yield return null; yield return null; if (MonoSingleton<MPSteamworks>.Instance.IsHost) { yield return RegisterHostSceneItemsRoutine(); if ((Object)(object)MonoSingleton<MPCore>.Instance != (Object)null && _hostDiscoveryRoutine == null) { _hostDiscoveryRoutine = ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StartCoroutine(HostDiscoveryRoutine()); } } else if (MPCore.IsInLobby) { CaptureSceneCandidates(snapshotCandidate: true); MPMain.LogInfo("[MP ItemSync] Captured client scene candidates. " + $"Candidates={_clientCandidates.Count}, SnapshotCandidates={_snapshotCandidates.Count}"); } else { MPMain.LogInfo("[MP ItemSync] Prepare skipped candidate capture because client is not in lobby."); } _prepareRoutine = null; MPMain.LogInfo("[MP ItemSync] PrepareWorldRoutine finished. " + $"Items={_items.Count}, HostSceneItemsRegistered={_hostSceneItemsRegistered}"); } private static IEnumerator SendSnapshotToClientRoutine(ulong clientId) { yield return WaitForWorldReady(); if (!_hostSceneItemsRegistered) { yield return RegisterHostSceneItemsRoutine(); } SendSnapshotReset(clientId); List<NetworkedItem> snapshot = new List<NetworkedItem>(EnumerateKnownHostWorldItems()); int sentThisFrame = 0; foreach (NetworkedItem identity in snapshot) { if ((Object)(object)identity == (Object)null || (Object)(object)((Component)identity).gameObject == (Object)null) { continue; } Item_Object itemObject = ((Component)identity).GetComponent<Item_Object>(); if (IsSyncableWorldItem(itemObject)) { SendCreate(clientId, identity, itemObject, GetVelocity(itemObject), isDropSpawn: false); sentThisFrame++; if (sentThisFrame >= 10) { sentThisFrame = 0; yield return null; } } } SendSnapshotFinalize(clientId); _snapshotRoutines.Remove(clientId); MPMain.LogInfo($"[MP ItemSync] Sent item snapshot to {clientId}. Items={snapshot.Count}"); } private static IEnumerator WaitForWorldReady() { float elapsed = 0f; while ((!WorldLoader.initialized || !WorldLoader.isLoaded) && elapsed < 12f) { elapsed += Time.unscaledDeltaTime; yield return null; } MPMain.LogInfo("[MP ItemSync] World ready wait finished. " + $"Elapsed={elapsed:F2}, Initialized={WorldLoader.initialized}, Loaded={WorldLoader.isLoaded}"); } private static IEnumerator RegisterHostSceneItemsRoutine() { if (!MonoSingleton<MPSteamworks>.Instance.IsHost) { yield break; } int registeredThisFrame = 0; int totalRegistered = 0; foreach (Item_Object itemObject in EnumerateSceneItems()) { string prefabKey = GetPrefabKey(itemObject); if (!string.IsNullOrEmpty(prefabKey)) { RegisterHostItem(itemObject, prefabKey, preferStableSceneIdentity: true); totalRegistered++; registeredThisFrame++; if (registeredThisFrame >= 10) { registeredThisFrame = 0; yield return null; } } } _hostSceneItemsRegistered = true; MPMain.LogInfo($"[MP ItemSync] Registered host scene items. Items={totalRegistered}"); } private static IEnumerator HostDiscoveryRoutine() { WaitForSecondsRealtime wait = new WaitForSecondsRealtime(0.5f); while ((Object)(object)MonoSingleton<MPCore>.Instance != (Object)null) { if (MPCore.CanSync && MonoSingleton<MPSteamworks>.Instance.IsHost && _hostSceneItemsRegistered) { DiscoverAndBroadcastNewHostWorldItems(); } yield return wait; } _hostDiscoveryRoutine = null; } private static void DiscoverAndBroadcastNewHostWorldItems() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) foreach (Item_Object item in EnumerateSceneItems()) { if (TryPrepareNewHostWorldItem(item, out string prefabKey)) { NetworkedItem networkedItem = RegisterHostItem(item, prefabKey, preferStableSceneIdentity: true); RememberSuppressedPickup(item); MPMain.LogInfo("[MP ItemSync] Registered dynamic host world item. Item=" + ((Object)item).name + ", NetworkId=" + networkedItem.NetworkId + ", PrefabKey=" + prefabKey); BroadcastCreate(networkedItem, item, GetVelocity(item), isDropSpawn: false); } } } private static bool TryPrepareNewHostWorldItem(Item_Object itemObject, out string prefabKey) { prefabKey = string.Empty; if (!IsSyncableWorldItem(itemObject)) { return false; } prefabKey = GetPrefabKey(itemObject); if (string.IsNullOrEmpty(prefabKey)) { return false; } NetworkedItem component = ((Component)itemObject).GetComponent<NetworkedItem>(); if ((Object)(object)component == (Object)null) { return true; } if (string.IsNullOrEmpty(component.NetworkId)) { return true; } return !_items.ContainsKey(component.NetworkId); } private static IEnumerable<NetworkedItem> EnumerateKnownHostWorldItems() { foreach (NetworkedItem identity in _items.Values) { if (!((Object)(object)identity == (Object)null) && !((Object)(object)((Component)identity).gameObject == (Object)null)) { Item_Object itemObject = ((Component)identity).GetComponent<Item_Object>(); if (IsSyncableWorldItem(itemObject)) { yield return identity; } } } } private static NetworkedItem RegisterHostItem(Item_Object itemObject, string prefabKey, bool preferStableSceneIdentity = false) { NetworkedItem orCreateIdentity = GetOrCreateIdentity(((Component)itemObject).gameObject); if (preferStableSceneIdentity) { TryAssignStableSceneIdentity(itemObject, orCreateIdentity); } if (string.IsNullOrEmpty(orCreateIdentity.NetworkId)) { orCreateIdentity.NetworkId = $"{MPSteamworks.UserSteamId}:item:{_nextHostItemId++}"; } orCreateIdentity.PrefabKey = prefabKey; orCreateIdentity.OwnerId = MPSteamworks.UserSteamId; orCreateIdentity.IsRemote = false; orCreateIdentity.WasInstantiatedBySync = false; if (_items.TryGetValue(orCreateIdentity.NetworkId, out NetworkedItem value) && (Object)(object)value != (Object)null && (Object)(object)value != (Object)(object)orCreateIdentity) { MPMain.LogWarning("[MP ItemSync] Duplicate NetworkId detected. NetworkId=" + orCreateIdentity.NetworkId + ", Existing=" + ((Object)value).name + ", New=" + ((Object)itemObject).name); } _items[orCreateIdentity.NetworkId] = orCreateIdentity; return orCreateIdentity; } private static void HandleSnapshotReset() { if (!MonoSingleton<MPSteamworks>.Instance.IsHost) { MPMain.LogInfo("[MP ItemSync] Received snapshot reset."); ResetState(); CaptureSceneCandidates(snapshotCandidate: true); } } private static void HandleSnapshotFinalize() { if (MonoSingleton<MPSteamworks>.Instance.IsHost) { return; } int num = 0; for (int num2 = _snapshotCandidates.Count - 1; num2 >= 0; num2--) { Item_Object val = _snapshotCandidates[num2]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { NetworkedItem component = ((Component)val).GetComponent<NetworkedItem>(); if (!((Object)(object)component != (Object)null) || string.IsNullOrEmpty(component.NetworkId) || !_items.ContainsKey(component.NetworkId)) { ((Component)val).gameObject.SetActive(false); num++; } } } _snapshotCandidates.Clear(); MPMain.LogInfo($"[MP ItemSync] Snapshot finalized. Hidden unmatched scene items={num}."); } private static void HandleCreate(ulong senderId, DataReader reader) { //IL_0025: 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_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) //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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) if (MonoSingleton<MPSteamworks>.Instance.IsHost) { return; } string text = reader.GetString(); string text2 = reader.GetString(); Vector3 vector = reader.GetVector3(); Quaternion quaternion = reader.GetQuaternion(); Vector3 vector2 = reader.GetVector3(); bool flag = reader.GetBool(); if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2)) { return; } if (_items.TryGetValue(text, out NetworkedItem value) && (Object)(object)value != (Object)null) { ApplyCreate(value, vector, quaternion, vector2, flag, skipDropCallbacks: true); return; } Item_Object val = (flag ? FindPendingLocalDrop(text2, vector) : null); bool wasSnapshotCandidate = false; if ((Object)(object)val == (Object)null) { val = FindSceneItemByStableId(text); if ((Object)(object)val != (Object)null) { wasSnapshotCandidate = _snapshotCandidates.Contains(val); RemoveCandidate(val); } } if ((Object)(object)val == (Object)null) { val = FindClientCandidate(text2, vector, out wasSnapshotCandidate); } Item_Object val2 = val; bool wasInstantiatedBySync = false; if ((Object)(object)val2 == (Object)null) { val2 = InstantiateWorldItem(text2, vector, quaternion); wasInstantiatedBySync = (Object)(object)val2 != (Object)null; } if ((Object)(object)val2 == (Object)null) { MPMain.LogWarning("[MP ItemSync] Could not create item '" + text2 + "' for " + text + "."); return; } NetworkedItem orCreateIdentity = GetOrCreateIdentity(((Component)val2).gameObject); if (text.StartsWith("sceneitem:", StringComparison.Ordinal)) { orCreateIdentity.StableSceneId = text; } orCreateIdentity.NetworkId = text; orCreateIdentity.PrefabKey = text2; orCreateIdentity.OwnerId = senderId; orCreateIdentity.IsRemote = true; orCreateIdentity.WasInstantiatedBySync = wasInstantiatedBySync; if (_items.TryGetValue(text, out NetworkedItem value2) && (Object)(object)value2 != (Object)null && (Object)(object)value2 != (Object)(object)orCreateIdentity) { MPMain.LogWarning("[MP ItemSync] Duplicate client NetworkId detected on create. NetworkId=" + text + ", Existing=" + ((Object)value2).name + ", New=" + ((Object)val2).name); } _items[text] = orCreateIdentity; bool skipDropCallbacks = !wasSnapshotCandidate && (Object)(object)val != (Object)null && flag; ApplyCreate(orCreateIdentity, vector, quaternion, vector2, flag, skipDropCallbacks); } private static void HandlePickupRequest(DataReader reader) { if (!MonoSingleton<MPSteamworks>.Instance.IsHost) { return; } string text = reader.GetString(); MPMain.LogInfo("[MP ItemSync] Host received pickup request. NetworkId=" + text); if (!string.IsNullOrEmpty(text)) { if (!_items.ContainsKey(text)) { MPMain.LogWarning("[MP ItemSync] Pickup request ignored. Unknown NetworkId=" + text); return; } BroadcastRemove(text); Forget(text); } } private static void HandleDropRequest(ulong senderId, DataReader reader) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (!MonoSingleton<MPSteamworks>.Instance.IsHost) { return; } string text = reader.GetString(); Vector3 vector = reader.GetVector3(); Quaternion quaternion = reader.GetQuaternion(); Vector3 vector2 = reader.GetVector3(); if (!string.IsNullOrEmpty(text)) { Item_Object val = InstantiateWorldItem(text, vector, quaternion); if ((Object)(object)val == (Object)null) { MPMain.LogWarning("[MP ItemSync] Could not instantiate dropped item '" + text + "'."); return; } NetworkedItem networkedItem = RegisterHostItem(val, text); networkedItem.OwnerId = senderId; MPMain.LogInfo("[MP ItemSync] Host accepted drop request. " + $"Sender={senderId}, Item={((Object)val).name}, NetworkId={networkedItem.NetworkId}, PrefabKey={text}"); ApplyCreate(networkedItem, vector, quaternion, vector2, isDropSpawn: true, skipDropCallbacks: false); BroadcastCreate(networkedItem, val, vector2, isDropSpawn: true); } } private static void HandleRemove(DataReader reader) { string text = reader.GetString(); MPMain.LogInfo("[MP ItemSync] Received remove. NetworkId=" + text); if (!string.IsNullOrEmpty(text)) { Forget(text); } } private static void ApplyCreate(NetworkedItem identity, Vector3 position, Quaternion rotation, Vector3 velocity, bool isDropSpawn, bool skipDropCallbacks) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)identity == (Object)null || (Object)(object)((Component)identity).gameObject == (Object)null) { return; } ApplyingRemoteState = true; try { ((Component)identity).transform.position = position; ((Component)identity).transform.rotation = rotation; Item_Object component = ((Component)identity).GetComponent<Item_Object>(); if ((Object)(object)component != (Object)null && component.itemData != null) { _dropObjectField.Invoke(component.itemData) = component; } if (isDropSpawn && (Object)(object)component != (Object)null && !skipDropCallbacks) { component.OnDrop(); } Rigidbody rigidbody = GetRigidbody(((Component)identity).gameObject); if ((Object)(object)rigidbody != (Object)null) { rigidbody.isKinematic = false; rigidbody.velocity = velocity; } ((Component)identity).gameObject.SetActive(true); } finally { ApplyingRemoteState = false; } } private static void Forget(string networkId) { if (!_items.TryGetValue(networkId, out NetworkedItem value) || (Object)(object)value == (Object)null) { if (!TryForgetUnknownSceneItem(networkId)) { MPMain.LogWarning("[MP ItemSync] Forget ignored. Unknown NetworkId=" + networkId); } return; } Item_Object component = ((Component)value).GetComponent<Item_Object>(); if ((Object)(object)component != (Object)null) { RemoveCandidate(component); } MPMain.LogInfo("[MP ItemSync] Forget item. NetworkId=" + networkId + ", Item=" + (((Object)(object)((Component)value).gameObject != (Object)null) ? ((Object)((Component)value).gameObject).name : "null") + ", " + $"WasInstantiatedBySync={value.WasInstantiatedBySync}"); if ((Object)(object)((Component)value).gameObject != (Object)null) { ((Component)value).gameObject.SetActive(false); if (value.WasInstantiatedBySync) { Object.Destroy((Object)(object)((Component)value).gameObject); } } _items.Remove(networkId); } private static bool TryForgetUnknownSceneItem(string networkId) { if (string.IsNullOrEmpty(networkId)) { return false; } if (!networkId.StartsWith("sceneitem:", StringComparison.Ordinal)) { return false; } Item_Object val = FindSceneItemByStableId(networkId); if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { return false; } NetworkedItem component = ((Component)val).GetComponent<NetworkedItem>(); if ((Object)(object)component != (Object)null && string.IsNullOrEmpty(component.NetworkId)) { component.NetworkId = networkId; component.StableSceneId = networkId; } RemoveCandidate(val); ((Component)val).gameObject.SetActive(false); _items.Remove(networkId); MPMain.LogWarning("[MP ItemSync] Forgot unknown scene item by stable ID fallback. NetworkId=" + networkId + ", Item=" + ((Object)val).name); return true; } private static void SendSnapshotReset(ulong clientId) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, clientId, PacketType.ItemStateSync); writer.Put((byte)0); MonoSingleton<MPSteamworks>.Instance.SendToPeer(SteamId.op_Implicit(clientId), writer, (SendType)8, 0); } private static void SendSnapshotFinalize(ulong clientId) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, clientId, PacketType.ItemStateSync); writer.Put((byte)1); MonoSingleton<MPSteamworks>.Instance.SendToPeer(SteamId.op_Implicit(clientId), writer, (SendType)8, 0); } private static void SendCreate(ulong clientId, NetworkedItem identity, Item_Object itemObject, Vector3 velocity, bool isDropSpawn) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)identity == (Object)null) && !((Object)(object)itemObject == (Object)null) && !string.IsNullOrEmpty(identity.NetworkId)) { DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, clientId, PacketType.ItemStateSync); writer.Put((byte)2); writer.Put(identity.NetworkId); writer.Put(identity.PrefabKey); writer.Put(((Component)itemObject).transform.position); writer.Put(((Component)itemObject).transform.rotation); writer.Put(velocity); writer.Put(isDropSpawn); MonoSingleton<MPSteamworks>.Instance.SendToPeer(SteamId.op_Implicit(clientId), writer, (SendType)8, 0); } } private static void BroadcastCreate(NetworkedItem identity, Item_Object itemObject, Vector3 velocity, bool isDropSpawn) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)identity == (Object)null) && !((Object)(object)itemObject == (Object)null) && !string.IsNullOrEmpty(identity.NetworkId)) { DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, 0uL, PacketType.ItemStateSync); writer.Put((byte)2); writer.Put(identity.NetworkId); writer.Put(identity.PrefabKey); writer.Put(((Component)itemObject).transform.position); writer.Put(((Component)itemObject).transform.rotation); writer.Put(velocity); writer.Put(isDropSpawn); MonoSingleton<MPSteamworks>.Instance.Broadcast(writer, (SendType)8, 0); } } private static void BroadcastRemove(string networkId) { DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, 0uL, PacketType.ItemStateSync); writer.Put((byte)5); writer.Put(networkId); MPMain.LogInfo("[MP ItemSync] Broadcast remove. NetworkId=" + networkId); MonoSingleton<MPSteamworks>.Instance.Broadcast(writer, (SendType)8, 0); } private static void SendPickupRequest(string networkId) { DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, MonoSingleton<MPSteamworks>.Instance.HostSteamId, PacketType.ItemStateSync); writer.Put((byte)3); writer.Put(networkId); MPMain.LogInfo("[MP ItemSync] Sent pickup request. NetworkId=" + networkId); MonoSingleton<MPSteamworks>.Instance.SendToHost(writer, (SendType)8, 0); } private static void SendDropRequest(string prefabKey, Vector3 position, Quaternion rotation, Vector3 velocity) { //IL_0029: 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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, MonoSingleton<MPSteamworks>.Instance.HostSteamId, PacketType.ItemStateSync); writer.Put((byte)4); writer.Put(prefabKey); writer.Put(position); writer.Put(rotation); writer.Put(velocity); MonoSingleton<MPSteamworks>.Instance.SendToHost(writer, (SendType)8, 0); } private static void CaptureSceneCandidates(bool snapshotCandidate) { foreach (Item_Object item in EnumerateSceneItems()) { RememberCandidate(item, snapshotCandidate); } } private static IEnumerable<Item_Object> EnumerateSceneItems() { Item_Object[] array = Object.FindObjectsOfType<Item_Object>(); foreach (Item_Object itemObject in array) { if (IsSyncableWorldItem(itemObject) && !IsBlacklisted(itemObject)) { yield return itemObject; } } } private static void RememberCandidate(Item_Object itemObject, bool snapshotCandidate) { if (!IsSyncableWorldItem(itemObject)) { return; } NetworkedItem orCreateIdentity = GetOrCreateIdentity(((Component)itemObject).gameObject); if (snapshotCandidate && TryAssignStableSceneIdentity(itemObject, orCreateIdentity)) { orCreateIdentity.PrefabKey = GetPrefabKey(itemObject); if (_items.TryGetValue(orCreateIdentity.NetworkId, out NetworkedItem value) && (Object)(object)value != (Object)null && (Object)(object)value != (Object)(object)orCreateIdentity) { MPMain.LogWarning("[MP ItemSync] Duplicate client candidate NetworkId detected. NetworkId=" + orCreateIdentity.NetworkId + ", Existing=" + ((Object)value).name + ", New=" + ((Object)itemObject).name); } _items[orCreateIdentity.NetworkId] = orCreateIdentity; } else if (!string.IsNullOrEmpty(orCreateIdentity.NetworkId)) { if (_items.TryGetValue(orCreateIdentity.NetworkId, out NetworkedItem value2) && (Object)(object)value2 != (Object)null && (Object)(object)value2 != (Object)(object)orCreateIdentity) { MPMain.LogWarning("[MP ItemSync] Duplicate remembered NetworkId detected. NetworkId=" + orCreateIdentity.NetworkId + ", Existing=" + ((Object)value2).name + ", New=" + ((Object)itemObject).name); } _items[orCreateIdentity.NetworkId] = orCreateIdentity; } else { if (!_clientCandidates.Contains(itemObject)) { _clientCandidates.Add(itemObject); } if (snapshotCandidate && !_snapshotCandidates.Contains(itemObject)) { _snapshotCandidates.Add(itemObject); } } } private static void RemoveCandidate(Item_Object itemObject) { _clientCandidates.Remove(itemObject); _snapshotCandidates.Remove(itemObject); RemovePendingLocalDrop(itemObject); } private static Item_Object FindClientCandidate(string prefabKey, Vector3 position, out bool wasSnapshotCandidate) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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) RemoveDestroyedCandidates(); Item_Object val = null; float num = float.MaxValue; wasSnapshotCandidate = false; foreach (Item_Object clientCandidate in _clientCandidates) { if (IsSyncableWorldItem(clientCandidate) && PrefabKeysMatch(prefabKey, GetPrefabKey(clientCandidate))) { Vector3 val2 = ((Component)clientCandidate).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > 0.5f) && !(sqrMagnitude >= num)) { val = clientCandidate; num = sqrMagnitude; } } } if ((Object)(object)val != (Object)null) { wasSnapshotCandidate = _snapshotCandidates.Contains(val); RemoveCandidate(val); } return val; } private static void RememberPendingLocalDrop(Item_Object itemObject, string prefabKey) { if (IsSyncableWorldItem(itemObject) && !string.IsNullOrEmpty(prefabKey)) { RemoveDestroyedPendingLocalDrops(); RemovePendingLocalDrop(itemObject); _pendingLocalDrops.Add(new PendingLocalDrop(itemObject, prefabKey, Time.time)); } } private static Item_Object FindPendingLocalDrop(string prefabKey, Vector3 position) { //IL_004d: 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) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) RemoveDestroyedPendingLocalDrops(); Item_Object val = null; float num = float.MaxValue; for (int num2 = _pendingLocalDrops.Count - 1; num2 >= 0; num2--) { PendingLocalDrop pendingLocalDrop = _pendingLocalDrops[num2]; if (PrefabKeysMatch(prefabKey, pendingLocalDrop.PrefabKey)) { Vector3 val2 = ((Component)pendingLocalDrop.ItemObject).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > 25f) && !(sqrMagnitude >= num)) { val = pendingLocalDrop.ItemObject; num = sqrMagnitude; } } } if ((Object)(object)val != (Object)null) { RemoveCandidate(val); } return val; } private static bool IsPendingLocalDrop(Item_Object itemObject) { if ((Object)(object)itemObject == (Object)null) { return false; } RemoveDestroyedPendingLocalDrops(); for (int i = 0; i < _pendingLocalDrops.Count; i++) { if ((Object)(object)_pendingLocalDrops[i].ItemObject == (Object)(object)itemObject) { return true; } } return false; } private static void RemovePendingLocalDrop(Item_Object itemObject) { if ((Object)(object)itemObject == (Object)null) { return; } for (int num = _pendingLocalDrops.Count - 1; num >= 0; num--) { if ((Object)(object)_pendingLocalDrops[num].ItemObject == (Object)(object)itemObject) { _pendingLocalDrops.RemoveAt(num); } } } private static void RemoveDestroyedCandidates() { for (int num = _clientCandidates.Count - 1; num >= 0; num--) { if (!IsSyncableWorldItem(_clientCandidates[num])) { _clientCandidates.RemoveAt(num); } } for (int num2 = _snapshotCandidates.Count - 1; num2 >= 0; num2--) { if (!IsSyncableWorldItem(_snapshotCandidates[num2])) { _snapshotCandidates.RemoveAt(num2); } } RemoveDestroyedPendingLocalDrops(); } private static void RemoveDestroyedPendingLocalDrops() { float num = Time.time - 3f; for (int num2 = _pendingLocalDrops.Count - 1; num2 >= 0; num2--) { PendingLocalDrop pendingLocalDrop = _pendingLocalDrops[num2]; if (!IsSyncableWorldItem(pendingLocalDrop.ItemObject) || pendingLocalDrop.CreatedAt < num) { _pendingLocalDrops.RemoveAt(num2); } } } private static void RememberSuppressedPickup(Item_Object itemObject) { if (!((Object)(object)itemObject == (Object)null) && !((Object)(object)((Component)itemObject).gameObject == (Object)null)) { RemoveExpiredSuppressedPickups(); _suppressedPickupObjects[((Object)((Component)itemObject).gameObject).GetInstanceID()] = Time.time + 0.2f; } } private static bool ShouldSuppressLocalPickup(Item_Object itemObject) { if ((Object)(object)itemObject == (Object)null || (Object)(object)((Component)itemObject).gameObject == (Object)null) { return false; } RemoveExpiredSuppressedPickups(); int instanceID = ((Object)((Component)itemObject).gameObject).GetInstanceID(); if (!_suppressedPickupObjects.TryGetValue(instanceID, out var value)) { return false; } if (Time.time > value) { _suppressedPickupObjects.Remove(instanceID); return false; } MPMain.LogInfo("[MP ItemSync] Suppressed pickup immediately after drop. Item=" + ((Object)itemObject).name); return true; } private static void RemoveExpiredSuppressedPickups() { if (_suppressedPickupObjects.Count == 0) { return; } foreach (int item in new List<int>(_suppressedPickupObjects.Keys)) { if (_suppressedPickupObjects.TryGetValue(item, out var value) && Time.time > value) { _suppressedPickupObjects.Remove(item); } } } private static bool IsSyncableWorldItem(Item_Object itemObject) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)itemObject == (Object)null || (Object)(object)((Component)itemObject).gameObject == (Object)null) { return false; } if (!((Component)itemObject).gameObject.activeInHierarchy) { return false; } Scene scene = ((Component)itemObject).gameObject.scene; if (string.IsNullOrEmpty(((Scene)(ref scene)).name)) { return false; } if (itemObject.itemData == null) { return false; } if (itemObject.itemData.inBag) { return false; } return true; } private static Item_Object InstantiateWorldItem(string prefabKey, Vector3 position, Quaternion rotation) { //IL_0028: 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) GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(prefabKey, ""); if ((Object)(object)assetGameObject == (Object)null) { return null; } ApplyingRemoteState = true; try { GameObject val = Object.Instantiate<GameObject>(assetGameObject, position, rotation); Transform currentLevelParentRoot = WorldLoader.GetCurrentLevelParentRoot(); if ((Object)(object)currentLevelParentRoot != (Object)null) { val.transform.SetParent(currentLevelParentRoot); } Item_Object val2 = val.GetComponent<Item_Object>() ?? val.GetComponentInChildren<Item_Object>(true); if ((Object)(object)val2 != (Object)null && val2.itemData != null) { val2.itemData.InitializeItemData(val2); } return val2; } finally { ApplyingRemoteState = false; } } private static Vector3 GetVelocity(Item_Object itemObject) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Rigidbody rigidbody = GetRigidbody(((Component)itemObject).gameObject); if ((Object)(object)rigidbody == (Object)null) { return Vector3.zero; } Vector3 velocity = rigidbody.velocity; return (((Vector3)(ref velocity)).sqrMagnitude > 0.0025f) ? rigidbody.velocity : Vector3.zero; } private static Rigidbody GetRigidbody(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return null; } return gameObject.GetComponent<Rigidbody>() ?? gameObject.GetComponentInChildren<Rigidbody>(); } private static NetworkedItem GetOrCreateIdentity(GameObject gameObject) { NetworkedItem networkedItem = gameObject.GetComponent<NetworkedItem>(); if ((Object)(object)networkedItem == (Object)null) { networkedItem = gameObject.AddComponent<NetworkedItem>(); } return networkedItem; } private static Item_Object FindSceneItemByStableId(string networkId) { if (string.IsNullOrEmpty(networkId) || !networkId.StartsWith("sceneitem:", StringComparison.Ordinal)) { return null; } foreach (Item_Object item in EnumerateSceneItems()) { if (string.Equals(GetStableSceneItemId(item), networkId, StringComparison.Ordinal)) { return item; } } return null; } private static bool TryAssignStableSceneIdentity(Item_Object itemObject, NetworkedItem identity) { if ((Object)(object)itemObject == (Object)null || (Object)(object)identity == (Object)null) { return false; } string stableSceneItemId = GetStableSceneItemId(itemObject); if (string.IsNullOrEmpty(stableSceneItemId)) { return false; } identity.StableSceneId = stableSceneItemId; identity.NetworkId = stableSceneItemId; return true; } private static string GetStableSceneItemId(Item_Object itemObject) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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) if ((Object)(object)itemObject == (Object)null || (Object)(object)((Component)itemObject).gameObject == (Object)null) { return string.Empty; } Scene scene = ((Component)itemObject).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { scene = ((Component)itemObject).gameObject.scene; if (!string.IsNullOrEmpty(((Scene)(ref scene)).name)) { NetworkedItem component = ((Component)itemObject).GetComponent<NetworkedItem>(); if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.StableSceneId)) { return component.StableSceneId; } string text = BuildTransformPath(((Component)itemObject).transform); if (string.IsNullOrEmpty(text)) { return string.Empty; } string text2 = BuildStableTransformAnchor(((Component)itemObject).transform); string[] obj = new string[6] { "sceneitem:", null, null, null, null, null }; scene = ((Component)itemObject).gameObject.scene; obj[1] = ((Scene)(ref scene)).name; obj[2] = ":"; obj[3] = text; obj[4] = "|"; obj[5] = text2; return string.Concat(obj); } } return string.Empty; } private static string BuildTransformPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); Stack<string> stack = new Stack<string>(); Transform val = transform; while ((Object)(object)val != (Object)null) { stack.Push($"{MPUtil.CleanCloneName(((Object)val).name)}[{val.GetSiblingIndex()}]"); val = val.parent; } while (stack.Count > 0) { if (stringBuilder.Length > 0) { stringBuilder.Append('/'); } stringBuilder.Append(stack.Pop()); } return stringBuilder.ToString(); } private static string BuildStableTransformAnchor(Transform transform) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)transform == (Object)null) { return string.Empty; } Vector3 localPosition = transform.localPosition; Vector3 localEulerAngles = transform.localEulerAngles; return $"lp:{Quantize(localPosition.x, 20f)}," + $"{Quantize(localPosition.y, 20f)}," + $"{Quantize(localPosition.z, 20f)}" + $"|lr:{Quantize(NormalizeAngle(localEulerAngles.x), 5f)}," + $"{Quantize(NormalizeAngle(localEulerAngles.y), 5f)}," + $"{Quantize(NormalizeAngle(localEulerAngles.z), 5f)}"; } private static int Quantize(float value, float precision) { return Mathf.RoundToInt(value * precision); } private static float NormalizeAngle(float value) { value %= 360f; if (value < 0f) { value += 360f; } return value; } private static string GetPrefabKey(Item_Object itemObject) { if ((Object)(object)itemObject == (Object)null) { return string.Empty; } if (itemObject.itemData != null && !string.IsNullOrEmpty(itemObject.itemData.prefabName)) { return itemObject.itemData.prefabName; } return MPUtil.CleanCloneName(((Object)((Component)itemObject).gameObject).name); } private static bool PrefabKeysMatch(string a, string b) { if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b)) { return false; } return string.Equals(MPUtil.CleanCloneName(a), MPUtil.CleanCloneName(b), StringComparison.OrdinalIgnoreCase); } public static bool IsBlacklisted(Item item) { return item != null && (_blacklistedPrefabNames.Contains(MPUtil.CleanCloneName(item.prefabName)) || _blacklistedItemTags.Intersect(item.itemTags).Any()); } public static bool IsBlacklisted(Item_Object itemObj) { return (Object)(object)itemObj != (Object)null && IsBlacklisted(itemObj.itemData); } } } 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 int Count => (!IsArray) ? 1 : ((string[])_data).Length; 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<string, Dictionary<string, LocalizedValue>> _table; private static Dictionary<string, LocalizedValue> _flatCache; private const string FILE_PREFIX = "texts"; private static readonly Random _staticRandom = new Random(); public static void Load() { string path = MPMain.path; _table = new Dictionary<string, Dictionary<string, LocalizedValue>>(); string path2 = "texts_en.json"; string text = Path.Combine(path, path2); bool flag = false; if (File.Exists(text)) { LoadAndMerge(text); flag = true; } else { MPMain.LogWarning("[Localization] Base English file not found at: " + text); } string gameLanguage = GetGameLanguage(); if (gameLanguage != "en") { string text2 = "texts_" + gameLanguage.ToLower() + ".json"; string text3 = Path.Combine(path, text2); if (File.Exists(text3)) { LoadAndMerge(text3); MPMain.LogInfo("[Localization] Loaded local language file: " + text2 + " and merged over English."); } else { MPMain.LogInfo("[Localization] Local language file " + text2 + " not found. Using English fallback."); } } if (_table.Count == 0 && !flag) { MPMain.LogError("[Localization] CRITICAL: No localization files could be loaded!"); return; } BuildFlatCache(); int num = 0; foreach (KeyValuePair<string, Dictionary<string, LocalizedValue>> item in _table) { num += item.Value.Count; } MPMain.LogInfo($"[Localization] Successfully loaded {_table.Count} categories with {num} entries"); } private static void LoadAndMerge(string filePath) { try { string text = File.ReadAllText(filePath); Dictionary<string, Dictionary<string, object>> dictionary = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, object>>>(text); if (dictionary == null) { return; } foreach (KeyValuePair<string, Dictionary<string, object>> item in dictionary) { if (!_table.ContainsKey(item.Key)) { _table[item.Key] = new Dictionary<string, LocalizedValue>(); } foreach (KeyValuePair<string, object> 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<JToken>)val).Select((JToken x) => ((object)x).ToString()).ToArray()); } else { _table[item.Key][item2.Key] = new LocalizedValue(item2.Value?.ToString()); } } } } catch (Exception ex) { MPMain.LogError("[Localization] Unable to parse localization file " + Path.GetFileName(filePath) + ": " + ex.Message); } } private static void BuildFlatCache() { _flatCache = new Dictionary<string, LocalizedValue>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, Dictionary<string, LocalizedValue>> item in _table) { foreach (KeyValuePair<string, LocalizedValue> 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<string, LocalizedValue> 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); } public static int GetCountSplit(string category, string key) { LocalizedValue value; return TryGetValueSplit(category, key, out value) ? value.Count : 0; } public static string[] GetAllSplit(string category, string key) { if (!TryGetValueSplit(category, key, out var value)) { return new string[0]; } return value.IsArray ? value.AsArray : new string[1] { value.AsString }; } public static string SafeFormat(string pattern, params object[] args) { if (string.IsNullOrEmpty(pattern)) { return string.Empty; } if (args == null || args.Length == 0) { return pattern; } try { MatchCollection matchCollection = Regex.Matches(pattern, "\\{([0-9]+)\\}"); int num = -1; foreach (Match item in matchCollection) { if (int.TryParse(item.Groups[1].Value, out var result) && result > num) { num = result; } } if (num == -1) { return pattern; } int num2 = num + 1; object[] array = new object[num2]; for (int i = 0; i < num2; i++) { array[i] = ((i < args.Length && args[i] != null) ? args[i] : ""); } return string.Format(pattern, array); } catch (Exception ex) { MPMain.LogError("[Localization] Format error: " + ex.Message + " | Pattern: " + pattern); 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 int GetCount(string key) { LocalizedValue value; return TryGetValue(key, out value) ? value.Count : 0; } public static string[] GetAll(string key) { if (!TryGetValue(key, out var value)) { return new string[0]; } return value.IsArray ? value.AsArray : new string[1] { value.AsString }; } public static bool HasKey(string key) { return _flatCache.ContainsKey(key); } public static bool HasKey(string category, string key) { if (_table.TryGetValue(category, out Dictionary<string, LocalizedValue> value)) { return value.ContainsKey(key); } return false; } public static IEnumerable<string> GetAllCategories() { return _table.Keys; } public static IEnumerable<string> GetKeysInCategory(string category) { if (_table.TryGetValue(category, out Dictionary<string, LocalizedValue> value)) { return value.Keys; } return new List<string>(); } 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<T> : MonoBehaviour where T : MonoSingleton<T> { 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<T>(); if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject(typeof(T).Name); _instance = val.AddComponent<T>(); 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 MPUtil { public static readonly Dictionary<string, Color32> PlayerColorPresets = new Dictionary<string, Color32>(StringComparer.OrdinalIgnoreCase) { { "default", new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) }, { "white", new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) }, { "red", new Color32(byte.MaxValue, (byte)80, (byte)80, byte.MaxValue) }, { "orange", new Color32(byte.MaxValue, (byte)165, (byte)0, byte.MaxValue) }, { "yellow", new Color32(byte.MaxValue, (byte)220, (byte)64, byte.MaxValue) }, { "green", new Color32((byte)80, (byte)220, (byte)120, byte.MaxValue) }, { "cyan", new Color32((byte)64, (byte)220, byte.MaxValue, byte.MaxValue) }, { "blue", new Color32((byte)90, (byte)140, byte.MaxValue, byte.MaxValue) }, { "purple", new Color32((byte)170, (byte)90, byte.MaxValue, byte.MaxValue) }, { "pink", new Color32(byte.MaxValue, (byte)110, (byte)180, byte.MaxValue) }, { "black", new Color32((byte)32, (byte)32, (byte)32, byte.MaxValue) } }; public static string CleanCloneName(string prefabKey) { if (string.IsNullOrEmpty(prefabKey)) { return string.Empty; } return prefabKey.Replace("(Clone)", string.Empty).Trim(); } public static string SerializePlayerColor(Color32 color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) return $"{color.r},{color.g},{color.b}"; } public static bool TryParsePlayerColor(string value, out Color32 color) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0096: Unknown result type (might be due to invalid IL or missing references) color = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); if (string.IsNullOrWhiteSpace(value)) { return false; } string[] array = value.Split(','); if (array.Length != 3) { return false; } if (!TryParseColorChannel(array[0], out var channel) || !TryParseColorChannel(array[1], out var channel2) || !TryParseColorChannel(array[2], out var channel3)) { return false; } color = new Color32((byte)channel, (byte)channel2, (byte)channel3, byte.MaxValue); return true; } public static bool TryParseColorChannel(string value, out int channel) { if (int.TryParse(value.Trim(), out channel)) { return channel >= 0 && channel <= 255; } return false; } } public static class NestedCommandEngine { public static readonly FieldRef<CommandConsole, IEnumerable> StatesRef; public static readonly FieldRef<object, IDictionary> CommandsRef; public static readonly FieldRef<object, Action<CommandAutocomplete>> AutocompleteRef; public static readonly FieldRef<CommandAutocomplete, List<string>> AutocompleteArgsRef; public static readonly Action<CommandAutocomplete, int> SetAutocompleteActiveArgAction; public static readonly FieldRef<object, Action<CommandValidator>> ValidatorRef; public static readonly FieldRef<CommandValidator, List<string>> ValidatorArgsRef; public static readonly Action<CommandValidator, int> SetValidatorActiveArgAction; static NestedCommandEngine() { try { Type typeFromHandle = typeof(CommandConsole); StatesRef = AccessTools.FieldRefAccess<CommandConsole, IEnumerable>("states"); Type type = AccessTools.Inner(typeFromHandle, "CommandLineState"); FieldInfo fieldInfo = AccessTools.Field(type, "commands"); CommandsRef = AccessTools.FieldRefAccess<object, IDictionary>(fieldInfo); Type type2 = AccessTools.Inner(typeFromHandle, "Command"); FieldInfo fieldInfo2 = AccessTools.Field(type2, "autocomplete"); AutocompleteRef = AccessTools.FieldRefAccess<object, Action<CommandAutocomplete>>(fieldInfo2); FieldInfo fieldInfo3 = AccessTools.Field(type2, "validator"); ValidatorRef = AccessTools.FieldRefAccess<object, Action<CommandValidator>>(fieldInfo3); Type typeFromHandle2 = typeof(CommandAutocomplete); AutocompleteArgsRef = AccessTools.FieldRefAccess<CommandAutocomplete, List<string>>("args"); MethodInfo methodInfo = AccessTools.PropertySetter(typeFromHandle2, "activeArg"); if (methodInfo != null) { SetAutocompleteActiveArgAction = AccessTools.MethodDelegate<Action<CommandAutocomplete, int>>(methodInfo, (object)null, true); } Type typeFromHandle3 = typeof(CommandValidator); ValidatorArgsRef = AccessTools.FieldRefAccess<CommandValidator, List<string>>("args"); MethodInfo methodInfo2 = AccessTools.PropertySetter(typeFromHandle3, "activeArg"); if (methodInfo2 != null) { SetValidatorActiveArgAction = AccessTools.MethodDelegate<Action<CommandValidator, int>>(methodInfo2, (object)null, true); } } catch (Exception ex) { MPMain.LogError(Localization.Get("Patch.HarmonyReflectionInitFailed", ex.Message)); } } public static void ForwardAutocomplete(CommandAutocomplete autocomplete, int defaultStartIndex) { if (StatesRef == null || CommandsRef == null) { return; } int num = defaultStartIndex; for (int i = defaultStartIndex; i <= autocomplete.activeArg; i++) { if (autocomplete.ArgumentAt(i) == "::") { num = i + 1; } } IEnumerable source = StatesRef.Invoke(CommandConsole.instance); object obj = source.Cast<object>().First(); IDictionary dictionary = CommandsRef.Invoke(obj); if (autocomplete.activeArg == num) { List<string> list = new List<string>(); foreach (object key2 in dictionary.Keys) { list.Add((string)key2); } list.Add("::"); autocomplete.FromArray((IReadOnlyList<string>)list); } else { if (autocomplete.activeArg <= num) { return; } string key = autocomplete.ArgumentAt(num).ToLower(); if (dictionary.Contains(key)) { object obj2 = dictionary[key]; Action<CommandAutocomplete> action = AutocompleteRef.Invoke(obj2); if (action != null) { int activeArg = autocomplete.activeArg; List<string> list2 = AutocompleteArgsRef.Invoke(autocomplete); SetAutocompleteActiveArgAction(autocomplete, activeArg - num); AutocompleteArgsRef.Invoke(autocomplete) = list2.Skip(num).ToList(); action(autocomplete); SetAutocompleteActiveArgAction(autocomplete, activeArg); AutocompleteArgsRef.Invoke(autocomplete) = list2; } } } } public static void ForwardValidator(CommandValidator validator, int defaultStartIndex) { if (StatesRef == null || CommandsRef == null || ValidatorArgsRef == null) { return; } int activeArg = validator.activeArg; List<string> list = ValidatorArgsRef.Invoke(validator); if (activeArg < defaultStartIndex) { return; } int num = defaultStartIndex; int num2 = Math.Min(activeArg, list.Count - 1); for (int i = defaultStartIndex; i <= num2; i++) { if (list[i] == "::") { num = i + 1; } } if (activeArg <= num || num >= list.Count) { return; } string key = list[num].ToLower(); IEnumerable source = StatesRef.Invoke(CommandConsole.instance); object obj = source.Cast<object>().First(); IDictionary dictionary = CommandsRef.Invoke(obj); if (dictionary.Contains(key)) { object obj2 = dictionary[key]; Action<CommandValidator> action = ValidatorRef.Invoke(obj2); if (action != null) { SetValidatorActiveArgAction(validator, activeArg - num); ValidatorArgsRef.Invoke(validator) = list.Skip(num).ToList(); action(validator); SetValidatorActiveArgAction(validator, activeArg); ValidatorArgsRef.Invoke(validator) = list; } } } } } 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<UI_LobbyCreateButton>(true) != (Object)null) { return; } Transform val = ((Component)value).transform.Find("Pages/Gamemode_Info_Screen/Tab Selection Hor/Play"); TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>(); 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<GameObject>(((Component)val).gameObject, val.parent); ((Object)val2).name = "Multi Play"; val2.transform.SetSiblingIndex(val.GetSiblingIndex() + 1); UI_LobbyCreateButton uI_LobbyCreateButton = val2.AddComponent<UI_LobbyCreateButton>(); uI_LobbyCreateButton.gamemodePanel = value; TMP_Text componentInChildren2 = val2.GetComponentInChildren<TMP_Text>(); 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 { 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); } private IEnumerator HideAfterDelay() { while (_remainingTime > 0f) { yield return null; _remainingTime -= Time.deltaTime; } ((Component)this).gameObject.SetActive(false); _hideCoroutine = null; } 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<Button> otherButtons = new List<Button>(); private void Awake() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown Button component = ((Component)this).GetComponent<Button>(); if ((Object)(object)component != (Object)null) { component.onClick = new ButtonClickedEvent(); button = component; } else { button = ((Component)this).gameObject.AddComponent<Button>(); } ((UnityEvent)button.onClick).AddListener(new UnityAction(CreateLobby)); } private void Start() { if (!((Object)(object)((Component)this).transform.parent != (Object)null)) { return; } Button[] componentsInChildren = ((Component)((Component)this).transform.parent).GetComponentsInChildren<Button>(); foreach (Button val in componentsInChildren) { if ((Object)(object)val != (Object)(object)button) { otherButtons.Add(val); } } } public async void CreateLobby() { string name = SteamClient.Name; MPMain.LogInfo(Localization.Get("MPCore.CreatingLobby", name)); Dictionary<string, string> lobbyData = new Dictionary<string, string> { { "name", name + "'s game" } }; Creating(); try { bool success = await MonoSingleton<MPSteamworks>.Instance.CreateRoomAsync(8, lobbyData); if (!((Object)(object)this == (Object)null) && !((Object)(object)((Component)this).gameObject == (Object)null)) { if (success) { CreateSuccess(); } else { CreateFailed(); } } } catch (Exception ex) { Exception ex2 = ex; if (!((Object)(object)this == (Object)null)) { CreateFailed(); MPMain.LogError(Localization.Get("UI_LobbyCreateButton.CreateLobbyFailed", ex2.Message)); } } } public void Creating() { MPCore.SetStatus(MPStatus.LobbyConnectionError, MPStatus.JoiningLobby); Button? obj = button; if (obj != null) { ((Selectable)obj).interactable = false; } foreach (Button otherButton in otherButtons) { ((Selectable)otherButton).interactable = false; } MPEventBusGame.NotifyShowLoading(10f); } public void CreateFailed() { MPCore.SetStatus(MPStatus.LobbyConnectionError, MPStatus.LobbyConnectionError); Button? obj = button; if (obj != null) { ((Selectable)obj).interactable = true; } foreach (Button otherButton in otherButtons) { ((Selectable)otherButton).interactable = true; } MPEventBusGame.NotifyHideLoading(); } public void CreateSuccess() { MPCore.SetStatus(MPStatus.LobbyConnectionError, MPStatus.InLobby); MPEventBusGame.NotifyHideLoading(); if ((Object)(object)gamemodePanel == (Object)null) { MPMain.LogError(Localization.Get("UI_LobbyCreateButton.GameModeDetailPanelNull")); } else { gamemodePanel.LoadGamemode(); } } } public class UI_LobbyJoinButton : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler { public Lobby lobby; public M_Gamemode? gamemode; public bool isOfficialGamemodes; public MPGameModeManager.GameModeData? gameModeData; public UI_LerpOpen? runInProgressDisplay; private bool isHovering; public TMP_Text? unlockText; public float showDelayAnimation; public Selectable? button; public CanvasGroup? group; public Image? unlockIcon; public TMP_Text? lobbyName; public Image? hostAvatar; public TMP_Text? hostName; public Button? btnComp; public Image? lobbyImage; public void Initialize(Lobby lobby) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_001c: 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_003d: Expected O, but got Unknown //IL_009b: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) this.lobby = lobby; ((UnityEvent)btnComp.onClick).AddListener((UnityAction)async delegate { Joining(); try { if (await MonoSingleton<MPSteamworks>.Instance.JoinRoomAsync(lobby)) { JoinSuccess(); } else { JoinFailed(); } } catch (Exception ex3) { Exception ex4 = ex3; MPMain.LogError(Localization.Get("UI_LobbyJoinButton.JoinLobbyFailed", ex4.Message)); JoinFailed(); } }); Image? obj = unlockIcon; if (obj != null) { ((Component)obj).gameObject.SetActive(false); } string data = ((Lobby)(ref lobby)).GetData("gamemode"); try { gameModeData = JsonConvert.DeserializeObject<MPGameModeManager.GameModeData>(data); MPMain.LogInfo("[MP UI] gameModeName: " + gameModeData?.gameModeName); } catch (JsonException ex) { JsonException ex2 = ex; MPMain.LogError(Localization.Get("UI_LobbyJoinButton.GamemodeParseError", data, ((Exception)(object)ex2).Message)); } isOfficialGamemodes = MPGameModeManager.TryGetGameMode(gameModeData?.gameModeName ?? "", out M_Gamemode val); if (!isOfficialGamemodes) { Image? obj2 = unlockIcon; if (obj2 != null) { ((Component)obj2).gameObject.SetActive(true); } TMP_Text? obj3 = unlockText; if (obj3 != null) { obj3.text = "Unknown gamemode"; } } Version version = new Version("1.7.3"); if (!Version.TryParse(((Lobby)(ref lobby)).GetData("mod version"), out Version result) || version.Major != result.Major || version.Minor != result.Minor) { Image? obj4 = unlockIcon; if (obj4 != null) { ((Component)obj4).gameObj
WKMultiPlayerMod.Shared.dll
Decompiled 2 days agousing System; using System.Buffers; using System.Buffers.Binary; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using WKMPMod.Data; using WKMPMod.Util; [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.Shared")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+b98d64200e307c3673484e728fc0fe1c77208fc9")] [assembly: AssemblyProduct("WKMultiPlayerMod.Shared")] [assembly: AssemblyTitle("WKMultiPlayerMod.Shared")] [assembly: AssemblyVersion("1.0.0.0")] 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; } } } [Serializable] public struct PlayerData : INetworkSerializable { [Serializable] public struct HandData : INetworkSerializable { public byte handType; public byte interactState; public float PosX; public float PosY; public float PosZ; public string itemName; public ulong targetId; public float desiredPosX; public float desiredPosY; public float desiredPosZ; public Vector3 Position { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(PosX, PosY, PosZ); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) PosX = value.x; PosY = value.y; PosZ = value.z; } } public Vector3 DesiredPosition { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(desiredPosX, desiredPosY, desiredPosZ); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) desiredPosX = value.x; desiredPosY = value.y; desiredPosZ = value.z; } } public void Serialize(DataWriter writer) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) writer.Put(handType); writer.Put(interactState); writer.Put(Position); switch (interactState) { case 0: writer.Put(itemName); break; case 2: writer.Put(targetId); writer.Put(DesiredPosition); break; case 4: writer.Put(targetId); break; case 1: case 3: break; } } public void Deserialize(DataReader reader) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) handType = reader.GetByte(); interactState = reader.GetByte(); Position = reader.GetVector3(); switch (interactState) { case 0: itemName = reader.GetString(); break; case 2: targetId = reader.GetULong(); DesiredPosition = reader.GetVector3(); break; case 4: targetId = reader.GetULong(); break; case 1: case 3: break; } } public bool IsBeGrabbing(ulong targetPlayerId) { return interactState == 2 && targetId == targetPlayerId; } public bool IsBeHanging(ulong targetPlayerId) { return interactState == 4 && targetId == targetPlayerId; } public static bool operator ==(HandData left, HandData right) { if (left.handType != right.handType || left.interactState != right.interactState) { return false; } float num = left.PosX - right.PosX; float num2 = left.PosY - right.PosY; float num3 = left.PosZ - right.PosZ; if (num * num + num2 * num2 + num3 * num3 >= 0.0025f) { return false; } switch (left.interactState) { case 0: return left.itemName == right.itemName; case 2: { if (left.targetId != right.targetId) { return false; } float num4 = left.desiredPosX - right.desiredPosX; float num5 = left.desiredPosY - right.desiredPosY; float num6 = left.desiredPosZ - right.desiredPosZ; return num4 * num4 + num5 * num5 + num6 * num6 < 0.0025f; } case 4: return left.targetId == right.targetId; default: return true; } } public static bool operator !=(HandData left, HandData right) { return !(left == right); } } private const float POSITION_CHANGE_THRESHOLD_SQR = 0.0025f; private const float ROTATION_CHANGE_THRESHOLD_DEG = 0.5f; public ulong playId; public long TimestampTicks; public float PosX; public float PosY; public float PosZ; public float RotX; public float RotY; public float RotZ; public float RotW; public HandData LeftHand; public HandData RightHand; public bool IsTeleport; public Vector3 Position { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(PosX, PosY, PosZ); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) PosX = value.x; PosY = value.y; PosZ = value.z; } } public Quaternion Rotation { get { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Quaternion(RotX, RotY, RotZ, RotW); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) RotX = value.x; RotY = value.y; RotZ = value.z; RotW = value.w; } } public void Serialize(DataWriter writer) { //IL_001b: 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) writer.Put(playId).Put(TimestampTicks); writer.Put(Position).Put(Rotation); writer.PutIn(in LeftHand).PutIn(in RightHand); writer.Put(IsTeleport); } public void Deserialize(DataReader reader) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) playId = reader.GetULong(); TimestampTicks = reader.GetLong(); Position = reader.GetVector3(); Rotation = reader.GetQuaternion(); reader.GetRef(ref LeftHand); reader.GetRef(ref RightHand); IsTeleport = reader.GetBool(); } public bool UpdateIfChanged(in PlayerData newData, bool forceUpdate = false) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (forceUpdate) { this = newData; return true; } float num = PosX - newData.PosX; float num2 = PosY - newData.PosY; float num3 = PosZ - newData.PosZ; if (num * num + num2 * num2 + num3 * num3 >= 0.0025f || !IsRotationSimilar(Rotation, newData.Rotation, 0.5f) || LeftHand != newData.LeftHand || RightHand != newData.RightHand) { this = newData; return true; } return false; } private static bool IsRotationSimilar(Quaternion a, Quaternion b, float thresholdDegrees) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Cos(thresholdDegrees * (MathF.PI / 180f) * 0.5f); float num2 = Mathf.Abs(Quaternion.Dot(a, b)); return num2 > num; } } namespace WKMPMod.Util { public static class DictionaryExtensions { public static List<ulong> FindByKeySuffix<T>(this Dictionary<ulong, T> dictionary, ulong suffix) { List<ulong> list = new List<ulong>(); if (dictionary == null || dictionary.Count == 0) { return list; } ulong num = CalculateDivisor(suffix); foreach (KeyValuePair<ulong, T> item in dictionary) { if (item.Key % num == suffix) { list.Add(item.Key); } } return list; } private static ulong CalculateDivisor(ulong suffix) { if (suffix == 0) { return 10uL; } ulong num; for (num = 1uL; num <= suffix; num *= 10) { } return num; } public static Dictionary<K, byte> SetDifference<K>(Dictionary<K, byte> minuend, Dictionary<K, byte> subtrahend) { Dictionary<K, byte> dictionary = new Dictionary<K, byte>(); foreach (var (key, b2) in minuend) { if (subtrahend.TryGetValue(key, out var value)) { if (b2 > value) { dictionary[key] = (byte)(b2 - value); } } else { dictionary[key] = b2; } } return dictionary; } } public class TickTimer { private float _interval; private float _lastTickTime; public float Progress => Mathf.Clamp01((Time.time - _lastTickTime) / _interval); public float TimeRemaining => Mathf.Max(0f, _interval - (Time.time - _lastTickTime)); public bool IsTickReached => Time.time - _lastTickTime >= _interval; public TickTimer(float tick) { _interval = tick; _lastTickTime = 0f - _interval; } public TickTimer(int hz) { _interval = 1f / (float)hz; _lastTickTime = 0f - _interval; } public void SetInterval(float tick) { _interval = tick; } public void SetFrequency(float hz) { _interval = 1f / hz; } public void Reset() { _lastTickTime = Time.time; } public bool TryTick() { if (Time.time - _lastTickTime >= _interval) { _lastTickTime = Time.time; return true; } return false; } public void ForceTick() { _lastTickTime = Time.time; } } } namespace WKMPMod.MK_Component { public class MK_CL_Handhold : MonoBehaviour { public UnityEvent activeEvent = new UnityEvent(); public UnityEvent stopEvent = new UnityEvent(); public Renderer handholdRenderer; } public class MK_ObjectTagger : MonoBehaviour { public List<string> tags = new List<string>(); } public class MK_RemoteEntity : MonoBehaviour { public ulong playerId; } public class MK_RemoteHand : MonoBehaviour { [Header("左右手")] public byte hand; [Header("距离设置")] [Tooltip("当当前位置与目标位置超过此距离时直接瞬移")] public float teleportThreshold = 50f; [Tooltip("平滑移动的最大距离限制")] public float fastSmoothDistance = 10f; [Header("拉拽参数")] public float basePullStrength = 0.2f; public void Teleport(Vector3 position) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.position = position; } } } namespace WKMPMod.Data { public class DataReader { private ReadOnlyMemory<byte> _data; private int _position; public int AvailableBytes => _data.Length - _position; public void SetSource(ArraySegment<byte> source) { _data = source; _position = 0; } public void SetSource(byte[] source) { _data = source; _position = 0; } public void SetSource(byte[] source, int offset, int length) { _data = new ReadOnlyMemory<byte>(source, offset, length); _position = 0; } public bool GetBool() { bool result = _data.Span[_position] != 0; _position++; return result; } public byte GetByte() { byte result = _data.Span[_position]; _position++; return result; } public short GetShort() { short result = BinaryPrimitives.ReadInt16LittleEndian(_data.Span.Slice(_position)); _position += 2; return result; } public ushort GetUShort() { ushort result = BinaryPrimitives.ReadUInt16LittleEndian(_data.Span.Slice(_position)); _position += 2; return result; } public int GetInt() { int result = BinaryPrimitives.ReadInt32LittleEndian(_data.Span.Slice(_position)); _position += 4; return result; } public uint GetUInt() { uint result = BinaryPrimitives.ReadUInt32LittleEndian(_data.Span.Slice(_position)); _position += 4; return result; } public long GetLong() { long result = BinaryPrimitives.ReadInt64LittleEndian(_data.Span.Slice(_position)); _position += 8; return result; } public ulong GetULong() { ulong result = BinaryPrimitives.ReadUInt64LittleEndian(_data.Span.Slice(_position)); _position += 8; return result; } public float GetFloat() { int value = BinaryPrimitives.ReadInt32LittleEndian(_data.Span.Slice(_position)); _position += 4; return BitConverter.Int32BitsToSingle(value); } public double GetDouble() { long value = BinaryPrimitives.ReadInt64LittleEndian(_data.Span.Slice(_position)); _position += 8; return BitConverter.Int64BitsToDouble(value); } public byte? GetNullableByte() { if (!GetBool()) { return null; } return GetByte(); } public int? GetNullableInt() { if (!GetBool()) { return null; } return GetInt(); } public float? GetNullableFloat() { if (!GetBool()) { return null; } return GetFloat(); } public Vector3 GetVector3() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) ReadOnlySpan<byte> source = _data.Span.Slice(_position); float num = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source)); float num2 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(4))); float num3 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(8))); _position += 12; return new Vector3(num, num2, num3); } public Quaternion GetQuaternion() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) ReadOnlySpan<byte> source = _data.Span.Slice(_position); float num = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source)); float num2 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(4))); float num3 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(8))); float num4 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(12))); _position += 16; return new Quaternion(num, num2, num3, num4); } public string GetString() { int num = GetInt(); if (num <= 0) { return string.Empty; } if (num > AvailableBytes) { throw new Exception("String length out of range"); } string result = Encoding.UTF8.GetString(_data.Span.Slice(_position, num)); _position += num; return result; } public ReadOnlySpan<byte> GetBytes() { int num = GetInt(); ReadOnlySpan<byte> result = _data.Span.Slice(_position, num); _position += num; return result; } public ReadOnlyMemory<byte> GetMemory() { int num = GetInt(); ReadOnlyMemory<byte> result = _data.Slice(_position, num); _position += num; return result; } public Dictionary<string, byte> GetStringByteDict() { int num = GetInt(); Dictionary<string, byte> dictionary = new Dictionary<string, byte>(); for (int i = 0; i < num; i++) { string key = GetString(); byte value = GetByte(); dictionary[key] = value; } return dictionary; } public List<string> GetStringList() { List<string> list = new List<string>(); int num = GetInt(); for (int i = 0; i < num; i++) { list.Add(GetString()); } return list; } public Dictionary<string, string> GetStringStringDict() { int num = GetInt(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); for (int i = 0; i < num; i++) { string key = GetString(); string value = GetString(); dictionary[key] = value; } return dictionary; } public T Get<T>() where T : INetworkSerializable, new() { T result = new T(); result.Deserialize(this); return result; } public void GetOut<T>(out T value) where T : struct, INetworkSerializable { value = default(T); value.Deserialize(this); } public void GetRef<T>(ref T value) where T : struct, INetworkSerializable { value.Deserialize(this); } public List<T> GetList<T>() where T : INetworkSerializable, new() { int num = GetInt(); if (num <= 0) { return new List<T>(0); } List<T> list = new List<T>(num); for (int i = 0; i < num; i++) { T item = new T(); item.Deserialize(this); list.Add(item); } return list; } public void GetList<T>(List<T> existingList) where T : INetworkSerializable, new() { int num = GetInt(); existingList.Clear(); for (int i = 0; i < num; i++) { T item = new T(); item.Deserialize(this); existingList.Add(item); } } } public class DataWriter : IDisposable { private byte[] _buffer; private int _position; private readonly ArrayPool<byte> _pool; public ArraySegment<byte> Data => new ArraySegment<byte>(_buffer, 0, _position); public DataWriter(int initialCapacity = 1024) { _pool = ArrayPool<byte>.Shared; _buffer = _pool.Rent(initialCapacity); _position = 0; } public byte[] ToArray() { byte[] array = new byte[_position]; Array.Copy(_buffer, 0, array, 0, _position); return array; } public void CopyDataTo(byte[] target, int targetOffset = 0) { if (target.Length - targetOffset < _position) { throw new ArgumentException("Target buffer is too small"); } Array.Copy(_buffer, 0, target, targetOffset, _position); } public void Reset() { _position = 0; } public DataWriter Put(bool value) { EnsureCapacity(1); _buffer[_position] = (byte)(value ? 1u : 0u); _position++; return this; } public DataWriter Put(byte value) { EnsureCapacity(1); _buffer[_position] = value; _position++; return this; } public DataWriter Put(short value) { EnsureCapacity(2); BinaryPrimitives.WriteInt16LittleEndian(_buffer.AsSpan(_position), value); _position += 2; return this; } public DataWriter Put(ushort value) { EnsureCapacity(2); BinaryPrimitives.WriteUInt16LittleEndian(_buffer.AsSpan(_position), value); _position += 2; return this; } public DataWriter Put(int value) { EnsureCapacity(4); BinaryPrimitives.WriteInt32LittleEndian(_buffer.AsSpan(_position), value); _position += 4; return this; } public DataWriter Put(uint value) { EnsureCapacity(4); BinaryPrimitives.WriteUInt32LittleEndian(_buffer.AsSpan(_position), value); _position += 4; return this; } public DataWriter Put(long value) { EnsureCapacity(8); BinaryPrimitives.WriteInt64LittleEndian(_buffer.AsSpan(_position), value); _position += 8; return this; } public DataWriter Put(ulong value) { EnsureCapacity(8); BinaryPrimitives.WriteUInt64LittleEndian(_buffer.AsSpan(_position), value); _position += 8; return this; } public DataWriter Put(float value) { EnsureCapacity(4); int value2 = BitConverter.SingleToInt32Bits(value); BinaryPrimitives.WriteInt32LittleEndian(_buffer.AsSpan(_position), value2); _position += 4; return this; } public DataWriter Put(double value) { EnsureCapacity(8); long value2 = BitConverter.DoubleToInt64Bits(value); BinaryPrimitives.WriteInt64LittleEndian(_buffer.AsSpan(_position), value2); _position += 8; return this; } public DataWriter Put(byte? value) { if (!value.HasValue) { Put(value: false); } else { Put(value: true); Put(value.Value); } return this; } public DataWriter Put(int? value) { if (!value.HasValue) { Put(value: false); } else { Put(value: true); Put(value.Value); } return this; } public DataWriter Put(float? value) { if (!value.HasValue) { Put(value: false); } else { Put(value: true); Put(value.Value); } return this; } public DataWriter Put(byte[] value) { if (value == null) { return Put(0); } return Put(value, 0, value.Length); } public DataWriter Put(byte[] value, int offset, int length) { if (value == null) { EnsureCapacity(4); BinaryPrimitives.WriteInt32LittleEndian(_buffer.AsSpan(_position), 0); _position += 4; return this; } Put(length); EnsureCapacity(length); Array.Copy(value, offset, _buffer, _position, length); _position += length; return this; } public DataWriter Put(ReadOnlySpan<byte> value) { Put(value.Length); EnsureCapacity(value.Length); value.CopyTo(_buffer.AsSpan(_position)); _position += value.Length; return this; } public DataWriter Put(string value) { if (string.IsNullOrEmpty(value)) { Put(0); return this; } int maxByteCount = Encoding.UTF8.GetMaxByteCount(value.Length); EnsureCapacity(maxByteCount + 4); int position = _position; _position += 4; int bytes = Encoding.UTF8.GetBytes(value, 0, value.Length, _buffer, _position); BinaryPrimitives.WriteInt32LittleEndian(_buffer.AsSpan(position), bytes); _position += bytes; return this; } public DataWriter Put(Vector3 value) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) EnsureCapacity(12); Span<byte> destination = _buffer.AsSpan(_position); BinaryPrimitives.WriteInt32LittleEndian(destination, BitConverter.SingleToInt32Bits(value.x)); BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(4), BitConverter.SingleToInt32Bits(value.y)); BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(8), BitConverter.SingleToInt32Bits(value.z)); _position += 12; return this; } public DataWriter Put(Quaternion value) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) EnsureCapacity(16); Span<byte> destination = _buffer.AsSpan(_position); BinaryPrimitives.WriteInt32LittleEndian(destination, BitConverter.SingleToInt32Bits(value.x)); BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(4), BitConverter.SingleToInt32Bits(value.y)); BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(8), BitConverter.SingleToInt32Bits(value.z)); BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(12), BitConverter.SingleToInt32Bits(value.w)); _position += 16; return this; } public DataWriter Put(Dictionary<string, byte> dict) { if (dict == null) { Put(0); return this; } Put(dict.Count); foreach (KeyValuePair<string, byte> item in dict) { Put(item.Key).Put(item.Value); } return this; } public DataWriter Put(IReadOnlyList<string> strings) { if (strings == null) { Put(0); return this; } Put(strings.Count); foreach (string @string in strings) { Put(@string); } return this; } public DataWriter Put(Dictionary<string, string> dict) { if (dict == null) { Put(0); return this; } Put(dict.Count); foreach (KeyValuePair<string, string> item in dict) { Put(item.Key).Put(item.Value); } return this; } public DataWriter Put<T>(T obj) where T : INetworkSerializable { obj.Serialize(this); return this; } public DataWriter PutIn<T>(in T obj) where T : struct, INetworkSerializable { obj.Serialize(this); return this; } public DataWriter Put<T>(IReadOnlyList<T> list) where T : INetworkSerializable { if (list == null || list.Count == 0) { Put(0); return this; } Put(list.Count); foreach (T item in list) { item.Serialize(this); } return this; } public void EnsureCapacity(int additional) { if (_position + additional > _buffer.Length) { byte[] array = _pool.Rent((_position + additional) * 2); Array.Copy(_buffer, 0, array, 0, _position); _pool.Return(_buffer); _buffer = array; } } public void Dispose() { if (_buffer != null) { _pool.Return(_buffer); _buffer = null; _position = 0; } } } public interface INetworkSerializable { void Serialize(DataWriter writer); void Deserialize(DataReader reader); } } namespace WKMPMod.Component { public class LookAt : MonoBehaviour { private Camera? mainCamera; [Header("锁定大小")] public bool maintainScreenSize = true; [Header("初始缩放比例")] public float baseScale = 0.1f; [Header("用户设置缩放比例")] public float userScale = 1f; private void LateUpdate() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mainCamera == (Object)null) { mainCamera = Camera.main; if ((Object)(object)mainCamera == (Object)null) { return; } } ((Component)this).transform.rotation = ((Component)mainCamera).transform.rotation; if (maintainScreenSize) { float num = Vector3.Distance(((Component)this).transform.position, ((Component)mainCamera).transform.position); float num2 = ((!(num < 10f)) ? num : (0.8f * num + 2f)); float num3 = num2 * baseScale * userScale; ((Component)this).transform.localScale = new Vector3(num3, num3, num3); } } } public class RemotePlayer : MonoBehaviour { public ulong playerId; [Header("距离设置")] [Tooltip("当当前位置与目标位置超过此距离时直接瞬移")] public float teleportThreshold = 50f; [Tooltip("平滑移动的最大距离限制")] public float maxSmoothDistance = 10f; private bool _isTeleporting = false; private Vector3 _targetPosition; private Vector3 _velocity = Vector3.zero; private void LateUpdate() { //IL_0016: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if (_isTeleporting) { return; } float num = Vector3.Distance(((Component)this).transform.position, _targetPosition); if (num > teleportThreshold) { Teleport(_targetPosition); } else if (((Component)this).transform.position != _targetPosition) { float num2 = CalculateSmoothTime(num); ((Component)this).transform.position = Vector3.SmoothDamp(((Component)this).transform.position, _targetPosition, ref _velocity, num2, float.MaxValue, Time.deltaTime); if (((Vector3)(ref _velocity)).magnitude < 0.5f && num > 0.05f) { Vector3 val = _targetPosition - ((Component)this).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; _velocity = normalized * 0.5f; } } } private float CalculateSmoothTime(float distance) { if (distance > maxSmoothDistance) { return Mathf.Clamp(Mathf.Log(distance) * 0.1f, 0.05f, 0.3f); } return Mathf.Clamp(distance / 10f, 0.05f, 0.1f); } public void UpdateFromPlayerData(Vector3 position, Quaternion rotation) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) _isTeleporting = false; _targetPosition = position; ((Component)this).transform.rotation = rotation; } public void UpdateFromPlayerData(ref PlayerData playerData) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) _isTeleporting = false; _targetPosition = playerData.Position; ((Component)this).transform.rotation = playerData.Rotation; } public void Teleport(Vector3 position, Quaternion? rotation = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) _isTeleporting = true; ((Component)this).transform.position = position; _targetPosition = position; _velocity = Vector3.zero; if (rotation.HasValue) { ((Component)this).transform.rotation = rotation.Value; } ((MonoBehaviour)this).StartCoroutine(ResetTeleportFlag()); } private IEnumerator ResetTeleportFlag() { yield return null; _isTeleporting = false; } } public class RemoteTag : MonoBehaviour { private Transform? _cameraTransform; private TextMeshPro? _textMeshPro; private float _lastUpdateDistance; private TickTimer updateTick = new TickTimer(1); [Header("Settings")] public const float MIN_DISTANCE_LABEL = 10f; public const float DISTANCE_CHANGE_THRESHOLD = 1f; public const float MESSAGE_TIMEOUT = 15f; [Header("Id")] public ulong PlayerId; [Header("名字")] public string PlayerName = ""; [Header("Message")] public string _message = ""; private Coroutine? _messageTimeoutCoroutine; public string Message { get { return _message; } set { string text = ((value.Length <= 15) ? value : value.Substring(0, 15)); if (!(_message == text)) { _message = text; if (_messageTimeoutCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_messageTimeoutCoroutine); } _messageTimeoutCoroutine = ((MonoBehaviour)this).StartCoroutine(MessageTimeoutRoutine()); RefreshName(); } } } private void Awake() { _textMeshPro = ((Component)this).GetComponent<TextMeshPro>(); if ((Object)(object)Camera.main != (Object)null) { _cameraTransform = ((Component)Camera.main).transform; } } private void OnDestroy() { if (_messageTimeoutCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_messageTimeoutCoroutine); } } private void Update() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (!updateTick.TryTick()) { return; } if ((Object)(object)_cameraTransform == (Object)null) { if (!((Object)(object)Camera.main != (Object)null)) { Debug.LogError((object)"[MP RemoteTag]No main camera found"); return; } _cameraTransform = ((Component)Camera.main).transform; } float num = Vector3.Distance(((Component)this).transform.position, _cameraTransform.position); if (Mathf.Abs(num - _lastUpdateDistance) >= 1f) { RefreshName(num); } } public void Initialize(ulong playerId, string playerName) { PlayerId = playerId; PlayerName = playerName; } public void RefreshName() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_cameraTransform == (Object)null)) { RefreshName(Vector3.Distance(((Component)this).transform.position, _cameraTransform.position)); } } private void RefreshName(float currentDistance) { _lastUpdateDistance = currentDistance; if (!((Object)(object)_textMeshPro == (Object)null)) { string text = currentDistance.ToString("F0"); if (currentDistance < 10f) { ((TMP_Text)_textMeshPro).text = (string.IsNullOrEmpty(_message) ? PlayerName : (PlayerName + "\n" + _message)); return; } ((TMP_Text)_textMeshPro).text = (string.IsNullOrEmpty(_message) ? (PlayerName + " (" + text + "m)") : (PlayerName + " (" + text + "m)\n" + _message)); } } private IEnumerator MessageTimeoutRoutine() { yield return (object)new WaitForSeconds(15f); _message = ""; RefreshName(); _messageTimeoutCoroutine = null; } } public class SimpleArmIK : MonoBehaviour { [Header("目标设置")] public Transform? target; public float originalLength = 1f; [Header("限制")] public float minScale = 0.1f; public float maxScale = 10f; private void Start() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (originalLength <= 0f && (Object)(object)target != (Object)null) { originalLength = Vector3.Distance(((Component)this).transform.position, target.position); } } private void LateUpdate() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null)) { Vector3 val = target.position - ((Component)this).transform.position; float magnitude = ((Vector3)(ref val)).magnitude; if (!(magnitude < 0.0001f)) { ((Component)this).transform.rotation = Quaternion.FromToRotation(Vector3.up, val); float num = magnitude / originalLength; num = Mathf.Clamp(num, minScale, maxScale); ((Component)this).transform.localScale = new Vector3(1f, num, 1f); } } } } }