IOS 相关代码迁移,增加新窗口
This commit is contained in:
parent
5d9c911414
commit
140146f1e3
@ -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;
|
||||
|
||||
598
Unity/Assets/Scripts/TH1_Logic/Editor/TH1UnifiedBuildWindow.cs
Normal file
598
Unity/Assets/Scripts/TH1_Logic/Editor/TH1UnifiedBuildWindow.cs
Normal file
@ -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<TH1UnifiedBuildWindow>("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<string>(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<string> 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<VersionConfig>(VersionConfigPath);
|
||||
if (_versionConfig == null)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(VersionConfigPath);
|
||||
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
_versionConfig = CreateInstance<VersionConfig>();
|
||||
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<string> 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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b7ee1d9bbf743e898610ee7468260ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -34,6 +34,12 @@ namespace TH1_Logic.Net
|
||||
|
||||
// 获取在线好友列表
|
||||
public Dictionary<ulong, MemberInfo> GetOnlineFriendsDict();
|
||||
|
||||
// 获取可展示房间列表
|
||||
public List<LobbyListInfo> 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<ulong, MemberInfo> GetOnlineFriendsDict()
|
||||
{
|
||||
return null;
|
||||
return new Dictionary<ulong, MemberInfo>();
|
||||
}
|
||||
|
||||
public List<LobbyListInfo> GetLobbyListInfos()
|
||||
{
|
||||
return new List<LobbyListInfo>();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aabdf2d1799e4f6192d3398f1a1f9290
|
||||
timeCreated: 1745464912
|
||||
@ -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)
|
||||
|
||||
@ -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<BaseMessage>(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;
|
||||
|
||||
21
Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs
Normal file
21
Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
11
Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs.meta
Normal file
11
Unity/Assets/Scripts/TH1_Logic/Steam/LobbyListInfo.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93f23d875f97403ba1d4cf2afdc2f8c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -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<LobbyListInfo> _lobbyListInfos;
|
||||
public List<LobbyListInfo> LobbyListInfos => _lobbyListInfos;
|
||||
public List<LobbyListInfo> GetLobbyListInfos() => _lobbyListInfos;
|
||||
private readonly HashSet<ulong> _lobbyReporters = new HashSet<ulong>();
|
||||
|
||||
// 事件委托
|
||||
@ -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
|
||||
|
||||
@ -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<LobbyListInfo> LobbyListInfos => GetLobbyListInfos();
|
||||
|
||||
public event Action<CSteamID> OnLobbyCreatedEvent;
|
||||
public event Action<CSteamID> OnLobbyEnteredEvent;
|
||||
public event Action<List<CSteamID>> OnLobbyLeftEvent;
|
||||
public event Action<CSteamID, CSteamID> OnHostChangedEvent;
|
||||
public event Action<List<CSteamID>> OnMembersChangedEvent;
|
||||
public event Action<string> OnLobbyErrorEvent;
|
||||
public event Action<CSteamID> OnMemberJoinedEvent;
|
||||
public event Action<CSteamID> 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<CSteamID> OnPeerConnectedEvent;
|
||||
public event Action<CSteamID> OnPeerDisconnectedEvent;
|
||||
public event Action<CSteamID, byte[]> OnMessageReceivedEvent;
|
||||
public event Action<CSteamID, string> OnMessageSendFailedEvent;
|
||||
public event Action<string> 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<CSteamID> GetConnectedPeers() => Array.Empty<CSteamID>();
|
||||
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<CSteamID> 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
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d9854f7e4ff4700b11fc15f41159a9b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
291
Unity/Assets/Scripts/TH1_Logic/Steam/SteamworksNonSteamStubs.cs
Normal file
291
Unity/Assets/Scripts/TH1_Logic/Steam/SteamworksNonSteamStubs.cs
Normal file
@ -0,0 +1,291 @@
|
||||
#if !(STEAM_CHANNEL || STEAMWORKS_NET)
|
||||
using System;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public struct CSteamID : IEquatable<CSteamID>
|
||||
{
|
||||
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<PublishedFileId_t>
|
||||
{
|
||||
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<T>
|
||||
{
|
||||
public static CallResult<T> Create(Action<T, bool> callback) => new CallResult<T>();
|
||||
public void Set(SteamAPICall_t apiCall) { }
|
||||
public void Set(SteamAPICall_t apiCall, Action<T, bool> 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<string> 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
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da2c27e88ef14b3d9b65f2b1222f1f5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user