TH1/Unity/Assets/Scripts/TH1_UI/View/Bottom/UIBottomNetRowMono.cs
2026-05-28 00:07:00 +08:00

337 lines
11 KiB
C#

using Logic.Multilingual;
using RuntimeData;
using TH1_Core.Managers;
using TH1_Logic.Core;
using TH1_Logic.Net;
using TH1_Logic.Steam;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace TH1_UI.View.Bottom
{
public class UIBottomNetRowMono : MonoBehaviour
{
public TextMeshProUGUI Name;
public TextMeshProUGUI Prop;
public TextMeshProUGUI Status;
public Image NetworkImage;
public Sprite Network_0;
public Sprite Network_1;
public Sprite Network_2;
public Sprite Network_3;
public Button InviteButton;
public TextMeshProUGUI InviteButtonText;
public Image InviteButtonImage;
public Sprite InviteButtonBG;
public Sprite AlreadyInvitedButtonBG;
public Button AIButton;
public Button CancelAIButton;
public GameObject AIPlayHint;
private ulong _memberid;
private bool _isNetOk;
private bool _isRoomOwner;
private bool _isAISlot;
private bool _invited;
public ulong MemberId => _memberid;
private void SetNoInvite()
{
_invited = false;
if (InviteButton != null) InviteButton.gameObject.SetActive(false);
}
private void SetInvite()
{
_invited = false;
if (InviteButton == null) return;
InviteButton.gameObject.SetActive(true);
InviteButtonText.text = MultilingualManager.Instance.GetMultilingualText(Table.Instance.TextDataAssets.MultiplayInviteButton);
InviteButtonImage.sprite = InviteButtonBG;
}
private void SetAlreadyInvited()
{
_invited = true;
if (InviteButton == null) return;
InviteButton.gameObject.SetActive(true);
InviteButtonText.text = MultilingualManager.Instance.GetMultilingualText(Table.Instance.TextDataAssets.MultiplayAlreadyInvitedButton);
InviteButtonImage.sprite = AlreadyInvitedButtonBG;
}
public void InitContent(ulong memberid, MemberInfo memberInfo, bool isRoomOwner, bool isNetOk)
{
_memberid = memberid;
_isNetOk = isNetOk;
_isRoomOwner = isRoomOwner;
_isAISlot = false;
Name.text = memberInfo?.Name ?? GetFallbackHumanName(memberid);
MultilingualManager.Instance.SetUIText(Prop, isRoomOwner ? Table.Instance.TextDataAssets.MultiplayRoomOwnerTitle : Table.Instance.TextDataAssets.MultiplayRoomGuestTitle);
UpdatePingStatus(isNetOk);
UpdateOfflineActions(isNetOk);
}
public void InitContent(MemberCiv slot, MemberInfo memberInfo, bool isRoomOwner)
{
_memberid = slot?.MemberId ?? 0;
_isRoomOwner = isRoomOwner;
_isAISlot = slot != null && slot.MemberId == 0 && slot.IsAI;
_isNetOk = _memberid != 0 && IsMemberOnline(_memberid);
if (_isAISlot)
{
Name.text = GetAIPlayerName(slot);
Prop.text = "AI";
UpdateAIStatus();
return;
}
Name.text = memberInfo?.Name ?? GetFallbackHumanName(_memberid);
MultilingualManager.Instance.SetUIText(Prop, isRoomOwner ? Table.Instance.TextDataAssets.MultiplayRoomOwnerTitle : Table.Instance.TextDataAssets.MultiplayRoomGuestTitle);
UpdatePingStatus(_isNetOk);
UpdateOfflineActions(_isNetOk);
}
public void UpdateNetStatus(bool isRoomOwner, bool isNetOk)
{
_isNetOk = isNetOk;
_isRoomOwner = isRoomOwner;
_isAISlot = false;
MultilingualManager.Instance.SetUIText(Prop, isRoomOwner ? Table.Instance.TextDataAssets.MultiplayRoomOwnerTitle : Table.Instance.TextDataAssets.MultiplayRoomGuestTitle);
UpdatePingStatus(isNetOk);
UpdateOfflineActions(isNetOk);
}
private void UpdateOfflineActions(bool isNetOk)
{
if (_isAISlot || _memberid == 0)
{
SetNoInvite();
SetNoAIControls();
return;
}
var confirm = Main.Instance?.ConfirmMap?.GetPlayerConfirm(_memberid);
if (isNetOk)
{
if (confirm != null && confirm.AIControl && IsSelfRoomOwner())
{
confirm.AIControl = false;
GameNetSender.Instance.SendMemberStateSync();
}
SetNoInvite();
SetNoAIControls();
return;
}
var aiControlled = confirm != null && confirm.AIControl;
SetAIPlayHint(aiControlled);
if (aiControlled)
{
SetNoInvite();
SetAIButtonActive(false);
SetCancelAIButtonActive(IsSelfRoomOwner());
BindCancelAIButton(confirm);
return;
}
SetCancelAIButtonActive(false);
if (!IsSelfRoomOwner())
{
SetNoInvite();
SetAIButtonActive(false);
return;
}
if (!_invited) SetInvite();
BindInviteButton();
SetAIButtonActive(true);
BindAIButton(confirm);
}
private void SetNoAIControls()
{
SetAIButtonActive(false);
SetCancelAIButtonActive(false);
SetAIPlayHint(false);
}
private void SetAIButtonActive(bool active)
{
if (AIButton != null) AIButton.gameObject.SetActive(active);
}
private void SetCancelAIButtonActive(bool active)
{
if (CancelAIButton != null) CancelAIButton.gameObject.SetActive(active);
}
private void SetAIPlayHint(bool active)
{
if (AIPlayHint != null) AIPlayHint.SetActive(active);
}
private void BindInviteButton()
{
if (InviteButton == null) return;
InviteButton.onClick.RemoveAllListeners();
InviteButton.onClick.AddListener(() =>
{
var lobby = LobbyManager.Instance.Lobby as SteamLobbyManager;
if (lobby == null) return;
lobby.InviteFriend(_memberid);
InviteButton.gameObject.SetActive(false);
if (_invited) return;
Timer.Instance.TimerRegister(this, () =>
{
if (ShouldShowInvite()) SetInvite();
}, 3f, "UIBottomNetRowMono_InviteClick");
SetAlreadyInvited();
});
}
private void BindAIButton(PlayerConfirmData confirm)
{
if (AIButton == null) return;
AIButton.onClick.RemoveAllListeners();
AIButton.onClick.AddListener(() =>
{
var data = confirm ?? Main.Instance?.ConfirmMap?.GetPlayerConfirm(_memberid);
if (data == null) return;
data.AIControl = true;
SetNoInvite();
SetAIPlayHint(true);
SetAIButtonActive(false);
SetCancelAIButtonActive(true);
BindCancelAIButton(data);
GameNetSender.Instance.SendMemberStateSync();
});
}
private void BindCancelAIButton(PlayerConfirmData confirm)
{
if (CancelAIButton == null) return;
CancelAIButton.onClick.RemoveAllListeners();
CancelAIButton.onClick.AddListener(() =>
{
var data = confirm ?? Main.Instance?.ConfirmMap?.GetPlayerConfirm(_memberid);
if (data == null) return;
data.AIControl = false;
SetAIPlayHint(false);
SetCancelAIButtonActive(false);
SetAIButtonActive(true);
SetInvite();
BindInviteButton();
BindAIButton(data);
GameNetSender.Instance.SendMemberStateSync();
});
}
private bool ShouldShowInvite()
{
if (_isNetOk || !IsSelfRoomOwner()) return false;
var confirm = Main.Instance?.ConfirmMap?.GetPlayerConfirm(_memberid);
return confirm == null || !confirm.AIControl;
}
private bool IsSelfRoomOwner()
{
return LobbyManager.Instance.Lobby != null && LobbyManager.Instance.Lobby.IsLobbyOwner();
}
private void UpdatePingStatus(bool isNetOk)
{
if (!isNetOk)
{
var offlineConfirm = Main.Instance?.ConfirmMap?.GetPlayerConfirm(_memberid);
Status.text = GetOfflineStatusText(offlineConfirm);
SetNetworkSprite(0);
return;
}
var confirm = Main.Instance?.ConfirmMap?.GetPlayerConfirm(_memberid);
if (confirm == null)
{
Status.text = "-- ms";
SetNetworkSprite(0);
return;
}
var pingMs = Mathf.RoundToInt(confirm.GetPing() * 1000f);
Status.text = $"{pingMs} ms";
SetNetworkSprite(GetNetworkLevel(pingMs));
}
private void UpdateAIStatus()
{
Status.text = "AI";
SetNetworkSprite(0);
SetNoInvite();
SetNoAIControls();
}
private string GetOfflineStatusText(PlayerConfirmData confirm)
{
if (confirm != null && confirm.AIControl) return "AI Control";
return confirm?.State switch
{
MemberNetState.Leaved => "Leaved",
MemberNetState.Disconnected => "Disconnected",
MemberNetState.Error => "Error",
_ => "Timeout"
};
}
private bool IsMemberOnline(ulong memberId)
{
if (memberId == 0) return false;
var lobby = LobbyManager.Instance.Lobby;
if (lobby == null || !lobby.IsInLobby()) return false;
if (!lobby.IsMemberInLobby(memberId)) return false;
var confirm = Main.Instance?.ConfirmMap?.GetPlayerConfirm(memberId);
return confirm == null || confirm.State == MemberNetState.OK;
}
private string GetFallbackHumanName(ulong memberId)
{
return memberId == 0 ? "Empty" : $"Player {memberId}";
}
private string GetAIPlayerName(MemberCiv slot)
{
var seatNo = (slot?.Index ?? 0) + 1;
return $"AI {seatNo}P";
}
private int GetNetworkLevel(int pingMs)
{
if (pingMs < 0) return 0;
if (pingMs < 100) return 3;
if (pingMs < 200) return 2;
if (pingMs < 500) return 1;
return 0;
}
private void SetNetworkSprite(int level)
{
if (NetworkImage == null) return;
NetworkImage.sprite = level switch
{
3 => Network_3,
2 => Network_2,
1 => Network_1,
_ => Network_0
};
}
}
}