minecraft data raw code
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
const fs = require('fs')
|
||||
const github = require('gh-helpers')()
|
||||
const { join } = require('path')
|
||||
const { extractPcEntityMetadata } = require('../../tools/js/extractPcEntityMetadata')
|
||||
const { exec, createInitialPR } = require('./utils')
|
||||
|
||||
const artifactsDir = join(__dirname, './artifacts')
|
||||
const root = join(__dirname, '..', '..')
|
||||
|
||||
async function handle (ourPR, genPullNo, version, artifactURL, shouldPull) {
|
||||
const branchNameVersion = version.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase()
|
||||
const branch = ourPR.headBranch || `pc-${branchNameVersion}`
|
||||
if (shouldPull) exec('git', ['pull', 'origin'])
|
||||
|
||||
// if external PR:
|
||||
// const branch = ourPR.headBranch
|
||||
// exec('git', ['remote', 'add', 'fo', ourPR.headCloneURL])
|
||||
// exec('git', ['fetch', 'fo', branch])
|
||||
// exec('git', ['checkout', '-b', branch, `fo/` + branch])
|
||||
|
||||
try {
|
||||
exec('git', ['checkout', branch])
|
||||
} catch (err) {
|
||||
console.error('Error checking out branch:', err)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const dataPaths = require('../../data/dataPaths.json')
|
||||
const dataPath = dataPaths.pc[version]
|
||||
|
||||
const destDir = join(root, `./data/pc/${version}`)
|
||||
if (!fs.existsSync(destDir) || !dataPath) {
|
||||
console.warn(`⚠️ Version ${version} not found (checked ${destDir}) ; cannot continue.`, fs.existsSync(destDir), dataPath)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (ourPR.body) {
|
||||
await github.updateIssue(ourPR.number, {
|
||||
body: ourPR.body.replace('<!--minecraft-data-generator-placeholder-->', `- https://github.com/PrismarineJS/minecraft-data-generator/pull/${genPullNo}`)
|
||||
})
|
||||
}
|
||||
|
||||
console.log('Handling PR:', ourPR)
|
||||
|
||||
fs.mkdirSync(artifactsDir, { recursive: true })
|
||||
|
||||
// https://github.com/PrismarineJS/minecraft-data-generator/actions/runs/17261281146/artifacts/3861320839
|
||||
const s = artifactURL.split('github.com/')[1]
|
||||
const [ownerName, repoName, _actions, _runs, _runId, _artifacts, artifactId] = s.split('/') // eslint-disable-line
|
||||
console.log('Downloading artifacts', { ownerName, repoName, artifactId, artifactsDir })
|
||||
await github.artifacts.downloadIdFrom(ownerName, repoName, artifactId, artifactsDir)
|
||||
|
||||
console.log(fs.readdirSync(artifactsDir))
|
||||
|
||||
// Now copy artifacts/${version}/*.json to data/pc/$version/*.json
|
||||
const versionArtifactsDir = join(artifactsDir, version)
|
||||
for (const file of fs.readdirSync(versionArtifactsDir)) {
|
||||
if (file.endsWith('.json')) {
|
||||
const src = join(versionArtifactsDir, file)
|
||||
const dest = join(destDir, file)
|
||||
fs.mkdirSync(destDir, { recursive: true })
|
||||
console.log(`copy ${src} => ${dest}`)
|
||||
fs.copyFileSync(src, dest)
|
||||
dataPath[file.replace('.json', '')] = 'pc/' + version
|
||||
}
|
||||
}
|
||||
|
||||
// Commit the new dataPath
|
||||
fs.writeFileSync(join(root, 'data', 'dataPaths.json'), JSON.stringify(dataPaths, null, 2))
|
||||
|
||||
try {
|
||||
process.chdir(join(__dirname, '../../tools/js'))
|
||||
extractPcEntityMetadata(version, version, { write: true, cloneIfMissing: true })
|
||||
} catch (e) {
|
||||
console.log('Failed to extract PC entity metadata', e)
|
||||
}
|
||||
|
||||
// Now, we need to commit the changes
|
||||
exec('git', ['config', 'user.name', 'github-actions[bot]'])
|
||||
exec('git', ['config', 'user.email', '41898282+github-actions[bot]@users.noreply.github.com'])
|
||||
exec('git', ['add', '--all'])
|
||||
exec('git', ['commit', '-m', `[Auto] Apply generated data from PrismarineJS/minecraft-data-generator#${genPullNo}`])
|
||||
exec('git', ['push', 'origin', branch])
|
||||
}
|
||||
|
||||
async function main (versions, genPullNo, artifactUrl, createPR) {
|
||||
const version = versions.at(-1)
|
||||
const pr = await github.findPullRequest({ titleIncludes: '🎈', author: null })
|
||||
console.log('Found PR', pr)
|
||||
if (pr && pr.isOpen) {
|
||||
const details = await github.getPullRequest(pr.id)
|
||||
console.log('PR', details)
|
||||
await handle(details, genPullNo, version, artifactUrl, true)
|
||||
} else if (createPR) {
|
||||
const pr = await createInitialPR('pc', '(This issue was created for a minecraft-data-generator PR)', {
|
||||
version,
|
||||
protocolVersion: null
|
||||
})
|
||||
console.log('Created PR', pr)
|
||||
const details = await github.getPullRequest(pr.number)
|
||||
console.log('PR', details)
|
||||
await handle(details, genPullNo, version, artifactUrl, false)
|
||||
} else {
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
main(
|
||||
JSON.parse(process.env.TRIGGER_MC_VERSIONS),
|
||||
process.env.TRIGGER_PR_NO,
|
||||
process.env.TRIGGER_ARTIFACT_URL,
|
||||
process.env.CREATE_PR_IF_NONE
|
||||
)
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
/* 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")
|
||||
<table>
|
||||
<tr><td><b>Name</b></td><td>${name}</td>
|
||||
<tr><td><b>Protocol ID</b></td><td>${protocolVersion}</td>
|
||||
<tr><td><b>Release Date</b></td><td>${date}</td>
|
||||
<tr><td><b>Release Type</b></td><td>${result.type}</td>
|
||||
<tr><td><b>Data Version</b></td><td>${jarData?.world_version}</td>
|
||||
<tr><td><b>Java Version</b></td><td>${jarData?.java_version}</td>
|
||||
</table>
|
||||
|
||||
<hr/>
|
||||
🤖 I am a bot, I check for updates every 2 hours without a trigger. You can close this issue to prevent any further updates.
|
||||
<!-- RP: ${JSON.stringify({ title, versionJson: jarData, latestVersionData: result, latestVersion: result.id })} -->
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
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-generator to handle new update
|
||||
const dispatchPayload = {
|
||||
owner: 'PrismarineJS',
|
||||
repo: 'minecraft-data-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 }
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"scripts": {
|
||||
"fix": "standard --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"gh-helpers": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"standard": "^17.1.2"
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
const cp = require('child_process')
|
||||
const github = require('gh-helpers')()
|
||||
const path = require('path')
|
||||
|
||||
const pm = process.versions.bun ? process.execPath : 'npm'
|
||||
|
||||
function exec (file, args = [], options = {}) {
|
||||
const opts = { stdio: ['inherit', 'inherit', 'inherit'], ...options }
|
||||
console.log('> ', file, args.join(' '), options.cwd ? `(cwd: ${options.cwd})` : '')
|
||||
return github.mock ? undefined : cp.execFileSync(file, args, opts)
|
||||
}
|
||||
|
||||
const toolsJs = path.join(__dirname, '..', '..', 'tools', 'js')
|
||||
const sanitizeBranch = (branchName) => branchName.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase()
|
||||
|
||||
async function createInitialPR (edition, issueUrl, { version, protocolVersion }) {
|
||||
exec(pm, ['install'], { cwd: toolsJs })
|
||||
if (protocolVersion) exec(pm, ['run', 'version', edition, version, protocolVersion], { cwd: toolsJs })
|
||||
exec(pm, ['run', 'build'], { cwd: toolsJs })
|
||||
const branchNameVersion = sanitizeBranch(version)
|
||||
const branchName = `${edition}_${branchNameVersion}`
|
||||
const title = `🎈 Add Minecraft ${edition} ${version} data`
|
||||
// First, delete any existing branch
|
||||
try {
|
||||
exec('git', ['branch', '-D', branchName])
|
||||
} catch (e) {
|
||||
// Branch doesn't exist, ignore error
|
||||
}
|
||||
exec('git', ['checkout', '-b', branchName])
|
||||
exec('git', ['config', 'user.name', 'github-actions[bot]'])
|
||||
exec('git', ['config', 'user.email', '41898282+github-actions[bot]@users.noreply.github.com'])
|
||||
exec('git', ['add', '--all'])
|
||||
exec('git', ['commit', '--allow-empty', '-m', title])
|
||||
exec('git', ['push', 'origin', branchName, '--force'])
|
||||
const body = `
|
||||
This automated PR sets up the relevant boilerplate for Minecraft ${edition} version ${version}. Fixes ${issueUrl}.
|
||||
|
||||
Related:
|
||||
- Issue: ${issueUrl}
|
||||
- Protocol Version: ${protocolVersion}
|
||||
<!--minecraft-data-generator-placeholder-->
|
||||
|
||||
* You can help contribute to this PR by opening a PR against this <code branch>${branchName}</code> branch instead of <code>master</code>.
|
||||
`
|
||||
const pr = await github.createPullRequest(title, body, branchName, 'master')
|
||||
pr.branchName = branchName
|
||||
return pr
|
||||
}
|
||||
|
||||
module.exports = { createInitialPR, exec }
|
||||
Reference in New Issue
Block a user