This commit is contained in:
2026-04-28 19:04:09 +07:00
parent 9484f1f1d4
commit 6a5baedced
7 changed files with 321 additions and 330 deletions

View File

@@ -6,296 +6,150 @@ using Fusion;
using Fusion.Sockets;
using UnityEngine;
// ghi nhận các input của người chơi, ở đây chỉ có hướng di chuyển
public class _BasicSpawner : MonoBehaviour, INetworkRunnerCallbacks
namespace Hallucinate.UI
{
private NetworkRunner _runner { get; set; }
public class _BasicSpawner : MonoBehaviour, INetworkRunnerCallbacks
{
private NetworkRunner _runner { get; set; }
public _LobbyManager LobbyManager;
public event Action<List<SessionInfo>> OnSessionListUpdatedEvent;
public event Action<string> OnShutdownEvent;
public event Action OnJoinStartedEvent;
public event Action OnJoinFailedEvent;
private void Awake()
{
if (_runner == null) _runner = gameObject.AddComponent<NetworkRunner>();
DontDestroyOnLoad(gameObject);
}
private void Awake()
{
// dont destroy this object when loading new scenes
if(_runner == null) _runner = gameObject.AddComponent<NetworkRunner>();
DontDestroyOnLoad(gameObject);
}
// thông tin profile của player local, sẽ được tạo ra từ lobby và gửi lên host để tạo player object, ở đây tạm thời chỉ tạo 1 profile mặc định
public _PlayerProfile LocalPlayerProfile { get; private set; }
public void SetLocalPlayerProfile(_PlayerProfile _profile)
{
LocalPlayerProfile = _profile;
}
// start lobby
public async Task StartLobby()
{
if(_runner == null) _runner = gameObject.AddComponent<NetworkRunner>();
_runner.ProvideInput = true;
_runner.AddCallbacks(this);
var result = await _runner.JoinSessionLobby(SessionLobby.ClientServer);
if (result.Ok)
public _PlayerProfile LocalPlayerProfile { get; private set; }
public void SetLocalPlayerProfile(_PlayerProfile _profile)
{
Debug.Log("Joined lobby successfully!");
LocalPlayerProfile = _profile;
}
else
{
Debug.LogError($"Failed to join lobby: {result.ShutdownReason}");
}
}
// tạo phòng
public async Task StartHost(string sessionName, SceneRef scene)
{
var result = await _runner.StartGame(new StartGameArgs()
{
GameMode = GameMode.Host,
SessionName = sessionName,
Scene = scene,
PlayerCount = 2,
SceneManager = gameObject.AddComponent<NetworkSceneManagerDefault>()
});
if (result.Ok)
{
Debug.Log("Started host successfully!");
}
else
{
Debug.LogError($"Failed to start host: {result.ShutdownReason}");
}
}
// tham gia phòng
public async Task StartClient(string sessionName)
{
var result = await _runner.StartGame(new StartGameArgs()
{
GameMode = GameMode.Client,
SessionName = sessionName,
SceneManager = gameObject.AddComponent<NetworkSceneManagerDefault>()
});
if (result.Ok) {
Debug.Log("Started client successfully!");
}
else {
Debug.LogError($"Failed to start client: {result.ShutdownReason}");
}
}
public void OnObjectExitAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player)
{
}
public async Task StartLobby()
{
if (_runner == null) _runner = gameObject.AddComponent<NetworkRunner>();
_runner.ProvideInput = true;
_runner.AddCallbacks(this);
var result = await _runner.JoinSessionLobby(SessionLobby.ClientServer);
if (!result.Ok) Debug.LogError($"Failed to join lobby: {result.ShutdownReason}");
}
public void OnObjectEnterAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player)
{
}
[SerializeField] private NetworkPrefabRef _playerPrefab;
private Dictionary<PlayerRef, NetworkObject> _spawnedCharacters = new Dictionary<PlayerRef, NetworkObject>();
public async Task StartHost(string sessionName, string password = null)
{
OnJoinStartedEvent?.Invoke();
public void OnPlayerJoined(NetworkRunner runner, PlayerRef player)
{
// nếu là host
if (runner.IsServer)
// Sử dụng SessionProperties để lưu mật khẩu
var customProps = new Dictionary<string, SessionProperty>();
if (!string.IsNullOrEmpty(password))
{
Vector2 spawnPosition;
customProps.Add("pw", password);
}
if (player == runner.LocalPlayer)
{
spawnPosition = new Vector2(-8, 0);
}
else
{
spawnPosition = new Vector2(8, 0);
}
// Create a unique position for the player
// var spawnPosition = new Vector2(Random.Range(0, 5), Random.Range(0, 5));
var networkPlayerObject = runner.Spawn(
_playerPrefab,
spawnPosition,
Quaternion.identity,
player);
// Keep track of the player avatars for easy access
_spawnedCharacters.Add(player, networkPlayerObject);
// if (runner.ActivePlayers.Count() == 2 && !_ballStarted)
// {
// var ball = FindFirstObjectByType<Ball>();
// ball.Launch();
// _ballStarted = true;
// }
}
Debug.Log("Player joined: " + player + ", is local player: " + (player == runner.LocalPlayer));
if (player == runner.LocalPlayer)
{
var pdm = FindFirstObjectByType<_PlayerDataManager>();
if (pdm == null) return;
var metaData = new _PlayerMetaData()
var result = await _runner.StartGame(new StartGameArgs()
{
Name = LocalPlayerProfile.Name,
Role = LocalPlayerProfile.Role,
};
pdm.RPC_UpdatePlayerMetaData(player, metaData);
}
}
GameMode = GameMode.Host,
SessionName = sessionName,
SessionProperties = customProps,
PlayerCount = 2,
SceneManager = gameObject.AddComponent<NetworkSceneManagerDefault>()
});
public void OnPlayerLeft(NetworkRunner runner, PlayerRef player)
{
if (_spawnedCharacters.TryGetValue(player, out NetworkObject networkObject))
{
runner.Despawn(networkObject);
_spawnedCharacters.Remove(player);
if (runner.IsServer)
if (!result.Ok)
{
runner.Shutdown();
Debug.LogError($"Failed to start host: {result.ShutdownReason}");
OnJoinFailedEvent?.Invoke();
}
}
}
private bool IsGameReady(NetworkRunner runner)
{
return runner.ActivePlayers.Count() >= 2;
}
public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason)
{
Debug.Log("Game shutdown: " + shutdownReason);
UnityEngine.SceneManagement.SceneManager.LoadScene("Lobby");
}
public void OnDisconnectedFromServer(NetworkRunner runner, NetDisconnectReason reason)
{
}
public void OnConnectRequest(NetworkRunner runner, NetworkRunnerCallbackArgs.ConnectRequest request, byte[] token)
{
}
public void OnConnectFailed(NetworkRunner runner, NetAddress remoteAddress, NetConnectFailedReason reason)
{
}
public void OnUserSimulationMessage(NetworkRunner runner, SimulationMessagePtr message)
{
}
public void OnReliableDataReceived(NetworkRunner runner, PlayerRef player, ReliableKey key, ArraySegment<byte> data)
{
}
public void OnReliableDataProgress(NetworkRunner runner, PlayerRef player, ReliableKey key, float progress)
{
}
public void OnInput(NetworkRunner runner, NetworkInput input)
{
// collect the input and send it to the runner, which will then be sent to the server and other clients
var data = new _PlayerInputData();
data.direction = Input.GetAxis("Vertical");
input.Set(data);
}
public void OnInputMissing(NetworkRunner runner, PlayerRef player, NetworkInput input)
{
}
public void OnConnectedToServer(NetworkRunner runner)
{
}
// khi có update về danh sách phòng,
// ví dụ khi có phòng mới được tạo hoặc phòng bị xóa,
// host sẽ gửi update này cho tất cả client trong lobby
public void OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList)
{
Debug.Log("Session list updated, total sessions: " + sessionList.Count);
LobbyManager.DisplayRoomList(sessionList);
}
public void OnCustomAuthenticationResponse(NetworkRunner runner, Dictionary<string, object> data)
{
}
public void OnHostMigration(NetworkRunner runner, HostMigrationToken hostMigrationToken)
{
}
public void OnSceneLoadDone(NetworkRunner runner)
{
}
public void OnSceneLoadStart(NetworkRunner runner)
{
}
public void DespawnGO(NetworkObject networkObject)
{
if (_runner != null && networkObject != null)
public async Task StartClient(string sessionName, string password = null)
{
_runner.Despawn(networkObject);
}
}
OnJoinStartedEvent?.Invoke();
public NetworkObject SpawnGO(NetworkPrefabRef prefabRef, Vector2 position,Quaternion rotation, PlayerRef owner = default)
{
if (_runner != null)
var result = await _runner.StartGame(new StartGameArgs()
{
GameMode = GameMode.Client,
SessionName = sessionName,
SceneManager = gameObject.AddComponent<NetworkSceneManagerDefault>()
});
if (!result.Ok)
{
Debug.LogError($"Failed to join client: {result.ShutdownReason}");
OnJoinFailedEvent?.Invoke();
}
}
[SerializeField] private NetworkPrefabRef _playerPrefab;
private Dictionary<PlayerRef, NetworkObject> _spawnedCharacters = new Dictionary<PlayerRef, NetworkObject>();
public void OnPlayerJoined(NetworkRunner runner, PlayerRef player)
{
return _runner.Spawn(prefabRef, position, rotation, owner);
if (runner.IsServer)
{
Vector2 spawnPosition = (player == runner.LocalPlayer) ? new Vector2(-8, 0) : new Vector2(8, 0);
var networkPlayerObject = runner.Spawn(_playerPrefab, spawnPosition, Quaternion.identity, player);
_spawnedCharacters.Add(player, networkPlayerObject);
}
if (player == runner.LocalPlayer)
{
var pdm = FindFirstObjectByType<_PlayerDataManager>();
if (pdm != null)
{
var metaData = new _PlayerMetaData()
{
Name = LocalPlayerProfile.Name,
Role = LocalPlayerProfile.Role,
};
pdm.RPC_UpdatePlayerMetaData(player, metaData);
}
}
}
return null;
}
void AssignRoles(NetworkRunner runner)
{
var players = runner.ActivePlayers.ToList();
if (players.Count < 2) return;
public void OnPlayerLeft(NetworkRunner runner, PlayerRef player)
{
if (_spawnedCharacters.TryGetValue(player, out NetworkObject networkObject))
{
runner.Despawn(networkObject);
_spawnedCharacters.Remove(player);
if (runner.IsServer) runner.Shutdown();
}
}
var p1 = players[0];
var p2 = players[1];
public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason)
{
OnShutdownEvent?.Invoke(shutdownReason.ToString());
}
bool random = UnityEngine.Random.value > 0.5f;
public void OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList)
{
OnSessionListUpdatedEvent?.Invoke(sessionList);
}
SetRole(runner, p1, random ? _Role.Seeker : _Role.Trapper);
SetRole(runner, p2, random ? _Role.Trapper : _Role.Seeker);
}
void SetRole(NetworkRunner runner, PlayerRef player, _Role role)
{
var obj = runner.GetPlayerObject(player);
var data = obj.GetComponent<_PlayerData>();
public void OnInput(NetworkRunner runner, NetworkInput input)
{
var data = new _PlayerInputData();
data.direction = Input.GetAxis("Vertical");
input.Set(data);
}
data.PlayerRole = role;
Debug.Log($"Player {player} assigned role: {role}");
public void OnConnectedToServer(NetworkRunner runner) { }
public void OnDisconnectedFromServer(NetworkRunner runner, NetDisconnectReason reason) { }
public void OnConnectRequest(NetworkRunner runner, NetworkRunnerCallbackArgs.ConnectRequest request, byte[] token) { }
public void OnConnectFailed(NetworkRunner runner, NetAddress remoteAddress, NetConnectFailedReason reason) { }
public void OnUserSimulationMessage(NetworkRunner runner, SimulationMessagePtr message) { }
public void OnReliableDataReceived(NetworkRunner runner, PlayerRef player, ReliableKey key, ArraySegment<byte> data) { }
public void OnReliableDataProgress(NetworkRunner runner, PlayerRef player, ReliableKey key, float progress) { }
public void OnInputMissing(NetworkRunner runner, PlayerRef player, NetworkInput input) { }
public void OnObjectExitAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player) { }
public void OnObjectEnterAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player) { }
public void OnCustomAuthenticationResponse(NetworkRunner runner, Dictionary<string, object> data) { }
public void OnHostMigration(NetworkRunner runner, HostMigrationToken hostMigrationToken) { }
public void OnSceneLoadDone(NetworkRunner runner) { }
public void OnSceneLoadStart(NetworkRunner runner) { }
}
}