@@ -94,6 +94,14 @@ Get the forge version info and install forge from it.
94
94
await ForgeInstaller .install (firstVersionOnPage , minecraftLocation );
95
95
```
96
96
97
+ If you know forge version and minecraft version. You can directly do such:
98
+
99
+ ``` ts
100
+ import { ForgeInstaller } from " @xmcl/installer" ;
101
+ const forgeVersion = ' a-forge-version' ; // like 31.1.27
102
+ await ForgeInstaller .install ({ version: forgeVersion , mcversion: ' 1.15.2' }, minecraftLocation );
103
+ ```
104
+
97
105
Notice that this installation doesn't ensure full libraries installation.
98
106
Please run ` Installer.installDependencies ` afther that.
99
107
@@ -126,8 +134,11 @@ For example, if you want to download the library `commons-io:commons-io:2.5` fro
126
134
}
127
135
// return undefined if you don't want to change lib url
128
136
return undefined ;
129
- }
137
+ },
138
+ mavenHost: [' https://www.your-other-maven.org' ], // you still can use this to add other maven
130
139
});
140
+
141
+ // it will first try you libraryHost url and then try mavenHost url.
131
142
```
132
143
133
144
To swap the assets host, you can just assign the assets host url to the options
@@ -210,7 +221,19 @@ Get the report of the version. It can check if version missing assets/libraries.
210
221
const minecraftLocation: string ;
211
222
const minecraftVersionId: string ;
212
223
213
- const report: Diagnosis .Report = await Diagnosis .diagnose (minecraftLocation , minecraftVersionId );
224
+ const report: Diagnosis .MinecraftIssueReport = await Diagnosis .diagnose (minecraftLocation , minecraftVersionId );
225
+
226
+ const issues: Diagnosis .MinecraftIssues [] = report .issues ;
227
+
228
+ for (let issue of issues ) {
229
+ switch (issue .role ) {
230
+ case " minecraftJar" : // your jar has problem
231
+ case " versionJson" : // your json has problem
232
+ case " library" : // your lib might be missing or corrupted
233
+ case " assets" : // some assets are missing or corrupted
234
+ // and so on
235
+ }
236
+ }
214
237
```
215
238
216
239
@@ -426,9 +449,18 @@ Parse minecraft version as a resolved version, which is used for launching proce
426
449
Read sever info (server ip, port) and fetch its status (ping, server motd):
427
450
428
451
``` ts
429
- import { fetchStatus , Status } from ' @xmcl/client'
430
- // or you want the raw json
431
- const rawStatusJson: Status = await fetchStatus (info );
452
+ import { queryStatus , Status , QueryOptions } from ' @xmcl/client'
453
+ const serverInfo = {
454
+ host: ' your host' ,
455
+ port: 25565 , // be default
456
+ };
457
+ const options: QueryOptions = {
458
+ /**
459
+ * see http://wiki.vg/Protocol_version_numbers
460
+ */
461
+ protocol: 203 ,
462
+ };
463
+ const rawStatusJson: Status = await fetchStatus (info , options );
432
464
```
433
465
434
466
### Progress Moniting
@@ -478,6 +510,112 @@ Therefore you can just treat the `TaskRuntime` object a stateless event emitter.
478
510
// the error will still reject to the promise
479
511
```
480
512
513
+ ### Progress Moniting on Installation
514
+
515
+ Most 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.
516
+
517
+ Here is the example of just moniting the install task overall progress:
518
+
519
+ ``` ts
520
+
521
+ let task: Task <ResolvedVersion > = installTask (' client' , versionMetadata , mcLocation );
522
+ let taskHandle: TaskHandle <ResolvedVersion > = task .execute ();
523
+
524
+ let rootTask: Task .State ;
525
+ taskHandle .on (' execute' , (task , parentTask ) => {
526
+ if (parentTask ) {
527
+ // remember which is the root tas
528
+ rootTask = task ;
529
+ } else {
530
+ // other child task executed
531
+ }
532
+ });
533
+ taskHandle .on (' update' , ({ progress , total , message }, taskState ) => {
534
+ if (rootTask === taskState ) {
535
+ // root task update
536
+ // you should update your ui progress
537
+ } else {
538
+ // other task update
539
+ }
540
+ });
541
+
542
+ // wait task finish
543
+ await taskHandle .wait ();
544
+
545
+ ```
546
+
547
+ The task is designed to organize the all the works in a tree like structure.
548
+
549
+ The ` installTask ` has such parent/child structure
550
+
551
+ - install
552
+ - installVersion
553
+ - json
554
+ - jar
555
+ - installDependencies
556
+ - installAssets
557
+ - assetsJson
558
+ - asset
559
+ - installLibraries
560
+ - library
561
+
562
+ To generally display this tree in UI. You can identify the task by its ` path ` .
563
+
564
+ ``` ts
565
+ function updateTaskUI(task : Task .State , progress : number , total ? : number ) {
566
+ // you can use task.path as identifier
567
+ // and update the task on UI
568
+ }
569
+
570
+ // taskHandle is the installTask handle
571
+ taskHandle .on (' update' , ({ progress , total , message }, taskState ) => {
572
+ let path = taskState .path ;
573
+ // the path is concated from each tasks' name
574
+ // it can be "install", "install.installVersion", "install.installVersion.jar"
575
+ // "install.installDependencies.installAssets.assetsJson" or so on...
576
+ updateTaskUI (taskState , progress , total );
577
+ });
578
+ ```
579
+
580
+ If you think that's not good enough, you can assign the id to the task state by yourself.
581
+
582
+ In this simple case, you will enconter type error in typescript!
583
+
584
+ ``` ts
585
+ taskHandle .on (' execute' , (task , parentTask ) => {
586
+ task .id = ' your-generated-id' ; // type error
587
+ });
588
+ taskHandle .on (' update' , ({ progress , total , message }, taskState ) => {
589
+ updateTaskUI (taskState , progress , total );
590
+ });
591
+ function updateTaskUI(task : Task .State , progress : number , total ? : number ) {
592
+ // update the task by task.id
593
+ }
594
+ ```
595
+
596
+ You can override the type by yourself, or you can use task state factory:
597
+
598
+ ``` ts
599
+ interface TaskState extends Task .State {
600
+ id: string ;
601
+ }
602
+ const factory: Task .StateFactory <TaskState > = n => ({
603
+ ... n ,
604
+ id: generateIdByYourselft (),
605
+ });
606
+
607
+ const runtime: TaskRuntime <TaskState > = Task .createRuntime (factory );
608
+ const task: Task <ResolvedVersion > = installTask (' client' , versionMetadata , mcLocation );
609
+
610
+ runtime .submit (task ); // use runtime submit!
611
+
612
+ // listen the task event from runtime!
613
+ runtime .on (' update' , ({progress , total }, state ) => {
614
+ task .id ; // this will not have type error!
615
+ });
616
+ ```
617
+
618
+
481
619
### Read and Write NBT
482
620
483
621
You can simply deserialize/serialize nbt.
0 commit comments