Skip to content

Instantly share code, notes, and snippets.

@HAHALOSAH
Last active January 23, 2022 05:00
Show Gist options
  • Save HAHALOSAH/c190816425f19c378cfef07875021015 to your computer and use it in GitHub Desktop.
Save HAHALOSAH/c190816425f19c378cfef07875021015 to your computer and use it in GitHub Desktop.
Node.JS script for downloading minecraft assets
// downloadMinecraftAssets.js by HAHALOSAH
//
// Usage: node downloadMinecraftAssets.js <version>
//
// Sorry for the messy code, I made this in 10 minutes
// Requires node-fetch, run `npm i node-fetch' or `npm i -g node-fetch' first
// This script downloads assets for minecraft in the same format you would find in .minecraft/assets
// Defaults to latest version if not specified
const fs = require("fs");
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
(async function() {
async function download(url) {
var req = await fetch(url);
var res = await req.text();
return res;
}
async function downloadBinary(url) {
var req = await fetch(url);
var res = await req.blob();
return res;
}
async function downloadJson(url) {
var req = await fetch(url);
var res = await req.json();
return res;
}
var VERSION_MANIFEST="https://launchermeta.mojang.com/mc/game/version_manifest.json";
console.log("Downloading "+VERSION_MANIFEST);
var versions = await downloadJson(VERSION_MANIFEST);
var selectedVersion;
if (process.argv[2] == undefined) {
console.log("No version selected, defaulting to latest ("+versions.latest.release+")");
selectedVersion = versions.latest.release;
} else {
selectedVersion = process.argv[2];
}
var versionInfo = versions.versions.find(v=>v.id==selectedVersion);
if (versionInfo == undefined) {
console.log("ERROR! Version not found!");
process.exit(1);
}
console.log("Downloading "+versionInfo.url);
var version = await downloadJson(versionInfo.url);
console.log("Downloading "+version.assetIndex.url)
var assetIndex = await download(version.assetIndex.url);
//console.log(assetIndex)
if (!fs.existsSync("assets")){
fs.mkdirSync("assets");
}
if (!fs.existsSync("assets/indexes")){
fs.mkdirSync("assets/indexes");
}
if (!fs.existsSync("assets/objects")){
fs.mkdirSync("assets/objects");
}
fs.writeFileSync("assets/indexes/"+version.assetIndex.url.split("/").reverse()[0], assetIndex);
function showPercentage(progress) {
var columns = process.stdout.columns;
var output = "["+("#".repeat(Math.round((columns-7)*progress)))+(".".repeat((columns-7)-Math.round((columns-7)*progress)))+"] "+Math.round(progress*100)+"%";
process.stdout.write("\x1b[2K\r"+output);
}
function log(msg) {
console.log("\x1b[2K\r"+msg);
}
assetIndex = JSON.parse(assetIndex);
var keys = Object.keys(assetIndex.objects);
var completed = 0;
showPercentage(completed/keys.length);
async function downloadAsset(name, hash) {
var url = `http://resources.download.minecraft.net/${hash.substring(0,2)}/${hash}`;
log("Downloading asset "+name+": "+url);
showPercentage(completed/keys.length);
var blob = await downloadBinary(url);
if (!fs.existsSync("assets/objects/"+hash.substring(0,2))){
fs.mkdirSync("assets/objects/"+hash.substring(0,2));
}
fs.writeFileSync("assets/objects/"+hash.substring(0,2)+"/"+hash, Buffer.from(await blob.arrayBuffer()));
log("Downloaded asset "+name);
completed += 1;
showPercentage(completed/keys.length);
}
var p = [];
keys.forEach(k=>p.push(downloadAsset(k,assetIndex.objects[k].hash)));
await Promise.all(p);
log("\nSaved assets to ./assets for version "+selectedVersion);
})();
@HAHALOSAH
Copy link
Author

Updated for the node-fetch update

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment