Initial commit: Client Doc docs Server Tools

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ud18010
2026-07-10 10:24:29 +08:00
co-authored by Cursor
commit 7e35d8da31
3374 changed files with 680813 additions and 0 deletions
@@ -0,0 +1,419 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace XGame
{
// 匹配大厅运行时控制器。沿用 AuthRegisterLoginController 模式:
// 按节点名缓存控件、克隆模板行、回调 Lua。只传基本类型跨 XLua。
public class GameLobbyController : MonoBehaviour
{
private Transform listGames;
private GameObject itemTemplate;
private TMP_Text statusText;
private RectTransform panelLobby;
private RectTransform collapseButtonRect;
private Button collapseButton;
private TMP_Text collapseText;
private GameObject titleObject;
private GameObject scrollObject;
private Vector2 expandedPanelSize;
private Vector2 expandedButtonPosition;
private bool hasCollapseMetrics;
private bool leftLayoutApplied;
private bool rootMatchButtonBound;
private bool collapsed;
private string currentStatus = string.Empty;
private string luaModule = "client/baseworld";
public Action<string> OnMatch;
private const float LobbyPanelWidth = 520f;
private const float LobbyPanelHeight = 296f;
private const float LobbyPanelLeft = 24f;
private const float LobbyPanelTop = -24f;
private const float CollapsedPanelWidth = 56f;
private void Awake()
{
CacheControls();
}
public void Bind(string module)
{
if (!string.IsNullOrEmpty(module))
{
luaModule = module;
}
}
// 清空旧克隆行
public void BeginGames()
{
CacheControls();
if (listGames == null)
{
return;
}
for (int i = listGames.childCount - 1; i >= 0; i--)
{
Transform child = listGames.GetChild(i);
if (itemTemplate != null && child == itemTemplate.transform)
{
continue;
}
Destroy(child.gameObject);
}
}
// 逐行追加。gameId 按行捕获用于点击回调
public void AddGame(string gameId, string name, string players)
{
CacheControls();
if (itemTemplate == null || listGames == null)
{
return;
}
GameObject row = Instantiate(itemTemplate, listGames);
row.name = "Item_Game_" + gameId;
row.SetActive(true);
SetChildText(row.transform, "Txt_GameName", name);
SetChildText(row.transform, "Txt_Players", players);
Transform btnTf = row.transform.FindTransform("Btn_Match");
if (btnTf != null)
{
Button btn = btnTf.GetComponent<Button>();
if (btn != null)
{
string captured = gameId;
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => OnMatch?.Invoke(captured));
}
}
}
public void EndGames()
{
}
public void SetStatus(string message)
{
CacheControls();
currentStatus = message ?? string.Empty;
if (statusText == null)
{
return;
}
statusText.text = currentStatus;
statusText.gameObject.SetActive(!collapsed && !string.IsNullOrEmpty(currentStatus));
}
public void Close()
{
Destroy(gameObject);
}
private void CacheControls()
{
if (panelLobby == null)
{
Transform t = transform.FindTransform("Panel_Lobby");
panelLobby = t == null ? null : t.GetComponent<RectTransform>();
}
EnsureCollapseButton();
if (collapseButton == null)
{
Transform t = transform.FindTransform("Btn_Collapse");
if (t != null)
{
collapseButtonRect = t.GetComponent<RectTransform>();
collapseButton = t.GetComponent<Button>();
if (collapseButton != null)
{
collapseButton.onClick.RemoveAllListeners();
collapseButton.onClick.AddListener(ToggleCollapsed);
}
}
}
if (collapseText == null)
{
Transform t = transform.FindTransform("Txt_Collapse");
collapseText = t == null ? null : t.GetComponent<TMP_Text>();
}
if (titleObject == null)
{
Transform t = transform.FindTransform("Txt_Title");
titleObject = t == null ? null : t.gameObject;
}
if (scrollObject == null)
{
Transform t = transform.FindTransform("Scroll_Games");
scrollObject = t == null ? null : t.gameObject;
}
if (listGames == null)
{
listGames = transform.FindTransform("List_Games");
}
if (itemTemplate == null)
{
Transform t = transform.FindTransform("Item_Game");
itemTemplate = t == null ? null : t.gameObject;
}
if (statusText == null)
{
Transform t = transform.FindTransform("Txt_Status");
statusText = t == null ? null : t.GetComponent<TMP_Text>();
}
BindRootMatchButton();
ApplyLeftDockLayout();
if (!hasCollapseMetrics && panelLobby != null && collapseButtonRect != null)
{
expandedPanelSize = panelLobby.sizeDelta;
expandedButtonPosition = collapseButtonRect.anchoredPosition;
hasCollapseMetrics = true;
ApplyCollapsedState();
}
}
private void BindRootMatchButton()
{
if (rootMatchButtonBound)
{
return;
}
Transform matchButton = transform.FindTransform("Btn_Match");
if (matchButton == null || itemTemplate != null && matchButton.IsChildOf(itemTemplate.transform))
{
return;
}
Button btn = matchButton.GetComponent<Button>();
if (btn == null)
{
return;
}
rootMatchButtonBound = true;
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => OnMatch?.Invoke(string.Empty));
}
private void EnsureCollapseButton()
{
if (transform.FindTransform("Btn_Collapse") != null)
{
return;
}
Transform parent = panelLobby != null && panelLobby.parent != null ? panelLobby.parent : transform;
GameObject buttonGo = new GameObject("Btn_Collapse", typeof(RectTransform), typeof(Image), typeof(Button));
buttonGo.transform.SetParent(parent, false);
RectTransform rt = buttonGo.GetComponent<RectTransform>();
rt.anchorMin = new Vector2(0f, 1f);
rt.anchorMax = new Vector2(0f, 1f);
rt.pivot = new Vector2(0f, 1f);
rt.anchoredPosition = new Vector2(LobbyPanelLeft + LobbyPanelWidth, LobbyPanelTop);
rt.sizeDelta = new Vector2(48f, 72f);
Image img = buttonGo.GetComponent<Image>();
Image matchImage = null;
Transform matchButton = transform.FindTransform("Btn_Match");
if (matchButton != null)
{
matchImage = matchButton.GetComponent<Image>();
}
img.sprite = matchImage != null ? matchImage.sprite : null;
img.type = matchImage != null ? matchImage.type : Image.Type.Sliced;
img.color = new Color(0.239f, 0.482f, 1f, 1f);
img.raycastTarget = true;
GameObject textGo = new GameObject("Txt_Collapse", typeof(RectTransform), typeof(TextMeshProUGUI));
textGo.transform.SetParent(buttonGo.transform, false);
RectTransform textRt = textGo.GetComponent<RectTransform>();
textRt.anchorMin = Vector2.zero;
textRt.anchorMax = Vector2.one;
textRt.pivot = new Vector2(0.5f, 0.5f);
textRt.offsetMin = Vector2.zero;
textRt.offsetMax = Vector2.zero;
TextMeshProUGUI text = textGo.GetComponent<TextMeshProUGUI>();
text.text = "<";
text.fontSize = 34f;
text.fontStyle = FontStyles.Bold;
text.alignment = TextAlignmentOptions.Center;
text.color = Color.white;
text.raycastTarget = false;
}
private void ApplyLeftDockLayout()
{
if (leftLayoutApplied)
{
return;
}
leftLayoutApplied = true;
if (panelLobby != null)
{
panelLobby.anchorMin = new Vector2(0f, 1f);
panelLobby.anchorMax = new Vector2(0f, 1f);
panelLobby.pivot = new Vector2(0f, 1f);
panelLobby.anchoredPosition = new Vector2(LobbyPanelLeft, LobbyPanelTop);
panelLobby.sizeDelta = new Vector2(LobbyPanelWidth, LobbyPanelHeight);
}
if (collapseButtonRect != null)
{
collapseButtonRect.anchorMin = new Vector2(0f, 1f);
collapseButtonRect.anchorMax = new Vector2(0f, 1f);
collapseButtonRect.pivot = new Vector2(0f, 1f);
collapseButtonRect.anchoredPosition = new Vector2(LobbyPanelLeft + LobbyPanelWidth, LobbyPanelTop);
collapseButtonRect.sizeDelta = new Vector2(48f, 72f);
}
SetRect("Txt_Title", new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -14f), new Vector2(448f, 36f));
SetOffsets("Scroll_Games", new Vector2(16f, 52f), new Vector2(-16f, -58f));
SetRect("Txt_Status", new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 16f), new Vector2(448f, 28f));
SetRect("Item_Game", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(0f, 76f));
SetLayoutElement("Item_Game", 76f);
SetRect("Txt_GameName", new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(18f, 12f), new Vector2(280f, 28f));
SetRect("Txt_Players", new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(18f, -14f), new Vector2(280f, 22f));
SetRect("Btn_Match", new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-10f, 0f), new Vector2(104f, 46f));
Transform titleText = transform.FindTransform("Txt_Title");
if (titleText != null)
{
TMP_Text text = titleText.GetComponent<TMP_Text>();
if (text != null)
{
text.fontSize = 28f;
}
}
Transform gameNameText = transform.FindTransform("Txt_GameName");
if (gameNameText != null)
{
TMP_Text text = gameNameText.GetComponent<TMP_Text>();
if (text != null)
{
text.fontSize = 22f;
}
}
Transform matchText = transform.FindTransform("Txt_Match");
if (matchText != null)
{
TMP_Text text = matchText.GetComponent<TMP_Text>();
if (text != null)
{
text.fontSize = 24f;
}
}
}
private void ToggleCollapsed()
{
collapsed = !collapsed;
ApplyCollapsedState();
}
private void ApplyCollapsedState()
{
if (!hasCollapseMetrics)
{
return;
}
if (panelLobby != null)
{
panelLobby.sizeDelta = collapsed ? new Vector2(CollapsedPanelWidth, expandedPanelSize.y) : expandedPanelSize;
}
if (collapseButtonRect != null)
{
collapseButtonRect.anchoredPosition = collapsed
? new Vector2(panelLobby != null ? panelLobby.anchoredPosition.x + CollapsedPanelWidth : LobbyPanelLeft + CollapsedPanelWidth, expandedButtonPosition.y)
: expandedButtonPosition;
}
if (collapseText != null)
{
collapseText.text = collapsed ? ">" : "<";
}
if (titleObject != null)
{
titleObject.SetActive(!collapsed);
}
if (scrollObject != null)
{
scrollObject.SetActive(!collapsed);
}
if (statusText != null)
{
statusText.gameObject.SetActive(!collapsed && !string.IsNullOrEmpty(currentStatus));
}
}
private void SetRect(string nodeName, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 anchoredPosition, Vector2 sizeDelta)
{
Transform t = transform.FindTransform(nodeName);
if (t == null)
{
return;
}
RectTransform rt = t.GetComponent<RectTransform>();
if (rt == null)
{
return;
}
rt.anchorMin = anchorMin;
rt.anchorMax = anchorMax;
rt.pivot = pivot;
rt.anchoredPosition = anchoredPosition;
rt.sizeDelta = sizeDelta;
}
private void SetOffsets(string nodeName, Vector2 offsetMin, Vector2 offsetMax)
{
Transform t = transform.FindTransform(nodeName);
if (t == null)
{
return;
}
RectTransform rt = t.GetComponent<RectTransform>();
if (rt == null)
{
return;
}
rt.anchorMin = Vector2.zero;
rt.anchorMax = Vector2.one;
rt.pivot = new Vector2(0.5f, 0.5f);
rt.offsetMin = offsetMin;
rt.offsetMax = offsetMax;
}
private void SetLayoutElement(string nodeName, float height)
{
Transform t = transform.FindTransform(nodeName);
if (t == null)
{
return;
}
LayoutElement layout = t.GetComponent<LayoutElement>();
if (layout == null)
{
return;
}
layout.minHeight = height;
layout.preferredHeight = height;
}
private static void SetChildText(Transform root, string childName, string text)
{
Transform t = root.FindTransform(childName);
if (t != null)
{
TMP_Text label = t.GetComponent<TMP_Text>();
if (label != null)
{
label.text = text ?? string.Empty;
}
}
}
}
}