/* eslint-disable no-return-assign, no-sequences */ const fs = require('fs') const github = require('gh-helpers')() const pcManifestURL = 'https://launchermeta.mojang.com/mc/game/version_manifest.json' const changelogURL = 'https://feedback.minecraft.net/hc/en-us/sections/360001186971-Release-Changelogs' const { exec, createInitialPR } = require('./utils') const download = (url, dest) => exec('curl', ['-L', url, '-o', dest]) function buildFirstIssue (title, result, jarData) { const protocolVersion = jarData?.protocol_version || 'Failed to obtain from JAR' const name = jarData?.name || result.id const date = result.releaseTime return { title, body: ` A new Minecraft Java Edition version is available (as of ${date}), version **${result.id}** ## Official Changelog * ${changelogURL} ## Protocol Details (I will close this issue automatically if "${result.id}" is added to data/pc/common/versions.json on "master")
Name${name}
Protocol ID${protocolVersion}
Release Date${date}
Release Type${result.type}
Data Version${jarData?.world_version}
Java Version${jarData?.java_version}

🤖 I am a bot, I check for updates every 2 hours without a trigger. You can close this issue to prevent any further updates. ` } } const protocolVersions = { pc: require('../../data/pc/common/protocolVersions.json'), bedrock: require('../../data/bedrock/common/protocolVersions.json') } const supportedVersions = { pc: require('../../data/pc/common/versions.json'), bedrock: require('../../data/bedrock/common/versions.json') } async function updateManifestPC () { const manifest = await fetch(pcManifestURL).then(res => res.json()) // fs.writeFileSync('./manifest.json', JSON.stringify(manifest, null, 2)) const knownVersions = protocolVersions.pc.reduce((acc, cur) => (acc[cur.minecraftVersion] = cur, acc), {}) const latestVersion = manifest.latest.snapshot const latestReleaseVersion = manifest.latest.release const latestVersionData = manifest.versions.find(v => v.id === latestVersion) const latestVersionIsSnapshot = latestVersionData.type !== 'release' const title = `Support Minecraft PC ${latestReleaseVersion}` const issueStatus = await github.findIssue({ titleIncludes: title, author: null }) || {} console.log('issueStatus', issueStatus) if (issueStatus?.isOpen) { if (supportedVersions.pc.includes(latestReleaseVersion)) { // If the issue is open and the latest release version is supported, we can close the issue github.close(issueStatus.id, `Closing as PC ${latestReleaseVersion} is now supported`) return } } if (latestVersionIsSnapshot) { // don't make issues for snapshots if (supportedVersions.pc.includes(latestVersion) || knownVersions[latestVersion]) { console.log('Latest version is a known snapshot, no work to do') return } } else if (knownVersions[latestVersion]) { console.log(`Latest PC version ${latestVersion} is known in protocolVersions.json, but not in versions.json (protocol version ${knownVersions[latestVersion].version})`) return // We expect to have already handled this version. } else { console.log(`Latest PC version ${latestVersion} is not known in protocolVersions.json, adding and making issue`) } let versionJson try { versionJson = await addEntryFor(latestVersion, latestVersionData) } catch (e) { console.error(e) if (latestVersionIsSnapshot) { console.warn('Failed to update protocolVersions.json for the snapshot', latestVersion) } else { console.log('Latest PC version is not supported and we failed to load data. Opening issue...') const issuePayload = buildFirstIssue(title, latestVersionData) github.createIssue(issuePayload) fs.writeFileSync('./issue.md', issuePayload.body) console.log('OK, wrote to ./issue.md', issuePayload) } } if (!latestVersionIsSnapshot && !issueStatus.isOpen && !issueStatus.isClosed) { await openIssueAndDispatch(title, versionJson, latestVersionData, latestVersion) } async function addEntryFor (releaseVersion, releaseData) { const latestReleaseManifest = await fetch(releaseData.url).then(res => res.json()) // Download client jar if (!fs.existsSync(`./${releaseVersion}.jar`)) { const clientJarUrl = latestReleaseManifest.downloads.client.url console.log('Downloading client jar', clientJarUrl) download(clientJarUrl, `./${releaseVersion}.jar`) } // Log the byte size of the client jar const clientJarSize = fs.statSync(`./${releaseVersion}.jar`).size console.log(`Downloaded client jar ${releaseVersion}.jar (${clientJarSize} bytes), extracting its version.json...`) // unzip with tar / unzip, Actions image uses 7z if (process.platform === 'win32') exec('tar', ['-xf', `./${releaseVersion}.jar`, 'version.json']) else exec('7z', ['-y', 'e', `./${releaseVersion}.jar`, 'version.json']) const versionJson = require('./version.json') let majorVersion if (versionJson.id && versionJson.id.includes('.')) { majorVersion = versionJson.id.split('.', 2).join('.') } else { console.error(`Version '${versionJson.id}' appears to be a snapshot (no dot in name). Using the last known majorVersion in protocolVersions.json for this version (may be incorrect)`) majorVersion = protocolVersions.pc[0].majorVersion } const newEntry = { minecraftVersion: versionJson.id, version: versionJson.protocol_version, dataVersion: versionJson.world_version, usesNetty: true, majorVersion, releaseType: latestVersionData.type } console.log('Adding new entry to pc protocolVersions.json', newEntry) const updatedProtocolVersions = [newEntry, ...protocolVersions.pc] fs.writeFileSync('../../data/pc/common/protocolVersions.json', JSON.stringify(updatedProtocolVersions, null, 2)) if (process.env.CI) { console.log('Committing changes to protocolVersions.json') // https://github.com/actions/checkout/pull/1184 exec('git', ['config', 'user.name', 'github-actions[bot]']) exec('git', ['config', 'user.email', '41898282+github-actions[bot]@users.noreply.github.com']) exec('git', ['add', '../../data/pc/common/protocolVersions.json']) exec('git', ['commit', '-m', `Add ${versionJson.id} to pc protocolVersions.json`]) exec('git', ['push']) } return versionJson } } async function openIssueAndDispatch (title, versionJson, latestVersionData, latestVersion) { console.log('Opening issue', versionJson) const issuePayload = buildFirstIssue(title, latestVersionData, versionJson) const issue = await github.createIssue(issuePayload) console.log('Created issue', issue) // Now create an initial PR with the new version data const pr = await createInitialPR('pc', issue.url, { minecraftVersion: versionJson.id, version: latestVersion, protocolVersion: versionJson.protocol_version }) console.log('Created PR', pr) // Ask minecraft-data-proto_generator to handle new update const dispatchPayload = { owner: 'PrismarineJS', repo: 'minecraft-data-proto_generator', workflow: 'handle-mcdata-update.yml', branch: 'main', inputs: { version: latestVersion, issue_number: String(issue?.number), pr_number: String(pr?.number) } } console.log('Sending workflow dispatch', dispatchPayload) await github.sendWorkflowDispatch(dispatchPayload) // Ask node-minecraft-protocol to handle new update const nodeDispatchPayload = { owner: 'PrismarineJS', repo: 'node-minecraft-protocol', workflow: 'update-from-minecraft-data.yml', branch: 'master', inputs: { new_mc_version: latestVersion, mcdata_branch: pr.branchName, mcdata_pr_url: pr.url } } console.log('Sending workflow dispatch', nodeDispatchPayload) await github.sendWorkflowDispatch(nodeDispatchPayload) // node-minecraft-protocol would then dispatch to mineflayer return { issue, pr } } if (process.env.FORCE_CREATE_PR) { const payload = JSON.parse(process.env.FORCE_CREATE_PR) openIssueAndDispatch(payload.title, payload.versionJson, payload.latestVersionData, payload.latestVersion).then(() => { console.log('Done with manual PR') }).catch(err => { console.error('Failed to do manual PR', err) process.exit(1) }) } else { updateManifestPC() } module.exports = { openIssueAndDispatch, updateManifestPC }