This commit is contained in:
2026-05-01 21:58:20 +07:00
parent 07fb48353c
commit 709ed4069d
26 changed files with 599 additions and 1008 deletions

View File

@@ -1,4 +1,4 @@
using UnityEngine;
using UnityEngine;
using UnityEngine.UIElements;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -31,6 +31,8 @@ namespace Hallucinate.UI
private Label _guestChatMessage;
private TextField _chatInput;
private bool _isBusy = false;
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
{
base.Initialize(uxmlRoot, manager);
@@ -49,6 +51,7 @@ namespace Hallucinate.UI
_loungeRoomName = root.Q<Label>("LoungeRoomName");
_readyBtn = root.Q<Button>("ReadyBtn");
_startBtn = root.Q<Button>("StartBtn");
if (_startBtn != null) _startBtn.style.display = DisplayStyle.None; // Default to hidden
_hostNameLabel = root.Q<Label>("HostName");
_hostStatusLabel = root.Q<Label>("HostReadyStatus");
_hostChatBox = root.Q<VisualElement>("HostChatBox");
@@ -59,9 +62,10 @@ namespace Hallucinate.UI
_guestChatMessage = root.Q<Label>("GuestChatMessage");
_chatInput = root.Q<TextField>("ChatInput");
root.Q<Button>("GoToCreateBtn").clicked += ShowCreate;
root.Q<Button>("CancelCreateBtn").clicked += ShowJoin;
root.Q<Button>("BackToMenuBtn").clicked += async () => await uiManager.Pop();
root.Q<Button>("BackToMenuBtn").clicked += async () => { if (_isBusy) return; await uiManager.Pop(); };
_confirmCreateBtn = root.Q<Button>("ConfirmCreateBtn");
if (_confirmCreateBtn != null) _confirmCreateBtn.clicked += OnCreateRoomClicked;
root.Q<Button>("ConfirmJoinBtn").clicked += OnConfirmPasswordClicked;
@@ -103,7 +107,8 @@ namespace Hallucinate.UI
{
var runner = Object.FindFirstObjectByType<NetworkRunner>();
if (runner == null) return;
bool isHost = sender.PlayerId == 1;
var sortedPlayers = runner.ActivePlayers.OrderBy(p => p.PlayerId).ToList();
bool isHost = sortedPlayers.Count > 0 && sender == sortedPlayers[0];
if (isHost) ShowChatBubble(_hostChatBox, _hostChatMessage, message);
else ShowChatBubble(_guestChatBox, _guestChatMessage, message);
}
@@ -120,7 +125,13 @@ namespace Hallucinate.UI
private void ApplyLocalization() { if (LocalizationManager.Instance == null) return; }
private string GetT(string key) => LocalizationManager.Instance != null ? LocalizationManager.Instance.GetLocalizedString(key) : key;
public void SetRoomTemplate(VisualTreeAsset template) => _roomItemTemplate = template;
public override async Task PlayTransitionIn() { await base.PlayTransitionIn(); ShowJoin(); }
public override async Task PlayTransitionIn()
{
_isBusy = false;
await base.PlayTransitionIn();
ShowJoin();
}
public void ShowJoin()
{
@@ -158,18 +169,39 @@ namespace Hallucinate.UI
private async void OnCreateRoomClicked()
{
if (_isBusy) return;
_isBusy = true;
if (_confirmCreateBtn != null) _confirmCreateBtn.SetEnabled(false);
if (_createErrorLabel != null) _createErrorLabel.style.display = DisplayStyle.None;
var spawner = BasicSpawner.Instance;
if (spawner == null) { ShowCreateError("System Error: Spawner missing. Please re-enter the Lobby."); return; }
if (spawner == null)
{
ShowCreateError("System Error: Spawner missing. Please re-enter the Lobby.");
_isBusy = false;
return;
}
string id = (_roomIDInput != null && !string.IsNullOrEmpty(_roomIDInput.value)) ? _roomIDInput.value.Trim() : "ROOM_" + Random.Range(1000, 9999).ToString();
string name = (_roomNameInput != null && !string.IsNullOrEmpty(_roomNameInput.value)) ? _roomNameInput.value.Trim() : id;
string pass = (_passToggle != null && _passToggle.value && _roomPassInput != null) ? _roomPassInput.value : null;
try {
try
{
bool success = await spawner.StartHost(id, name, pass);
if (success) ShowLounge(name);
else ShowCreateError("Failed to create room. ID might be taken.");
} catch (System.Exception ex) { ShowCreateError("Network Error: " + ex.Message); }
}
catch (System.Exception ex)
{
ShowCreateError("Network Error: " + ex.Message);
}
finally
{
_isBusy = false;
if (_confirmCreateBtn != null) _confirmCreateBtn.SetEnabled(true);
}
}
private void ShowCreateError(string message)
@@ -203,6 +235,8 @@ namespace Hallucinate.UI
private async void OnRoomItemClicked(SessionInfo session)
{
if (_isBusy) return;
bool needsPass = session.Properties.ContainsKey("pw");
if (needsPass)
{
@@ -216,16 +250,49 @@ namespace Hallucinate.UI
private async void OnConfirmPasswordClicked()
{
if (_selectedSession == null) return;
if (_isBusy || _selectedSession == null) return;
_isBusy = true;
string pass = _joinPassInput != null ? _joinPassInput.value : "";
if (_passOverlay != null) _passOverlay.style.display = DisplayStyle.None;
await JoinRoom(_selectedSession.Name, pass);
_isBusy = false;
}
private async Task JoinRoom(string sessionName, string password) { if (BasicSpawner.Instance != null) { if (await BasicSpawner.Instance.StartClient(sessionName, password)) ShowLounge(sessionName); } }
private void OnReadyClicked() { var runner = Object.FindFirstObjectByType<NetworkRunner>(); if (runner != null && _playerDataManager != null && _playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData)) _playerDataManager.RPC_SetReady(runner.LocalPlayer, !myData.IsReady); }
private void OnStartClicked() { BasicSpawner.Instance?.StartGame(); }
private async void OnLeaveLoungeClicked() { var runner = Object.FindFirstObjectByType<NetworkRunner>(); if (runner != null) await runner.Shutdown(); if (_playerDataManager != null) _playerDataManager.OnChatMessageReceived -= OnChatMessageReceived; ShowJoin(); }
private async Task JoinRoom(string sessionName, string password)
{
if (BasicSpawner.Instance != null)
{
if (await BasicSpawner.Instance.StartClient(sessionName, password)) ShowLounge(sessionName);
}
}
private void OnReadyClicked()
{
if (_isBusy) return;
var runner = Object.FindFirstObjectByType<NetworkRunner>();
if (runner != null && _playerDataManager != null && _playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData))
_playerDataManager.RPC_SetReady(runner.LocalPlayer, !myData.IsReady);
}
private void OnStartClicked()
{
if (_isBusy) return;
BasicSpawner.Instance?.StartGame();
}
private async void OnLeaveLoungeClicked()
{
if (_isBusy) return;
_isBusy = true;
var runner = Object.FindFirstObjectByType<NetworkRunner>();
if (runner != null) await runner.Shutdown(false);
if (_playerDataManager != null) _playerDataManager.OnChatMessageReceived -= OnChatMessageReceived;
ShowJoin();
_isBusy = false;
}
public override void Update() { if (_loungeContainer != null && _loungeContainer.style.display == DisplayStyle.Flex) UpdateLoungeUI(); }
@@ -234,24 +301,44 @@ namespace Hallucinate.UI
var spawner = BasicSpawner.Instance;
if (spawner == null) return;
var runner = spawner.Runner;
if (runner == null || _playerDataManager == null || _playerDataManager.Object == null || !_playerDataManager.Object.IsValid) return;
if (runner == null) return;
PlayerRef hostRef = PlayerRef.None;
PlayerRef guestRef = PlayerRef.None;
// 1. Strict Visibility Check
bool isHost = runner.IsServer;
if (_startBtn != null)
{
_startBtn.style.display = isHost ? DisplayStyle.Flex : DisplayStyle.None;
}
// 2. PlayerDataManager Sync
if (_playerDataManager == null || _playerDataManager.Object == null || !_playerDataManager.Object.IsValid)
{
_playerDataManager = PlayerDataManager.Instance;
if (_playerDataManager != null)
{
_playerDataManager.OnChatMessageReceived += OnChatMessageReceived;
}
else return; // Still waiting for synchronization
}
// 3. Identify Players
var sortedPlayers = runner.ActivePlayers.OrderBy(p => p.PlayerId).ToList();
if (sortedPlayers.Count > 0) hostRef = sortedPlayers[0];
if (sortedPlayers.Count > 1) guestRef = sortedPlayers[1];
PlayerRef hostRef = sortedPlayers.Count > 0 ? sortedPlayers[0] : PlayerRef.None;
PlayerRef guestRef = sortedPlayers.Count > 1 ? sortedPlayers[1] : PlayerRef.None;
if (runner.SessionInfo != null && runner.SessionInfo.Properties.TryGetValue("rn", out var rnProp)) _loungeRoomName.text = rnProp.ToString().ToUpper();
// Host Display
if (hostRef != PlayerRef.None && _playerDataManager.TryGetPlayerMetaData(hostRef, out var hostData))
{
_hostNameLabel.text = hostData.Name.ToString().ToUpper();
_hostStatusLabel.text = hostData.IsReady ? GetT("LOBBY_READY") : GetT("LOBBY_NOT_READY");
string readyStatus = hostData.IsReady ? GetT("LOBBY_READY") : GetT("LOBBY_NOT_READY");
_hostStatusLabel.text = $"{GetT("LOBBY_HOST_LABEL")} - {readyStatus}";
_hostStatusLabel.style.color = hostData.IsReady ? Color.green : Color.red;
}
else if (hostRef != PlayerRef.None) { _hostNameLabel.text = GetT("LOBBY_SYNCING"); _hostStatusLabel.text = "-"; }
else { _hostNameLabel.text = GetT("LOBBY_SYNCING"); _hostStatusLabel.text = "-"; }
// Guest Display
if (guestRef != PlayerRef.None && _playerDataManager.TryGetPlayerMetaData(guestRef, out var guestData))
{
_guestNameLabel.text = guestData.Name.ToString().ToUpper();
@@ -261,17 +348,55 @@ namespace Hallucinate.UI
else if (runner.ActivePlayers.Count() >= 2) { _guestNameLabel.text = GetT("LOBBY_SYNCING"); _guestStatusLabel.text = "-"; }
else { _guestNameLabel.text = GetT("LOBBY_WAITING_LABEL"); _guestStatusLabel.text = "-"; _guestStatusLabel.style.color = Color.gray; }
bool allReady = true;
int playerCount = 0;
foreach (var p in runner.ActivePlayers) { playerCount++; if (_playerDataManager.TryGetPlayerMetaData(p, out var data)) { if (!data.IsReady) allReady = false; } else allReady = false; }
bool isHost = runner.LocalPlayer == hostRef;
if (_startBtn != null) { _startBtn.text = GetT("LOBBY_START_BTN"); _startBtn.style.display = isHost ? DisplayStyle.Flex : DisplayStyle.None; _startBtn.SetEnabled(allReady && playerCount >= 2); }
if (_readyBtn != null && _playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData))
// 4. Start Button Logic (Host Only)
if (_startBtn != null && isHost)
{
if (myData.IsReady) { _readyBtn.text = GetT("LOBBY_UNREADY_BTN"); _readyBtn.style.backgroundColor = new StyleColor(Color.green); _readyBtn.style.color = new StyleColor(Color.black); }
else { _readyBtn.text = GetT("LOBBY_READY_BTN"); _readyBtn.style.backgroundColor = new StyleColor(new Color(0.2f, 0.2f, 0.2f, 0.8f)); _readyBtn.style.color = new StyleColor(Color.white); }
bool allReady = true;
int playerCount = 0;
foreach (var p in runner.ActivePlayers)
{
playerCount++;
if (_playerDataManager.TryGetPlayerMetaData(p, out var data))
{
if (!data.IsReady) allReady = false;
}
else allReady = false;
}
bool canStart = allReady && playerCount >= 2;
_startBtn.SetEnabled(canStart);
_startBtn.text = GetT("LOBBY_START_BTN");
if (canStart)
{
_startBtn.style.backgroundColor = new StyleColor(Color.green);
_startBtn.style.color = new StyleColor(Color.black);
}
else
{
_startBtn.style.backgroundColor = new StyleColor(new Color(0.2f, 0.2f, 0.2f, 0.8f));
_startBtn.style.color = new StyleColor(new Color(1f, 1f, 1f, 0.5f));
}
}
// Ready Button Logic (Everyone)
if (_readyBtn != null)
{
if (_playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData))
{
if (myData.IsReady)
{
_readyBtn.text = GetT("LOBBY_UNREADY_BTN");
_readyBtn.style.backgroundColor = new StyleColor(Color.green);
_readyBtn.style.color = new StyleColor(Color.black);
}
else
{
_readyBtn.text = GetT("LOBBY_READY_BTN");
_readyBtn.style.backgroundColor = new StyleColor(new Color(0.2f, 0.2f, 0.2f, 0.8f));
_readyBtn.style.color = new StyleColor(Color.white);
}
}
}
}