First pass at Claritas implementation.
The resolution logic was reworked so that Claritas only needs to be invoked once per supported type, ie only once for ForgeMod and LiteMod resolutions per server. The resolver now uses identifies module candidates and collects them. Claritas is invoked and the resulting metadata is stored. The module resolution then proceeds with all of this data available. Toggleable module logic was also reworked to first accumulate all candidates and then process. This required the resolution function to optionally take a preprocess and postprocess callback to perform the necessary cleanup and transformations. The minor rework was necessary because spawning child process is expensive, and we should only do it as often as we must to keep the application performant. Claritas resolution also supports exceptions defined by the structure class. This is to facilitate handling of special cases (ex. Optifine).
This commit is contained in:
BIN
libraries/java/Claritas.jar
Normal file
BIN
libraries/java/Claritas.jar
Normal file
Binary file not shown.
115
package-lock.json
generated
115
package-lock.json
generated
@@ -67,15 +67,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/runtime-corejs3": {
|
|
||||||
"version": "7.10.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz",
|
|
||||||
"integrity": "sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw==",
|
|
||||||
"requires": {
|
|
||||||
"core-js-pure": "^3.0.0",
|
|
||||||
"regenerator-runtime": "^0.13.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@dabh/diagnostics": {
|
"@dabh/diagnostics": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz",
|
||||||
@@ -113,9 +104,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "12.12.47",
|
"version": "12.12.50",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.47.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.50.tgz",
|
||||||
"integrity": "sha512-yzBInQFhdY8kaZmqoL2+3U5dSTMrKaYcb561VU+lDzAYvqt+2lojvBEy+hmpSNuXnPTx7m9+04CzWYOUqWME2A==",
|
"integrity": "sha512-5ImO01Fb8YsEOYpV+aeyGYztcYcjGsBvN4D7G5r1ef2cuQOpymjWNQi5V0rKHE6PC2ru3HkoUr/Br2/8GUA84w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/triple-beam": {
|
"@types/triple-beam": {
|
||||||
@@ -140,12 +131,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@typescript-eslint/eslint-plugin": {
|
"@typescript-eslint/eslint-plugin": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.1.tgz",
|
||||||
"integrity": "sha512-m4erZ8AkSjoIUOf8s4k2V1xdL2c1Vy0D3dN6/jC9d7+nEqjY3gxXCkgi3gW/GAxPaA4hV8biaCoTVdQmfAeTCQ==",
|
"integrity": "sha512-06lfjo76naNeOMDl+mWG9Fh/a0UHKLGhin+mGaIw72FUMbMGBkdi/FEJmgEDzh4eE73KIYzHWvOCYJ0ak7nrJQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/experimental-utils": "3.5.0",
|
"@typescript-eslint/experimental-utils": "3.6.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"regexpp": "^3.0.0",
|
"regexpp": "^3.0.0",
|
||||||
@@ -171,45 +162,45 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/experimental-utils": {
|
"@typescript-eslint/experimental-utils": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.1.tgz",
|
||||||
"integrity": "sha512-zGNOrVi5Wz0jcjUnFZ6QUD0MCox5hBuVwemGCew2qJzUX5xPoyR+0EzS5qD5qQXL/vnQ8Eu+nv03tpeFRwLrDg==",
|
"integrity": "sha512-oS+hihzQE5M84ewXrTlVx7eTgc52eu+sVmG7ayLfOhyZmJ8Unvf3osyFQNADHP26yoThFfbxcibbO0d2FjnYhg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/json-schema": "^7.0.3",
|
"@types/json-schema": "^7.0.3",
|
||||||
"@typescript-eslint/types": "3.5.0",
|
"@typescript-eslint/types": "3.6.1",
|
||||||
"@typescript-eslint/typescript-estree": "3.5.0",
|
"@typescript-eslint/typescript-estree": "3.6.1",
|
||||||
"eslint-scope": "^5.0.0",
|
"eslint-scope": "^5.0.0",
|
||||||
"eslint-utils": "^2.0.0"
|
"eslint-utils": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.6.1.tgz",
|
||||||
"integrity": "sha512-sU07VbYB70WZHtgOjH/qfAp1+OwaWgrvD1Km1VXqRpcVxt971PMTU7gJtlrCje0M+Sdz7xKAbtiyIu+Y6QdnVA==",
|
"integrity": "sha512-SLihQU8RMe77YJ/jGTqOt0lMq7k3hlPVfp7v/cxMnXA9T0bQYoMDfTsNgHXpwSJM1Iq2aAJ8WqekxUwGv5F67Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/eslint-visitor-keys": "^1.0.0",
|
"@types/eslint-visitor-keys": "^1.0.0",
|
||||||
"@typescript-eslint/experimental-utils": "3.5.0",
|
"@typescript-eslint/experimental-utils": "3.6.1",
|
||||||
"@typescript-eslint/types": "3.5.0",
|
"@typescript-eslint/types": "3.6.1",
|
||||||
"@typescript-eslint/typescript-estree": "3.5.0",
|
"@typescript-eslint/typescript-estree": "3.6.1",
|
||||||
"eslint-visitor-keys": "^1.1.0"
|
"eslint-visitor-keys": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/types": {
|
"@typescript-eslint/types": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.6.1.tgz",
|
||||||
"integrity": "sha512-Dreqb5idi66VVs1QkbAwVeDmdJG+sDtofJtKwKCZXIaBsINuCN7Jv5eDIHrS0hFMMiOvPH9UuOs4splW0iZe4Q==",
|
"integrity": "sha512-NPxd5yXG63gx57WDTW1rp0cF3XlNuuFFB5G+Kc48zZ+51ZnQn9yjDEsjTPQ+aWM+V+Z0I4kuTFKjKvgcT1F7xQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@typescript-eslint/typescript-estree": {
|
"@typescript-eslint/typescript-estree": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.6.1.tgz",
|
||||||
"integrity": "sha512-Na71ezI6QP5WVR4EHxwcBJgYiD+Sre9BZO5iJK2QhrmRPo/42+b0no/HZIrdD1sjghzlYv7t+7Jis05M1uMxQg==",
|
"integrity": "sha512-G4XRe/ZbCZkL1fy09DPN3U0mR6SayIv1zSeBNquRFRk7CnVLgkC2ZPj8llEMJg5Y8dJ3T76SvTGtceytniaztQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "3.5.0",
|
"@typescript-eslint/types": "3.6.1",
|
||||||
"@typescript-eslint/visitor-keys": "3.5.0",
|
"@typescript-eslint/visitor-keys": "3.6.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"is-glob": "^4.0.1",
|
"is-glob": "^4.0.1",
|
||||||
@@ -236,9 +227,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/visitor-keys": {
|
"@typescript-eslint/visitor-keys": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.1.tgz",
|
||||||
"integrity": "sha512-7cTp9rcX2sz9Z+zua9MCOX4cqp5rYyFD5o8LlbSpXrMTXoRdngTtotRZEkm8+FNMHPWYFhitFK+qt/brK8BVJQ==",
|
"integrity": "sha512-qC8Olwz5ZyMTZrh4Wl3K4U6tfms0R/mzU4/5W3XeUZptVraGVmbptJbn6h2Ey6Rb3hOs3zWoAUebZk8t47KGiQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"eslint-visitor-keys": "^1.1.0"
|
"eslint-visitor-keys": "^1.1.0"
|
||||||
@@ -451,11 +442,6 @@
|
|||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"core-js-pure": {
|
|
||||||
"version": "3.6.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz",
|
|
||||||
"integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA=="
|
|
||||||
},
|
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
@@ -481,12 +467,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"decamelize": {
|
"decamelize": {
|
||||||
"version": "3.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||||
"integrity": "sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==",
|
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
||||||
"requires": {
|
|
||||||
"xregexp": "^4.2.4"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"deep-is": {
|
"deep-is": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
@@ -976,9 +959,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.15",
|
"version": "4.17.19",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"logform": {
|
"logform": {
|
||||||
@@ -1156,11 +1139,6 @@
|
|||||||
"util-deprecate": "^1.0.1"
|
"util-deprecate": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"regenerator-runtime": {
|
|
||||||
"version": "0.13.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
|
|
||||||
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
|
|
||||||
},
|
|
||||||
"regexpp": {
|
"regexpp": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
|
||||||
@@ -1559,26 +1537,18 @@
|
|||||||
"mkdirp": "^0.5.1"
|
"mkdirp": "^0.5.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"xregexp": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime-corejs3": "^7.8.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"y18n": {
|
"y18n": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
|
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
|
||||||
},
|
},
|
||||||
"yargs": {
|
"yargs": {
|
||||||
"version": "15.4.0",
|
"version": "15.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||||
"integrity": "sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw==",
|
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"cliui": "^6.0.0",
|
"cliui": "^6.0.0",
|
||||||
"decamelize": "^3.2.0",
|
"decamelize": "^1.2.0",
|
||||||
"find-up": "^4.1.0",
|
"find-up": "^4.1.0",
|
||||||
"get-caller-file": "^2.0.1",
|
"get-caller-file": "^2.0.1",
|
||||||
"require-directory": "^2.1.1",
|
"require-directory": "^2.1.1",
|
||||||
@@ -1597,13 +1567,6 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"camelcase": "^5.0.0",
|
"camelcase": "^5.0.0",
|
||||||
"decamelize": "^1.2.0"
|
"decamelize": "^1.2.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"decamelize": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
|
||||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,11 @@
|
|||||||
"homepage": "https://github.com/dscalzi/Nebula#readme",
|
"homepage": "https://github.com/dscalzi/Nebula#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/fs-extra": "^9.0.1",
|
"@types/fs-extra": "^9.0.1",
|
||||||
"@types/node": "^12.12.47",
|
"@types/node": "^12.12.50",
|
||||||
"@types/triple-beam": "^1.3.1",
|
"@types/triple-beam": "^1.3.1",
|
||||||
"@types/yargs": "^15.0.5",
|
"@types/yargs": "^15.0.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^3.5.0",
|
"@typescript-eslint/eslint-plugin": "^3.6.1",
|
||||||
"@typescript-eslint/parser": "^3.5.0",
|
"@typescript-eslint/parser": "^3.6.1",
|
||||||
"eslint": "^7.4.0",
|
"eslint": "^7.4.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"typescript": "^3.9.6"
|
"typescript": "^3.9.6"
|
||||||
@@ -46,6 +46,6 @@
|
|||||||
"toml": "^3.0.0",
|
"toml": "^3.0.0",
|
||||||
"triple-beam": "^1.3.0",
|
"triple-beam": "^1.3.0",
|
||||||
"winston": "^3.3.3",
|
"winston": "^3.3.3",
|
||||||
"yargs": "^15.4.0"
|
"yargs": "^15.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
src/model/claritas/ClaritasLibraryType.ts
Normal file
6
src/model/claritas/ClaritasLibraryType.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export enum LibraryType {
|
||||||
|
|
||||||
|
FORGE = 'FORGE',
|
||||||
|
LITELOADER = 'LITELOADER'
|
||||||
|
|
||||||
|
}
|
||||||
26
src/model/claritas/ClaritasResult.ts
Normal file
26
src/model/claritas/ClaritasResult.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
export interface ClaritasModuleMetadata {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Present on ForgeMods
|
||||||
|
*/
|
||||||
|
id?: string
|
||||||
|
/**
|
||||||
|
* Always Present
|
||||||
|
*/
|
||||||
|
group: string
|
||||||
|
/**
|
||||||
|
* Possibly present on ForgeMods 1.12-
|
||||||
|
*/
|
||||||
|
version?: string
|
||||||
|
/**
|
||||||
|
* Possibly present on ForgeMods 1.12-
|
||||||
|
*/
|
||||||
|
name?: string
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClaritasResult {
|
||||||
|
|
||||||
|
[jarPath: string]: ClaritasModuleMetadata | undefined
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import { mkdirs } from 'fs-extra'
|
import { mkdirs } from 'fs-extra'
|
||||||
import { join, resolve } from 'path'
|
import { join, resolve } from 'path'
|
||||||
import { FileStructure } from './FileStructure'
|
import { FileStructure } from './FileStructure'
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
import { LoggerUtil } from '../../util/LoggerUtil'
|
||||||
|
|
||||||
export abstract class BaseFileStructure implements FileStructure {
|
export abstract class BaseFileStructure implements FileStructure {
|
||||||
|
|
||||||
|
protected logger: Logger
|
||||||
protected containerDirectory: string
|
protected containerDirectory: string
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -13,10 +16,13 @@ export abstract class BaseFileStructure implements FileStructure {
|
|||||||
) {
|
) {
|
||||||
this.relativeRoot = join(relativeRoot, structRoot)
|
this.relativeRoot = join(relativeRoot, structRoot)
|
||||||
this.containerDirectory = resolve(absoluteRoot, structRoot)
|
this.containerDirectory = resolve(absoluteRoot, structRoot)
|
||||||
|
this.logger = LoggerUtil.getLogger(this.getLoggerName())
|
||||||
}
|
}
|
||||||
|
|
||||||
public async init(): Promise<void> {
|
public async init(): Promise<void> {
|
||||||
mkdirs(this.containerDirectory)
|
mkdirs(this.containerDirectory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract getLoggerName(): string
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,21 @@ import { resolve as resolveURL } from 'url'
|
|||||||
import { ModuleStructure } from './module.struct'
|
import { ModuleStructure } from './module.struct'
|
||||||
import { readdir, stat } from 'fs-extra'
|
import { readdir, stat } from 'fs-extra'
|
||||||
import { join, resolve, sep } from 'path'
|
import { join, resolve, sep } from 'path'
|
||||||
|
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
|
||||||
|
|
||||||
export class MiscFileStructure extends ModuleStructure {
|
export class MiscFileStructure extends ModuleStructure {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
absoluteRoot: string,
|
absoluteRoot: string,
|
||||||
relativeRoot: string,
|
relativeRoot: string,
|
||||||
baseUrl: string
|
baseUrl: string,
|
||||||
|
minecraftVersion: MinecraftVersion
|
||||||
) {
|
) {
|
||||||
super(absoluteRoot, relativeRoot, 'files', baseUrl, Type.File)
|
super(absoluteRoot, relativeRoot, 'files', baseUrl, minecraftVersion, Type.File)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'MiscFileStructure'
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getSpecModel(): Promise<Module[]> {
|
public async getSpecModel(): Promise<Module[]> {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import { resolve } from 'url'
|
|||||||
import { VersionSegmented } from '../../../../util/VersionSegmented'
|
import { VersionSegmented } from '../../../../util/VersionSegmented'
|
||||||
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
|
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
|
||||||
import { ToggleableModuleStructure } from './toggleablemodule.struct'
|
import { ToggleableModuleStructure } from './toggleablemodule.struct'
|
||||||
|
import { LibraryType } from '../../../claritas/ClaritasLibraryType'
|
||||||
|
import { ClaritasException } from './module.struct'
|
||||||
|
|
||||||
export abstract class BaseForgeModStructure extends ToggleableModuleStructure implements VersionSegmented {
|
export abstract class BaseForgeModStructure extends ToggleableModuleStructure implements VersionSegmented {
|
||||||
|
|
||||||
@@ -13,9 +15,10 @@ export abstract class BaseForgeModStructure extends ToggleableModuleStructure im
|
|||||||
constructor(
|
constructor(
|
||||||
absoluteRoot: string,
|
absoluteRoot: string,
|
||||||
relativeRoot: string,
|
relativeRoot: string,
|
||||||
baseUrl: string
|
baseUrl: string,
|
||||||
|
minecraftVersion: MinecraftVersion
|
||||||
) {
|
) {
|
||||||
super(absoluteRoot, relativeRoot, 'forgemods', baseUrl, Type.ForgeMod)
|
super(absoluteRoot, relativeRoot, 'forgemods', baseUrl, minecraftVersion, Type.ForgeMod)
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract isForVersion(version: MinecraftVersion, libraryVersion: string): boolean
|
public abstract isForVersion(version: MinecraftVersion, libraryVersion: string): boolean
|
||||||
@@ -29,4 +32,21 @@ export abstract class BaseForgeModStructure extends ToggleableModuleStructure im
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getClaritasExceptions(): ClaritasException[] {
|
||||||
|
return [{
|
||||||
|
exceptionName: 'optifine',
|
||||||
|
proxyMetadata: {
|
||||||
|
group: 'net.optifine'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getClaritasType(): LibraryType {
|
||||||
|
return LibraryType.FORGE
|
||||||
|
}
|
||||||
|
|
||||||
|
protected discernResult(claritasValue: string | undefined, crudeInference: string): string {
|
||||||
|
return (claritasValue == null || claritasValue == '') ? crudeInference : claritasValue
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,9 @@ import { VersionUtil } from '../../../../../util/versionutil'
|
|||||||
import { ModsToml } from '../../../../forge/modstoml'
|
import { ModsToml } from '../../../../forge/modstoml'
|
||||||
import { BaseForgeModStructure } from '../forgemod.struct'
|
import { BaseForgeModStructure } from '../forgemod.struct'
|
||||||
import { MinecraftVersion } from '../../../../../util/MinecraftVersion'
|
import { MinecraftVersion } from '../../../../../util/MinecraftVersion'
|
||||||
import { LoggerUtil } from '../../../../../util/LoggerUtil'
|
|
||||||
|
|
||||||
export class ForgeModStructure113 extends BaseForgeModStructure {
|
export class ForgeModStructure113 extends BaseForgeModStructure {
|
||||||
|
|
||||||
private static readonly logger = LoggerUtil.getLogger('ForgeModStructure (1.13)')
|
|
||||||
|
|
||||||
public static readonly IMPLEMENTATION_VERSION_REGEX = /^Implementation-Version: (.+)[\r\n]/
|
public static readonly IMPLEMENTATION_VERSION_REGEX = /^Implementation-Version: (.+)[\r\n]/
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
@@ -23,18 +20,23 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
|||||||
constructor(
|
constructor(
|
||||||
absoluteRoot: string,
|
absoluteRoot: string,
|
||||||
relativeRoot: string,
|
relativeRoot: string,
|
||||||
baseUrl: string
|
baseUrl: string,
|
||||||
|
minecraftVersion: MinecraftVersion
|
||||||
) {
|
) {
|
||||||
super(absoluteRoot, relativeRoot, baseUrl)
|
super(absoluteRoot, relativeRoot, baseUrl, minecraftVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||||
return ForgeModStructure113.isForVersion(version, libraryVersion)
|
return ForgeModStructure113.isForVersion(version, libraryVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'ForgeModStructure (1.13)'
|
||||||
|
}
|
||||||
|
|
||||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||||
const fmData = await this.getForgeModMetadata(name, path)
|
const fmData = await this.getForgeModMetadata(name, path)
|
||||||
return this.generateMavenIdentifier(fmData.mods[0].modId, fmData.mods[0].version)
|
return this.generateMavenIdentifier(this.getClaritasGroup(path), fmData.mods[0].modId, fmData.mods[0].version)
|
||||||
}
|
}
|
||||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||||
return capitalize((await this.getForgeModMetadata(name, path)).mods[0].displayName)
|
return capitalize((await this.getForgeModMetadata(name, path)).mods[0].displayName)
|
||||||
@@ -52,7 +54,7 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
|||||||
zip.on('error', err => reject(err))
|
zip.on('error', err => reject(err))
|
||||||
zip.on('ready', () => {
|
zip.on('ready', () => {
|
||||||
try {
|
try {
|
||||||
const res = this.processZip(zip, name)
|
const res = this.processZip(zip, name, path)
|
||||||
zip.close()
|
zip.close()
|
||||||
resolve(res)
|
resolve(res)
|
||||||
return
|
return
|
||||||
@@ -71,7 +73,7 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private processZip(zip: StreamZip, name: string): ModsToml {
|
private processZip(zip: StreamZip, name: string, path: string): ModsToml {
|
||||||
|
|
||||||
// Optifine is a tweak that can be loaded as a forge mod. It does not
|
// Optifine is a tweak that can be loaded as a forge mod. It does not
|
||||||
// appear to contain a mcmod.info class. This a special case we will
|
// appear to contain a mcmod.info class. This a special case we will
|
||||||
@@ -116,12 +118,21 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
|||||||
const parsed = toml.parse(raw.toString()) as ModsToml
|
const parsed = toml.parse(raw.toString()) as ModsToml
|
||||||
this.forgeModMetadata[name] = parsed
|
this.forgeModMetadata[name] = parsed
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ForgeModStructure113.logger.error(`ForgeMod ${name} contains an invalid mods.toml file.`)
|
this.logger.error(`ForgeMod ${name} contains an invalid mods.toml file.`)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ForgeModStructure113.logger.error(`ForgeMod ${name} does not contain mods.toml file.`)
|
this.logger.error(`ForgeMod ${name} does not contain mods.toml file.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cRes = this.claritasResult?.[path]
|
||||||
|
|
||||||
|
if(cRes == null) {
|
||||||
|
this.logger.error(`Claritas failed to yield metadata for ForgeMod ${name}!`)
|
||||||
|
this.logger.error('Is this mod malformated or does Claritas need an update?')
|
||||||
|
}
|
||||||
|
|
||||||
|
const claritasId = cRes?.id
|
||||||
|
|
||||||
const crudeInference = this.attemptCrudeInference(name)
|
const crudeInference = this.attemptCrudeInference(name)
|
||||||
|
|
||||||
if(this.forgeModMetadata[name] != null) {
|
if(this.forgeModMetadata[name] != null) {
|
||||||
@@ -130,7 +141,7 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
|||||||
for(const entry of x.mods) {
|
for(const entry of x.mods) {
|
||||||
|
|
||||||
if(entry.modId === this.EXAMPLE_MOD_ID) {
|
if(entry.modId === this.EXAMPLE_MOD_ID) {
|
||||||
entry.modId = crudeInference.name.toLowerCase()
|
entry.modId = this.discernResult(claritasId, crudeInference.name.toLowerCase())
|
||||||
entry.displayName = crudeInference.name
|
entry.displayName = crudeInference.name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,16 +150,16 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
|||||||
try {
|
try {
|
||||||
const manifest = zip.entryDataSync('META-INF/MANIFEST.MF')
|
const manifest = zip.entryDataSync('META-INF/MANIFEST.MF')
|
||||||
const keys = manifest.toString().split('\n')
|
const keys = manifest.toString().split('\n')
|
||||||
ForgeModStructure113.logger.debug(keys)
|
this.logger.debug(keys)
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
const match = ForgeModStructure113.IMPLEMENTATION_VERSION_REGEX.exec(key)
|
const match = ForgeModStructure113.IMPLEMENTATION_VERSION_REGEX.exec(key)
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
version = match[1]
|
version = match[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ForgeModStructure113.logger.debug(`ForgeMod ${name} contains a version wildcard, inferring ${version}`)
|
this.logger.debug(`ForgeMod ${name} contains a version wildcard, inferring ${version}`)
|
||||||
} catch {
|
} catch {
|
||||||
ForgeModStructure113.logger.debug(`ForgeMod ${name} contains a version wildcard yet no MANIFEST.MF.. Defaulting to ${version}`)
|
this.logger.debug(`ForgeMod ${name} contains a version wildcard yet no MANIFEST.MF.. Defaulting to ${version}`)
|
||||||
}
|
}
|
||||||
entry.version = version
|
entry.version = version
|
||||||
}
|
}
|
||||||
@@ -159,7 +170,7 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
|||||||
modLoader: 'javafml',
|
modLoader: 'javafml',
|
||||||
loaderVersion: '',
|
loaderVersion: '',
|
||||||
mods: [{
|
mods: [{
|
||||||
modId: crudeInference.name.toLowerCase(),
|
modId: this.discernResult(claritasId, crudeInference.name.toLowerCase()),
|
||||||
version: crudeInference.version,
|
version: crudeInference.version,
|
||||||
displayName: crudeInference.name,
|
displayName: crudeInference.name,
|
||||||
description: ''
|
description: ''
|
||||||
|
|||||||
@@ -5,12 +5,9 @@ import { McModInfo } from '../../../../forge/mcmodinfo'
|
|||||||
import { McModInfoList } from '../../../../forge/mcmodinfolist'
|
import { McModInfoList } from '../../../../forge/mcmodinfolist'
|
||||||
import { BaseForgeModStructure } from '../forgemod.struct'
|
import { BaseForgeModStructure } from '../forgemod.struct'
|
||||||
import { MinecraftVersion } from '../../../../../util/MinecraftVersion'
|
import { MinecraftVersion } from '../../../../../util/MinecraftVersion'
|
||||||
import { LoggerUtil } from '../../../../../util/LoggerUtil'
|
|
||||||
|
|
||||||
export class ForgeModStructure17 extends BaseForgeModStructure {
|
export class ForgeModStructure17 extends BaseForgeModStructure {
|
||||||
|
|
||||||
private static readonly logger = LoggerUtil.getLogger('ForgeModStructure (1.7)')
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
public static isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
public static isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||||
return VersionUtil.isVersionAcceptable(version, [7, 8, 9, 10, 11, 12])
|
return VersionUtil.isVersionAcceptable(version, [7, 8, 9, 10, 11, 12])
|
||||||
@@ -21,18 +18,23 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
|||||||
constructor(
|
constructor(
|
||||||
absoluteRoot: string,
|
absoluteRoot: string,
|
||||||
relativeRoot: string,
|
relativeRoot: string,
|
||||||
baseUrl: string
|
baseUrl: string,
|
||||||
|
minecraftVersion: MinecraftVersion
|
||||||
) {
|
) {
|
||||||
super(absoluteRoot, relativeRoot, baseUrl)
|
super(absoluteRoot, relativeRoot, baseUrl, minecraftVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||||
return ForgeModStructure17.isForVersion(version, libraryVersion)
|
return ForgeModStructure17.isForVersion(version, libraryVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'ForgeModStructure (1.7)'
|
||||||
|
}
|
||||||
|
|
||||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||||
const fmData = await this.getForgeModMetadata(name, path)
|
const fmData = await this.getForgeModMetadata(name, path)
|
||||||
return this.generateMavenIdentifier(fmData.modid, fmData.version)
|
return this.generateMavenIdentifier(this.getClaritasGroup(path), fmData.modid, fmData.version)
|
||||||
}
|
}
|
||||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||||
return capitalize((await this.getForgeModMetadata(name, path)).name)
|
return capitalize((await this.getForgeModMetadata(name, path)).name)
|
||||||
@@ -50,7 +52,7 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
|||||||
zip.on('error', err => reject(err))
|
zip.on('error', err => reject(err))
|
||||||
zip.on('ready', () => {
|
zip.on('ready', () => {
|
||||||
try {
|
try {
|
||||||
const res = this.processZip(zip, name)
|
const res = this.processZip(zip, name, path)
|
||||||
zip.close()
|
zip.close()
|
||||||
resolve(res)
|
resolve(res)
|
||||||
return
|
return
|
||||||
@@ -69,7 +71,7 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private processZip(zip: StreamZip, name: string): McModInfo {
|
private processZip(zip: StreamZip, name: string, path: string): McModInfo {
|
||||||
// Optifine is a tweak that can be loaded as a forge mod. It does not
|
// Optifine is a tweak that can be loaded as a forge mod. It does not
|
||||||
// appear to contain a mcmod.info class. This a special case we will
|
// appear to contain a mcmod.info class. This a special case we will
|
||||||
// account for.
|
// account for.
|
||||||
@@ -113,38 +115,50 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ForgeModStructure17.logger.error(`ForgeMod ${name} contains an invalid mcmod.info file.`)
|
this.logger.error(`ForgeMod ${name} contains an invalid mcmod.info file.`)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ForgeModStructure17.logger.error(`ForgeMod ${name} does not contain mcmod.info file.`)
|
this.logger.error(`ForgeMod ${name} does not contain mcmod.info file.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cRes = this.claritasResult[path]
|
||||||
|
|
||||||
|
if(cRes == null) {
|
||||||
|
this.logger.error(`Claritas failed to yield metadata for ForgeMod ${name}!`)
|
||||||
|
this.logger.error('Is this mod malformated or does Claritas need an update?')
|
||||||
|
}
|
||||||
|
|
||||||
|
const claritasId = cRes?.id
|
||||||
|
const claritasVersion = cRes?.version
|
||||||
|
const claritasName = cRes?.name
|
||||||
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
const crudeInference = this.attemptCrudeInference(name)
|
const crudeInference = this.attemptCrudeInference(name)
|
||||||
if(this.forgeModMetadata[name] != null) {
|
if(this.forgeModMetadata[name] != null) {
|
||||||
|
|
||||||
const x = this.forgeModMetadata[name]!
|
const x = this.forgeModMetadata[name]!
|
||||||
if(x.modid == null || x.modid === '' || x.modid === this.EXAMPLE_MOD_ID) {
|
if(x.modid == null || x.modid === '' || x.modid === this.EXAMPLE_MOD_ID) {
|
||||||
x.modid = crudeInference.name.toLowerCase()
|
x.modid = this.discernResult(claritasId, crudeInference.name.toLowerCase())
|
||||||
x.name = crudeInference.name
|
x.name = this.discernResult(claritasName, crudeInference.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ex. @VERSION@, ${version}
|
// Ex. @VERSION@, ${version}
|
||||||
if(this.forgeModMetadata[name]!.version != null) {
|
if(this.forgeModMetadata[name]!.version != null) {
|
||||||
const isVersionWildcard = this.forgeModMetadata[name]!.version.indexOf('@') > -1 || this.forgeModMetadata[name]!.version.indexOf('$') > -1
|
const isVersionWildcard = this.forgeModMetadata[name]!.version.indexOf('@') > -1 || this.forgeModMetadata[name]!.version.indexOf('$') > -1
|
||||||
if(isVersionWildcard) {
|
if(isVersionWildcard) {
|
||||||
x.version = crudeInference.version
|
x.version = this.discernResult(claritasVersion, crudeInference.version)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
x.version = crudeInference.version
|
x.version = this.discernResult(claritasVersion, crudeInference.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.forgeModMetadata[name] = ({
|
this.forgeModMetadata[name] = ({
|
||||||
modid: crudeInference.name.toLowerCase(),
|
modid: this.discernResult(claritasId, crudeInference.name.toLowerCase()),
|
||||||
name: crudeInference.name,
|
name: this.discernResult(claritasName, crudeInference.name),
|
||||||
version: crudeInference.version
|
version: this.discernResult(claritasVersion, crudeInference.version)
|
||||||
}) as McModInfo
|
}) as McModInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,23 +3,29 @@ import { Type, TypeMetadata } from 'helios-distribution-types'
|
|||||||
import { Stats } from 'fs-extra'
|
import { Stats } from 'fs-extra'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { resolve } from 'url'
|
import { resolve } from 'url'
|
||||||
|
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
|
||||||
|
|
||||||
export class LibraryStructure extends ModuleStructure {
|
export class LibraryStructure extends ModuleStructure {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
absoluteRoot: string,
|
absoluteRoot: string,
|
||||||
relativeRoot: string,
|
relativeRoot: string,
|
||||||
baseUrl: string
|
baseUrl: string,
|
||||||
|
minecraftVersion: MinecraftVersion
|
||||||
) {
|
) {
|
||||||
super(absoluteRoot, relativeRoot, 'libraries', baseUrl, Type.Library, (name: string) => {
|
super(absoluteRoot, relativeRoot, 'libraries', baseUrl, minecraftVersion, Type.Library, (name: string) => {
|
||||||
return name.toLowerCase().endsWith(TypeMetadata[this.type].defaultExtension!)
|
return name.toLowerCase().endsWith(TypeMetadata[this.type].defaultExtension!)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'LibraryStructure'
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||||
const inference = this.attemptCrudeInference(name)
|
const inference = this.attemptCrudeInference(name)
|
||||||
return this.generateMavenIdentifier(inference.name, inference.version)
|
return this.generateMavenIdentifier(this.getDefaultGroup(), inference.name, inference.version)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { resolve } from 'url'
|
|||||||
import { capitalize } from '../../../../util/stringutils'
|
import { capitalize } from '../../../../util/stringutils'
|
||||||
import { LiteMod } from '../../../liteloader/litemod'
|
import { LiteMod } from '../../../liteloader/litemod'
|
||||||
import { ToggleableModuleStructure } from './toggleablemodule.struct'
|
import { ToggleableModuleStructure } from './toggleablemodule.struct'
|
||||||
|
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
|
||||||
|
import { LibraryType } from '../../../claritas/ClaritasLibraryType'
|
||||||
|
|
||||||
export class LiteModStructure extends ToggleableModuleStructure {
|
export class LiteModStructure extends ToggleableModuleStructure {
|
||||||
|
|
||||||
@@ -14,14 +16,19 @@ export class LiteModStructure extends ToggleableModuleStructure {
|
|||||||
constructor(
|
constructor(
|
||||||
absoluteRoot: string,
|
absoluteRoot: string,
|
||||||
relativeRoot: string,
|
relativeRoot: string,
|
||||||
baseUrl: string
|
baseUrl: string,
|
||||||
|
minecraftVersion: MinecraftVersion
|
||||||
) {
|
) {
|
||||||
super(absoluteRoot, relativeRoot, 'litemods', baseUrl, Type.LiteMod)
|
super(absoluteRoot, relativeRoot, 'litemods', baseUrl, minecraftVersion, Type.LiteMod)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'LiteModStructure'
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||||
const liteModData = await this.getLiteModMetadata(name, path)
|
const liteModData = await this.getLiteModMetadata(name, path)
|
||||||
return this.generateMavenIdentifier(liteModData.name, `${liteModData.version}-${liteModData.mcversion}`)
|
return this.generateMavenIdentifier(this.getClaritasGroup(path), liteModData.name, `${liteModData.version}-${liteModData.mcversion}`)
|
||||||
}
|
}
|
||||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||||
return capitalize((await this.getLiteModMetadata(name, path)).name)
|
return capitalize((await this.getLiteModMetadata(name, path)).name)
|
||||||
@@ -35,6 +42,10 @@ export class LiteModStructure extends ToggleableModuleStructure {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getClaritasType(): LibraryType {
|
||||||
|
return LibraryType.LITELOADER
|
||||||
|
}
|
||||||
|
|
||||||
private getLiteModMetadata(name: string, path: string): Promise<LiteMod> {
|
private getLiteModMetadata(name: string, path: string): Promise<LiteMod> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!Object.prototype.hasOwnProperty.call(this.liteModMetadata, name)) {
|
if (!Object.prototype.hasOwnProperty.call(this.liteModMetadata, name)) {
|
||||||
|
|||||||
@@ -3,17 +3,35 @@ import { lstat, pathExists, readdir, readFile, Stats } from 'fs-extra'
|
|||||||
import { Module, Type, TypeMetadata } from 'helios-distribution-types'
|
import { Module, Type, TypeMetadata } from 'helios-distribution-types'
|
||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
import { BaseModelStructure } from '../basemodel.struct'
|
import { BaseModelStructure } from '../basemodel.struct'
|
||||||
|
import { LibraryType } from '../../../claritas/ClaritasLibraryType'
|
||||||
|
import { ClaritasResult, ClaritasModuleMetadata } from '../../../claritas/ClaritasResult'
|
||||||
|
import { ClaritasWrapper } from '../../../../util/java/ClaritasWrapper'
|
||||||
|
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
|
||||||
|
|
||||||
|
export interface ModuleCandidate {
|
||||||
|
file: string
|
||||||
|
filePath: string
|
||||||
|
stats: Stats
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClaritasException {
|
||||||
|
exceptionName: string
|
||||||
|
proxyMetadata: ClaritasModuleMetadata
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class ModuleStructure extends BaseModelStructure<Module> {
|
export abstract class ModuleStructure extends BaseModelStructure<Module> {
|
||||||
|
|
||||||
private readonly crudeRegex = /(.+?)-(.+).[jJ][aA][rR]/
|
private readonly crudeRegex = /(.+?)-(.+).[jJ][aA][rR]/
|
||||||
protected readonly DEFAULT_VERSION = '0.0.0'
|
protected readonly DEFAULT_VERSION = '0.0.0'
|
||||||
|
|
||||||
|
protected claritasResult!: ClaritasResult
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
absoluteRoot: string,
|
absoluteRoot: string,
|
||||||
relativeRoot: string,
|
relativeRoot: string,
|
||||||
structRoot: string,
|
structRoot: string,
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
|
protected minecraftVersion: MinecraftVersion,
|
||||||
protected type: Type,
|
protected type: Type,
|
||||||
protected filter?: ((name: string, path: string, stats: Stats) => boolean)
|
protected filter?: ((name: string, path: string, stats: Stats) => boolean)
|
||||||
) {
|
) {
|
||||||
@@ -22,14 +40,18 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
|
|||||||
|
|
||||||
public async getSpecModel(): Promise<Module[]> {
|
public async getSpecModel(): Promise<Module[]> {
|
||||||
if (this.resolvedModels == null) {
|
if (this.resolvedModels == null) {
|
||||||
this.resolvedModels = await this._doModuleRetrieval(this.containerDirectory)
|
this.resolvedModels = await this._doModuleRetrieval(await this._doModuleDiscovery(this.containerDirectory))
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.resolvedModels
|
return this.resolvedModels
|
||||||
}
|
}
|
||||||
|
|
||||||
protected generateMavenIdentifier(name: string, version: string): string {
|
protected getDefaultGroup(): string {
|
||||||
return `generated.${this.type.toLowerCase()}:${name}:${version}@${TypeMetadata[this.type].defaultExtension}`
|
return `generated.${this.type.toLowerCase()}`
|
||||||
|
}
|
||||||
|
|
||||||
|
protected generateMavenIdentifier(group: string, id: string, version: string): string {
|
||||||
|
return `${group}:${id}:${version}@${TypeMetadata[this.type].defaultExtension}`
|
||||||
}
|
}
|
||||||
|
|
||||||
protected attemptCrudeInference(name: string): { name: string, version: string } {
|
protected attemptCrudeInference(name: string): { name: string, version: string } {
|
||||||
@@ -47,6 +69,18 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getClaritasGroup(path: string): string {
|
||||||
|
return this.claritasResult[path]?.group || this.getDefaultGroup()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getClaritasExceptions(): ClaritasException[] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getClaritasType(): LibraryType | null {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
protected async abstract getModuleId(name: string, path: string): Promise<string>
|
protected async abstract getModuleId(name: string, path: string): Promise<string>
|
||||||
protected async abstract getModuleName(name: string, path: string): Promise<string>
|
protected async abstract getModuleName(name: string, path: string): Promise<string>
|
||||||
protected async abstract getModuleUrl(name: string, path: string, stats: Stats): Promise<string>
|
protected async abstract getModuleUrl(name: string, path: string, stats: Stats): Promise<string>
|
||||||
@@ -71,9 +105,9 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
|
|||||||
return mdl
|
return mdl
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async _doModuleRetrieval(scanDirectory: string): Promise<Module[]> {
|
protected async _doModuleDiscovery(scanDirectory: string): Promise<ModuleCandidate[]> {
|
||||||
|
|
||||||
const accumulator: Module[] = []
|
const moduleCandidates: ModuleCandidate[] = []
|
||||||
|
|
||||||
if (await pathExists(scanDirectory)) {
|
if (await pathExists(scanDirectory)) {
|
||||||
const files = await readdir(scanDirectory)
|
const files = await readdir(scanDirectory)
|
||||||
@@ -82,13 +116,63 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
|
|||||||
const stats = await lstat(filePath)
|
const stats = await lstat(filePath)
|
||||||
if (stats.isFile()) {
|
if (stats.isFile()) {
|
||||||
if(this.filter == null || this.filter(file, filePath, stats)) {
|
if(this.filter == null || this.filter(file, filePath, stats)) {
|
||||||
accumulator.push(await this.parseModule(file, filePath, stats))
|
moduleCandidates.push({file, filePath, stats})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return moduleCandidates
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async _doModuleRetrieval(moduleCandidates: ModuleCandidate[], options?: {
|
||||||
|
preProcess?: (candidate: ModuleCandidate) => void
|
||||||
|
postProcess?: (module: Module) => void
|
||||||
|
}): Promise<Module[]> {
|
||||||
|
|
||||||
|
const accumulator: Module[] = []
|
||||||
|
|
||||||
|
if(moduleCandidates.length > 0) {
|
||||||
|
|
||||||
|
// Invoke Claritas
|
||||||
|
if(this.getClaritasType() != null) {
|
||||||
|
const claritasExecutor = new ClaritasWrapper()
|
||||||
|
|
||||||
|
let claritasCandidates = moduleCandidates
|
||||||
|
const exceptionCandidates: [ModuleCandidate, ClaritasException][] = []
|
||||||
|
for(const exception of this.getClaritasExceptions()) {
|
||||||
|
const exceptionCandidate = moduleCandidates.find((value) => value.file.toLowerCase().indexOf(exception.exceptionName) > -1)
|
||||||
|
if(exceptionCandidate != null) {
|
||||||
|
exceptionCandidates.push([exceptionCandidate, exception])
|
||||||
|
claritasCandidates = claritasCandidates.filter((value) => value.file.toLowerCase().indexOf(exception.exceptionName) === -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.claritasResult = await claritasExecutor.execute(
|
||||||
|
this.getClaritasType()!,
|
||||||
|
this.minecraftVersion,
|
||||||
|
claritasCandidates.map(entry => entry.filePath)
|
||||||
|
)
|
||||||
|
if(this.claritasResult == null) {
|
||||||
|
this.logger.error('Failed to process Claritas result!')
|
||||||
|
} else {
|
||||||
|
for(const [candidate, exception] of exceptionCandidates) {
|
||||||
|
this.claritasResult[candidate.filePath] = exception.proxyMetadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process Modules
|
||||||
|
for(const candidate of moduleCandidates) {
|
||||||
|
options?.preProcess?.(candidate)
|
||||||
|
const mdl = await this.parseModule(candidate.file, candidate.filePath, candidate.stats)
|
||||||
|
options?.postProcess?.(mdl)
|
||||||
|
accumulator.push(mdl)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return accumulator
|
return accumulator
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { ModuleStructure } from './module.struct'
|
import { ModuleStructure, ModuleCandidate } from './module.struct'
|
||||||
import { Type, Module } from 'helios-distribution-types'
|
import { Type, Module } from 'helios-distribution-types'
|
||||||
import { Stats, mkdirs } from 'fs-extra'
|
import { Stats, mkdirs } from 'fs-extra'
|
||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
|
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
|
||||||
|
|
||||||
export enum ToggleableNamespace {
|
export enum ToggleableNamespace {
|
||||||
|
|
||||||
@@ -11,6 +12,10 @@ export enum ToggleableNamespace {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ToggleableModuleCandidate extends ModuleCandidate {
|
||||||
|
namespace: ToggleableNamespace
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class ToggleableModuleStructure extends ModuleStructure {
|
export abstract class ToggleableModuleStructure extends ModuleStructure {
|
||||||
|
|
||||||
private activeNamespace: string | undefined
|
private activeNamespace: string | undefined
|
||||||
@@ -20,10 +25,11 @@ export abstract class ToggleableModuleStructure extends ModuleStructure {
|
|||||||
relativeRoot: string,
|
relativeRoot: string,
|
||||||
structRoot: string,
|
structRoot: string,
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
protected type: Type,
|
minecraftVersion: MinecraftVersion,
|
||||||
protected filter?: ((name: string, path: string, stats: Stats) => boolean)
|
type: Type,
|
||||||
|
filter?: ((name: string, path: string, stats: Stats) => boolean)
|
||||||
) {
|
) {
|
||||||
super(absoluteRoot, relativeRoot, structRoot, baseUrl, type, filter)
|
super(absoluteRoot, relativeRoot, structRoot, baseUrl, minecraftVersion, type, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
public async init(): Promise<void> {
|
public async init(): Promise<void> {
|
||||||
@@ -36,13 +42,21 @@ export abstract class ToggleableModuleStructure extends ModuleStructure {
|
|||||||
public async getSpecModel(): Promise<Module[]> {
|
public async getSpecModel(): Promise<Module[]> {
|
||||||
if (this.resolvedModels == null) {
|
if (this.resolvedModels == null) {
|
||||||
|
|
||||||
this.resolvedModels = []
|
const moduleCandidates: ToggleableModuleCandidate[] = []
|
||||||
for(const value of Object.values(ToggleableNamespace)) {
|
for(const value of Object.values(ToggleableNamespace)) {
|
||||||
this.activeNamespace = value
|
moduleCandidates.push(...(await super._doModuleDiscovery(resolve(this.containerDirectory, value))).map(val => ({...val, namespace: value})))
|
||||||
const models = await this._doModuleRetrieval(resolve(this.containerDirectory, value))
|
|
||||||
models.forEach(this.getNamespaceMapper(value))
|
|
||||||
this.resolvedModels = this.resolvedModels.concat(models)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.resolvedModels = await this._doModuleRetrieval(moduleCandidates, {
|
||||||
|
preProcess: (candidate) => {
|
||||||
|
this.activeNamespace = (candidate as ToggleableModuleCandidate).namespace
|
||||||
|
},
|
||||||
|
postProcess: (module) => {
|
||||||
|
this.getNamespaceMapper(this.activeNamespace as ToggleableNamespace)(module)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
this.activeNamespace = undefined
|
this.activeNamespace = undefined
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,9 @@ import { MiscFileStructure } from './module/file.struct'
|
|||||||
import { LiteModStructure } from './module/litemod.struct'
|
import { LiteModStructure } from './module/litemod.struct'
|
||||||
import { LibraryStructure } from './module/library.struct'
|
import { LibraryStructure } from './module/library.struct'
|
||||||
import { MinecraftVersion } from '../../../util/MinecraftVersion'
|
import { MinecraftVersion } from '../../../util/MinecraftVersion'
|
||||||
import { LoggerUtil } from '../../../util/LoggerUtil'
|
|
||||||
|
|
||||||
export class ServerStructure extends BaseModelStructure<Server> {
|
export class ServerStructure extends BaseModelStructure<Server> {
|
||||||
|
|
||||||
private static readonly logger = LoggerUtil.getLogger('ServerStructure')
|
|
||||||
|
|
||||||
private readonly ID_REGEX = /(.+-(.+)$)/
|
private readonly ID_REGEX = /(.+-(.+)$)/
|
||||||
private readonly SERVER_META_FILE = 'servermeta.json'
|
private readonly SERVER_META_FILE = 'servermeta.json'
|
||||||
|
|
||||||
@@ -25,6 +22,10 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
|||||||
super(absoluteRoot, '', 'servers', baseUrl)
|
super(absoluteRoot, '', 'servers', baseUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'ServerStructure'
|
||||||
|
}
|
||||||
|
|
||||||
public async getSpecModel(): Promise<Server[]> {
|
public async getSpecModel(): Promise<Server[]> {
|
||||||
if (this.resolvedModels == null) {
|
if (this.resolvedModels == null) {
|
||||||
this.resolvedModels = await this._doSeverRetrieval()
|
this.resolvedModels = await this._doSeverRetrieval()
|
||||||
@@ -45,7 +46,7 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
|||||||
const relativeServerRoot = join(this.relativeRoot, effectiveId)
|
const relativeServerRoot = join(this.relativeRoot, effectiveId)
|
||||||
|
|
||||||
if (await pathExists(absoluteServerRoot)) {
|
if (await pathExists(absoluteServerRoot)) {
|
||||||
ServerStructure.logger.error('Server already exists! Aborting.')
|
this.logger.error('Server already exists! Aborting.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.liteloaderVersion != null) {
|
if (options.liteloaderVersion != null) {
|
||||||
const lms = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
const lms = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
|
||||||
await lms.init()
|
await lms.init()
|
||||||
serverMetaOpts.liteloaderVersion = options.liteloaderVersion
|
serverMetaOpts.liteloaderVersion = options.liteloaderVersion
|
||||||
}
|
}
|
||||||
@@ -74,10 +75,10 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
|||||||
const serverMeta: ServerMeta = getDefaultServerMeta(id, minecraftVersion.toString(), serverMetaOpts)
|
const serverMeta: ServerMeta = getDefaultServerMeta(id, minecraftVersion.toString(), serverMetaOpts)
|
||||||
await writeFile(resolvePath(absoluteServerRoot, this.SERVER_META_FILE), JSON.stringify(serverMeta, null, 2))
|
await writeFile(resolvePath(absoluteServerRoot, this.SERVER_META_FILE), JSON.stringify(serverMeta, null, 2))
|
||||||
|
|
||||||
const libS = new LibraryStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
const libS = new LibraryStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
|
||||||
await libS.init()
|
await libS.init()
|
||||||
|
|
||||||
const mfs = new MiscFileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
const mfs = new MiscFileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
|
||||||
await mfs.init()
|
await mfs.init()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -93,8 +94,8 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
|||||||
|
|
||||||
const match = this.ID_REGEX.exec(file)
|
const match = this.ID_REGEX.exec(file)
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
ServerStructure.logger.warn(`Server directory ${file} does not match the defined standard.`)
|
this.logger.warn(`Server directory ${file} does not match the defined standard.`)
|
||||||
ServerStructure.logger.warn('All server ids must end with -<minecraft version> (ex. -1.12.2)')
|
this.logger.warn('All server ids must end with -<minecraft version> (ex. -1.12.2)')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!iconUrl) {
|
if (!iconUrl) {
|
||||||
ServerStructure.logger.warn(`No icon file found for server ${file}.`)
|
this.logger.warn(`No icon file found for server ${file}.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read server meta
|
// Read server meta
|
||||||
@@ -146,16 +147,16 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
|||||||
|
|
||||||
|
|
||||||
if(serverMeta.liteloader) {
|
if(serverMeta.liteloader) {
|
||||||
const liteModStruct = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
const liteModStruct = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
|
||||||
const liteModModules = await liteModStruct.getSpecModel()
|
const liteModModules = await liteModStruct.getSpecModel()
|
||||||
modules.push(...liteModModules)
|
modules.push(...liteModModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
const libraryStruct = new LibraryStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
const libraryStruct = new LibraryStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
|
||||||
const libraryModules = await libraryStruct.getSpecModel()
|
const libraryModules = await libraryStruct.getSpecModel()
|
||||||
modules.push(...libraryModules)
|
modules.push(...libraryModules)
|
||||||
|
|
||||||
const fileStruct = new MiscFileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
const fileStruct = new MiscFileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
|
||||||
const fileModules = await fileStruct.getSpecModel()
|
const fileModules = await fileStruct.getSpecModel()
|
||||||
modules.push(...fileModules)
|
modules.push(...fileModules)
|
||||||
|
|
||||||
@@ -174,7 +175,7 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ServerStructure.logger.warn(`Path ${file} in server directory is not a directory!`)
|
this.logger.warn(`Path ${file} in server directory is not a directory!`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return accumulator
|
return accumulator
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ export class LibRepoStructure extends BaseMavenRepo {
|
|||||||
super(absoluteRoot, relativeRoot, 'lib')
|
super(absoluteRoot, relativeRoot, 'lib')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'LibRepoStructure'
|
||||||
|
}
|
||||||
|
|
||||||
public getLocalForge(version: string, classifier?: string): string {
|
public getLocalForge(version: string, classifier?: string): string {
|
||||||
return this.getArtifactByComponents(
|
return this.getArtifactByComponents(
|
||||||
LibRepoStructure.FORGE_GROUP,
|
LibRepoStructure.FORGE_GROUP,
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ export class RepoStructure extends BaseFileStructure {
|
|||||||
this.versionRepoStruct = new VersionRepoStructure(this.containerDirectory, this.relativeRoot)
|
this.versionRepoStruct = new VersionRepoStructure(this.containerDirectory, this.relativeRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'RepoStructure'
|
||||||
|
}
|
||||||
|
|
||||||
public async init(): Promise<void> {
|
public async init(): Promise<void> {
|
||||||
super.init()
|
super.init()
|
||||||
await this.libRepoStruct.init()
|
await this.libRepoStruct.init()
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ export class VersionRepoStructure extends BaseFileStructure {
|
|||||||
super(absoluteRoot, relativeRoot, 'versions')
|
super(absoluteRoot, relativeRoot, 'versions')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLoggerName(): string {
|
||||||
|
return 'VersionRepoStructure'
|
||||||
|
}
|
||||||
|
|
||||||
public getFileName(minecraftVersion: MinecraftVersion, forgeVersion: string): string {
|
public getFileName(minecraftVersion: MinecraftVersion, forgeVersion: string): string {
|
||||||
return `${minecraftVersion}-forge-${forgeVersion}`
|
return `${minecraftVersion}-forge-${forgeVersion}`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { basename, join } from 'path'
|
|||||||
import { VersionManifestFG2 } from '../../../model/forge/VersionManifestFG2'
|
import { VersionManifestFG2 } from '../../../model/forge/VersionManifestFG2'
|
||||||
import { LibRepoStructure } from '../../../model/struct/repo/librepo.struct'
|
import { LibRepoStructure } from '../../../model/struct/repo/librepo.struct'
|
||||||
import { MavenUtil } from '../../../util/maven'
|
import { MavenUtil } from '../../../util/maven'
|
||||||
import { PackXZExtractWrapper } from '../../../util/PackXZExtractWrapper'
|
import { PackXZExtractWrapper } from '../../../util/java/PackXZExtractWrapper'
|
||||||
import { VersionUtil } from '../../../util/versionutil'
|
import { VersionUtil } from '../../../util/versionutil'
|
||||||
import { ForgeResolver } from '../forge.resolver'
|
import { ForgeResolver } from '../forge.resolver'
|
||||||
import { MinecraftVersion } from '../../../util/MinecraftVersion'
|
import { MinecraftVersion } from '../../../util/MinecraftVersion'
|
||||||
@@ -227,7 +227,8 @@ export class ForgeGradle2Adapter extends ForgeResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ForgeGradle2Adapter.logger.debug('Spawning PackXZExtract.')
|
ForgeGradle2Adapter.logger.debug('Spawning PackXZExtract.')
|
||||||
await PackXZExtractWrapper.extractUnpack(files)
|
const packXZExecutor = new PackXZExtractWrapper()
|
||||||
|
await packXZExecutor.extractUnpack(files)
|
||||||
ForgeGradle2Adapter.logger.debug('All files extracted, calculating hashes..')
|
ForgeGradle2Adapter.logger.debug('All files extracted, calculating hashes..')
|
||||||
|
|
||||||
for (const entry of processingQueue) {
|
for (const entry of processingQueue) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { LibRepoStructure } from '../../../model/struct/repo/librepo.struct'
|
|||||||
import { pathExists, remove, mkdirs, copy, writeFile, readFile, lstat, move, writeJson } from 'fs-extra'
|
import { pathExists, remove, mkdirs, copy, writeFile, readFile, lstat, move, writeJson } from 'fs-extra'
|
||||||
import { join, basename, dirname } from 'path'
|
import { join, basename, dirname } from 'path'
|
||||||
import { spawn } from 'child_process'
|
import { spawn } from 'child_process'
|
||||||
import { JavaUtil } from '../../../util/javautil'
|
import { JavaUtil } from '../../../util/java/javautil'
|
||||||
import { VersionManifestFG3 } from '../../../model/forge/VersionManifestFG3'
|
import { VersionManifestFG3 } from '../../../model/forge/VersionManifestFG3'
|
||||||
import { MavenUtil } from '../../../util/maven'
|
import { MavenUtil } from '../../../util/maven'
|
||||||
import { createHash } from 'crypto'
|
import { createHash } from 'crypto'
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
import { spawn } from 'child_process'
|
|
||||||
import { join } from 'path'
|
|
||||||
import { JavaUtil } from './javautil'
|
|
||||||
import { LoggerUtil } from './LoggerUtil'
|
|
||||||
|
|
||||||
export class PackXZExtractWrapper {
|
|
||||||
|
|
||||||
private static readonly logger = LoggerUtil.getLogger('PackXZExtract')
|
|
||||||
|
|
||||||
public static getPackXZExtract(): string {
|
|
||||||
return join(process.cwd(), 'libraries', 'java', 'PackXZExtract.jar')
|
|
||||||
}
|
|
||||||
|
|
||||||
public static extractUnpack(paths: string[]): Promise<void> {
|
|
||||||
return PackXZExtractWrapper.execute('-packxz', paths)
|
|
||||||
}
|
|
||||||
|
|
||||||
public static extract(paths: string[]): Promise<void> {
|
|
||||||
return PackXZExtractWrapper.execute('-xz', paths)
|
|
||||||
}
|
|
||||||
|
|
||||||
public static unpack(paths: string[]): Promise<void> {
|
|
||||||
return PackXZExtractWrapper.execute('-pack', paths)
|
|
||||||
}
|
|
||||||
|
|
||||||
private static execute(command: string, paths: string[]): Promise<void> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const child = spawn(JavaUtil.getJavaExecutable(), [
|
|
||||||
'-jar',
|
|
||||||
PackXZExtractWrapper.getPackXZExtract(),
|
|
||||||
command,
|
|
||||||
paths.join(',')
|
|
||||||
])
|
|
||||||
child.stdout.on('data', (data) => PackXZExtractWrapper.logger.info(data.toString('utf8').trim()))
|
|
||||||
child.stderr.on('data', (data) => PackXZExtractWrapper.logger.error(data.toString('utf8').trim()))
|
|
||||||
child.on('close', code => {
|
|
||||||
PackXZExtractWrapper.logger.info('Exited with code', code)
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
child.on('error', (err) => {
|
|
||||||
PackXZExtractWrapper.logger.info('Error during process execution', err)
|
|
||||||
reject(err)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -42,7 +42,7 @@ export class VersionSegmentedRegistry {
|
|||||||
): BaseForgeModStructure {
|
): BaseForgeModStructure {
|
||||||
for (const impl of VersionSegmentedRegistry.FORGEMOD_STRUCT_IML) {
|
for (const impl of VersionSegmentedRegistry.FORGEMOD_STRUCT_IML) {
|
||||||
if (impl.isForVersion(minecraftVersion, forgeVersion)) {
|
if (impl.isForVersion(minecraftVersion, forgeVersion)) {
|
||||||
return new impl(absoluteRoot, relativeRoot, baseUrl)
|
return new impl(absoluteRoot, relativeRoot, baseUrl, minecraftVersion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error(`No forge mod structure found for Minecraft ${minecraftVersion}!`)
|
throw new Error(`No forge mod structure found for Minecraft ${minecraftVersion}!`)
|
||||||
|
|||||||
32
src/util/java/ClaritasWrapper.ts
Normal file
32
src/util/java/ClaritasWrapper.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { JarExecutor } from './JarExecutor'
|
||||||
|
import { join } from 'path'
|
||||||
|
import { ClaritasResult } from '../../model/claritas/ClaritasResult'
|
||||||
|
import { MinecraftVersion } from '../MinecraftVersion'
|
||||||
|
import { LibraryType } from '../../model/claritas/ClaritasLibraryType'
|
||||||
|
|
||||||
|
export class ClaritasWrapper extends JarExecutor<ClaritasResult> {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super('Claritas')
|
||||||
|
this.stdoutListeners.push((data) => {
|
||||||
|
const clean = data.toString('utf8').trim() as string
|
||||||
|
const spike = 'results::'
|
||||||
|
if(clean.startsWith(spike)) {
|
||||||
|
this.lastExecutionResult = JSON.parse(clean.substr(spike.length)) as ClaritasResult
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getJarPath(): string {
|
||||||
|
return join(process.cwd(), 'libraries', 'java', 'Claritas.jar')
|
||||||
|
}
|
||||||
|
|
||||||
|
public execute(libraryType: LibraryType, mcVersion: MinecraftVersion, absoluteJarPaths: string[]): Promise<ClaritasResult> {
|
||||||
|
return super.executeJar(
|
||||||
|
'--absoluteJarPaths', absoluteJarPaths.join(','),
|
||||||
|
'--libraryType', libraryType,
|
||||||
|
'--mcVersion', mcVersion.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
48
src/util/java/JarExecutor.ts
Normal file
48
src/util/java/JarExecutor.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { JavaUtil } from './javautil'
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
import { spawn } from 'child_process'
|
||||||
|
import { LoggerUtil } from '../LoggerUtil'
|
||||||
|
|
||||||
|
export abstract class JarExecutor<T> {
|
||||||
|
|
||||||
|
protected readonly logger: Logger
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
protected stdoutListeners: ((chunk: any) => void)[] = []
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
protected stderrListeners: ((chunk: any) => void)[] = []
|
||||||
|
|
||||||
|
protected lastExecutionResult!: T
|
||||||
|
|
||||||
|
protected constructor(loggerName: string) {
|
||||||
|
this.logger = LoggerUtil.getLogger(loggerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract getJarPath(): string
|
||||||
|
|
||||||
|
protected executeJar(...args: string[]): Promise<T> {
|
||||||
|
this.lastExecutionResult = undefined!
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const child = spawn(JavaUtil.getJavaExecutable(), [
|
||||||
|
'-jar',
|
||||||
|
this.getJarPath(),
|
||||||
|
...args
|
||||||
|
])
|
||||||
|
child.stdout.on('data', (data) => this.logger.info(data.toString('utf8').trim()))
|
||||||
|
this.stdoutListeners.forEach(l => child.stdout.on('data', l))
|
||||||
|
|
||||||
|
child.stderr.on('data', (data) => this.logger.error(data.toString('utf8').trim()))
|
||||||
|
this.stderrListeners.forEach(l => child.stderr.on('data', l))
|
||||||
|
|
||||||
|
child.on('close', code => {
|
||||||
|
this.logger.info('Exited with code', code)
|
||||||
|
resolve(this.lastExecutionResult)
|
||||||
|
})
|
||||||
|
child.on('error', (err) => {
|
||||||
|
this.logger.info('Error during process execution', err)
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
30
src/util/java/PackXZExtractWrapper.ts
Normal file
30
src/util/java/PackXZExtractWrapper.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { join } from 'path'
|
||||||
|
import { JarExecutor } from './JarExecutor'
|
||||||
|
|
||||||
|
export class PackXZExtractWrapper extends JarExecutor<void> {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super('PackXZExtract')
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getJarPath(): string {
|
||||||
|
return join(process.cwd(), 'libraries', 'java', 'PackXZExtract.jar')
|
||||||
|
}
|
||||||
|
|
||||||
|
protected execute(command: string, paths: string[]): Promise<void> {
|
||||||
|
return super.executeJar(command, paths.join(','))
|
||||||
|
}
|
||||||
|
|
||||||
|
public extractUnpack(paths: string[]): Promise<void> {
|
||||||
|
return this.execute('-packxz', paths)
|
||||||
|
}
|
||||||
|
|
||||||
|
public extract(paths: string[]): Promise<void> {
|
||||||
|
return this.execute('-xz', paths)
|
||||||
|
}
|
||||||
|
|
||||||
|
public unpack(paths: string[]): Promise<void> {
|
||||||
|
return this.execute('-pack', paths)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user