nmdk
Version:
CLI tool for downloading and setting up Minecraft mod development kits (MDK) for Forge, Fabric, and NeoForge
148 lines (117 loc) • 4.96 kB
JavaScript
const axios = require('axios');
const path = require('path');
const fs = require('fs-extra');
const { downloadFileFromUrl } = require('../utils/download');
const { extractProjectArchive, reorganizeProjectStructure } = require('../utils/extract');
const { sanitizeGradleConfigurationFiles, configureFabricModMetadata, executeGradleBuildCommands } = require('../utils/gradle');
const ora = require('ora');
const chalk = require('chalk');
async function resolveFabricMDKDownloadUrl(mcVersion, fabricVersion) {
const spinner = ora('Resolving Fabric MDK download URL').start();
try {
try {
const response = await axios.get(`https://api.github.com/repos/FabricMC/fabric-example-mod/releases/latest`);
const release = response.data;
const mdkAsset = release.assets.find(asset =>
asset.name.includes('mdk') && asset.name.includes(mcVersion)
);
if (mdkAsset) {
spinner.succeed(chalk.green('Fabric MDK URL resolved from GitHub'));
return mdkAsset.browser_download_url;
}
} catch (githubError) {
}
const baseUrl = 'https://github.com/FabricMC/fabric-example-mod/archive/refs/heads/';
const branchName = `${mcVersion}.x`;
const directUrl = `${baseUrl}${branchName}.zip`;
try {
const response = await axios.head(directUrl);
if (response.status === 200) {
spinner.succeed(chalk.green('Fabric MDK URL resolved from direct link'));
return directUrl;
}
} catch (directError) {
const alternativeBranches = [
`${mcVersion}`,
`1.${mcVersion.split('.')[1]}.x`,
'main',
'master'
];
for (const branch of alternativeBranches) {
const altUrl = `${baseUrl}${branch}.zip`;
try {
const altResponse = await axios.head(altUrl);
if (altResponse.status === 200) {
spinner.succeed(chalk.green(`Fabric MDK URL resolved from branch: ${branch}`));
return altUrl;
}
} catch (altError) {
continue;
}
}
}
throw new Error(`No Fabric MDK found for MC ${mcVersion}`);
} catch (error) {
spinner.fail('Failed to get Fabric MDK URL');
throw new Error(`Failed to get Fabric MDK URL: ${error.message}`);
}
}
async function initializeFabricProject(modName, mcVersion, fabricVersion, projectPath, modConfig) {
const spinner = ora('Initializing Fabric project').start();
try {
const mdkUrl = await resolveFabricMDKDownloadUrl(mcVersion, fabricVersion);
const archivePath = path.join(projectPath, 'fabric-mdk.zip');
await downloadFileFromUrl(mdkUrl, archivePath);
const tempExtractPath = path.join(projectPath, 'temp-extract');
await extractProjectArchive(archivePath, tempExtractPath);
await reorganizeProjectStructure(tempExtractPath, projectPath);
try {
await fs.remove(tempExtractPath);
} catch (error) {
console.warn('Warning: Could not remove temp extract directory:', error.message);
}
try {
await fs.remove(archivePath);
} catch (error) {
console.warn('Warning: Could not remove archive file:', error.message);
}
await sanitizeGradleConfigurationFiles(projectPath);
await configureFabricModMetadata(projectPath, modConfig);
await configureFabricModJsonFile(projectPath, modConfig, mcVersion, fabricVersion);
spinner.succeed(chalk.green('Fabric project initialized'));
} catch (error) {
spinner.fail('Failed to setup Fabric project');
throw new Error(`Failed to setup Fabric project: ${error.message}`);
}
}
async function configureFabricModJsonFile(projectPath, modConfig, mcVersion, fabricVersion) {
const fabricModJsonPath = path.join(projectPath, 'src/main/resources/fabric.mod.json');
if (await fs.pathExists(fabricModJsonPath)) {
let content = await fs.readFile(fabricModJsonPath, 'utf8');
const fabricMod = JSON.parse(content);
fabricMod.id = modConfig.modId;
fabricMod.name = modConfig.modName;
fabricMod.description = modConfig.description;
fabricMod.version = modConfig.version;
fabricMod.authors = [modConfig.author];
fabricMod.depends = {
"fabricloader": `>=${fabricVersion}`,
"minecraft": `~${mcVersion}`,
"java": ">=17"
};
await fs.writeFile(fabricModJsonPath, JSON.stringify(fabricMod, null, 2));
}
}
async function executeFabricGradleCommands(projectPath, options = []) {
const commands = [];
if (options.includes('build')) {
commands.push('./gradlew build');
}
if (commands.length > 0) {
await executeGradleBuildCommands(projectPath, commands);
}
}
module.exports = {
initializeFabricProject,
executeFabricGradleCommands
};