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
@@ -0,0 +1,68 @@
using System;
using System.IO;
using System.Reflection;
using UnityEngine;
using XWorld.Framework;
namespace XGame.MiniGame
{
// 从代码 ABmanifest.CodeAb)取出 Core/Client 热更 DLL 字节并加载,反射出 IGameClient 入口工厂
public sealed class MiniGameAssemblyLoader
{
public Func<IGameClient> CreateClient { get; private set; }
public string Error { get; private set; }
// localDir: MiniGameDownloader.LocalDirmanifest: 解析好的 game.json
public bool Load(string localDir, MiniGameManifest manifest)
{
string abPath = localDir + manifest.CodeAb;
if (!File.Exists(abPath))
{ Error = $"缺少代码 AB: {abPath}(需要 codeAb 统一 AB 格式,旧 .bytes 包不再支持)"; return false; }
AssetBundle ab = null;
try
{
ab = MiniGamePlatform.LoadAssetBundle(abPath);
if (ab == null) { Error = "代码 AB 打开失败: " + abPath; return false; }
byte[] coreBytes = LoadDllBytes(ab, manifest.CoreDll);
byte[] clientBytes = LoadDllBytes(ab, manifest.ClientDll);
if (coreBytes == null || clientBytes == null)
{
Error = $"代码 AB 内缺少 {manifest.CoreDll}/{manifest.ClientDll} 的 .bytesAB 内资产: {string.Join(", ", ab.GetAllAssetNames())}";
return false;
}
// Core 先于 Client 加载(Client 依赖 Core
Assembly.Load(coreBytes);
Assembly clientAsm = Assembly.Load(clientBytes);
Type entry = clientAsm.GetType(manifest.ClientEntryType);
if (entry == null) { Error = "找不到入口类型 " + manifest.ClientEntryType; return false; }
if (!typeof(IGameClient).IsAssignableFrom(entry))
{ Error = manifest.ClientEntryType + " 未实现 IGameClient"; return false; }
CreateClient = () => (IGameClient)Activator.CreateInstance(entry);
return true;
}
catch (Exception e)
{
Error = "加载小游戏程序集失败: " + e;
Debug.LogError("[MiniGameAssemblyLoader] " + Error);
return false;
}
finally
{
// DLL 字节已复制进托管内存,AB 本体可卸;false=不销毁已取出的对象
if (ab != null) ab.Unload(false);
}
}
// "X.dll.bytes" 导入后资产名为 "X.dll"Unity 剥最后一个扩展名);两种写法都试
private static byte[] LoadDllBytes(AssetBundle ab, string dllName)
{
TextAsset ta = ab.LoadAsset<TextAsset>(dllName) ?? ab.LoadAsset<TextAsset>(dllName + ".bytes");
return ta != null ? ta.bytes : null;
}
}
}