using System; using System.Collections.Generic; using System.Text; using UnityEngine; using UnityEngine.Serialization; namespace LobbyRelaySample { [Flags] // Some UI elements will want to specify multiple states in which to be active, so this is Flags. public enum LobbyState { Lobby = 1, CountDown = 2, InGame = 4 } public enum LobbyColor { None = 0, Orange = 1, Green = 2, Blue = 3 } /// /// A local wrapper around a lobby's remote data, with additional functionality for providing that data to UI elements and tracking local player objects. /// (The way that the Lobby service handles its data doesn't necessarily match our needs, so we need to map from that to this LocalLobby for use in the sample code.) /// [System.Serializable] public class LocalLobby : Observed { public bool CanSetChanged = true; public Action> onUserListChanged; Dictionary m_LocalPlayers = new Dictionary(); public Dictionary LocalPlayers => m_LocalPlayers; #region LocalLobbyData ServerAddress m_RelayServer; public LocalLobby() { LastUpdated.Value = DateTime.Now.ToFileTimeUtc(); LobbyID.onChanged = (s) => { SetValueChanged(); }; LobbyCode.onChanged = (s) => { SetValueChanged(); }; RelayCode.onChanged = (s) => { SetValueChanged(); }; RelayNGOCode.onChanged = (s) => { SetValueChanged(); }; RelayServer.onChanged = (s) => { SetValueChanged(); }; LobbyName.onChanged = (s) => { SetValueChanged(); }; LocalLobbyState.onChanged = (s) => { SetValueChanged(); }; Private.onChanged = (s) => { SetValueChanged(); }; AvailableSlots.onChanged = (s) => { SetValueChanged(); }; MaxPlayerCount.onChanged = (s) => { SetValueChanged(); }; LocalLobbyColor.onChanged = (s) => { SetValueChanged(); }; LastUpdated.onChanged = (s) => { SetValueChanged(); }; } /// Used only for visual output of the Relay connection info. The obfuscated Relay server IP is obtained during allocation in the RelayUtpSetup. #endregion public CallbackValue LobbyID = new CallbackValue(); public CallbackValue LobbyCode = new CallbackValue(); public CallbackValue RelayCode = new CallbackValue(); public CallbackValue RelayNGOCode = new CallbackValue(); public CallbackValue RelayServer = new CallbackValue(); public CallbackValue LobbyName = new CallbackValue(); public CallbackValue LocalLobbyState = new CallbackValue(); public CallbackValue Private = new CallbackValue(); public CallbackValue AvailableSlots = new CallbackValue(); public CallbackValue MaxPlayerCount = new CallbackValue(); public CallbackValue LocalLobbyColor = new CallbackValue(); public CallbackValue LastUpdated = new CallbackValue(); public int PlayerCount => m_LocalPlayers.Count; public void ResetLobby() { m_LocalPlayers.Clear(); LobbyName.Value = ""; LobbyID.Value = ""; LobbyCode.Value = ""; Private.Value = false; LocalLobbyColor.Value = LobbyRelaySample.LobbyColor.None; AvailableSlots.Value = 4; MaxPlayerCount.Value = 4; } /// /// A locking mechanism for registering when something has looked at the Lobby to see if anything has changed /// /// public bool IsLobbyChanged() { bool isChanged = m_ValuesChanged; m_ValuesChanged = false; return isChanged; } void SetValueChanged() { if(CanSetChanged) m_ValuesChanged = true; } bool m_ValuesChanged; public void AddPlayer(LocalPlayer user) { if (m_LocalPlayers.ContainsKey(user.ID.Value)) { Debug.LogError($"Cant add player {user.DisplayName}({user.ID}) to lobby: {LobbyID} twice"); return; } Debug.Log($"Adding User: {user.DisplayName} - {user.ID}"); m_LocalPlayers.Add(user.ID.Value, user); onUserListChanged?.Invoke(m_LocalPlayers); } public void RemovePlayer(LocalPlayer user) { DoRemoveUser(user); onUserListChanged?.Invoke(m_LocalPlayers); } void DoRemoveUser(LocalPlayer user) { if (!m_LocalPlayers.ContainsKey(user.ID.Value)) { Debug.LogWarning($"Player {user.DisplayName}({user.ID}) does not exist in lobby: {LobbyID}"); return; } m_LocalPlayers.Remove(user.ID.Value); } public override string ToString() { StringBuilder sb = new StringBuilder("Lobby : "); sb.AppendLine(LobbyName.Value); sb.Append("ID: "); sb.AppendLine(LobbyID.Value); sb.Append("Code: "); sb.AppendLine(LobbyCode.Value); sb.Append("Private: "); sb.AppendLine(Private.Value.ToString()); sb.Append("AvailableSlots: "); sb.AppendLine(AvailableSlots.Value.ToString()); sb.Append("Max Players: "); sb.AppendLine(MaxPlayerCount.Value.ToString()); sb.Append("LocalLobbyState: "); sb.AppendLine(LocalLobbyState.Value.ToString()); sb.Append("Lobby LocalLobbyState Last Edit: "); sb.AppendLine(new DateTime(LastUpdated.Value).ToString()); sb.Append("LocalLobbyColor: "); sb.AppendLine(LocalLobbyColor.Value.ToString()); sb.Append("RelayCode: "); sb.AppendLine(RelayCode.Value); sb.Append("RelayNGO: "); sb.AppendLine(RelayNGOCode.Value); return sb.ToString(); } // This ends up being called from the lobby list when we get data about a lobby without having joined it yet. public override void CopyObserved(LocalLobby oldObserved) { // CopyObserved(oldObserved.Data, oldObserved.m_LocalPlayers); } } }