578 lines
22 KiB
C#
578 lines
22 KiB
C#
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Logic.CrashSight;
|
||
using Steamworks;
|
||
using TH1_Logic.Net;
|
||
using UnityEngine;
|
||
|
||
|
||
namespace TH1_Logic.Steam
|
||
{
|
||
public class SteamLobbyManager : ILobby
|
||
{
|
||
public CSteamID CurrentLobby = CSteamID.Nil;
|
||
public CSteamID CachedOwner = CSteamID.Nil;
|
||
public LobbyState CurrentState { get; private set; } = LobbyState.None;
|
||
|
||
// 事件委托
|
||
public event System.Action<CSteamID> OnLobbyCreatedEvent; // 房间创建成功
|
||
public event System.Action<CSteamID> OnLobbyEnteredEvent; // 进入房间
|
||
public event System.Action OnLobbyLeftEvent; // 离开房间
|
||
public event System.Action<CSteamID, CSteamID> OnHostChangedEvent; // 房主变更 (oldHost, newHost)
|
||
public event System.Action<List<CSteamID>> OnMembersChangedEvent; // 成员变化
|
||
public event System.Action<string> OnLobbyErrorEvent; // 房间错误
|
||
public event System.Action<CSteamID> OnMemberJoinedEvent; // 成员加入
|
||
public event System.Action<CSteamID> OnMemberLeftEvent; // 成员离开
|
||
|
||
// LobbyCreated_t
|
||
// 谁会收到:只有调用 CreateLobby 的本机(创建者)。
|
||
// 何时触发:SteamMatchmaking.CreateLobby 异步完成后。
|
||
// 成功判定:data.m_eResult == k_EResultOK。失败则不会进入房间,也不会再收到 LobbyEnter_t。
|
||
// 用途:确认为房主,保存 LobbyID,设置 LobbyData / Rich Presence,然后等别人加入。
|
||
private Callback<LobbyCreated_t> _cbLobbyCreated;
|
||
|
||
// 谁会收到:被邀请者、或通过好友资料 / 邀请链接 / Overlay 点"加入"你 Lobby 的玩家客户端。
|
||
// 何时触发:玩家端点击接受邀请(或点击你在好友列表中的"加入游戏")后,Steam 向你的进程派发此回调。
|
||
// 典型处理:立即调用 SteamMatchmaking.JoinLobby(data.m_steamIDLobby)。不代表已经进房,只是"请求加入"。
|
||
private Callback<GameLobbyJoinRequested_t> _cbLobbyJoinRequested;
|
||
|
||
// 谁会收到:任意成功进入 Lobby 的客户端(包括创建者自己与每个加入者)。
|
||
// 何时触发:JoinLobby(或 CreateLobby 成功后的内部自动加入)完成并真正加入成员列表后。
|
||
// 作用:此时可读取成员列表 / LobbyData,更新 UI,开始建立 P2P。
|
||
// 注意:创建者会先收到 LobbyCreated_t,随后收到自己的 LobbyEnter_t。被邀请者只会收到 GameLobbyJoinRequested_t →(调用 JoinLobby)→ LobbyEnter_t。
|
||
private Callback<LobbyEnter_t> _cbLobbyEnter;
|
||
|
||
// 谁会收到:当前已在该 Lobby 中的所有成员。
|
||
// 何时触发:成员进入、离开、断线、被踢、被封禁等成员列表变化时。可能多次。
|
||
// 数据意义:data.m_ulSteamIDLobby = 目标 Lobby;data.m_ulSteamIDUserChanged = 发生变化的成员;data.m_ulSteamIDMakingChange = 触发者(踢人时是房主);data.m_rgfChatMemberStateChange 标志位指示加入/离开/踢/封禁等。
|
||
// 用途:刷新成员 UI,迁移 Host(若房主离开), 清理对应的 P2P 连接。
|
||
private Callback<LobbyChatUpdate_t> _cbLobbyChatUpdate;
|
||
|
||
// 初始化
|
||
public void InitCallbacks()
|
||
{
|
||
_cbLobbyCreated = Callback<LobbyCreated_t>.Create(OnLobbyCreatedCallback);
|
||
_cbLobbyJoinRequested = Callback<GameLobbyJoinRequested_t>.Create(OnLobbyJoinRequestedCallback);
|
||
_cbLobbyEnter = Callback<LobbyEnter_t>.Create(OnLobbyEnterCallback);
|
||
_cbLobbyChatUpdate = Callback<LobbyChatUpdate_t>.Create(OnLobbyChatUpdateCallback);
|
||
|
||
// 初始化P2P
|
||
SimpleP2P.Instance.Initialize();
|
||
|
||
// 订阅P2P事件
|
||
SimpleP2P.Instance.OnPeerConnectedEvent += OnP2PPeerConnected;
|
||
SimpleP2P.Instance.OnPeerDisconnectedEvent += OnP2PPeerDisconnected;
|
||
SimpleP2P.Instance.OnConnectionErrorEvent += OnP2PConnectionError;
|
||
|
||
LogSystem.LogInfo("SteamLobbyManager initialized");
|
||
}
|
||
|
||
// 建房
|
||
public void CreateFriendsLobby(int maxMembers = 4)
|
||
{
|
||
if (CurrentState != LobbyState.None)
|
||
{
|
||
LogSystem.LogInfo($"Cannot create lobby in state: {CurrentState}");
|
||
return;
|
||
}
|
||
|
||
CurrentState = LobbyState.Creating;
|
||
LogSystem.LogInfo($"Creating friends lobby with max members: {maxMembers}");
|
||
SteamMatchmaking.CreateLobby(ELobbyType.k_ELobbyTypeFriendsOnly, maxMembers);
|
||
}
|
||
|
||
// 加入房间
|
||
public void JoinLobby(CSteamID lobbyId)
|
||
{
|
||
if (CurrentState != LobbyState.None)
|
||
{
|
||
LogSystem.LogInfo($"Cannot join lobby in state: {CurrentState}");
|
||
return;
|
||
}
|
||
|
||
LogSystem.LogInfo($"Joining lobby: {lobbyId}");
|
||
CurrentState = LobbyState.Joining;
|
||
SteamMatchmaking.JoinLobby(lobbyId);
|
||
}
|
||
|
||
// 离开房间
|
||
public void LeaveLobby()
|
||
{
|
||
if (!CurrentLobby.IsValid() || CurrentState == LobbyState.None) return;
|
||
|
||
CurrentState = LobbyState.Leaving;
|
||
LogSystem.LogInfo("Leaving lobby");
|
||
|
||
// 断开所有P2P连接
|
||
SimpleP2P.Instance.DisconnectAll();
|
||
SteamMatchmaking.LeaveLobby(CurrentLobby);
|
||
ResetLobbyState();
|
||
}
|
||
|
||
// 解散房间(仅房主可用)
|
||
public void DisbandLobby()
|
||
{
|
||
if (!IsLobbyOwner())
|
||
{
|
||
LogSystem.LogInfo("Only lobby owner can disband the lobby");
|
||
return;
|
||
}
|
||
|
||
LogSystem.LogInfo("Disbanding lobby");
|
||
// 设置房间数据标记解散
|
||
SteamMatchmaking.SetLobbyData(CurrentLobby, "disbanded", "true");
|
||
// 踢出所有其他成员
|
||
foreach (var member in EnumerateMembers())
|
||
{
|
||
if (member != SteamUser.GetSteamID())
|
||
{
|
||
// Steam没有直接踢人API,通过设置数据让客户端自动离开
|
||
SteamMatchmaking.SetLobbyMemberData(CurrentLobby, "kicked", "true");
|
||
}
|
||
}
|
||
|
||
// 房主最后离开
|
||
LeaveLobby();
|
||
}
|
||
|
||
// 踢出指定成员(仅房主可用)
|
||
public void KickMember(CSteamID memberToKick)
|
||
{
|
||
if (!IsLobbyOwner())
|
||
{
|
||
OnLobbyErrorEvent?.Invoke("Only lobby owner can kick members");
|
||
return;
|
||
}
|
||
|
||
if (memberToKick == SteamUser.GetSteamID())
|
||
{
|
||
OnLobbyErrorEvent?.Invoke("Cannot kick yourself");
|
||
return;
|
||
}
|
||
|
||
LogSystem.LogInfo($"Kicking member: {memberToKick}");
|
||
|
||
// 通过设置成员数据标记被踢,客户端检测到后自动离开
|
||
SteamMatchmaking.SetLobbyMemberData(CurrentLobby, $"kick_{memberToKick.m_SteamID}", "true");
|
||
}
|
||
|
||
// 邀请好友
|
||
public void InviteFriend(CSteamID friendId)
|
||
{
|
||
if (!CurrentLobby.IsValid())
|
||
{
|
||
OnLobbyErrorEvent?.Invoke("Not in a lobby");
|
||
return;
|
||
}
|
||
|
||
LogSystem.LogInfo($"Inviting friend: {friendId}");
|
||
SteamMatchmaking.InviteUserToLobby(CurrentLobby, friendId);
|
||
}
|
||
|
||
// 打开好友邀请对话框
|
||
public void OpenInviteOverlay()
|
||
{
|
||
if (!CurrentLobby.IsValid())
|
||
{
|
||
OnLobbyErrorEvent?.Invoke("Not in a lobby");
|
||
return;
|
||
}
|
||
|
||
SteamFriends.ActivateGameOverlayInviteDialog(CurrentLobby);
|
||
}
|
||
|
||
// 获取在线好友
|
||
public List<(CSteamID id, string name)> GetOnlineFriends()
|
||
{
|
||
var list = new List<(CSteamID, string)>();
|
||
int count = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate);
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
var fid = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate);
|
||
var state = SteamFriends.GetFriendPersonaState(fid);
|
||
if (state == EPersonaState.k_EPersonaStateOnline ||
|
||
state == EPersonaState.k_EPersonaStateAway ||
|
||
state == EPersonaState.k_EPersonaStateBusy ||
|
||
state == EPersonaState.k_EPersonaStateSnooze)
|
||
{
|
||
list.Add((fid, SteamFriends.GetFriendPersonaName(fid)));
|
||
}
|
||
}
|
||
return list;
|
||
}
|
||
|
||
// 设置房间数据
|
||
public void SetLobbyData(string key, string value)
|
||
{
|
||
if (!IsLobbyOwner())
|
||
{
|
||
OnLobbyErrorEvent?.Invoke("Only lobby owner can set lobby data");
|
||
return;
|
||
}
|
||
|
||
if (!CurrentLobby.IsValid()) return;
|
||
|
||
SteamMatchmaking.SetLobbyData(CurrentLobby, key, value);
|
||
}
|
||
|
||
// 获取房间数据
|
||
public string GetLobbyData(string key)
|
||
{
|
||
if (!CurrentLobby.IsValid()) return "";
|
||
return SteamMatchmaking.GetLobbyData(CurrentLobby, key);
|
||
}
|
||
|
||
// 房间创建回调
|
||
private void OnLobbyCreatedCallback(LobbyCreated_t data)
|
||
{
|
||
if (data.m_eResult != EResult.k_EResultOK)
|
||
{
|
||
CurrentState = LobbyState.None;
|
||
OnLobbyErrorEvent?.Invoke($"Failed to create lobby: {data.m_eResult}");
|
||
return;
|
||
}
|
||
|
||
CurrentLobby = new CSteamID(data.m_ulSteamIDLobby);
|
||
CachedOwner = SteamUser.GetSteamID();
|
||
|
||
LogSystem.LogInfo($"Lobby created successfully: {CurrentLobby}");
|
||
|
||
// 设置房间基础数据
|
||
SteamMatchmaking.SetLobbyData(CurrentLobby, "owner", SteamUser.GetSteamID().m_SteamID.ToString());
|
||
SteamMatchmaking.SetLobbyData(CurrentLobby, "version", "1.0");
|
||
SteamMatchmaking.SetLobbyData(CurrentLobby, "game_mode", "default");
|
||
|
||
// 设置Rich Presence
|
||
SteamFriends.SetRichPresence("connect", "+connect_lobby " + CurrentLobby.m_SteamID);
|
||
SteamFriends.SetRichPresence("status", "In Lobby");
|
||
|
||
OnLobbyCreatedEvent?.Invoke(CurrentLobby);
|
||
}
|
||
|
||
// 加入请求回调
|
||
private void OnLobbyJoinRequestedCallback(GameLobbyJoinRequested_t data)
|
||
{
|
||
LogSystem.LogInfo($"Join requested for lobby: {data.m_steamIDLobby}");
|
||
|
||
// 检查是否被踢或房间被解散
|
||
var disbandedData = SteamMatchmaking.GetLobbyData(data.m_steamIDLobby, "disbanded");
|
||
if (disbandedData == "true")
|
||
{
|
||
LogSystem.LogInfo($"Cannot join disbanded lobby");
|
||
return;
|
||
}
|
||
|
||
JoinLobby(data.m_steamIDLobby);
|
||
}
|
||
|
||
// 进入房间回调
|
||
private void OnLobbyEnterCallback(LobbyEnter_t data)
|
||
{
|
||
// 检查加入结果
|
||
if ((EChatRoomEnterResponse)data.m_EChatRoomEnterResponse != EChatRoomEnterResponse.k_EChatRoomEnterResponseSuccess)
|
||
{
|
||
CurrentState = LobbyState.None;
|
||
LogSystem.LogError($"Failed to enter lobby: {(EChatRoomEnterResponse)data.m_EChatRoomEnterResponse}");
|
||
return;
|
||
}
|
||
|
||
CurrentLobby = new CSteamID(data.m_ulSteamIDLobby);
|
||
CachedOwner = SteamMatchmaking.GetLobbyOwner(CurrentLobby);
|
||
CurrentState = LobbyState.InLobby;
|
||
|
||
LogSystem.LogInfo($"Successfully entered lobby: {CurrentLobby}");
|
||
|
||
// 检查是否被踢
|
||
CheckIfKicked();
|
||
OnLobbyReadyInternal();
|
||
OnLobbyMembersChangedInternal();
|
||
}
|
||
|
||
// 成员变化回调
|
||
private void OnLobbyChatUpdateCallback(LobbyChatUpdate_t data)
|
||
{
|
||
if (data.m_ulSteamIDLobby != CurrentLobby.m_SteamID) return;
|
||
|
||
var changedUser = new CSteamID(data.m_ulSteamIDUserChanged);
|
||
var stateChange = (EChatMemberStateChange)data.m_rgfChatMemberStateChange;
|
||
|
||
LogSystem.LogInfo($"Lobby member update: {changedUser} - {stateChange}");
|
||
|
||
// 处理成员状态变化
|
||
if (stateChange.HasFlag(EChatMemberStateChange.k_EChatMemberStateChangeEntered))
|
||
{
|
||
OnMemberJoinedEvent?.Invoke(changedUser);
|
||
|
||
// 如果我是房主,尝试连接到新成员
|
||
if (IsLobbyOwner() && changedUser != SteamUser.GetSteamID())
|
||
{
|
||
SimpleP2P.Instance.ConnectToPeer(changedUser);
|
||
}
|
||
}
|
||
else if (stateChange.HasFlag(EChatMemberStateChange.k_EChatMemberStateChangeLeft) ||
|
||
stateChange.HasFlag(EChatMemberStateChange.k_EChatMemberStateChangeDisconnected) ||
|
||
stateChange.HasFlag(EChatMemberStateChange.k_EChatMemberStateChangeKicked) ||
|
||
stateChange.HasFlag(EChatMemberStateChange.k_EChatMemberStateChangeBanned))
|
||
{
|
||
OnMemberLeftEvent?.Invoke(changedUser);
|
||
|
||
// 断开P2P连接
|
||
SimpleP2P.Instance.DisconnectFromPeer(changedUser);
|
||
}
|
||
|
||
OnLobbyMembersChangedInternal();
|
||
CheckOwnerChange();
|
||
}
|
||
|
||
// 检查房主变化
|
||
private void CheckOwnerChange()
|
||
{
|
||
if (!CurrentLobby.IsValid()) return;
|
||
|
||
var currentOwner = SteamMatchmaking.GetLobbyOwner(CurrentLobby);
|
||
if (!CachedOwner.IsValid())
|
||
{
|
||
CachedOwner = currentOwner;
|
||
return;
|
||
}
|
||
|
||
if (currentOwner != CachedOwner)
|
||
{
|
||
var oldOwner = CachedOwner;
|
||
CachedOwner = currentOwner;
|
||
|
||
LogSystem.LogInfo($"Host changed from {oldOwner} to {currentOwner}");
|
||
|
||
OnHostChangedEvent?.Invoke(oldOwner, currentOwner);
|
||
OnHostChangedInternal();
|
||
}
|
||
}
|
||
|
||
// 房主切换时内部处理
|
||
private void OnHostChangedInternal()
|
||
{
|
||
if (IsLobbyOwner())
|
||
{
|
||
LogSystem.LogInfo("I became the new host");
|
||
|
||
// 新房主连接到所有其他成员
|
||
foreach (var member in EnumerateMembers())
|
||
{
|
||
if (member != SteamUser.GetSteamID())
|
||
{
|
||
SimpleP2P.Instance.ConnectToPeer(member);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LogSystem.LogInfo($"New host is: {CachedOwner}");
|
||
|
||
// 普通成员断开旧连接,连接新房主
|
||
SimpleP2P.Instance.DisconnectAll();
|
||
SimpleP2P.Instance.ConnectToPeer(CachedOwner);
|
||
}
|
||
}
|
||
|
||
// 房间准备完毕时内部处理
|
||
private void OnLobbyReadyInternal()
|
||
{
|
||
// 如果不是房主,连接到房主
|
||
if (!IsLobbyOwner() && CachedOwner.IsValid())
|
||
{
|
||
SimpleP2P.Instance.ConnectToPeer(CachedOwner);
|
||
}
|
||
}
|
||
|
||
// 有成员变化时内部处理
|
||
private void OnLobbyMembersChangedInternal()
|
||
{
|
||
var members = EnumerateMembers().ToList();
|
||
LogSystem.LogInfo($"Lobby members changed. Count: {members.Count}");
|
||
OnMembersChangedEvent?.Invoke(members);
|
||
}
|
||
|
||
// 检查是否被踢
|
||
private void CheckIfKicked()
|
||
{
|
||
var kickData = SteamMatchmaking.GetLobbyMemberData(CurrentLobby, SteamUser.GetSteamID(), "kicked");
|
||
var specificKick = SteamMatchmaking.GetLobbyData(CurrentLobby, $"kick_{SteamUser.GetSteamID().m_SteamID}");
|
||
|
||
if (kickData == "true" || specificKick == "true")
|
||
{
|
||
LogSystem.LogInfo("I was kicked from the lobby");
|
||
LeaveLobby();
|
||
}
|
||
}
|
||
|
||
// 重置房间状态
|
||
private void ResetLobbyState()
|
||
{
|
||
CurrentLobby = CSteamID.Nil;
|
||
CachedOwner = CSteamID.Nil;
|
||
CurrentState = LobbyState.None;
|
||
|
||
// 清除Rich Presence
|
||
SteamFriends.ClearRichPresence();
|
||
}
|
||
|
||
// P2P事件处理
|
||
private void OnP2PPeerConnected(CSteamID steamID)
|
||
{
|
||
LogSystem.LogInfo($"P2P connection established with: {steamID}");
|
||
}
|
||
|
||
private void OnP2PPeerDisconnected(CSteamID steamID)
|
||
{
|
||
LogSystem.LogInfo($"P2P connection lost with: {steamID}");
|
||
}
|
||
|
||
private void OnP2PConnectionError(string error)
|
||
{
|
||
LogSystem.LogError($"P2P connection error: {error}");
|
||
}
|
||
|
||
// 轮询P2P消息(需要在Update中调用)
|
||
public void Update()
|
||
{
|
||
SimpleP2P.Instance.PollMessages();
|
||
}
|
||
|
||
// 发送P2P消息
|
||
public bool SendMessageToPeer(ulong member, byte[] data, bool reliable = true)
|
||
{
|
||
if (!IsInLobby())
|
||
{
|
||
OnLobbyErrorEvent?.Invoke("Not in lobby");
|
||
return false;
|
||
}
|
||
|
||
if (IsMemberInLobby(member)) return false;
|
||
if (member == GetSelfMemberId()) return false;
|
||
var cSteamId = new CSteamID(member);
|
||
return SimpleP2P.Instance.SendTo(cSteamId, data, reliable);
|
||
}
|
||
|
||
// 广播P2P消息
|
||
public void BroadcastMessage(byte[] data, bool reliable = true)
|
||
{
|
||
if (!IsInLobby())
|
||
{
|
||
OnLobbyErrorEvent?.Invoke("Not in lobby");
|
||
return;
|
||
}
|
||
|
||
SimpleP2P.Instance.Broadcast(data, reliable);
|
||
}
|
||
|
||
// 枚举房间成员
|
||
private IEnumerable<CSteamID> EnumerateMembers()
|
||
{
|
||
if (!CurrentLobby.IsValid()) yield break;
|
||
int count = SteamMatchmaking.GetNumLobbyMembers(CurrentLobby);
|
||
for (int i = 0; i < count; i++)
|
||
yield return SteamMatchmaking.GetLobbyMemberByIndex(CurrentLobby, i);
|
||
}
|
||
|
||
// 获取房间所有成员
|
||
public List<ulong> GetAllMemberIds()
|
||
{
|
||
if (!CurrentLobby.IsValid()) return new List<ulong>();
|
||
int count = SteamMatchmaking.GetNumLobbyMembers(CurrentLobby);
|
||
var list = new List<ulong>();
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
var cSteamId = SteamMatchmaking.GetLobbyMemberByIndex(CurrentLobby, i);
|
||
list.Add(cSteamId.m_SteamID);
|
||
}
|
||
return list;
|
||
}
|
||
|
||
// 获取成员数量
|
||
public int GetMemberCount()
|
||
{
|
||
if (!CurrentLobby.IsValid()) return 0;
|
||
return SteamMatchmaking.GetNumLobbyMembers(CurrentLobby);
|
||
}
|
||
|
||
// 获取最大成员数
|
||
public int GetMemberLimit()
|
||
{
|
||
if (!CurrentLobby.IsValid()) return 0;
|
||
return SteamMatchmaking.GetLobbyMemberLimit(CurrentLobby);
|
||
}
|
||
|
||
// 判断成员是否在房间中
|
||
public bool IsMemberInLobby(ulong memberId)
|
||
{
|
||
if (!CurrentLobby.IsValid()) return false;
|
||
int count = SteamMatchmaking.GetNumLobbyMembers(CurrentLobby);
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
var cSteamId = SteamMatchmaking.GetLobbyMemberByIndex(CurrentLobby, i);
|
||
if (cSteamId.m_SteamID == memberId) return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// 根据 memberId 获取 CSteamId
|
||
public CSteamID GetCSteamID(ulong memberId)
|
||
{
|
||
if (!CurrentLobby.IsValid()) return CSteamID.Nil;
|
||
int count = SteamMatchmaking.GetNumLobbyMembers(CurrentLobby);
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
var cSteamId = SteamMatchmaking.GetLobbyMemberByIndex(CurrentLobby, i);
|
||
if (cSteamId.m_SteamID == memberId) return cSteamId;
|
||
}
|
||
return CSteamID.Nil;
|
||
}
|
||
|
||
// 获取自己的 memberId
|
||
public ulong GetSelfMemberId()
|
||
{
|
||
return SteamUser.GetSteamID().m_SteamID;
|
||
}
|
||
|
||
// 获取房主的 memberId
|
||
public ulong GetLobbyOwnerId()
|
||
{
|
||
if (!CurrentLobby.IsValid()) return 0;
|
||
var owner = SteamMatchmaking.GetLobbyOwner(CurrentLobby);
|
||
return owner.m_SteamID;
|
||
}
|
||
|
||
// 获取当前房间状态
|
||
public LobbyState GetCurState()
|
||
{
|
||
return CurrentState;
|
||
}
|
||
|
||
// 自己是否是房主
|
||
public bool IsLobbyOwner()
|
||
{
|
||
return IsInLobby() && SteamMatchmaking.GetLobbyOwner(CurrentLobby) == SteamUser.GetSteamID();
|
||
}
|
||
|
||
// 自己是否在房间中
|
||
public bool IsInLobby()
|
||
{
|
||
return CurrentState == LobbyState.InLobby && CurrentLobby.IsValid();
|
||
}
|
||
|
||
// 清理资源
|
||
public void Cleanup()
|
||
{
|
||
LeaveLobby();
|
||
SimpleP2P.Instance.Cleanup();
|
||
|
||
_cbLobbyCreated?.Dispose();
|
||
_cbLobbyJoinRequested?.Dispose();
|
||
_cbLobbyEnter?.Dispose();
|
||
_cbLobbyChatUpdate?.Dispose();
|
||
|
||
LogSystem.LogInfo("SteamLobbyManager cleaned up");
|
||
}
|
||
}
|
||
}
|