437 lines
18 KiB
C#
437 lines
18 KiB
C#
// Port of C++ DlgArrangeTeam - Arrange Team dialog (invite, kick, leave, list teammates, nearby players, pickup mode, make leader).
|
|
// Uses Unity UI: content RectTransforms + item prefab with DlgArrangeTeamListItem (text component, optional Button).
|
|
|
|
using System.Collections.Generic;
|
|
using BrewMonster;
|
|
using BrewMonster.Managers;
|
|
using BrewMonster.Network;
|
|
using BrewMonster.Scripts;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using TMPro;
|
|
|
|
namespace BrewMonster.UI
|
|
{
|
|
public class DlgArrangeTeam : AUIDialog
|
|
{
|
|
#region UI References
|
|
|
|
[Header("Teammates list (Unity UI)")]
|
|
[SerializeField] private RectTransform Content_Teammates;
|
|
[SerializeField] private GameObject TeammateItemPrefab;
|
|
|
|
[Header("Nearby players list (Unity UI)")]
|
|
[SerializeField] private RectTransform Content_Nearby;
|
|
[SerializeField] private GameObject NearbyItemPrefab;
|
|
|
|
[Header("Buttons")]
|
|
[SerializeField] private Button m_pBtn_Invite;
|
|
[SerializeField] private Button m_pBtn_Kick;
|
|
[SerializeField] private Button m_pBtn_Leave;
|
|
[SerializeField] private Button m_pBtn_Disband;
|
|
[SerializeField] private Button m_pBtn_MakeLeader;
|
|
[SerializeField] private Button m_pBtn_Refresh;
|
|
[SerializeField] private Button m_pBtn_Close;
|
|
|
|
[Header("Invite")]
|
|
[SerializeField] private TMP_InputField m_pInput_Name;
|
|
|
|
[Header("Pickup Mode")]
|
|
[SerializeField] private Toggle m_pChk_Random;
|
|
[SerializeField] private Toggle m_pChk_Free;
|
|
|
|
[Header("Profession filter (dropdown: trigger opens panel with multi-select toggles)")]
|
|
[SerializeField] private TMP_Dropdown m_pDropdown_Prof;
|
|
|
|
#endregion
|
|
|
|
private readonly List<DlgArrangeTeamListItem> m_TeammateItems = new List<DlgArrangeTeamListItem>();
|
|
private int m_selectedTeammateId;
|
|
|
|
public override void Awake()
|
|
{
|
|
base.Awake();
|
|
SetName("Win_ArrangeTeam");
|
|
#if UNITY_EDITOR
|
|
if (m_pBtn_Leave == null) Debug.LogWarning("[DlgArrangeTeam] m_pBtn_Leave is not assigned in Inspector. Assign the Leave button.");
|
|
if (m_pBtn_Disband == null) Debug.LogWarning("[DlgArrangeTeam] m_pBtn_Disband is not assigned in Inspector. Assign the Disband button.");
|
|
#endif
|
|
}
|
|
|
|
private new void Start()
|
|
{
|
|
BindButtonListeners();
|
|
}
|
|
|
|
public override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
BindButtonListeners();
|
|
}
|
|
|
|
public override void OnDisable()
|
|
{
|
|
UnbindButtonListeners();
|
|
base.OnDisable();
|
|
}
|
|
|
|
private void BindButtonListeners()
|
|
{
|
|
if (m_pBtn_Invite != null) { m_pBtn_Invite.onClick.RemoveListener(OnInvite); m_pBtn_Invite.onClick.AddListener(OnInvite); }
|
|
if (m_pBtn_Kick != null) { m_pBtn_Kick.onClick.RemoveListener(OnKick); m_pBtn_Kick.onClick.AddListener(OnKick); }
|
|
if (m_pBtn_Leave != null) { m_pBtn_Leave.onClick.RemoveListener(OnLeave); m_pBtn_Leave.onClick.AddListener(OnLeave); }
|
|
if (m_pBtn_Disband != null) { m_pBtn_Disband.onClick.RemoveListener(OnDisband); m_pBtn_Disband.onClick.AddListener(OnDisband); }
|
|
if (m_pBtn_MakeLeader != null) { m_pBtn_MakeLeader.onClick.RemoveListener(OnMakeLeader); m_pBtn_MakeLeader.onClick.AddListener(OnMakeLeader); }
|
|
if (m_pBtn_Refresh != null) { m_pBtn_Refresh.onClick.RemoveListener(OnRefresh); m_pBtn_Refresh.onClick.AddListener(OnRefresh); }
|
|
if (m_pChk_Random != null) m_pChk_Random.onValueChanged.AddListener(OnRandomToggled);
|
|
if (m_pChk_Free != null) m_pChk_Free.onValueChanged.AddListener(OnFreeToggled);
|
|
if (m_pBtn_Close != null) m_pBtn_Close.onClick.AddListener(CloseDialogue);
|
|
BindProfDropdown();
|
|
}
|
|
|
|
private void UnbindButtonListeners()
|
|
{
|
|
if (m_pBtn_Invite != null) m_pBtn_Invite.onClick.RemoveListener(OnInvite);
|
|
if (m_pBtn_Kick != null) m_pBtn_Kick.onClick.RemoveListener(OnKick);
|
|
if (m_pBtn_Leave != null) m_pBtn_Leave.onClick.RemoveListener(OnLeave);
|
|
if (m_pBtn_Disband != null) m_pBtn_Disband.onClick.RemoveListener(OnDisband);
|
|
if (m_pBtn_MakeLeader != null) m_pBtn_MakeLeader.onClick.RemoveListener(OnMakeLeader);
|
|
if (m_pBtn_Refresh != null) m_pBtn_Refresh.onClick.RemoveListener(OnRefresh);
|
|
if (m_pChk_Random != null) m_pChk_Random.onValueChanged.RemoveListener(OnRandomToggled);
|
|
if (m_pChk_Free != null) m_pChk_Free.onValueChanged.RemoveListener(OnFreeToggled);
|
|
if (m_pBtn_Close != null) m_pBtn_Close.onClick.RemoveListener(CloseDialogue);
|
|
UnbindProfDropdown();
|
|
CloseProfFilterPanel();
|
|
}
|
|
|
|
private void OnRandomToggled(bool on) { if (on) OnPickupModeChanged(1); }
|
|
private void OnFreeToggled(bool on) { if (on) OnPickupModeChanged(0); }
|
|
|
|
private void BindProfDropdown()
|
|
{
|
|
if (m_pDropdown_Prof == null) return;
|
|
m_pDropdown_Prof.onValueChanged.RemoveListener(OnProfessionDropdownChanged);
|
|
m_pDropdown_Prof.onValueChanged.AddListener(OnProfessionDropdownChanged);
|
|
}
|
|
|
|
private void UnbindProfDropdown()
|
|
{
|
|
if (m_pDropdown_Prof == null) return;
|
|
m_pDropdown_Prof.onValueChanged.RemoveListener(OnProfessionDropdownChanged);
|
|
}
|
|
|
|
private void OnProfessionDropdownChanged(int _)
|
|
{
|
|
UpdateProfDropdownCaption();
|
|
UpdateTeam(true);
|
|
}
|
|
|
|
private void CloseProfFilterPanel() { }
|
|
|
|
private void UpdateProfDropdownCaption()
|
|
{
|
|
if (m_pDropdown_Prof == null) return;
|
|
var set = GetSelectedProfessionSet();
|
|
string caption;
|
|
if (set == null) caption = "All";
|
|
else if (set.Count >= (int)Profession.NUM_PROFESSION) caption = "All";
|
|
else
|
|
{
|
|
var gameRun = EC_Game.GetGameRun();
|
|
var names = new List<string>();
|
|
foreach (int i in set)
|
|
{
|
|
string name = gameRun?.GetProfName(i);
|
|
names.Add(string.IsNullOrEmpty(name) ? $"Prof {i}" : name);
|
|
}
|
|
caption = string.Join(", ", names);
|
|
}
|
|
var label = m_pDropdown_Prof.captionText;
|
|
if (label != null) label.text = caption;
|
|
}
|
|
|
|
|
|
public override void OnShowDialogue()
|
|
{
|
|
EnsureProfDropdownHasCaption();
|
|
UpdateProfDropdownCaption();
|
|
CloseProfFilterPanel();
|
|
UpdateTeam(true);
|
|
}
|
|
|
|
private void EnsureProfDropdownHasCaption()
|
|
{
|
|
if (m_pDropdown_Prof == null) return;
|
|
if (m_pDropdown_Prof.options.Count != 0) return;
|
|
|
|
var opts = new List<string>();
|
|
opts.Add("All");
|
|
var gameRun = EC_Game.GetGameRun();
|
|
for (int i = 0; i < (int)Profession.NUM_PROFESSION; i++)
|
|
{
|
|
string name = gameRun?.GetProfName(i);
|
|
opts.Add(string.IsNullOrEmpty(name) ? $"Prof {i}" : name);
|
|
}
|
|
m_pDropdown_Prof.AddOptions(opts);
|
|
}
|
|
|
|
/// <summary>Selected profession filter: null = show all.</summary>
|
|
private HashSet<int> GetSelectedProfessionSet()
|
|
{
|
|
if (m_pDropdown_Prof == null) return null;
|
|
|
|
// Dropdown mapping:
|
|
// 0 = All (no filter)
|
|
// 1..NUM_PROFESSION = specific profession (value-1)
|
|
int v = m_pDropdown_Prof.value;
|
|
if (v <= 0) return null;
|
|
|
|
int prof = v - 1;
|
|
if (prof < 0 || prof >= (int)Profession.NUM_PROFESSION) return null;
|
|
|
|
return new HashSet<int> { prof };
|
|
}
|
|
|
|
/// <summary>Refresh teammate list, optional nearby list, and button states.</summary>
|
|
public bool UpdateTeam(bool bUpdateNear = false)
|
|
{
|
|
CECHostPlayer host = GetHostPlayer();
|
|
if (host == null) return true;
|
|
|
|
var team = host.GetTeam();
|
|
bool hasTeam = team != null;
|
|
int idHost = host.GetCharacterID();
|
|
bool isLeader = hasTeam && team.GetLeaderID() == idHost;
|
|
|
|
// Teammates list: clear and rebuild from prefab. Sort by each member's single profession, then by name.
|
|
ClearList(Content_Teammates, m_TeammateItems);
|
|
m_selectedTeammateId = 0;
|
|
if (Content_Teammates != null && TeammateItemPrefab != null && hasTeam)
|
|
{
|
|
var members = new List<CECTeamMember>();
|
|
int n = team.GetMemberNum();
|
|
for (int i = 0; i < n; i++)
|
|
{
|
|
var m = team.GetMemberByIndex(i);
|
|
if (m != null) members.Add(m);
|
|
}
|
|
members.Sort((a, b) => { int c = a.GetProfession().CompareTo(b.GetProfession()); if (c != 0) return c; return string.CompareOrdinal(a.GetName() ?? "", b.GetName() ?? ""); });
|
|
foreach (var m in members)
|
|
{
|
|
string mateName = m.GetName();
|
|
int cid = m.GetCharacterID();
|
|
if (!string.IsNullOrEmpty(mateName))
|
|
Debug.Log($"[DlgArrangeTeam] Teammate: {mateName} (id {cid})");
|
|
var item = CreateListItem(Content_Teammates, TeammateItemPrefab, mateName, cid, true, out var listItem);
|
|
if (listItem != null)
|
|
{
|
|
Debug.Log($"[DlgArrangeTeam] Set teammate item detail: level {m.GetLevel()}");
|
|
listItem.SetDetail(m.GetProfession());
|
|
m_TeammateItems.Add(listItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Nearby players list: filter by selected professions (multi-select); sort by each player's single profession, then by name
|
|
if (bUpdateNear && Content_Nearby != null)
|
|
{
|
|
var prefab = NearbyItemPrefab != null ? NearbyItemPrefab : TeammateItemPrefab;
|
|
ClearList(Content_Nearby, null);
|
|
var manPlayer = EC_ManMessageMono.Instance?.GetECManPlayer;
|
|
if (manPlayer != null && prefab != null)
|
|
{
|
|
HashSet<int> filterSet = GetSelectedProfessionSet();
|
|
var nearby = new List<(string name, int cid, int prof)>();
|
|
var otherIds = manPlayer.GetOtherPlayerCharacterIds();
|
|
foreach (int cid in otherIds)
|
|
{
|
|
if (hasTeam && team.GetMemberByID(cid) != null) continue;
|
|
var p = manPlayer.GetPlayer(cid, 0);
|
|
string name = p != null ? (p.GetName() ?? "") : "";
|
|
if (string.IsNullOrEmpty(name) && p?.gameObject != null && !string.IsNullOrEmpty(p.gameObject.name)) name = p.gameObject.name;
|
|
if (string.IsNullOrEmpty(name)) name = "Player_" + cid;
|
|
int prof = (p as CECPlayer) != null ? (p as CECPlayer).GetProfession() : 0;
|
|
if (filterSet != null && !filterSet.Contains(prof)) continue;
|
|
nearby.Add((name, cid, prof));
|
|
}
|
|
nearby.Sort((a, b) => { int c = a.prof.CompareTo(b.prof); if (c != 0) return c; return string.CompareOrdinal(a.name, b.name); });
|
|
foreach (var t in nearby)
|
|
{
|
|
Debug.Log($"[DlgArrangeTeam] Nearby: {t.name} (id {t.cid})");
|
|
CreateListItem(Content_Nearby, prefab, t.name, t.cid, false, out var listItem);
|
|
listItem.SetDetail(t.prof);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Button states
|
|
if (m_pBtn_Leave != null) m_pBtn_Leave.interactable = hasTeam;
|
|
if (m_pBtn_Disband != null) m_pBtn_Disband.interactable = hasTeam && isLeader;
|
|
if (m_pBtn_Kick != null) m_pBtn_Kick.interactable = hasTeam && isLeader;
|
|
if (m_pBtn_Invite != null) m_pBtn_Invite.interactable = isLeader;
|
|
if (m_pBtn_MakeLeader != null) m_pBtn_MakeLeader.interactable = hasTeam && isLeader;
|
|
if (m_pBtn_Refresh != null) m_pBtn_Refresh.interactable = true;
|
|
|
|
if (m_pChk_Random != null) m_pChk_Random.interactable = hasTeam && isLeader;
|
|
if (m_pChk_Free != null) m_pChk_Free.interactable = hasTeam && isLeader;
|
|
if (hasTeam && isLeader)
|
|
{
|
|
ushort pick = team.GetPickupFlag();
|
|
if (m_pChk_Random != null) m_pChk_Random.SetIsOnWithoutNotify(pick != 0);
|
|
if (m_pChk_Free != null) m_pChk_Free.SetIsOnWithoutNotify(pick == 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static void ClearList(RectTransform content, List<DlgArrangeTeamListItem> items)
|
|
{
|
|
if (content == null) return;
|
|
if (items != null) items.Clear();
|
|
for (int i = content.childCount - 1; i >= 0; i--)
|
|
{
|
|
var child = content.GetChild(i);
|
|
if (child != null && child.gameObject != null)
|
|
Destroy(child.gameObject);
|
|
}
|
|
}
|
|
|
|
private GameObject CreateListItem(RectTransform content, GameObject prefab, string displayName, int characterId, bool isTeammate, out DlgArrangeTeamListItem listItem)
|
|
{
|
|
listItem = null;
|
|
var go = Instantiate(prefab, content);
|
|
go.SetActive(true);
|
|
var comp = go.GetComponent<DlgArrangeTeamListItem>();
|
|
if (comp != null)
|
|
{
|
|
comp.Set(displayName, characterId);
|
|
listItem = comp;
|
|
if (isTeammate)
|
|
comp.SetClickCallback(OnTeammateItemSelected);
|
|
else
|
|
{
|
|
comp.SetClickCallback(OnNearbyItemSelected);
|
|
comp.SetInviteCallback(OnNearbyItemInvite);
|
|
}
|
|
}
|
|
return go;
|
|
}
|
|
|
|
private void OnTeammateItemSelected(DlgArrangeTeamListItem item)
|
|
{
|
|
m_selectedTeammateId = item.CharacterId;
|
|
foreach (var i in m_TeammateItems)
|
|
i.SetSelected(i == item);
|
|
}
|
|
|
|
private void OnNearbyItemSelected(DlgArrangeTeamListItem item)
|
|
{
|
|
if (m_pInput_Name != null)
|
|
m_pInput_Name.text = !string.IsNullOrEmpty(item.DisplayName) ? item.DisplayName : item.CharacterId.ToString();
|
|
}
|
|
|
|
private void OnNearbyItemInvite(DlgArrangeTeamListItem item)
|
|
{
|
|
if (item?.CharacterId > 0)
|
|
UnityGameSession.c2s_CmdTeamInvite(item.CharacterId);
|
|
}
|
|
|
|
/// <summary>Invite by name/ID in input field. Public so you can assign to Button.onClick in Inspector.</summary>
|
|
public void OnInvite()
|
|
{
|
|
CECHostPlayer host = GetHostPlayer();
|
|
if (host == null) return;
|
|
|
|
int idPlayer = ResolveInviteTarget();
|
|
if (idPlayer <= 0) return;
|
|
UnityGameSession.c2s_CmdTeamInvite(idPlayer);
|
|
}
|
|
|
|
private int ResolveInviteTarget()
|
|
{
|
|
if (m_pInput_Name == null || string.IsNullOrWhiteSpace(m_pInput_Name.text)) return 0;
|
|
string raw = m_pInput_Name.text.Trim();
|
|
if (int.TryParse(raw, out int id) && id > 0) return id;
|
|
var manPlayer = EC_ManMessageMono.Instance?.GetECManPlayer;
|
|
if (manPlayer == null) return 0;
|
|
var otherIds = manPlayer.GetOtherPlayerCharacterIds();
|
|
foreach (int cid in otherIds)
|
|
{
|
|
var p = manPlayer.GetPlayer(cid, 0);
|
|
string name = p?.GetName();
|
|
if (!string.IsNullOrEmpty(name) && string.Equals(name, raw, System.StringComparison.OrdinalIgnoreCase))
|
|
return cid;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>Kick selected teammate. Public so you can assign to Button.onClick in Inspector.</summary>
|
|
public void OnKick()
|
|
{
|
|
int idMember = GetSelectedTeammateId();
|
|
if (idMember <= 0)
|
|
{
|
|
Debug.Log("[DlgArrangeTeam] Kick: select a teammate first (click a row in the list).");
|
|
return;
|
|
}
|
|
Debug.Log($"[DlgArrangeTeam] Kick member id={idMember}");
|
|
UnityGameSession.c2s_CmdTeamKickMember(idMember);
|
|
}
|
|
|
|
/// <summary>Leave team. Public so you can assign to Button.onClick in Inspector.</summary>
|
|
public void OnLeave()
|
|
{
|
|
if (UnityGameSession.Instance == null)
|
|
{
|
|
Debug.LogWarning("[DlgArrangeTeam] OnLeave: UnityGameSession.Instance is null. Cannot send leave command.");
|
|
return;
|
|
}
|
|
Debug.Log("[DlgArrangeTeam] Leave team");
|
|
UnityGameSession.c2s_CmdTeamLeaveParty();
|
|
Show(false);
|
|
}
|
|
|
|
/// <summary>Disband team (leader). Uses C2S TEAM_DISMISS_PARTY, not leave.</summary>
|
|
public void OnDisband()
|
|
{
|
|
if (UnityGameSession.Instance == null)
|
|
{
|
|
Debug.LogWarning("[DlgArrangeTeam] OnDisband: UnityGameSession.Instance is null. Cannot send disband command.");
|
|
return;
|
|
}
|
|
Debug.Log("[DlgArrangeTeam] Disband team");
|
|
UnityGameSession.c2s_CmdTeamDismissParty();
|
|
Show(false);
|
|
}
|
|
|
|
/// <summary>Make selected member leader. Public so you can assign to Button.onClick in Inspector.</summary>
|
|
public void OnMakeLeader()
|
|
{
|
|
int idMember = GetSelectedTeammateId();
|
|
if (idMember <= 0)
|
|
{
|
|
Debug.Log("[DlgArrangeTeam] Make leader: select a teammate first (click a row in the list).");
|
|
return;
|
|
}
|
|
Debug.Log($"[DlgArrangeTeam] Make leader id={idMember}");
|
|
UnityGameSession.c2s_CmdTeamChangeLeader(idMember);
|
|
}
|
|
|
|
/// <summary>Refresh teammate and nearby lists. Public so you can assign to Button.onClick in Inspector.</summary>
|
|
public void OnRefresh()
|
|
{
|
|
UpdateTeam(true);
|
|
}
|
|
|
|
private void OnPickupModeChanged(short mode)
|
|
{
|
|
UnityGameSession.c2s_CmdTeamSetPickupFlag(mode);
|
|
}
|
|
|
|
private int GetSelectedTeammateId()
|
|
{
|
|
return m_selectedTeammateId;
|
|
}
|
|
}
|
|
}
|