using System; using System.Collections.Generic; using ExitGames.Client.Photon; using UnityEngine; using Hashtable = ExitGames.Client.Photon.Hashtable; /// /// Implements teams in a room/game with help of player properties. Access them by PhotonPlayer.GetTeam extension. /// /// /// Teams are defined by enum Team. Change this to get more / different teams. /// There are no rules when / if you can join a team. You could add this in JoinTeam or something. /// public class PunTeams : MonoBehaviour { /// Enum defining the teams available. First team should be neutral (it's the default value any field of this enum gets). public enum Team : byte {none, red, blue}; /// The main list of teams with their player-lists. Automatically kept up to date. /// Note that this is static. Can be accessed by PunTeam.PlayersPerTeam. You should not modify this. public static Dictionary> PlayersPerTeam; /// Defines the player custom property name to use for team affinity of "this" player. public const string TeamPlayerProp = "team"; #region Events by Unity and Photon public void Start() { PlayersPerTeam = new Dictionary>(); Array enumVals = Enum.GetValues(typeof (Team)); foreach (var enumVal in enumVals) { PlayersPerTeam[(Team)enumVal] = new List(); } } public void OnDisable() { PlayersPerTeam = new Dictionary>(); } /// Needed to update the team lists when joining a room. /// Called by PUN. See enum PhotonNetworkingMessage for an explanation. public void OnJoinedRoom() { this.UpdateTeams(); } public void OnLeftRoom() { Start(); } /// Refreshes the team lists. It could be a non-team related property change, too. /// Called by PUN. See enum PhotonNetworkingMessage for an explanation. public void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps) { this.UpdateTeams(); } public void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer) { this.UpdateTeams(); } public void OnPhotonPlayerConnected(PhotonPlayer newPlayer) { this.UpdateTeams(); } #endregion public void UpdateTeams() { Array enumVals = Enum.GetValues(typeof(Team)); foreach (var enumVal in enumVals) { PlayersPerTeam[(Team)enumVal].Clear(); } for (int i = 0; i < PhotonNetwork.playerList.Length; i++) { PhotonPlayer player = PhotonNetwork.playerList[i]; Team playerTeam = player.GetTeam(); PlayersPerTeam[playerTeam].Add(player); } } } /// Extension used for PunTeams and PhotonPlayer class. Wraps access to the player's custom property. public static class TeamExtensions { /// Extension for PhotonPlayer class to wrap up access to the player's custom property. /// PunTeam.Team.none if no team was found (yet). public static PunTeams.Team GetTeam(this PhotonPlayer player) { object teamId; if (player.CustomProperties.TryGetValue(PunTeams.TeamPlayerProp, out teamId)) { return (PunTeams.Team)teamId; } return PunTeams.Team.none; } /// Switch that player's team to the one you assign. /// Internally checks if this player is in that team already or not. Only team switches are actually sent. /// /// public static void SetTeam(this PhotonPlayer player, PunTeams.Team team) { if (!PhotonNetwork.connectedAndReady) { Debug.LogWarning("JoinTeam was called in state: " + PhotonNetwork.connectionStateDetailed + ". Not connectedAndReady."); return; } PunTeams.Team currentTeam = player.GetTeam(); if (currentTeam != team) { player.SetCustomProperties(new Hashtable() {{PunTeams.TeamPlayerProp, (byte) team}}); } } }