Driftology/Assets/Scripts/.FusionLauncher.cs
2025-06-30 16:51:24 +05:00

278 lines
8.7 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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) { }
}