|
|
|
|
@ -87,6 +87,12 @@ namespace TH1_Logic.Steam
|
|
|
|
|
private const string LobbyHasPasswordKey = "HasPassword";
|
|
|
|
|
private const string LobbyPasswordKey = "Password";
|
|
|
|
|
private const string LobbyIsPublicKey = "IsPublic";
|
|
|
|
|
private const string LobbyOwnerSteamIdKey = "OwnerSteamId";
|
|
|
|
|
private const string LobbyReportCountKey = "ReportCount";
|
|
|
|
|
private const string LobbyRoomNameKey = "RoomName";
|
|
|
|
|
private const string LobbyGameStateKey = "GameState";
|
|
|
|
|
private const int LobbyReportRenameThreshold = 5;
|
|
|
|
|
private const string ReportedLobbyDefaultRoomName = "Default";
|
|
|
|
|
private string _pendingLobbyPassword = "";
|
|
|
|
|
private string _pendingLobbyRoomName = "";
|
|
|
|
|
private bool _pendingLobbyIsPublic = true;
|
|
|
|
|
@ -98,6 +104,7 @@ namespace TH1_Logic.Steam
|
|
|
|
|
// 房间列表
|
|
|
|
|
private List<LobbyListInfo> _lobbyListInfos;
|
|
|
|
|
public List<LobbyListInfo> LobbyListInfos => _lobbyListInfos;
|
|
|
|
|
private readonly HashSet<ulong> _lobbyReporters = new HashSet<ulong>();
|
|
|
|
|
|
|
|
|
|
// 事件委托
|
|
|
|
|
public event System.Action<CSteamID> OnLobbyCreatedEvent; // 房间创建成功
|
|
|
|
|
@ -991,11 +998,13 @@ namespace TH1_Logic.Steam
|
|
|
|
|
OwnerId = _selfID.m_SteamID,
|
|
|
|
|
|
|
|
|
|
OwnerName = SteamMatchmaking.GetLobbyData(CurrentLobby, "Owner"),
|
|
|
|
|
RoomName = SteamMatchmaking.GetLobbyData(CurrentLobby, "RoomName"),
|
|
|
|
|
RoomName = SteamMatchmaking.GetLobbyData(CurrentLobby, LobbyRoomNameKey),
|
|
|
|
|
Version = SteamMatchmaking.GetLobbyData(CurrentLobby, "Version"),
|
|
|
|
|
CurrentPlayers = SteamMatchmaking.GetNumLobbyMembers(CurrentLobby),
|
|
|
|
|
MaxPlayers = SteamMatchmaking.GetLobbyMemberLimit(CurrentLobby),
|
|
|
|
|
GameState = GetLobbyGameStateFromData(CurrentLobby),
|
|
|
|
|
HasPassword = LobbyHasPassword(CurrentLobby),
|
|
|
|
|
ReportCount = GetLobbyReportCountFromData(CurrentLobby),
|
|
|
|
|
};
|
|
|
|
|
var data = new InviteMessage();
|
|
|
|
|
data.LobbyInfo = lobbyInfo;
|
|
|
|
|
@ -1020,6 +1029,98 @@ namespace TH1_Logic.Steam
|
|
|
|
|
LogSystem.LogInfo($"Game invite sent to: {targetSteamId}");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool ReportLobby(LobbyListInfo lobbyInfo)
|
|
|
|
|
{
|
|
|
|
|
if (lobbyInfo == null || lobbyInfo.LobbyId == 0)
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogError("Report lobby failed: invalid lobby info");
|
|
|
|
|
NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyOperationFailed);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lobbyInfo.OwnerId == 0)
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogError($"Report lobby failed: missing owner Steam ID, lobby={lobbyInfo.LobbyId}");
|
|
|
|
|
NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyOperationFailed);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var selfId = GetSelfMemberId();
|
|
|
|
|
if (selfId == 0)
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogError("Report lobby failed: missing self Steam ID");
|
|
|
|
|
NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyOperationFailed);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lobbyInfo.OwnerId == selfId)
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogInfo($"Report lobby skipped: cannot report own lobby, lobby={lobbyInfo.LobbyId}");
|
|
|
|
|
NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyOperationFailed);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var targetId = new CSteamID(lobbyInfo.OwnerId);
|
|
|
|
|
if (!targetId.IsValid())
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogError($"Report lobby failed: invalid owner Steam ID, owner={lobbyInfo.OwnerId}, lobby={lobbyInfo.LobbyId}");
|
|
|
|
|
NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyOperationFailed);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var data = new LobbyReportMessage
|
|
|
|
|
{
|
|
|
|
|
LobbyId = lobbyInfo.LobbyId,
|
|
|
|
|
ReporterId = selfId,
|
|
|
|
|
Version = ConfigManager.Instance.VersionCfg.CurVersionInfo.Version,
|
|
|
|
|
};
|
|
|
|
|
var bytes = MemoryPackSerializer.Serialize<BaseMessage>(data);
|
|
|
|
|
if (!SimpleP2P.Instance.SendToWithOutConnect(targetId, bytes))
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogError($"Report lobby failed: send to owner failed, lobby={lobbyInfo.LobbyId}, owner={lobbyInfo.OwnerId}");
|
|
|
|
|
NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyOperationFailed);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LogSystem.LogInfo($"Report lobby sent: lobby={lobbyInfo.LobbyId}, owner={lobbyInfo.OwnerId}, reporter={selfId}");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnReceivedLobbyReport(LobbyReportMessage message)
|
|
|
|
|
{
|
|
|
|
|
if (message == null) return;
|
|
|
|
|
if (!IsLobbyOwner()) return;
|
|
|
|
|
if (!CurrentLobby.IsValid() || message.LobbyId != CurrentLobby.m_SteamID)
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogWarning($"Ignore lobby report for unmatched lobby: current={CurrentLobby.m_SteamID}, report={message.LobbyId}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (message.ReporterId == 0 || message.ReporterId == GetSelfMemberId())
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogWarning($"Ignore invalid lobby report: lobby={message.LobbyId}, reporter={message.ReporterId}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_lobbyReporters.Contains(message.ReporterId))
|
|
|
|
|
{
|
|
|
|
|
LogSystem.LogInfo($"Ignore duplicate lobby report: lobby={message.LobbyId}, reporter={message.ReporterId}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_lobbyReporters.Add(message.ReporterId);
|
|
|
|
|
var reportCount = GetLobbyReportCountFromData(CurrentLobby) + 1;
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyReportCountKey, reportCount.ToString());
|
|
|
|
|
LogSystem.LogInfo($"Lobby report received: lobby={message.LobbyId}, reporter={message.ReporterId}, count={reportCount}");
|
|
|
|
|
|
|
|
|
|
if (reportCount <= LobbyReportRenameThreshold) return;
|
|
|
|
|
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyRoomNameKey, ReportedLobbyDefaultRoomName);
|
|
|
|
|
RoomName = ReportedLobbyDefaultRoomName;
|
|
|
|
|
EventManager.Publish(new UpdateUIOutsideMultiplayLobbyList());
|
|
|
|
|
LogSystem.LogInfo($"Lobby report count exceeded threshold, room name reset: lobby={message.LobbyId}, count={reportCount}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 搜索房间
|
|
|
|
|
public void SearchPublicLobbies(ELobbyDistanceFilter filter = ELobbyDistanceFilter.k_ELobbyDistanceFilterWorldwide,
|
|
|
|
|
@ -1055,20 +1156,9 @@ namespace TH1_Logic.Steam
|
|
|
|
|
for (int i = 0; i < data.m_nLobbiesMatching; i++)
|
|
|
|
|
{
|
|
|
|
|
var lobbyId = SteamMatchmaking.GetLobbyByIndex(i);
|
|
|
|
|
var ownerId = SteamMatchmaking.GetLobbyOwner(lobbyId);
|
|
|
|
|
|
|
|
|
|
_lobbyListInfos.Add(new LobbyListInfo
|
|
|
|
|
{
|
|
|
|
|
LobbyId = lobbyId.m_SteamID,
|
|
|
|
|
OwnerId = ownerId.m_SteamID,
|
|
|
|
|
OwnerName = SteamMatchmaking.GetLobbyData(lobbyId, "Owner"),
|
|
|
|
|
RoomName = SteamMatchmaking.GetLobbyData(lobbyId, "RoomName"),
|
|
|
|
|
Version = SteamMatchmaking.GetLobbyData(lobbyId, "Version"),
|
|
|
|
|
CurrentPlayers = SteamMatchmaking.GetNumLobbyMembers(lobbyId),
|
|
|
|
|
MaxPlayers = SteamMatchmaking.GetLobbyMemberLimit(lobbyId),
|
|
|
|
|
GameState = int.Parse(SteamMatchmaking.GetLobbyData(lobbyId, "GameState")),
|
|
|
|
|
HasPassword = LobbyHasPassword(lobbyId),
|
|
|
|
|
});
|
|
|
|
|
var lobbyInfo = new LobbyListInfo { LobbyId = lobbyId.m_SteamID };
|
|
|
|
|
RefreshLobbyListInfo(lobbyInfo, lobbyId);
|
|
|
|
|
_lobbyListInfos.Add(lobbyInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 触发UI刷新事件
|
|
|
|
|
@ -1081,19 +1171,47 @@ namespace TH1_Logic.Steam
|
|
|
|
|
foreach (var lobbyInfo in _lobbyListInfos)
|
|
|
|
|
{
|
|
|
|
|
var cSteamId = new CSteamID(lobbyInfo.LobbyId);
|
|
|
|
|
lobbyInfo.OwnerName = SteamMatchmaking.GetLobbyData(cSteamId, "Owner");
|
|
|
|
|
lobbyInfo.RoomName = SteamMatchmaking.GetLobbyData(cSteamId, "RoomName");
|
|
|
|
|
lobbyInfo.Version = SteamMatchmaking.GetLobbyData(cSteamId, "Version");
|
|
|
|
|
lobbyInfo.CurrentPlayers = SteamMatchmaking.GetNumLobbyMembers(cSteamId);
|
|
|
|
|
lobbyInfo.MaxPlayers = SteamMatchmaking.GetLobbyMemberLimit(cSteamId);
|
|
|
|
|
lobbyInfo.GameState = int.Parse(SteamMatchmaking.GetLobbyData(cSteamId, "GameState"));
|
|
|
|
|
lobbyInfo.HasPassword = LobbyHasPassword(cSteamId);
|
|
|
|
|
RefreshLobbyListInfo(lobbyInfo, cSteamId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshLobbyListInfo(LobbyListInfo lobbyInfo, CSteamID lobbyId)
|
|
|
|
|
{
|
|
|
|
|
if (lobbyInfo == null) return;
|
|
|
|
|
lobbyInfo.LobbyId = lobbyId.m_SteamID;
|
|
|
|
|
lobbyInfo.OwnerId = GetLobbyOwnerSteamIdFromData(lobbyId);
|
|
|
|
|
lobbyInfo.OwnerName = SteamMatchmaking.GetLobbyData(lobbyId, "Owner");
|
|
|
|
|
lobbyInfo.RoomName = SteamMatchmaking.GetLobbyData(lobbyId, LobbyRoomNameKey);
|
|
|
|
|
lobbyInfo.Version = SteamMatchmaking.GetLobbyData(lobbyId, "Version");
|
|
|
|
|
lobbyInfo.CurrentPlayers = SteamMatchmaking.GetNumLobbyMembers(lobbyId);
|
|
|
|
|
lobbyInfo.MaxPlayers = SteamMatchmaking.GetLobbyMemberLimit(lobbyId);
|
|
|
|
|
lobbyInfo.GameState = GetLobbyGameStateFromData(lobbyId);
|
|
|
|
|
lobbyInfo.HasPassword = LobbyHasPassword(lobbyId);
|
|
|
|
|
lobbyInfo.ReportCount = GetLobbyReportCountFromData(lobbyId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static ulong GetLobbyOwnerSteamIdFromData(CSteamID lobbyId)
|
|
|
|
|
{
|
|
|
|
|
var ownerIdData = SteamMatchmaking.GetLobbyData(lobbyId, LobbyOwnerSteamIdKey);
|
|
|
|
|
return ulong.TryParse(ownerIdData, out var ownerId) ? ownerId : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int GetLobbyReportCountFromData(CSteamID lobbyId)
|
|
|
|
|
{
|
|
|
|
|
var reportCountData = SteamMatchmaking.GetLobbyData(lobbyId, LobbyReportCountKey);
|
|
|
|
|
return int.TryParse(reportCountData, out var reportCount) && reportCount > 0 ? reportCount : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int GetLobbyGameStateFromData(CSteamID lobbyId)
|
|
|
|
|
{
|
|
|
|
|
var gameStateData = SteamMatchmaking.GetLobbyData(lobbyId, LobbyGameStateKey);
|
|
|
|
|
return int.TryParse(gameStateData, out var gameState) ? gameState : 0;
|
|
|
|
|
|
|
|
|
|
public static string GetDefaultRoomName(string selfName)
|
|
|
|
|
{
|
|
|
|
|
return selfName + MultilingualManager.Instance.GetMultilingualText(Table.Instance.TextDataAssets.OutsideMultiplayRoomNameSuffix);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 过滤房间名称,只保留中文、英文字母、数字和常用符号
|
|
|
|
|
@ -1264,6 +1382,7 @@ namespace TH1_Logic.Steam
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CurrentLobby = new CSteamID(data.m_ulSteamIDLobby);
|
|
|
|
|
_lobbyReporters.Clear();
|
|
|
|
|
if (!TrySteamApi("OnLobbyCreatedCallback.GetSteamID", SteamUser.GetSteamID, out CachedOwner))
|
|
|
|
|
{
|
|
|
|
|
ResetLobbyState();
|
|
|
|
|
@ -1275,10 +1394,14 @@ namespace TH1_Logic.Steam
|
|
|
|
|
// 设置房间基础数据
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, "Game", "TOHOTOPIA");
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, "Owner", SelfName);
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyOwnerSteamIdKey, _selfID.m_SteamID.ToString());
|
|
|
|
|
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, LobbyRoomNameKey, 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, LobbyGameStateKey, "0");
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyReportCountKey, "0");
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyHasPasswordKey, string.IsNullOrEmpty(_pendingLobbyPassword) ? "false" : "true");
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyPasswordKey, _pendingLobbyPassword);
|
|
|
|
|
SteamMatchmaking.SetLobbyData(CurrentLobby, LobbyIsPublicKey, _pendingLobbyIsPublic ? "true" : "false");
|
|
|
|
|
@ -1524,6 +1647,7 @@ namespace TH1_Logic.Steam
|
|
|
|
|
_pendingLobbyRoomName = "";
|
|
|
|
|
_pendingLobbyIsPublic = true;
|
|
|
|
|
ClearPendingJoinLobby();
|
|
|
|
|
_lobbyReporters.Clear();
|
|
|
|
|
|
|
|
|
|
// 清除Rich Presence
|
|
|
|
|
SteamFriends.ClearRichPresence();
|
|
|
|
|
@ -1936,5 +2060,6 @@ namespace TH1_Logic.Steam
|
|
|
|
|
public int MaxPlayers;
|
|
|
|
|
public int GameState;
|
|
|
|
|
public bool HasPassword;
|
|
|
|
|
public int ReportCount;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|