联机功能优化

This commit is contained in:
kawagiri 2026-05-24 14:38:52 +08:00
parent 31f26a8ec6
commit 17e411707a
33 changed files with 13464 additions and 5414 deletions

View File

@ -1,5 +1,5 @@
{
"nextId": 263,
"nextId": 265,
"bugs": [
{
"id": 2,
@ -2600,6 +2600,26 @@
"module": "",
"createdAt": 1779539151076,
"updatedAt": 1779539151076
},
{
"id": 263,
"title": "咲夜/妹红的Lv3 技能描述问题",
"description": "",
"status": "open",
"priority": "medium",
"module": "",
"createdAt": 1779597876284,
"updatedAt": 1779597876284
},
{
"id": 264,
"title": "早苗行动点问题",
"description": "",
"status": "open",
"priority": "medium",
"module": "",
"createdAt": 1779599217683,
"updatedAt": 1779599217683
}
]
}

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -32,11 +32,11 @@ MonoBehaviour:
OutsideMultiplayIncludeAIPlayerHint: 2405
OutsideMultiplayNoRoomHint: 17453
OutsideMultiplayRoomNameSuffix: 17705
OutsideMultiplayTeamTitle:
OutsideMultiplayAIPlayerTitle:
OutsideMultiplayOpenTitle:
OutsideMultiplayReadyTitle:
OutsideMultiplayOpenHint:
OutsideMultiplayTeamTitle: 20066
OutsideMultiplayAIPlayerTitle: 20067
OutsideMultiplayOpenTitle: 20068
OutsideMultiplayReadyTitle: 20069
OutsideMultiplayOpenHint: 20070
OutsideHistoryDropListNoLimitP: 17352
OutsideHistoryDropList2P: 17353
OutsideHistoryDropList3P: 17354

View File

@ -4312,7 +4312,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7849747489070299319, guid: 19402153ee79dbc4e80a78f3222e6b47, type: 3}
propertyPath: m_SizeDelta.x
value: 0
value: 830.08167
objectReference: {fileID: 0}
- target: {fileID: 7849747489070299319, guid: 19402153ee79dbc4e80a78f3222e6b47, type: 3}
propertyPath: m_AnchoredPosition.x
@ -4497,7 +4497,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7849747489070299319, guid: ed55b8a014ca41543a2d95f370c5750d, type: 3}
propertyPath: m_SizeDelta.x
value: 0
value: 556.2688
objectReference: {fileID: 0}
- target: {fileID: 7849747489070299319, guid: ed55b8a014ca41543a2d95f370c5750d, type: 3}
propertyPath: m_AnchoredPosition.x

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a5218c398c8b8364891b636ee8199fca
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 017702e379c4b504f909f601f647475f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -14157,6 +14157,7 @@ MonoBehaviour:
CreateRoomPanelCheckButton: {fileID: 1280182484141737278}
CreateRoomPanelCloseButton: {fileID: 8542356455767446690}
RoomType: {fileID: 1344031542082465645}
CreateRoomPanelMono: {fileID: 0}
FriendRowPrefab: {fileID: 6041009835357861232, guid: 70146c0c4b561f342aa79e9b1d023c0f, type: 3}
FriendList: {fileID: 7803650363429376031}
MemberRowPrefab: {fileID: 7377647467463133788, guid: 2594e36360312bd46901e6c0b34f9814, type: 3}
@ -33991,6 +33992,12 @@ PrefabInstance:
- targetCorrespondingSourceObject: {fileID: 4045480400424864957, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}
insertIndex: -1
addedObject: {fileID: 2479160155700041659}
- targetCorrespondingSourceObject: {fileID: 5872298964086764219, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}
insertIndex: -1
addedObject: {fileID: 2388837226645455965}
- targetCorrespondingSourceObject: {fileID: 9107250659884233687, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}
insertIndex: -1
addedObject: {fileID: 6849889798537212103}
m_SourcePrefab: {fileID: 100100000, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}
--- !u!1 &210972501572928377 stripped
GameObject:
@ -34013,7 +34020,7 @@ MonoBehaviour:
NoExport: 0
FontBan: 0
Preset: 0
ID: 19647
ID: 20061
FontID: 0
TextCfg: []
--- !u!1 &1280182484141737278 stripped
@ -34042,6 +34049,30 @@ GameObject:
m_CorrespondingSourceObject: {fileID: 1515226799700260099, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}
m_PrefabInstance: {fileID: 4236172710499078084}
m_PrefabAsset: {fileID: 0}
--- !u!1 &4947939333884034067 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 9107250659884233687, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}
m_PrefabInstance: {fileID: 4236172710499078084}
m_PrefabAsset: {fileID: 0}
--- !u!114 &6849889798537212103
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4947939333884034067}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6b27f832d22e4a8d916272b644937774, type: 3}
m_Name:
m_EditorClassIdentifier:
Ban: 0
NoExport: 0
FontBan: 0
Preset: 0
ID: 20065
FontID: 0
TextCfg: []
--- !u!1 &5449829335624652389 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 8171858811077351841, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}
@ -34066,6 +34097,30 @@ MonoBehaviour:
ID: 19979
FontID: 0
TextCfg: []
--- !u!1 &7761796080576593279 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 5872298964086764219, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}
m_PrefabInstance: {fileID: 4236172710499078084}
m_PrefabAsset: {fileID: 0}
--- !u!114 &2388837226645455965
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7761796080576593279}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6b27f832d22e4a8d916272b644937774, type: 3}
m_Name:
m_EditorClassIdentifier:
Ban: 0
NoExport: 0
FontBan: 0
Preset: 0
ID: 20064
FontID: 0
TextCfg: []
--- !u!1 &8542356455767446690 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 5495908103617043302, guid: d6836e0f2f42f5f4a9b91f596f8bb5eb, type: 3}

