using System; using System.Collections.Generic; using System.Runtime.InteropServices; using HG; using JetBrains.Annotations; using RoR2.Networking; using UnityEngine; using UnityEngine.Networking; namespace RoR2; public class NetworkUIPromptController : NetworkBehaviour { private struct LocalUserInfo { public LocalUser localUser; public NetworkUIPromptController currentController; } private float lastCurrentLocalParticipantUpdateTime = float.NegativeInfinity; private LocalUser _currentLocalParticipant; private CharacterMaster _currentParticipantMaster; private bool _inControl; [SyncVar(hook = "SetParticipantMasterId")] private NetworkInstanceId masterObjectInstanceId; private CameraRigController _currentCamera; private static LocalUserInfo[] allLocalUserInfo = Array.Empty(); private static int allLocalUserInfoCount = 0; public Action messageFromClientHandler; private LocalUser currentLocalParticipant { get { return _currentLocalParticipant; } set { if (_currentLocalParticipant != value) { if (_currentLocalParticipant != null) { OnLocalParticipantLost(_currentLocalParticipant); } _currentLocalParticipant = value; if (_currentLocalParticipant != null) { OnLocalParticipantDiscovered(_currentLocalParticipant); } } } } public CharacterMaster currentParticipantMaster { get { return _currentParticipantMaster; } private set { if ((object)_currentParticipantMaster != value) { if ((object)_currentParticipantMaster != null) { OnParticipantLost(_currentParticipantMaster); } _currentParticipantMaster = value; if ((object)_currentParticipantMaster != null) { OnParticipantDiscovered(_currentParticipantMaster); } } } } private bool inControl { get { return _inControl; } set { if (_inControl != value) { _inControl = value; if (_inControl) { OnControlBegin(); } else { OnControlEnd(); } } } } private CameraRigController currentCamera { get { return _currentCamera; } set { if ((object)_currentCamera != value) { if ((object)_currentCamera != null) { this.onDisplayEnd?.Invoke(this, currentLocalParticipant, _currentCamera); } _currentCamera = value; if ((object)_currentCamera != null) { this.onDisplayBegin?.Invoke(this, currentLocalParticipant, _currentCamera); } } } } public bool inUse => currentParticipantMaster; public bool isDisplaying => currentCamera; public NetworkInstanceId NetworkmasterObjectInstanceId { get { return masterObjectInstanceId; } [param: In] set { if (NetworkServer.localClientActive && !base.syncVarHookGuard) { base.syncVarHookGuard = true; SetParticipantMasterId(value); base.syncVarHookGuard = false; } SetSyncVar(value, ref masterObjectInstanceId, 1u); } } public event Action onDisplayBegin; public event Action onDisplayEnd; private void OnParticipantDiscovered([NotNull] CharacterMaster master) { LocalUser localUser = null; if ((bool)master.playerCharacterMasterController && (bool)master.playerCharacterMasterController.networkUser) { localUser = master.playerCharacterMasterController.networkUser.localUser; } currentLocalParticipant = localUser; } private void OnParticipantLost([NotNull] CharacterMaster master) { currentLocalParticipant = null; } private void OnLocalParticipantDiscovered([NotNull] LocalUser localUser) { lastCurrentLocalParticipantUpdateTime = Time.unscaledTime; UpdateBestControllerForLocalUser(localUser); } private void OnLocalParticipantLost([NotNull] LocalUser localUser) { ref LocalUserInfo localUserInfo = ref GetLocalUserInfo(localUser); if (localUserInfo.currentController == this) { localUserInfo.currentController.inControl = false; localUserInfo.currentController = null; } } private void HandleCameraDiscovered(CameraRigController cameraRigController) { currentCamera = cameraRigController; } private void HandleCameraLost(CameraRigController cameraRigController) { currentCamera = null; } private void OnControlBegin() { currentCamera = currentLocalParticipant.cameraRigController; currentLocalParticipant.onCameraDiscovered += HandleCameraDiscovered; currentLocalParticipant.onCameraLost += HandleCameraLost; } private void OnControlEnd() { currentLocalParticipant.onCameraLost -= HandleCameraLost; currentLocalParticipant.onCameraDiscovered -= HandleCameraDiscovered; currentCamera = null; } [CanBeNull] private static NetworkUIPromptController FindBestControllerForLocalUser([NotNull] LocalUser localUser) { NetworkUIPromptController result = null; float num = float.PositiveInfinity; List instancesList = InstanceTracker.GetInstancesList(); for (int i = 0; i < instancesList.Count; i++) { NetworkUIPromptController networkUIPromptController = instancesList[i]; if (networkUIPromptController.currentLocalParticipant == localUser && networkUIPromptController.lastCurrentLocalParticipantUpdateTime < num) { num = networkUIPromptController.lastCurrentLocalParticipantUpdateTime; result = networkUIPromptController; } } return result; } private static void UpdateBestControllerForLocalUser([NotNull] LocalUser localUser) { ref LocalUserInfo localUserInfo = ref GetLocalUserInfo(localUser); NetworkUIPromptController currentController = localUserInfo.currentController; NetworkUIPromptController networkUIPromptController = FindBestControllerForLocalUser(localUser); if ((object)currentController != networkUIPromptController) { if ((object)currentController != null) { currentController.inControl = false; } if ((object)networkUIPromptController != null) { networkUIPromptController.inControl = true; } localUserInfo.currentController = networkUIPromptController; } } private void OnEnable() { InstanceTracker.Add(this); } private void OnDisable() { SetParticipantMasterId(NetworkInstanceId.Invalid); InstanceTracker.Remove(this); } public override void OnStartClient() { base.OnStartClient(); if (!NetworkServer.active) { SetParticipantMasterId(masterObjectInstanceId); } } private void SetParticipantMasterId(NetworkInstanceId newMasterObjectInstanceId) { NetworkmasterObjectInstanceId = newMasterObjectInstanceId; GameObject gameObject = Util.FindNetworkObject(masterObjectInstanceId); CharacterMaster characterMaster = null; if ((bool)gameObject) { characterMaster = gameObject.GetComponent(); } currentParticipantMaster = characterMaster; } [Server] public void ClearParticipant() { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.NetworkUIPromptController::ClearParticipant()' called on client"); } else { SetParticipantMaster(null); } } [Server] public void SetParticipantMaster([CanBeNull] CharacterMaster newParticipantMaster) { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.NetworkUIPromptController::SetParticipantMaster(RoR2.CharacterMaster)' called on client"); return; } NetworkIdentity networkIdentity = (newParticipantMaster ? newParticipantMaster.networkIdentity : null); SetParticipantMasterId(networkIdentity ? networkIdentity.netId : NetworkInstanceId.Invalid); } [Server] public void SetParticipantMasterFromInteractor([CanBeNull] Interactor newParticipantInteractor) { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.NetworkUIPromptController::SetParticipantMasterFromInteractor(RoR2.Interactor)' called on client"); return; } CharacterMaster participantMaster = ((!newParticipantInteractor) ? null : newParticipantInteractor.GetComponent()?.master); SetParticipantMaster(participantMaster); } [Server] public void SetParticipantMasterFromInteractorObject([CanBeNull] UnityEngine.Object newParticipantInteractor) { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.NetworkUIPromptController::SetParticipantMasterFromInteractorObject(UnityEngine.Object)' called on client"); } else { SetParticipantMasterFromInteractor(newParticipantInteractor as Interactor); } } [SystemInitializer(new Type[] { })] private static void Init() { LocalUserManager.onUserSignIn += OnUserSignIn; LocalUserManager.onUserSignOut += OnUserSignOut; } private static void OnUserSignIn(LocalUser localUser) { LocalUserInfo localUserInfo = default(LocalUserInfo); localUserInfo.localUser = localUser; localUserInfo.currentController = null; LocalUserInfo value = localUserInfo; ArrayUtils.ArrayAppend(ref allLocalUserInfo, ref allLocalUserInfoCount, in value); } private static void OnUserSignOut(LocalUser localUser) { for (int i = 0; i < allLocalUserInfoCount; i++) { if (allLocalUserInfo[i].localUser == localUser) { ArrayUtils.ArrayRemoveAt(allLocalUserInfo, ref allLocalUserInfoCount, i); break; } } } private static ref LocalUserInfo GetLocalUserInfo(LocalUser localUser) { for (int i = 0; i < allLocalUserInfoCount; i++) { if (allLocalUserInfo[i].localUser == localUser) { return ref allLocalUserInfo[i]; } } throw new ArgumentException("localUser must be signed in"); } [Client] public NetworkWriter BeginMessageToServer() { if (!NetworkClient.active) { Debug.LogWarning("[Client] function 'UnityEngine.Networking.NetworkWriter RoR2.NetworkUIPromptController::BeginMessageToServer()' called on server"); return null; } NetworkWriter networkWriter = new NetworkWriter(); networkWriter.StartMessage(76); networkWriter.Write(base.gameObject); return networkWriter; } [Client] public void FinishMessageToServer(NetworkWriter writer) { if (!NetworkClient.active) { Debug.LogWarning("[Client] function 'System.Void RoR2.NetworkUIPromptController::FinishMessageToServer(UnityEngine.Networking.NetworkWriter)' called on server"); return; } writer.FinishMessage(); NetworkUser networkUser = FindParticipantNetworkUser(this); if ((bool)networkUser) { networkUser.connectionToServer.SendWriter(writer, GetNetworkChannel()); } } private static NetworkUser FindParticipantNetworkUser(NetworkUIPromptController instance) { if ((bool)instance) { CharacterMaster characterMaster = instance.currentParticipantMaster; if ((bool)characterMaster) { PlayerCharacterMasterController playerCharacterMasterController = characterMaster.playerCharacterMasterController; if ((bool)playerCharacterMasterController) { return playerCharacterMasterController.networkUser; } } } return null; } [NetworkMessageHandler(client = false, server = true, msgType = 76)] private static void HandleNetworkUIPromptMessage(NetworkMessage netMsg) { GameObject gameObject = netMsg.reader.ReadGameObject(); if (!gameObject) { return; } NetworkUIPromptController component = gameObject.GetComponent(); if ((bool)component) { NetworkUser networkUser = FindParticipantNetworkUser(component); NetworkConnection networkConnection = (networkUser ? networkUser.connectionToClient : null); if (netMsg.conn == networkConnection) { component.messageFromClientHandler?.Invoke(netMsg.reader); } } } private void UNetVersion() { } public override bool OnSerialize(NetworkWriter writer, bool forceAll) { if (forceAll) { writer.Write(masterObjectInstanceId); return true; } bool flag = false; if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) { if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); flag = true; } writer.Write(masterObjectInstanceId); } if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); } return flag; } public override void OnDeserialize(NetworkReader reader, bool initialState) { if (initialState) { masterObjectInstanceId = reader.ReadNetworkId(); return; } int num = (int)reader.ReadPackedUInt32(); if (((uint)num & (true ? 1u : 0u)) != 0) { SetParticipantMasterId(reader.ReadNetworkId()); } } public override void PreStartClient() { } }