# Conflicts:
#	Unity/Assets/Resources/BT/BT.asset
#	Unity/Assets/Resources/BT/DiplomacyStage2.asset
This commit is contained in:
kawagiri 2025-09-02 20:12:35 +08:00
commit 8ab284e5e3
16 changed files with 1535 additions and 35 deletions

View File

@ -30,7 +30,7 @@ MonoBehaviour:
_version: 3.33
_category:
_comments:
_translation: {x: -244.58202, y: -54.64604}
_zoomFactor: 1
_translation: {x: -120, y: 106}
_zoomFactor: 0.6445859
_haltSerialization: 0
_externalSerializationFile: {fileID: 0}

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,7 @@ using Logic.Timeline;
using RuntimeData;
using TH1_Core.Events;
using TH1_Core.Managers;
using TH1_Logic.Steam;
using TH1Renderer;
using TH1Resource;
using UnityEngine;
@ -36,6 +37,7 @@ namespace TH1_Logic.Core
public float AnimationSpeed = 1f;
public bool DebugMode = false;
public bool DebugHideCenterMessage = false;
public bool SteamTest = false;
[Header("Play Settings")]
public int cityCount;
@ -132,6 +134,22 @@ namespace TH1_Logic.Core
//step #7 更新成就的情况
AchievementDataManager.Instance.ReCheckAchievementDataNotComplete();
#if UNITY_EDITOR
if (SteamTest)
{
var obj = this.transform.Find("SteamTest");
if (!obj)
{
obj = new GameObject("SteamTest").transform;
obj.parent = this.transform;
}
var com = obj.GetComponent<SteamTestManager>();
if (!com) com = obj.gameObject.AddComponent<SteamTestManager>();
}
#endif
}
@ -223,18 +241,13 @@ namespace TH1_Logic.Core
AudioManager.Instance.Update();
ConfigManager.Instance.Update();
//如果正在游戏中执行下方的这些update
InputLogic?.Update();
}
public bool HasArchive()
{
return PlayerPrefs.GetInt("Archive", 0) == 1;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a4cdcbaca1344a0399ccc65bd583b481
timeCreated: 1756803391

View File

@ -0,0 +1,119 @@
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System.IO;
namespace TH1_Logic.Steam
{
/// <summary>
/// Steam Build后处理器 - 自动复制steam_appid.txt到Build目录
/// </summary>
public class SteamBuildPostProcessor
{
[PostProcessBuild(1)]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
{
// 只处理Windows平台的Build
if (target != BuildTarget.StandaloneWindows && target != BuildTarget.StandaloneWindows64)
return;
string projectRoot = Directory.GetParent(Application.dataPath).FullName;
string steamAppIdSource = Path.Combine(projectRoot, "steam_appid.txt");
// 检查源文件是否存在
if (!File.Exists(steamAppIdSource))
{
Debug.LogWarning("[Steam] steam_appid.txt not found in project root. Steam功能可能无法正常工作。");
return;
}
// 确定目标路径与exe文件同级
string buildDirectory = Path.GetDirectoryName(pathToBuiltProject);
string steamAppIdTarget = Path.Combine(buildDirectory, "steam_appid.txt");
try
{
// 复制文件
File.Copy(steamAppIdSource, steamAppIdTarget, true);
Debug.Log($"[Steam] steam_appid.txt 已复制到Build目录: {steamAppIdTarget}");
// 读取并显示App ID
string appId = File.ReadAllText(steamAppIdSource).Trim();
Debug.Log($"[Steam] Steam App ID: {appId}");
}
catch (System.Exception e)
{
Debug.LogError($"[Steam] 复制steam_appid.txt失败: {e.Message}");
}
}
/// <summary>
/// 手动复制steam_appid.txt到指定Build目录
/// </summary>
[MenuItem("Tools/Steam/Copy steam_appid.txt to Build Directory")]
public static void CopySteamAppIdToBuild()
{
string buildPath = EditorUtility.OpenFolderPanel("选择Build目录", "", "");
if (string.IsNullOrEmpty(buildPath))
return;
string projectRoot = Directory.GetParent(Application.dataPath).FullName;
string steamAppIdSource = Path.Combine(projectRoot, "steam_appid.txt");
if (!File.Exists(steamAppIdSource))
{
EditorUtility.DisplayDialog("错误", "项目根目录下未找到steam_appid.txt文件", "确定");
return;
}
string steamAppIdTarget = Path.Combine(buildPath, "steam_appid.txt");
try
{
File.Copy(steamAppIdSource, steamAppIdTarget, true);
EditorUtility.DisplayDialog("成功", $"steam_appid.txt已复制到:\n{steamAppIdTarget}", "确定");
}
catch (System.Exception e)
{
EditorUtility.DisplayDialog("错误", $"复制失败:\n{e.Message}", "确定");
}
}
/// <summary>
/// 验证当前steam_appid.txt配置
/// </summary>
[MenuItem("Tools/Steam/Validate steam_appid.txt")]
public static void ValidateSteamAppId()
{
string projectRoot = Directory.GetParent(Application.dataPath).FullName;
string steamAppIdPath = Path.Combine(projectRoot, "steam_appid.txt");
if (!File.Exists(steamAppIdPath))
{
EditorUtility.DisplayDialog("配置错误",
"未找到steam_appid.txt文件!\n\n请在项目根目录创建此文件并添加Steam App ID。", "确定");
return;
}
string content = File.ReadAllText(steamAppIdPath).Trim();
if (string.IsNullOrEmpty(content))
{
EditorUtility.DisplayDialog("配置错误",
"steam_appid.txt文件为空!\n\n请添加有效的Steam App ID。", "确定");
return;
}
if (!uint.TryParse(content, out uint appId))
{
EditorUtility.DisplayDialog("配置错误",
$"steam_appid.txt内容无效: {content}\n\n请确保文件只包含数字形式的App ID。", "确定");
return;
}
string appName = appId == 480 ? " (Spacewar - 测试应用)" : "";
EditorUtility.DisplayDialog("配置正确",
$"steam_appid.txt配置正确!\n\nApp ID: {appId}{appName}\n文件位置: {steamAppIdPath}", "确定");
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d6a6223ed8844724b62fecf689fa257c
timeCreated: 1756803391

View File

@ -0,0 +1,291 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Logic.CrashSight;
using Steamworks;
using UnityEngine;
namespace TH1_Logic.Steam
{
public class SimpleP2P
{
public static SimpleP2P Instance { get; } = new SimpleP2P();
// 连接映射表SteamID -> 连接句柄
private readonly Dictionary<CSteamID, HSteamNetConnection> _connections = new Dictionary<CSteamID, HSteamNetConnection>();
// 监听套接字
private HSteamListenSocket _listenSocket = HSteamListenSocket.Invalid;
// 回调
private Callback<SteamNetConnectionStatusChangedCallback_t> _cbConnectionStatusChanged;
// 事件委托
public event System.Action<CSteamID> OnPeerConnectedEvent;
public event System.Action<CSteamID> OnPeerDisconnectedEvent;
public event System.Action<CSteamID, byte[]> OnMessageReceivedEvent;
public event System.Action<string> OnConnectionErrorEvent;
// 初始化
public void Initialize()
{
_cbConnectionStatusChanged = Callback<SteamNetConnectionStatusChangedCallback_t>.Create(OnConnectionStatusChanged);
// 创建监听套接字
CreateListenSocket();
}
// 创建监听套接字
private void CreateListenSocket()
{
// 使用默认端口0Steam会自动分配
_listenSocket = SteamNetworkingSockets.CreateListenSocketP2P(0, 0, null);
if (_listenSocket == HSteamListenSocket.Invalid)
{
OnConnectionErrorEvent?.Invoke("Failed to create listen socket");
return;
}
LogSystem.LogInfo($"P2P Listen socket created: {_listenSocket}");
}
// 连接到指定玩家
public bool ConnectToPeer(CSteamID steamID)
{
if (_connections.ContainsKey(steamID))
{
LogSystem.LogInfo($"Already connected to {steamID}");
return true;
}
// 创建到目标玩家的连接
var identity = new SteamNetworkingIdentity();
identity.SetSteamID(steamID);
var connection = SteamNetworkingSockets.ConnectP2P(ref identity, 0, 0, null);
if (connection == HSteamNetConnection.Invalid)
{
OnConnectionErrorEvent?.Invoke($"Failed to connect to {steamID}");
return false;
}
_connections[steamID] = connection;
LogSystem.LogInfo($"Connecting to peer: {steamID}");
return true;
}
// 断开与指定玩家的连接
public void DisconnectFromPeer(CSteamID steamID)
{
if (!_connections.TryGetValue(steamID, out var connection))
return;
SteamNetworkingSockets.CloseConnection(connection, 0, "Disconnected by user", false);
_connections.Remove(steamID);
LogSystem.LogInfo($"Disconnected from peer: {steamID}");
}
// 断开所有连接
public void DisconnectAll()
{
foreach (var kvp in _connections)
{
SteamNetworkingSockets.CloseConnection(kvp.Value, 0, "Disconnecting all", false);
}
_connections.Clear();
LogSystem.LogInfo("Disconnected from all peers");
}
// 连接状态变化回调
private void OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t info)
{
var state = info.m_info.m_eState;
// 获取连接信息
SteamNetworkingSockets.GetConnectionInfo(info.m_hConn, out var connectionInfo);
var remote = connectionInfo.m_identityRemote.GetSteamID();
switch (state)
{
case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connecting:
LogSystem.LogInfo($"Connecting to {remote}...");
break;
case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_FindingRoute:
LogSystem.LogInfo($"Finding route to {remote}...");
break;
case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connected:
LogSystem.LogInfo($"Connected to {remote}");
if (!_connections.ContainsKey(remote))
{
_connections[remote] = info.m_hConn;
}
OnPeerConnectedEvent?.Invoke(remote);
break;
case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ClosedByPeer:
LogSystem.LogInfo($"Connection closed by peer: {remote}");
HandleDisconnection(remote, info.m_hConn);
break;
case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
LogSystem.LogWarning($"Connection problem detected locally: {remote}");
HandleDisconnection(remote, info.m_hConn);
break;
case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_None:
// 连接被拒绝或失败
LogSystem.LogError($"Connection failed or rejected: {remote}");
HandleDisconnection(remote, info.m_hConn);
break;
}
}
// 处理断开连接
private void HandleDisconnection(CSteamID steamID, HSteamNetConnection connection)
{
if (_connections.ContainsKey(steamID))
{
_connections.Remove(steamID);
OnPeerDisconnectedEvent?.Invoke(steamID);
}
SteamNetworkingSockets.CloseConnection(connection, 0, "", false);
}
// 发送消息到指定玩家
public bool SendTo(CSteamID target, byte[] data, bool reliable = true)
{
if (data == null || data.Length == 0)
{
LogSystem.LogWarning("Trying to send null or empty data");
return false;
}
if (!_connections.TryGetValue(target, out var conn))
{
LogSystem.LogWarning($"No connection to {target}");
return false;
}
// 可靠传输=8不可靠传输=0
int flags = reliable ? 8 : 0;
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, ptr, data.Length);
var result = SteamNetworkingSockets.SendMessageToConnection(conn, ptr, (uint)data.Length, flags, out _);
if (result != EResult.k_EResultOK)
{
LogSystem.LogError($"Failed to send message to {target}: {result}");
return false;
}
return true;
}
catch (Exception e)
{
LogSystem.LogError($"Exception while sending message: {e.Message}");
return false;
}
finally
{
if (ptr != IntPtr.Zero)
Marshal.FreeHGlobal(ptr);
}
}
// 广播消息给所有连接的玩家
public void Broadcast(byte[] data, bool reliable = true)
{
foreach (var steamID in _connections.Keys)
{
SendTo(steamID, data, reliable);
}
}
// 轮询接收消息
public void PollMessages()
{
// 为每个连接轮询消息
foreach (var kvp in _connections)
{
var steamID = kvp.Key;
var connection = kvp.Value;
PollMessagesForConnection(steamID, connection);
}
}
// 为特定连接轮询消息
private void PollMessagesForConnection(CSteamID steamID, HSteamNetConnection connection)
{
IntPtr[] messages = new IntPtr[32]; // 一次最多处理32条消息
int messageCount = SteamNetworkingSockets.ReceiveMessagesOnConnection(connection, messages, 32);
for (int i = 0; i < messageCount; i++)
{
var messagePtr = messages[i];
if (messagePtr == IntPtr.Zero) continue;
try
{
// 获取消息结构
var message = Marshal.PtrToStructure<SteamNetworkingMessage_t>(messagePtr);
// 复制数据
byte[] data = new byte[message.m_cbSize];
Marshal.Copy(message.m_pData, data, 0, message.m_cbSize);
// 触发接收事件
OnMessageReceivedEvent?.Invoke(steamID, data);
}
catch (Exception e)
{
LogSystem.LogError($"Error processing message from {steamID}: {e.Message}");
}
finally
{
// 释放消息
SteamNetworkingMessage_t.Release(messagePtr);
}
}
}
// 获取连接状态
public bool IsConnectedTo(CSteamID steamID)
{
return _connections.ContainsKey(steamID);
}
// 获取所有连接的玩家
public IEnumerable<CSteamID> GetConnectedPeers()
{
return _connections.Keys;
}
// 获取连接数量
public int GetConnectionCount()
{
return _connections.Count;
}
// 清理资源
public void Cleanup()
{
DisconnectAll();
if (_listenSocket != HSteamListenSocket.Invalid)
{
SteamNetworkingSockets.CloseListenSocket(_listenSocket);
_listenSocket = HSteamListenSocket.Invalid;
}
_cbConnectionStatusChanged?.Dispose();
_cbConnectionStatusChanged = null;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e6d704b4f9b049d69589fb5dae84c372
timeCreated: 1756715947

View File

@ -0,0 +1,520 @@
using System.Collections.Generic;
using System.Linq;
using Logic.CrashSight;
using Steamworks;
using UnityEngine;
namespace TH1_Logic.Steam
{
public class SteamLobbyManager
{
public static SteamLobbyManager Instance { get; } = new SteamLobbyManager();
public CSteamID CurrentLobby = CSteamID.Nil;
public CSteamID CachedOwner = CSteamID.Nil;
// 房间状态
public enum LobbyState
{
None, // 未在房间中
Creating, // 正在创建房间
Joining, // 正在加入房间
InLobby, // 在房间中
Leaving // 正在离开房间
}
public LobbyState CurrentState { get; private set; } = LobbyState.None;
public bool IsLobbyOwner =>
CurrentLobby.IsValid() &&
SteamMatchmaking.GetLobbyOwner(CurrentLobby) == SteamUser.GetSteamID();
public bool IsInLobby => CurrentState == LobbyState.InLobby && CurrentLobby.IsValid();
// 事件委托
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 = 目标 Lobbydata.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消息
public bool SendMessageToPeer(CSteamID target, byte[] data, bool reliable = true)
{
if (!IsInLobby)
{
OnLobbyErrorEvent?.Invoke("Not in lobby");
return false;
}
return SimpleP2P.Instance.SendTo(target, data, reliable);
}
// 广播P2P消息
public void BroadcastMessage(byte[] data, bool reliable = true)
{
if (!IsInLobby)
{
OnLobbyErrorEvent?.Invoke("Not in lobby");
return;
}
SimpleP2P.Instance.Broadcast(data, reliable);
}
// 轮询P2P消息需要在Update中调用
public void Update()
{
SimpleP2P.Instance.PollMessages();
}
// 枚举房间成员
public 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 int GetMemberCount()
{
if (!CurrentLobby.IsValid()) return 0;
return SteamMatchmaking.GetNumLobbyMembers(CurrentLobby);
}
// 获取最大成员数
public int GetMemberLimit()
{
if (!CurrentLobby.IsValid()) return 0;
return SteamMatchmaking.GetLobbyMemberLimit(CurrentLobby);
}
// 清理资源
public void Cleanup()
{
LeaveLobby();
SimpleP2P.Instance.Cleanup();
_cbLobbyCreated?.Dispose();
_cbLobbyJoinRequested?.Dispose();
_cbLobbyEnter?.Dispose();
_cbLobbyChatUpdate?.Dispose();
LogSystem.LogInfo("SteamLobbyManager cleaned up");
}
}
}

View File

@ -1,25 +0,0 @@
/*
* @Author:
* @Description:
* @Date: 20250526 14:05:31
* @Modify:
*/
using UnityEngine;
using Steamworks;
using System;
namespace Logic.SteamManager
{
public class SteamManager
{
public static SteamManager Instance = new SteamManager();
public void Init()
{
}
}
}

View File

@ -0,0 +1,440 @@
using System.Collections;
using System.IO;
using UnityEngine;
using Steamworks;
using TH1_Logic.Steam;
using Logic.CrashSight;
namespace TH1_Logic.Steam
{
/// <summary>
/// Steam测试管理器 - 用于在Unity编辑器中测试Steam功能
/// </summary>
public class SteamTestManager : MonoBehaviour
{
[Header("Steam 连接状态")]
public bool IsSteamInitialized = false;
public bool IsLoggedIn = false;
public string CurrentUserName = "";
public CSteamID CurrentUserID;
[Header("测试配置")]
[SerializeField] private bool autoInitialize = true;
[SerializeField] private bool enableDebugLog = true;
[Header("房间测试")]
[SerializeField] private int maxLobbyMembers = 4;
private void Awake()
{
// 确保只有一个实例
if (FindObjectsOfType<SteamTestManager>().Length > 1)
{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
}
private void Start()
{
if (autoInitialize)
{
StartCoroutine(InitializeSteam());
}
}
/// <summary>
/// 初始化Steam
/// </summary>
private IEnumerator InitializeSteam()
{
LogSystem.LogInfo("开始初始化Steam...");
LogSystem.LogInfo($"启动方式检测: {(SteamAPI.RestartAppIfNecessary(new Steamworks.AppId_t(480)) ? "Steam启动" : "Steam启动")}");
// 检查Steam是否运行
if (!SteamAPI.IsSteamRunning())
{
LogSystem.LogError("Steam客户端未运行请先启动Steam。");
yield break;
}
// 检查steam_appid.txt文件状态
CheckSteamAppIdFile();
// 初始化Steam API
IsSteamInitialized = SteamAPI.Init();
if (!IsSteamInitialized)
{
LogSystem.LogError("Steam API初始化失败");
LogSystem.LogError("可能的原因:");
LogSystem.LogError("1. Steam客户端未运行");
LogSystem.LogError("2. steam_appid.txt文件配置错误开发环境");
LogSystem.LogError("3. 没有以Steam方式启动应用开发环境");
LogSystem.LogError("4. Steam App ID不匹配");
yield break;
}
LogSystem.LogInfo("Steam API初始化成功");
// 等待一帧确保Steam完全初始化
yield return null;
// 检查用户登录状态
try
{
CheckUserLoginStatus();
}
catch (System.Exception e)
{
LogSystem.LogError($"检查用户登录状态异常: {e.Message}");
}
// 显示启动信息
DisplayLaunchInfo();
// 初始化Steam房间管理器
try
{
InitializeSteamLobbyManager();
}
catch (System.Exception e)
{
LogSystem.LogError($"Steam房间管理器初始化异常: {e.Message}");
}
LogSystem.LogInfo("Steam测试环境初始化完成");
}
/// <summary>
/// 检查steam_appid.txt文件状态
/// </summary>
private void CheckSteamAppIdFile()
{
string steamAppIdPath = Path.Combine(Directory.GetCurrentDirectory(), "steam_appid.txt");
if (File.Exists(steamAppIdPath))
{
try
{
string content = File.ReadAllText(steamAppIdPath).Trim();
LogSystem.LogInfo($"发现steam_appid.txt文件App ID: {content}");
}
catch (System.Exception e)
{
LogSystem.LogWarning($"读取steam_appid.txt失败: {e.Message}");
}
}
else
{
LogSystem.LogInfo("未发现steam_appid.txt文件 - 这在Steam平台发布时是正常的");
}
}
/// <summary>
/// 显示启动信息
/// </summary>
private void DisplayLaunchInfo()
{
if (!IsSteamInitialized) return;
// 获取当前App ID
var currentAppId = SteamUtils.GetAppID();
LogSystem.LogInfo($"当前Steam App ID: {currentAppId}");
// 检查启动方式
bool launchedViaSteam = SteamApps.BIsSubscribedApp(currentAppId);
LogSystem.LogInfo($"通过Steam启动: {(launchedViaSteam ? "" : "")}");
// 显示Steam环境信息
LogSystem.LogInfo($"Steam语言: {SteamApps.GetCurrentGameLanguage()}");
LogSystem.LogInfo($"Steam服务器连接: {(SteamUser.BLoggedOn() ? "" : "")}");
// 检查DLC和订阅状态
if (currentAppId.m_AppId == 480) // Spacewar测试应用
{
LogSystem.LogInfo("当前使用Spacewar测试应用 - 适用于开发测试");
}
else
{
LogSystem.LogInfo($"当前使用正式应用ID: {currentAppId.m_AppId}");
}
}
/// <summary>
/// 检查用户登录状态
/// </summary>
private void CheckUserLoginStatus()
{
if (!IsSteamInitialized) return;
IsLoggedIn = SteamUser.BLoggedOn();
if (IsLoggedIn)
{
CurrentUserID = SteamUser.GetSteamID();
CurrentUserName = SteamFriends.GetPersonaName();
LogSystem.LogInfo($"Steam用户已登录: {CurrentUserName} ({CurrentUserID})");
}
else
{
LogSystem.LogWarning("Steam用户未登录");
}
}
/// <summary>
/// 初始化Steam房间管理器
/// </summary>
private void InitializeSteamLobbyManager()
{
if (!IsSteamInitialized || !IsLoggedIn) return;
try
{
// 初始化房间管理器
SteamLobbyManager.Instance.InitCallbacks();
// 订阅事件
SteamLobbyManager.Instance.OnLobbyCreatedEvent += OnLobbyCreated;
SteamLobbyManager.Instance.OnLobbyEnteredEvent += OnLobbyEntered;
SteamLobbyManager.Instance.OnLobbyLeftEvent += OnLobbyLeft;
SteamLobbyManager.Instance.OnMemberJoinedEvent += OnMemberJoined;
SteamLobbyManager.Instance.OnMemberLeftEvent += OnMemberLeft;
SteamLobbyManager.Instance.OnHostChangedEvent += OnHostChanged;
SteamLobbyManager.Instance.OnLobbyErrorEvent += OnLobbyError;
// 订阅P2P事件
SimpleP2P.Instance.OnPeerConnectedEvent += OnP2PPeerConnected;
SimpleP2P.Instance.OnPeerDisconnectedEvent += OnP2PPeerDisconnected;
SimpleP2P.Instance.OnMessageReceivedEvent += OnP2PMessageReceived;
SimpleP2P.Instance.OnConnectionErrorEvent += OnP2PConnectionError;
LogSystem.LogInfo("Steam房间管理器初始化成功");
}
catch (System.Exception e)
{
LogSystem.LogError($"Steam房间管理器初始化失败: {e.Message}");
}
}
private void Update()
{
if (IsSteamInitialized)
{
// 更新Steam回调
SteamAPI.RunCallbacks();
// 更新P2P消息
SteamLobbyManager.Instance.Update();
}
}
private void OnDestroy()
{
if (IsSteamInitialized)
{
SteamLobbyManager.Instance.Cleanup();
SteamAPI.Shutdown();
LogSystem.LogInfo("Steam API已关闭");
}
}
#region
private void OnLobbyCreated(CSteamID lobbyId)
{
LogSystem.LogInfo($"[测试] 房间创建成功: {lobbyId}");
}
private void OnLobbyEntered(CSteamID lobbyId)
{
LogSystem.LogInfo($"[测试] 进入房间: {lobbyId}");
LogSystem.LogInfo($"[测试] 房间成员数: {SteamLobbyManager.Instance.GetMemberCount()}/{SteamLobbyManager.Instance.GetMemberLimit()}");
}
private void OnLobbyLeft()
{
LogSystem.LogInfo("[测试] 离开房间");
}
private void OnMemberJoined(CSteamID memberId)
{
string memberName = SteamFriends.GetFriendPersonaName(memberId);
LogSystem.LogInfo($"[测试] 成员加入: {memberName} ({memberId})");
}
private void OnMemberLeft(CSteamID memberId)
{
string memberName = SteamFriends.GetFriendPersonaName(memberId);
LogSystem.LogInfo($"[测试] 成员离开: {memberName} ({memberId})");
}
private void OnHostChanged(CSteamID oldHost, CSteamID newHost)
{
string oldHostName = SteamFriends.GetFriendPersonaName(oldHost);
string newHostName = SteamFriends.GetFriendPersonaName(newHost);
LogSystem.LogInfo($"[测试] 房主变更: {oldHostName} -> {newHostName}");
}
private void OnLobbyError(string error)
{
LogSystem.LogError($"[测试] 房间错误: {error}");
}
#endregion
#region P2P事件处理
private void OnP2PPeerConnected(CSteamID peerId)
{
string peerName = SteamFriends.GetFriendPersonaName(peerId);
LogSystem.LogInfo($"[测试] P2P连接建立: {peerName} ({peerId})");
}
private void OnP2PPeerDisconnected(CSteamID peerId)
{
string peerName = SteamFriends.GetFriendPersonaName(peerId);
LogSystem.LogInfo($"[测试] P2P连接断开: {peerName} ({peerId})");
}
private void OnP2PMessageReceived(CSteamID senderId, byte[] data)
{
string senderName = SteamFriends.GetFriendPersonaName(senderId);
string message = System.Text.Encoding.UTF8.GetString(data);
LogSystem.LogInfo($"[测试] 收到P2P消息 from {senderName}: {message}");
}
private void OnP2PConnectionError(string error)
{
LogSystem.LogError($"[测试] P2P连接错误: {error}");
}
#endregion
#region - Inspector中调用
[ContextMenu("创建测试房间")]
public void TestCreateLobby()
{
if (!CanPerformLobbyAction()) return;
LogSystem.LogInfo("[测试] 创建房间...");
SteamLobbyManager.Instance.CreateFriendsLobby(maxLobbyMembers);
}
[ContextMenu("离开房间")]
public void TestLeaveLobby()
{
if (!SteamLobbyManager.Instance.IsInLobby)
{
LogSystem.LogWarning("[测试] 当前不在房间中");
return;
}
LogSystem.LogInfo("[测试] 离开房间...");
SteamLobbyManager.Instance.LeaveLobby();
}
[ContextMenu("发送测试消息")]
public void TestSendMessage()
{
if (!SteamLobbyManager.Instance.IsInLobby)
{
LogSystem.LogWarning("[测试] 当前不在房间中,无法发送消息");
return;
}
string testMessage = $"测试消息 from {CurrentUserName} at {System.DateTime.Now:HH:mm:ss}";
byte[] data = System.Text.Encoding.UTF8.GetBytes(testMessage);
LogSystem.LogInfo($"[测试] 广播消息: {testMessage}");
SteamLobbyManager.Instance.BroadcastMessage(data, true);
}
[ContextMenu("显示在线好友")]
public void TestShowOnlineFriends()
{
if (!CanPerformLobbyAction()) return;
var friends = SteamLobbyManager.Instance.GetOnlineFriends();
LogSystem.LogInfo($"[测试] 在线好友数量: {friends.Count}");
foreach (var friend in friends)
{
LogSystem.LogInfo($"[测试] 好友: {friend.name} ({friend.id})");
}
}
[ContextMenu("打开邀请界面")]
public void TestOpenInviteOverlay()
{
if (!SteamLobbyManager.Instance.IsInLobby)
{
LogSystem.LogWarning("[测试] 当前不在房间中,无法邀请好友");
return;
}
LogSystem.LogInfo("[测试] 打开Steam邀请界面...");
SteamLobbyManager.Instance.OpenInviteOverlay();
}
private bool CanPerformLobbyAction()
{
if (!IsSteamInitialized)
{
LogSystem.LogError("[测试] Steam未初始化");
return false;
}
if (!IsLoggedIn)
{
LogSystem.LogError("[测试] Steam用户未登录");
return false;
}
return true;
}
#endregion
#region GUI显示状态
private void OnGUI()
{
if (!enableDebugLog) return;
GUILayout.BeginArea(new Rect(10, 10, 300, 400));
GUILayout.BeginVertical("box");
GUILayout.Label("Steam 测试状态", GUI.skin.label);
GUILayout.Label($"Steam初始化: {(IsSteamInitialized ? "" : "")}");
GUILayout.Label($"用户登录: {(IsLoggedIn ? "" : "")}");
if (IsLoggedIn)
{
GUILayout.Label($"用户: {CurrentUserName}");
GUILayout.Label($"ID: {CurrentUserID}");
}
GUILayout.Space(10);
GUILayout.Label("房间状态", GUI.skin.label);
GUILayout.Label($"当前状态: {SteamLobbyManager.Instance.CurrentState}");
GUILayout.Label($"在房间中: {(SteamLobbyManager.Instance.IsInLobby ? "" : "")}");
GUILayout.Label($"是房主: {(SteamLobbyManager.Instance.IsLobbyOwner ? "" : "")}");
if (SteamLobbyManager.Instance.IsInLobby)
{
GUILayout.Label($"房间ID: {SteamLobbyManager.Instance.CurrentLobby}");
GUILayout.Label($"成员数: {SteamLobbyManager.Instance.GetMemberCount()}/{SteamLobbyManager.Instance.GetMemberLimit()}");
GUILayout.Label($"P2P连接数: {SimpleP2P.Instance.GetConnectionCount()}");
}
GUILayout.EndVertical();
GUILayout.EndArea();
}
#endregion
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6d8d18aba4f448e095c425fe5a24a1c8
timeCreated: 1756803052

View File

@ -0,0 +1,125 @@
// using UnityEngine;
// using UnityEngine.UI;
// using Logic.CrashSight;
//
//
// namespace TH1_Logic.Steam
// {
// /// <summary>
// /// Steam测试UI - 提供简单的UI界面来测试Steam功能
// /// </summary>
// public class SteamTestUI : MonoBehaviour
// {
// [Header("UI组件")]
// public Button createLobbyButton;
// public Button leaveLobbyButton;
// public Button sendMessageButton;
// public Button showFriendsButton;
// public Button inviteButton;
// public Text statusText;
// public Text lobbyInfoText;
// public InputField messageInput;
//
// private SteamTestManager steamTestManager;
//
// private void Start()
// {
// steamTestManager = FindObjectOfType<SteamTestManager>();
// if (steamTestManager == null)
// {
// LogSystem.LogError("找不到SteamTestManager组件");
// return;
// }
//
// SetupUI();
// }
//
// private void SetupUI()
// {
// if (createLobbyButton) createLobbyButton.onClick.AddListener(OnCreateLobby);
// if (leaveLobbyButton) leaveLobbyButton.onClick.AddListener(OnLeaveLobby);
// if (sendMessageButton) sendMessageButton.onClick.AddListener(OnSendMessage);
// if (showFriendsButton) showFriendsButton.onClick.AddListener(OnShowFriends);
// if (inviteButton) inviteButton.onClick.AddListener(OnInviteFriends);
//
// if (messageInput) messageInput.text = "Hello Steam P2P!";
// }
//
// private void Update()
// {
// UpdateUI();
// }
//
// private void UpdateUI()
// {
// if (!steamTestManager) return;
//
// // 更新状态文本
// if (statusText)
// {
// statusText.text = $"Steam: {(steamTestManager.IsSteamInitialized ? "✓" : "✗")} | " +
// $"登录: {(steamTestManager.IsLoggedIn ? "✓" : "✗")} | " +
// $"用户: {steamTestManager.CurrentUserName}";
// }
//
// // 更新房间信息
// if (lobbyInfoText)
// {
// var lobby = SteamLobbyManager.Instance;
// lobbyInfoText.text = $"状态: {lobby.CurrentState}\n" +
// $"在房间: {(lobby.IsInLobby ? "✓" : "✗")}\n" +
// $"是房主: {(lobby.IsLobbyOwner ? "✓" : "✗")}\n" +
// $"成员数: {lobby.GetMemberCount()}/{lobby.GetMemberLimit()}\n" +
// $"P2P连接: {SimpleP2P.Instance.GetConnectionCount()}";
// }
//
// // 更新按钮状态
// bool canCreateLobby = steamTestManager.IsSteamInitialized &&
// steamTestManager.IsLoggedIn &&
// !SteamLobbyManager.Instance.IsInLobby;
//
// bool inLobby = SteamLobbyManager.Instance.IsInLobby;
//
// if (createLobbyButton) createLobbyButton.interactable = canCreateLobby;
// if (leaveLobbyButton) leaveLobbyButton.interactable = inLobby;
// if (sendMessageButton) sendMessageButton.interactable = inLobby;
// if (inviteButton) inviteButton.interactable = inLobby;
// if (showFriendsButton) showFriendsButton.interactable = steamTestManager.IsSteamInitialized && steamTestManager.IsLoggedIn;
// }
//
// public void OnCreateLobby()
// {
// steamTestManager.TestCreateLobby();
// }
//
// public void OnLeaveLobby()
// {
// steamTestManager.TestLeaveLobby();
// }
//
// public void OnSendMessage()
// {
// if (messageInput && !string.IsNullOrEmpty(messageInput.text))
// {
// string message = $"{steamTestManager.CurrentUserName}: {messageInput.text}";
// byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
// SteamLobbyManager.Instance.BroadcastMessage(data, true);
// LogSystem.LogInfo($"发送消息: {message}");
// }
// else
// {
// steamTestManager.TestSendMessage();
// }
// }
//
// public void OnShowFriends()
// {
// steamTestManager.TestShowOnlineFriends();
// }
//
// public void OnInviteFriends()
// {
// steamTestManager.TestOpenInviteOverlay();
// }
// }
// }

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dee2e67a5e7243edbd18fd09ef135a55
timeCreated: 1756803150

View File

@ -0,0 +1,2 @@
480