初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace PCL;
|
||||
|
||||
/// <summary>
|
||||
/// Jar-in-Jar(内嵌模组)解析。
|
||||
/// </summary>
|
||||
public static class ModJarInJar
|
||||
{
|
||||
private const int MaxDepth = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 解析 <paramref name="jar" /> 内嵌套的其它 Mod jar,返回内嵌 Mod 列表。
|
||||
/// </summary>
|
||||
public static List<ModLocalComp.LocalCompFile> Resolve(string parentPath, ZipArchive jar, int depth = 0)
|
||||
{
|
||||
var result = new List<ModLocalComp.LocalCompFile>();
|
||||
if (depth >= MaxDepth) return result;
|
||||
|
||||
var nestedPaths = new List<string>();
|
||||
_CollectFabricNestedJars(jar, nestedPaths);
|
||||
_CollectForgeNestedJars(jar, nestedPaths);
|
||||
|
||||
foreach (var nestedPath in nestedPaths.Distinct())
|
||||
{
|
||||
try
|
||||
{
|
||||
var entry = jar.GetEntry(nestedPath);
|
||||
if (entry is null) continue;
|
||||
using var ms = new MemoryStream();
|
||||
using (var es = entry.Open()) es.CopyTo(ms);
|
||||
ms.Position = 0;
|
||||
using var nestedJar = new ZipArchive(ms, ZipArchiveMode.Read);
|
||||
|
||||
var childPath = parentPath + "!/" + nestedPath;
|
||||
var child = new ModLocalComp.LocalCompFile(childPath);
|
||||
child.LookupMetadata(nestedJar);
|
||||
child.MarkLoaded();
|
||||
child.EmbeddedMods = Resolve(childPath, nestedJar, depth + 1);
|
||||
result.Add(child);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModBase.Log(ex, "解析内嵌 Mod 失败(" + parentPath + " -> " + nestedPath + ")", ModBase.LogLevel.Developer);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void _CollectFabricNestedJars(ZipArchive jar, List<string> paths)
|
||||
{
|
||||
try
|
||||
{
|
||||
var entry = jar.GetEntry("fabric.mod.json");
|
||||
if (entry is null) return;
|
||||
var obj = (JsonObject)ModBase.GetJson(ModBase.ReadFile(entry.Open()));
|
||||
if (obj.TryGetPropertyValue("jars", out var jars) && jars is JsonArray arr)
|
||||
foreach (var j in arr)
|
||||
if (j is JsonObject jo && jo.TryGetPropertyValue("file", out var file) && file is not null)
|
||||
paths.Add(file.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModBase.Log(ex, "解析 fabric.mod.json 内嵌清单失败", ModBase.LogLevel.Developer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void _CollectForgeNestedJars(ZipArchive jar, List<string> paths)
|
||||
{
|
||||
try
|
||||
{
|
||||
var entry = jar.GetEntry("META-INF/jarjar/metadata.json");
|
||||
if (entry is null) return;
|
||||
var obj = (JsonObject)ModBase.GetJson(ModBase.ReadFile(entry.Open()));
|
||||
if (obj.TryGetPropertyValue("jars", out var jars) && jars is JsonArray arr)
|
||||
foreach (var j in arr)
|
||||
if (j is JsonObject jo && jo.TryGetPropertyValue("path", out var p) && p is not null)
|
||||
paths.Add(p.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModBase.Log(ex, "解析 META-INF/jarjar/metadata.json 内嵌清单失败", ModBase.LogLevel.Developer);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user