using System; using System.Collections.Generic; using Unity.BossRoom.ConnectionManagement; using Unity.Multiplayer.Samples.BossRoom; using Unity.Netcode; using UnityEngine; namespace Unity.BossRoom.Gameplay.GameplayObjects.Character { /// /// Attached to the player-characters' prefab, this maintains a list of active ServerCharacter objects for players. /// /// /// This is an optimization. In server code you can already get a list of players' ServerCharacters by /// iterating over the active connections and calling GetComponent() on their PlayerObject. But we need /// to iterate over all players quite often -- the monsters' IdleAIState does so in every Update() -- /// and all those GetComponent() calls add up! So this optimization lets us iterate without calling /// GetComponent(). This will be refactored with a ScriptableObject-based approach on player collection. /// [RequireComponent(typeof(ServerCharacter))] public class PlayerServerCharacter : NetworkBehaviour { static List s_ActivePlayers = new List(); [SerializeField] ServerCharacter m_CachedServerCharacter; public override void OnNetworkSpawn() { if (IsServer) { s_ActivePlayers.Add(m_CachedServerCharacter); } else { enabled = false; } } void OnDisable() { s_ActivePlayers.Remove(m_CachedServerCharacter); } public override void OnNetworkDespawn() { if (IsServer) { var movementTransform = m_CachedServerCharacter.Movement.transform; SessionPlayerData? sessionPlayerData = SessionManager.Instance.GetPlayerData(OwnerClientId); if (sessionPlayerData.HasValue) { var playerData = sessionPlayerData.Value; playerData.PlayerPosition = movementTransform.position; playerData.PlayerRotation = movementTransform.rotation; playerData.CurrentHitPoints = m_CachedServerCharacter.HitPoints; playerData.HasCharacterSpawned = true; SessionManager.Instance.SetPlayerData(OwnerClientId, playerData); } } } /// /// Returns a list of all active players' ServerCharacters. Treat the list as read-only! /// The list will be empty on the client. /// public static List GetPlayerServerCharacters() { return s_ActivePlayers; } /// /// Returns the ServerCharacter owned by a specific client. Always returns null on the client. /// /// /// The ServerCharacter owned by the client, or null if no ServerCharacter is found public static ServerCharacter GetPlayerServerCharacter(ulong ownerClientId) { foreach (var playerServerCharacter in s_ActivePlayers) { if (playerServerCharacter.OwnerClientId == ownerClientId) { return playerServerCharacter; } } return null; } } }