chore(HM):使解压功能可用
This commit is contained in:
32
backend/package-lock.json
generated
32
backend/package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"adm-zip": "^0.5.16",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"fs-extra": "^11.3.1",
|
"fs-extra": "^11.3.1",
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||||
"@rollup/plugin-terser": "^0.4.4",
|
"@rollup/plugin-terser": "^0.4.4",
|
||||||
"@rollup/plugin-typescript": "^12.1.4",
|
"@rollup/plugin-typescript": "^12.1.4",
|
||||||
|
"@types/adm-zip": "^0.5.7",
|
||||||
"@types/cors": "^2.8.19",
|
"@types/cors": "^2.8.19",
|
||||||
"@types/express": "^5.0.3",
|
"@types/express": "^5.0.3",
|
||||||
"@types/fs-extra": "^11.0.4",
|
"@types/fs-extra": "^11.0.4",
|
||||||
@@ -193,6 +195,7 @@
|
|||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -656,6 +659,16 @@
|
|||||||
"node": ">=14.16"
|
"node": ">=14.16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/adm-zip": {
|
||||||
|
"version": "0.5.7",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/adm-zip/-/adm-zip-0.5.7.tgz",
|
||||||
|
"integrity": "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/body-parser": {
|
"node_modules/@types/body-parser": {
|
||||||
"version": "1.19.6",
|
"version": "1.19.6",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.6.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.6.tgz",
|
||||||
@@ -1225,6 +1238,7 @@
|
|||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -1245,12 +1259,22 @@
|
|||||||
"acorn": "^8.14.0"
|
"acorn": "^8.14.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/adm-zip": {
|
||||||
|
"version": "0.5.16",
|
||||||
|
"resolved": "https://registry.npmmirror.com/adm-zip/-/adm-zip-0.5.16.tgz",
|
||||||
|
"integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "8.17.1",
|
"version": "8.17.1",
|
||||||
"resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz",
|
"resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz",
|
||||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"fast-uri": "^3.0.1",
|
"fast-uri": "^3.0.1",
|
||||||
@@ -1577,6 +1601,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001737",
|
"caniuse-lite": "^1.0.30001737",
|
||||||
"electron-to-chromium": "^1.5.211",
|
"electron-to-chromium": "^1.5.211",
|
||||||
@@ -5326,6 +5351,7 @@
|
|||||||
"integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==",
|
"integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.8"
|
"@types/estree": "1.0.8"
|
||||||
},
|
},
|
||||||
@@ -6173,7 +6199,8 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
|
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
|
||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "0BSD"
|
"license": "0BSD",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/tunnel-agent": {
|
"node_modules/tunnel-agent": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
@@ -6253,6 +6280,7 @@
|
|||||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -6396,6 +6424,7 @@
|
|||||||
"integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==",
|
"integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/eslint-scope": "^3.7.7",
|
"@types/eslint-scope": "^3.7.7",
|
||||||
"@types/estree": "^1.0.8",
|
"@types/estree": "^1.0.8",
|
||||||
@@ -6445,6 +6474,7 @@
|
|||||||
"integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==",
|
"integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discoveryjs/json-ext": "^0.6.1",
|
"@discoveryjs/json-ext": "^0.6.1",
|
||||||
"@webpack-cli/configtest": "^3.0.1",
|
"@webpack-cli/configtest": "^3.0.1",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||||
"@rollup/plugin-terser": "^0.4.4",
|
"@rollup/plugin-terser": "^0.4.4",
|
||||||
"@rollup/plugin-typescript": "^12.1.4",
|
"@rollup/plugin-typescript": "^12.1.4",
|
||||||
|
"@types/adm-zip": "^0.5.7",
|
||||||
"@types/cors": "^2.8.19",
|
"@types/cors": "^2.8.19",
|
||||||
"@types/express": "^5.0.3",
|
"@types/express": "^5.0.3",
|
||||||
"@types/fs-extra": "^11.0.4",
|
"@types/fs-extra": "^11.0.4",
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
"typescript": "^5.9.2"
|
"typescript": "^5.9.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"adm-zip": "^0.5.16",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"fs-extra": "^11.3.1",
|
"fs-extra": "^11.3.1",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import p from "node:path";
|
import p from "node:path";
|
||||||
import websocket, { WebSocketServer } from "ws";
|
import websocket, { WebSocketServer } from "ws";
|
||||||
import { yauzl_promise } from "./utils/yauzl.promise.js";
|
//import { yauzl_promise } from "./utils/yauzl.promise.js";
|
||||||
import { pipeline } from "node:stream/promises";
|
import { pipeline } from "node:stream/promises";
|
||||||
import { platform, what_platform } from "./platform/index.js";
|
import { platform, what_platform } from "./platform/index.js";
|
||||||
import { DeEarth } from "./utils/DeEarth.js";
|
import { DeEarth } from "./utils/DeEarth.js";
|
||||||
@@ -10,6 +10,7 @@ import config from "./utils/config.js";
|
|||||||
import { execPromise } from "./utils/utils.js";
|
import { execPromise } from "./utils/utils.js";
|
||||||
import { MessageWS } from "./utils/ws.js";
|
import { MessageWS } from "./utils/ws.js";
|
||||||
import { logger } from "./utils/logger.js";
|
import { logger } from "./utils/logger.js";
|
||||||
|
import { yauzl_promise } from "./utils/ziplib.js";
|
||||||
|
|
||||||
export class Dex {
|
export class Dex {
|
||||||
wsx!: WebSocketServer;
|
wsx!: WebSocketServer;
|
||||||
@@ -24,7 +25,8 @@ export class Dex {
|
|||||||
public async Main(buffer: Buffer, dser: boolean) {
|
public async Main(buffer: Buffer, dser: boolean) {
|
||||||
try {
|
try {
|
||||||
const first = Date.now();
|
const first = Date.now();
|
||||||
const { contain, info } = await this._getinfo(buffer);
|
const zps = await this._zps(buffer);
|
||||||
|
const { contain, info } = await zps._getinfo();
|
||||||
const plat = what_platform(contain);
|
const plat = what_platform(contain);
|
||||||
logger.debug("Platform detected", plat);
|
logger.debug("Platform detected", plat);
|
||||||
logger.debug("Modpack info", info);
|
logger.debug("Modpack info", info);
|
||||||
@@ -32,9 +34,11 @@ export class Dex {
|
|||||||
const unpath = `./instance/${mpname}`;
|
const unpath = `./instance/${mpname}`;
|
||||||
// 解压和下载(并行处理)
|
// 解压和下载(并行处理)
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._unzip(buffer, mpname),
|
zps._unzip(mpname),
|
||||||
platform(plat).downloadfile(info, unpath, this.message)
|
platform(plat).downloadfile(info, unpath, this.message)
|
||||||
]);
|
]).catch(e=>{
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
this.message.statusChange(); //改变状态
|
this.message.statusChange(); //改变状态
|
||||||
await new DeEarth(`${unpath}/mods`, `./.rubbish/${mpname}`).Main();
|
await new DeEarth(`${unpath}/mods`, `./.rubbish/${mpname}`).Main();
|
||||||
this.message.statusChange(); //改变状态(DeEarth筛选模组完毕)
|
this.message.statusChange(); //改变状态(DeEarth筛选模组完毕)
|
||||||
@@ -68,10 +72,10 @@ export class Dex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _getinfo(buffer: Buffer) {
|
private async _zps(buffer: Buffer) {
|
||||||
const importantFiles = ["manifest.json", "modrinth.index.json"];
|
|
||||||
const zip = await yauzl_promise(buffer);
|
const zip = await yauzl_promise(buffer);
|
||||||
|
const _getinfo = async () => {
|
||||||
|
const importantFiles = ["manifest.json", "modrinth.index.json"];
|
||||||
for await (const entry of zip) {
|
for await (const entry of zip) {
|
||||||
if (importantFiles.includes(entry.fileName)) {
|
if (importantFiles.includes(entry.fileName)) {
|
||||||
const content = await entry.ReadEntry;
|
const content = await entry.ReadEntry;
|
||||||
@@ -80,19 +84,16 @@ export class Dex {
|
|||||||
return { contain: entry.fileName, info };
|
return { contain: entry.fileName, info };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("No manifest file found in modpack");
|
throw new Error("No manifest file found in modpack");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _unzip(buffer: Buffer, instancename: string) {
|
const _unzip = async (instancename: string) => {
|
||||||
logger.info("Starting unzip process", { instancename });
|
logger.info("Starting unzip process", { instancename });
|
||||||
const zip = await yauzl_promise(buffer);
|
|
||||||
const instancePath = `./instance/${instancename}`;
|
const instancePath = `./instance/${instancename}`;
|
||||||
let index = 1;
|
let index = 1;
|
||||||
|
|
||||||
for await (const entry of zip) {
|
for await (const entry of zip) {
|
||||||
const isDir = entry.fileName.endsWith("/");
|
const isDir = entry.fileName.endsWith("/");
|
||||||
|
console.log(index, entry.fileName);
|
||||||
if (isDir) {
|
if (isDir) {
|
||||||
await fs.promises.mkdir(`${instancePath}/${entry.fileName}`, {
|
await fs.promises.mkdir(`${instancePath}/${entry.fileName}`, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
@@ -100,27 +101,27 @@ export class Dex {
|
|||||||
} else if (entry.fileName.startsWith("overrides/")) {
|
} else if (entry.fileName.startsWith("overrides/")) {
|
||||||
// 跳过黑名单文件
|
// 跳过黑名单文件
|
||||||
if (this._ublack(entry.fileName)) {
|
if (this._ublack(entry.fileName)) {
|
||||||
|
console.log("Skip blacklist file", entry.fileName);
|
||||||
index++;
|
index++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建目标目录
|
// 创建目标目录
|
||||||
const targetPath = entry.fileName.replace("overrides/", "");
|
const targetPath = entry.fileName.replace("overrides/", "");
|
||||||
const dirPath = `${instancePath}/${targetPath.substring(0, targetPath.lastIndexOf("/"))}`;
|
const dirPath = `${instancePath}/${targetPath.substring(0, targetPath.lastIndexOf("/"))}`;
|
||||||
await fs.promises.mkdir(dirPath, { recursive: true });
|
await fs.promises.mkdir(dirPath, { recursive: true });
|
||||||
|
|
||||||
// 解压文件
|
// 解压文件
|
||||||
const stream = await entry.openReadStream;
|
const stream = await entry.openReadStream;
|
||||||
|
console.log(entry.fileName);
|
||||||
const write = fs.createWriteStream(`${instancePath}/${targetPath}`);
|
const write = fs.createWriteStream(`${instancePath}/${targetPath}`);
|
||||||
await pipeline(stream, write);
|
await pipeline(stream, write);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.message.unzip(entry.fileName, zip.length, index);
|
this.message.unzip(entry.fileName, zip.length, index);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Unzip process completed", { instancename, totalFiles: zip.length });
|
logger.info("Unzip process completed", { instancename, totalFiles: zip.length });
|
||||||
}
|
}
|
||||||
|
return { _getinfo, _unzip };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查文件是否在解压黑名单中
|
* 检查文件是否在解压黑名单中
|
||||||
@@ -128,8 +129,8 @@ export class Dex {
|
|||||||
* @returns 是否在黑名单中
|
* @returns 是否在黑名单中
|
||||||
*/
|
*/
|
||||||
private _ublack(filename: string): boolean {
|
private _ublack(filename: string): boolean {
|
||||||
|
if (filename === "overrides/") return true;
|
||||||
const blacklist = [
|
const blacklist = [
|
||||||
"overrides/",
|
|
||||||
"overrides/options.txt",
|
"overrides/options.txt",
|
||||||
"shaderpacks",
|
"shaderpacks",
|
||||||
"essential",
|
"essential",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import got, { Got } from "got";
|
|||||||
import fs from "node:fs"
|
import fs from "node:fs"
|
||||||
import fse from "fs-extra"
|
import fse from "fs-extra"
|
||||||
import { execPromise, fastdownload, version_compare } from "../utils/utils.js";
|
import { execPromise, fastdownload, version_compare } from "../utils/utils.js";
|
||||||
import { yauzl_promise } from "../utils/yauzl.promise.js";
|
import { Azip } from "../utils/ziplib.js";
|
||||||
import { execSync } from "node:child_process";
|
import { execSync } from "node:child_process";
|
||||||
|
|
||||||
interface Iforge{
|
interface Iforge{
|
||||||
@@ -51,17 +51,17 @@ export class Forge {
|
|||||||
async library(){
|
async library(){
|
||||||
const _downlist: [string,string][]= []
|
const _downlist: [string,string][]= []
|
||||||
const data = await fs.promises.readFile(`${this.path}/forge-${this.minecraft}-${this.loaderVersion}-installer.jar`)
|
const data = await fs.promises.readFile(`${this.path}/forge-${this.minecraft}-${this.loaderVersion}-installer.jar`)
|
||||||
const zip = await yauzl_promise(data)
|
const zip = Azip(data)
|
||||||
for await(const entry of zip){
|
for await(const entry of zip){
|
||||||
if(entry.fileName === "version.json" || entry.fileName === "install_profile.json"){ //Libraries
|
if(entry.entryName === "version.json" || entry.entryName === "install_profile.json"){ //Libraries
|
||||||
JSON.parse((await entry.ReadEntry).toString()).libraries.forEach(async (e:any)=>{
|
JSON.parse((entry.getData()).toString()).libraries.forEach(async (e:any)=>{
|
||||||
const t = e.downloads.artifact.path
|
const t = e.downloads.artifact.path
|
||||||
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${t}`,`${this.path}/libraries/${t}`])
|
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${t}`,`${this.path}/libraries/${t}`])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if(entry.fileName === "install_profile.json"){ //MOJMAPS
|
if(entry.entryName === "install_profile.json"){ //MOJMAPS
|
||||||
/* 获取MOJMAPS */
|
/* 获取MOJMAPS */
|
||||||
const json = JSON.parse((await entry.ReadEntry).toString()) as Iforge
|
const json = JSON.parse((entry.getData()).toString()) as Iforge
|
||||||
const vjson = await this.got.get(`version/${this.minecraft}/json`).json<Iversion>()
|
const vjson = await this.got.get(`version/${this.minecraft}/json`).json<Iversion>()
|
||||||
console.log(`${new URL(vjson.downloads.server_mappings.url).pathname}`)
|
console.log(`${new URL(vjson.downloads.server_mappings.url).pathname}`)
|
||||||
const mojpath = this.MTP(json.data.MOJMAPS.server)
|
const mojpath = this.MTP(json.data.MOJMAPS.server)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import fs from "node:fs"
|
import fs from "node:fs"
|
||||||
import { fastdownload, version_compare } from "../utils/utils.js";
|
import { fastdownload, version_compare } from "../utils/utils.js";
|
||||||
import { yauzl_promise } from "../utils/yauzl.promise.js";
|
|
||||||
import { pipeline } from "node:stream/promises";
|
import { pipeline } from "node:stream/promises";
|
||||||
import got from "got";
|
import got from "got";
|
||||||
|
import { Azip } from "../utils/ziplib.js";
|
||||||
|
|
||||||
interface ILInfo {
|
interface ILInfo {
|
||||||
libraries: {
|
libraries: {
|
||||||
@@ -49,12 +49,12 @@ export class Minecraft {
|
|||||||
// 1.18.x + MC依赖解压
|
// 1.18.x + MC依赖解压
|
||||||
const mcpath = `${this.path}/libraries/net/minecraft/server/${this.minecraft}/server-${this.minecraft}.jar`
|
const mcpath = `${this.path}/libraries/net/minecraft/server/${this.minecraft}/server-${this.minecraft}.jar`
|
||||||
await fastdownload([`https://bmclapi2.bangbang93.com/version/${this.minecraft}/server`, mcpath])
|
await fastdownload([`https://bmclapi2.bangbang93.com/version/${this.minecraft}/server`, mcpath])
|
||||||
const zip = await yauzl_promise(await fs.promises.readFile(mcpath))
|
const zip = await Azip(await fs.promises.readFile(mcpath))
|
||||||
for await (const entry of zip) {
|
for await (const entry of zip) {
|
||||||
if (entry.fileName.startsWith("META-INF/libraries/") && !entry.fileName.endsWith("/")) {
|
if (entry.entryName.startsWith("META-INF/libraries/") && !entry.entryName.endsWith("/")) {
|
||||||
console.log(entry.fileName)
|
console.log(entry.entryName)
|
||||||
const stream = await entry.openReadStream;
|
const stream = entry.getData();
|
||||||
const write = fs.createWriteStream(`${this.path}/libraries/${entry.fileName.replace("META-INF/libraries/", "")}`);
|
const write = fs.createWriteStream(`${this.path}/libraries/${entry.entryName.replace("META-INF/libraries/", "")}`);
|
||||||
await pipeline(stream, write);
|
await pipeline(stream, write);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import fs from "node:fs"
|
import fs from "node:fs"
|
||||||
import crypto from "node:crypto"
|
import crypto from "node:crypto"
|
||||||
import { yauzl_promise } from "./yauzl.promise.js"
|
//import { yauzl_promise } from "./yauzl.promise.js"
|
||||||
|
import { Azip } from "./ziplib.js"
|
||||||
import got from "got"
|
import got from "got"
|
||||||
import { Utils } from "./utils.js"
|
import { Utils } from "./utils.js"
|
||||||
import config from "./config.js"
|
import config from "./config.js"
|
||||||
@@ -56,6 +57,7 @@ export class DeEarth{
|
|||||||
const result = [...new Set(hash.concat(mixins))]
|
const result = [...new Set(hash.concat(mixins))]
|
||||||
//console.log(result)
|
//console.log(result)
|
||||||
result.forEach(async e=>{
|
result.forEach(async e=>{
|
||||||
|
console.log(e)
|
||||||
await fs.promises.rename(`${e}`,`${this.movepath}/${e}`.replace(this.modspath,""))
|
await fs.promises.rename(`${e}`,`${this.movepath}/${e}`.replace(this.modspath,""))
|
||||||
//await fs.promises.rename(`${this.modspath}/${e}`,`${this.movepath}/${e}`)
|
//await fs.promises.rename(`${this.modspath}/${e}`,`${this.movepath}/${e}`)
|
||||||
})
|
})
|
||||||
@@ -136,9 +138,9 @@ export class DeEarth{
|
|||||||
const data = fs.readFileSync(file)
|
const data = fs.readFileSync(file)
|
||||||
const sha1 = crypto.createHash('sha1').update(data).digest('hex') //Get Hash
|
const sha1 = crypto.createHash('sha1').update(data).digest('hex') //Get Hash
|
||||||
const mxarr:{name:string,data:string}[] = []
|
const mxarr:{name:string,data:string}[] = []
|
||||||
const mixins = (await yauzl_promise(data)).forEach(async e=>{ //Get Mixins Info to check
|
const mixins = (Azip(data)).forEach(async e=>{ //Get Mixins Info to check
|
||||||
if(e.fileName.endsWith(".mixins.json")&&!e.fileName.includes("/")){
|
if(e.entryName.endsWith(".mixins.json")&&!e.entryName.includes("/")){
|
||||||
mxarr.push({name:e.fileName,data:(await e.ReadEntry).toString()})
|
mxarr.push({name:e.entryName,data:(await e.getData()).toString()})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
arr.push({filename:file,hash:sha1,mixins:mxarr})
|
arr.push({filename:file,hash:sha1,mixins:mxarr})
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
import yauzl from "yauzl";
|
|
||||||
import Stream from "node:stream"
|
|
||||||
|
|
||||||
export interface IentryP extends yauzl.Entry {
|
|
||||||
openReadStream: Promise<Stream.Readable>;
|
|
||||||
ReadEntry: Promise<Buffer>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function yauzl_promise(buffer: Buffer): Promise<IentryP[]>{
|
|
||||||
const zip = await (new Promise((resolve,reject)=>{
|
|
||||||
yauzl.fromBuffer(buffer,/*{lazyEntries:true},*/ (err, zipfile) => {
|
|
||||||
if (err){
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve(zipfile);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}) as Promise<yauzl.ZipFile>);
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const entries: IentryP[]= []
|
|
||||||
zip.on("entry", async (entry: yauzl.Entry) => {
|
|
||||||
const _entry = {
|
|
||||||
...entry,
|
|
||||||
getLastModDate: entry.getLastModDate,
|
|
||||||
isEncrypted: entry.isEncrypted,
|
|
||||||
isCompressed: entry.isCompressed,
|
|
||||||
openReadStream: _openReadStream(zip,entry),
|
|
||||||
ReadEntry: _ReadEntry(zip,entry),
|
|
||||||
}
|
|
||||||
entries.push(_entry)
|
|
||||||
if (zip.entryCount === entries.length){
|
|
||||||
zip.close();
|
|
||||||
resolve(entries);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
zip.on("error",err=>{
|
|
||||||
reject(err);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _ReadEntry(zip:yauzl.ZipFile,entry:yauzl.Entry): Promise<Buffer>{
|
|
||||||
return new Promise((resolve,reject)=>{
|
|
||||||
zip.openReadStream(entry,(err,stream)=>{
|
|
||||||
if (err){
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const chunks: Buffer[] = [];
|
|
||||||
stream.on("data",(chunk)=>{
|
|
||||||
chunks.push(chunk);
|
|
||||||
})
|
|
||||||
stream.on("end",()=>{
|
|
||||||
resolve(Buffer.concat(chunks));
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _openReadStream(zip:yauzl.ZipFile,entry:yauzl.Entry): Promise<Stream.Readable>{
|
|
||||||
return new Promise((resolve,reject)=>{
|
|
||||||
zip.openReadStream(entry,(err,stream)=>{
|
|
||||||
if (err){
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve(stream);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
89
backend/src/utils/yauzl.promise.ts1
Normal file
89
backend/src/utils/yauzl.promise.ts1
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import yauzl from "yauzl";
|
||||||
|
import Stream from "node:stream"
|
||||||
|
|
||||||
|
export interface IentryP extends yauzl.Entry {
|
||||||
|
openReadStream: Promise<Stream.Readable>;
|
||||||
|
ReadEntry: Promise<Buffer>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function yauzl_promise(buffer: Buffer): Promise<IentryP[]>{
|
||||||
|
const zip = await (new Promise((resolve,reject)=>{
|
||||||
|
yauzl.fromBuffer(buffer, { lazyEntries: true }, (err, zipfile) => {
|
||||||
|
if (err){
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(zipfile);
|
||||||
|
});
|
||||||
|
}) as Promise<yauzl.ZipFile>);
|
||||||
|
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
const entries: IentryP[] = [];
|
||||||
|
let entryCount = 0;
|
||||||
|
|
||||||
|
zip.on("entry", (entry: yauzl.Entry) => {
|
||||||
|
// 创建新对象并复制所有entry属性,避免yauzl重用对象导致的引用问题
|
||||||
|
const _entry = Object.assign({}, entry) as IentryP;
|
||||||
|
_entry.openReadStream = _openReadStream(zip, entry);
|
||||||
|
_entry.ReadEntry = _ReadEntry(zip, entry);
|
||||||
|
|
||||||
|
entries.push(_entry);
|
||||||
|
entryCount++;
|
||||||
|
//console.log(entryCount, entry.fileName);
|
||||||
|
// 继续读取下一个条目
|
||||||
|
zip.readEntry();
|
||||||
|
});
|
||||||
|
|
||||||
|
zip.on("end", () => {
|
||||||
|
zip.close();
|
||||||
|
console.log(entryCount, "entries read");
|
||||||
|
if(entryCount === zip.entryCount){
|
||||||
|
console.log("All entries read");
|
||||||
|
resolve(entries);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
zip.on("error", (err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 开始读取第一个条目
|
||||||
|
zip.readEntry();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _openReadStream(zip: yauzl.ZipFile, entry: yauzl.Entry): Promise<Stream.Readable>{
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
zip.openReadStream(entry, (err, stream) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(stream);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _ReadEntry(zip: yauzl.ZipFile, entry: yauzl.Entry): Promise<Buffer>{
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
zip.openReadStream(entry, (err, stream) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunks: Buffer[] = [];
|
||||||
|
stream.on("data", (chunk) => {
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on("end", () => {
|
||||||
|
resolve(Buffer.concat(chunks));
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on("error", (err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
84
backend/src/utils/ziplib.ts
Normal file
84
backend/src/utils/ziplib.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import admZip from "adm-zip";
|
||||||
|
import yauzl from "yauzl";
|
||||||
|
import Stream from "node:stream";
|
||||||
|
|
||||||
|
export interface IentryP extends yauzl.Entry {
|
||||||
|
openReadStream: Promise<Stream.Readable>;
|
||||||
|
ReadEntry: Promise<Buffer>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function yauzl_promise(buffer: Buffer): Promise<IentryP[]> {
|
||||||
|
const zip = await (new Promise((resolve, reject) => {
|
||||||
|
yauzl.fromBuffer(
|
||||||
|
buffer,
|
||||||
|
/*{lazyEntries:true},*/ (err, zipfile) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(zipfile);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}) as Promise<yauzl.ZipFile>);
|
||||||
|
|
||||||
|
const _ReadEntry = async (
|
||||||
|
zip: yauzl.ZipFile,
|
||||||
|
entry: yauzl.Entry
|
||||||
|
): Promise<Buffer> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
zip.openReadStream(entry, (err, stream) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const chunks: Buffer[] = [];
|
||||||
|
stream.on("data", (chunk) => {
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
stream.on("end", () => {
|
||||||
|
resolve(Buffer.concat(chunks));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const _openReadStream = async (
|
||||||
|
zip: yauzl.ZipFile,
|
||||||
|
entry: yauzl.Entry
|
||||||
|
): Promise<Stream.Readable> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
zip.openReadStream(entry, (err, stream) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(stream);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const entries: IentryP[] = [];
|
||||||
|
zip.on("entry", async (entry: yauzl.Entry) => {
|
||||||
|
const entryP = entry as IentryP;
|
||||||
|
//console.log(entry.fileName);
|
||||||
|
entryP.openReadStream = _openReadStream(zip, entry);
|
||||||
|
entryP.ReadEntry = _ReadEntry(zip, entry);
|
||||||
|
entries.push(entryP);
|
||||||
|
if (zip.entryCount === entries.length) {
|
||||||
|
zip.close();
|
||||||
|
resolve(entries);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
zip.on("error", (err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Azip(buffer: Buffer) {
|
||||||
|
const zip = new admZip(buffer);
|
||||||
|
const entries = zip.getEntries();
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user