Started adding multiplayer
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Bootstrap
|
||||
{
|
||||
public static class BootstrapLoader
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
||||
private static void LoadBoostrapScene() => SceneManager.LoadScene("Bootstrap", LoadSceneMode.Additive);
|
||||
}
|
||||
}
|
||||
22
Assets/Scripts/Core/BootstrapLoader.cs
Normal file
22
Assets/Scripts/Core/BootstrapLoader.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Core
|
||||
{
|
||||
public static class BootstrapLoader
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void LoadBoostrapScene()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// Stops loading in on the bootstrap scene
|
||||
if (SceneManager.GetActiveScene().name == "Bootstrap")
|
||||
{
|
||||
SceneManager.LoadScene("MainMenu", LoadSceneMode.Single);
|
||||
}
|
||||
#endif // UNITY_EDITOR
|
||||
|
||||
SceneManager.LoadScene("Bootstrap", LoadSceneMode.Additive);
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Assets/Scripts/Core/Network.meta
Normal file
8
Assets/Scripts/Core/Network.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 903cd34a044dfb14999cc382d7fb01bd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Assets/Scripts/Core/Network/Authenticator.cs
Normal file
26
Assets/Scripts/Core/Network/Authenticator.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Unity.Services.Authentication;
|
||||
using Unity.Services.Core;
|
||||
using System.Collections;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Core.Network
|
||||
{
|
||||
public static class Authenticator
|
||||
{
|
||||
public static bool IsAuthenticated { get; private set; }
|
||||
|
||||
public static IEnumerator Authenticate()
|
||||
{
|
||||
if (IsAuthenticated)
|
||||
{
|
||||
// User is already authenticated
|
||||
yield break;
|
||||
}
|
||||
|
||||
// TODO: Sign in via current platform
|
||||
|
||||
yield return UnityServices.InitializeAsync();
|
||||
yield return AuthenticationService.Instance.SignInAnonymouslyAsync();
|
||||
IsAuthenticated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Network/Authenticator.cs.meta
Normal file
3
Assets/Scripts/Core/Network/Authenticator.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ed9598a0f71474ea90df6a62ba55723
|
||||
timeCreated: 1779203851
|
||||
46
Assets/Scripts/Core/Network/ConnectionManager.cs
Normal file
46
Assets/Scripts/Core/Network/ConnectionManager.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using PashaBibko.PenguinChase.Extensions;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Core.Network
|
||||
{
|
||||
public class ConnectionManager : MonoBehaviour
|
||||
{
|
||||
private static ConnectionManager sInstance;
|
||||
|
||||
[SerializeField] private GameObject PrefabForEachClient;
|
||||
public static GameObject ClientPrefab => sInstance?.PrefabForEachClient;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Stops overlapping instances
|
||||
if (sInstance is not null)
|
||||
{
|
||||
Debug.LogError($"Multiple of [{nameof(ConnectionManager)}] cannot exist.");
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
public static void CreateNetworkConnectionManager()
|
||||
{
|
||||
NetworkManager.Singleton.OnClientConnectedCallback += OnClientJoin;
|
||||
OnClientJoin(0); // Has to be manually called for local client
|
||||
}
|
||||
|
||||
public static void DestroyNetworkConnectionManager()
|
||||
{
|
||||
NetworkManager.Singleton.OnClientConnectedCallback -= OnClientJoin;
|
||||
sInstance.DestroyAllChildren();
|
||||
}
|
||||
|
||||
private static void OnClientJoin(ulong id)
|
||||
{
|
||||
GameObject client = Instantiate(ClientPrefab);
|
||||
NetworkObject networkObject = client.GetComponent<NetworkObject>();
|
||||
networkObject.SpawnAsPlayerObject(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Network/ConnectionManager.cs.meta
Normal file
3
Assets/Scripts/Core/Network/ConnectionManager.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed9f8d66fd664fd68f1901f0120a0daf
|
||||
timeCreated: 1779208828
|
||||
146
Assets/Scripts/Core/Network/Network.cs
Normal file
146
Assets/Scripts/Core/Network/Network.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using PashaBibko.Pacore.Attributes;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
using System.Collections;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Core.Network
|
||||
{
|
||||
public enum TransportType
|
||||
{
|
||||
UnityRelay,
|
||||
Localhost,
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
public interface INetworkTransport
|
||||
{
|
||||
public IEnumerator Join(string code);
|
||||
public IEnumerator Host();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
public static UnityTransport CurrentTransportComponent
|
||||
{
|
||||
get
|
||||
{
|
||||
UnityTransport component = null;
|
||||
sInstance?.mCurrentChildTransport?.TryGetComponent(out component);
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Stops overlapping instances
|
||||
if (sInstance is not null)
|
||||
{
|
||||
Debug.LogError($"Multiple of [{nameof(Network)}] cannot exist.");
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
[UsedImplicitly, InspectorCallable("Choose Local Host Transport")]
|
||||
private void ChooseLocalHostTransport() => CurrentTransport = TransportType.Localhost;
|
||||
|
||||
[UsedImplicitly, InspectorCallable("Host")]
|
||||
public void Host()
|
||||
{
|
||||
if (sConnectionManager is null)
|
||||
{
|
||||
throw new InvalidOperationException("No connection manager has been set.");
|
||||
}
|
||||
|
||||
StartCoroutine(sConnectionManager.Host());
|
||||
}
|
||||
|
||||
[UsedImplicitly, InspectorCallable("Join")]
|
||||
public void Join()
|
||||
{
|
||||
if (sConnectionManager is null)
|
||||
{
|
||||
throw new InvalidOperationException("No connection manager has been set.");
|
||||
}
|
||||
|
||||
StartCoroutine(sConnectionManager.Join(GameJoinCode));
|
||||
}
|
||||
|
||||
private IEnumerator ChangeTransport(TransportType transport)
|
||||
{
|
||||
// Stops network from being restarted when unneeded
|
||||
if (transport == InternalCurrentTransport)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
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:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
DontDestroyOnLoad(mCurrentChildTransport);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Network/Network.cs.meta
Normal file
3
Assets/Scripts/Core/Network/Network.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f490d6c8b73d447fbe47c95efede54d0
|
||||
timeCreated: 1779196408
|
||||
3
Assets/Scripts/Core/Network/Transports.meta
Normal file
3
Assets/Scripts/Core/Network/Transports.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d478eb44fa9f45258a97c4a57e2e97e9
|
||||
timeCreated: 1779205011
|
||||
23
Assets/Scripts/Core/Network/Transports/LocalhostTransport.cs
Normal file
23
Assets/Scripts/Core/Network/Transports/LocalhostTransport.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Collections;
|
||||
using Unity.Netcode;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Core.Network
|
||||
{
|
||||
public class LocalhostTransport : INetworkTransport
|
||||
{
|
||||
// TODO: Allow connection to different devices on local network
|
||||
public IEnumerator Join(string _)
|
||||
{
|
||||
NetworkManager.Singleton.StartClient();
|
||||
yield break;
|
||||
}
|
||||
|
||||
public IEnumerator Host()
|
||||
{
|
||||
NetworkManager.Singleton.StartHost();
|
||||
ConnectionManager.CreateNetworkConnectionManager();
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54594dc099644958a5f437811cc47a5e
|
||||
timeCreated: 1779205047
|
||||
@@ -0,0 +1,61 @@
|
||||
using PashaBibko.PenguinChase.Extensions;
|
||||
using Unity.Services.Relay.Models;
|
||||
using Unity.Services.Relay;
|
||||
using System.Collections;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Core.Network
|
||||
{
|
||||
public class UnityRelayTransport : INetworkTransport
|
||||
{
|
||||
private const uint MAX_CONNECTIONS = 7;
|
||||
|
||||
public IEnumerator Join(string code)
|
||||
{
|
||||
yield return Authenticator.Authenticate();
|
||||
JoinAllocation allocation;
|
||||
{
|
||||
Result<JoinAllocation> result = new();
|
||||
yield return RelayService.Instance
|
||||
.JoinAllocationAsync(code)
|
||||
.Await(result);
|
||||
|
||||
allocation = result.Value;
|
||||
}
|
||||
|
||||
Network.CurrentTransportComponent.SetRelayServerData(allocation);
|
||||
NetworkManager.Singleton.StartClient();
|
||||
}
|
||||
|
||||
public IEnumerator Host()
|
||||
{
|
||||
yield return Authenticator.Authenticate();
|
||||
Allocation allocation;
|
||||
{
|
||||
Result<Allocation> result = new();
|
||||
yield return RelayService.Instance
|
||||
.CreateAllocationAsync(7)
|
||||
.Await(result);
|
||||
|
||||
allocation = result.Value;
|
||||
}
|
||||
|
||||
string joinCode = null;
|
||||
{
|
||||
Result<string> result = new();
|
||||
yield return RelayService.Instance
|
||||
.GetJoinCodeAsync(allocation.AllocationId)
|
||||
.Await(result);
|
||||
|
||||
joinCode = result.Value;
|
||||
}
|
||||
|
||||
Network.CurrentTransportComponent.SetHostRelayData(allocation);
|
||||
NetworkManager.Singleton.StartHost();
|
||||
|
||||
ConnectionManager.CreateNetworkConnectionManager();
|
||||
Debug.Log($"Started server with code: [{joinCode}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 873c14eb9ab94868b0572ae86759b2a7
|
||||
timeCreated: 1779205549
|
||||
3
Assets/Scripts/Extensions.meta
Normal file
3
Assets/Scripts/Extensions.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0270fb2159f4bbfbad1b8d165ef6454
|
||||
timeCreated: 1779206080
|
||||
15
Assets/Scripts/Extensions/MonoBehaviourExtensions.cs
Normal file
15
Assets/Scripts/Extensions/MonoBehaviourExtensions.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Extensions
|
||||
{
|
||||
public static class MonoBehaviourExtensions
|
||||
{
|
||||
public static void DestroyAllChildren(this MonoBehaviour go)
|
||||
{
|
||||
foreach (Transform child in go.transform)
|
||||
{
|
||||
Object.Destroy(child.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b9109919a0b4b969424d31ac875d6bf
|
||||
timeCreated: 1779211792
|
||||
26
Assets/Scripts/Extensions/TaskExtensions.cs
Normal file
26
Assets/Scripts/Extensions/TaskExtensions.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Extensions
|
||||
{
|
||||
public sealed class Result<T>
|
||||
{
|
||||
public T Value { get; set; }
|
||||
}
|
||||
|
||||
public static class TaskExtensions
|
||||
{
|
||||
public static IEnumerator Await<T>(this Task<T> task, Result<T> result)
|
||||
where T : class
|
||||
{
|
||||
// Waits until the task is completed
|
||||
while (!task.IsCompleted)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Has to return the value like this because of the wonders of C#
|
||||
result.Value = task.Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Extensions/TaskExtensions.cs.meta
Normal file
3
Assets/Scripts/Extensions/TaskExtensions.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf8f135562fd4650924729e686a5a815
|
||||
timeCreated: 1779206087
|
||||
33
Assets/Scripts/Extensions/UnityTransportExtensions.cs
Normal file
33
Assets/Scripts/Extensions/UnityTransportExtensions.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
using Unity.Services.Relay.Models;
|
||||
|
||||
namespace PashaBibko.PenguinChase.Extensions
|
||||
{
|
||||
public static class UnityTransportExtensions
|
||||
{
|
||||
public static void SetHostRelayData(this UnityTransport transport, Allocation allocation)
|
||||
{
|
||||
transport.SetHostRelayData
|
||||
(
|
||||
allocation.RelayServer.IpV4,
|
||||
(ushort)allocation.RelayServer.Port,
|
||||
allocation.AllocationIdBytes,
|
||||
allocation.Key,
|
||||
allocation.ConnectionData
|
||||
);
|
||||
}
|
||||
|
||||
public static void SetRelayServerData(this UnityTransport transport, JoinAllocation allocation)
|
||||
{
|
||||
transport.SetRelayServerData
|
||||
(
|
||||
allocation.RelayServer.IpV4,
|
||||
(ushort)allocation.RelayServer.Port,
|
||||
allocation.AllocationIdBytes,
|
||||
allocation.Key,
|
||||
allocation.ConnectionData,
|
||||
allocation.HostConnectionData
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c69f8839a8834857b6dc5df1627045df
|
||||
timeCreated: 1779207616
|
||||
Reference in New Issue
Block a user