View File

@ -3184,7 +3184,9 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: b944c6e03ad742440a76463c2ecf000a, type: 3}
m_Name:
m_EditorClassIdentifier:
AvatarRoot: {fileID: 6592483684148402150}
AvatarImage: {fileID: 7762177666811050190}
LeaderRoot: {fileID: 3382124894360767356}
LeaderImage: {fileID: 2028509407625721253}
NameText: {fileID: 6503687505537430979}
StatusText: {fileID: 9094648081951770890}

View File

@ -2200,9 +2200,9 @@ RectTransform:
- {fileID: 7354981697241446154}
m_Father: {fileID: 5566567905778636362}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 36.7275, y: -39.524}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 73.455, y: 79.048}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6757100784094017993
@ -3167,9 +3167,9 @@ RectTransform:
- {fileID: 3962389234318188601}
m_Father: {fileID: 3698126482628459019}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 377.4315, y: -59.52385}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 714.863, y: 79.0477}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &2164550660865405208
@ -3529,9 +3529,9 @@ RectTransform:
- {fileID: 7578212672192949060}
m_Father: {fileID: 5566567905778636362}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 416.73907, y: -24.0022}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 686.5681, y: 48.0044}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6522695967421094694

View File

@ -84,9 +84,11 @@ namespace TH1_Core.Events
EventManager.Subscribe<HideUIOutsideStory>(HandleHideUIOutsideStory);
EventManager.Subscribe<ShowUIOutsideMod>(HandleShowUIOutsideMod);
EventManager.Subscribe<HideUIOutsideMod>(HandleHideUIOutsideMod);
EventManager.Subscribe<ShowUIGlobalBugReport>(HandleShowUIGlobalBugReport);
EventManager.Subscribe<HideUIGlobalBugReport>(HandleHideUIGlobalBugReport);
EventManager.Subscribe<ShowUIBottomBottomBar>(HandleShowUIBottomBottomBar);
EventManager.Subscribe<HideUIBottomBottomBar>(HandleHideUIBottomBottomBar);
EventManager.Subscribe<ShowUIBottomBottomBarNextTurn>(HandleShowUIBottomBottomBarNextTurn);
@ -175,8 +177,10 @@ namespace TH1_Core.Events
EventManager.Unsubscribe<ShowUIOutsideMod>(HandleShowUIOutsideMod);
EventManager.Unsubscribe<HideUIOutsideMod>(HandleHideUIOutsideMod);
EventManager.Unsubscribe<ShowUIGlobalBugReport>(HandleShowUIGlobalBugReport);
EventManager.Unsubscribe<HideUIGlobalBugReport>(HandleHideUIGlobalBugReport);
EventManager.Unsubscribe<ShowUIBottomBottomBar>(HandleShowUIBottomBottomBar);
EventManager.Unsubscribe<HideUIBottomBottomBar>(HandleHideUIBottomBottomBar);
EventManager.Unsubscribe<ShowUIBottomBottomBarNextTurn>(HandleShowUIBottomBottomBarNextTurn);
@ -457,7 +461,17 @@ namespace TH1_Core.Events
UIManager.Instance.UIOutsideManager.HideCurTask();
}
private void HandleShowUIGlobalBugReport(ShowUIGlobalBugReport evt)
{
ViewControllerManager.UIGlobalBugReportController?.OpenWithParam(evt);
}
private void HandleHideUIGlobalBugReport(HideUIGlobalBugReport evt)
{
ViewControllerManager.UIGlobalBugReportController?.Close();
}
private void HandleShowUIOutsideInvited(ShowUIOutsideInvited evt)
{
UIManager.Instance.UIOutsideManager.OpenInvited(evt);

View File

@ -196,7 +196,11 @@ namespace TH1_Core.Events
public struct ShowUIOutsideInvited { public ulong LobbyId; }
public struct HideUIOutsideInvited { }
//----------------------------------------- UIGlobal 相关的事件 ----------------------------------
public struct ShowUIGlobalBugReport { }
public struct HideUIGlobalBugReport { }
// ------------------------------------------------ UIBottom 相关的事件 ------------------------------------

View File

@ -38,7 +38,7 @@ namespace TH1_Core.Managers
OutsideUI,//所有外部UI
BottomUI,//包含 bottombar ranking 等
TopUI,//包含topbar
OutsideTopUI//主要是全局通知这种
GlobalTopUI//主要是全局通知这种
};
public class UIManager
@ -92,7 +92,7 @@ namespace TH1_Core.Managers
UIResourceController.Instance.SetUIRoot(UIRootType.BottomUI,ROUIManager.transform.Find("Inside/Bottom"));
UIResourceController.Instance.SetUIRoot(UIRootType.TopUI,ROUIManager.transform.Find("Inside/Top"));
UIResourceController.Instance.SetUIRoot(UIRootType.OutsideUI,ROUIManager.transform.Find("Outside"));
UIResourceController.Instance.SetUIRoot(UIRootType.OutsideTopUI,ROUIManager.transform.Find("OutsideTop"));
UIResourceController.Instance.SetUIRoot(UIRootType.GlobalTopUI,ROUIManager.transform.Find("GlobalTop"));
UIInfoManager = new UIInfoManager();

