214 lines
6.7 KiB
C#
214 lines
6.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using Unity.Netcode;
|
|
using Unity.Netcode.Transports.UTP;
|
|
using Unity.Services.Authentication;
|
|
using Unity.Services.Core;
|
|
using Unity.Services.Lobbies;
|
|
using Unity.Services.Lobbies.Models;
|
|
using Unity.Services.Relay;
|
|
using Unity.Services.Relay.Models;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using Random = UnityEngine.Random;
|
|
|
|
public class KitchenGameLobby : MonoBehaviour {
|
|
public Lobby JoinedLobby { get; private set; }
|
|
public static KitchenGameLobby Instance { get; private set; }
|
|
private float heartbeatTimer;
|
|
private const float heartbeatTimerMax = 15f;
|
|
|
|
public event EventHandler OnCreateLobbyStarted;
|
|
public event EventHandler OnCreateLobbyFailed;
|
|
public event EventHandler OnJoinStarted;
|
|
public event EventHandler OnQuickJoinFailed;
|
|
public event EventHandler OnJoinFailed;
|
|
public event EventHandler<LobbyListChangedEventArgs> OnLobbyListChanged;
|
|
|
|
public class LobbyListChangedEventArgs : EventArgs {
|
|
public List<Lobby> LobbyList;
|
|
}
|
|
|
|
private void Awake() {
|
|
Instance = this;
|
|
DontDestroyOnLoad(gameObject);
|
|
InitializeUnityAuthentitcation();
|
|
}
|
|
|
|
private void Update() {
|
|
HandleHeartbeat();
|
|
HandlePeriodicListLobbies();
|
|
}
|
|
|
|
private float listLobbiesTimer;
|
|
private const float listLobbiesTimerMax = 3f;
|
|
|
|
private void HandlePeriodicListLobbies() {
|
|
if (JoinedLobby == null && AuthenticationService.Instance.IsSignedIn && SceneManager.GetActiveScene().name == Loader.Scene.LobbyScene.ToString()) {
|
|
listLobbiesTimer -= Time.deltaTime;
|
|
if (listLobbiesTimer <= 0f) {
|
|
listLobbiesTimer = listLobbiesTimerMax;
|
|
ListLobbies();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void HandleHeartbeat() {
|
|
if (IsLobbyHost()) {
|
|
heartbeatTimer -= Time.deltaTime;
|
|
if (heartbeatTimer <= 0f) {
|
|
heartbeatTimer = heartbeatTimerMax;
|
|
LobbyService.Instance.SendHeartbeatPingAsync(JoinedLobby.Id);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool IsLobbyHost() => JoinedLobby != null && JoinedLobby.HostId == AuthenticationService.Instance.PlayerId;
|
|
|
|
private async void ListLobbies() {
|
|
try {
|
|
QueryLobbiesOptions queryLobbiesOptions = new() { Filters = new() { new(QueryFilter.FieldOptions.AvailableSlots, "0", QueryFilter.OpOptions.GT) } };
|
|
QueryResponse queryResponse = await LobbyService.Instance.QueryLobbiesAsync(queryLobbiesOptions);
|
|
OnLobbyListChanged?.Invoke(this, new() { LobbyList = queryResponse.Results });
|
|
}
|
|
catch (LobbyServiceException e) {
|
|
Debug.Log(e);
|
|
}
|
|
}
|
|
|
|
private async void InitializeUnityAuthentitcation() {
|
|
if (UnityServices.State != ServicesInitializationState.Initialized) await UnityServices.InitializeAsync();
|
|
InitializationOptions initializationOptions = new();
|
|
// initializationOptions.SetProfile(Random.Range(0, 10000).ToString());
|
|
await AuthenticationService.Instance.SignInAnonymouslyAsync();
|
|
}
|
|
|
|
private const string keyRelayJoinCode = "RelayJoinCode";
|
|
|
|
public async void CreateLobby(string lobbyName, bool isPrivate) {
|
|
OnCreateLobbyStarted?.Invoke(this, EventArgs.Empty);
|
|
try {
|
|
JoinedLobby = await LobbyService.Instance.CreateLobbyAsync(lobbyName, KitchenGameMultiplayer.MaxPlayerAmount, new() { IsPrivate = isPrivate });
|
|
|
|
Allocation allocation = await AllocateRelay();
|
|
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(new(allocation, "dtls"));
|
|
string relayJoinCode = await GetRelayJoinCode(allocation);
|
|
await LobbyService.Instance.UpdateLobbyAsync(JoinedLobby.Id, new() { Data = new() { { keyRelayJoinCode, new(DataObject.VisibilityOptions.Member, relayJoinCode) } } });
|
|
|
|
KitchenGameMultiplayer.Instance.StartHost();
|
|
Loader.LoadNetwork(Loader.Scene.CharacterSelectScene);
|
|
}
|
|
catch (LobbyServiceException e) {
|
|
Debug.Log(e);
|
|
OnCreateLobbyFailed?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
private async Task<Allocation> AllocateRelay() {
|
|
try {
|
|
return await RelayService.Instance.CreateAllocationAsync(KitchenGameMultiplayer.MaxPlayerAmount - 1);
|
|
}
|
|
catch (RelayServiceException e) {
|
|
Debug.Log(e);
|
|
return default;
|
|
}
|
|
}
|
|
|
|
private async Task<string> GetRelayJoinCode(Allocation allocation) {
|
|
try {
|
|
return await RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId);
|
|
}
|
|
catch (RelayServiceException e) {
|
|
Debug.Log(e);
|
|
return default;
|
|
}
|
|
}
|
|
|
|
private async Task<JoinAllocation> JoinRelay(string joinCode) {
|
|
try {
|
|
return await RelayService.Instance.JoinAllocationAsync(joinCode);
|
|
}
|
|
catch (RelayServiceException e) {
|
|
Debug.Log(e);
|
|
return default;
|
|
}
|
|
}
|
|
|
|
public async void QuickJoin() {
|
|
OnJoinStarted?.Invoke(this, EventArgs.Empty);
|
|
try {
|
|
JoinedLobby = await LobbyService.Instance.QuickJoinLobbyAsync();
|
|
JoinAllocation joinAllocation = await JoinRelay(JoinedLobby.Data[keyRelayJoinCode].Value);
|
|
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(new(joinAllocation, "dtls"));
|
|
KitchenGameMultiplayer.Instance.StartClient();
|
|
}
|
|
catch (LobbyServiceException e) {
|
|
Debug.Log(e);
|
|
OnQuickJoinFailed?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
public async void DeleteLobby() {
|
|
if (JoinedLobby != null) {
|
|
try {
|
|
await LobbyService.Instance.DeleteLobbyAsync(JoinedLobby.Id);
|
|
JoinedLobby = null;
|
|
}
|
|
catch (LobbyServiceException e) {
|
|
Debug.Log(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public async void LeaveLobby() {
|
|
if (JoinedLobby != null) {
|
|
try {
|
|
await LobbyService.Instance.RemovePlayerAsync(JoinedLobby.Id, AuthenticationService.Instance.PlayerId);
|
|
JoinedLobby = null;
|
|
}
|
|
catch (LobbyServiceException e) {
|
|
Debug.Log(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public async void KickPlayer(string playerId) {
|
|
if (IsLobbyHost()) {
|
|
try {
|
|
await LobbyService.Instance.RemovePlayerAsync(JoinedLobby.Id, playerId);
|
|
}
|
|
catch (LobbyServiceException e) {
|
|
Debug.Log(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public async void JoinWithCode(string lobbyCode) {
|
|
OnJoinStarted?.Invoke(this, EventArgs.Empty);
|
|
try {
|
|
JoinedLobby = await LobbyService.Instance.JoinLobbyByCodeAsync(lobbyCode);
|
|
JoinAllocation joinAllocation = await JoinRelay(JoinedLobby.Data[keyRelayJoinCode].Value);
|
|
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(new(joinAllocation, "dtls"));
|
|
KitchenGameMultiplayer.Instance.StartClient();
|
|
}
|
|
catch (LobbyServiceException e) {
|
|
Debug.Log(e);
|
|
OnJoinFailed?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
public async void JoinWithId(string lobbyId) {
|
|
OnJoinStarted?.Invoke(this, EventArgs.Empty);
|
|
try {
|
|
JoinedLobby = await LobbyService.Instance.JoinLobbyByIdAsync(lobbyId);
|
|
JoinAllocation joinAllocation = await JoinRelay(JoinedLobby.Data[keyRelayJoinCode].Value);
|
|
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(new(joinAllocation, "dtls"));
|
|
KitchenGameMultiplayer.Instance.StartClient();
|
|
}
|
|
catch (LobbyServiceException e) {
|
|
Debug.Log(e);
|
|
OnJoinFailed?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
} |