using HurricaneVR.Framework.Components; using HurricaneVR.Framework.ControllerInput; using HurricaneVR.Framework.Core.Player; using HurricaneVR.Framework.Core.UI; using Meta.XR.MultiplayerBlocks.NGO; using Sirenix.OdinInspector; using System.Collections; using System.Collections.Generic; using Unity.Netcode; using Unity.Netcode.Components; using Unity.VisualScripting; using UnityEngine; using UnityEngine.Rendering.Universal; using UnityEngine.UIElements; using Zenject; public class PlayerComponent : NetworkBehaviour { [SerializeField] [Inject] private HVRInputModule inputModule; [SerializeField] private NetworkObject networkObject; [SerializeField] private HVRTeleporter teleporter; [SerializeField] private HVRPlayerController controller; [SerializeField] private CharacterController characterController; [SerializeField] private AudioListener audioListener; [ReadOnly] [SerializeField] private float fadeDuration = 2f; private GameObject[] dependencies => new GameObject[] { controller.RightHand.ForceGrabber._anchor.gameObject, controller.LeftHand.ForceGrabber._anchor.gameObject, controller.LeftHand._anchor, controller.RightHand._anchor }; public Vector3 Position => controller.transform.position; public Vector3 Rotation => controller.Camera.forward; private bool isSoloRig => !networkObject.IsPlayerObject; private bool isLocalRig => networkObject.IsLocalPlayer; private bool isRemoteRig => !networkObject.IsOwner && networkObject.IsPlayerObject; // Teleport information after player is loaded into scene private Vector3 teleportPosition; private Vector3 teleportRotation; private bool teleportAfterLoad; private bool isLoaded; private void Start() { this.Inject(); StartCoroutine(AddDontDestroyToDependencies()); if (isSoloRig) { AddPointersToInputModule(); name = "Player - SP"; StartCoroutine(DestroyComponentsNotNeededForSolo()); DontDestroyOnLoad(gameObject); } else if (isLocalRig) { AddPointersToInputModule(); name = $"Player - MP {networkObject.OwnerClientId} (local)"; } else if (isRemoteRig) { name = $"Player - MP {networkObject.OwnerClientId}"; StartCoroutine(DestroyComponentsNotNeededForRemoteRigs()); } isLoaded = true; if (teleportAfterLoad) { Teleport(teleportPosition, teleportRotation); } } private void AddPointersToInputModule() { foreach (var pointer in GetComponentsInChildren()) { inputModule.AddPointer(pointer); } } private IEnumerator DestroyComponentsNotNeededForRemoteRigs() { yield return new WaitForEndOfFrame(); DestroyDependencies(); foreach (var t in new[] { typeof(UniversalAdditionalCameraData), typeof(HandMenuUI) }) { foreach (var component in GetComponentsInChildren(t)) { Destroy(component); } } controller.RemoveMultiplayerComponents(); } private IEnumerator DestroyComponentsNotNeededForSolo() { yield return new WaitForEndOfFrame(); foreach (var t in new[] { typeof(NetworkObject), typeof(NetworkTransform) }) { foreach (var component in GetComponentsInChildren(t)) { Destroy(component); } } } private IEnumerator AddDontDestroyToDependencies() { yield return new WaitForEndOfFrame(); foreach (var d in dependencies) { DontDestroyOnLoad(d); } } public void DestroyDependencies() { foreach (var d in dependencies) { Destroy(d); } } public void Teleport(Vector3 position, Vector3 direction) { StartCoroutine(TeleportAtTheEndOfFrame(position, direction)); } private IEnumerator TeleportAtTheEndOfFrame(Vector3 position, Vector3 direction) { yield return new WaitForEndOfFrame(); if (isLoaded) { teleporter.Teleport(position, direction); } else { teleportPosition = position; teleportRotation = direction; teleportAfterLoad = true; } } public void FadeScreen(float to, float duration) { controller.ScreenFader.Fade(to, duration); } public void FadeIn() { controller.ScreenFader.Fade(1, fadeDuration); } public void FadeOut() { controller.ScreenFader.Fade(0, fadeDuration); } }