You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

314 lines
8.8 KiB

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<string, PlayerDataObject>
{
{ "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<bool> 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<QueryFilter>
{
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<bool> 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<string, DataObject>
{
{ "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<bool> 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<string> 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<UnityTransport>().SetRelayServerData(relayServerData);
NetworkManager.Singleton.StartHost();
return joinCode;
}
catch (RelayServiceException ex)
{
Debug.Log(ex);
return "";
}
}
private async Task<bool> 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<UnityTransport>().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<QueryFilter>()
{
new QueryFilter(QueryFilter.FieldOptions.AvailableSlots, "0", QueryFilter.OpOptions.GT)
},
Order = new List<QueryOrder>()
{
new QueryOrder(false, QueryOrder.FieldOptions.Created)
}
};
QueryResponse lobbies = await Lobbies.Instance.QueryLobbiesAsync();
foreach (var lobbie in lobbies.Results)
{
Debug.Log($"{lobbie.Name} (${lobbie.Id})");
}
}
}