diff --git a/Unity/Assets/Scripts/TH1_Logic/Action/UnitActionLogic.cs b/Unity/Assets/Scripts/TH1_Logic/Action/UnitActionLogic.cs index 297b150e0..3883d075a 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Action/UnitActionLogic.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Action/UnitActionLogic.cs @@ -15,7 +15,6 @@ using Logic.Audio; using Logic.CrashSight; using Logic.Skill; using RuntimeData; -using Steamworks; using TH1_Core.Events; using TH1_Core.Managers; using TH1_Logic.Core; diff --git a/Unity/Assets/Scripts/TH1_Logic/Editor/TH1UnifiedBuildWindow.cs b/Unity/Assets/Scripts/TH1_Logic/Editor/TH1UnifiedBuildWindow.cs new file mode 100644 index 000000000..338c486a4 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Editor/TH1UnifiedBuildWindow.cs @@ -0,0 +1,598 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Logic.Config; +using TH1_Logic.Editor.HybridCLR; +using TH1_Logic.Editor.YooAssetTools; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +using UnityEngine; + +namespace TH1_Logic.Editor +{ + public sealed class TH1UnifiedBuildWindow : EditorWindow + { + private const string VersionConfigPath = "Assets/BundleResources/DataAssets/VersionConfig.asset"; + private const string ProductName = "TOHOTOPIA"; + private const string ExeName = "TOHOTOPIA.exe"; + + private static readonly string[] BaseSharedDefines = + { + "UNITY", + "ENABLE_VIEW", + "NODECANVAS" + }; + + private static readonly string[] ControlledDefines = + { + "UNITY", + "ENABLE_VIEW", + "NODECANVAS", + "STEAMWORKS_NET", + "STEAM_CHANNEL", + "USE_INPUT", + "ENABLE_SPEEDUP", + "ENABLE_TRAIN", + "ENABLE_AIMODEL", + "GAME_AUTO_DEBUG", + "CHECK_ACTIONDEFFERENCE", + "STEAM_TEST", + "TH1_PLATFORM_PC", + "TH1_PLATFORM_IOS" + }; + + private VersionConfig _versionConfig; + private Vector2 _scroll; + private int _versionIndex; + private uint _major; + private uint _minor; + private uint _patch; + private uint _fourth; + private BuildPlatformProfile _platform = BuildPlatformProfile.PC; + private PackageProfile _package = PackageProfile.Test; + private bool _prepareBeforeBuild = true; + private bool _buildPlayer = true; + private bool _cleanOutput; + private bool _showAdvanced; + private bool _enableSpeedup; + private bool _enableTrain; + private bool _enableAiModel; + private bool _gameAutoDebug; + private bool _checkActionDifference; + private bool _steamTest; + private string _lastAction = "Ready"; + + [MenuItem("Tools/TH1/Unified Build Window")] + [MenuItem("Tools/TH1/一体化出包工具")] + public static void Open() + { + var window = GetWindow("TH1 Unified Build"); + window.minSize = new Vector2(680, 620); + window.Show(); + } + + private void OnEnable() + { + LoadVersionConfig(); + ResetReleaseTogglesIfNeeded(); + } + + private void OnGUI() + { + LoadVersionConfig(); + DrawHeader(); + + _scroll = EditorGUILayout.BeginScrollView(_scroll); + DrawVersionSection(); + EditorGUILayout.Space(8); + DrawProfileSection(); + EditorGUILayout.Space(8); + DrawSpecialDefinesSection(); + EditorGUILayout.Space(8); + DrawActions(); + EditorGUILayout.EndScrollView(); + } + + private void DrawHeader() + { + EditorGUILayout.LabelField("TH1 PC / iOS 一体化出包", EditorStyles.boldLabel); + EditorGUILayout.LabelField("当前 Unity 平台", EditorUserBuildSettings.activeBuildTarget.ToString()); + EditorGUILayout.LabelField("上次操作", _lastAction); + + if (EditorApplication.isCompiling) + { + EditorGUILayout.HelpBox("Unity 正在编译脚本,等编译结束后再执行切平台或构建。", MessageType.Warning); + } + + EditorGUILayout.HelpBox( + "流程:选版本 -> 选平台 -> 选测试/发布 -> 勾特殊功能 -> 一键执行。发布包会关闭所有特殊功能宏;iOS 配置不会写入 STEAM_CHANNEL/STEAMWORKS_NET。", + MessageType.Info); + } + + private void DrawVersionSection() + { + EditorGUILayout.LabelField("版本", EditorStyles.boldLabel); + if (_versionConfig == null) + { + EditorGUILayout.HelpBox($"找不到或无法创建 {VersionConfigPath}", MessageType.Error); + return; + } + + using (new EditorGUILayout.HorizontalScope()) + { + _major = (uint)Mathf.Max(0, EditorGUILayout.IntField((int)_major, GUILayout.Width(46))); + EditorGUILayout.LabelField(".", GUILayout.Width(10)); + _minor = (uint)Mathf.Max(0, EditorGUILayout.IntField((int)_minor, GUILayout.Width(46))); + EditorGUILayout.LabelField(".", GUILayout.Width(10)); + _patch = (uint)Mathf.Max(0, EditorGUILayout.IntField((int)_patch, GUILayout.Width(46))); + EditorGUILayout.LabelField("+", GUILayout.Width(10)); + _fourth = (uint)Mathf.Clamp(EditorGUILayout.IntField((int)_fourth, GUILayout.Width(46)), 0, 25); + + var versionId = _major * 1000000 + _minor * 10000 + _patch * 100 + _fourth; + using (new EditorGUI.DisabledScope(_versionConfig.GetVersionInfo(versionId) != null)) + { + if (GUILayout.Button("创建版本", GUILayout.Width(96))) + { + _versionConfig.CreateNewVersion(_major, _minor, _patch, _fourth); + SortVersions(); + _versionIndex = FindVersionIndex(versionId); + SaveVersionConfig(); + } + } + } + + if (_versionConfig.Versions == null || _versionConfig.Versions.Count == 0) + { + EditorGUILayout.HelpBox("还没有版本号,请先创建一个。", MessageType.Warning); + return; + } + + SortVersions(); + var labels = _versionConfig.Versions.Select(v => v.FullVersion).ToArray(); + _versionIndex = Mathf.Clamp(_versionIndex, 0, labels.Length - 1); + _versionIndex = EditorGUILayout.Popup("打包版本", _versionIndex, labels); + + var selected = GetSelectedVersion(); + if (selected != null) + { + selected.Description = EditorGUILayout.TextArea(selected.Description, GUILayout.MinHeight(90)); + } + } + + private void DrawProfileSection() + { + EditorGUILayout.LabelField("平台和包类型", EditorStyles.boldLabel); + var nextPlatform = (BuildPlatformProfile)EditorGUILayout.EnumPopup("平台", _platform); + var nextPackage = (PackageProfile)EditorGUILayout.EnumPopup("包类型", _package); + + if (nextPlatform != _platform || nextPackage != _package) + { + _platform = nextPlatform; + _package = nextPackage; + ResetReleaseTogglesIfNeeded(); + } + + _prepareBeforeBuild = EditorGUILayout.ToggleLeft("构建前执行 HybridCLR + YooAsset 准备流程", _prepareBeforeBuild); + _buildPlayer = EditorGUILayout.ToggleLeft("准备完成后 Build Player", _buildPlayer); + _cleanOutput = EditorGUILayout.ToggleLeft("构建前清空本次输出目录", _cleanOutput); + + var group = GetBuildTargetGroup(_platform); + EditorGUILayout.LabelField("目标平台组", group.ToString()); + EditorGUILayout.LabelField("目标 BuildTarget", GetBuildTarget(_platform).ToString()); + EditorGUILayout.LabelField("脚本后端", GetScriptingBackend(_platform, _package).ToString()); + EditorGUILayout.LabelField("输出目录", GetOutputPathPreview()); + } + + private void DrawSpecialDefinesSection() + { + EditorGUILayout.LabelField("特殊功能", EditorStyles.boldLabel); + + using (new EditorGUI.DisabledScope(_package == PackageProfile.Release)) + { + _enableSpeedup = EditorGUILayout.ToggleLeft("加速模式 ENABLE_SPEEDUP", _enableSpeedup); + _enableTrain = EditorGUILayout.ToggleLeft("训练模式 ENABLE_TRAIN", _enableTrain); + _enableAiModel = EditorGUILayout.ToggleLeft("AI 模型 ENABLE_AIMODEL", _enableAiModel); + _gameAutoDebug = EditorGUILayout.ToggleLeft("自动战斗 GAME_AUTO_DEBUG", _gameAutoDebug); + _checkActionDifference = EditorGUILayout.ToggleLeft("MapData 变化检查 CHECK_ACTIONDEFFERENCE", _checkActionDifference); + _steamTest = EditorGUILayout.ToggleLeft("Steam 测试窗口 STEAM_TEST", _platform == BuildPlatformProfile.PC && _steamTest); + } + + if (_package == PackageProfile.Release) + { + EditorGUILayout.HelpBox("发布包会强制关闭上面所有特殊功能宏。OPS 混淆设置不会被这个窗口自动修改,需要单独确认后再处理。", MessageType.None); + } + } + + private void DrawActions() + { + EditorGUILayout.LabelField("执行", EditorStyles.boldLabel); + using (new EditorGUI.DisabledScope(EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode || GetSelectedVersion() == null)) + { + if (GUILayout.Button("一键应用配置并出包", GUILayout.Height(42))) + { + RunAction("Apply And Build", ApplyAndRun); + } + + using (new EditorGUILayout.HorizontalScope()) + { + if (GUILayout.Button("只应用配置", GUILayout.Height(30))) + { + RunAction("Apply Profile", ApplySelectedProfile); + } + + if (GUILayout.Button("只准备热更/AB", GUILayout.Height(30))) + { + RunAction("Prepare Assets", () => TH1MigrationCommandLine.PrepareCurrentPlatform(IsDevelopmentBuild())); + } + } + + _showAdvanced = EditorGUILayout.Foldout(_showAdvanced, "高级单项", true); + if (_showAdvanced) + { + using (new EditorGUILayout.HorizontalScope()) + { + if (GUILayout.Button("HybridCLR Generate All")) + { + RunAction("HybridCLR Generate All", TH1HybridCLRBuildTools.GenerateAll); + } + + if (GUILayout.Button("Build Hotfix DLL")) + { + RunAction("Build Hotfix DLL", () => + { + if (!TH1HybridCLRBuildTools.BuildAndCopyHotfixArtifacts(IsDevelopmentBuild())) + throw new Exception("Build hotfix dll failed. See Console for details."); + }); + } + } + + using (new EditorGUILayout.HorizontalScope()) + { + if (GUILayout.Button("Build YooAsset AB")) + { + RunAction("Build YooAsset AB", TH1YooAssetBuildTools.BuildBuiltinDefaultPackage); + } + + if (GUILayout.Button("打开输出目录")) + { + EditorUtility.RevealInFinder(Path.GetDirectoryName(GetOutputPath())); + } + } + } + } + } + + private void ApplyAndRun() + { + ApplySelectedProfile(); + + if (_prepareBeforeBuild) + { + TH1MigrationCommandLine.PrepareCurrentPlatform(IsDevelopmentBuild()); + } + + if (_buildPlayer) + { + BuildPlayer(); + } + } + + private void ApplySelectedProfile() + { + var selected = GetSelectedVersion(); + if (selected == null) throw new InvalidOperationException("No build version selected."); + + SwitchBuildTargetIfNeeded(); + ApplyVersion(selected); + ApplyDefines(); + ApplyPlayerSettings(); + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + private void ApplyVersion(VersionInfo selected) + { + _versionConfig.CurVersionId = selected.VersionId; + PlayerSettings.productName = ProductName; + PlayerSettings.bundleVersion = selected.FullVersion; + SaveVersionConfig(); + } + + private void ApplyDefines() + { + var group = GetBuildTargetGroup(_platform); + var defines = new HashSet(GetDefines(group), StringComparer.Ordinal); + foreach (var symbol in ControlledDefines) + { + defines.Remove(symbol); + } + + foreach (var symbol in BaseSharedDefines) + { + defines.Add(symbol); + } + + if (_platform == BuildPlatformProfile.PC) + { + defines.Add("TH1_PLATFORM_PC"); + defines.Add("STEAMWORKS_NET"); + defines.Add("STEAM_CHANNEL"); + } + else + { + defines.Add("TH1_PLATFORM_IOS"); + } + + if (_package == PackageProfile.Test) + { + defines.Add("USE_INPUT"); + AddSpecialDefines(defines); + } + + PlayerSettings.SetScriptingDefineSymbolsForGroup(group, string.Join(";", defines.OrderBy(s => s))); + } + + private void AddSpecialDefines(HashSet defines) + { + if (_enableSpeedup) defines.Add("ENABLE_SPEEDUP"); + if (_enableTrain) defines.Add("ENABLE_TRAIN"); + if (_enableAiModel) defines.Add("ENABLE_AIMODEL"); + if (_gameAutoDebug) defines.Add("GAME_AUTO_DEBUG"); + if (_checkActionDifference) defines.Add("CHECK_ACTIONDEFFERENCE"); + if (_platform == BuildPlatformProfile.PC && _steamTest) defines.Add("STEAM_TEST"); + } + + private void ApplyPlayerSettings() + { + var group = GetBuildTargetGroup(_platform); + PlayerSettings.SetScriptingBackend(group, GetScriptingBackend(_platform, _package)); + EditorUserBuildSettings.development = IsDevelopmentBuild(); + EditorUserBuildSettings.allowDebugging = IsDevelopmentBuild(); + PlayerSettings.usePlayerLog = IsDevelopmentBuild(); + PlayerSettings.enableInternalProfiler = IsDevelopmentBuild(); + + if (_platform == BuildPlatformProfile.iOS) + { + PlayerSettings.iOS.targetOSVersionString = "13.0"; + } + + if (IsDevelopmentBuild()) + { + SetStackTrace(StackTraceLogType.ScriptOnly, StackTraceLogType.ScriptOnly, StackTraceLogType.ScriptOnly); + } + else + { + PlayerSettings.SetStackTraceLogType(LogType.Log, StackTraceLogType.None); + PlayerSettings.SetStackTraceLogType(LogType.Warning, StackTraceLogType.None); + PlayerSettings.SetStackTraceLogType(LogType.Error, StackTraceLogType.ScriptOnly); + PlayerSettings.SetStackTraceLogType(LogType.Assert, StackTraceLogType.ScriptOnly); + PlayerSettings.SetStackTraceLogType(LogType.Exception, StackTraceLogType.ScriptOnly); + } + } + + private static void SetStackTrace(StackTraceLogType log, StackTraceLogType warning, StackTraceLogType error) + { + PlayerSettings.SetStackTraceLogType(LogType.Log, log); + PlayerSettings.SetStackTraceLogType(LogType.Warning, warning); + PlayerSettings.SetStackTraceLogType(LogType.Error, error); + PlayerSettings.SetStackTraceLogType(LogType.Assert, error); + PlayerSettings.SetStackTraceLogType(LogType.Exception, error); + } + + private void BuildPlayer() + { + var outputPath = GetOutputPath(); + var outputDir = _platform == BuildPlatformProfile.iOS ? outputPath : Path.GetDirectoryName(outputPath); + if (string.IsNullOrEmpty(outputDir)) throw new BuildFailedException("Invalid output path."); + + if (_cleanOutput && Directory.Exists(outputDir)) + { + var fullOutputDir = Path.GetFullPath(outputDir); + var packRoot = Path.GetFullPath(Path.Combine(GetProjectRoot(), "..", "Pack")); + if (!fullOutputDir.StartsWith(packRoot, StringComparison.OrdinalIgnoreCase)) + { + throw new BuildFailedException($"Refuse to clean unexpected output dir: {fullOutputDir}"); + } + + FileUtil.DeleteFileOrDirectory(fullOutputDir); + } + + Directory.CreateDirectory(outputDir); + + var scenes = EditorBuildSettings.scenes + .Where(scene => scene.enabled) + .Select(scene => scene.path) + .ToArray(); + if (scenes.Length == 0) throw new BuildFailedException("No enabled scenes in EditorBuildSettings."); + + var options = new BuildPlayerOptions + { + scenes = scenes, + target = GetBuildTarget(_platform), + targetGroup = GetBuildTargetGroup(_platform), + locationPathName = outputPath, + options = GetBuildOptions() + }; + + using (TH1MigrationBuildValidationGate.Suppress()) + { + var report = BuildPipeline.BuildPlayer(options); + if (report.summary.result != BuildResult.Succeeded) + { + throw new BuildFailedException( + $"Build failed: {report.summary.result}, errors={report.summary.totalErrors}, warnings={report.summary.totalWarnings}"); + } + } + + Debug.Log($"[TH1.UnifiedBuild] Build succeeded: {outputPath}"); + } + + private BuildOptions GetBuildOptions() + { + if (!IsDevelopmentBuild()) return BuildOptions.None; + return BuildOptions.Development | BuildOptions.AllowDebugging | BuildOptions.ConnectWithProfiler; + } + + private string GetOutputPath() + { + var selected = GetSelectedVersion(); + var version = selected?.FullVersion ?? "NoVersion"; + var folder = $"{_platform}_{_package}_{version}"; + var root = Path.GetFullPath(Path.Combine(GetProjectRoot(), "..", "Pack", folder)); + + if (_platform == BuildPlatformProfile.iOS) + { + return root; + } + + return Path.Combine(root, ExeName); + } + + private string GetOutputPathPreview() + { + var output = GetOutputPath(); + return _platform == BuildPlatformProfile.iOS ? output : Path.GetDirectoryName(output); + } + + private void SwitchBuildTargetIfNeeded() + { + var target = GetBuildTarget(_platform); + var group = GetBuildTargetGroup(_platform); + if (EditorUserBuildSettings.activeBuildTarget == target) return; + if (!EditorUserBuildSettings.SwitchActiveBuildTarget(group, target)) + { + throw new BuildFailedException($"Switch build target failed: {target}"); + } + } + + private static BuildTarget GetBuildTarget(BuildPlatformProfile platform) + { + return platform == BuildPlatformProfile.iOS ? BuildTarget.iOS : BuildTarget.StandaloneWindows64; + } + + private static BuildTargetGroup GetBuildTargetGroup(BuildPlatformProfile platform) + { + return platform == BuildPlatformProfile.iOS ? BuildTargetGroup.iOS : BuildTargetGroup.Standalone; + } + + private static ScriptingImplementation GetScriptingBackend(BuildPlatformProfile platform, PackageProfile package) + { + if (platform == BuildPlatformProfile.iOS) return ScriptingImplementation.IL2CPP; + return package == PackageProfile.Release ? ScriptingImplementation.IL2CPP : ScriptingImplementation.Mono2x; + } + + private bool IsDevelopmentBuild() + { + return _package == PackageProfile.Test; + } + + private VersionInfo GetSelectedVersion() + { + if (_versionConfig?.Versions == null || _versionConfig.Versions.Count == 0) return null; + _versionIndex = Mathf.Clamp(_versionIndex, 0, _versionConfig.Versions.Count - 1); + return _versionConfig.Versions[_versionIndex]; + } + + private void LoadVersionConfig() + { + if (_versionConfig != null) return; + _versionConfig = AssetDatabase.LoadAssetAtPath(VersionConfigPath); + if (_versionConfig == null) + { + var dir = Path.GetDirectoryName(VersionConfigPath); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + Directory.CreateDirectory(dir); + _versionConfig = CreateInstance(); + AssetDatabase.CreateAsset(_versionConfig, VersionConfigPath); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + SortVersions(); + _versionIndex = _versionConfig.CurVersionId == 0 ? 0 : FindVersionIndex(_versionConfig.CurVersionId); + } + + private void SaveVersionConfig() + { + EditorUtility.SetDirty(_versionConfig); + AssetDatabase.SaveAssets(); + } + + private void SortVersions() + { + if (_versionConfig?.Versions == null) return; + _versionConfig.Versions = _versionConfig.Versions.OrderByDescending(v => v.VersionId).ToList(); + } + + private int FindVersionIndex(uint versionId) + { + if (_versionConfig?.Versions == null) return 0; + for (var i = 0; i < _versionConfig.Versions.Count; i++) + { + if (_versionConfig.Versions[i].VersionId == versionId) return i; + } + + return 0; + } + + private void ResetReleaseTogglesIfNeeded() + { + if (_package != PackageProfile.Release) return; + _enableSpeedup = false; + _enableTrain = false; + _enableAiModel = false; + _gameAutoDebug = false; + _checkActionDifference = false; + _steamTest = false; + } + + private static IEnumerable GetDefines(BuildTargetGroup group) + { + return PlayerSettings.GetScriptingDefineSymbolsForGroup(group) + .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) + .Select(s => s.Trim()) + .Where(s => !string.IsNullOrEmpty(s)); + } + + private static string GetProjectRoot() + { + return Directory.GetParent(Application.dataPath)?.FullName ?? Application.dataPath; + } + + private void RunAction(string title, Action action) + { + try + { + _lastAction = $"{title} running..."; + Repaint(); + action(); + _lastAction = $"{title} OK"; + Debug.Log($"[TH1.UnifiedBuild] {title} OK"); + } + catch (Exception e) + { + _lastAction = $"{title} failed: {e.Message}"; + Debug.LogError($"[TH1.UnifiedBuild] {title} failed:\n{e}"); + } + finally + { + Repaint(); + } + } + } + + public enum BuildPlatformProfile + { + PC, + iOS + } + + public enum PackageProfile + { + Test, + Release + } +} diff --git a/Unity/Assets/Scripts/TH1_Logic/Editor/TH1UnifiedBuildWindow.cs.meta b/Unity/Assets/Scripts/TH1_Logic/Editor/TH1UnifiedBuildWindow.cs.meta new file mode 100644 index 000000000..584630e7c --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Editor/TH1UnifiedBuildWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b7ee1d9bbf743e898610ee7468260ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Logic/Net/ILobby.cs b/Unity/Assets/Scripts/TH1_Logic/Net/ILobby.cs index 7756400cb..e49dc778a 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Net/ILobby.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Net/ILobby.cs @@ -34,6 +34,12 @@ namespace TH1_Logic.Net // 获取在线好友列表 public Dictionary GetOnlineFriendsDict(); + + // 获取可展示房间列表 + public List GetLobbyListInfos(); + + // 刷新房间列表缓存 + public void RefreshLobbyListInfo(); // 是否初始化完毕 public bool IsInitialized(); @@ -43,6 +49,9 @@ namespace TH1_Logic.Net // 举报房间 public bool ReportLobby(LobbyListInfo lobbyInfo); + + // 处理收到的房间举报消息 + public void OnReceivedLobbyReport(LobbyReportMessage message); // 踢出成员 public void KickMember(ulong memberId); @@ -68,6 +77,9 @@ namespace TH1_Logic.Net // 获取房间所有成员信息 public MemberInfo GetMemberInfo(ulong steamID); + // 获取平台展示名 + public string GetSelfDisplayName(); + // 获取成员数量 public int GetMemberCount(); @@ -101,14 +113,24 @@ namespace TH1_Logic.Net // 发送P2P消息 public bool SendMessageToPeer(ulong member, byte[] data, bool reliable = true); + // 不要求已建立房间内 P2P 连接的直发消息,用于邀请/举报等房间外消息 + public bool SendMessageToPeerWithoutConnection(ulong member, byte[] data, bool reliable = true); + // 广播P2P消息 public bool BroadcastMessage(byte[] data, bool reliable = true); + + // 检查和某成员的 P2P 连接是否已建立 + public bool IsPeerConnected(ulong memberId); // 获取当前房间ID用于分享 public ulong GetShareableLobbyId(); // 获取自己是否为隐私状态 public bool IsSelfStatusInvisibleOrOffline(); + + // 平台房间名工具 + public string GetDefaultRoomName(string ownerName); + public string FilterRoomName(string roomName); } @@ -193,7 +215,16 @@ namespace TH1_Logic.Net public Dictionary GetOnlineFriendsDict() { - return null; + return new Dictionary(); + } + + public List GetLobbyListInfos() + { + return new List(); + } + + public void RefreshLobbyListInfo() + { } public void CreateLobby(int maxMembers = 4,bool isPublic = true, string password = "", string roomName = "") @@ -266,6 +297,16 @@ namespace TH1_Logic.Net return false; } + public bool SendMessageToPeerWithoutConnection(ulong member, byte[] data, bool reliable = true) + { + return false; + } + + public bool IsPeerConnected(ulong memberId) + { + return false; + } + public ulong GetShareableLobbyId() { return 0; @@ -275,5 +316,24 @@ namespace TH1_Logic.Net { return false; } + + public void OnReceivedLobbyReport(LobbyReportMessage message) + { + } + + public string GetSelfDisplayName() + { + return string.Empty; + } + + public string GetDefaultRoomName(string ownerName) + { + return string.IsNullOrWhiteSpace(ownerName) ? "Default" : ownerName; + } + + public string FilterRoomName(string roomName) + { + return roomName ?? string.Empty; + } } } diff --git a/Unity/Assets/Scripts/TH1_Logic/Net/LobbyManager.cs b/Unity/Assets/Scripts/TH1_Logic/Net/LobbyManager.cs index c7313471d..83d098263 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Net/LobbyManager.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Net/LobbyManager.cs @@ -6,7 +6,7 @@ */ -using TH1_Logic.Steam; +using System; namespace TH1_Logic.Net { @@ -18,12 +18,23 @@ namespace TH1_Logic.Net public void Init() { -#if UNITY_EDITOR || STEAM_CHANNEL - Lobby = new SteamLobbyManager(); +#if STEAM_CHANNEL || STEAMWORKS_NET + Lobby = CreateSteamLobby() ?? new LobbyBase(); #else Lobby = new LobbyBase(); #endif Lobby.Init(); } + +#if STEAM_CHANNEL || STEAMWORKS_NET + private static ILobby CreateSteamLobby() + { + var lobbyType = Type.GetType("TH1_Logic.Steam.SteamLobbyManager") + ?? Type.GetType("TH1_Logic.Steam.SteamLobbyManager, TH1.Hotfix") + ?? Type.GetType("TH1_Logic.Steam.SteamLobbyManager, TH1.Steam.Runtime"); + if (lobbyType == null) return null; + return Activator.CreateInstance(lobbyType) as ILobby; + } +#endif } -} \ No newline at end of file +} diff --git a/Unity/Assets/Scripts/TH1_Logic/Oss/OssManager.cs b/Unity/Assets/Scripts/TH1_Logic/Oss/OssManager.cs index 4d9b20bc8..d4bd5a260 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Oss/OssManager.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Oss/OssManager.cs @@ -3,7 +3,9 @@ using System.Threading.Tasks; using Logic.CrashSight; using MemoryPack; using RuntimeData; +#if STEAM_CHANNEL || STEAMWORKS_NET using Steamworks; +#endif using TH1_Logic.Collect; using TH1_Logic.Config; using TH1_Logic.Core; @@ -245,6 +247,7 @@ namespace TH1_Logic.Oss private static bool TryGetSteamId(out string steamId) { steamId = ""; +#if STEAM_CHANNEL || STEAMWORKS_NET try { if (!SteamUser.BLoggedOn()) return false; @@ -259,11 +262,15 @@ namespace TH1_Logic.Oss { return false; } +#else + return false; +#endif } private static bool TryGetAuthTicket(out string authTicket) { authTicket = null; +#if STEAM_CHANNEL || STEAMWORKS_NET try { var ticket = new byte[1024]; @@ -283,6 +290,9 @@ namespace TH1_Logic.Oss LogSystem.LogWarning($"Steam auth ticket unavailable: {ex.Message}"); return false; } +#else + return false; +#endif } } } diff --git a/Unity/Assets/Scripts/TH1_Logic/Oss/StsTokenService.cs b/Unity/Assets/Scripts/TH1_Logic/Oss/StsTokenService.cs index 03d076bdb..dcd69335b 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Oss/StsTokenService.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Oss/StsTokenService.cs @@ -2,7 +2,9 @@ using System; using System.Text; using System.Threading.Tasks; using Logic.CrashSight; +#if STEAM_CHANNEL || STEAMWORKS_NET using Steamworks; +#endif using TH1_Logic.Config; using UnityEngine; using UnityEngine.Networking; @@ -144,6 +146,7 @@ namespace TH1_Logic.Oss private static string GetSteamAppId() { +#if STEAM_CHANNEL || STEAMWORKS_NET try { var appId = SteamUtils.GetAppID().m_AppId; @@ -153,6 +156,9 @@ namespace TH1_Logic.Oss { return string.Empty; } +#else + return string.Empty; +#endif } } } diff --git a/Unity/Assets/Scripts/TH1_Logic/Rersource.meta b/Unity/Assets/Scripts/TH1_Logic/Rersource.meta deleted file mode 100644 index bdb2c3987..000000000 --- a/Unity/Assets/Scripts/TH1_Logic/Rersource.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: aabdf2d1799e4f6192d3398f1a1f9290 -timeCreated: 1745464912 \ No newline at end of file diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/GameNetReceiver.cs b/Unity/Assets/Scripts/TH1_Logic/Steam/GameNetReceiver.cs index 6562729e6..850bb29b5 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Steam/GameNetReceiver.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/GameNetReceiver.cs @@ -762,8 +762,7 @@ namespace TH1_Logic.Steam return; } - if (LobbyManager.Instance.Lobby is SteamLobbyManager steamLobby) - steamLobby.OnReceivedLobbyReport(message); + LobbyManager.Instance.Lobby?.OnReceivedLobbyReport(message); } private void OnReceivedInviteVersionMismatch(InviteVersionMismatchMessage message) diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/GameNetSender.cs b/Unity/Assets/Scripts/TH1_Logic/Steam/GameNetSender.cs index ed8f85f8d..393342768 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Steam/GameNetSender.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/GameNetSender.cs @@ -12,7 +12,6 @@ using Logic.AI; using Logic.CrashSight; using MemoryPack; using RuntimeData; -using Steamworks; using TH1_Logic.Chat; using TH1_Logic.Config; using TH1_Logic.Core; @@ -57,9 +56,6 @@ namespace TH1_Logic.Steam { if (lobbyInfo == null || lobbyInfo.OwnerId == 0 || lobbyInfo.LobbyId == 0) return false; - var targetId = new CSteamID(lobbyInfo.OwnerId); - if (!targetId.IsValid()) return false; - var data = new InviteVersionMismatchMessage { LobbyId = lobbyInfo.LobbyId, @@ -68,8 +64,8 @@ namespace TH1_Logic.Steam LobbyVersion = lobbyInfo.Version, }; - byte[] messageBytes = NetworkPayloadCodec.Encode(TH1Serialization.Serialize(data)); - if (SimpleP2P.Instance.SendToWithOutConnect(targetId, messageBytes)) return true; + byte[] messageBytes = SerializeForNetwork(data); + if (LobbyManager.Instance.Lobby.SendMessageToPeerWithoutConnection(lobbyInfo.OwnerId, messageBytes)) return true; LogSystem.LogError($"InviteVersionMismatchMessage: 发送给房主失败 owner={lobbyInfo.OwnerId}, lobby={lobbyInfo.LobbyId}"); return false; @@ -313,8 +309,7 @@ namespace TH1_Logic.Steam { if (memberId == selfId) continue; - var target = new CSteamID(memberId); - if (!SimpleP2P.Instance.IsConnectedTo(target)) + if (!LobbyManager.Instance.Lobby.IsPeerConnected(memberId)) { LogSystem.LogInfo($"UpdateLobbyData deferred until P2P connected: memberId={memberId}"); continue; @@ -330,7 +325,7 @@ namespace TH1_Logic.Steam if (LobbyManager.Instance.Lobby.IsLobbyOwner()) return false; if (!LobbyManager.Instance.Lobby.IsInLobby()) return false; var hostId = LobbyManager.Instance.Lobby.GetLobbyOwnerId(); - if (hostId == 0 || !SimpleP2P.Instance.IsConnectedTo(new CSteamID(hostId))) + if (hostId == 0 || !LobbyManager.Instance.Lobby.IsPeerConnected(hostId)) { NetworkPlayerTipManager.Instance.Request(NetworkPlayerTipType.LobbyDataRequestFailed); return false; diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs b/Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs new file mode 100644 index 000000000..f6449ef58 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs @@ -0,0 +1,21 @@ +using MemoryPack; + +namespace TH1_Logic.Steam +{ + // 房间信息结构。保持命名空间和字段不变,避免影响已有网络消息和 UI 引用。 + [MemoryPackable] + public partial class LobbyListInfo + { + public ulong LobbyId; + public ulong OwnerId; + + public string OwnerName; + public string RoomName; + public string Version; + public int CurrentPlayers; + public int MaxPlayers; + public int GameState; + public bool HasPassword; + public int ReportCount; + } +} diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs.meta b/Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs.meta new file mode 100644 index 000000000..08b5f1bed --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93f23d875f97403ba1d4cf2afdc2f8c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/SimpleP2P.cs b/Unity/Assets/Scripts/TH1_Logic/Steam/SimpleP2P.cs index efd0dae48..b5eb14943 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Steam/SimpleP2P.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/SimpleP2P.cs @@ -1,4 +1,5 @@ using System; +#if STEAM_CHANNEL || STEAMWORKS_NET using System.Collections.Generic; using System.Runtime.InteropServices; using Logic.CrashSight; @@ -1738,3 +1739,4 @@ namespace TH1_Logic.Steam } } } +#endif diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/SteamGUIMono.cs b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamGUIMono.cs index 63445b1e4..376614774 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Steam/SteamGUIMono.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamGUIMono.cs @@ -5,7 +5,7 @@ * @Modify: */ - +#if STEAM_CHANNEL || STEAMWORKS_NET using TH1_Logic.Core; using TH1_Logic.Net; using UnityEngine; @@ -138,4 +138,5 @@ namespace TH1_Logic.Steam #endif } -} \ No newline at end of file +} +#endif diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/SteamLobbyManager.cs b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamLobbyManager.cs index c4d379c19..fd6bbe5f9 100644 --- a/Unity/Assets/Scripts/TH1_Logic/Steam/SteamLobbyManager.cs +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamLobbyManager.cs @@ -1,4 +1,4 @@ - +#if STEAM_CHANNEL || STEAMWORKS_NET using System; using System.Collections.Generic; using System.IO; @@ -108,6 +108,7 @@ namespace TH1_Logic.Steam // 房间列表 private List _lobbyListInfos; public List LobbyListInfos => _lobbyListInfos; + public List GetLobbyListInfos() => _lobbyListInfos; private readonly HashSet _lobbyReporters = new HashSet(); // 事件委托 @@ -1274,6 +1275,21 @@ namespace TH1_Logic.Steam if (string.IsNullOrEmpty(filteredRoomName)) return "Default"; return BannedWordFilter.Filter(filteredRoomName, BannedTextContext.Name); } + + string ILobby.GetDefaultRoomName(string ownerName) + { + return GetDefaultRoomName(ownerName); + } + + string ILobby.FilterRoomName(string roomName) + { + return FilterRoomName(roomName); + } + + public string GetSelfDisplayName() + { + return SelfName; + } public bool IsInitialized() { @@ -1797,6 +1813,23 @@ namespace TH1_Logic.Steam return SimpleP2P.Instance.SendTo(cSteamId, data, reliable); } + public bool SendMessageToPeerWithoutConnection(ulong member, byte[] data, bool reliable = true) + { + if (data == null || data.Length == 0) + return ReportP2PSendPrecheckFailed(member, "Trying to send null or empty data"); + var targetId = new CSteamID(member); + if (!targetId.IsValid()) + return ReportP2PSendPrecheckFailed(member, $"Invalid target member: {member}"); + return SimpleP2P.Instance.SendToWithOutConnect(targetId, data, reliable); + } + + public bool IsPeerConnected(ulong memberId) + { + if (memberId == 0) return false; + var targetId = new CSteamID(memberId); + return targetId.IsValid() && SimpleP2P.Instance.IsConnectedTo(targetId); + } + // 广播P2P消息 public bool BroadcastMessage(byte[] data, bool reliable = true) { @@ -2129,22 +2162,5 @@ namespace TH1_Logic.Steam LogSystem.LogInfo("SteamLobbyManager cleaned up"); } } - - - // 房间信息结构 - [MemoryPackable] - public partial class LobbyListInfo - { - public ulong LobbyId; - public ulong OwnerId; - - public string OwnerName; - public string RoomName; - public string Version; - public int CurrentPlayers; - public int MaxPlayers; - public int GameState; - public bool HasPassword; - public int ReportCount; - } } +#endif diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/SteamNonSteamRuntimeStubs.cs b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamNonSteamRuntimeStubs.cs new file mode 100644 index 000000000..8ea9a653c --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamNonSteamRuntimeStubs.cs @@ -0,0 +1,145 @@ +#if !(STEAM_CHANNEL || STEAMWORKS_NET) +using System; +using System.Collections.Generic; +using Steamworks; +using TH1_Logic.Chat; +using TH1_Logic.Net; + +namespace TH1_Logic.Steam +{ + public class SteamLobbyManager : LobbyBase + { + public const string LobbyPasswordWrongError = "LobbyPasswordWrong"; + + public bool IsSteamInitialized => false; + public bool IsloggedIn => false; + public bool IsLobbyInitialized => false; + public string SelfName => GetSelfDisplayName(); + public CSteamID SelfID => CSteamID.Nil; + public List LobbyListInfos => GetLobbyListInfos(); + + public event Action OnLobbyCreatedEvent; + public event Action OnLobbyEnteredEvent; + public event Action> OnLobbyLeftEvent; + public event Action OnHostChangedEvent; + public event Action> OnMembersChangedEvent; + public event Action OnLobbyErrorEvent; + public event Action OnMemberJoinedEvent; + public event Action OnMemberLeftEvent; + + public new static string GetDefaultRoomName(string selfName) + { + return string.IsNullOrWhiteSpace(selfName) ? "Default" : $"{selfName} Room"; + } + + public static string FilterRoomName(string input, int maxLength = 20) + { + if (string.IsNullOrWhiteSpace(input)) return "Default"; + var result = input.Trim(); + if (result.Length > maxLength) result = result.Substring(0, maxLength); + return BannedWordFilter.Filter(result, BannedTextContext.Name); + } + + public string GetRoomName() + { + return "Default"; + } + + public bool SetRoomName(string roomName) + { + return false; + } + + public bool CanCreateLobbyNow(out string reason) + { + reason = "Steam is unavailable on this platform."; + return false; + } + + public void SearchPublicLobbies() + { + } + + public List<(CSteamID id, string name)> GetOnlineFriends() + { + return new List<(CSteamID, string)>(); + } + + public CSteamID GetCSteamID(ulong memberId) + { + return CSteamID.Nil; + } + + public EPersonaState GetSelfPersonaState() + { + return EPersonaState.k_EPersonaStateOffline; + } + + public void RaiseNoSteamError() + { + OnLobbyErrorEvent?.Invoke("Steam is unavailable on this platform."); + } + + public void SuppressEventWarnings() + { + _ = OnLobbyCreatedEvent; + _ = OnLobbyEnteredEvent; + _ = OnLobbyLeftEvent; + _ = OnHostChangedEvent; + _ = OnMembersChangedEvent; + _ = OnMemberJoinedEvent; + _ = OnMemberLeftEvent; + } + } + + public class SimpleP2P + { + public static SimpleP2P Instance { get; } = new SimpleP2P(); + + public bool IsInitialized => false; + public event Action OnPeerConnectedEvent; + public event Action OnPeerDisconnectedEvent; + public event Action OnMessageReceivedEvent; + public event Action OnMessageSendFailedEvent; + public event Action OnConnectionErrorEvent; + + public void Initialize() { } + public void Update() { } + public void PollMessages() { } + public void Cleanup() { } + public void DisconnectAll() { } + public void DisconnectFromPeer(CSteamID steamID) { } + public void MarkExpectedDisconnect(CSteamID steamID) { } + public int GetConnectionCount() => 0; + public bool ConnectToPeer(CSteamID steamID) => false; + public bool IsConnectedTo(CSteamID steamID) => false; + public IEnumerable GetConnectedPeers() => Array.Empty(); + public bool HasRecentConnectionFailure(float seconds, out string reason) + { + reason = string.Empty; + return false; + } + + public bool SendTo(CSteamID target, byte[] data, bool reliable = true, bool ordered = true) => false; + public bool SendToWithOutConnect(CSteamID target, byte[] data, bool reliable = true, bool ordered = true) => false; + + public bool CanQueueMessages(IReadOnlyList targets, int dataLength, out CSteamID failedTarget, out string reason) + { + failedTarget = CSteamID.Nil; + reason = string.Empty; + return targets == null || targets.Count == 0; + } + + public void LogDetailedConnectionInfo(CSteamID steamID) { } + + public void SuppressEventWarnings() + { + _ = OnPeerConnectedEvent; + _ = OnPeerDisconnectedEvent; + _ = OnMessageReceivedEvent; + _ = OnMessageSendFailedEvent; + _ = OnConnectionErrorEvent; + } + } +} +#endif diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/SteamNonSteamRuntimeStubs.cs.meta b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamNonSteamRuntimeStubs.cs.meta new file mode 100644 index 000000000..edfdcd20f --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamNonSteamRuntimeStubs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6d9854f7e4ff4700b11fc15f41159a9b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/SteamworksNonSteamStubs.cs b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamworksNonSteamStubs.cs new file mode 100644 index 000000000..3ccea06bc --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamworksNonSteamStubs.cs @@ -0,0 +1,291 @@ +#if !(STEAM_CHANNEL || STEAMWORKS_NET) +using System; + +namespace Steamworks +{ + public struct CSteamID : IEquatable + { + public static readonly CSteamID Nil = new CSteamID(0); + public ulong m_SteamID; + + public CSteamID(ulong value) + { + m_SteamID = value; + } + + public bool IsValid() => m_SteamID != 0; + public uint GetAccountID() => (uint)(m_SteamID & 0xffffffff); + public bool Equals(CSteamID other) => m_SteamID == other.m_SteamID; + public override bool Equals(object obj) => obj is CSteamID other && Equals(other); + public override int GetHashCode() => m_SteamID.GetHashCode(); + public override string ToString() => m_SteamID.ToString(); + public static bool operator ==(CSteamID left, CSteamID right) => left.Equals(right); + public static bool operator !=(CSteamID left, CSteamID right) => !left.Equals(right); + } + + public struct PublishedFileId_t : IEquatable + { + public ulong m_PublishedFileId; + + public PublishedFileId_t(ulong value) + { + m_PublishedFileId = value; + } + + public bool Equals(PublishedFileId_t other) => m_PublishedFileId == other.m_PublishedFileId; + public override bool Equals(object obj) => obj is PublishedFileId_t other && Equals(other); + public override int GetHashCode() => m_PublishedFileId.GetHashCode(); + public override string ToString() => m_PublishedFileId.ToString(); + public static bool operator ==(PublishedFileId_t left, PublishedFileId_t right) => left.Equals(right); + public static bool operator !=(PublishedFileId_t left, PublishedFileId_t right) => !left.Equals(right); + } + + public struct AppId_t + { + public uint m_AppId; + + public AppId_t(uint value) + { + m_AppId = value; + } + } + + public struct SteamAPICall_t + { + public ulong m_SteamAPICall; + } + + public struct UGCQueryHandle_t + { + public ulong m_UGCQueryHandle; + } + + public struct UGCUpdateHandle_t + { + public ulong m_UGCUpdateHandle; + } + + public struct SteamNetworkingIdentity + { + public CSteamID SteamID; + + public void SetSteamID(CSteamID steamId) + { + SteamID = steamId; + } + } + + public enum EResult + { + k_EResultOK = 1, + k_EResultFail = 2, + k_EResultNoConnection = 3, + k_EResultInvalidPassword = 5, + k_EResultLimitExceeded = 25, + k_EResultIgnored = 43, + k_EResultAccessDenied = 15 + } + + public enum EPersonaState + { + k_EPersonaStateOffline = 0, + k_EPersonaStateOnline = 1, + k_EPersonaStateBusy = 2, + k_EPersonaStateAway = 3, + k_EPersonaStateSnooze = 4, + k_EPersonaStateInvisible = 7 + } + + public enum ETextFilteringContext + { + k_ETextFilteringContextUnknown = 0, + k_ETextFilteringContextGameContent = 1, + k_ETextFilteringContextChat = 2, + k_ETextFilteringContextName = 3 + } + + [Flags] + public enum EItemState + { + k_EItemStateNone = 0, + k_EItemStateSubscribed = 1, + k_EItemStateInstalled = 4 + } + + public enum EItemUpdateStatus + { + k_EItemUpdateStatusInvalid = 0 + } + + public enum EWorkshopFileType + { + k_EWorkshopFileTypeCommunity = 0 + } + + public enum ERemoteStoragePublishedFileVisibility + { + k_ERemoteStoragePublishedFileVisibilityPublic = 0 + } + + public enum EUGCQuery + { + k_EUGCQuery_RankedByPublicationDate = 0 + } + + public enum EUGCMatchingUGCType + { + k_EUGCMatchingUGCType_Items = 0, + k_EUGCMatchingUGCType_Items_ReadyToUse = 1 + } + + public enum EUserUGCList + { + k_EUserUGCList_Published = 0 + } + + public enum EUserUGCListSortOrder + { + k_EUserUGCListSortOrder_CreationOrderDesc = 0 + } + + public struct SteamUGCDetails_t + { + public PublishedFileId_t m_nPublishedFileId; + public string m_rgchTitle; + public string m_rgchDescription; + public string m_rgchTags; + public uint m_unVotesUp; + public uint m_unVotesDown; + public int m_nFileSize; + public uint m_rtimeCreated; + public uint m_rtimeUpdated; + public ulong m_ulSteamIDOwner; + } + + public struct SteamUGCQueryCompleted_t + { + public UGCQueryHandle_t m_handle; + public EResult m_eResult; + public uint m_unNumResultsReturned; + public uint m_unTotalMatchingResults; + } + + public struct CreateItemResult_t + { + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + public bool m_bUserNeedsToAcceptWorkshopLegalAgreement; + } + + public struct SubmitItemUpdateResult_t + { + public EResult m_eResult; + public bool m_bUserNeedsToAcceptWorkshopLegalAgreement; + } + + public struct RemoteStorageSubscribePublishedFileResult_t + { + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + } + + public struct RemoteStorageUnsubscribePublishedFileResult_t + { + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + } + + public sealed class CallResult + { + public static CallResult Create(Action callback) => new CallResult(); + public void Set(SteamAPICall_t apiCall) { } + public void Set(SteamAPICall_t apiCall, Action callback) { } + } + + public static class CallbackDispatcher + { + public static bool IsInitialized => false; + } + + public static class SteamAPI + { + public static bool IsSteamRunning() => false; + public static void RunCallbacks() { } + } + + public static class SteamUtils + { + public static AppId_t GetAppID() => new AppId_t(0); + public static bool InitFilterText(uint filterOptions = 0) => false; + + public static int FilterText(ETextFilteringContext context, CSteamID sourceSteamId, string input, out string filtered, uint filteredSize) + { + filtered = input; + return -1; + } + } + + public static class SteamUser + { + public static bool BLoggedOn() => false; + public static CSteamID GetSteamID() => CSteamID.Nil; + + public static uint GetAuthSessionTicket(byte[] ticket, int maxTicket, out uint ticketSize, ref SteamNetworkingIdentity identity) + { + ticketSize = 0; + return 0; + } + } + + public static class SteamFriends + { + public static string GetPersonaName() => string.Empty; + public static bool RequestUserInformation(CSteamID steamId, bool requireNameOnly) => false; + public static string GetFriendPersonaName(CSteamID steamId) => string.Empty; + } + + public static class SteamUGC + { + public static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery queryType, EUGCMatchingUGCType matchingType, AppId_t creatorAppId, AppId_t consumerAppId, uint page) => default; + public static UGCQueryHandle_t CreateQueryUserUGCRequest(uint accountId, EUserUGCList listType, EUGCMatchingUGCType matchingType, EUserUGCListSortOrder sortOrder, AppId_t creatorAppId, AppId_t consumerAppId, uint page) => default; + public static bool SetReturnLongDescription(UGCQueryHandle_t handle, bool value) => false; + public static bool SetReturnTotalOnly(UGCQueryHandle_t handle, bool value) => false; + public static SteamAPICall_t SendQueryUGCRequest(UGCQueryHandle_t handle) => default; + public static bool ReleaseQueryUGCRequest(UGCQueryHandle_t handle) => true; + public static bool GetQueryUGCResult(UGCQueryHandle_t handle, uint index, out SteamUGCDetails_t details) + { + details = default; + return false; + } + + public static uint GetItemState(PublishedFileId_t fileId) => 0; + public static bool GetItemInstallInfo(PublishedFileId_t fileId, out ulong sizeOnDisk, out string folder, uint folderSize, out uint timestamp) + { + sizeOnDisk = 0; + folder = string.Empty; + timestamp = 0; + return false; + } + + public static uint GetNumSubscribedItems() => 0; + public static uint GetSubscribedItems(PublishedFileId_t[] publishedFileIds, uint maxEntries) => 0; + public static SteamAPICall_t SubscribeItem(PublishedFileId_t fileId) => default; + public static SteamAPICall_t UnsubscribeItem(PublishedFileId_t fileId) => default; + public static SteamAPICall_t CreateItem(AppId_t consumerAppId, EWorkshopFileType fileType) => default; + public static UGCUpdateHandle_t StartItemUpdate(AppId_t consumerAppId, PublishedFileId_t fileId) => default; + public static bool SetItemTitle(UGCUpdateHandle_t handle, string title) => false; + public static bool SetItemDescription(UGCUpdateHandle_t handle, string description) => false; + public static bool SetItemContent(UGCUpdateHandle_t handle, string contentFolder) => false; + public static bool SetItemPreview(UGCUpdateHandle_t handle, string previewFile) => false; + public static bool SetItemVisibility(UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility visibility) => false; + public static bool SetItemTags(UGCUpdateHandle_t handle, System.Collections.Generic.IList tags) => false; + public static SteamAPICall_t SubmitItemUpdate(UGCUpdateHandle_t handle, string changeNote) => default; + public static EItemUpdateStatus GetItemUpdateProgress(UGCUpdateHandle_t handle, out ulong bytesProcessed, out ulong bytesTotal) + { + bytesProcessed = 0; + bytesTotal = 0; + return EItemUpdateStatus.k_EItemUpdateStatusInvalid; + } + } +} +#endif diff --git a/Unity/Assets/Scripts/TH1_Logic/Steam/SteamworksNonSteamStubs.cs.meta b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamworksNonSteamStubs.cs.meta new file mode 100644 index 000000000..5a18614eb --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Steam/SteamworksNonSteamStubs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da2c27e88ef14b3d9b65f2b1222f1f5d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_UI/Controller/Global/UIGlobalBugReportController.cs b/Unity/Assets/Scripts/TH1_UI/Controller/Global/UIGlobalBugReportController.cs index 32fc0a530..218e9bbb2 100644 --- a/Unity/Assets/Scripts/TH1_UI/Controller/Global/UIGlobalBugReportController.cs +++ b/Unity/Assets/Scripts/TH1_UI/Controller/Global/UIGlobalBugReportController.cs @@ -2,7 +2,9 @@ using TH1_Core.Events; using Logic.CrashSight; using TH1_Logic.Config; using TH1_Logic.Oss; +#if STEAM_CHANNEL || STEAMWORKS_NET using Steamworks; +#endif using TH1_UI.Controller.Base; using TH1_UI.View.Global; @@ -117,6 +119,7 @@ namespace TH1_UI.Controller.Global private static bool TryGetSteamId(out string steamId) { steamId = ""; +#if STEAM_CHANNEL || STEAMWORKS_NET try { if (!SteamUser.BLoggedOn()) @@ -134,6 +137,9 @@ namespace TH1_UI.Controller.Global LogSystem.LogWarning($"PlayerBugReport SteamID unavailable: {ex.Message}"); return false; } +#else + return false; +#endif } } }