using System.Collections; using System.Collections.Generic; using Unity.Services.Authentication; using Unity.Services.Core; using Unity.Services.Lobbies.Models; using Unity.Services.Lobbies; using UnityEngine; using Unity.Netcode.Transports.UTP; using Unity.Netcode; using Unity.Services.Relay.Models; using Unity.Services.Relay; using Unity.Networking.Transport.Relay; using System; using System.Threading.Tasks; public class ConnectionManager : MonoBehaviour { public static ConnectionManager Instance { get; private set; } private void Awake() { if (Instance == null) Instance = this; } private Lobby hostLobby; private Lobby joinedLobby; private float heartbeatTimer; private string scene; public async void Start() { await UnityServices.InitializeAsync(); AuthenticationService.Instance.SignedIn += () => { Debug.Log("signed in " + AuthenticationService.Instance.PlayerId); GameManager.Instance.Loaded(); }; NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected; NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnected; await AuthenticationService.Instance.SignInAnonymouslyAsync(); } private Action onClientConnected; private Action onClientDisconnected; private void OnClientConnected(ulong cliendID) { onClientConnected?.Invoke(); } private void OnClientDisconnected(ulong cliendID) { onClientDisconnected?.Invoke(); } private Unity.Services.Lobbies.Models.Player GetPlayer() { return new Unity.Services.Lobbies.Models.Player() { Data = new Dictionary { { "PlayerName", new PlayerDataObject(PlayerDataObject.VisibilityOptions.Public, LocalPlayerData.PlayerName) } } }; } private void Update() { HandleLobbyHeartbeat(); } private async void HandleLobbyHeartbeat() { if (hostLobby != null) { heartbeatTimer -= Time.deltaTime; if (heartbeatTimer < 0f) { float heartbeatTimerMax = 10f; heartbeatTimer = heartbeatTimerMax; try { await LobbyService.Instance.SendHeartbeatPingAsync(hostLobby.Id); } catch { } } } } private async Task LeaveLobbyAsync() { try { if (joinedLobby != null) { await LobbyService.Instance.RemovePlayerAsync(joinedLobby.Id, AuthenticationService.Instance.PlayerId); } if (hostLobby != null) { await LobbyService.Instance.DeleteLobbyAsync(hostLobby.Id); hostLobby = null; } return true; } catch (LobbyServiceException ex) { Debug.Log(ex); return false; } } public void Shutdown() { if (NetworkManager.Singleton != null && NetworkManager.Singleton.IsClient) { Debug.Log("Client already running, shutting down the existing client."); NetworkManager.Singleton.Shutdown(); Debug.Log("Yay"); } } public async void JoinLocation(string locationName, Action onJoin) { try { QueryLobbiesOptions queryOptions = new QueryLobbiesOptions { Filters = new List { new QueryFilter(QueryFilter.FieldOptions.Name, locationName, QueryFilter.OpOptions.EQ) } }; QueryResponse response = await LobbyService.Instance.QueryLobbiesAsync(queryOptions); if (response.Results.Count == 0) { Debug.Log("No lobby found. Let's create one!"); Debug.Log("CreateLobbyAndRelay Start"); await CreateLobbyAndRelayAsync(locationName, 20, false); } else { Lobby lobby = response.Results[0]; Debug.Log(lobby.Id); Debug.Log(lobby.LobbyCode); Debug.Log(lobby.Name); await JoinLobbyAndRelayAsync(lobby.Id); } Debug.Log("JoinLocation CanInvoke"); onJoin?.Invoke(); } catch (LobbyServiceException ex) { Debug.Log(ex); } } public async void CreateLobbyAndRelay(string lobbyName, int maxPlayers, bool isPrivate, Action onCreated = null) { await CreateLobbyAndRelayAsync(lobbyName, maxPlayers, isPrivate); onCreated?.Invoke(); } public async void JoinLobbyAndRelay(string lobbyId, Action onJoined = null) { await JoinLobbyAndRelayAsync(lobbyId); onJoined?.Invoke(); } public async void JoinRelay(string joinCode, Action onJoined = null) { await JoinRelayAsync(joinCode); onJoined?.Invoke(); } private async Task CreateLobbyAndRelayAsync(string lobbyName, int maxPlayers, bool isPrivate) { try { await LeaveLobbyAsync(); string joinCode = await CreateRelayAsync(maxPlayers); CreateLobbyOptions options = new CreateLobbyOptions { IsPrivate = isPrivate, Player = GetPlayer(), Data = new Dictionary { { "joinCode", new DataObject(DataObject.VisibilityOptions.Public, joinCode) } } }; hostLobby = await LobbyService.Instance.CreateLobbyAsync(lobbyName, maxPlayers, options); joinedLobby = hostLobby; return true; } catch (LobbyServiceException ex) { Debug.Log(ex); return false; } } private async Task JoinLobbyAndRelayAsync(string lobbyId) { try { await LeaveLobbyAsync(); JoinLobbyByIdOptions options = new JoinLobbyByIdOptions { Player = GetPlayer() }; Lobby lobby = await LobbyService.Instance.GetLobbyAsync(lobbyId); //joinedLobby = await LobbyService.Instance.JoinLobbyByIdAsync(lobbyId, options); await JoinRelayAsync(lobby.Data["joinCode"].Value); return true; } catch (LobbyServiceException ex) { Debug.Log(ex); return false; } } //==============RELAY============== private async Task CreateRelayAsync(int maxPlayers) { try { ChatManager.Instance.ClearUsers(); ChatManager.Instance.ClearLocationChat(); Shutdown(); Allocation allocation = await RelayService.Instance.CreateAllocationAsync(maxPlayers); string joinCode = await RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId); Debug.Log(joinCode); RelayServerData relayServerData = new RelayServerData(allocation, "dtls"); NetworkManager.Singleton.GetComponent().SetRelayServerData(relayServerData); NetworkManager.Singleton.StartHost(); return joinCode; } catch (RelayServiceException ex) { Debug.Log(ex); return ""; } } private async Task JoinRelayAsync(string joinCode) { try { ChatManager.Instance.ClearUsers(); ChatManager.Instance.ClearLocationChat(); Shutdown(); JoinAllocation joinAllocation = await RelayService.Instance.JoinAllocationAsync(joinCode); RelayServerData relayServerData = new RelayServerData(joinAllocation, "dtls"); NetworkManager.Singleton.GetComponent().SetRelayServerData(relayServerData); NetworkManager.Singleton.StartClient(); return true; } catch (RelayServiceException ex) { Debug.Log(ex); return false; } } private async void ListLobbies() { QueryLobbiesOptions options = new QueryLobbiesOptions() { Count = 25, Filters = new List() { new QueryFilter(QueryFilter.FieldOptions.AvailableSlots, "0", QueryFilter.OpOptions.GT) }, Order = new List() { new QueryOrder(false, QueryOrder.FieldOptions.Created) } }; QueryResponse lobbies = await Lobbies.Instance.QueryLobbiesAsync(); foreach (var lobbie in lobbies.Results) { Debug.Log($"{lobbie.Name} (${lobbie.Id})"); } } }