Files
BABA_YAGA/Assets/Scripts/UI/LobbyController.cs
2026-04-29 13:10:00 +07:00

277 lines
10 KiB
C#

using UnityEngine;
using UnityEngine.UIElements;
using System.Collections.Generic;
using System.Threading.Tasks;
using Fusion;
using System.Linq;
namespace Hallucinate.UI
{
public class LobbyController : BaseUIController
{
private VisualTreeAsset _roomItemTemplate;
private _BasicSpawner _spawner;
private _PlayerDataManager _playerDataManager;
// Containers
private VisualElement _joinContainer, _createContainer, _loungeContainer, _passOverlay;
// Create Room Fields
private TextField _roomIDInput, _roomNameInput, _roomPassInput;
private Toggle _passToggle;
// Join Room Fields
private ScrollView _roomList;
private TextField _joinPassInput;
private Label _joinPassError;
private SessionInfo _selectedSession;
// Lounge Elements
private VisualElement _playerListContainer;
private Button _readyBtn, _startBtn;
private Label _loungeRoomName;
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
{
base.Initialize(uxmlRoot, manager);
_spawner = Object.FindFirstObjectByType<_BasicSpawner>();
// Query Elements
_joinContainer = root.Q<VisualElement>("JoinContainer");
_createContainer = root.Q<VisualElement>("CreateContainer");
_loungeContainer = root.Q<VisualElement>("LoungeContainer");
_passOverlay = root.Q<VisualElement>("PasswordOverlay");
_roomIDInput = root.Q<TextField>("RoomIDInput");
_roomNameInput = root.Q<TextField>("RoomNameInput");
_roomPassInput = root.Q<TextField>("RoomPassInput");
_passToggle = root.Q<Toggle>("PassToggle");
_roomList = root.Q<ScrollView>("RoomList");
_joinPassInput = root.Q<TextField>("JoinPassInput");
_joinPassError = root.Q<Label>("JoinPassError");
// Lounge Elements
_playerListContainer = root.Q<VisualElement>("PlayerList");
_readyBtn = root.Q<Button>("ReadyBtn");
_startBtn = root.Q<Button>("StartBtn");
_loungeRoomName = root.Q<Label>("LoungeRoomName");
// Event Bindings
var goToCreateBtn = root.Q<Button>("GoToCreateBtn");
if (goToCreateBtn != null) goToCreateBtn.clicked += ShowCreate;
var cancelCreateBtn = root.Q<Button>("CancelCreateBtn");
if (cancelCreateBtn != null) cancelCreateBtn.clicked += ShowJoin;
var backToMenuBtn = root.Q<Button>("BackToMenuBtn");
if (backToMenuBtn != null) backToMenuBtn.clicked += async () => await uiManager.Pop();
var confirmCreateBtn = root.Q<Button>("ConfirmCreateBtn");
if (confirmCreateBtn != null) confirmCreateBtn.clicked += OnCreateRoomClicked;
var confirmJoinBtn = root.Q<Button>("ConfirmJoinBtn");
if (confirmJoinBtn != null) confirmJoinBtn.clicked += OnConfirmPasswordClicked;
var closePassBtn = root.Q<Button>("ClosePassBtn");
if (closePassBtn != null) closePassBtn.clicked += () => { if(_passOverlay != null) _passOverlay.style.display = DisplayStyle.None; };
var leaveLoungeBtn = root.Q<Button>("LeaveLoungeBtn");
if (leaveLoungeBtn != null) leaveLoungeBtn.clicked += OnLeaveLoungeClicked;
if (_readyBtn != null) _readyBtn.clicked += OnReadyClicked;
if (_startBtn != null) _startBtn.clicked += OnStartClicked;
if (_passToggle != null)
{
_passToggle.RegisterValueChangedCallback(evt =>
{
if (_roomPassInput != null)
_roomPassInput.style.display = evt.newValue ? DisplayStyle.Flex : DisplayStyle.None;
});
}
// Đăng ký sự kiện từ Spawner
if (_spawner != null)
{
_spawner.OnSessionListUpdatedEvent += UpdateRoomList;
_spawner.OnJoinFailedEvent += () => _joinPassError.style.display = DisplayStyle.Flex;
_spawner.OnJoinStartedEvent += () => { /* Show loading if needed */ };
}
}
public void SetRoomTemplate(VisualTreeAsset template) => _roomItemTemplate = template;
public override async Task PlayTransitionIn()
{
await base.PlayTransitionIn();
ShowJoin();
}
public void ShowJoin()
{
_joinContainer.style.display = DisplayStyle.Flex;
_createContainer.style.display = DisplayStyle.None;
_loungeContainer.style.display = DisplayStyle.None;
_spawner?.StartLobby();
}
public void ShowCreate()
{
_joinContainer.style.display = DisplayStyle.None;
_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}";
_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;
if (string.IsNullOrEmpty(id)) return;
await _spawner.StartHost(id, pass);
ShowLounge(name);
}
private void UpdateRoomList(List<SessionInfo> sessions)
{
if (_roomList == null) return;
_roomList.Clear();
foreach (var session in sessions)
{
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 joinBtn = item.Q<Button>("JoinBtn");
joinBtn.clicked += () => OnRoomItemClicked(session);
_roomList.Add(item);
}
}
private 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 = "";
}
else
{
JoinRoom(session.Name, null);
}
}
private async void OnConfirmPasswordClicked()
{
if (_selectedSession == null) return;
string pass = _joinPassInput.value;
_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);
}
private void OnReadyClicked()
{
if (_playerDataManager != null)
{
var runner = Object.FindFirstObjectByType<NetworkRunner>();
if (runner != null)
{
_playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData);
_playerDataManager.RPC_SetReady(runner.LocalPlayer, !myData.IsReady);
}
}
}
private void OnStartClicked()
{
_spawner.StartGame();
}
private void OnLeaveLoungeClicked()
{
var runner = Object.FindFirstObjectByType<NetworkRunner>();
runner?.Shutdown();
ShowJoin();
}
public override void Update()
{
if (_loungeContainer.style.display == DisplayStyle.Flex)
{
UpdateLoungeUI();
}
}
private void UpdateLoungeUI()
{
if (_playerDataManager == null)
{
_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)
{
playerCount++;
var playerRef = kvp.Key;
var data = kvp.Value;
var playerItem = new VisualElement();
playerItem.style.flexDirection = FlexDirection.Row;
playerItem.style.justifyContent = Justify.SpaceBetween;
playerItem.style.paddingBottom = 5;
var nameLabel = new Label(data.Name.ToString());
var readyLabel = new Label(data.IsReady ? "READY" : "WAITING...");
readyLabel.style.color = data.IsReady ? Color.green : Color.yellow;
playerItem.Add(nameLabel);
playerItem.Add(readyLabel);
_playerListContainer.Add(playerItem);
if (!data.IsReady) allReady = false;
}
// 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";
}
}
}