Initial commit: Client Doc docs Server Tools

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ud18010
2026-07-10 10:24:29 +08:00
co-authored by Cursor
commit 7e35d8da31
3374 changed files with 680813 additions and 0 deletions
+136
View File
@@ -0,0 +1,136 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace XGame.Editor
{
// publish.json 视图(JsonUtilityC# 字段名须与 json 键一致,故小写开头)
[Serializable]
public sealed class MiniGamePublishSpec
{
public string gameId;
public string serverSrcDir; // 相对 Server/games-src/
public string serverProject; // 相对 serverSrcDir
public string serverAssembly;
public string serverEntryType;
public string clientProject; // 相对仓库根
public string coreDll;
public string clientDll;
public string clientEntryType;
public int minFrameworkVersion = 1;
public int playerCount = 2;
public int tickRateHz = 10;
}
public static class MiniGamePublishMenu
{
[MenuItem("XWorld/生成小游戏更新", false, 802)]
public static void Open() => MiniGamePublishWindow.Open();
}
public sealed class MiniGamePublishWindow : EditorWindow
{
private string[] _gameDirs = Array.Empty<string>();
private string[] _gameNames = Array.Empty<string>();
private int _selected;
private int _version = 1;
private bool _pc, _android, _ios, _webgl;
private Vector2 _scroll;
public static void Open()
{
var w = GetWindow<MiniGamePublishWindow>("生成小游戏更新");
w.minSize = new Vector2(360, 320);
w.RefreshGames();
w.Show();
}
private void RefreshGames()
{
string root = Path.Combine(Application.dataPath, "MiniGames");
_gameDirs = Directory.Exists(root)
? Directory.GetDirectories(root).Where(d => File.Exists(Path.Combine(d, "publish.json"))).ToArray()
: Array.Empty<string>();
_gameNames = _gameDirs.Select(Path.GetFileName).ToArray();
_selected = Mathf.Clamp(_selected, 0, Mathf.Max(0, _gameDirs.Length - 1));
// 默认平台 = 当前激活 BuildTarget
_pc = _android = _ios = _webgl = false;
switch (EditorUserBuildSettings.activeBuildTarget)
{
case BuildTarget.Android: _android = true; break;
case BuildTarget.iOS: _ios = true; break;
case BuildTarget.WebGL: _webgl = true; break;
default: _pc = true; break;
}
RefreshDefaultVersion();
}
private void RefreshDefaultVersion()
{
if (_gameDirs.Length == 0) return;
var spec = LoadSpec(_gameDirs[_selected]);
_version = (spec == null || string.IsNullOrEmpty(spec.gameId))
? 1 : MiniGamePublishPipeline.NextVersion(spec.gameId);
}
private static MiniGamePublishSpec LoadSpec(string gameDir)
{
try { return JsonUtility.FromJson<MiniGamePublishSpec>(File.ReadAllText(Path.Combine(gameDir, "publish.json"))); }
catch (Exception e) { Debug.LogError("[MiniGamePublish] publish.json 解析失败: " + e.Message); return null; }
}
private void OnGUI()
{
if (_gameDirs.Length == 0)
{
EditorGUILayout.HelpBox("Assets/MiniGames 下没有含 publish.json 的小游戏目录。", MessageType.Warning);
if (GUILayout.Button("刷新")) RefreshGames();
return;
}
_scroll = EditorGUILayout.BeginScrollView(_scroll);
EditorGUILayout.LabelField("小游戏", EditorStyles.boldLabel);
int sel = GUILayout.SelectionGrid(_selected, _gameNames, 1, EditorStyles.radioButton);
if (sel != _selected) { _selected = sel; RefreshDefaultVersion(); }
EditorGUILayout.Space();
_version = Mathf.Max(1, EditorGUILayout.IntField("版本号", _version));
EditorGUILayout.Space();
EditorGUILayout.LabelField("平台(AB 按平台构建)", EditorStyles.boldLabel);
_pc = EditorGUILayout.ToggleLeft("PC (StandaloneWindows64)", _pc);
_android = EditorGUILayout.ToggleLeft("Android", _android);
_ios = EditorGUILayout.ToggleLeft("iOS", _ios);
_webgl = EditorGUILayout.ToggleLeft("WebGL", _webgl);
EditorGUILayout.EndScrollView();
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(!(_pc || _android || _ios || _webgl)))
{
if (GUILayout.Button("生成", GUILayout.Height(32)))
{
var spec = LoadSpec(_gameDirs[_selected]);
if (spec == null || string.IsNullOrEmpty(spec.gameId))
{
EditorUtility.DisplayDialog("生成小游戏更新", "publish.json 无效(缺 gameId", "OK");
}
else
{
var targets = new List<MiniGamePublishPipeline.PlatformChoice>();
if (_pc) targets.Add(new MiniGamePublishPipeline.PlatformChoice("pc", BuildTarget.StandaloneWindows64));
if (_android) targets.Add(new MiniGamePublishPipeline.PlatformChoice("android", BuildTarget.Android));
if (_ios) targets.Add(new MiniGamePublishPipeline.PlatformChoice("ios", BuildTarget.iOS));
if (_webgl) targets.Add(new MiniGamePublishPipeline.PlatformChoice("webgl", BuildTarget.WebGL));
MiniGamePublishPipeline.Run(spec, _gameDirs[_selected], _version, targets);
}
}
}
}
}
}
#endif