using ExitGames.Client.Photon; using Photon.Pun; using Photon.Realtime; using System.Collections.Generic; using UnityEngine; public class PlayerSlotManager : MonoBehaviour { public Room Room { get; set; } public List playerSlots; public GameObject colorSelector; private List ActiveSlots { get => playerSlots.FindAll(p => !p.IsEmpty); } private List EmptySlots { get => playerSlots.FindAll(p => p.IsEmpty); } private List Players { get => new List(Room.Players.Values); } public void OnJoinedRoom() { Room = PhotonNetwork.CurrentRoom; if (PhotonNetwork.IsMasterClient) OnCreatedRoom(); foreach (Player player in Players) OnPlayerEnteredRoom(player); int colorIndex = 1; for (int i = 1; i <= 8; i++) { if (IsColorUsed(i, out Player player) && player != PhotonNetwork.LocalPlayer) continue; colorIndex = i; break; } PhotonNetwork.LocalPlayer.SetCustomProperties(new Hashtable() { ["IsReady"] = false, ["ColorIndex"] = colorIndex }); } private bool TryGetColor(Player p, out int index) { bool success = p.CustomProperties.TryGetValue("ColorIndex", out object objIndex); if (success) index = (int)objIndex; else index = 0; return success; } private bool TryGetReady(Player p, out bool ready) { bool success = p.CustomProperties.TryGetValue("IsReady", out object objReady); if (success) ready = (bool)objReady; else ready = false; return success; } public void OnCreatedRoom() { } public void Clear() { Debug.Log("Clearing player slots"); foreach (PlayerSlot playerSlot in playerSlots) playerSlot.Player = null; } public void OnPlayerEnteredRoom(Player player) { if (playerSlots.Exists(s => s.Player == player)) return; EmptySlots[0].Player = player; } public void OnPlayerLeftRoom(Player player) { PlayerSlot slot = ActiveSlots.Find(s => s.Player == player); if (slot != null) { slot.Player = null; PlayerColorsUpdate(); } } public void OnMasterClientSwitched(Player newMaster) { } public void OnPlayerPropertiesUpdate(Player player, Hashtable props) { PlayerSlot slot = ActiveSlots.Find(s => s.Player == player); if (slot != null) { slot.OnPropertiesUpdate(props); PlayerColorsUpdate(); } } private void PlayerColorsUpdate() { List playerColors = new List(colorSelector.GetComponentsInChildren()); foreach (PlayerColor playerColor in playerColors) { if (IsColorUsed(playerColor.colorIndex, out Player player)) { if (player == PhotonNetwork.LocalPlayer && !playerColor.IsSelected) { playerColor.Select(); } else { playerColor.Forbid(); } } else { playerColor.Allow(); } } } public void RequestSetPlayerColor(int colorIndex) { pv.RPC("RpcRequestSetPlayerColor", RpcTarget.MasterClient, PhotonNetwork.LocalPlayer.ActorNumber, colorIndex); } [PunRPC] //Called on master client private void RpcRequestSetPlayerColor(int actorNumber, int colorIndex) { if (IsColorUsed(colorIndex)) return; PlayerSlot slot = ActiveSlots.Find(s => s.Player.ActorNumber == actorNumber); if (slot != null) { slot.Player.SetCustomProperties(new Hashtable() { ["ColorIndex"] = colorIndex }); } } private bool IsColorUsed(int colorIndex) { return Players.Exists(p => TryGetColor(p, out int index) && index == colorIndex); } private bool IsColorUsed(int colorIndex, out Player player) { if (IsColorUsed(colorIndex)) { player = Players.Find(p => TryGetColor(p, out int index) && index == colorIndex); return true; } else { player = null; return false; } } public bool IsEveryoneReady() { foreach (PlayerSlot playerSlot in playerSlots) if (!playerSlot.IsReady && !playerSlot.IsEmpty) return false; return true; } private PhotonView pv; public static PlayerSlotManager Instance { get; set; } private void Awake() { Instance = this; pv = GetComponent(); } }