cyclops-infobook-html 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +7 -0
- package/assets/styles.css +5 -0
- package/bin/generate-infobook-html.js +2 -0
- package/bin/generate-mod-metadata.js +1 -1
- package/lib/infobook/IItem.d.ts +1 -1
- package/lib/infobook/appendix/InfoBookAppendixHandlerTextfield.d.ts +11 -0
- package/lib/infobook/appendix/InfoBookAppendixHandlerTextfield.js +24 -0
- package/lib/modloader/ModLoader.d.ts +15 -3
- package/lib/modloader/ModLoader.js +59 -27
- package/lib/resource/ResourceHandler.js +2 -2
- package/lib/resource/ResourceLoader.js +1 -1
- package/lib/serialize/HtmlInfoBookSerializer.js +1 -1
- package/package.json +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
|
|
4
|
+
<a name="v4.0.0"></a>
|
|
5
|
+
## [v4.0.0](https://github.com/CyclopsMC/infobook-html/compare/v3.0.0...v4.0.0) - 2024-07-23
|
|
6
|
+
|
|
7
|
+
### BREAKING CHANGE
|
|
8
|
+
* [Update to NeoForge 1.21](https://github.com/CyclopsMC/infobook-html/commit/bec55a8a0d2049a07cc3dafee2276c94ed738e73)
|
|
9
|
+
The most notable change here is that "nbt" on items and fluids is replaced by "components".
|
|
10
|
+
|
|
11
|
+
<a name="v3.1.0"></a>
|
|
12
|
+
## [v3.1.0](https://github.com/CyclopsMC/infobook-html/compare/v3.0.0...v3.1.0) - 2024-01-31
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
* [Support text field appendix](https://github.com/CyclopsMC/infobook-html/commit/6f24bbbd606b6cfd1237e3bf740e73ffc23008be)
|
|
16
|
+
* [Allowing raw mod URLs in modpack](https://github.com/CyclopsMC/infobook-html/commit/11c9ed5adc554ae7dafa66a202ac83fcacd240fb)
|
|
17
|
+
|
|
4
18
|
<a name="v3.0.0"></a>
|
|
5
19
|
## [v3.0.0](https://github.com/CyclopsMC/infobook-html/compare/v2.0.0...v3.0.0) - 2022-03-10
|
|
6
20
|
|
package/README.md
CHANGED
|
@@ -44,11 +44,18 @@ Before you can execute this phase, you need a `modpack.json` file with contents
|
|
|
44
44
|
"type": "maven",
|
|
45
45
|
"artifact": "org.cyclops.commoncapabilities:CommonCapabilities:1.12.2-2.4.4-309",
|
|
46
46
|
"repo": "https://oss.jfrog.org/artifactory/simple/libs-release/"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"type": "raw",
|
|
50
|
+
"name": "integratedscripting-1.19.2-1.0.0-61.jar",
|
|
51
|
+
"url": "https://www.dropbox.com/s/mbbikni5ieyttuq/integratedscripting-1.19.2-1.0.0-61.jar?dl=1"
|
|
47
52
|
}
|
|
48
53
|
]
|
|
49
54
|
}
|
|
50
55
|
```
|
|
51
56
|
|
|
57
|
+
*The "forge" entry may be replaced by "neoforge".*
|
|
58
|
+
|
|
52
59
|
To start this phase, simply run `generate-mod-metadata modpack.json generate`.
|
|
53
60
|
|
|
54
61
|
Optionally, you can delete the resulting server files afterwards using `generate-mod-metadata modpack.json clean`.
|
package/assets/styles.css
CHANGED
|
@@ -10,6 +10,7 @@ const InfoBookAppendixHandlerCraftingRecipe_1 = require("../lib/infobook/appendi
|
|
|
10
10
|
const InfoBookAppendixHandlerSmeltingRecipe_1 = require("../lib/infobook/appendix/InfoBookAppendixHandlerSmeltingRecipe");
|
|
11
11
|
const InfoBookAppendixHandlerImage_1 = require("../lib/infobook/appendix/InfoBookAppendixHandlerImage");
|
|
12
12
|
const InfoBookAppendixHandlerKeybinding_1 = require("../lib/infobook/appendix/InfoBookAppendixHandlerKeybinding");
|
|
13
|
+
const InfoBookAppendixHandlerTextfield_1 = require("../lib/infobook/appendix/InfoBookAppendixHandlerTextfield");
|
|
13
14
|
const InfoBookInitializer_1 = require("../lib/infobook/InfoBookInitializer");
|
|
14
15
|
const ResourceLoader_1 = require("../lib/resource/ResourceLoader");
|
|
15
16
|
const HtmlInfoBookSerializer_1 = require("../lib/serialize/HtmlInfoBookSerializer");
|
|
@@ -61,6 +62,7 @@ function create() {
|
|
|
61
62
|
infoBookInitializer.registerAppendixHandler('minecraft:smelting', new InfoBookAppendixHandlerSmeltingRecipe_1.InfoBookAppendixHandlerSmeltingRecipe(resourceLoader.getResourceHandler(), 'registries', config.recipeOverrides));
|
|
62
63
|
infoBookInitializer.registerAppendixHandler('image', new InfoBookAppendixHandlerImage_1.InfoBookAppendixHandlerImage(resourceLoader.getResourceHandler()));
|
|
63
64
|
infoBookInitializer.registerAppendixHandler('keybinding', new InfoBookAppendixHandlerKeybinding_1.InfoBookAppendixHandlerKeybinding(resourceLoader.getResourceHandler()));
|
|
65
|
+
infoBookInitializer.registerAppendixHandler('textfield', new InfoBookAppendixHandlerTextfield_1.InfoBookAppendixHandlerTextfield(resourceLoader.getResourceHandler()));
|
|
64
66
|
// Load plugins
|
|
65
67
|
const assetsPaths = [];
|
|
66
68
|
const headSuffixGetters = [];
|
|
@@ -18,7 +18,7 @@ function run(command, configPath) {
|
|
|
18
18
|
const modLoader = new ModLoader_1.ModLoader({
|
|
19
19
|
mods: config.mods,
|
|
20
20
|
path: path_1.join(process.cwd(), 'server'),
|
|
21
|
-
versionForge: config.forge,
|
|
21
|
+
loader: 'forge' in config ? { versionForge: config.forge } : { versionNeoForge: config.neoforge },
|
|
22
22
|
versionMinecraft: config.minecraft,
|
|
23
23
|
});
|
|
24
24
|
switch (command) {
|
package/lib/infobook/IItem.d.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ResourceHandler } from "../../resource/ResourceHandler";
|
|
2
|
+
import { IInfoAppendix } from "../IInfoAppendix";
|
|
3
|
+
import { IInfoBookAppendixHandler } from "./IInfoBookAppendixHandler";
|
|
4
|
+
/**
|
|
5
|
+
* Handles text field appendices.
|
|
6
|
+
*/
|
|
7
|
+
export declare class InfoBookAppendixHandlerTextfield implements IInfoBookAppendixHandler {
|
|
8
|
+
private readonly resourceHandler;
|
|
9
|
+
constructor(resourceHandler: ResourceHandler);
|
|
10
|
+
createAppendix(data: any): IInfoAppendix;
|
|
11
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InfoBookAppendixHandlerTextfield = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Handles text field appendices.
|
|
6
|
+
*/
|
|
7
|
+
class InfoBookAppendixHandlerTextfield {
|
|
8
|
+
constructor(resourceHandler) {
|
|
9
|
+
this.resourceHandler = resourceHandler;
|
|
10
|
+
}
|
|
11
|
+
createAppendix(data) {
|
|
12
|
+
const contents = data._
|
|
13
|
+
.replace(/ /g, ' ')
|
|
14
|
+
.replace(/\n/g, '<br \>');
|
|
15
|
+
const scale = data.$.scale || 1;
|
|
16
|
+
return {
|
|
17
|
+
toHtml: (context, fileWriter) => {
|
|
18
|
+
return `<div class="appendix-textfield" style="font-size: ${scale}em">${contents}</div>`;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.InfoBookAppendixHandlerTextfield = InfoBookAppendixHandlerTextfield;
|
|
24
|
+
//# sourceMappingURL=InfoBookAppendixHandlerTextfield.js.map
|
|
@@ -6,7 +6,7 @@ import { ChildProcess } from "child_process";
|
|
|
6
6
|
export declare class ModLoader {
|
|
7
7
|
private readonly mods;
|
|
8
8
|
private readonly path;
|
|
9
|
-
private readonly
|
|
9
|
+
private readonly loader;
|
|
10
10
|
private readonly versionMinecraft;
|
|
11
11
|
constructor(args: IModLoaderArgs);
|
|
12
12
|
/**
|
|
@@ -29,6 +29,7 @@ export declare class ModLoader {
|
|
|
29
29
|
* Download and install mods.
|
|
30
30
|
*/
|
|
31
31
|
installMods(): Promise<void>;
|
|
32
|
+
downloadFile(url: string, fileName: string, modsDir: string): Promise<void>;
|
|
32
33
|
/**
|
|
33
34
|
* Start the server and execute a command to dump all registries
|
|
34
35
|
*/
|
|
@@ -75,14 +76,20 @@ export declare class ModLoader {
|
|
|
75
76
|
export interface IModLoaderArgs {
|
|
76
77
|
mods: IMod[];
|
|
77
78
|
path: string;
|
|
78
|
-
|
|
79
|
+
loader: ILoader;
|
|
79
80
|
versionMinecraft: string;
|
|
80
81
|
}
|
|
81
|
-
export declare type
|
|
82
|
+
export declare type ILoader = {
|
|
83
|
+
versionForge: string;
|
|
84
|
+
} | {
|
|
85
|
+
versionNeoForge: string;
|
|
86
|
+
};
|
|
87
|
+
export declare type IMod = IModMaven | IModCurseforge | IModRaw;
|
|
82
88
|
export interface IModMaven {
|
|
83
89
|
type: 'maven';
|
|
84
90
|
artifact: string;
|
|
85
91
|
repo: string;
|
|
92
|
+
name?: string;
|
|
86
93
|
}
|
|
87
94
|
export interface IModCurseforge {
|
|
88
95
|
type: 'curseforge';
|
|
@@ -90,3 +97,8 @@ export interface IModCurseforge {
|
|
|
90
97
|
artifact: string;
|
|
91
98
|
version: string;
|
|
92
99
|
}
|
|
100
|
+
export interface IModRaw {
|
|
101
|
+
type: 'raw';
|
|
102
|
+
name: string;
|
|
103
|
+
url: string;
|
|
104
|
+
}
|
|
@@ -20,7 +20,7 @@ class ModLoader {
|
|
|
20
20
|
constructor(args) {
|
|
21
21
|
this.mods = args.mods;
|
|
22
22
|
this.path = args.path;
|
|
23
|
-
this.
|
|
23
|
+
this.loader = args.loader;
|
|
24
24
|
this.versionMinecraft = args.versionMinecraft;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
@@ -37,22 +37,41 @@ class ModLoader {
|
|
|
37
37
|
if (!fs.existsSync(this.path)) {
|
|
38
38
|
yield fs.promises.mkdir(this.path);
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
let installerFile;
|
|
41
|
+
if ('versionForge' in this.loader) {
|
|
42
|
+
// Download Forge installer
|
|
43
|
+
process.stdout.write('Downloading Forge...\n');
|
|
44
|
+
const forgeInstaller = `https://files.minecraftforge.net/maven/net/minecraftforge/forge/${this.versionMinecraft}-${this.loader.versionForge}/forge-${this.versionMinecraft}-${this.loader.versionForge}-installer.jar`;
|
|
45
|
+
const res = yield node_fetch_1.default(forgeInstaller);
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
throw new Error(`Failed to fetch (${res.statusText}): ${forgeInstaller}`);
|
|
48
|
+
}
|
|
49
|
+
installerFile = path_1.join(this.path, 'forge-installer.jar');
|
|
50
|
+
yield new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
return fs.writeFile(installerFile, yield res.buffer(), (err) => err ? reject(err) : resolve());
|
|
52
|
+
}));
|
|
53
|
+
// Install Forge
|
|
54
|
+
process.stdout.write('Installing Forge...\n');
|
|
55
|
+
yield new Promise((resolve, reject) => child_process_1.exec(`cd ${this.path} && java -jar forge-installer.jar --installServer`).on('exit', resolve));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Download NeoForge installer
|
|
59
|
+
process.stdout.write('Downloading NeoForge...\n');
|
|
60
|
+
const installer = `https://maven.neoforged.net/releases/net/neoforged/neoforge/${this.loader.versionNeoForge}/neoforge-${this.loader.versionNeoForge}-installer.jar`;
|
|
61
|
+
const res = yield node_fetch_1.default(installer);
|
|
62
|
+
if (!res.ok) {
|
|
63
|
+
throw new Error(`Failed to fetch (${res.statusText}): ${installer}`);
|
|
64
|
+
}
|
|
65
|
+
installerFile = path_1.join(this.path, 'neoforge-installer.jar');
|
|
66
|
+
yield new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
return fs.writeFile(installerFile, yield res.buffer(), (err) => err ? reject(err) : resolve());
|
|
68
|
+
}));
|
|
69
|
+
// Install Forge
|
|
70
|
+
process.stdout.write('Installing NeoForge...\n');
|
|
71
|
+
yield new Promise((resolve, reject) => child_process_1.exec(`cd ${this.path} && java -jar neoforge-installer.jar --installServer`).on('exit', resolve));
|
|
46
72
|
}
|
|
47
|
-
const installerFile = path_1.join(this.path, 'forge-installer.jar');
|
|
48
|
-
yield new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
return fs.writeFile(installerFile, yield res.buffer(), (err) => err ? reject(err) : resolve());
|
|
50
|
-
}));
|
|
51
|
-
// Install Forge
|
|
52
|
-
process.stdout.write('Installing Forge...\n');
|
|
53
|
-
yield new Promise((resolve, reject) => child_process_1.exec(`cd ${this.path} && java -jar forge-installer.jar --installServer`).on('exit', resolve));
|
|
54
73
|
// Wait a bit, because otherwise some files don't exist yet (while they should...)
|
|
55
|
-
process.stdout.write('Wait a bit after
|
|
74
|
+
process.stdout.write('Wait a bit after mod loader installation...\n');
|
|
56
75
|
yield new Promise((resolve) => setTimeout(resolve, 10000));
|
|
57
76
|
// Cleanup
|
|
58
77
|
process.stdout.write('Cleaning up...\n');
|
|
@@ -91,20 +110,19 @@ class ModLoader {
|
|
|
91
110
|
process.stdout.write(` - ${fileName} from CurseForge...\n`);
|
|
92
111
|
const url = `https://minecraft.curseforge.com/api/maven/${mod.project}/${mod.artifact
|
|
93
112
|
.replace(/-/g, '/')}/${fileName}`;
|
|
94
|
-
|
|
95
|
-
if (response.status !== 200) {
|
|
96
|
-
throw new Error(response.statusText + ' on ' + url);
|
|
97
|
-
}
|
|
98
|
-
yield new Promise((resolve, reject) => {
|
|
99
|
-
response.body
|
|
100
|
-
.on('error', reject)
|
|
101
|
-
.on('end', resolve)
|
|
102
|
-
.pipe(fs.createWriteStream(path_1.join(modsDir, fileName)));
|
|
103
|
-
});
|
|
113
|
+
yield this.downloadFile(url, fileName, modsDir);
|
|
104
114
|
}
|
|
105
115
|
else if (mod.type === 'maven') {
|
|
106
116
|
process.stdout.write(` - ${mod.artifact} from ${mod.repo}...\n`);
|
|
107
|
-
yield mvn_artifact_download_1.default(mod.artifact, modsDir, mod.repo);
|
|
117
|
+
const name = yield mvn_artifact_download_1.default(mod.artifact, modsDir, mod.repo);
|
|
118
|
+
// Rename file if needed
|
|
119
|
+
if ('name' in mod) {
|
|
120
|
+
fs.renameSync(name, path_1.join(modsDir, mod.name));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else if (mod.type === 'raw') {
|
|
124
|
+
process.stdout.write(` - ${mod.name} from ${mod.url}...\n`);
|
|
125
|
+
yield this.downloadFile(mod.url, mod.name, modsDir);
|
|
108
126
|
}
|
|
109
127
|
else {
|
|
110
128
|
throw new Error('Unknown mod type ' + mod.type);
|
|
@@ -112,6 +130,20 @@ class ModLoader {
|
|
|
112
130
|
}
|
|
113
131
|
});
|
|
114
132
|
}
|
|
133
|
+
downloadFile(url, fileName, modsDir) {
|
|
134
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
const response = yield node_fetch_1.default(url);
|
|
136
|
+
if (response.status !== 200) {
|
|
137
|
+
throw new Error(response.statusText + ' on ' + url);
|
|
138
|
+
}
|
|
139
|
+
yield new Promise((resolve, reject) => {
|
|
140
|
+
response.body
|
|
141
|
+
.on('error', reject)
|
|
142
|
+
.on('end', resolve)
|
|
143
|
+
.pipe(fs.createWriteStream(path_1.join(modsDir, fileName)));
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
115
147
|
/**
|
|
116
148
|
* Start the server and execute a command to dump all registries
|
|
117
149
|
*/
|
|
@@ -135,7 +167,7 @@ class ModLoader {
|
|
|
135
167
|
});
|
|
136
168
|
// Once the loading is complete, send our command and stop the server
|
|
137
169
|
proc.stdout.on('data', (line) => {
|
|
138
|
-
if (line.indexOf('
|
|
170
|
+
if (line.indexOf('Done') >= 0 && line.indexOf('For help, type "help"') >= 0) {
|
|
139
171
|
process.stdout.write('Dumping registries...\n');
|
|
140
172
|
this.sendCommand(proc, '/cyclopscore dumpregistries');
|
|
141
173
|
this.sendCommand(proc, '/stop');
|
|
@@ -179,7 +179,7 @@ class ResourceHandler {
|
|
|
179
179
|
*/
|
|
180
180
|
addItemTranslationKey(item, translationKey) {
|
|
181
181
|
const { namespace, path } = ResourceHandler.splitItemId(item.item);
|
|
182
|
-
ResourceHandler.addItemKeyedRegistryEntry(this.itemTranslationKeys, namespace, path, item.
|
|
182
|
+
ResourceHandler.addItemKeyedRegistryEntry(this.itemTranslationKeys, namespace, path, item.components, translationKey);
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
185
185
|
* Get an item translation key.
|
|
@@ -188,7 +188,7 @@ class ResourceHandler {
|
|
|
188
188
|
*/
|
|
189
189
|
getItemTranslationKey(item) {
|
|
190
190
|
const { namespace, path } = ResourceHandler.splitItemId(item.item);
|
|
191
|
-
return ResourceHandler.getItemKeyedRegistryEntry(this.itemTranslationKeys, namespace, path, item.
|
|
191
|
+
return ResourceHandler.getItemKeyedRegistryEntry(this.itemTranslationKeys, namespace, path, item.components);
|
|
192
192
|
}
|
|
193
193
|
/**
|
|
194
194
|
* Add an fluid translation key.
|
|
@@ -126,7 +126,7 @@ class ResourceLoader {
|
|
|
126
126
|
// Ignore mods without language files
|
|
127
127
|
}
|
|
128
128
|
// Handle advancements
|
|
129
|
-
const advancementsDir = path_1.join(fullPath, '
|
|
129
|
+
const advancementsDir = path_1.join(fullPath, 'advancement');
|
|
130
130
|
try {
|
|
131
131
|
if ((yield fs_1.promises.stat(langDir)).isDirectory()) {
|
|
132
132
|
yield this.loadAssetsAdvancements(modid, advancementsDir, '');
|
|
@@ -177,7 +177,7 @@ class HtmlInfoBookSerializer {
|
|
|
177
177
|
if (item.item === 'minecraft:air') {
|
|
178
178
|
return slot ? '<div class="item item-slot"> </div>' : '<div class="item"> </div>';
|
|
179
179
|
}
|
|
180
|
-
const icon = resourceHandler.getItemIconFile(item.item, item.
|
|
180
|
+
const icon = resourceHandler.getItemIconFile(item.item, item.components);
|
|
181
181
|
if (!icon) {
|
|
182
182
|
throw new Error(`Could not find an icon for item ${JSON.stringify(item)}`);
|
|
183
183
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyclops-infobook-html",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Output Cyclops infobooks as HTML",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": "git@github.com:CyclopsMC/infobook-html.git",
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
"testEnvironment": "node"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@types/jest": "^
|
|
53
|
+
"@types/jest": "^28.0.0",
|
|
54
54
|
"@types/minimist": "^1.2.0",
|
|
55
55
|
"coveralls": "^3.0.3",
|
|
56
|
-
"jest": "^
|
|
56
|
+
"jest": "^28.0.0",
|
|
57
57
|
"manual-git-changelog": "^1.0.1",
|
|
58
58
|
"pre-commit": "^1.2.2",
|
|
59
|
-
"ts-jest": "^
|
|
59
|
+
"ts-jest": "^28.0.0",
|
|
60
60
|
"tslint": "^6.0.0",
|
|
61
61
|
"tslint-eslint-rules": "^5.4.0",
|
|
62
62
|
"typescript": "^4.0.0"
|
|
@@ -90,5 +90,8 @@
|
|
|
90
90
|
"rimraf": "^3.0.0",
|
|
91
91
|
"xml2js": "^0.4.19",
|
|
92
92
|
"yauzl": "^2.10.0"
|
|
93
|
+
},
|
|
94
|
+
"resolutions": {
|
|
95
|
+
"@types/istanbul-reports": "3.0.0"
|
|
93
96
|
}
|
|
94
97
|
}
|