UNPKG

10.6 kBMarkdownView Raw
1# Installer Module
2
3[![npm version](https://img.shields.io/npm/v/@xmcl/installer.svg)](https://www.npmjs.com/package/@xmcl/installer)
4[![Downloads](https://img.shields.io/npm/dm/@xmcl/installer.svg)](https://npmjs.com/@xmcl/installer)
5[![Install size](https://packagephobia.now.sh/badge?p=@xmcl/installer)](https://packagephobia.now.sh/result?p=@xmcl/installer)
6[![npm](https://img.shields.io/npm/l/@xmcl/minecraft-launcher-core.svg)](https://github.com/voxelum/minecraft-launcher-core-node/blob/master/LICENSE)
7[![Build Status](https://github.com/voxelum/minecraft-launcher-core-node/workflows/Build/badge.svg)](https://github.com/Voxelum/minecraft-launcher-core-node/actions?query=workflow%3ABuild)
8
9Provide functions to install Minecraft client, libraries, and assets.
10
11## Usage
12
13### Install Minecraft
14
15Fully install vanilla minecraft client including assets and libs.
16
17```ts
18 import { getVersionList, MinecraftVersion, install } from "@xmcl/installer";
19 import { MinecraftLocation } from "@xmcl/core";
20
21 const minecraft: MinecraftLocation;
22 const list: MinecraftVersion[] = (await getVersionList()).versions;
23 const aVersion: MinecraftVersion = list[0]; // i just pick the first version in list here
24 await install(aVersion, minecraft);
25```
26
27Just install libraries:
28
29```ts
30 import { installLibraries } from "@xmcl/installer";
31 import { ResolvedVersion, MinecraftLocation, Version } from "@xmcl/core";
32
33 const minecraft: MinecraftLocation;
34 const version: string; // version string like 1.13
35 const resolvedVersion: ResolvedVersion = await Version.parse(minecraft, version);
36 await installLibraries(resolvedVersion);
37```
38
39Just install assets:
40
41```ts
42 import { installAssets } from "@xmcl/installer";
43 import { MinecraftLocation, ResolvedVersion, Version } from "@xmcl/core";
44
45 const minecraft: MinecraftLocation;
46 const version: string; // version string like 1.13
47 const resolvedVersion: ResolvedVersion = await Version.parse(minecraft, version);
48 await installAssets(resolvedVersion);
49```
50
51Just ensure all assets and libraries are installed:
52
53```ts
54 import { installDependencies } from "@xmcl/installer";
55 import { MinecraftLocation, ResolvedVersion, Version } from "@xmcl/core";
56
57 const minecraft: MinecraftLocation;
58 const version: string; // version string like 1.13
59 const resolvedVersion: ResolvedVersion = await Version.parse(minecraft, version);
60 await installDependencies(resolvedVersion);
61```
62### Progress Moniting on Installation
63
64Most install function has a corresponding task function. For example, `install` function has the function name `installTask` which is the task version monitor the progress of install.
65
66Here is the example of just moniting the install task overall progress:
67
68```ts
69// suppose you have define such functions to update UI
70declare function updateTaskProgress(task: Task<any>, progress: number, total: number): void;
71declare function setTaskToFail(task: Task<any>): void;
72declare function setTaskToSuccess(task: Task<any>): void;
73declare function trackTask(task: Task<any>): void;
74
75const installAllTask: Task<ResolvedVersion> = installTask(versionMetadata, mcLocation);
76await installAllTask.startAndWait({
77 onStart(task: Task<any>) {
78 // a task start
79 // task.path show the path
80 // task.name is the name
81 trackTask(task)
82 },
83 onUpdate(task: Task<any>, chunkSize: number) {
84 // a task update
85 // the chunk size usually the buffer size
86 // you can use this to track download speed
87
88 // you can track this specific task progress
89 updateTaskProgress(task, task.progress, task.total);
90
91 // or you can update the root task by
92 updateTaskProgress(task, installAllTask.progress, installAllTask.total);
93 },
94 onFailed(task: Task<any>, error: any) {
95 // on a task fail
96 setTaskToFail(task);
97 },
98 onSuccessed(task: Task<any>, result: any) {
99 // on task success
100 setTaskToSuccess(task);
101 },
102 // on task is paused/resumed/cancelled
103 onPaused(task: Task<any>) {
104 },
105 onResumed(task: Task<any>) {
106 },
107 onCancelled(task: Task<any>) {
108 },
109});
110
111```
112
113The task is designed to organize the all the works in a tree like structure.
114
115The `installTask` has such parent/child structure
116
117- install
118 - version
119 - json
120 - jar
121 - dependencies
122 - assets
123 - assetsJson
124 - asset
125 - libraries
126 - library
127
128To generally display this tree in UI. You can identify the task by its `path`.
129
130```ts
131function updateTaskUI(task: Task<any>, progress: number, total: number) {
132 // you can use task.path as identifier
133 // and update the task on UI
134 const path = task.path;
135 // the path can be something like `install.version.json`
136}
137```
138
139Or you can use your own identifier like uuid:
140
141```ts
142// you customize function to make task to a user reacable string to display in UI
143declare function getTaskName(task: Task<any>): string;
144
145function runTask(rootTask: Task<any>) {
146 // your own id for this root task
147 const uid = uuid();
148 await rootTask.startAndWait({
149 onStart(task: Task<any>) {
150 // tell ui that a task with such name started
151 // the task id is a number id from 0
152 trackTask(`${uid}.${task.id}`, getTaskName(task));
153 },
154 onUpdate(task: Task<any>, chunkSize: number) {
155 // update the total progress
156 updateTaskProgress(`${uid}.${task.id}`, installAllTask.progress, installAllTask.total);
157 },
158 onStart(task: Task<any>) {
159 // tell ui this task ended
160 endTask(`${uid}.${task.id}`);
161 },
162 });
163}
164
165```
166
167### Install Library/Assets with Customized Host
168
169To swap the library to your self-host or other customized host, you can assign the `libraryHost` field in options.
170
171For example, if you want to download the library `commons-io:commons-io:2.5` from your self hosted server, you can have
172
173```ts
174 // the example for call `installLibraries`
175 // this option will also work for other functions involving libraries like `install`, `installDependencies`.
176 await installLibraries(resolvedVersion, {
177 libraryHost(library: ResolvedLibrary) {
178 if (library.name === "commons-io:commons-io:2.5") {
179 // the downloader will first try the first url in the array
180 // if this failed, it will try the 2nd.
181 // if it's still failed, it will try original url
182 return ["https://your-host.org/the/path/to/the/jar", "your-sencodary-url"];
183 // if you just have one url
184 // just return a string here...
185 }
186 // return undefined if you don't want to change lib url
187 return undefined;
188 },
189 mavenHost: ['https://www.your-other-maven.org'], // you still can use this to add other maven
190 });
191
192 // it will first try you libraryHost url and then try mavenHost url.
193```
194
195To swap the assets host, you can just assign the assets host url to the options
196
197```ts
198 await installAssets(resolvedVersion, {
199 assetsHost: "https://www.your-url/assets"
200 });
201```
202
203The assets host should accept the get asset request like `GET https://www.your-url/assets/<hash-head>/<hash>`, where `hash-head` is the first two char in `<hash>`. The `<hash>` is the sha1 of the asset.
204
205### Install Forge
206
207Get the forge version info and install forge from it.
208
209```ts
210 import { installForge, getForgeVersionList, ForgeVersionList, ForgeVersion } from "@xmcl/installer";
211 import { MinecraftLocation } from "@xmcl/core";
212
213 const list: ForgeVersionList = await getForgeVersionList();
214 const minecraftLocation: MinecraftLocation;
215 const mcversion = page.mcversion; // mc version
216 const firstVersionOnPage: ForgeVersion = page.versions[0];
217 await installForge(firstVersionOnPage, minecraftLocation);
218```
219
220If you know forge version and minecraft version. You can directly do such:
221
222```ts
223 import { installForge } from "@xmcl/installer";
224
225 const forgeVersion = 'a-forge-version'; // like 31.1.27
226 await installForge({ version: forgeVersion, mcversion: '1.15.2' }, minecraftLocation);
227```
228
229Notice that this installation doesn't ensure full libraries installation.
230Please run `installDependencies` afther that.
231
232The new 1.13 forge installation process requires java to run.
233Either you have `java` executable in your environment variable PATH,
234or you can assign java location by `installForge(forgeVersionMeta, minecraftLocation, { java: yourJavaExecutablePath });`.
235
236If you use this auto installation process to install forge, please checkout [Lex's Patreon](https://www.patreon.com/LexManos).
237Consider support him to maintains forge.
238
239### Install Fabric
240
241Fetch the new fabric version list.
242
243```ts
244 import { installFabric, FabricArtifactVersion } from "@xmcl/installer";
245
246 const versionList: FabricArtifactVersion[] = await getFabricArtifactList();
247```
248
249Install fabric to the client. This installation process doesn't ensure the minecraft libraries.
250
251```ts
252 const minecraftLocation: MinecraftLocation;
253 await installFabric(versionList[0], minecraftLocation);
254```
255
256Please run `Installer.installDependencies` after that to install fully.
257
258## New Forge Installing process
259
260The module have three stage for installing new forge *(mcversion >= 1.13)*
261
2621. Deploy forge installer jar
263 1. Download installer jar
264 2. Extract forge universal jar files in installer jar into `.minecraft/libraries`
265 3. Extract `version.json` into target version folder, `.minecraft/versions/<ver>/<ver>.json`
266 4. Extract `installer_profile.json` into target version folder, `.minecraft/versions/<ver>/installer_profile.json`
2672. Download Dependencies
268 1. Merge libraires in `installer_profile.json` and `<ver>.json`
269 2. Download them
2703. Post processing forge jar
271 1. Parse `installer_profile.json`
272 2. Get the processors info and execute all of them.
273
274The `installForge` will do all of them.
275
276The `installByProfile` will do 2 and 3.
277
278### Install Java 8 From Mojang Source
279
280Scan java installation path from the disk. (Require a lzma unpacker, like [7zip-bin](https://www.npmjs.com/package/7zip-bin) or [lzma-native](https://www.npmjs.com/package/lzma-native))
281
282```ts
283 import { installJreFromMojang } from "@xmcl/installer";
284
285 // this require a unpackLZMA util to work
286 // you can use `7zip-bin`
287 // or `lzma-native` for this
288 const unpackLZMA: (src: string, dest: string) => Promise<void>;
289
290 await installJreFromMojang({
291 destination: "your/java/home",
292 unpackLZMA,
293 });
294```