Files
bansonic_beta_main/Assets/scripts/roomSystem/roomDetails.cs
T

545 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using Bansonic;
using GameServer.Client;
using UnityEngine;
using UnityEngine.UI;
public class roomDetails : MonoBehaviour
{
[Header("room Info")]
public Text roomID;
public Text roomRemainTime;
public Button quitRoom;
public Button quitRoom2;
public Button getReady;
public Button showRoomRankingList;
[Header("song info")]
public Text thisSongName;
public Text thisSongDifficulty;
[Header("objs")]
public GameObject roommatePrefab;
public Transform roommateParent;
[Header("sprites")]
public Sprite[] btmSprites;
private ArenaRoomService _service;
private Coroutine _countdownRoutine;
private GameObject _roomRankingPrefabTemplate;
private Transform _roomRankingSpawnParent;
private GameObject _spawnedRoomRankingInstance;
public void ConfigureRoomRanking(GameObject roomRankingPrefab, Transform roomRankingSpawnParent)
{
_roomRankingPrefabTemplate = roomRankingPrefab;
_roomRankingSpawnParent = roomRankingSpawnParent;
}
public void Bind(ArenaRoomService service)
{
_service = service;
if (_service == null)
{
Debug.LogWarning("[roomDetails] ArenaRoomService is missing.");
return;
}
_service.OnRoomSnapshotChanged -= HandleRoomSnapshotChanged;
_service.OnRoomSnapshotChanged += HandleRoomSnapshotChanged;
_service.OnKicked -= HandleKicked;
_service.OnKicked += HandleKicked;
_service.OnRoomDismissed -= HandleRoomDismissed;
_service.OnRoomDismissed += HandleRoomDismissed;
if (quitRoom != null)
{
quitRoom.onClick.RemoveListener(OnQuitClicked);
quitRoom.onClick.AddListener(OnQuitClicked);
}
if (quitRoom2 != null)
{
quitRoom2.onClick.RemoveListener(OnQuitClicked);
quitRoom2.onClick.AddListener(OnQuitClicked);
}
if (getReady != null)
{
getReady.onClick.RemoveListener(OnReadyButtonClicked);
getReady.onClick.AddListener(OnReadyButtonClicked);
}
if (showRoomRankingList != null)
{
showRoomRankingList.onClick.RemoveListener(OnShowRoomRankingClicked);
showRoomRankingList.onClick.AddListener(OnShowRoomRankingClicked);
}
Refresh(_service.CurrentRoom);
}
private void OnDestroy()
{
if (_service != null)
{
_service.OnRoomSnapshotChanged -= HandleRoomSnapshotChanged;
_service.OnKicked -= HandleKicked;
_service.OnRoomDismissed -= HandleRoomDismissed;
}
if (quitRoom != null)
{
quitRoom.onClick.RemoveListener(OnQuitClicked);
}
if (quitRoom2 != null)
{
quitRoom2.onClick.RemoveListener(OnQuitClicked);
}
if (getReady != null)
{
getReady.onClick.RemoveListener(OnReadyButtonClicked);
}
if (showRoomRankingList != null)
{
showRoomRankingList.onClick.RemoveListener(OnShowRoomRankingClicked);
}
if (_countdownRoutine != null)
{
StopCoroutine(_countdownRoutine);
_countdownRoutine = null;
}
if (_spawnedRoomRankingInstance != null)
{
Destroy(_spawnedRoomRankingInstance);
_spawnedRoomRankingInstance = null;
}
}
private void HandleRoomSnapshotChanged(ArenaRoomSnapshot snapshot)
{
if (snapshot == null)
{
Destroy(gameObject);
return;
}
Refresh(snapshot);
}
private void HandleKicked(string kickedSteamId, string bySteamId)
{
Destroy(gameObject);
}
private void HandleRoomDismissed(string roomCode, string bySteamId)
{
Destroy(gameObject);
}
private async void OnQuitClicked()
{
if (_service == null)
{
Destroy(gameObject);
return;
}
try
{
string localSteamId = NetworkManager.Instance != null ? NetworkManager.Instance.SteamId : string.Empty;
bool localIsHost = IsLocalHost(_service.CurrentRoom, localSteamId);
if (localIsHost)
{
await _service.DismissRoom();
}
else
{
await _service.LeaveRoom();
}
}
catch (Exception ex)
{
Debug.LogWarning($"[roomDetails] Leave room failed: {ex.Message}");
}
finally
{
Destroy(gameObject);
}
}
private void Refresh(ArenaRoomSnapshot snapshot)
{
if (snapshot == null)
{
return;
}
if (roomID != null)
{
roomID.text = snapshot.room_code;
}
if (thisSongName != null)
{
thisSongName.text = !string.IsNullOrWhiteSpace(snapshot.song_name)
? snapshot.song_name
: snapshot.song_id ?? string.Empty;
}
if (thisSongDifficulty != null)
{
thisSongDifficulty.text = FormatDifficulty(snapshot.difficulty);
}
if (_countdownRoutine != null)
{
StopCoroutine(_countdownRoutine);
}
_countdownRoutine = StartCoroutine(UpdateRemainTime(snapshot));
UpdateQuitButtonTexts(snapshot);
UpdateReadyButton(snapshot);
RenderParticipants(snapshot);
}
private IEnumerator UpdateRemainTime(ArenaRoomSnapshot snapshot)
{
while (snapshot != null && roomRemainTime != null)
{
long nowUnix = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
long remainSeconds = Math.Max(0L, snapshot.expires_at_unix - nowUnix);
int remainMinutes = Mathf.CeilToInt(remainSeconds / 60f);
roomRemainTime.text = $"{remainMinutes}分钟内不开始游戏将自动关闭房间";
yield return new WaitForSeconds(1f);
}
}
private void RenderParticipants(ArenaRoomSnapshot snapshot)
{
if (roommateParent == null || roommatePrefab == null)
{
return;
}
for (int i = roommateParent.childCount - 1; i >= 0; i--)
{
Destroy(roommateParent.GetChild(i).gameObject);
}
string localSteamId = _service != null && NetworkManager.Instance != null
? NetworkManager.Instance.SteamId
: string.Empty;
bool localIsHost = IsLocalHost(snapshot, localSteamId);
if (snapshot.participants == null)
{
return;
}
for (int i = 0; i < snapshot.participants.Count; i++)
{
ArenaRoomParticipant participant = snapshot.participants[i];
GameObject item = Instantiate(roommatePrefab, roommateParent);
roomPrefab itemController = item.GetComponent<roomPrefab>();
if (itemController == null)
{
continue;
}
Sprite background = null;
if (participant != null && participant.is_host)
{
if (btmSprites != null && btmSprites.Length > 0)
{
background = btmSprites[0];
}
}
else if (btmSprites != null && btmSprites.Length > 1)
{
background = btmSprites[1];
}
itemController.Bind(participant, i + 1, localIsHost, localSteamId, background, HandleKickRequested);
}
}
private async void HandleKickRequested(string targetSteamId)
{
if (_service == null || string.IsNullOrWhiteSpace(targetSteamId))
{
return;
}
try
{
await _service.KickPlayer(targetSteamId);
}
catch (Exception ex)
{
Debug.LogWarning($"[roomDetails] Kick failed: {ex.Message}");
}
}
private async void OnReadyButtonClicked()
{
if (_service == null || _service.CurrentRoom == null)
{
return;
}
try
{
string localSteamId = NetworkManager.Instance != null ? NetworkManager.Instance.SteamId : string.Empty;
bool localIsHost = IsLocalHost(_service.CurrentRoom, localSteamId);
if (localIsHost)
{
if (CanHostStartGame(_service.CurrentRoom))
{
await _service.StartGame();
}
}
else
{
await _service.ToggleReady();
}
}
catch (Exception ex)
{
Debug.LogWarning($"[roomDetails] Ready/start failed: {ex.Message}");
}
}
private void OnShowRoomRankingClicked()
{
if (_service == null)
{
return;
}
GameObject template = _roomRankingPrefabTemplate;
Transform parent = _roomRankingSpawnParent != null ? _roomRankingSpawnParent : transform.parent;
if (template == null || parent == null)
{
Debug.LogWarning("[roomDetails] Room ranking prefab or parent is missing.");
return;
}
if (_spawnedRoomRankingInstance == null)
{
_spawnedRoomRankingInstance = Instantiate(template, parent, false);
RectTransform rect = _spawnedRoomRankingInstance.GetComponent<RectTransform>();
if (rect != null)
{
rect.localScale = Vector3.one;
rect.anchoredPosition3D = Vector3.zero;
}
}
rankingListPrefab ranking = _spawnedRoomRankingInstance.GetComponent<rankingListPrefab>();
if (ranking == null)
{
Debug.LogWarning("[roomDetails] Room ranking prefab is missing rankingListPrefab component.");
return;
}
ArenaRoomSnapshot snapshot = _service.CurrentRoom;
LeaderboardData roomRanking = _service.GetRoomRankingLeaderboardData();
string localSteamId = NetworkManager.Instance != null ? NetworkManager.Instance.SteamId : string.Empty;
ranking.BindRoomRanking(
snapshot != null ? snapshot.song_id : string.Empty,
snapshot != null ? snapshot.song_name : string.Empty,
roomRanking,
localSteamId);
}
private void UpdateQuitButtonTexts(ArenaRoomSnapshot snapshot)
{
string localSteamId = NetworkManager.Instance != null ? NetworkManager.Instance.SteamId : string.Empty;
bool localIsHost = IsLocalHost(snapshot, localSteamId);
string buttonText = localIsHost ? "解散房间" : "退出房间";
SetButtonText(quitRoom, buttonText);
SetButtonText(quitRoom2, buttonText);
}
private void UpdateReadyButton(ArenaRoomSnapshot snapshot)
{
if (getReady == null)
{
return;
}
string localSteamId = NetworkManager.Instance != null ? NetworkManager.Instance.SteamId : string.Empty;
bool localIsHost = IsLocalHost(snapshot, localSteamId);
int readyCount = CountReadyPlayers(snapshot);
int totalCount = snapshot != null
? Mathf.Max(snapshot.player_count, snapshot.participants != null ? snapshot.participants.Count : 0)
: 0;
bool roomStarted = IsRoomStarted(snapshot);
string buttonText;
bool interactable;
if (localIsHost)
{
buttonText = $"开始游戏({readyCount}/{totalCount}";
interactable = !roomStarted && CanHostStartGame(snapshot);
}
else
{
bool localReady = IsLocalReady(snapshot, localSteamId);
buttonText = localReady ? "取消准备" : "准备";
interactable = !roomStarted;
}
getReady.interactable = interactable;
SetButtonText(getReady, buttonText);
}
private static bool IsLocalHost(ArenaRoomSnapshot snapshot, string localSteamId)
{
if (snapshot == null || string.IsNullOrWhiteSpace(localSteamId))
{
return false;
}
if (string.Equals(snapshot.host_steam_id, localSteamId, StringComparison.Ordinal))
{
return true;
}
if (snapshot.participants == null)
{
return false;
}
foreach (ArenaRoomParticipant participant in snapshot.participants)
{
if (participant != null
&& string.Equals(participant.steam_id, localSteamId, StringComparison.Ordinal)
&& participant.is_host)
{
return true;
}
}
return false;
}
private static bool IsLocalReady(ArenaRoomSnapshot snapshot, string localSteamId)
{
if (snapshot == null || snapshot.participants == null || string.IsNullOrWhiteSpace(localSteamId))
{
return false;
}
foreach (ArenaRoomParticipant participant in snapshot.participants)
{
if (participant != null && string.Equals(participant.steam_id, localSteamId, StringComparison.Ordinal))
{
return participant.is_ready;
}
}
return false;
}
private static int CountReadyPlayers(ArenaRoomSnapshot snapshot)
{
if (snapshot == null || snapshot.participants == null)
{
return 0;
}
int count = 0;
foreach (ArenaRoomParticipant participant in snapshot.participants)
{
if (participant != null && participant.is_ready)
{
count++;
}
}
return count;
}
private static bool CanHostStartGame(ArenaRoomSnapshot snapshot)
{
if (snapshot == null || snapshot.participants == null || snapshot.participants.Count < 2)
{
return false;
}
foreach (ArenaRoomParticipant participant in snapshot.participants)
{
if (participant == null)
{
continue;
}
if (!participant.is_host && !participant.is_ready)
{
return false;
}
}
return true;
}
private static bool IsRoomStarted(ArenaRoomSnapshot snapshot)
{
if (snapshot == null || string.IsNullOrWhiteSpace(snapshot.status))
{
return false;
}
return string.Equals(snapshot.status, "STARTED", StringComparison.OrdinalIgnoreCase)
|| string.Equals(snapshot.status, "PLAYING", StringComparison.OrdinalIgnoreCase);
}
private static void SetButtonText(Button button, string text)
{
if (button == null)
{
return;
}
Text label = button.GetComponentInChildren<Text>(true);
if (label != null)
{
label.text = text;
}
}
private static string FormatDifficulty(string difficulty)
{
if (string.IsNullOrWhiteSpace(difficulty))
{
return string.Empty;
}
switch (difficulty.Trim().ToLowerInvariant())
{
case "ez":
return "EZ";
case "hd":
return "HD";
case "in":
return "IN";
case "im":
return "IM";
default:
return difficulty;
}
}
}