You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Driftology/Assets/Scripts/.FusionLauncher.cs

278 lines
8.7 KiB
C#

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Fusion;
using Fusion.Sockets;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
using UnityEngine.UI;
using System.Linq;
public class FusionLauncher : MonoBehaviour, INetworkRunnerCallbacks
{
[Header("Network Runner (Drag NOTHING here)")]
public NetworkRunner runner;
[Header("Lobby UI")]
public GameObject lobbyUI;
public SessionListUIHandler sessionListUIHandler;
public TMP_InputField lobbyNameInput;
public Button createLobbyButton;
public TextMeshProUGUI waitingText;
[Header("Player Prefab")]
public NetworkPrefabRef playerPrefab;
private Coroutine refreshCoroutine;
private int playerCount = 0;
private const int maxPlayers = 2;
private bool gameplayLoaded = false;
private bool connectedToServer = false;
private List<PlayerRef> playersToSpawn = new List<PlayerRef>();
void Awake()
{
if (FindObjectsOfType<FusionLauncher>().Length > 1)
{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
}
void Start()
{
StartDummyRunner();
if (lobbyNameInput != null) lobbyNameInput.onValueChanged.AddListener(OnLobbyNameChanged);
OnLobbyNameChanged(lobbyNameInput.text);
waitingText.gameObject.SetActive(false);
refreshCoroutine = StartCoroutine(AutoRefreshLobbyList());
}
void OnDestroy()
{
if (refreshCoroutine != null)
StopCoroutine(refreshCoroutine);
}
IEnumerator AutoRefreshLobbyList()
{
while (true)
{
RefreshLobbyList();
yield return new WaitForSeconds(5f);
}
}
void OnLobbyNameChanged(string s)
{
createLobbyButton.interactable = !string.IsNullOrWhiteSpace(s) && s.Length <= 15;
}
async void StartDummyRunner()
{
if (runner != null && runner.IsRunning) return;
await EnsureFreshRunner();
var result = await runner.StartGame(new StartGameArgs()
{
GameMode = GameMode.Client,
SceneManager = runner.gameObject.AddComponent<NetworkSceneManagerDefault>()
});
if (result.Ok)
{
Debug.Log("✅ Browser runner connected (Client mode).");
connectedToServer = true;
}
else if (result.ShutdownReason == ShutdownReason.GameNotFound)
{
Debug.Log(" No lobbies yet—but browser runner is live.");
connectedToServer = true;
}
else
{
Debug.LogError($"❌ Browser runner failed: {result.ShutdownReason}");
}
}
private async Task EnsureFreshRunner()
{
playerCount = 0;
gameplayLoaded = false;
connectedToServer = false;
playersToSpawn.Clear();
if (runner != null && runner.IsRunning)
{
await runner.Shutdown();
Destroy(runner.gameObject);
}
if (refreshCoroutine != null)
{
StopCoroutine(refreshCoroutine);
refreshCoroutine = null;
}
var go = new GameObject("NetworkRunnerGO");
DontDestroyOnLoad(go);
runner = go.AddComponent<NetworkRunner>();
runner.ProvideInput = true;
runner.AddCallbacks(this);
var inputProv = go.AddComponent<FusionInputProvider>();
runner.AddCallbacks(inputProv);
Debug.Log($"[Launcher] Spawned {go.name} → ProvideInput={runner.ProvideInput}; FusionInputProvider attached");
}
public async void CreateLobby()
{
var name = lobbyNameInput.text.Trim();
if (string.IsNullOrEmpty(name)) return;
await EnsureFreshRunner();
var sceneRef = SceneRef.FromIndex(SceneManager.GetActiveScene().buildIndex);
var res = await runner.StartGame(new StartGameArgs()
{
GameMode = GameMode.Host,
SessionName = name,
PlayerCount = maxPlayers,
Scene = sceneRef,
SceneManager = runner.gameObject.AddComponent<NetworkSceneManagerDefault>()
});
if (res.Ok)
{
Debug.Log($"✔ Hosted Lobby '{name}'");
lobbyUI.SetActive(false);
waitingText.text = "Waiting for player 2…";
waitingText.gameObject.SetActive(true);
}
else
{
Debug.LogError($"✖ Host failed: {res.ShutdownReason}");
}
}
public async void JoinLobby(SessionInfo info)
{
await EnsureFreshRunner();
var res = await runner.StartGame(new StartGameArgs()
{
GameMode = GameMode.Client,
SessionName = info.Name,
Scene = SceneRef.FromIndex(SceneManager.GetActiveScene().buildIndex),
SceneManager = runner.gameObject.AddComponent<NetworkSceneManagerDefault>()
});
if (res.Ok)
{
Debug.Log($"✔ Joined Lobby '{info.Name}'");
lobbyUI.SetActive(false);
waitingText.text = "Waiting for host…";
waitingText.gameObject.SetActive(true);
}
else
{
Debug.LogError($"✖ Join failed: {res.ShutdownReason}");
}
}
public void RefreshLobbyList()
{
if (!connectedToServer) return;
runner.JoinSessionLobby(SessionLobby.ClientServer);
}
public void OnConnectedToServer(NetworkRunner r)
{
connectedToServer = true;
Debug.Log("✔ Connected to server; can refresh lobbies.");
RefreshLobbyList();
}
public void OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList)
{
sessionListUIHandler.ClearList();
if (sessionList.Count == 0)
{
sessionListUIHandler.ShowNoSessionsMessage();
return;
}
foreach (var session in sessionList)
{
if (session.IsOpen && session.IsVisible && session.PlayerCount < session.MaxPlayers)
{
sessionListUIHandler.AddToList(session, JoinLobby);
}
}
}
public void OnPlayerJoined(NetworkRunner r, PlayerRef p)
{
playerCount++;
playersToSpawn.Add(p);
Debug.Log($"➡ Player joined: {p}");
if (r.IsServer && playerCount == maxPlayers && !gameplayLoaded)
{
gameplayLoaded = true;
var scene = SceneRef.FromIndex(SceneUtility.GetBuildIndexByScenePath("Assets/Scenes/Gameplay.unity"));
r.LoadScene(scene, LoadSceneMode.Single);
waitingText.gameObject.SetActive(false);
}
}
public void OnSceneLoadDone(NetworkRunner runner)
{
if (!runner.IsServer) return;
var provider = FindObjectOfType<SpawnPointProvider>();
if (provider == null || provider.spawnPoints == null || provider.spawnPoints.Length == 0)
{
Debug.LogError("❌ No SpawnPointProvider or no spawnPoints assigned!");
return;
}
for (int i = 0; i < playersToSpawn.Count && i < provider.spawnPoints.Length; i++)
{
PlayerRef player = playersToSpawn[i];
Transform spawnPoint = provider.spawnPoints[i];
runner.Spawn(playerPrefab, spawnPoint.position, spawnPoint.rotation, inputAuthority: player);
Debug.Log($"✔ Spawned player with authority: {player}");
}
playersToSpawn.Clear();
}
// Stub callbacks
public void OnDisconnectedFromServer(NetworkRunner r, NetDisconnectReason reason) { }
public void OnConnectRequest(NetworkRunner r, NetworkRunnerCallbackArgs.ConnectRequest req, byte[] tok) { }
public void OnConnectFailed(NetworkRunner r, NetAddress addr, NetConnectFailedReason reason) { }
public void OnUserSimulationMessage(NetworkRunner r, SimulationMessagePtr msg) { }
public void OnShutdown(NetworkRunner r, ShutdownReason reason) { }
public void OnPlayerLeft(NetworkRunner r, PlayerRef p) { }
public void OnInput(NetworkRunner r, NetworkInput input) { }
public void OnInputMissing(NetworkRunner r, PlayerRef p, NetworkInput input) { }
public void OnObjectEnterAOI(NetworkRunner r, NetworkObject obj, PlayerRef p) { }
public void OnObjectExitAOI(NetworkRunner r, NetworkObject obj, PlayerRef p) { }
public void OnReliableDataReceived(NetworkRunner r, PlayerRef p, ReliableKey k, System.ArraySegment<byte> data) { }
public void OnReliableDataProgress(NetworkRunner r, PlayerRef p, ReliableKey k, float prog) { }
public void OnSceneLoadStart(NetworkRunner r) { }
public void OnHostMigration(NetworkRunner r, HostMigrationToken t) { }
public void OnCustomAuthenticationResponse(NetworkRunner r, Dictionary<string, object> data) { }
}