UI功能修复

This commit is contained in:
daixiawu 2026-05-28 00:07:00 +08:00
parent cc73377572
commit 8ed05518e7
17 changed files with 6183 additions and 5953 deletions

File diff suppressed because one or more lines are too long

View File

@ -44,6 +44,7 @@ MonoBehaviour:
OutsideMultiplayRoomNetError: "\u7F51\u7EDC\u9519\u8BEF"
OutsideMultiplayRoomJubaoSuccess: "\u4E3E\u62A5\u5DF2\u63D0\u4EA4"
OutsideMultiplayRoomMuteSuccess: "\u5DF2\u9690\u85CF\u8BE5\u623F\u95F4\uFF0C24\u5C0F\u65F6\u5185\u4E0D\u518D\u663E\u793A"
OutsideMultiplayRoomPasswordWrong: "\u5BC6\u7801\u9519\u8BEF\uFF01"
OutsideHistoryDropListNoLimitP: "\u4E0D\u9650"
OutsideHistoryDropList2P: "2\u4EBA"
OutsideHistoryDropList3P: "3\u4EBA"

View File

@ -44,6 +44,7 @@ MonoBehaviour:
OutsideMultiplayRoomNetError: 17451
OutsideMultiplayRoomJubaoSuccess: 20095
OutsideMultiplayRoomMuteSuccess: 20096
OutsideMultiplayRoomPasswordWrong: 20088
OutsideHistoryDropListNoLimitP: 17352
OutsideHistoryDropList2P: 17353
OutsideHistoryDropList3P: 17354

View File

@ -14046,11 +14046,11 @@ RectTransform:
- {fileID: 1440541157806079047}
- {fileID: 6896587755546489264}
- {fileID: 3276026647213520749}
- {fileID: 8080017689044529554}
- {fileID: 2533752944694645976}
- {fileID: 1800154829384274985}
- {fileID: 5706120783204626353}
- {fileID: 1829137900443655153}
- {fileID: 8080017689044529554}
- {fileID: 5972108517643533097}
- {fileID: 8627289949919189300}
- {fileID: 2317128859859036338}

View File

@ -328,6 +328,7 @@ MonoBehaviour:
PanelRoot: {fileID: 1515226799700260099}
CheckButton: {fileID: 4295583436560441463}
CloseButton: {fileID: 8083913519070174357}
BlockerButton: {fileID: 0}
RoomNameInput: {fileID: 7389518212591164549}
RoomNamePlaceholderText: {fileID: 3511343210454506103}
RoomType: {fileID: 2913579592440520873}

View File

@ -137,6 +137,7 @@ namespace TH1_Core.Events
OutsideMultiplayRoomFull,
OutsideMultiplayRoomGone,
OutsideMultiplayRoomNetError,
OutsideMultiplayRoomPasswordWrong,
OutsideMultiplayOpenHint,
OutsideMultiplayCantStartCount
}

View File

@ -48,6 +48,7 @@ public class TextDataAssets : ScriptableObject
[MultilingualField]public string OutsideMultiplayRoomNetError;
[MultilingualField]public string OutsideMultiplayRoomJubaoSuccess;
[MultilingualField]public string OutsideMultiplayRoomMuteSuccess;
[MultilingualField]public string OutsideMultiplayRoomPasswordWrong;
[MultilingualField]public string OutsideHistoryDropListNoLimitP;
[MultilingualField]public string OutsideHistoryDropList2P;

View File

@ -216,6 +216,20 @@ namespace TH1_Logic.MatchConfig
return;
}
if (map?.MapConfig?.GameMode == GameMode.PERFECT)
{
info.Param1Cur = GetCompletedTurnCount(map, player);
if (player.IsSurvival &&
info.Param1Cur >= info.Param1 &&
IsTargetTurnCompletedByAllSurvivalPlayers(map, info.Param1))
{
info.IsSettlement = true;
info.IsSuccess = true;
}
return;
}
info.Param1Cur = (int)player.Turn;
if (player.IsSurvival && player.Turn >= info.Param1)
{
@ -223,6 +237,40 @@ namespace TH1_Logic.MatchConfig
info.IsSuccess = true;
}
}
private static int GetCompletedTurnCount(MapData map, PlayerData player)
{
if (player == null)
{
return 0;
}
var completedTurn = (int)player.Turn;
if (map?.Net != null && map.Net.CurPlayerId == player.Id)
{
completedTurn--;
}
return System.Math.Max(0, completedTurn);
}
private static bool IsTargetTurnCompletedByAllSurvivalPlayers(MapData map, int targetTurn)
{
if (map?.PlayerMap?.PlayerDataList == null)
{
return false;
}
foreach (var player in map.PlayerMap.PlayerDataList)
{
if (player.IsSurvival && GetCompletedTurnCount(map, player) < targetTurn)
{
return false;
}
}
return true;
}
}

