diff --git a/README.md b/README.md index bf237ab..350452d 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ Options: * `--forge ` Specify forge version. This is WITHOUT the minecraft version (ex. 14.23.5.2847) * OPTIONAL (default: null) * If not provided forge will not be enabled. + * You can provide either `latest` or `recommended` to use the latest/recommended version of forge. * `--liteloader ` Specify liteloader version. * OPTIONAL (default: null) * If not provided liteloader will not be enabled. @@ -112,6 +113,23 @@ Options: > `generate distribution --root C:/TestRoot --baseUrl https://myhost.com` > +--- + +### Latest Forge + +Get the latest version of Forge. + +`latest-forge ` + +--- + +### Recommended Forge + +Get the recommended version of Forge. If no recommended build is available, it will pull the latest version. + +`recommended-forge ` + +--- ## File Structure Setup (Tentative) diff --git a/src/index.ts b/src/index.ts index 11a621a..c0bc1b0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ import yargs from 'yargs' import { DistributionStructure } from './model/struct/model/distribution.struct' import { ServerStructure } from './model/struct/model/server.struct' import { VersionSegmentedRegistry } from './util/VersionSegmentedRegistry' +import { VersionUtil } from './util/versionutil' dotenv.config() @@ -135,7 +136,7 @@ const generateServerCommand: yargs.CommandModule = { default: null }) }, - handler: (argv) => { + handler: async (argv) => { argv.root = getRoot() console.debug(`Root set to ${argv.root}`) @@ -143,6 +144,13 @@ const generateServerCommand: yargs.CommandModule = { `\n\t├ Forge version: ${argv.forge}`, `\n\t└ LiteLoader version: ${argv.liteloader}`) + if (VersionUtil.isPromotionVersion(argv.forge as string)) { + console.debug(`Resolving ${argv.forge} Forge Version..`) + const version = await VersionUtil.getPromotedForgeVersion(argv.version as string, argv.forge as string) + console.debug(`Forge version set to ${version}`) + argv.forge = version + } + const serverStruct = new ServerStructure(argv.root as string, getBaseURL()) serverStruct.createServer( argv.id as string, @@ -208,6 +216,42 @@ const validateCommand: yargs.CommandModule = { } } +const latestForgeCommand: yargs.CommandModule = { + command: 'latest-forge ', + describe: 'Get the latest version of forge.', + handler: async (argv) => { + console.debug(`Invoked latest-forge with version ${argv.version}.`) + + const forgeVer = await VersionUtil.getPromotedForgeVersion(argv.version as string, 'latest') + console.log(`Latest version: Forge ${forgeVer} (${argv.version})`) + } +} + +const recommendedForgeCommand: yargs.CommandModule = { + command: 'recommended-forge ', + describe: 'Get the recommended version of forge. Returns latest if there is no recommended build.', + handler: async (argv) => { + console.debug(`Invoked recommended-forge with version ${argv.version}.`) + + const index = await VersionUtil.getPromotionIndex() + const mcVer = argv.version as string + + let forgeVer = VersionUtil.getPromotedVersionStrict(index, mcVer, 'recommended') + if (forgeVer != null) { + console.log(`Recommended version: Forge ${forgeVer} (${mcVer})`) + } else { + console.log(`No recommended build for ${mcVer}. Checking for latest version..`) + forgeVer = VersionUtil.getPromotedVersionStrict(index, mcVer, 'latest') + if (forgeVer != null) { + console.log(`Latest version: Forge ${forgeVer} (${mcVer})`) + } else { + console.log(`No build available for ${mcVer}.`) + } + } + + } +} + const testCommand: yargs.CommandModule = { command: 'test ', describe: 'Validate a distribution.json against the spec.', @@ -234,6 +278,8 @@ yargs .command(initCommand) .command(generateCommand) .command(validateCommand) +.command(latestForgeCommand) +.command(recommendedForgeCommand) .command(testCommand) .demandCommand() .help() diff --git a/src/model/forge/promotionsslim.ts b/src/model/forge/promotionsslim.ts new file mode 100644 index 0000000..7a835b6 --- /dev/null +++ b/src/model/forge/promotionsslim.ts @@ -0,0 +1,8 @@ +export interface PromotionsSlim { + + homepage: string + promos: { + [id: string]: string + } + +} diff --git a/src/util/versionutil.ts b/src/util/versionutil.ts index b2b0353..8124b0f 100644 --- a/src/util/versionutil.ts +++ b/src/util/versionutil.ts @@ -1,5 +1,13 @@ +import Axios from 'axios' +import { PromotionsSlim } from '../model/forge/promotionsslim' + export class VersionUtil { + public static readonly PROMOTION_TYPE = [ + 'recommended', + 'latest' + ] + public static readonly MINECRAFT_VERSION_REGEX = /(\d+).(\d+).(\d+)/ public static isMinecraftVersion(version: string) { @@ -28,4 +36,37 @@ export class VersionUtil { return false } + public static isPromotionVersion(version: string) { + return VersionUtil.PROMOTION_TYPE.indexOf(version.toLowerCase()) > -1 + } + + public static async getPromotionIndex() { + const response = await Axios({ + method: 'get', + url: 'https://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json', + responseType: 'json' + }) + return response.data as PromotionsSlim + } + + public static getPromotedVersionStrict(index: PromotionsSlim, minecraftVersion: string, promotion: string) { + const workingPromotion = promotion.toLowerCase() + return index.promos[`${minecraftVersion}-${workingPromotion}`] + } + + public static async getPromotedForgeVersion(minecraftVersion: string, promotion: string) { + const workingPromotion = promotion.toLowerCase() + const res = await VersionUtil.getPromotionIndex() + let version = res.promos[`${minecraftVersion}-${workingPromotion}`] + if (version == null) { + console.warn(`No ${workingPromotion} version found for Forge ${minecraftVersion}.`) + console.warn(`Attempting to pull latest version instead.`) + version = res.promos[`${minecraftVersion}-latest`] + if (version == null) { + throw new Error(`No latest version found for Forge ${minecraftVersion}.`) + } + } + return version + } + }