694 lines
31 KiB
C#
694 lines
31 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description: 回放编辑器
|
||
* @Date: 2025年04月22日 星期二 15:04:14
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System;
|
||
using System.Text;
|
||
using Logic.CrashSight;
|
||
using Logic.Multilingual;
|
||
using Steamworks;
|
||
using TH1_Logic.Core;
|
||
using TH1_Logic.Net;
|
||
using TH1_Logic.Oss;
|
||
using TH1_Logic.Steam;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
|
||
|
||
namespace Logic.Editor
|
||
{
|
||
public class SteamEditorWindow : EditorWindow
|
||
{
|
||
// 滑条
|
||
private Vector2 _barPosition;
|
||
|
||
// 背景
|
||
private GUIStyle _redBoxStyle;
|
||
private GUIStyle _whiteBoxStyle;
|
||
|
||
|
||
[MenuItem("Tools/Steam 编辑器")]
|
||
private static void ShowWindow()
|
||
{
|
||
var window = CreateWindow<SteamEditorWindow>();
|
||
window.titleContent = new GUIContent("Steam 编辑器");
|
||
window.Show();
|
||
}
|
||
|
||
private void OnGUI()
|
||
{
|
||
if (_redBoxStyle == null)
|
||
{
|
||
_redBoxStyle = InspectorUtils.GetHelpBoxStyle();
|
||
InspectorUtils.AddBorder(_redBoxStyle, new Color(0.5f, 0.4f, 0.4f, 0.6f));
|
||
}
|
||
if (_whiteBoxStyle == null)
|
||
{
|
||
_whiteBoxStyle = InspectorUtils.GetHelpBoxStyle();
|
||
InspectorUtils.AddBorder(_whiteBoxStyle, new Color(1f, 1f, 1f, 0.2f));
|
||
}
|
||
|
||
var lobby = LobbyManager.Instance.Lobby as SteamLobbyManager;
|
||
if (lobby == null) return;
|
||
|
||
GUI.skin.button.wordWrap = true;
|
||
_barPosition = EditorGUILayout.BeginScrollView(_barPosition);
|
||
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
InspectorUtils.InspectorTextWidthRich("Steam 测试状态");
|
||
InspectorUtils.InspectorTextWidthRich($"Steam初始化: {(lobby.IsSteamInitialized ? "✓" : "✗")}");
|
||
InspectorUtils.InspectorTextWidthRich($"用户登录: {(lobby.IsloggedIn ? "✓" : "✗")}");
|
||
InspectorUtils.InspectorTextWidthRich($"Lobby 初始化: {(lobby.IsLobbyInitialized ? "✓" : "✗")}");
|
||
InspectorUtils.InspectorTextWidthRich($"P2P 初始化: {(SimpleP2P.Instance.IsInitialized ? "✓" : "✗")}");
|
||
InspectorUtils.InspectorTextWidthRich($"是否全部初始化完毕: {(lobby.IsInitialized() ? "✓" : "✗")}");
|
||
InspectorUtils.InspectorTextWidthRich($"用户: {lobby.SelfName}");
|
||
InspectorUtils.InspectorTextWidthRich($"ID: {lobby.SelfID}");
|
||
|
||
InspectorUtils.InspectorTextWidthRich("房间状态");
|
||
InspectorUtils.InspectorTextWidthRich($"当前状态: {lobby.GetCurState()}");
|
||
InspectorUtils.InspectorTextWidthRich($"在房间中: {(lobby.IsInLobby() ? "✓" : "✗")}");
|
||
InspectorUtils.InspectorTextWidthRich($"是房主: {(lobby.IsLobbyOwner() ? "✓" : "✗")}");
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
|
||
if (lobby.IsInitialized() && lobby.IsInLobby())
|
||
{
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
InspectorUtils.InspectorTextWidthRich($"房间ID: {lobby.GetShareableLobbyId()}");
|
||
InspectorUtils.InspectorTextWidthRich($"成员数: {lobby.GetMemberCount()}/{lobby.GetMemberLimit()}");
|
||
InspectorUtils.InspectorTextWidthRich($"P2P连接数: {SimpleP2P.Instance.GetConnectionCount()}");
|
||
if (lobby.IsLobbyOwner())
|
||
{
|
||
foreach (var kv in lobby.GetAllMemberInfo())
|
||
{
|
||
EditorGUILayout.BeginHorizontal();
|
||
InspectorUtils.InspectorTextWidthRich($"{kv.Value.Name}");
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("踢出"))
|
||
{
|
||
lobby.KickMember(kv.Key);
|
||
}
|
||
EditorGUILayout.EndHorizontal();
|
||
}
|
||
}
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
}
|
||
|
||
if (lobby.IsInitialized())
|
||
{
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
InspectorUtils.InspectorTextWidthRich($"测试按钮");
|
||
EditorGUILayout.BeginHorizontal();
|
||
// 房间操作按钮
|
||
if (!lobby.IsInLobby())
|
||
{
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("创建房间"))
|
||
{
|
||
lobby.CreateLobby();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("离开房间")) lobby.LeaveLobby();
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("测试")) GameNetSender.Instance.BroadcastString("testtesttest");
|
||
if (lobby.IsLobbyOwner())
|
||
{
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("设置房间公开")) lobby.SetLobbyPublic();
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("设置房间私密")) lobby.SetLobbyFriendsOnly();
|
||
}
|
||
}
|
||
EditorGUILayout.EndHorizontal();
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
|
||
if (lobby.IsInLobby())
|
||
{
|
||
// 好友操作
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
InspectorUtils.InspectorTextWidthRich($"好友列表");
|
||
var friends = lobby.GetOnlineFriendsDict();
|
||
foreach (var kv in friends)
|
||
{
|
||
EditorGUILayout.BeginHorizontal();
|
||
InspectorUtils.InspectorTextWidthRich($"{kv.Value.Name}");
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("邀请"))
|
||
{
|
||
lobby.InviteFriend(kv.Key);
|
||
}
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
}
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
}
|
||
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
InspectorUtils.InspectorTextWidthRich($"测试改阵营");
|
||
var selfMemberId = LobbyManager.Instance.Lobby.GetSelfMemberId();
|
||
var civ = Main.Instance.MapConfig.GetMemberCiv(selfMemberId);
|
||
if (civ != null)
|
||
{
|
||
EditorGUILayout.BeginHorizontal();
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("改1")) civ.CivId = 1;
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("改2")) civ.CivId = 2;
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("改3")) civ.CivId = 3;
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("改4")) civ.CivId = 4;
|
||
EditorGUILayout.EndHorizontal();
|
||
}
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
}
|
||
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
EditorGUILayout.BeginHorizontal();
|
||
InspectorUtils.InspectorTextWidthRich($"服务器上的房间信息");
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("搜索")) lobby.SearchPublicLobbies();
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
foreach (var lobbyInfo in lobby.LobbyListInfos)
|
||
{
|
||
EditorGUILayout.BeginVertical(_redBoxStyle);
|
||
InspectorUtils.InspectorTextWidthRich($"LobbyId : {lobbyInfo.LobbyId}");
|
||
InspectorUtils.InspectorTextWidthRich($"OwnerId : {lobbyInfo.OwnerId}");
|
||
InspectorUtils.InspectorTextWidthRich($"OwnerName : {lobbyInfo.OwnerName}");
|
||
InspectorUtils.InspectorTextWidthRich($"RoomName : {lobbyInfo.RoomName}");
|
||
InspectorUtils.InspectorTextWidthRich($"Version : {lobbyInfo.Version}");
|
||
InspectorUtils.InspectorTextWidthRich($"CurrentPlayers : {lobbyInfo.CurrentPlayers}");
|
||
InspectorUtils.InspectorTextWidthRich($"MaxPlayers : {lobbyInfo.MaxPlayers}");
|
||
InspectorUtils.InspectorTextWidthRich($"GameState : {lobbyInfo.GameState}");
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("加入此房间"))
|
||
LobbyManager.Instance.Lobby.JoinLobbyById(lobbyInfo.LobbyId);
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
}
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
|
||
EditorGUILayout.EndScrollView();
|
||
}
|
||
}
|
||
|
||
public class SteamUploadFlowTestEditorWindow : EditorWindow
|
||
{
|
||
private const string FunctionUrl = "https://get-sts-token-qltjykaafr.cn-shanghai.fcapp.run";
|
||
|
||
private Vector2 _scrollPosition;
|
||
private GUIStyle _whiteBoxStyle;
|
||
private GUIStyle _sectionHeaderStyle;
|
||
private StsTokenService _stsService;
|
||
private OssUploadService _uploadService;
|
||
private bool _isRunning;
|
||
private string _version = "";
|
||
private string _normalPayload = "{\"test\":\"ossdata\"}";
|
||
private string _bugDescription = "测试 Bug 汇报";
|
||
private string _multilingualId = "1";
|
||
private string _multilingualSelectedText = "测试多语言选中文本";
|
||
private string _multilingualDescription = "测试多语言问题自述";
|
||
private MultilingualType _multilingualLanguage = MultilingualType.EN;
|
||
private string _questionnaireId = "upload-flow-test";
|
||
private string _questionnaireSingleChoiceId = "test-choice-a";
|
||
private string _questionnaireOpenText = "测试问卷开放题回答";
|
||
private string _status = "就绪";
|
||
private string _lastObjectKey = "";
|
||
|
||
[MenuItem("Tools/Steam 上传流程测试器")]
|
||
private static void ShowWindow()
|
||
{
|
||
var window = GetWindow<SteamUploadFlowTestEditorWindow>();
|
||
window.titleContent = new GUIContent("Steam 上传流程测试器");
|
||
window.minSize = new Vector2(560, 520);
|
||
window.Show();
|
||
}
|
||
|
||
private void OnEnable()
|
||
{
|
||
_stsService = new StsTokenService(FunctionUrl);
|
||
_uploadService = new OssUploadService();
|
||
|
||
if (string.IsNullOrEmpty(_version))
|
||
_version = PlayerBugReportService.GetCurrentVersion();
|
||
_multilingualLanguage = PlayerMultilingualReportService.GetCurrentLanguage();
|
||
}
|
||
|
||
private void OnGUI()
|
||
{
|
||
InitStyles();
|
||
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
|
||
|
||
DrawSteamState();
|
||
EditorGUILayout.Space(8);
|
||
DrawCommonInputs();
|
||
EditorGUILayout.Space(8);
|
||
DrawTestButtons();
|
||
EditorGUILayout.Space(8);
|
||
DrawStatus();
|
||
|
||
EditorGUILayout.EndScrollView();
|
||
}
|
||
|
||
private void InitStyles()
|
||
{
|
||
if (_whiteBoxStyle == null)
|
||
{
|
||
_whiteBoxStyle = InspectorUtils.GetHelpBoxStyle();
|
||
InspectorUtils.AddBorder(_whiteBoxStyle, new Color(1f, 1f, 1f, 0.2f));
|
||
}
|
||
|
||
if (_sectionHeaderStyle == null)
|
||
{
|
||
_sectionHeaderStyle = new GUIStyle(EditorStyles.boldLabel)
|
||
{
|
||
fontSize = 13,
|
||
padding = new RectOffset(2, 0, 4, 4)
|
||
};
|
||
}
|
||
}
|
||
|
||
private void DrawSteamState()
|
||
{
|
||
EditorGUILayout.LabelField("Steam 状态", _sectionHeaderStyle);
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
|
||
var lobby = LobbyManager.Instance.Lobby as SteamLobbyManager;
|
||
EditorGUILayout.LabelField("Play Mode", Application.isPlaying ? "运行中" : "未运行");
|
||
EditorGUILayout.LabelField("Steam AppID", GetSteamAppIdForDisplay());
|
||
if (lobby != null)
|
||
{
|
||
EditorGUILayout.LabelField("Steam 初始化", lobby.IsSteamInitialized ? "是" : "否");
|
||
EditorGUILayout.LabelField("用户登录", lobby.IsloggedIn ? "是" : "否");
|
||
EditorGUILayout.LabelField("Lobby 初始化", lobby.IsLobbyInitialized ? "是" : "否");
|
||
EditorGUILayout.LabelField("用户", lobby.SelfName);
|
||
EditorGUILayout.LabelField("SteamID", lobby.SelfID.ToString());
|
||
}
|
||
else
|
||
{
|
||
EditorGUILayout.HelpBox("未找到 SteamLobbyManager。请进入 Play Mode 后再测试。", MessageType.Warning);
|
||
}
|
||
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
|
||
private void DrawCommonInputs()
|
||
{
|
||
EditorGUILayout.LabelField("测试参数", _sectionHeaderStyle);
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
|
||
_version = EditorGUILayout.TextField("版本号", _version);
|
||
EditorGUILayout.LabelField("普通 OSS 测试内容");
|
||
_normalPayload = EditorGUILayout.TextArea(_normalPayload, GUILayout.MinHeight(45));
|
||
EditorGUILayout.LabelField("Bug 汇报自述");
|
||
_bugDescription = EditorGUILayout.TextArea(_bugDescription, GUILayout.MinHeight(55));
|
||
_multilingualLanguage = (MultilingualType)EditorGUILayout.EnumPopup("多语言语种", _multilingualLanguage);
|
||
_multilingualId = EditorGUILayout.TextField("多语言 ID", _multilingualId);
|
||
EditorGUILayout.LabelField("多语言选中文本");
|
||
_multilingualSelectedText = EditorGUILayout.TextArea(_multilingualSelectedText, GUILayout.MinHeight(55));
|
||
EditorGUILayout.LabelField("多语言玩家自述");
|
||
_multilingualDescription = EditorGUILayout.TextArea(_multilingualDescription, GUILayout.MinHeight(55));
|
||
_questionnaireId = EditorGUILayout.TextField("问卷 ID", _questionnaireId);
|
||
_questionnaireSingleChoiceId = EditorGUILayout.TextField("问卷单选选项 ID", _questionnaireSingleChoiceId);
|
||
EditorGUILayout.LabelField("问卷开放题回答");
|
||
_questionnaireOpenText = EditorGUILayout.TextArea(_questionnaireOpenText, GUILayout.MinHeight(45));
|
||
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
|
||
private void DrawTestButtons()
|
||
{
|
||
EditorGUILayout.LabelField("上传流程", _sectionHeaderStyle);
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
|
||
using (new EditorGUI.DisabledScope(_isRunning || !Application.isPlaying))
|
||
{
|
||
if (GUILayout.Button("1. Steam 身份预校验 action=steamauth", GUILayout.Height(28)))
|
||
TestSteamWarmup();
|
||
if (GUILayout.Button("2. 普通 OSS 上传 type=ossdata", GUILayout.Height(28)))
|
||
TestOssDataUpload();
|
||
if (GUILayout.Button("3. Bug 汇报上传 type=bugreport", GUILayout.Height(28)))
|
||
TestBugReportUpload();
|
||
if (GUILayout.Button("4. 多语言汇报上传 type=multilingualreport", GUILayout.Height(28)))
|
||
TestMultilingualReportUpload();
|
||
if (GUILayout.Button("5. 问卷上传 type=questionnaire", GUILayout.Height(28)))
|
||
TestQuestionnaireUpload();
|
||
if (GUILayout.Button("顺序测试 1-5", GUILayout.Height(32)))
|
||
TestAll();
|
||
}
|
||
|
||
if (!Application.isPlaying)
|
||
EditorGUILayout.HelpBox("这个测试器需要 Play Mode 中的 Steam 登录态和 AuthTicket。", MessageType.Info);
|
||
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
|
||
private void DrawStatus()
|
||
{
|
||
EditorGUILayout.LabelField("结果", _sectionHeaderStyle);
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
EditorGUILayout.HelpBox(_status, MessageType.Info);
|
||
if (!string.IsNullOrEmpty(_lastObjectKey))
|
||
EditorGUILayout.SelectableLabel(_lastObjectKey, EditorStyles.textField, GUILayout.Height(22));
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
|
||
private async void TestSteamWarmup()
|
||
{
|
||
await RunTest("Steam 身份预校验", async () =>
|
||
{
|
||
var steamId = GetSteamId();
|
||
var authTicket = GetAuthTicket();
|
||
var response = await _stsService.WarmupSteamAuthAsync(steamId, authTicket, _version);
|
||
_lastObjectKey = "";
|
||
return $"Steam 预校验成功: cached={response.cached}, expiresIn={response.expiresIn}s, steamId={response.steamId}";
|
||
});
|
||
}
|
||
|
||
private async void TestOssDataUpload()
|
||
{
|
||
await RunTest("普通 OSS 上传", async () =>
|
||
{
|
||
var steamId = GetSteamId();
|
||
var authTicket = GetAuthTicket();
|
||
var credentials = await _stsService.RequestStsTokenAsync(steamId, authTicket, "ossdata", _version);
|
||
var bytes = Encoding.UTF8.GetBytes(string.IsNullOrEmpty(_normalPayload)
|
||
? "{\"test\":\"ossdata\"}"
|
||
: _normalPayload);
|
||
var success = await _uploadService.UploadFileAsync(credentials, bytes, "application/json");
|
||
_lastObjectKey = credentials.objectKey;
|
||
return success
|
||
? $"普通 OSS 上传成功: {credentials.objectKey}"
|
||
: $"普通 OSS 上传失败: {credentials.objectKey}";
|
||
});
|
||
}
|
||
|
||
private async void TestBugReportUpload()
|
||
{
|
||
await RunTest("Bug 汇报上传", async () =>
|
||
{
|
||
var steamId = GetSteamId();
|
||
var package = PlayerBugReportService.BuildPackage(steamId, _bugDescription, _version,
|
||
false, false, false);
|
||
var result = await OssManager.Instance.UploadPlayerBugReportAsync(steamId, package.Data,
|
||
package.Manifest.version);
|
||
_lastObjectKey = result.objectKey ?? "";
|
||
return result.success
|
||
? $"Bug 汇报上传成功: {result.objectKey}"
|
||
: $"Bug 汇报上传失败: {result.objectKey}";
|
||
});
|
||
}
|
||
|
||
private async void TestMultilingualReportUpload()
|
||
{
|
||
await RunTest("多语言汇报上传", async () =>
|
||
{
|
||
if (!uint.TryParse(_multilingualId.Trim(), out var id) || id == 0)
|
||
throw new Exception("多语言 ID 必须是大于 0 的整数");
|
||
if (string.IsNullOrWhiteSpace(_multilingualSelectedText))
|
||
throw new Exception("多语言选中文本不能为空");
|
||
if (string.IsNullOrWhiteSpace(_multilingualDescription))
|
||
throw new Exception("多语言玩家自述不能为空");
|
||
|
||
var steamId = GetSteamId();
|
||
var package = PlayerMultilingualReportService.BuildPackage(steamId, id, _multilingualSelectedText,
|
||
_multilingualDescription, _version, _multilingualLanguage);
|
||
var result = await OssManager.Instance.UploadPlayerMultilingualReportAsync(steamId, package.Data,
|
||
package.Manifest.version);
|
||
_lastObjectKey = result.objectKey ?? "";
|
||
return result.success
|
||
? $"多语言汇报上传成功: {result.objectKey}"
|
||
: $"多语言汇报上传失败: {result.objectKey}";
|
||
});
|
||
}
|
||
|
||
private async void TestQuestionnaireUpload()
|
||
{
|
||
await RunTest("问卷上传", async () =>
|
||
{
|
||
var steamId = GetSteamId();
|
||
var authTicket = GetAuthTicket();
|
||
var questionnaireBytes = BuildQuestionnairePayloadBytes(steamId);
|
||
var credentials = await _stsService.RequestStsTokenAsync(steamId, authTicket, "questionnaire",
|
||
_version);
|
||
if (!IsQuestionnaireObjectKey(credentials?.objectKey))
|
||
throw new Exception($"服务端返回了非问卷 objectKey: {credentials?.objectKey}");
|
||
var success = await _uploadService.UploadFileAsync(credentials, questionnaireBytes,
|
||
"application/json", MaxQuestionnaireUploadBytes);
|
||
_lastObjectKey = credentials.objectKey ?? "";
|
||
return success
|
||
? $"问卷上传成功: {credentials.objectKey}"
|
||
: $"问卷上传失败: {credentials.objectKey}";
|
||
});
|
||
}
|
||
|
||
private async void TestAll()
|
||
{
|
||
await RunTest("顺序测试 1-5", async () =>
|
||
{
|
||
var steamId = GetSteamId();
|
||
var authTicket = GetAuthTicket();
|
||
var warmup = await _stsService.WarmupSteamAuthAsync(steamId, authTicket, _version);
|
||
|
||
var credentials = await _stsService.RequestStsTokenAsync(steamId, authTicket, "ossdata", _version);
|
||
var normalBytes = Encoding.UTF8.GetBytes(string.IsNullOrEmpty(_normalPayload)
|
||
? "{\"test\":\"ossdata\"}"
|
||
: _normalPayload);
|
||
var normalOk = await _uploadService.UploadFileAsync(credentials, normalBytes, "application/json");
|
||
|
||
var bugPackage = PlayerBugReportService.BuildPackage(steamId, _bugDescription, _version,
|
||
false, false, false);
|
||
var bugOk = await OssManager.Instance.UploadPlayerBugReportAsync(steamId, bugPackage.Data,
|
||
bugPackage.Manifest.version);
|
||
|
||
if (!uint.TryParse(_multilingualId.Trim(), out var id) || id == 0)
|
||
throw new Exception("多语言 ID 必须是大于 0 的整数");
|
||
var multilingualPackage = PlayerMultilingualReportService.BuildPackage(steamId, id,
|
||
_multilingualSelectedText, _multilingualDescription, _version, _multilingualLanguage);
|
||
var multilingualOk = await OssManager.Instance.UploadPlayerMultilingualReportAsync(steamId,
|
||
multilingualPackage.Data, multilingualPackage.Manifest.version);
|
||
|
||
var questionnaireBytes = BuildQuestionnairePayloadBytes(steamId);
|
||
var questionnaireCredentials = await _stsService.RequestStsTokenAsync(steamId, authTicket,
|
||
"questionnaire", _version);
|
||
if (!IsQuestionnaireObjectKey(questionnaireCredentials?.objectKey))
|
||
throw new Exception($"服务端返回了非问卷 objectKey: {questionnaireCredentials?.objectKey}");
|
||
var questionnaireOk = await _uploadService.UploadFileAsync(questionnaireCredentials,
|
||
questionnaireBytes, "application/json", MaxQuestionnaireUploadBytes);
|
||
|
||
_lastObjectKey = questionnaireCredentials.objectKey ?? "";
|
||
return $"顺序测试完成: steamauth cached={warmup.cached}; ossdata={(normalOk ? "成功" : "失败")} {credentials.objectKey}; bugreport={(bugOk.success ? "成功" : "失败")} {bugOk.objectKey}; multilingualreport={(multilingualOk.success ? "成功" : "失败")} {multilingualOk.objectKey}; questionnaire={(questionnaireOk ? "成功" : "失败")} {questionnaireCredentials.objectKey}";
|
||
});
|
||
}
|
||
|
||
private async System.Threading.Tasks.Task RunTest(string title,
|
||
Func<System.Threading.Tasks.Task<string>> action)
|
||
{
|
||
_isRunning = true;
|
||
_status = $"{title} 运行中...";
|
||
Repaint();
|
||
|
||
try
|
||
{
|
||
var result = await action();
|
||
_status = result;
|
||
Debug.Log($"[SteamUploadFlowTest] {result}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_status = $"{title} 失败: {ex.Message}";
|
||
Debug.LogError($"[SteamUploadFlowTest] {title} failed: {ex}");
|
||
}
|
||
finally
|
||
{
|
||
_isRunning = false;
|
||
Repaint();
|
||
}
|
||
}
|
||
|
||
private static string GetSteamId()
|
||
{
|
||
try
|
||
{
|
||
if (SteamUser.BLoggedOn())
|
||
{
|
||
var id = SteamUser.GetSteamID().m_SteamID;
|
||
if (id != 0) return id.ToString();
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// ignored
|
||
}
|
||
|
||
var lobbyId = LobbyManager.Instance.Lobby.GetSelfMemberId();
|
||
if (lobbyId != 0) return lobbyId.ToString();
|
||
throw new Exception("未获取到 SteamID,请确认 Steam 已初始化并登录");
|
||
}
|
||
|
||
private static string GetAuthTicket()
|
||
{
|
||
var ticket = new byte[1024];
|
||
var identity = new SteamNetworkingIdentity();
|
||
SteamUser.GetAuthSessionTicket(ticket, 1024, out var ticketSize, ref identity);
|
||
if (ticketSize == 0)
|
||
throw new Exception("Steam auth ticket is empty");
|
||
|
||
return BitConverter.ToString(ticket, 0, (int)ticketSize).Replace("-", "").ToLower();
|
||
}
|
||
|
||
private static string GetSteamAppIdForDisplay()
|
||
{
|
||
try
|
||
{
|
||
var appId = SteamUtils.GetAppID().m_AppId;
|
||
return appId == 0 ? "(未获取到)" : appId.ToString();
|
||
}
|
||
catch
|
||
{
|
||
return "(Steam 未初始化)";
|
||
}
|
||
}
|
||
|
||
private const int MaxQuestionnaireUploadBytes = 512 * 1024;
|
||
|
||
private static bool IsQuestionnaireObjectKey(string objectKey)
|
||
{
|
||
return !string.IsNullOrEmpty(objectKey)
|
||
&& objectKey.StartsWith("questionnaire/", StringComparison.Ordinal)
|
||
&& objectKey.EndsWith(".json", StringComparison.OrdinalIgnoreCase);
|
||
}
|
||
|
||
[Serializable]
|
||
private class QuestionnaireTestPayload
|
||
{
|
||
public string schema = "th1.questionnaire-answer.v1";
|
||
public string responseId;
|
||
public string questionnaireId;
|
||
public long submittedAtUnix;
|
||
public string submittedAtUtc;
|
||
public string createdAtUtc;
|
||
public string createdAtLocal;
|
||
public string timezone;
|
||
public string steamId;
|
||
public string version;
|
||
public string unityVersion;
|
||
public string platform;
|
||
public string crashSightDeviceId;
|
||
public string deviceModel;
|
||
public string deviceName;
|
||
public string operatingSystem;
|
||
public string processorType;
|
||
public int processorCount;
|
||
public int systemMemorySizeMb;
|
||
public string graphicsDeviceName;
|
||
public int graphicsMemorySizeMb;
|
||
public QuestionnaireTestAnswerSheet answerSheet;
|
||
}
|
||
|
||
[Serializable]
|
||
private class QuestionnaireTestAnswerSheet
|
||
{
|
||
public string QuestionnaireId;
|
||
public long SubmittedAtUnix;
|
||
public string SubmittedAtUtc;
|
||
public string LastUploadObjectKey = "";
|
||
public string LastUploadedAtUtc = "";
|
||
public string LastUploadError = "";
|
||
public QuestionnaireTestAnswer[] Answers;
|
||
}
|
||
|
||
[Serializable]
|
||
private class QuestionnaireTestAnswer
|
||
{
|
||
public string QuestionId;
|
||
public int QuestionType;
|
||
public string[] SelectedOptionIds;
|
||
public string OpenText;
|
||
}
|
||
|
||
private byte[] BuildQuestionnairePayloadBytes(string steamId)
|
||
{
|
||
var now = DateTimeOffset.UtcNow;
|
||
var questionnaireId = string.IsNullOrWhiteSpace(_questionnaireId)
|
||
? "upload-flow-test"
|
||
: _questionnaireId.Trim();
|
||
var selectedOptionId = string.IsNullOrWhiteSpace(_questionnaireSingleChoiceId)
|
||
? "test-choice-a"
|
||
: _questionnaireSingleChoiceId.Trim();
|
||
var openText = string.IsNullOrWhiteSpace(_questionnaireOpenText)
|
||
? "测试问卷开放题回答"
|
||
: _questionnaireOpenText.Trim();
|
||
var submittedAtUtc = now.UtcDateTime.ToString("O");
|
||
var answerSheet = new QuestionnaireTestAnswerSheet
|
||
{
|
||
QuestionnaireId = questionnaireId,
|
||
SubmittedAtUnix = now.ToUnixTimeSeconds(),
|
||
SubmittedAtUtc = submittedAtUtc,
|
||
Answers = new[]
|
||
{
|
||
new QuestionnaireTestAnswer
|
||
{
|
||
QuestionId = "upload-flow-single-choice",
|
||
QuestionType = 1,
|
||
SelectedOptionIds = new[] { selectedOptionId },
|
||
OpenText = ""
|
||
},
|
||
new QuestionnaireTestAnswer
|
||
{
|
||
QuestionId = "upload-flow-open",
|
||
QuestionType = 0,
|
||
SelectedOptionIds = Array.Empty<string>(),
|
||
OpenText = openText
|
||
}
|
||
}
|
||
};
|
||
|
||
var payload = new QuestionnaireTestPayload
|
||
{
|
||
responseId = Guid.NewGuid().ToString("N"),
|
||
questionnaireId = questionnaireId,
|
||
submittedAtUnix = answerSheet.SubmittedAtUnix,
|
||
submittedAtUtc = submittedAtUtc,
|
||
createdAtUtc = DateTime.UtcNow.ToString("O"),
|
||
createdAtLocal = DateTime.Now.ToString("O"),
|
||
timezone = GetLocalTimezone(),
|
||
steamId = steamId ?? "",
|
||
version = string.IsNullOrWhiteSpace(_version) ? PlayerBugReportService.GetCurrentVersion() : _version.Trim(),
|
||
unityVersion = Application.unityVersion,
|
||
platform = Application.platform.ToString(),
|
||
crashSightDeviceId = CrashSightManager.GetCrashSightDeviceId(),
|
||
deviceModel = SystemInfo.deviceModel,
|
||
deviceName = SystemInfo.deviceName,
|
||
operatingSystem = SystemInfo.operatingSystem,
|
||
processorType = SystemInfo.processorType,
|
||
processorCount = SystemInfo.processorCount,
|
||
systemMemorySizeMb = SystemInfo.systemMemorySize,
|
||
graphicsDeviceName = SystemInfo.graphicsDeviceName,
|
||
graphicsMemorySizeMb = SystemInfo.graphicsMemorySize,
|
||
answerSheet = answerSheet
|
||
};
|
||
|
||
var bytes = new UTF8Encoding(false).GetBytes(JsonUtility.ToJson(payload, true));
|
||
if (bytes.Length > MaxQuestionnaireUploadBytes)
|
||
throw new Exception($"问卷测试 payload 大小 {bytes.Length} 超过 {MaxQuestionnaireUploadBytes} 字节限制");
|
||
|
||
return bytes;
|
||
}
|
||
|
||
private static string GetLocalTimezone()
|
||
{
|
||
try
|
||
{
|
||
var offset = DateTimeOffset.Now.Offset;
|
||
var sign = offset < TimeSpan.Zero ? "-" : "+";
|
||
return $"{TimeZoneInfo.Local.Id} (UTC{sign}{offset.Duration():hh\\:mm})";
|
||
}
|
||
catch
|
||
{
|
||
return DateTimeOffset.Now.Offset.ToString();
|
||
}
|
||
}
|
||
}
|
||
}
|