Added game state and network client
This commit is contained in:
202
Assets/Scripts/Network/Network.cs
Normal file
202
Assets/Scripts/Network/Network.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using PashaBibko.Pacore.Attributes;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Network
|
||||
{
|
||||
public enum TransportType
|
||||
{
|
||||
UnityRelay,
|
||||
Localhost,
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
public interface INetworkTransport
|
||||
{
|
||||
public IEnumerator Join(string code, Action callback);
|
||||
public IEnumerator Host(Action callback);
|
||||
}
|
||||
|
||||
public class Network : MonoBehaviour
|
||||
{
|
||||
private static Network sInstance;
|
||||
|
||||
[Header("Transports")]
|
||||
[SerializeField] private GameObject LocalHostTransport;
|
||||
[SerializeField] private GameObject UnityRelayTransport;
|
||||
|
||||
[Header("View only")] [SerializeField, InspectorReadOnly]
|
||||
private TransportType InternalCurrentTransport = TransportType.None;
|
||||
|
||||
public static TransportType CurrentTransport
|
||||
{
|
||||
get => sInstance?.InternalCurrentTransport ?? TransportType.None;
|
||||
set => sInstance?.StartCoroutine(sInstance.ChangeTransport(value));
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[Header("Editor Only")]
|
||||
[SerializeField] private string GameJoinCode;
|
||||
#endif // UNITY_EDITOR
|
||||
|
||||
private static INetworkTransport sConnectionManager;
|
||||
|
||||
private GameObject mCurrentChildTransport;
|
||||
private bool mSafeToConnect = true;
|
||||
|
||||
public static UnityTransport CurrentTransportComponent
|
||||
{
|
||||
get
|
||||
{
|
||||
UnityTransport component = null;
|
||||
sInstance?.mCurrentChildTransport?.TryGetComponent(out component);
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Stops overlapping instances
|
||||
if (sInstance is not null)
|
||||
{
|
||||
Debug.LogError($"Multiple of [{nameof(Network)}] cannot exist.");
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
private IEnumerator HostInternal()
|
||||
{
|
||||
// Waits for it to be safe to connect, quits after 5 seconds
|
||||
float timeout = 0f;
|
||||
while (!mSafeToConnect)
|
||||
{
|
||||
if (timeout > 5f)
|
||||
{
|
||||
Debug.LogError("Host timed out");
|
||||
yield break;
|
||||
}
|
||||
|
||||
timeout += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Then actually hosts the lobby
|
||||
yield return sConnectionManager.Host(() =>
|
||||
{
|
||||
NetworkManager.Singleton.SceneManager.LoadScene("LobbyScene", LoadSceneMode.Single);
|
||||
Debug.Log("Hosted");
|
||||
});
|
||||
}
|
||||
|
||||
public static void Host()
|
||||
{
|
||||
if (sConnectionManager is null)
|
||||
{
|
||||
throw new InvalidOperationException("No connection manager has been set.");
|
||||
}
|
||||
|
||||
if (sInstance is null)
|
||||
{
|
||||
throw new InvalidOperationException("No network manager has been set.");
|
||||
}
|
||||
|
||||
sInstance.StartCoroutine(sInstance.HostInternal());
|
||||
}
|
||||
|
||||
private IEnumerator JoinInternal(string code)
|
||||
{
|
||||
// Waits for it to be safe to connect, quits after 5 seconds
|
||||
float timeout = 0f;
|
||||
while (!mSafeToConnect)
|
||||
{
|
||||
if (timeout > 5f)
|
||||
{
|
||||
Debug.LogError("Host timed out");
|
||||
yield break;
|
||||
}
|
||||
|
||||
timeout += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Then connects to the lobby
|
||||
yield return sConnectionManager.Join(code, () =>
|
||||
{
|
||||
Debug.Log($"Joined {code}");
|
||||
});
|
||||
}
|
||||
|
||||
public static void Join(string code)
|
||||
{
|
||||
if (sConnectionManager is null)
|
||||
{
|
||||
throw new InvalidOperationException("No connection manager has been set.");
|
||||
}
|
||||
|
||||
if (sInstance is null)
|
||||
{
|
||||
throw new InvalidOperationException("No network manager has been set.");
|
||||
}
|
||||
|
||||
sInstance.StartCoroutine(sInstance.JoinInternal(code));
|
||||
}
|
||||
|
||||
private IEnumerator ChangeTransport(TransportType transport)
|
||||
{
|
||||
// Stops network from being restarted when unneeded
|
||||
if (transport == InternalCurrentTransport)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
mSafeToConnect = false;
|
||||
InternalCurrentTransport = transport;
|
||||
|
||||
// Shutdown existing network manager (if there is one) to stop multiple at once
|
||||
if (NetworkManager.Singleton is not null)
|
||||
{
|
||||
NetworkManager.Singleton.Shutdown();
|
||||
while (NetworkManager.Singleton.ShutdownInProgress)
|
||||
{
|
||||
yield return null; // Waits for next frame
|
||||
}
|
||||
|
||||
Destroy(mCurrentChildTransport);
|
||||
}
|
||||
|
||||
// Loads the new transport controller and lets it setup
|
||||
switch (InternalCurrentTransport)
|
||||
{
|
||||
case TransportType.UnityRelay:
|
||||
mCurrentChildTransport = Instantiate(UnityRelayTransport);
|
||||
sConnectionManager = new UnityRelayTransport();
|
||||
break;
|
||||
|
||||
case TransportType.Localhost:
|
||||
mCurrentChildTransport = Instantiate(LocalHostTransport);
|
||||
sConnectionManager = new LocalhostTransport();
|
||||
break;
|
||||
|
||||
case TransportType.None:
|
||||
// Nothing needs to be done here as there is no network controller
|
||||
mCurrentChildTransport = null;
|
||||
yield break;
|
||||
|
||||
default:
|
||||
mSafeToConnect = true;
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
DontDestroyOnLoad(mCurrentChildTransport);
|
||||
mSafeToConnect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user