download minecraft-data on demand

This commit is contained in:
Vitaly 2023-09-02 03:34:50 +03:00
commit ac0170b146
5 changed files with 137 additions and 22 deletions

View file

@ -3,9 +3,9 @@
"version": "1.5.0",
"description": "A minecraft client running in a browser",
"scripts": {
"start": "node scripts/build.js copyFilesDev && node esbuild.mjs --minify --watch",
"start": "node scripts/build.js copyFilesDev && node scripts/prepareData.mjs && node esbuild.mjs --minify --watch",
"start-watch-script": "nodemon -w esbuild.mjs esbuild.mjs",
"build": "node scripts/build.js copyFiles && node esbuild.mjs --minify --prod",
"build": "node scripts/build.js copyFiles && node scripts/prepareData.mjs && node esbuild.mjs --minify --prod",
"watch": "node scripts/build.js copyFilesDev && webpack serve --config webpack.dev.js --progress",
"test:cypress": "cypress run",
"test:e2e": "start-test http-get://localhost:8080 test:cypress",
@ -32,6 +32,7 @@
"compression": "^1.7.4",
"cypress-plugin-snapshots": "^1.4.4",
"diamond-square": "^1.2.0",
"eruda": "^3.0.1",
"esbuild": "^0.19.2",
"esbuild-loader": "^4.0.0",
"esbuild-plugin-polyfill-node": "^0.3.0",
@ -73,6 +74,7 @@
"https-browserify": "^1.0.0",
"lodash-webpack-plugin": "^0.11.6",
"memfs": "^3.5.3",
"minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next",
"mineflayer": "github:zardoy/mineflayer#custom",
"mineflayer-pathfinder": "^2.4.4",
"npm-run-all": "^4.1.5",
@ -92,8 +94,7 @@
"webpack-dev-middleware": "^6.1.1",
"webpack-dev-server": "^4.15.1",
"webpack-merge": "^5.9.0",
"workbox-webpack-plugin": "^6.6.0",
"minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next"
"workbox-webpack-plugin": "^6.6.0"
},
"pnpm": {
"overrides": {

View file

@ -20,24 +20,24 @@ const plugins = [
path: (await build.resolve('minecraft-protocol/src/index.js', { kind, resolveDir })).path,
}
})
// build.onResolve({
// filter: /^\.\/data.js$/,
// }, ({ resolveDir, path }) => {
// if (!resolveDir.endsWith('minecraft-data')) return
// return {
// namespace: 'load-global-minecraft-data',
// path
// }
// })
// build.onLoad({
// filter: /.+/,
// namespace: 'load-global-minecraft-data',
// }, () => {
// return {
// contents: 'module.exports = window.minecraftData',
// loader: 'js',
// }
// })
build.onResolve({
filter: /^\.\/data.js$/,
}, ({ resolveDir, path }) => {
if (!resolveDir.endsWith('minecraft-data')) return
return {
namespace: 'load-global-minecraft-data',
path
}
})
build.onLoad({
filter: /.+/,
namespace: 'load-global-minecraft-data',
}, () => {
return {
contents: 'window.mcData ??= {};module.exports = { pc: window.mcData }',
loader: 'js',
}
})
// build.onResolve({
// filter: /^minecraft-assets$/,
// }, ({ resolveDir, path }) => {
@ -89,6 +89,7 @@ const plugins = [
filter: /.*/,
namespace: customMcDataNs,
}, async ({ path, ...rest }) => {
throw new Error('unreachable')
const resolvedPath = await build.resolve('minecraft-data/minecraft-data/data/dataPaths.json', { kind: 'require-call', resolveDir: process.cwd() })
const dataPaths = JSON.parse(await fs.promises.readFile(resolvedPath.path, 'utf8'))

79
scripts/prepareData.mjs Normal file
View file

@ -0,0 +1,79 @@
//@ts-check
import { build } from 'esbuild'
import Module from "node:module"
import { dirname } from 'node:path'
const require = Module.createRequire(import.meta.url)
const dataPaths = require('minecraft-data/minecraft-data/data/dataPaths.json')
function toMajor (version) {
const [a, b] = (version + '').split('.')
return `${a}.${b}`
}
const ignoredVersionsRegex = /(^0\.30c$)|w|-pre|-rc/
const grouped = {}
for (const [version, data] of Object.entries(dataPaths.pc)) {
if (ignoredVersionsRegex.test(version)) continue
const major = toMajor(version)
grouped[major] ??= {}
grouped[major][version] = data
}
console.log('preparing data')
for (const [major, versions] of Object.entries(grouped)) {
let contents = 'Object.assign(window.mcData, {\n'
for (const [version, dataSet] of Object.entries(versions)) {
contents += ` '${version}': {\n`
for (const [dataType, dataPath] of Object.entries(dataSet)) {
const loc = `minecraft-data/data/${dataPath}/`
contents += ` get ${dataType} () { return require("./${loc}${dataType}.json") },\n`
}
contents += ' },\n'
}
contents += '})'
build({
bundle: true,
outfile: `dist/mc-data/${major}.js`,
// entryPoints: ['mcData.js'],
stdin: {
contents,
resolveDir: dirname(require.resolve('minecraft-data')),
sourcefile: `mcData${major}.js`,
loader: 'js',
},
plugins: [
// {
// name: 'mcData',
// setup (build) {
// build.onResolve({
// filter: /^mcData\.js$/,
// }, ({ path, pluginData }) => {
// return {
// path,
// namespace: 'mc-data',
// }
// })
// build.onLoad({
// filter: /.*/,
// namespace: 'mc-data',
// }, ({ namespace, path }) => {
// const version = path.split('/')[2]
// const data = versions[version]
// if (!data) throw new Error(`No data for ${version}`)
// return {
// contents: `export const data = ${JSON.stringify(data, null, 2)}`,
// loader: 'js',
// }
// })
// }
// }
],
})
}
console.log('data prepared')

View file

@ -366,6 +366,13 @@ async function connect (connectOptions) {
})
let singlePlayerServer
try {
Object.assign(serverOptions, _.defaultsDeep({}, connectOptions.serverOverrides, options.localServerOptions, serverOptions))
let version = connectOptions.botVersion ?? serverOptions.version
if (version) {
setLoadingScreenStatus(`Downloading data for ${version}`)
await loadScript(`./mc-data/${toMajorVersion(version)}.js`)
}
if (singeplayer) {
window.serverDataChannel ??= {}
window.worldLoaded = false

View file

@ -132,3 +132,30 @@ function javaUUID (s) {
export function nameToMcOfflineUUID (name) {
return (new UUID(javaUUID('OfflinePlayer:' + name))).toString()
}
export const loadScript = async function (/** @type {string} */ scriptSrc) {
if (document.querySelector(`script[src="${scriptSrc}"]`)) {
return
}
return new Promise((resolve, reject) => {
const scriptElement = document.createElement('script')
scriptElement.src = scriptSrc
scriptElement.async = true
scriptElement.onload = () => {
resolve(scriptElement)
}
scriptElement.onerror = (error) => {
reject(error)
}
document.head.appendChild(scriptElement)
})
}
// doesn't support snapshots
export const toMajorVersion = (version) => {
const [a, b] = (version + '').split('.')
return `${a}.${b}`
}