import { MinecraftFolder , MinecraftLocation } from "@xmcl/core" ; import { Task , task } from "@xmcl/task" ; import { join } from "path" ; import { getAndParseIfUpdate , Timestamped } from "./http/fetch" ; import { ensureDir , InstallOptions , missing , readFile , writeFile } from "./utils" ; export const DEFAULT_VERSION_MANIFEST = "http://dl.liteloader.com/versions/versions.json" ; /**
 * The liteloader version list. Containing the minecraft version -> liteloader version info mapping.
 */ export interface LiteloaderVersionList extends Timestamped { meta : { description : string ; authors : string ; url : string ; updated : string ; updatedTime : number ; } ; versions : { [ version ] : { snapshot ? : LiteloaderVersion ; release ? : LiteloaderVersion ; } ; } ; } function processLibraries ( lib ) { if ( Object . keys ( lib ) . length === 1 && lib . name ) { if ( lib . name . startsWith ( "org.ow2.asm" ) ) { lib . url = "https://files.minecraftforge.net/maven/" ; } } return lib ; } export namespace LiteloaderVersionList { export function parse ( content ) { const result = JSON . parse ( content ) ; const metalist = { meta : result . meta , versions : { } } ; for ( const mcversion in result . versions ) { const versions = ( metalist . versions as any ) [ mcversion ] = { } ; const snapshots = result . versions [ mcversion ] . snapshots ; const artifacts = result . versions [ mcversion ] . artefacts ; const url = result . versions [ mcversion ] . repo . url ; if ( snapshots ) { const { stream , file , version , md5 , timestamp , tweakClass , libraries } = snapshots [ "com.mumfrey:liteloader" ] . latest ; const type = ( stream === "RELEASE" ? "RELEASE" : "SNAPSHOT" ) ; versions . snapshot = { url , type , file , version , md5 , timestamp , mcversion , tweakClass , libraries : libraries . map ( processLibraries ) , } ; } if ( artifacts ) { const { stream , file , version , md5 , timestamp , tweakClass , libraries } = artifacts [ "com.mumfrey:liteloader" ] . latest ; const type = ( stream === "RELEASE" ? "RELEASE" : "SNAPSHOT" ) ; versions . release = { url , type , file , version , md5 , timestamp , mcversion , tweakClass , libraries : libraries . map ( processLibraries ) , } ; } } return metalist ; } } /**
 * A liteloader remote version information
 */ export interface LiteloaderVersion { version : string ; url : string ; file : string ; mcversion : string ; type : "RELEASE" | "SNAPSHOT" ; md5 : string ; timestamp : string ; libraries : Array < { name : string ; url ? : string ; } > ; tweakClass : string ; } const snapshotRoot = "http://dl.liteloader.com/versions/" ; const releaseRoot = "http://repo.mumfrey.com/content/repositories/liteloader/" ; /**
 * This error is only thrown from liteloader install currently.
 */ export class MissingVersionJsonError extends Error { constructor ( public version , /**
     * The path of version json
     */ public path ) { super ( ) ; } error : "MissingVersionJson" = "MissingVersionJson" ; } /**
 * Get or update the LiteLoader version list.
 *
 * This will request liteloader offical json by default. You can replace the request by assigning the remote option.
 */ export function getLiteloaderVersionList ( option = { } ) { return getAndParseIfUpdate ( option . remote || DEFAULT_VERSION_MANIFEST , LiteloaderVersionList . parse , option . original ) ; } param versionMeta param location param version throws MissingVersionJsonError export function installLiteloader ( versionMeta , location , options ? ) { return installLiteloaderTask ( versionMeta , location , options ) . startAndWait ( ) ; } function buildVersionInfo ( versionMeta , mountedJSON ) { const id = `${ mountedJSON . id }-Liteloader${ versionMeta . mcversion }-${ versionMeta . version }` ; const time = new Date ( Number . parseInt ( versionMeta . timestamp , 10 ) * 1000 ) . toISOString ( ) ; const releaseTime = time ; const type = versionMeta . type ; const libraries = [ { name : `com.mumfrey:liteloader:${ versionMeta . version }` , url : type === "SNAPSHOT" ? snapshotRoot : releaseRoot , } , ... versionMeta . libraries . map ( processLibraries ) , ] ; const mainClass = "net.minecraft.launchwrapper.Launch" ; const inheritsFrom = mountedJSON . id ; const jar = mountedJSON . jar || mountedJSON . id ; const info = { id , time , releaseTime , type , libraries , mainClass , inheritsFrom , jar , } ; if ( mountedJSON . arguments ) { info . arguments = { game : [ "--tweakClass" , versionMeta . tweakClass ] , jvm : [ ] , } ; } else { info . minecraftArguments = `--tweakClass ${ versionMeta . tweakClass } ` + mountedJSON . minecraftArguments ; } return info ; } tasks param versionMeta param location param version export function installLiteloaderTask ( versionMeta , location , options = { } ) { return task ( "installLiteloader" , async function installLiteloader ( ) { const mc = MinecraftFolder . from ( location ) ; const mountVersion = options . inheritsFrom || versionMeta . mcversion ; const mountedJSON = await this . yield ( task ( "resolveVersionJson" , async function resolveVersionJson ( ) { if ( await missing ( mc . getVersionJson ( mountVersion ) ) ) { throw new MissingVersionJsonError ( mountVersion , mc . getVersionJson ( mountVersion ) ) ; } return readFile ( mc . getVersionJson ( mountVersion ) ) . then ( ( b ) => b . toString ( ) ) . then ( JSON . parse ) ; } ) ) ; const versionInf = await this . yield ( task ( "generateLiteloaderJson" , async function generateLiteloaderJson ( ) { const inf = buildVersionInfo ( versionMeta , mountedJSON ) ; inf . id = options . versionId || inf . id ; inf . inheritsFrom = options . inheritsFrom || inf . inheritsFrom ; const versionPath = mc . getVersionRoot ( inf . id ) ; await ensureDir ( versionPath ) ; await writeFile ( join ( versionPath , inf . id + ".json" ) , JSON . stringify ( inf , undefined , 4 ) ) ; return inf ; } ) ) ; return versionInf . id as string ; } ) ; }