View File

@ -44,7 +44,7 @@ namespace TH1_Logic.Net
public void KickMember(ulong memberId);
// 创建房间
public void CreateLobby(int maxMembers = 4,bool isPublic = true, string password = "");
public void CreateLobby(int maxMembers = 4,bool isPublic = true, string password = "", string roomName = "");
// 加入房间
public void JoinLobbyById(ulong lobbyId, string password = "");
@ -187,9 +187,9 @@ namespace TH1_Logic.Net
return null;
}
public void CreateLobby(int maxMembers = 4,bool isPublic = true, string password = "")
public void CreateLobby(int maxMembers = 4,bool isPublic = true, string password = "", string roomName = "")
{
}
// 获取成员数量

View File

@ -87,6 +87,7 @@ namespace TH1_Logic.Steam
private const string LobbyPasswordKey = "Password";
private const string LobbyIsPublicKey = "IsPublic";
private string _pendingLobbyPassword = "";
private string _pendingLobbyRoomName = "";
private bool _pendingLobbyIsPublic = true;
private CSteamID _pendingJoinLobby = CSteamID.Nil;
private string _pendingJoinPassword = "";
@ -624,7 +625,7 @@ namespace TH1_Logic.Steam
}
// 建房
public void CreateLobby(int maxMembers = 4, bool isPublic = true, string password = "")
public void CreateLobby(int maxMembers = 4, bool isPublic = true, string password = "", string roomName = "")
{
if (!EnsureSteamReadyForLobbyAction(nameof(CreateLobby))) return;
if (CurrentState != LobbyState.None)
@ -634,6 +635,7 @@ namespace TH1_Logic.Steam
}
_pendingLobbyPassword = password ?? "";
_pendingLobbyRoomName = string.IsNullOrWhiteSpace(roomName) ? GetDefaultRoomName(SelfName) : roomName.Trim();
_pendingLobbyIsPublic = isPublic;
CurrentState = LobbyState.Creating;
LogSystem.LogInfo($"Creating {(isPublic ? "public" : "friends-only")} lobby with max members: {maxMembers}, hasPassword: {!string.IsNullOrEmpty(_pendingLobbyPassword)}");
@ -1088,6 +1090,11 @@ namespace TH1_Logic.Steam
}
}
public static string GetDefaultRoomName(string selfName)
{
return selfName + MultilingualManager.Instance.GetMultilingualText(Table.Instance.TextDataAssets.OutsideMultiplayRoomNameSuffix);
}
// 过滤房间名称,只保留中文、英文字母、数字和常用符号
public static string FilterRoomName(string input, int maxLength = 20)
{
@ -1214,6 +1221,7 @@ namespace TH1_Logic.Steam
{
CurrentState = LobbyState.None;
_pendingLobbyPassword = "";
_pendingLobbyRoomName = "";
_pendingLobbyIsPublic = true;
LogSystem.LogError($"Failed to create lobby: {data.m_eResult}");
NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyCreateFailed);
@ -1233,14 +1241,14 @@ namespace TH1_Logic.Steam
SteamMatchmaking.SetLobbyData(CurrentLobby, "Game", "TOHOTOPIA");
SteamMatchmaking.SetLobbyData(CurrentLobby, "Owner", SelfName);
SteamMatchmaking.SetLobbyData(CurrentLobby, "Version", ConfigManager.Instance.VersionCfg.CurVersionInfo.Version);
//SteamMatchmaking.SetLobbyData(CurrentLobby, "RoomName", FilterRoomName(SelfName + MultilingualManager.Instance.GetMultilingualText(Table.Instance.TextDataAssets.OutsideMultiplayRoomNameSuffix)));
SteamMatchmaking.SetLobbyData(CurrentLobby, "RoomName", SelfName + MultilingualManager.Instance.GetMultilingualText(Table.Instance.TextDataAssets.OutsideMultiplayRoomNameSuffix));
SteamMatchmaking.SetLobbyData(CurrentLobby, "RoomName", _pendingLobbyRoomName);
SteamMatchmaking.SetLobbyData(CurrentLobby, "RoomCode", GenerateRoomCode());
SteamMatchmaking.SetLobbyData(CurrentLobby, "GameState", "0");
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyHasPasswordKey, string.IsNullOrEmpty(_pendingLobbyPassword) ? "false" : "true");
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyPasswordKey, _pendingLobbyPassword);
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyIsPublicKey, _pendingLobbyIsPublic ? "true" : "false");
_pendingLobbyPassword = "";
_pendingLobbyRoomName = "";
_pendingLobbyIsPublic = true;
// 设置Rich Presence
@ -1472,6 +1480,7 @@ namespace TH1_Logic.Steam
_steamSessionFailCount = 0;
_refreshSteamStatus = 0f;
_pendingLobbyPassword = "";
_pendingLobbyRoomName = "";
_pendingLobbyIsPublic = true;
ClearPendingJoinLobby();

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: da5416ff5e2fd5d448abc57411ce9d52
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,49 @@
using TH1_Core.Events;
using TH1_UI.Controller.Base;
using TH1_UI.View.Global;
namespace TH1_UI.Controller.Global
{
public class UIGlobalBugReportController : ViewController<UIGlobalBugReportView>
{
public UIGlobalBugReportController() { }
protected override void RegisterEventCallback()
{
base.RegisterEventCallback();
if (WindowScript != null)
{
WindowScript.OnBtnCloseClick += _OnBtnCloseClick;
}
}
protected override void UnregisterEventCallback()
{
if (WindowScript != null)
{
WindowScript.OnBtnCloseClick = null;
}
base.UnregisterEventCallback();
}
protected override void OnOpen()
{
base.OnOpen();
if (_openParameter is ShowUIGlobalBugReport evt)
{
WindowScript?.SetContent(evt);
}
}
public override bool Close()
{
WindowScript?.CloseView();
return base.Close();
}
void _OnBtnCloseClick()
{
Close();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68cb96a353924dc785044a1a656753b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -35,6 +35,7 @@ namespace TH1_UI.Core
public static readonly string ViewOutsideInvited = "UIOutsideInvited";
public static readonly string ViewOutsideStory = "UIOutsideStory";
public static readonly string ViewOutsideMod = "UIOutsideMod";
public static readonly string ViewGlobalBugReport = "UIGlobalBugReport";

View File

@ -5,6 +5,7 @@ using TH1_Core.Managers;
using TH1_UI.Controller.Announce;
using TH1_UI.Controller.Base;
using TH1_UI.Controller.Bottom;
using TH1_UI.Controller.Global;
using TH1_UI.Controller.Info;
using TH1_UI.Controller.Interaction;
using TH1_UI.Controller.Notify;
@ -60,7 +61,10 @@ namespace TH1_UI.Core
public static UIOutsideInvitedController UIOutsideInvitedController{ get { return _outsideInvitedController; } } // 新增
public static UIOutsideStoryController UIOutsideStoryController { get { return _outsideStoryController; } }
public static UIOutsideModController UIOutsideModController { get { return _outsideModController; } }
// ================================================= Global ================================================================
public static UIGlobalBugReportController UIGlobalBugReportController { get { return _globalBugReportController; } }
// ================================================= Bottom ================================================================
public static UIBottomBottomBarController UIBottomBottomBarController { get { return _bottomBottomBarController; } }
@ -130,9 +134,12 @@ namespace TH1_UI.Core
_outsideLibraryController = _CreateView<UIOutsideLibraryController>("Outside", UIResourceName.ViewOutsideLibrary, ViewDestroyDomain.None,UIRootType.OutsideUI);
_outsideWikiController = _CreateView<UIOutsideWikiController>("Outside", UIResourceName.ViewOutsideWiki, ViewDestroyDomain.None,UIRootType.OutsideUI);
_outsideTutorController = _CreateView<UIOutsideTutorController>("Outside", UIResourceName.ViewOutsideTutor, ViewDestroyDomain.None,UIRootType.OutsideUI); // 新增
_outsideInvitedController = _CreateView<UIOutsideInvitedController>("Outside", UIResourceName.ViewOutsideInvited, ViewDestroyDomain.None,UIRootType.OutsideTopUI); // 新增
_outsideStoryController = _CreateView<UIOutsideStoryController>("Outside", UIResourceName.ViewOutsideStory, ViewDestroyDomain.None,UIRootType.OutsideTopUI); // 新增
_outsideInvitedController = _CreateView<UIOutsideInvitedController>("Outside", UIResourceName.ViewOutsideInvited, ViewDestroyDomain.None,UIRootType.GlobalTopUI); // 新增
_outsideStoryController = _CreateView<UIOutsideStoryController>("Outside", UIResourceName.ViewOutsideStory, ViewDestroyDomain.None,UIRootType.GlobalTopUI); // 新增
_outsideModController = _CreateView<UIOutsideModController>("Outside", UIResourceName.ViewOutsideMod, ViewDestroyDomain.None,UIRootType.OutsideUI); // 新增
// ================================================= Global ================================================================
_globalBugReportController = _CreateView<UIGlobalBugReportController>("Global", UIResourceName.ViewGlobalBugReport, ViewDestroyDomain.None,UIRootType.GlobalTopUI);
@ -291,7 +298,9 @@ namespace TH1_UI.Core
private static UIOutsideStoryController _outsideStoryController = null; // 新增
private static UIOutsideModController _outsideModController = null; // 新增
private static UIOutsideInvitedController _outsideInvitedController = null;
private static UIGlobalBugReportController _globalBugReportController = null;
private static UIBottomBottomBarController _bottomBottomBarController = null;
private static UIBottomRankingController _bottomRankingController = null;
private static UIBottomNetController _bottomNetController = null;

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7835e66806b65e1438934459614338a7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,39 @@
using TH1_Core.Events;
using TH1_UI.View.Base;
using UnityEngine.UI;
namespace TH1_UI.View.Global
{
public class UIGlobalBugReportView : View
{
public Button CloseButton;
public Button BlockerButton;
public ViDelegateAssisstant.Dele OnBtnCloseClick;
protected override void OnInit()
{
base.OnInit();
if (CloseButton != null)
{
CloseButton.onClick.RemoveAllListeners();
CloseButton.onClick.AddListener(() => { OnBtnCloseClick?.Invoke(); });
}
if (BlockerButton != null)
{
BlockerButton.onClick.RemoveAllListeners();
BlockerButton.onClick.AddListener(() => { OnBtnCloseClick?.Invoke(); });
}
}
public void SetContent(ShowUIGlobalBugReport evt)
{
}
public void CloseView()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28f0d3b6d3da1ef43acc777166cab49d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,338 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace TH1_UI.View.Outside
{
public class UIOutsideMultiplayCreateRoomPanelMono : MonoBehaviour
{
public enum RoomKind
{
Public,
Friend,
Password
}
public struct CreateRoomParams
{
public RoomKind Kind;
public int SeatCount;
public bool IsPublic;
public string RoomName;
public string Password;
}
public GameObject PanelRoot;
public Button CheckButton;
public Button CloseButton;
public TMP_InputField RoomNameInput;
public TextMeshProUGUI RoomNamePlaceholderText;
public GameObject RoomNameHintObject;
public TextMeshProUGUI RoomNameHintText;
public UIOutsideSelectOptionGroupMono RoomType;
public UIOutsideSelectOptionGroupMono SeatCount;
public GameObject PasswordRoot;
public TMP_InputField PasswordInput;
public GameObject PasswordHintObject;
public TextMeshProUGUI PasswordHintText;
private Action<CreateRoomParams> _onConfirm;
private Action _onClose;
private GameObject _passwordLabelObject;
private GameObject _runtimeSeatRoot;
private string _defaultRoomName;
public void Init(Action<CreateRoomParams> onConfirm, Action onClose = null)
{
_onConfirm = onConfirm;
_onClose = onClose;
if (CheckButton != null)
{
CheckButton.onClick.RemoveAllListeners();
CheckButton.onClick.AddListener(OnClickCheck);
}
if (CloseButton != null)
{
CloseButton.onClick.RemoveAllListeners();
CloseButton.onClick.AddListener(OnClickClose);
}
if (RoomType != null)
RoomType.OnOptionClicked = _ => RefreshPasswordVisible();
AutoBindRoomNameInput();
if (RoomNameInput != null)
{
RoomNameInput.onValueChanged.RemoveListener(OnRoomNameChanged);
RoomNameInput.onValueChanged.AddListener(OnRoomNameChanged);
}
HideRoomNameHint();
EnsureSeatCountOption();
AutoBindPasswordLabel();
EnsurePasswordHint();
}
public void Show(int defaultSeatCount = 4, string defaultRoomName = "")
{
_defaultRoomName = defaultRoomName ?? string.Empty;
GetRoot().SetActive(true);
RoomType?.Init(0);
SeatCount?.Init(SeatToIndex(defaultSeatCount));
if (RoomNameInput != null) RoomNameInput.text = string.Empty;
SetRoomNamePlaceholder(_defaultRoomName);
HideRoomNameHint();
if (PasswordInput != null) PasswordInput.text = string.Empty;
HidePasswordHint();
RefreshPasswordVisible();
}
public void Hide()
{
GetRoot().SetActive(false);
}
public bool TryBuildParams(out CreateRoomParams args)
{
var roomName = RoomNameInput != null ? RoomNameInput.text?.Trim() : string.Empty;
args = new CreateRoomParams
{
Kind = GetRoomKind(),
SeatCount = GetSeatCount(),
IsPublic = true,
RoomName = roomName,
Password = string.Empty
};
if (string.IsNullOrEmpty(roomName))
{
ShowRoomNameHint();
return false;
}
HideRoomNameHint();
if (args.Kind == RoomKind.Friend)
{
args.IsPublic = false;
return true;
}
if (args.Kind != RoomKind.Password) return true;
var password = PasswordInput != null ? PasswordInput.text?.Trim() : string.Empty;
if (!IsValidPassword(password))
{
ShowPasswordHint();
return false;
}
args.Password = password;
return true;
}
private void OnClickCheck()
{
if (!TryBuildParams(out var args)) return;
Hide();
_onConfirm?.Invoke(args);
}
private void OnClickClose()
{
Hide();
_onClose?.Invoke();
}
private void OnRoomNameChanged(string value)
{
HideRoomNameHint();
}
private void RefreshPasswordVisible()
{
var showPassword = GetRoomKind() == RoomKind.Password;
if (PasswordRoot != null) PasswordRoot.SetActive(showPassword);
if (_passwordLabelObject != null) _passwordLabelObject.SetActive(showPassword);
if (!showPassword)
{
if (PasswordInput != null) PasswordInput.text = string.Empty;
HidePasswordHint();
}
RebuildSettingLayout();
}
private void ShowRoomNameHint()
{
if (RoomNameHintText != null) RoomNameHintText.text = "房间名称未设置!";
if (RoomNameHintObject != null) RoomNameHintObject.SetActive(true);
}
private void HideRoomNameHint()
{
if (RoomNameHintObject != null) RoomNameHintObject.SetActive(false);
}
private void SetRoomNamePlaceholder(string roomName)
{
if (RoomNamePlaceholderText != null) RoomNamePlaceholderText.text = roomName;
else if (RoomNameInput != null && RoomNameInput.placeholder is TextMeshProUGUI placeholder)
placeholder.text = roomName;
}
private void AutoBindRoomNameInput()
{
if (RoomNameInput != null && RoomNamePlaceholderText != null) return;
if (PasswordInput == null || PasswordRoot == null || PasswordRoot.transform.parent == null) return;
var parent = PasswordRoot.transform.parent;
for (int i = 0; i < parent.childCount; i++)
{
var input = parent.GetChild(i).GetComponentInChildren<TMP_InputField>(true);
if (input == null || input == PasswordInput) continue;
RoomNameInput = input;
RoomNamePlaceholderText = input.placeholder as TextMeshProUGUI;
return;
}
}
private void ShowPasswordHint()
{
EnsurePasswordHint();
if (PasswordHintText != null) PasswordHintText.text = "请输入4位数字密码";
if (PasswordHintObject != null) PasswordHintObject.SetActive(true);
}
private void HidePasswordHint()
{
if (PasswordHintObject != null) PasswordHintObject.SetActive(false);
}
private RoomKind GetRoomKind()
{
if (RoomType == null) return RoomKind.Public;
return RoomType.SelectedIndex switch
{
1 => RoomKind.Friend,
2 => RoomKind.Password,
_ => RoomKind.Public
};
}
private void AutoBindPasswordLabel()
{
if (PasswordInput == null || PasswordRoot == null || PasswordRoot.transform.parent == null) return;
var parent = PasswordRoot.transform.parent;
for (int i = 0; i < parent.childCount; i++)
{
var child = parent.GetChild(i);
if (child == PasswordRoot.transform) continue;
var text = child.GetComponent<TextMeshProUGUI>();
if (text == null || text.text != "房间名称") continue;
text.text = "房间密码";
_passwordLabelObject = child.gameObject;
return;
}
}
private void EnsureSeatCountOption()
{
if (SeatCount != null || RoomType == null || RoomType.transform.parent == null) return;
if (_runtimeSeatRoot != null)
{
SeatCount = _runtimeSeatRoot.GetComponentInChildren<UIOutsideSelectOptionGroupMono>(true);
return;
}
_runtimeSeatRoot = Instantiate(RoomType.transform.parent.gameObject, RoomType.transform.parent.parent);
_runtimeSeatRoot.name = "SeatCountGroup";
_runtimeSeatRoot.transform.SetSiblingIndex(RoomType.transform.parent.GetSiblingIndex() + 1);
var label = _runtimeSeatRoot.GetComponentInChildren<TextMeshProUGUI>(true);
if (label != null && label.text == "私密性") label.text = "房间席位";
SeatCount = _runtimeSeatRoot.GetComponentInChildren<UIOutsideSelectOptionGroupMono>(true);
if (SeatCount == null) return;
var optionTexts = new[] { "2", "3", "4" };
for (int i = 0; i < SeatCount.options.Count && i < optionTexts.Length; i++)
{
var text = SeatCount.options[i].GetComponentInChildren<TextMeshProUGUI>(true);
if (text != null) text.text = optionTexts[i];
}
RebuildSettingLayout();
}
private void RebuildSettingLayout()
{
var target = PasswordRoot != null ? PasswordRoot.transform.parent as RectTransform : null;
if (target == null && RoomType != null) target = RoomType.transform.parent?.parent as RectTransform;
if (target == null) return;
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(target);
}
private void EnsurePasswordHint()
{
if (PasswordHintObject != null && PasswordHintText != null) return;
if (PasswordInput == null || PasswordInput.textComponent == null) return;
var hintObject = new GameObject("PasswordHint", typeof(RectTransform));
hintObject.transform.SetParent(PasswordInput.transform.parent, false);
var rect = hintObject.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0.5f, 0.5f);
rect.anchorMax = new Vector2(0.5f, 0.5f);
rect.pivot = new Vector2(0.5f, 0.5f);
rect.anchoredPosition = new Vector2(0f, -34f);
rect.sizeDelta = new Vector2(360f, 30f);
PasswordHintText = hintObject.AddComponent<TextMeshProUGUI>();
PasswordHintText.font = PasswordInput.textComponent.font;
PasswordHintText.fontSize = 20f;
PasswordHintText.color = Color.red;
PasswordHintText.alignment = TextAlignmentOptions.Center;
PasswordHintText.text = "请输入4位数字密码";
PasswordHintObject = hintObject;
PasswordHintObject.SetActive(false);
}
private int GetSeatCount()
{
if (SeatCount == null) return 4;
return ClampSeatCount((int)SeatCount.SelectedIndex + 2);
}
private static uint SeatToIndex(int seatCount)
{
return (uint)(ClampSeatCount(seatCount) - 2);
}
private static int ClampSeatCount(int seatCount)
{
return Mathf.Clamp(seatCount, 2, 4);
}
private static bool IsValidPassword(string password)
{
if (string.IsNullOrEmpty(password) || password.Length != 4) return false;
for (int i = 0; i < password.Length; i++)
{
if (!char.IsDigit(password[i])) return false;
}
return true;
}
private GameObject GetRoot()
{
return PanelRoot != null ? PanelRoot : gameObject;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9d7b5fbf6d714a0cb12a1bdca9d23e10
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -11,7 +11,9 @@ using UnityEngine.UI;
public class UIOutsideMultiplayMemberRowMono : MonoBehaviour
{
public GameObject AvatarRoot;
public Image AvatarImage;
public GameObject LeaderRoot;
public Image LeaderImage;
public TextMeshProUGUI NameText;
public TextMeshProUGUI StatusText;
@ -76,6 +78,7 @@ public class UIOutsideMultiplayMemberRowMono : MonoBehaviour
_onTeamChanged = onTeamChanged;
SetAvatarVisible(true);
SetLeaderVisible(true);
NameText.text = info.Name;
SetAvatar(info.Texture);
UpdatePlayerInfoView(civ, force);
@ -91,6 +94,7 @@ public class UIOutsideMultiplayMemberRowMono : MonoBehaviour
if (!CheckParam()) return;
ResetButtons();
SetAvatarVisible(false);
SetLeaderVisible(false);
MultilingualManager.Instance.SetUIText(NameText, Table.Instance.TextDataAssets.OutsideMultiplayOpenTitle);
StatusText.text = string.Empty;
ForcesText.text = string.Empty;
@ -118,6 +122,7 @@ public class UIOutsideMultiplayMemberRowMono : MonoBehaviour
_onTeamChanged = onTeamChanged;
SetAvatarVisible(false);
SetLeaderVisible(true);
MultilingualManager.Instance.SetUIText(NameText, Table.Instance.TextDataAssets.OutsideMultiplayAIPlayerTitle);
StatusText.text = string.Empty;
UpdatePlayerInfoView(civ, force);
@ -175,7 +180,13 @@ public class UIOutsideMultiplayMemberRowMono : MonoBehaviour
private void SetAvatarVisible(bool visible)
{
if (AvatarRoot != null) AvatarRoot.SetActive(visible);
if (AvatarImage != null) AvatarImage.gameObject.SetActive(visible);
}
private void SetLeaderVisible(bool visible)
{
if (LeaderRoot != null) LeaderRoot.SetActive(visible);
if (LeaderImage != null) LeaderImage.gameObject.SetActive(visible);
}

View File

@ -56,6 +56,7 @@ namespace TH1_UI.View.Outside
public GameObject CreateRoomPanelCheckButton;
public GameObject CreateRoomPanelCloseButton;
public UIOutsideSelectOptionGroupMono RoomType;
public UIOutsideMultiplayCreateRoomPanelMono CreateRoomPanelMono;
@ -151,20 +152,26 @@ namespace TH1_UI.View.Outside
CreateRoomButton.onClick.RemoveAllListeners();
CreateRoomButton.onClick.AddListener(CreateRoom);
// 注册创建房间面板确认按钮
var checkButton = CreateRoomPanelCheckButton?.GetComponent<Button>();
if (checkButton != null)
{
checkButton.onClick.RemoveAllListeners();
checkButton.onClick.AddListener(CreateRoomWithType);
}
if (CreateRoomPanelMono == null && CreateRoomPanel != null)
CreateRoomPanelMono = CreateRoomPanel.GetComponent<UIOutsideMultiplayCreateRoomPanelMono>();
CreateRoomPanelMono?.Init(OnCreateRoomPanelConfirm);
// 注册创建房间面板关闭按钮
var closeButton = CreateRoomPanelCloseButton?.GetComponent<Button>();
if (closeButton != null)
// 旧字段保留为 prefab 兜底,正常流程由 CreateRoomPanelMono 接管。
if (CreateRoomPanelMono == null)
{
closeButton.onClick.RemoveAllListeners();
closeButton.onClick.AddListener(() => CreateRoomPanel?.SetActive(false));
var checkButton = CreateRoomPanelCheckButton?.GetComponent<Button>();
if (checkButton != null)
{
checkButton.onClick.RemoveAllListeners();
checkButton.onClick.AddListener(CreateRoomWithType);
}
var closeButton = CreateRoomPanelCloseButton?.GetComponent<Button>();
if (closeButton != null)
{
closeButton.onClick.RemoveAllListeners();
closeButton.onClick.AddListener(() => CreateRoomPanel?.SetActive(false));
}
}
LeaveRoomButton.onClick.RemoveAllListeners();
@ -886,11 +893,16 @@ namespace TH1_UI.View.Outside
return;
}
//显示创建房间面板
if (CreateRoomPanelMono != null)
{
CreateRoomPanelMono.Show(_roomSeatCount, SteamLobbyManager.GetDefaultRoomName(_lobby.SelfName));
return;
}
// 兼容未绑定新 Mono 的 prefab正式绑定后不会走到这里。
if (CreateRoomPanel != null)
{
CreateRoomPanel.SetActive(true);
//初始化房间类型选择(默认公开房间)
RoomType?.Init(0);
}
}
@ -907,10 +919,19 @@ namespace TH1_UI.View.Outside
_lobby.OnLobbyEnteredEvent += OnLobbyJoinSuccess;
_lobby.OnLobbyErrorEvent += OnLobbyJoinFailed;
//获取房间类型0=公开1=私密
bool isPublic = RoomType?.SelectedIndex == 0;
_roomSeatCount = Mathf.Max(1, (int)Main.Instance.MapConfig.PlayerCount);
_lobby.CreateLobby(_roomSeatCount, isPublic);
// 旧入口兜底:没有绑定新面板 Mono 时仍能创建公开/好友房。
bool isPublic = RoomType?.SelectedIndex != 1;
_roomSeatCount = Mathf.Clamp(_roomSeatCount, 2, 4);
_lobby.CreateLobby(_roomSeatCount, isPublic, string.Empty, SteamLobbyManager.GetDefaultRoomName(_lobby.SelfName));
}
private void OnCreateRoomPanelConfirm(UIOutsideMultiplayCreateRoomPanelMono.CreateRoomParams args)
{
_lobby.OnLobbyEnteredEvent += OnLobbyJoinSuccess;
_lobby.OnLobbyErrorEvent += OnLobbyJoinFailed;
_roomSeatCount = Mathf.Clamp(args.SeatCount, 2, 4);
_lobby.CreateLobby(_roomSeatCount, args.IsPublic, args.Password, args.RoomName);
}
public void LeaveRoom()

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff