LobbyMainPanel.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. using ExitGames.Client.Photon;
  2. using Photon.Realtime;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.UI;
  6. namespace Photon.Pun.Demo.Asteroids
  7. {
  8. public class LobbyMainPanel : MonoBehaviourPunCallbacks
  9. {
  10. [Header("Login Panel")]
  11. public GameObject LoginPanel;
  12. public InputField PlayerNameInput;
  13. [Header("Selection Panel")]
  14. public GameObject SelectionPanel;
  15. [Header("Create Room Panel")]
  16. public GameObject CreateRoomPanel;
  17. public InputField RoomNameInputField;
  18. public InputField MaxPlayersInputField;
  19. [Header("Join Random Room Panel")]
  20. public GameObject JoinRandomRoomPanel;
  21. [Header("Room List Panel")]
  22. public GameObject RoomListPanel;
  23. public GameObject RoomListContent;
  24. public GameObject RoomListEntryPrefab;
  25. [Header("Inside Room Panel")]
  26. public GameObject InsideRoomPanel;
  27. public Button StartGameButton;
  28. public GameObject PlayerListEntryPrefab;
  29. private Dictionary<string, RoomInfo> cachedRoomList;
  30. private Dictionary<string, GameObject> roomListEntries;
  31. private Dictionary<int, GameObject> playerListEntries;
  32. #region UNITY
  33. public void Awake()
  34. {
  35. PhotonNetwork.AutomaticallySyncScene = true;
  36. cachedRoomList = new Dictionary<string, RoomInfo>();
  37. roomListEntries = new Dictionary<string, GameObject>();
  38. PlayerNameInput.text = "Player " + Random.Range(1000, 10000);
  39. }
  40. #endregion
  41. #region PUN CALLBACKS
  42. public override void OnConnectedToMaster()
  43. {
  44. this.SetActivePanel(SelectionPanel.name);
  45. }
  46. public override void OnRoomListUpdate(List<RoomInfo> roomList)
  47. {
  48. ClearRoomListView();
  49. UpdateCachedRoomList(roomList);
  50. UpdateRoomListView();
  51. }
  52. public override void OnJoinedLobby()
  53. {
  54. // whenever this joins a new lobby, clear any previous room lists
  55. cachedRoomList.Clear();
  56. ClearRoomListView();
  57. }
  58. // note: when a client joins / creates a room, OnLeftLobby does not get called, even if the client was in a lobby before
  59. public override void OnLeftLobby()
  60. {
  61. cachedRoomList.Clear();
  62. ClearRoomListView();
  63. }
  64. public override void OnCreateRoomFailed(short returnCode, string message)
  65. {
  66. SetActivePanel(SelectionPanel.name);
  67. }
  68. public override void OnJoinRoomFailed(short returnCode, string message)
  69. {
  70. SetActivePanel(SelectionPanel.name);
  71. }
  72. public override void OnJoinRandomFailed(short returnCode, string message)
  73. {
  74. string roomName = "Room " + Random.Range(1000, 10000);
  75. RoomOptions options = new RoomOptions {MaxPlayers = 8};
  76. PhotonNetwork.CreateRoom(roomName, options, null);
  77. }
  78. public override void OnJoinedRoom()
  79. {
  80. // joining (or entering) a room invalidates any cached lobby room list (even if LeaveLobby was not called due to just joining a room)
  81. cachedRoomList.Clear();
  82. SetActivePanel(InsideRoomPanel.name);
  83. if (playerListEntries == null)
  84. {
  85. playerListEntries = new Dictionary<int, GameObject>();
  86. }
  87. foreach (Player p in PhotonNetwork.PlayerList)
  88. {
  89. GameObject entry = Instantiate(PlayerListEntryPrefab);
  90. entry.transform.SetParent(InsideRoomPanel.transform);
  91. entry.transform.localScale = Vector3.one;
  92. entry.GetComponent<PlayerListEntry>().Initialize(p.ActorNumber, p.NickName);
  93. object isPlayerReady;
  94. if (p.CustomProperties.TryGetValue(AsteroidsGame.PLAYER_READY, out isPlayerReady))
  95. {
  96. entry.GetComponent<PlayerListEntry>().SetPlayerReady((bool) isPlayerReady);
  97. }
  98. playerListEntries.Add(p.ActorNumber, entry);
  99. }
  100. StartGameButton.gameObject.SetActive(CheckPlayersReady());
  101. Hashtable props = new Hashtable
  102. {
  103. {AsteroidsGame.PLAYER_LOADED_LEVEL, false}
  104. };
  105. PhotonNetwork.LocalPlayer.SetCustomProperties(props);
  106. }
  107. public override void OnLeftRoom()
  108. {
  109. SetActivePanel(SelectionPanel.name);
  110. foreach (GameObject entry in playerListEntries.Values)
  111. {
  112. Destroy(entry.gameObject);
  113. }
  114. playerListEntries.Clear();
  115. playerListEntries = null;
  116. }
  117. public override void OnPlayerEnteredRoom(Player newPlayer)
  118. {
  119. GameObject entry = Instantiate(PlayerListEntryPrefab);
  120. entry.transform.SetParent(InsideRoomPanel.transform);
  121. entry.transform.localScale = Vector3.one;
  122. entry.GetComponent<PlayerListEntry>().Initialize(newPlayer.ActorNumber, newPlayer.NickName);
  123. playerListEntries.Add(newPlayer.ActorNumber, entry);
  124. StartGameButton.gameObject.SetActive(CheckPlayersReady());
  125. }
  126. public override void OnPlayerLeftRoom(Player otherPlayer)
  127. {
  128. Destroy(playerListEntries[otherPlayer.ActorNumber].gameObject);
  129. playerListEntries.Remove(otherPlayer.ActorNumber);
  130. StartGameButton.gameObject.SetActive(CheckPlayersReady());
  131. }
  132. public override void OnMasterClientSwitched(Player newMasterClient)
  133. {
  134. if (PhotonNetwork.LocalPlayer.ActorNumber == newMasterClient.ActorNumber)
  135. {
  136. StartGameButton.gameObject.SetActive(CheckPlayersReady());
  137. }
  138. }
  139. public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
  140. {
  141. if (playerListEntries == null)
  142. {
  143. playerListEntries = new Dictionary<int, GameObject>();
  144. }
  145. GameObject entry;
  146. if (playerListEntries.TryGetValue(targetPlayer.ActorNumber, out entry))
  147. {
  148. object isPlayerReady;
  149. if (changedProps.TryGetValue(AsteroidsGame.PLAYER_READY, out isPlayerReady))
  150. {
  151. entry.GetComponent<PlayerListEntry>().SetPlayerReady((bool) isPlayerReady);
  152. }
  153. }
  154. StartGameButton.gameObject.SetActive(CheckPlayersReady());
  155. }
  156. #endregion
  157. #region UI CALLBACKS
  158. public void OnBackButtonClicked()
  159. {
  160. if (PhotonNetwork.InLobby)
  161. {
  162. PhotonNetwork.LeaveLobby();
  163. }
  164. SetActivePanel(SelectionPanel.name);
  165. }
  166. public void OnCreateRoomButtonClicked()
  167. {
  168. string roomName = RoomNameInputField.text;
  169. roomName = (roomName.Equals(string.Empty)) ? "Room " + Random.Range(1000, 10000) : roomName;
  170. byte maxPlayers;
  171. byte.TryParse(MaxPlayersInputField.text, out maxPlayers);
  172. maxPlayers = (byte) Mathf.Clamp(maxPlayers, 2, 8);
  173. RoomOptions options = new RoomOptions {MaxPlayers = maxPlayers, PlayerTtl = 10000 };
  174. PhotonNetwork.CreateRoom(roomName, options, null);
  175. }
  176. public void OnJoinRandomRoomButtonClicked()
  177. {
  178. SetActivePanel(JoinRandomRoomPanel.name);
  179. PhotonNetwork.JoinRandomRoom();
  180. }
  181. public void OnLeaveGameButtonClicked()
  182. {
  183. PhotonNetwork.LeaveRoom();
  184. }
  185. public void OnLoginButtonClicked()
  186. {
  187. string playerName = PlayerNameInput.text;
  188. if (!playerName.Equals(""))
  189. {
  190. PhotonNetwork.LocalPlayer.NickName = playerName;
  191. PhotonNetwork.ConnectUsingSettings();
  192. }
  193. else
  194. {
  195. Debug.LogError("Player Name is invalid.");
  196. }
  197. }
  198. public void OnRoomListButtonClicked()
  199. {
  200. if (!PhotonNetwork.InLobby)
  201. {
  202. PhotonNetwork.JoinLobby();
  203. }
  204. SetActivePanel(RoomListPanel.name);
  205. }
  206. public void OnStartGameButtonClicked()
  207. {
  208. PhotonNetwork.CurrentRoom.IsOpen = false;
  209. PhotonNetwork.CurrentRoom.IsVisible = false;
  210. PhotonNetwork.LoadLevel("DemoAsteroids-GameScene");
  211. }
  212. #endregion
  213. private bool CheckPlayersReady()
  214. {
  215. if (!PhotonNetwork.IsMasterClient)
  216. {
  217. return false;
  218. }
  219. foreach (Player p in PhotonNetwork.PlayerList)
  220. {
  221. object isPlayerReady;
  222. if (p.CustomProperties.TryGetValue(AsteroidsGame.PLAYER_READY, out isPlayerReady))
  223. {
  224. if (!(bool) isPlayerReady)
  225. {
  226. return false;
  227. }
  228. }
  229. else
  230. {
  231. return false;
  232. }
  233. }
  234. return true;
  235. }
  236. private void ClearRoomListView()
  237. {
  238. foreach (GameObject entry in roomListEntries.Values)
  239. {
  240. Destroy(entry.gameObject);
  241. }
  242. roomListEntries.Clear();
  243. }
  244. public void LocalPlayerPropertiesUpdated()
  245. {
  246. StartGameButton.gameObject.SetActive(CheckPlayersReady());
  247. }
  248. private void SetActivePanel(string activePanel)
  249. {
  250. LoginPanel.SetActive(activePanel.Equals(LoginPanel.name));
  251. SelectionPanel.SetActive(activePanel.Equals(SelectionPanel.name));
  252. CreateRoomPanel.SetActive(activePanel.Equals(CreateRoomPanel.name));
  253. JoinRandomRoomPanel.SetActive(activePanel.Equals(JoinRandomRoomPanel.name));
  254. RoomListPanel.SetActive(activePanel.Equals(RoomListPanel.name)); // UI should call OnRoomListButtonClicked() to activate this
  255. InsideRoomPanel.SetActive(activePanel.Equals(InsideRoomPanel.name));
  256. }
  257. private void UpdateCachedRoomList(List<RoomInfo> roomList)
  258. {
  259. foreach (RoomInfo info in roomList)
  260. {
  261. // Remove room from cached room list if it got closed, became invisible or was marked as removed
  262. if (!info.IsOpen || !info.IsVisible || info.RemovedFromList)
  263. {
  264. if (cachedRoomList.ContainsKey(info.Name))
  265. {
  266. cachedRoomList.Remove(info.Name);
  267. }
  268. continue;
  269. }
  270. // Update cached room info
  271. if (cachedRoomList.ContainsKey(info.Name))
  272. {
  273. cachedRoomList[info.Name] = info;
  274. }
  275. // Add new room info to cache
  276. else
  277. {
  278. cachedRoomList.Add(info.Name, info);
  279. }
  280. }
  281. }
  282. private void UpdateRoomListView()
  283. {
  284. foreach (RoomInfo info in cachedRoomList.Values)
  285. {
  286. GameObject entry = Instantiate(RoomListEntryPrefab);
  287. entry.transform.SetParent(RoomListContent.transform);
  288. entry.transform.localScale = Vector3.one;
  289. entry.GetComponent<RoomListEntry>().Initialize(info.Name, (byte)info.PlayerCount, (byte)info.MaxPlayers);
  290. roomListEntries.Add(info.Name, entry);
  291. }
  292. }
  293. }
  294. }