2026-04-30 15:08:19 +07:00
|
|
|
|
using UnityEngine;
|
2026-04-25 18:20:16 +07:00
|
|
|
|
using UnityEngine.UIElements;
|
2026-04-28 19:04:09 +07:00
|
|
|
|
using System.Collections.Generic;
|
2026-04-28 00:07:42 +07:00
|
|
|
|
using System.Threading.Tasks;
|
2026-04-28 19:04:09 +07:00
|
|
|
|
using Fusion;
|
2026-04-29 13:10:00 +07:00
|
|
|
|
using System.Linq;
|
2026-04-25 18:20:16 +07:00
|
|
|
|
|
2026-04-28 00:07:42 +07:00
|
|
|
|
namespace Hallucinate.UI
|
2026-04-25 18:20:16 +07:00
|
|
|
|
{
|
2026-04-28 00:07:42 +07:00
|
|
|
|
public class LobbyController : BaseUIController
|
2026-04-25 18:20:16 +07:00
|
|
|
|
{
|
2026-04-28 19:04:09 +07:00
|
|
|
|
private VisualTreeAsset _roomItemTemplate;
|
2026-04-30 00:55:16 +07:00
|
|
|
|
private PlayerDataManager _playerDataManager;
|
2026-04-25 18:20:16 +07:00
|
|
|
|
|
2026-04-28 19:04:09 +07:00
|
|
|
|
// 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;
|
2026-04-28 00:07:42 +07:00
|
|
|
|
|
2026-04-29 13:10:00 +07:00
|
|
|
|
// Lounge Elements
|
|
|
|
|
|
private Label _loungeRoomName;
|
2026-04-30 15:08:19 +07:00
|
|
|
|
private Button _readyBtn, _startBtn;
|
|
|
|
|
|
|
|
|
|
|
|
// Host Slot
|
|
|
|
|
|
private Label _hostNameLabel, _hostStatusLabel;
|
|
|
|
|
|
private VisualElement _hostChatBox;
|
|
|
|
|
|
private Label _hostChatMessage;
|
|
|
|
|
|
|
|
|
|
|
|
// Guest Slot
|
|
|
|
|
|
private Label _guestNameLabel, _guestStatusLabel;
|
|
|
|
|
|
private VisualElement _guestChatBox;
|
|
|
|
|
|
private Label _guestChatMessage;
|
|
|
|
|
|
|
|
|
|
|
|
// Chat Input
|
|
|
|
|
|
private TextField _chatInput;
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-28 00:07:42 +07:00
|
|
|
|
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
|
2026-04-25 18:20:16 +07:00
|
|
|
|
{
|
2026-04-28 00:07:42 +07:00
|
|
|
|
base.Initialize(uxmlRoot, manager);
|
2026-04-26 05:02:49 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Query Containers
|
2026-04-28 00:07:42 +07:00
|
|
|
|
_joinContainer = root.Q<VisualElement>("JoinContainer");
|
|
|
|
|
|
_createContainer = root.Q<VisualElement>("CreateContainer");
|
|
|
|
|
|
_loungeContainer = root.Q<VisualElement>("LoungeContainer");
|
2026-04-28 19:04:09 +07:00
|
|
|
|
_passOverlay = root.Q<VisualElement>("PasswordOverlay");
|
2026-04-26 05:02:49 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Create Room Fields
|
2026-04-28 19:04:09 +07:00
|
|
|
|
_roomIDInput = root.Q<TextField>("RoomIDInput");
|
|
|
|
|
|
_roomNameInput = root.Q<TextField>("RoomNameInput");
|
|
|
|
|
|
_roomPassInput = root.Q<TextField>("RoomPassInput");
|
|
|
|
|
|
_passToggle = root.Q<Toggle>("PassToggle");
|
2026-04-30 15:08:19 +07:00
|
|
|
|
|
|
|
|
|
|
// Join Room Fields
|
2026-04-28 19:04:09 +07:00
|
|
|
|
_roomList = root.Q<ScrollView>("RoomList");
|
|
|
|
|
|
_joinPassInput = root.Q<TextField>("JoinPassInput");
|
|
|
|
|
|
_joinPassError = root.Q<Label>("JoinPassError");
|
2026-04-26 05:02:49 +07:00
|
|
|
|
|
2026-04-29 13:10:00 +07:00
|
|
|
|
// Lounge Elements
|
2026-04-30 15:08:19 +07:00
|
|
|
|
_loungeRoomName = root.Q<Label>("LoungeRoomName");
|
2026-04-29 13:10:00 +07:00
|
|
|
|
_readyBtn = root.Q<Button>("ReadyBtn");
|
|
|
|
|
|
_startBtn = root.Q<Button>("StartBtn");
|
|
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Host Slot
|
|
|
|
|
|
_hostNameLabel = root.Q<Label>("HostName");
|
|
|
|
|
|
_hostStatusLabel = root.Q<Label>("HostReadyStatus");
|
|
|
|
|
|
_hostChatBox = root.Q<VisualElement>("HostChatBox");
|
|
|
|
|
|
_hostChatMessage = root.Q<Label>("HostChatMessage");
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Guest Slot
|
|
|
|
|
|
_guestNameLabel = root.Q<Label>("GuestName");
|
|
|
|
|
|
_guestStatusLabel = root.Q<Label>("GuestReadyStatus");
|
|
|
|
|
|
_guestChatBox = root.Q<VisualElement>("GuestChatBox");
|
|
|
|
|
|
_guestChatMessage = root.Q<Label>("GuestChatMessage");
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Chat Input
|
|
|
|
|
|
_chatInput = root.Q<TextField>("ChatInput");
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Event Bindings
|
|
|
|
|
|
root.Q<Button>("GoToCreateBtn").clicked += ShowCreate;
|
|
|
|
|
|
root.Q<Button>("CancelCreateBtn").clicked += ShowJoin;
|
|
|
|
|
|
root.Q<Button>("BackToMenuBtn").clicked += async () => await uiManager.Pop();
|
|
|
|
|
|
root.Q<Button>("ConfirmCreateBtn").clicked += OnCreateRoomClicked;
|
|
|
|
|
|
root.Q<Button>("ConfirmJoinBtn").clicked += OnConfirmPasswordClicked;
|
|
|
|
|
|
root.Q<Button>("ClosePassBtn").clicked += () => { if(_passOverlay != null) _passOverlay.style.display = DisplayStyle.None; };
|
|
|
|
|
|
root.Q<Button>("LeaveLoungeBtn").clicked += OnLeaveLoungeClicked;
|
2026-04-26 05:20:47 +07:00
|
|
|
|
|
2026-04-29 13:10:00 +07:00
|
|
|
|
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;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-04-26 05:20:47 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
if (_chatInput != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_chatInput.RegisterCallback<KeyDownEvent>(OnChatKeyDown, TrickleDown.TrickleDown);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-30 01:30:58 +07:00
|
|
|
|
// Đăng ký sự kiện từ Spawner
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (BasicSpawner.Instance != null)
|
2026-04-28 19:04:09 +07:00
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
RegisterSpawnerEvents();
|
2026-04-30 01:30:58 +07:00
|
|
|
|
_ = BasicSpawner.Instance.StartLobby();
|
2026-04-28 19:04:09 +07:00
|
|
|
|
}
|
2026-04-30 00:55:16 +07:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
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; };
|
2026-04-30 15:08:19 +07:00
|
|
|
|
BasicSpawner.Instance.OnJoinStartedEvent += () => { };
|
2026-04-30 01:30:58 +07:00
|
|
|
|
_ = BasicSpawner.Instance.StartLobby();
|
2026-04-28 00:07:42 +07:00
|
|
|
|
}
|
2026-04-26 05:20:47 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
private void OnChatKeyDown(KeyDownEvent evt)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)
|
|
|
|
|
|
{
|
|
|
|
|
|
evt.StopImmediatePropagation();
|
|
|
|
|
|
evt.PreventDefault();
|
|
|
|
|
|
|
|
|
|
|
|
string msg = _chatInput.value.Trim();
|
|
|
|
|
|
if (!string.IsNullOrEmpty(msg) && PlayerDataManager.Instance != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var runner = Object.FindFirstObjectByType<NetworkRunner>();
|
|
|
|
|
|
if (runner != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
PlayerDataManager.Instance.RPC_SendChatMessage(runner.LocalPlayer, msg);
|
|
|
|
|
|
_chatInput.value = "";
|
|
|
|
|
|
// Re-focus after clearing
|
|
|
|
|
|
_chatInput.Focus();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnChatMessageReceived(PlayerRef sender, string message)
|
|
|
|
|
|
{
|
|
|
|
|
|
var runner = Object.FindFirstObjectByType<NetworkRunner>();
|
|
|
|
|
|
if (runner == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
// Kiểm tra sender là Host hay Guest
|
|
|
|
|
|
bool isHost = sender.PlayerId == 1; // Trong Host Mode, người tạo phòng luôn có ID 1
|
|
|
|
|
|
|
|
|
|
|
|
if (isHost)
|
|
|
|
|
|
{
|
|
|
|
|
|
ShowChatBubble(_hostChatBox, _hostChatMessage, message);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ShowChatBubble(_guestChatBox, _guestChatMessage, message);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async void ShowChatBubble(VisualElement box, Label label, string msg)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (box == null || label == null) return;
|
|
|
|
|
|
label.text = msg;
|
|
|
|
|
|
box.style.display = DisplayStyle.Flex;
|
|
|
|
|
|
await Task.Delay(4000);
|
|
|
|
|
|
if (label.text == msg) // Chỉ ẩn nếu chưa có tin nhắn mới đè lên
|
|
|
|
|
|
box.style.display = DisplayStyle.None;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-28 19:04:09 +07:00
|
|
|
|
public void SetRoomTemplate(VisualTreeAsset template) => _roomItemTemplate = template;
|
|
|
|
|
|
|
2026-04-29 13:10:00 +07:00
|
|
|
|
public override async Task PlayTransitionIn()
|
|
|
|
|
|
{
|
|
|
|
|
|
await base.PlayTransitionIn();
|
|
|
|
|
|
ShowJoin();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-28 00:07:42 +07:00
|
|
|
|
public void ShowJoin()
|
|
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.Flex;
|
|
|
|
|
|
if (_createContainer != null) _createContainer.style.display = DisplayStyle.None;
|
|
|
|
|
|
if (_loungeContainer != null) _loungeContainer.style.display = DisplayStyle.None;
|
2026-04-30 01:30:58 +07:00
|
|
|
|
_ = BasicSpawner.Instance?.StartLobby();
|
2026-04-26 05:20:47 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-28 00:07:42 +07:00
|
|
|
|
public void ShowCreate()
|
2026-04-26 05:20:47 +07:00
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.None;
|
|
|
|
|
|
if (_createContainer != null) _createContainer.style.display = DisplayStyle.Flex;
|
2026-04-25 18:20:16 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 13:10:00 +07:00
|
|
|
|
private void ShowLounge(string roomName)
|
|
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.None;
|
|
|
|
|
|
if (_createContainer != null) _createContainer.style.display = DisplayStyle.None;
|
|
|
|
|
|
if (_loungeContainer != null) _loungeContainer.style.display = DisplayStyle.Flex;
|
2026-04-30 15:08:19 +07:00
|
|
|
|
if (_loungeRoomName != null) _loungeRoomName.text = roomName.ToUpper();
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 00:55:16 +07:00
|
|
|
|
_playerDataManager = Object.FindFirstObjectByType<PlayerDataManager>();
|
2026-04-30 15:08:19 +07:00
|
|
|
|
if (_playerDataManager != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_playerDataManager.OnChatMessageReceived += OnChatMessageReceived;
|
|
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-28 19:04:09 +07:00
|
|
|
|
private async void OnCreateRoomClicked()
|
2026-04-25 18:20:16 +07:00
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
var spawner = BasicSpawner.Instance;
|
2026-04-30 01:30:58 +07:00
|
|
|
|
if (spawner == null) return;
|
2026-04-30 00:55:16 +07:00
|
|
|
|
|
|
|
|
|
|
string id = _roomIDInput != null && !string.IsNullOrEmpty(_roomIDInput.value)
|
|
|
|
|
|
? _roomIDInput.value.Trim()
|
|
|
|
|
|
: Random.Range(1000, 9999).ToString();
|
2026-04-28 19:04:09 +07:00
|
|
|
|
|
2026-04-30 00:55:16 +07:00
|
|
|
|
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;
|
2026-04-28 19:04:09 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
bool success = await spawner.StartHost(id, name, pass);
|
2026-04-30 01:30:58 +07:00
|
|
|
|
if (success) ShowLounge(name);
|
2026-04-26 05:20:47 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-28 19:04:09 +07:00
|
|
|
|
private void UpdateRoomList(List<SessionInfo> sessions)
|
2026-04-26 05:20:47 +07:00
|
|
|
|
{
|
2026-04-29 13:10:00 +07:00
|
|
|
|
if (_roomList == null) return;
|
2026-04-28 19:04:09 +07:00
|
|
|
|
_roomList.Clear();
|
|
|
|
|
|
foreach (var session in sessions)
|
2026-04-28 00:07:42 +07:00
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (_roomItemTemplate == null) continue;
|
2026-04-28 19:04:09 +07:00
|
|
|
|
var item = _roomItemTemplate.Instantiate();
|
2026-04-30 15:08:19 +07:00
|
|
|
|
|
|
|
|
|
|
// Hiển thị tên phòng thân thiện nếu có
|
|
|
|
|
|
string displayName = session.Name;
|
|
|
|
|
|
if (session.Properties.TryGetValue("rn", out var rnProp))
|
|
|
|
|
|
{
|
|
|
|
|
|
displayName = rnProp;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
item.Q<Label>("RoomName").text = displayName;
|
2026-04-28 19:04:09 +07:00
|
|
|
|
item.Q<Label>("PlayerCount").text = $"{session.PlayerCount}/{session.MaxPlayers}";
|
|
|
|
|
|
|
2026-04-29 01:04:28 +07:00
|
|
|
|
bool needsPass = session.Properties.ContainsKey("pw");
|
2026-04-30 00:55:16 +07:00
|
|
|
|
var lockIcon = item.Q<Label>("LockIcon");
|
|
|
|
|
|
if (lockIcon != null) lockIcon.style.display = needsPass ? DisplayStyle.Flex : DisplayStyle.None;
|
2026-04-28 19:04:09 +07:00
|
|
|
|
|
|
|
|
|
|
var joinBtn = item.Q<Button>("JoinBtn");
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (joinBtn != null) joinBtn.clicked += () => OnRoomItemClicked(session);
|
2026-04-28 19:04:09 +07:00
|
|
|
|
|
|
|
|
|
|
_roomList.Add(item);
|
2026-04-28 00:07:42 +07:00
|
|
|
|
}
|
2026-04-25 18:20:16 +07:00
|
|
|
|
}
|
2026-04-28 19:04:09 +07:00
|
|
|
|
|
2026-04-30 00:55:16 +07:00
|
|
|
|
private async void OnRoomItemClicked(SessionInfo session)
|
2026-04-28 19:04:09 +07:00
|
|
|
|
{
|
2026-04-29 13:10:00 +07:00
|
|
|
|
bool needsPass = session.Properties.ContainsKey("pw");
|
|
|
|
|
|
if (needsPass)
|
|
|
|
|
|
{
|
|
|
|
|
|
_selectedSession = session;
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (_passOverlay != null) _passOverlay.style.display = DisplayStyle.Flex;
|
|
|
|
|
|
if (_joinPassError != null) _joinPassError.style.display = DisplayStyle.None;
|
|
|
|
|
|
if (_joinPassInput != null) _joinPassInput.value = "";
|
2026-04-29 13:10:00 +07:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
await JoinRoom(session.Name, null);
|
2026-04-29 13:10:00 +07:00
|
|
|
|
}
|
2026-04-28 19:04:09 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async void OnConfirmPasswordClicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_selectedSession == null) return;
|
2026-04-30 00:55:16 +07:00
|
|
|
|
string pass = _joinPassInput != null ? _joinPassInput.value : "";
|
|
|
|
|
|
if (_passOverlay != null) _passOverlay.style.display = DisplayStyle.None;
|
2026-04-29 13:10:00 +07:00
|
|
|
|
await JoinRoom(_selectedSession.Name, pass);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async Task JoinRoom(string sessionName, string password)
|
|
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (BasicSpawner.Instance != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
bool success = await BasicSpawner.Instance.StartClient(sessionName, password);
|
|
|
|
|
|
if (success) ShowLounge(sessionName);
|
|
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnReadyClicked()
|
|
|
|
|
|
{
|
2026-04-30 15:08:19 +07:00
|
|
|
|
var runner = Object.FindFirstObjectByType<NetworkRunner>();
|
|
|
|
|
|
if (runner != null && _playerDataManager != null)
|
2026-04-29 13:10:00 +07:00
|
|
|
|
{
|
2026-04-30 15:08:19 +07:00
|
|
|
|
if (_playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData))
|
2026-04-29 13:10:00 +07:00
|
|
|
|
{
|
|
|
|
|
|
_playerDataManager.RPC_SetReady(runner.LocalPlayer, !myData.IsReady);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnStartClicked()
|
|
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
BasicSpawner.Instance?.StartGame();
|
2026-04-29 13:10:00 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnLeaveLoungeClicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
var runner = Object.FindFirstObjectByType<NetworkRunner>();
|
2026-04-30 15:08:19 +07:00
|
|
|
|
if (runner != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
runner.Shutdown();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (_playerDataManager != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_playerDataManager.OnChatMessageReceived -= OnChatMessageReceived;
|
|
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
ShowJoin();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Update()
|
|
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (_loungeContainer != null && _loungeContainer.style.display == DisplayStyle.Flex)
|
2026-04-29 13:10:00 +07:00
|
|
|
|
{
|
|
|
|
|
|
UpdateLoungeUI();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateLoungeUI()
|
|
|
|
|
|
{
|
2026-04-30 15:08:19 +07:00
|
|
|
|
var runner = Object.FindFirstObjectByType<NetworkRunner>();
|
|
|
|
|
|
if (runner == null) return;
|
|
|
|
|
|
|
2026-04-29 13:10:00 +07:00
|
|
|
|
if (_playerDataManager == null)
|
|
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
_playerDataManager = Object.FindFirstObjectByType<PlayerDataManager>();
|
2026-04-30 15:08:19 +07:00
|
|
|
|
if (_playerDataManager != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_playerDataManager.OnChatMessageReceived += OnChatMessageReceived;
|
|
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
if (_playerDataManager == null || !_playerDataManager.Object.IsValid) return;
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
PlayerRef hostRef = PlayerRef.None;
|
|
|
|
|
|
PlayerRef guestRef = PlayerRef.None;
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
foreach (var p in runner.ActivePlayers)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (runner.IsPlayerServer(p))
|
2026-04-30 00:55:16 +07:00
|
|
|
|
{
|
2026-04-30 15:08:19 +07:00
|
|
|
|
hostRef = p;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
guestRef = p;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-30 00:55:16 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Update Room Name for Guest
|
|
|
|
|
|
if (runner.SessionInfo != null && runner.SessionInfo.Properties.TryGetValue("rn", out var rnProp))
|
|
|
|
|
|
{
|
|
|
|
|
|
_loungeRoomName.text = rnProp.ToString().ToUpper();
|
|
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Update Host UI
|
|
|
|
|
|
if (hostRef != PlayerRef.None && _playerDataManager.TryGetPlayerMetaData(hostRef, out var hostData))
|
|
|
|
|
|
{
|
|
|
|
|
|
_hostNameLabel.text = hostData.Name.ToString().ToUpper();
|
|
|
|
|
|
_hostStatusLabel.text = hostData.IsReady ? "READY" : "NOT READY";
|
|
|
|
|
|
_hostStatusLabel.style.color = hostData.IsReady ? Color.green : Color.red;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (hostRef != PlayerRef.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
_hostNameLabel.text = "SYNCING...";
|
|
|
|
|
|
_hostStatusLabel.text = "-";
|
|
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Update Guest UI
|
|
|
|
|
|
if (guestRef != PlayerRef.None && _playerDataManager.TryGetPlayerMetaData(guestRef, out var guestData))
|
|
|
|
|
|
{
|
|
|
|
|
|
_guestNameLabel.text = guestData.Name.ToString().ToUpper();
|
|
|
|
|
|
_guestStatusLabel.text = guestData.IsReady ? "READY" : "NOT READY";
|
|
|
|
|
|
_guestStatusLabel.style.color = guestData.IsReady ? Color.green : Color.red;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (runner.ActivePlayers.Count() >= 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
_guestNameLabel.text = "SYNCING...";
|
|
|
|
|
|
_guestStatusLabel.text = "-";
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
_guestNameLabel.text = "WAITING...";
|
|
|
|
|
|
_guestStatusLabel.text = "-";
|
|
|
|
|
|
_guestStatusLabel.style.color = Color.gray;
|
|
|
|
|
|
}
|
2026-04-30 00:55:16 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Start Button visibility logic
|
|
|
|
|
|
bool allReady = true;
|
|
|
|
|
|
int playerCount = 0;
|
|
|
|
|
|
foreach (var p in runner.ActivePlayers)
|
|
|
|
|
|
{
|
|
|
|
|
|
playerCount++;
|
|
|
|
|
|
if (_playerDataManager.TryGetPlayerMetaData(p, out var data))
|
|
|
|
|
|
{
|
2026-04-30 00:55:16 +07:00
|
|
|
|
if (!data.IsReady) allReady = false;
|
|
|
|
|
|
}
|
2026-04-30 15:08:19 +07:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
allReady = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 15:08:19 +07:00
|
|
|
|
bool isHost = runner.LocalPlayer == hostRef;
|
|
|
|
|
|
|
|
|
|
|
|
if (_startBtn != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_startBtn.style.display = isHost ? DisplayStyle.Flex : DisplayStyle.None;
|
|
|
|
|
|
_startBtn.SetEnabled(allReady && playerCount >= 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_readyBtn != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData))
|
2026-04-30 00:55:16 +07:00
|
|
|
|
{
|
2026-04-30 15:08:19 +07:00
|
|
|
|
// Style for Ready Button
|
|
|
|
|
|
if (myData.IsReady)
|
|
|
|
|
|
{
|
|
|
|
|
|
_readyBtn.text = "UNREADY";
|
|
|
|
|
|
_readyBtn.style.backgroundColor = new StyleColor(Color.green);
|
|
|
|
|
|
_readyBtn.style.color = new StyleColor(Color.black);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
_readyBtn.text = "READY UP";
|
|
|
|
|
|
_readyBtn.style.backgroundColor = new StyleColor(new Color(0.2f, 0.2f, 0.2f, 0.8f));
|
|
|
|
|
|
_readyBtn.style.color = new StyleColor(Color.white);
|
|
|
|
|
|
}
|
2026-04-30 00:55:16 +07:00
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
}
|
2026-04-30 00:55:16 +07:00
|
|
|
|
}
|
2026-04-29 13:10:00 +07:00
|
|
|
|
|
2026-04-30 00:55:16 +07:00
|
|
|
|
private async void Invoke(string methodName, float delay)
|
|
|
|
|
|
{
|
|
|
|
|
|
await Task.Delay((int)(delay * 1000));
|
|
|
|
|
|
if (methodName == nameof(RegisterSpawnerEvents)) RegisterSpawnerEvents();
|
2026-04-28 19:04:09 +07:00
|
|
|
|
}
|
2026-04-25 18:20:16 +07:00
|
|
|
|
}
|
|
|
|
|
|
}
|