This commit is contained in:
2026-04-30 00:55:16 +07:00
parent 1222d39fdf
commit a8d268c42b
18 changed files with 326 additions and 464 deletions

View File

@@ -1,12 +0,0 @@
using Fusion;
using UnityEngine;
namespace OnlyScove.Scripts
{
public struct PlayerInputData : INetworkInput
{
public Vector2 Direction;
public NetworkBool sprint;
public Quaternion rot;
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 731ed4a4b6e0ae64c8194463a76646c7

View File

@@ -1,200 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Fusion;
using Fusion.Sockets;
using UnityEngine;
using OnlyScove.Scripts;
namespace Hallucinate.UI
{
public class _BasicSpawner : MonoBehaviour, INetworkRunnerCallbacks
{
private NetworkRunner _runner { get; set; }
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);
}
public _PlayerProfile LocalPlayerProfile { get; private set; }
public void SetLocalPlayerProfile(_PlayerProfile _profile)
{
LocalPlayerProfile = _profile;
}
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 async Task StartHost(string sessionName, string password = null)
{
OnJoinStartedEvent?.Invoke();
var customProps = new Dictionary<string, SessionProperty>();
if (!string.IsNullOrEmpty(password))
{
customProps.Add("pw", password);
}
var result = await _runner.StartGame(new StartGameArgs()
{
GameMode = GameMode.Host,
SessionName = sessionName,
SessionProperties = customProps,
PlayerCount = 2,
SceneManager = gameObject.AddComponent<NetworkSceneManagerDefault>()
});
if (!result.Ok)
{
Debug.LogError($"Failed to start host: {result.ShutdownReason}");
OnJoinFailedEvent?.Invoke();
}
}
public async Task StartClient(string sessionName, string password = null)
{
OnJoinStartedEvent?.Invoke();
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)
{
if (player == runner.LocalPlayer)
{
var pdm = FindFirstObjectByType<_PlayerDataManager>();
if (pdm != null)
{
var metaData = new _PlayerMetaData()
{
Name = LocalPlayerProfile.Name,
Role = LocalPlayerProfile.Role,
IsReady = false
};
pdm.RPC_UpdatePlayerMetaData(player, metaData);
}
}
}
public void StartGame()
{
if (_runner.IsServer)
{
_runner.LoadScene("Main Scene");
}
}
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();
}
}
public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason)
{
OnShutdownEvent?.Invoke(shutdownReason.ToString());
}
public void OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList)
{
OnSessionListUpdatedEvent?.Invoke(sessionList);
}
public void OnInput(NetworkRunner runner, NetworkInput input)
{
var data = new PlayerInputData();
// Try to get input from the local player's InputReader
if (PlayerStateMachine.Local != null && PlayerStateMachine.Local.Input != null)
{
var inputReader = PlayerStateMachine.Local.Input;
data.Direction = inputReader.MoveInput;
data.sprint = inputReader.IsSprintHeld;
if (PlayerStateMachine.Local.Cam != null)
{
data.rot = PlayerStateMachine.Local.Cam.PlanarRotation;
}
}
else
{
// Fallback to basic input if player not spawned or InputReader missing
data.Direction = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
data.sprint = Input.GetKey(KeyCode.LeftShift);
}
input.Set(data);
}
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)
{
string currentSceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
if (runner.IsServer && currentSceneName == "Main Scene")
{
foreach (var player in runner.ActivePlayers)
{
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 (currentSceneName == "Main Scene")
{
if (UIManager.Instance != null) UIManager.Instance.OnGameStarted();
}
else if (currentSceneName == "Lobby" || currentSceneName == "Menu")
{
if (UIManager.Instance != null) UIManager.Instance.OnBackToMenu();
}
}
public void OnSceneLoadStart(NetworkRunner runner) { }
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: ca752d01bdc2c5e42938776307031da3

View File

@@ -1,30 +0,0 @@
using Fusion;
using UnityEngine;
public class _PlayerData : NetworkBehaviour
{
[Networked]
public _Role PlayerRole { get; set; }
public override void Spawned()
{
if (Object.HasInputAuthority)
{
SetupByRole(PlayerRole);
}
}
void SetupByRole(_Role role)
{
if (role == _Role.Seeker)
{
Debug.Log("I am Seeker");
// bật flashlight
}
else
{
Debug.Log("I am Trapper");
// bật trap UI
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 96ce77b74a34e7440a0b54af32c6d402

View File

@@ -1,37 +0,0 @@
using Fusion;
using UnityEngine;
// struct quản lý thông tin
public struct _PlayerMetaData : INetworkStruct
{
public NetworkString<_16> Name;
public _Role Role;
public NetworkBool IsReady;
}
public class _PlayerDataManager : NetworkBehaviour
{
[Networked]
public NetworkDictionary<PlayerRef, _PlayerMetaData> Players => default;
[Rpc(RpcSources.All, RpcTargets.StateAuthority)]
public void RPC_UpdatePlayerMetaData(PlayerRef playerRef, _PlayerMetaData metaData)
{
Players.Set(playerRef, metaData);
}
[Rpc(RpcSources.All, RpcTargets.StateAuthority)]
public void RPC_SetReady(PlayerRef playerRef, bool ready)
{
if (Players.TryGet(playerRef, out var data))
{
data.IsReady = ready;
Players.Set(playerRef, data);
}
}
public bool TryGetPlayerMetaData(PlayerRef playerRef, out _PlayerMetaData metaData)
{
return Players.TryGet(playerRef, out metaData);
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: b3d9934ebd60c9c4ea3e464b77fd7ae0

View File

@@ -1,50 +0,0 @@
using Fusion;
using TMPro;
using UnityEngine;
public enum _Role
{
Seeker,
Trapper
}
public struct _PlayerProfile
{
public string Name;
public _Role Role;
}
public class _PlayerInfo : NetworkBehaviour
{
[Networked] public string playerName { get; set; }
public _PlayerDataManager playerDataManager;
public TextMeshProUGUI nameText;
public GameObject[] characterIcons; // mảng chứa icon tương ứng với từng class, có thể gán trong inspector
// sau khi game object được tạo ra trên mạng,
// sẽ gọi phương thức này để khởi tạo thông tin player
public override void Spawned()
{
playerDataManager = FindFirstObjectByType<_PlayerDataManager>(); // tìm PlayerDataManager trong scene
}
// phương thức này sẽ được gọi mỗi frame để cập nhật thông tin hiển thị của player
public override void Render()
{
if (playerDataManager == null) return;
if (playerDataManager.TryGetPlayerMetaData(Object.InputAuthority, out var metadata))
{
var name = metadata.Name;
var charClass = metadata.Role;
nameText.text = $"{name} ({charClass})";
for (var i = 0; i < characterIcons.Length; i++)
{
characterIcons[i].SetActive(i == (int)charClass); // hiển thị icon tương ứng với class của player
}
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 70abb536cf50f2948882e913634daedf