View File

@ -39,6 +39,8 @@ namespace TH1_Logic.Steam
public class SteamLobbyManager : ILobby
{
public const string LobbyPasswordWrongError = "LobbyPasswordWrong";
// 登录状态
private bool _isLoggedIn = false;
public bool IsloggedIn => _isLoggedIn;
@ -860,7 +862,7 @@ namespace TH1_Logic.Steam
: "Lobby password mismatch";
LogSystem.LogInfo(errorMsg);
NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyJoinFailed);
OnLobbyErrorEvent?.Invoke(errorMsg);
OnLobbyErrorEvent?.Invoke(LobbyPasswordWrongError);
return false;
}

View File

@ -32,6 +32,7 @@ namespace TH1_UI.View.Bottom
private ulong _memberid;
private bool _isNetOk;
private bool _isRoomOwner;
private bool _isAISlot;
private bool _invited;
public ulong MemberId => _memberid;
@ -64,17 +65,40 @@ namespace TH1_UI.View.Bottom
_memberid = memberid;
_isNetOk = isNetOk;
_isRoomOwner = isRoomOwner;
_isAISlot = false;
Name.text = memberInfo.Name;
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);
@ -82,6 +106,13 @@ namespace TH1_UI.View.Bottom
private void UpdateOfflineActions(bool isNetOk)
{
if (_isAISlot || _memberid == 0)
{
SetNoInvite();
SetNoAIControls();
return;
}
var confirm = Main.Instance?.ConfirmMap?.GetPlayerConfirm(_memberid);
if (isNetOk)
{
@ -220,7 +251,8 @@ namespace TH1_UI.View.Bottom
{
if (!isNetOk)
{
Status.text = "Timeout";
var offlineConfirm = Main.Instance?.ConfirmMap?.GetPlayerConfirm(_memberid);
Status.text = GetOfflineStatusText(offlineConfirm);
SetNetworkSprite(0);
return;
}
@ -238,6 +270,48 @@ namespace TH1_UI.View.Bottom
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;

View File

@ -76,31 +76,7 @@ namespace TH1_UI.View.Bottom
if (!isMulti) return;
var lobbyInfo = LobbyManager.Instance.Lobby as SteamLobbyManager;
if (lobbyInfo == null) return;
var mids = lobbyInfo.GetAllMemberInfo();
while (_netInfoRowList.Count < mids.Count)
{
var obj = Instantiate(NetRowPrefab, NetRowContainer);
var cpn = obj.GetComponent<UIBottomNetRowMono>();
if (cpn == null) break;
_netInfoRowList.Add(cpn);
}
int i = 0;
foreach(var pair in mids)
{
_netInfoRowList[i].gameObject.SetActive(true);
_netInfoRowList[i].InitContent(pair.Key, pair.Value, pair.Key == lobbyInfo.GetLobbyOwnerId(), true);
i++;
}
int activeCount = i;
while(i < _netInfoRowList.Count)
{
_netInfoRowList[i].gameObject.SetActive(false);
i++;
}
ResizeScrollView(activeCount);
RenderNetRows();
}
private void ResizeScrollView(int activeRowCount)
@ -132,29 +108,53 @@ namespace TH1_UI.View.Bottom
if (lobbyInfo == null) return;
var mids = lobbyInfo.GetAllMemberInfo();
PlayMemberEnterAudioIfNeeded(mids.Count);
// Reinitialize if the lobby member count grows.
if (mids.Count > _netInfoRowList.Count)
Init();
for (int i = 0; i < _netInfoRowList.Count; i++)
{
if (!_netInfoRowList[i].gameObject.activeSelf) break;
bool isOnline = false;
bool isRoomOwner = false;
foreach(var pair in mids)
if (pair.Key == _netInfoRowList[i].MemberId)
{
isOnline = true;
isRoomOwner = pair.Key == lobbyInfo.GetLobbyOwnerId();
break;
}
_netInfoRowList[i].UpdateNetStatus(isRoomOwner, isOnline);
}
RenderNetRows();
}
private void RenderNetRows()
{
var lobbyInfo = LobbyManager.Instance.Lobby as SteamLobbyManager;
var mapConfig = Main.MapData?.MapConfig ?? Main.Instance?.MapConfig;
if (lobbyInfo == null || mapConfig == null) return;
mapConfig.EnsurePlayerSlots(NetMode.Multi);
var slots = mapConfig.MultiCivs;
var memberInfos = lobbyInfo.GetAllMemberInfo();
var ownerId = lobbyInfo.GetLobbyOwnerId();
var activeCount = slots?.Count ?? 0;
EnsureNetRowCount(activeCount);
for (int i = 0; i < _netInfoRowList.Count; i++)
{
var row = _netInfoRowList[i];
var active = i < activeCount;
row.gameObject.SetActive(active);
if (!active) continue;
var slot = slots[i];
memberInfos.TryGetValue(slot.MemberId, out var memberInfo);
row.InitContent(slot, memberInfo, slot.MemberId != 0 && slot.MemberId == ownerId);
}
ResizeScrollView(activeCount);
}
private void EnsureNetRowCount(int count)
{
while (_netInfoRowList.Count < count)
{
var obj = Instantiate(NetRowPrefab, NetRowContainer);
var cpn = obj.GetComponent<UIBottomNetRowMono>();
if (cpn == null)
{
Destroy(obj);
break;
}
_netInfoRowList.Add(cpn);
}
}
private void PlayMemberEnterAudioIfNeeded(int memberCount)
{
if (_lastNetMemberCount >= 0 && memberCount > _lastNetMemberCount)

View File

@ -65,6 +65,9 @@ namespace TH1_UI.View.Notify
case UINotifyCommonType.OutsideMultiplayRoomNetError:
MultilingualManager.Instance.SetUIText(content,Table.Instance.TextDataAssets.OutsideMultiplayRoomNetError);
break;
case UINotifyCommonType.OutsideMultiplayRoomPasswordWrong:
MultilingualManager.Instance.SetUIText(content,Table.Instance.TextDataAssets.OutsideMultiplayRoomPasswordWrong);
break;
case UINotifyCommonType.OutsideMultiplayOpenHint:
MultilingualManager.Instance.SetUIText(content,Table.Instance.TextDataAssets.OutsideMultiplayOpenHint);
break;

View File

@ -1999,6 +1999,9 @@ namespace TH1_UI.View.Outside
case UINotifyCommonType.OutsideMultiplayRoomNetError:
ShowMultiplayInsideNotify(Table.Instance.TextDataAssets.OutsideMultiplayRoomNetError);
break;
case UINotifyCommonType.OutsideMultiplayRoomPasswordWrong:
ShowMultiplayInsideNotify(Table.Instance.TextDataAssets.OutsideMultiplayRoomPasswordWrong);
break;
case UINotifyCommonType.OutsideMultiplayOpenHint:
ShowMultiplayInsideNotify(Table.Instance.TextDataAssets.OutsideMultiplayOpenHint);
break;
@ -2290,7 +2293,9 @@ namespace TH1_UI.View.Outside
//显示加入失败提示
ShowLobbyNotify(UINotifyCommonType.OutsideMultiplayRoomNetError);
ShowLobbyNotify(error == SteamLobbyManager.LobbyPasswordWrongError
? UINotifyCommonType.OutsideMultiplayRoomPasswordWrong
: UINotifyCommonType.OutsideMultiplayRoomNetError);
}

View File

@ -109,7 +109,15 @@ namespace TH1_UI.View.Top
WinFlowerDeco.gameObject.SetActive(isWin);
CityCount.text = Main.MapData.GetCityCount(Main.MapData.PlayerMap.SelfPlayerData.Id).ToString();
TurnCount.text = Main.MapData.PlayerMap.SelfPlayerData.Turn.ToString();
var displayTurn = (int)Main.MapData.PlayerMap.SelfPlayerData.Turn;
if (Main.MapData.MapConfig.GameMode == RuntimeData.GameMode.PERFECT &&
Main.MapData.Net != null &&
Main.MapData.Net.CurPlayerId == Main.MapData.PlayerMap.SelfPlayerData.Id)
{
displayTurn = Mathf.Max(0, displayTurn - 1);
}
TurnCount.text = displayTurn.ToString();
Score.text = Main.MapData.PlayerMap.SelfPlayerData.PlayerScore.ToString();
if (Difficult != null)
Difficult.text = Main.MapData.MapConfig.AIDiff.ToString();

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff