From 3735c68756bb2acdbe560562c088c3c12a8e657f Mon Sep 17 00:00:00 2001 From: Fredrik Lillemoen Eiding Date: Sat, 13 Jul 2024 00:46:37 +0200 Subject: [PATCH] Revert player intialization refactor --- .../Control&Input/Peer2PeerTransport.cs | 224 ++++++++++++++++-- Assets/Scripts/Gamestate/PlayerFactory.cs | 164 +------------ Assets/Scripts/Gamestate/PlayerIdentity.cs | 4 +- .../PlayerSelect/PlayerSelectManager.cs | 2 +- 4 files changed, 222 insertions(+), 172 deletions(-) diff --git a/Assets/Scripts/Control&Input/Peer2PeerTransport.cs b/Assets/Scripts/Control&Input/Peer2PeerTransport.cs index 985786df0..2b353f555 100644 --- a/Assets/Scripts/Control&Input/Peer2PeerTransport.cs +++ b/Assets/Scripts/Control&Input/Peer2PeerTransport.cs @@ -27,14 +27,6 @@ public struct PlayerDetails public string body; public string barrel; public string extension; - - public string PlayerNameWithIndex() - { - var mySteamID = steamID; - if (Peer2PeerTransport.PlayerDetails.Count(p => p.steamID == mySteamID) > 1) - return $"{name} {localInputID + 1}"; - return name; - } } public struct PlayerConnectedMessage : NetworkMessage @@ -143,6 +135,8 @@ public class Peer2PeerTransport : NetworkManager private const int AIFPSPlayerPrefabIndex = 2; private const int TrainingPlayerPrefabIndex = 4; + private const int NetworkPlayerLayer = 3; + private PlayerFactory playerFactory; private static Transform[] spawnPoints; private static Stack spawnPointStack; @@ -707,8 +701,8 @@ private IEnumerator SendSpawnRequestsAfterSceneLoad(string originalSceneName) #endregion + #region Spawn FPS players - #region Spawn players private void SpawnPlayer(NetworkConnectionToClient connection, SpawnPlayerMessage message, int prefabIndexOffset = 0) { @@ -760,9 +754,148 @@ private void OnSpawnFPSPlayer(NetworkConnectionToClient connection, SpawnPlayerM private void InitializeFPSPlayer(InitializePlayerMessage message) { - StartCoroutine(WaitAndInitializePlayer(message, false)); + StartCoroutine(WaitAndInitializeFPSPlayer(message)); + } + + // TODO move this somewhere else? + public static string PlayerNameWithIndex(PlayerDetails playerDetails) + { + var playerName = playerDetails.name; + if (players.Values.Count(p => p.steamID == playerDetails.steamID) > 1) + playerName = $"{playerName} {playerDetails.localInputID + 1}"; + return playerName; + } + + private void UpdateIdentityFromDetails(PlayerIdentity identity, PlayerDetails playerDetails) + { + identity.UpdateFromDetails(playerDetails, PlayerNameWithIndex(playerDetails)); + } + + private IEnumerator WaitAndInitializeFPSPlayer(InitializePlayerMessage message) + { + // Wait until player object is spawned + PlayerManager player = null; + while (player == null) + { + player = FindObjectsOfType() + .FirstOrDefault(p => p.id == message.id); + yield return null; + } + + if (!player) + { + Debug.LogError($"Could not find player object for id {message.id}"); + yield break; + } + + if (!players.TryGetValue(message.id, out var playerDetails)) + { + Debug.LogError($"Could not find player details for id {message.id}"); + yield break; + } + + var playerManager = player.GetComponent(); + + player.transform.position = message.position; + player.transform.rotation = message.rotation; + + var cameraOffset = player.transform.Find("CameraOffset"); + playerManager.GetComponent().enabled = true; + + if (playerDetails.type is PlayerType.Local) + { + Debug.Log($"Spawning local player {playerDetails.id}"); + var input = PlayerInputManagerController.Singleton.LocalPlayerInputs[playerDetails.localInputID]; + + // Reset camera transform (it may have been kerfluffled by the spectator cam thingy) + input.transform.localPosition = Vector3.zero; + input.transform.localRotation = Quaternion.identity; + input.PlayerCamera.transform.localRotation = Quaternion.identity; + input.PlayerCamera.transform.localPosition = Vector3.zero; + + // Make playerInput child of player it's attached to + input.transform.parent = player.transform; + // Set received playerInput (and most importantly its camera) at an offset from player's position + input.transform.localPosition = cameraOffset.localPosition; + input.transform.rotation = player.transform.rotation; + + // Enable Camera + input.PlayerCamera.enabled = true; + input.PlayerCamera.orthographic = false; + + playerManager.HUDController.gameObject.SetActive(true); + var movement = player.GetComponent(); + + // The identity sits on the input in this case, so edit that + var identity = input.GetComponent(); + UpdateIdentityFromDetails(identity, playerDetails); + + // Update player's movement script with which playerInput it should attach listeners to + playerManager.SetPlayerInput(input); + var gunHolder = input.transform.GetChild(0); + playerManager.SetGun(gunHolder); + + // Set unique layer for player + playerManager.SetLayer(input.playerInput.playerIndex); + movement.SetInitialRotation(message.rotation.eulerAngles.y * Mathf.Deg2Rad); + + if (GunFactory.TryGetGunAchievement(playerManager.identity.Body, playerManager.identity.Barrel, + playerManager.identity.Extension, out var achievement)) + SteamManager.Singleton.UnlockAchievement(achievement); + } + else if (playerDetails.type is PlayerType.AI && NetworkServer.active) + { + Debug.Log($"Spawning AI player {playerDetails.id}"); + AIManager manager = player.GetComponent(); + manager.SetLayer(NetworkPlayerLayer); + UpdateIdentityFromDetails(playerManager.identity, playerDetails); + manager.SetIdentity(playerManager.identity); + manager.GetComponent().SetInitialRotation(message.rotation.eulerAngles.y * Mathf.Deg2Rad); + } + else + { + Debug.Log($"Spawning network player {playerDetails.id}"); + + UpdateIdentityFromDetails(playerManager.identity, playerDetails); + + // TODO do some other version of disabling HUD completely + Destroy(playerManager.HUDController); + + // Disable physics + playerManager.GetComponent().isKinematic = true; + + // Create display gun structure + var gunHolderParent = new GameObject("DisplayGunParent").transform; + gunHolderParent.parent = player.transform; + gunHolderParent.position = cameraOffset.position; + gunHolderParent.rotation = player.transform.rotation; + var gunHolder = new GameObject("DisplayGunHolder").transform; + gunHolder.parent = gunHolderParent.transform; + gunHolder.localPosition = Vector3.zero; + gunHolder.localRotation = Quaternion.identity; + playerManager.SetLayer(NetworkPlayerLayer); + // Can't initialize quite like the AIs because of where the GunController network behaviour is located :( + playerManager.SetGun(gunHolder); + } + + playerManager.ApplyIdentity(); + + // This ensures that behaviours on the gun have identities. + // SHOULD be safe to initialize them here as this is at roughly the same point on all clients + player.GetComponent().InitializeNetworkBehaviours(); + + if (MatchController.Singleton) + { + MatchController.Singleton.RegisterPlayer(playerManager); + } + + playerInstances[player.id] = player; } + #endregion + + #region Bidding spawning + private void OnSpawnBiddingPlayer(NetworkConnectionToClient connection, SpawnPlayerMessage message) { SpawnPlayer(connection, message, BiddingPlayerPrefabIndexOffset); @@ -770,12 +903,12 @@ private void OnSpawnBiddingPlayer(NetworkConnectionToClient connection, SpawnPla private void InitializeBiddingPlayer(InitializePlayerMessage message) { - StartCoroutine(WaitAndInitializePlayer(message, true)); + StartCoroutine(WaitAndInitializeBiddingPlayer(message)); } - private IEnumerator WaitAndInitializePlayer(InitializePlayerMessage message, bool isBidding = false) + private IEnumerator WaitAndInitializeBiddingPlayer(InitializePlayerMessage message) { - // Wait until player object is spawned + // Wait until players must've been spawned PlayerManager player = null; while (player == null) { @@ -796,7 +929,70 @@ private IEnumerator WaitAndInitializePlayer(InitializePlayerMessage message, boo yield break; } - PlayerFactory.InitializePlayer(message, player, playerDetails, isBidding); + var playerManager = player.GetComponent(); + + player.transform.position = message.position; + player.transform.rotation = message.rotation; + + var cameraOffset = player.transform.Find("CameraOffset"); + playerManager.GetComponent().enabled = true; + + if (playerDetails.type is PlayerType.Local) + { + Debug.Log($"Spawning local player {playerDetails.id}"); + var input = PlayerInputManagerController.Singleton.LocalPlayerInputs[playerDetails.localInputID]; + + // Reset camera transform (ensuring we don't mess up in weapon building) + input.transform.localPosition = Vector3.zero; + input.transform.localRotation = Quaternion.identity; + input.PlayerCamera.transform.localRotation = Quaternion.identity; + input.PlayerCamera.transform.localPosition = Vector3.zero; + + // Make playerInput child of player it's attached to + input.transform.parent = player.transform; + // Set received playerInput (and most importantly its camera) at an offset from player's position + input.transform.localPosition = cameraOffset.localPosition; + input.transform.rotation = player.transform.rotation; + + // Disable Camera + input.PlayerCamera.enabled = false; + + // Update player's movement script with which playerInput it should attach listeners to + playerManager.SetPlayerInput(input); + player.GetComponent().enabled = false; + + // The identity sits on the input in this case, so edit that + var identity = input.GetComponent(); + UpdateIdentityFromDetails(identity, playerDetails); + } + else if (playerDetails.type is PlayerType.AI && NetworkServer.active) + { + Debug.Log($"Spawning AI player {playerDetails.id}"); + AIManager manager = player.GetComponent(); + manager.SetLayer(NetworkPlayerLayer); + UpdateIdentityFromDetails(playerManager.identity, playerDetails); + manager.SetIdentity(manager.identity); + } + else + { + Debug.Log($"Spawning network player {playerDetails.id}"); + + UpdateIdentityFromDetails(playerManager.identity, playerDetails); + + // Disable physics + playerManager.GetComponent().isKinematic = true; + } + + playerManager.ApplyIdentity(); + + // This ensures that behaviours on the gun have identities. + // SHOULD be safe to initialize them here as this is at roughly the same point on all clients + player.GetComponent().InitializeNetworkBehaviours(); + + if (MatchController.Singleton) + { + MatchController.Singleton.RegisterPlayer(playerManager); + } playerInstances[player.id] = player; } diff --git a/Assets/Scripts/Gamestate/PlayerFactory.cs b/Assets/Scripts/Gamestate/PlayerFactory.cs index a9453ab4c..0b2c57d92 100644 --- a/Assets/Scripts/Gamestate/PlayerFactory.cs +++ b/Assets/Scripts/Gamestate/PlayerFactory.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using UnityEngine; using CollectionExtensions; -using Mirror; public class PlayerFactory : MonoBehaviour { @@ -11,12 +10,9 @@ public class PlayerFactory : MonoBehaviour private Transform[] spawnPoints; [SerializeField] private GameObject playerSelectItemPrefab; - private float spawnInterval = 0f; private PlayerInputManagerController playerInputManagerController; - private const int NetworkPlayerLayer = 3; - private void Awake() { if (PlayerInputManagerController.Singleton == null) @@ -33,15 +29,14 @@ private void Awake() playerInputManagerController.PlayerInputManager.splitScreen = true; } - #region Weapon construction spawning - public void InstantiatePlayerSelectItems() { playerInputManagerController.ChangeInputMaps("Menu"); InstantiateInputsOnSpawnpoints(InstantiateItemSelectPlayer); } - private List InstantiateInputsOnSpawnpoints(Func instantiate) + // TODO remove this from its mortal coil, we don't really use PlayerFactory anymore :) + private List InstantiateInputsOnSpawnpoints(Func instantiate, Func instantiateAI = null, int aiPlayerCount = 0) { var shuffledSpawnPoints = spawnPoints.ShuffledCopy(); @@ -50,6 +45,13 @@ private List InstantiateInputsOnSpawnpoints(Func().SpawnItems(inputManager)); return null; } - - #endregion - - - #region Initialization - - public static void InitializePlayer(InitializePlayerMessage message, PlayerManager player, PlayerDetails playerDetails, bool isBidding = false) - { - player.GetComponent().enabled = true; - - player.transform.position = message.position; - player.transform.rotation = message.rotation; - - Debug.Log($"Spawning {playerDetails.type} player {playerDetails.id}"); - - if (isBidding) - InitializeBiddingPlayer(message, player, playerDetails); - else - InitializeFPSPlayer(message, player, playerDetails); - - player.ApplyIdentity(); - - // This ensures that behaviours on the gun have identities. - // SHOULD be safe to initialize them here as this is at roughly the same point on all clients - player.GetComponent().InitializeNetworkBehaviours(); - - if (MatchController.Singleton) - { - MatchController.Singleton.RegisterPlayer(player); - } - } - - private static void InitializeFPSPlayer(InitializePlayerMessage message, PlayerManager player, PlayerDetails playerDetails) - { - var cameraOffset = player.transform.Find("CameraOffset"); - if (playerDetails.type is PlayerType.Local) - { - var input = SetupLocalPlayerInput(player, playerDetails); - - // Enable Camera - input.PlayerCamera.enabled = true; - input.PlayerCamera.orthographic = false; - - player.HUDController.gameObject.SetActive(true); - var movement = player.GetComponent(); - - // Update player's movement script with which playerInput it should attach listeners to - var gunHolder = input.transform.GetChild(0); - player.SetGun(gunHolder); - - // Set unique layer for player - player.SetLayer(input.playerInput.playerIndex); - movement.SetInitialRotation(message.rotation.eulerAngles.y * Mathf.Deg2Rad); - - if (GunFactory.TryGetGunAchievement(player.identity.Body, player.identity.Barrel, - player.identity.Extension, out var achievement)) - SteamManager.Singleton.UnlockAchievement(achievement); - } - else if (playerDetails.type is PlayerType.AI && NetworkServer.active) - { - InitializeAIPlayer(message, player, playerDetails); - } - else - { - player.identity.UpdateFromDetails(playerDetails); - - // TODO do some other version of disabling HUD completely - Destroy(player.HUDController); - - // Disable physics - player.GetComponent().isKinematic = true; - - // Create display gun structure - var gunHolderParent = new GameObject("DisplayGunParent").transform; - gunHolderParent.parent = player.transform; - gunHolderParent.position = cameraOffset.position; - gunHolderParent.rotation = player.transform.rotation; - var gunHolder = new GameObject("DisplayGunHolder").transform; - gunHolder.parent = gunHolderParent.transform; - gunHolder.localPosition = Vector3.zero; - gunHolder.localRotation = Quaternion.identity; - player.SetLayer(NetworkPlayerLayer); - // Can't initialize quite like the AIs because of where the GunController network behaviour is located :( - player.SetGun(gunHolder); - } - } - - private static void InitializeBiddingPlayer(InitializePlayerMessage message, PlayerManager player, PlayerDetails playerDetails) - { - if (playerDetails.type is PlayerType.Local) - { - var input = SetupLocalPlayerInput(player, playerDetails); - - // Disable camera - input.PlayerCamera.enabled = false; - - // Disable health - player.GetComponent().enabled = false; - } - else if (playerDetails.type is PlayerType.AI && NetworkServer.active) - { - InitializeAIPlayer(message, player, playerDetails); - } - else - { - player.identity.UpdateFromDetails(playerDetails); - - // Disable physics - player.GetComponent().isKinematic = true; - } - } - - private static InputManager SetupLocalPlayerInput(PlayerManager player, PlayerDetails playerDetails) - { - var input = PlayerInputManagerController.Singleton.LocalPlayerInputs[playerDetails.localInputID]; - var cameraOffset = player.transform.Find("CameraOffset"); - - // Reset camera transform (it may have been kerfluffled by the spectator cam thingy) - input.transform.localPosition = Vector3.zero; - input.transform.localRotation = Quaternion.identity; - input.PlayerCamera.transform.localRotation = Quaternion.identity; - input.PlayerCamera.transform.localPosition = Vector3.zero; - - // Make playerInput child of player it's attached to - input.transform.parent = player.transform; - // Set received playerInput (and most importantly its camera) at an offset from player's position - input.transform.localPosition = cameraOffset.localPosition; - input.transform.rotation = player.transform.rotation; - - // The identity sits on the input in this case, so edit that - var identity = input.GetComponent(); - identity.UpdateFromDetails(playerDetails); - - player.SetPlayerInput(input); - - return input; - } - - private static void InitializeAIPlayer(InitializePlayerMessage message, PlayerManager player, PlayerDetails playerDetails) - { - AIManager manager = player.GetComponent(); - manager.SetLayer(NetworkPlayerLayer); - player.identity.UpdateFromDetails(playerDetails); - manager.SetIdentity(player.identity); - manager.GetComponent().SetInitialRotation(message.rotation.eulerAngles.y * Mathf.Deg2Rad); - } - - #endregion } diff --git a/Assets/Scripts/Gamestate/PlayerIdentity.cs b/Assets/Scripts/Gamestate/PlayerIdentity.cs index f8790bb66..74ac8ec12 100644 --- a/Assets/Scripts/Gamestate/PlayerIdentity.cs +++ b/Assets/Scripts/Gamestate/PlayerIdentity.cs @@ -199,11 +199,11 @@ public void SetLoadout(Item body, Item barrel, Item extension) this.extension = extension; } - public void UpdateFromDetails(PlayerDetails playerDetails) + public void UpdateFromDetails(PlayerDetails playerDetails, string name) { id = playerDetails.id; - playerName = playerDetails.PlayerNameWithIndex(); + playerName = name; color = playerDetails.color; Chips = playerDetails.chips; diff --git a/Assets/Scripts/PlayerSelect/PlayerSelectManager.cs b/Assets/Scripts/PlayerSelect/PlayerSelectManager.cs index c2f7e91de..ea44a34ec 100644 --- a/Assets/Scripts/PlayerSelect/PlayerSelectManager.cs +++ b/Assets/Scripts/PlayerSelect/PlayerSelectManager.cs @@ -95,7 +95,7 @@ public void SetupPlayerModel(PlayerDetails player, int index) playerModels[index].GetComponentInChildren().material.color = player.color; // Set player model color playerModels[index].SetActive(true); // Show corresponding player model playerModels[index].transform.LookAt(new Vector3(playerSelectCam.transform.position.x, playerModels[index].transform.position.y, playerSelectCam.transform.position.z)); // Orient player model to look at camera - nameTags[index].text = player.PlayerNameWithIndex(); + nameTags[index].text = Peer2PeerTransport.PlayerNameWithIndex(player); nameTags[index].enabled = true; joinText[index].enabled = false; }