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

@@ -10,8 +10,7 @@ namespace Hallucinate.UI
public class LobbyController : BaseUIController
{
private VisualTreeAsset _roomItemTemplate;
private _BasicSpawner _spawner;
private _PlayerDataManager _playerDataManager;
private PlayerDataManager _playerDataManager;
// Containers
private VisualElement _joinContainer, _createContainer, _loungeContainer, _passOverlay;
@@ -34,7 +33,6 @@ namespace Hallucinate.UI
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
{
base.Initialize(uxmlRoot, manager);
_spawner = Object.FindFirstObjectByType<_BasicSpawner>();
// Query Elements
_joinContainer = root.Q<VisualElement>("JoinContainer");
@@ -91,13 +89,24 @@ namespace Hallucinate.UI
});
}
// Đăng ký sự kiện từ Spawner
if (_spawner != null)
// Đăng ký sự kiện từ Spawner (Sử dụng Instance)
if (BasicSpawner.Instance != null)
{
_spawner.OnSessionListUpdatedEvent += UpdateRoomList;
_spawner.OnJoinFailedEvent += () => _joinPassError.style.display = DisplayStyle.Flex;
_spawner.OnJoinStartedEvent += () => { /* Show loading if needed */ };
RegisterSpawnerEvents();
}
else
{
// Nếu chưa có, thử tìm sau một chút
Invoke(nameof(RegisterSpawnerEvents), 0.1f);
}
}
private void RegisterSpawnerEvents()
{
if (BasicSpawner.Instance == null) return;
BasicSpawner.Instance.OnSessionListUpdatedEvent += UpdateRoomList;
BasicSpawner.Instance.OnJoinFailedEvent += () => { if(_joinPassError != null) _joinPassError.style.display = DisplayStyle.Flex; };
BasicSpawner.Instance.OnJoinStartedEvent += () => { /* Show loading if needed */ };
}
public void SetRoomTemplate(VisualTreeAsset template) => _roomItemTemplate = template;
@@ -110,38 +119,60 @@ namespace Hallucinate.UI
public void ShowJoin()
{
_joinContainer.style.display = DisplayStyle.Flex;
_createContainer.style.display = DisplayStyle.None;
_loungeContainer.style.display = DisplayStyle.None;
_spawner?.StartLobby();
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.Flex;
if (_createContainer != null) _createContainer.style.display = DisplayStyle.None;
if (_loungeContainer != null) _loungeContainer.style.display = DisplayStyle.None;
BasicSpawner.Instance?.StartLobby();
}
public void ShowCreate()
{
_joinContainer.style.display = DisplayStyle.None;
_createContainer.style.display = DisplayStyle.Flex;
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.None;
if (_createContainer != null) _createContainer.style.display = DisplayStyle.Flex;
}
private void ShowLounge(string roomName)
{
_joinContainer.style.display = DisplayStyle.None;
_createContainer.style.display = DisplayStyle.None;
_loungeContainer.style.display = DisplayStyle.Flex;
_loungeRoomName.text = $"Room: {roomName}";
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.None;
if (_createContainer != null) _createContainer.style.display = DisplayStyle.None;
if (_loungeContainer != null) _loungeContainer.style.display = DisplayStyle.Flex;
if (_loungeRoomName != null) _loungeRoomName.text = $"Room: {roomName}";
_playerDataManager = Object.FindFirstObjectByType<_PlayerDataManager>();
_playerDataManager = Object.FindFirstObjectByType<PlayerDataManager>();
}
private async void OnCreateRoomClicked()
{
string id = _roomIDInput.value.Trim();
string name = string.IsNullOrEmpty(_roomNameInput.value) ? id : _roomNameInput.value;
string pass = _passToggle.value ? _roomPassInput.value : null;
var spawner = BasicSpawner.Instance;
if (spawner == null)
{
Debug.LogError("[LobbyController] BasicSpawner.Instance is missing!");
return;
}
if (string.IsNullOrEmpty(id)) return;
string id = _roomIDInput != null && !string.IsNullOrEmpty(_roomIDInput.value)
? _roomIDInput.value.Trim()
: Random.Range(1000, 9999).ToString();
await _spawner.StartHost(id, pass);
ShowLounge(name);
if (_roomIDInput != null) _roomIDInput.value = id;
string name = _roomNameInput != null && !string.IsNullOrEmpty(_roomNameInput.value)
? _roomNameInput.value
: $"Room {id}";
string pass = (_passToggle != null && _passToggle.value && _roomPassInput != null)
? _roomPassInput.value
: null;
bool success = await spawner.StartHost(id, pass);
if (success)
{
ShowLounge(name);
}
else
{
Debug.LogWarning("[LobbyController] Failed to create room. Please check AppID/Region.");
}
}
private void UpdateRoomList(List<SessionInfo> sessions)
@@ -150,48 +181,53 @@ namespace Hallucinate.UI
_roomList.Clear();
foreach (var session in sessions)
{
if (_roomItemTemplate == null) continue;
var item = _roomItemTemplate.Instantiate();
item.Q<Label>("RoomName").text = session.Name;
item.Q<Label>("PlayerCount").text = $"{session.PlayerCount}/{session.MaxPlayers}";
bool needsPass = session.Properties.ContainsKey("pw");
item.Q<Label>("LockIcon").style.display = needsPass ? DisplayStyle.Flex : DisplayStyle.None;
var lockIcon = item.Q<Label>("LockIcon");
if (lockIcon != null) lockIcon.style.display = needsPass ? DisplayStyle.Flex : DisplayStyle.None;
var joinBtn = item.Q<Button>("JoinBtn");
joinBtn.clicked += () => OnRoomItemClicked(session);
if (joinBtn != null) joinBtn.clicked += () => OnRoomItemClicked(session);
_roomList.Add(item);
}
}
private void OnRoomItemClicked(SessionInfo session)
private async void OnRoomItemClicked(SessionInfo session)
{
bool needsPass = session.Properties.ContainsKey("pw");
if (needsPass)
{
_selectedSession = session;
_passOverlay.style.display = DisplayStyle.Flex;
_joinPassError.style.display = DisplayStyle.None;
_joinPassInput.value = "";
if (_passOverlay != null) _passOverlay.style.display = DisplayStyle.Flex;
if (_joinPassError != null) _joinPassError.style.display = DisplayStyle.None;
if (_joinPassInput != null) _joinPassInput.value = "";
}
else
{
JoinRoom(session.Name, null);
await JoinRoom(session.Name, null);
}
}
private async void OnConfirmPasswordClicked()
{
if (_selectedSession == null) return;
string pass = _joinPassInput.value;
_passOverlay.style.display = DisplayStyle.None;
string pass = _joinPassInput != null ? _joinPassInput.value : "";
if (_passOverlay != null) _passOverlay.style.display = DisplayStyle.None;
await JoinRoom(_selectedSession.Name, pass);
}
private async Task JoinRoom(string sessionName, string password)
{
await _spawner.StartClient(sessionName, password);
ShowLounge(sessionName);
if (BasicSpawner.Instance != null)
{
bool success = await BasicSpawner.Instance.StartClient(sessionName, password);
if (success) ShowLounge(sessionName);
}
}
private void OnReadyClicked()
@@ -209,7 +245,7 @@ namespace Hallucinate.UI
private void OnStartClicked()
{
_spawner.StartGame();
BasicSpawner.Instance?.StartGame();
}
private void OnLeaveLoungeClicked()
@@ -221,7 +257,7 @@ namespace Hallucinate.UI
public override void Update()
{
if (_loungeContainer.style.display == DisplayStyle.Flex)
if (_loungeContainer != null && _loungeContainer.style.display == DisplayStyle.Flex)
{
UpdateLoungeUI();
}
@@ -231,46 +267,55 @@ namespace Hallucinate.UI
{
if (_playerDataManager == null)
{
_playerDataManager = Object.FindFirstObjectByType<_PlayerDataManager>();
_playerDataManager = Object.FindFirstObjectByType<PlayerDataManager>();
return;
}
var runner = Object.FindFirstObjectByType<NetworkRunner>();
if (runner == null) return;
// Update Player List
_playerListContainer.Clear();
bool allReady = true;
int playerCount = 0;
foreach (var kvp in _playerDataManager.Players)
if (_playerListContainer != null)
{
playerCount++;
var playerRef = kvp.Key;
var data = kvp.Value;
_playerListContainer.Clear();
bool allReady = true;
int playerCount = 0;
var playerItem = new VisualElement();
playerItem.style.flexDirection = FlexDirection.Row;
playerItem.style.justifyContent = Justify.SpaceBetween;
playerItem.style.paddingBottom = 5;
foreach (var kvp in _playerDataManager.Players)
{
playerCount++;
var data = kvp.Value;
var nameLabel = new Label(data.Name.ToString());
var readyLabel = new Label(data.IsReady ? "READY" : "WAITING...");
readyLabel.style.color = data.IsReady ? Color.green : Color.yellow;
var playerItem = new VisualElement();
playerItem.style.flexDirection = FlexDirection.Row;
playerItem.style.justifyContent = Justify.SpaceBetween;
playerItem.style.paddingBottom = 5;
playerItem.Add(nameLabel);
playerItem.Add(readyLabel);
_playerListContainer.Add(playerItem);
var nameLabel = new Label(data.Name.ToString());
var readyLabel = new Label(data.IsReady ? "READY" : "WAITING...");
readyLabel.style.color = data.IsReady ? Color.green : Color.yellow;
if (!data.IsReady) allReady = false;
playerItem.Add(nameLabel);
playerItem.Add(readyLabel);
_playerListContainer.Add(playerItem);
if (!data.IsReady) allReady = false;
}
if (_startBtn != null)
_startBtn.style.display = (runner.IsServer && allReady && playerCount >= 2) ? DisplayStyle.Flex : DisplayStyle.None;
if (_readyBtn != null)
{
_playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData);
_readyBtn.text = myData.IsReady ? "UNREADY" : "READY UP";
}
}
}
// Update Buttons
_startBtn.style.display = (runner.IsServer && allReady && playerCount >= 2) ? DisplayStyle.Flex : DisplayStyle.None;
_playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData);
_readyBtn.text = myData.IsReady ? "UNREADY" : "READY UP";
private async void Invoke(string methodName, float delay)
{
await Task.Delay((int)(delay * 1000));
if (methodName == nameof(RegisterSpawnerEvents)) RegisterSpawnerEvents();
}
}
}