486 lines
12 KiB
C#
486 lines
12 KiB
C#
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<LocalUserInfo>();
|
|
|
|
private static int allLocalUserInfoCount = 0;
|
|
|
|
public Action<NetworkReader> 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<NetworkUIPromptController, LocalUser, CameraRigController> onDisplayBegin;
|
|
|
|
public event Action<NetworkUIPromptController, LocalUser, CameraRigController> 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<NetworkUIPromptController> instancesList = InstanceTracker.GetInstancesList<NetworkUIPromptController>();
|
|
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<CharacterMaster>();
|
|
}
|
|
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<CharacterBody>()?.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<NetworkUIPromptController>();
|
|
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()
|
|
{
|
|
}
|
|
}
|