using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text.Json.Nodes; namespace PCL; /// /// Jar-in-Jar(内嵌模组)解析。 /// public static class ModJarInJar { private const int MaxDepth = 5; /// /// 解析 内嵌套的其它 Mod jar,返回内嵌 Mod 列表。 /// public static List Resolve(string parentPath, ZipArchive jar, int depth = 0) { var result = new List(); if (depth >= MaxDepth) return result; var nestedPaths = new List(); _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 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 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); } } }