Skip to content

Commit af52a00

Browse files
authored
Merge branch 'main' into bump
2 parents 6732bf1 + 4931a8d commit af52a00

File tree

7 files changed

+258
-5
lines changed

7 files changed

+258
-5
lines changed

.github/AGENTS.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
minecraft-data-generator extracts and generates Minecraft server-side data for multiple Minecraft versions via a Fabric mod that hooks into the vanilla Minecraft server.
2+
This generated data is then stored inside the https://github.com/PrismarineJS/minecraft-data repo, a cross language repo holding minecraft data on blocks, items and more.
3+
4+
There is a different mod for each Minecraft version this repo supports, under the `mc/<version>` folder.
5+
Each version has a Gradle project at `:mc:<version>` and generating the data is done by running the Gradle task:
6+
```
7+
./gradlew :mc:<version>:runServer
8+
```
9+
Generated data ends up under `mc/<version>/run/server/minecraft-data` in the repo when run locally.
10+
11+
## Repo Layout
12+
- mc/ — per-Minecraft-version directories of OUR extractor code (e.g. `mc/1.21.8`)
13+
- versions.json — canonical JSON array of versions that are supported (i.e. there are folders in mc/ for it)
14+
- mc-source/<version> — (External) minecraft java edition code for relevant version with Mojang mappings that you can reference for changes.
15+
* we store the last 2 most recent versions in the folder to save space, but if you need more versions you can do `cd mc-source/1.21.3 && git fetch origin client1.21.3 && git switch client1.21.3` (as these folders are a repo cloned with specific branches)
16+
* there is a .diff file in mc-source/ like `1.21.7_to_1.21.8.diff` that contains result of `git diff --no-index old new` that you can reference for changes (note it's typically large)
17+
* Since our generator is using Mojang mappings, the API naming is the same.
18+
- README.md — info how to set up
19+
20+
## Typical Flow
21+
22+
minecraft-data-generator typically needs updates every time there is a new Minecraft version, particularly if there was code changes
23+
around one of the areas that our extractors touches (e.g. an API changes, gets renamed, etc.).
24+
25+
As explained in the README.md, there is an auto update workflow that typically creates scaffolding PRs (under the `bump` branch) whenever there is a new minecraft update.
26+
These PRs are simply copying old version code into new, so there may be changes and other code fixes needed to support the new version. It's your
27+
job to help plug the gaps by making these changes until the build passes for the given version.
28+
It's also possible that there maybe missing or broken generated data even if the build is passing: in these cases, listen to the user's request
29+
and figure out how to replicate, debug and fix the logical issues in data generation.
30+
31+
## Troubleshooting
32+
33+
Simply iterating over errors one by one is a good way to fix most issues. Inside mc-source/ you are provided the latest
34+
code for the latest minecraft versions you can reference to investigate any code changes that we may need to accomodate in our
35+
generator code.
36+
37+
Sometimes, some APIs might change inside the mc code and make the data that the current code extracts no longer
38+
valid. In these cases, do your best to conform the new data to the old structure even if it feels wrong. If you
39+
can't, for example, let's say something about effects are removed from the game--but our data gen still expects it.
40+
What to do? You should set the data to null, and inform the user about the issue -- perhaps a schema change is needed.
41+
You can propose a new schema to the user (so that the relevant changes can be made to minecraft-data) and if the user confirms, you'd update the generator to output in that new schema.
42+
43+
### Steps
44+
- Reproduce the problem locally inside the container and run the generator task.
45+
- Example run command: `./gradlew :mc:1.21.6:runServer --stacktrace`
46+
- See if the problem exists on an older version -- if so inform the user, otherwise compare logs and code
47+
- Inspect diffs in `mc-source/` to correlate Mojang API changes.
48+
- See mc-source/
49+
- Validate generated output at `mc/<version>/run/server/minecraft-data` to make sure all files are there
50+
51+
---
52+
53+
## Examples
54+
55+
Session 1 — Compile error after bump PR
56+
- User prompt: "The bump PR for mc/1.21.8 fails to compile. Build error: cannot find symbol method RegistryKey.of(...)."
57+
- Agent actions:
58+
1. Reproduce: `./gradlew :mc:1.21.8:runServer --stacktrace`
59+
2. Inspect compile error and mc-source/1.21.7_to_1.21.8.diff for API renames.
60+
3. Update generator code: edit mc/1.21.8/src/main/java/.../SomeRegistryAdapter.java to use the new Registry API.
61+
4. Build again and run generation.
62+
63+
Session 2 — Runtime NPE during generation
64+
- User prompt: "Generation starts but crashes with NullPointerException in EnchantmentsDataGenerator."
65+
- Agent actions:
66+
1. Reproduce with stacktrace: `./gradlew :mc:1.20.4:runServer --stacktrace`
67+
2. Add temporary logging to EnchantmentsDataGenerator to identify the null object, or run in debugger.
68+
3. Fix by guarding against null Registries or empty lists and add defensive checks.
69+
4. Re-run generation and verify produced files.
70+
- If problem persists:
71+
* Add logging to old version too
72+
* Check relevant code diff to see if anything changed related to this
73+
74+
Session 3 — Semantically incorrect generated data
75+
- User prompt: "Output JSON is valid but item tags are incorrect after the bump."
76+
- Agent actions:
77+
1. Reproduce generation and open the produced JSON at mc/<version>/run/server/minecraft-data/tags/items.json
78+
2. Compare against previous version output (`git diff --no-index`) to identify mismatches.
79+
3. Inspect generator assumptions vs. mc-source diffs (names, tag keys, or logic changes).
80+
4. Correct mapping logic in generator class and run generation.

.github/commands/send.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = async ([mergedArtifactURL], helpers) => {
99
branch: 'master',
1010
inputs: {
1111
versions: JSON.stringify(require('../../versions.json')),
12-
mergedArtifactURL: mergedArtifactURL,
12+
mergedArtifactURL,
1313
prNumber: process.env.PR_NUMBER
1414
}
1515
}

.github/commands/setupCopilot.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* setupCopilot.js
3+
*
4+
* Reads versions from:
5+
* - versions.json at repo root (if present), else
6+
* - directories under mc/
7+
*
8+
* For each version it runs:
9+
* ./gradlew :mc:<version>:runServer --stacktrace
10+
*
11+
* Uses child_process.execSync(cmd, { stdio: 'inherit' }) so logs stream to the action console.
12+
* Errors are caught, logged, and the loop continues. At the end the script writes
13+
* success_versions and failed_versions to $GITHUB_OUTPUT (if available) for downstream steps.
14+
*
15+
* To force the action to fail if any version errors, set env FAIL_ON_ERROR=true in the workflow.
16+
*/
17+
18+
const cp = require('child_process')
19+
const fs = require('fs')
20+
const { join } = require('path')
21+
22+
const failOnError = process.env.FAIL_ON_ERROR === 'true'
23+
24+
// Save some time by skipping old versions as we are not parallelizing builds
25+
const versions = require('../../versions.json')
26+
const SKIP_VERSIONS = versions.slice(0, -2) // all but last 2 versions
27+
28+
async function main () {
29+
30+
if (!Array.isArray(versions) || versions.length === 0) {
31+
console.error('No versions found (no VERSION env, no versions.json, no mc/* directories).')
32+
process.exit(1)
33+
}
34+
35+
console.log('Versions to build:', versions.join(', '))
36+
37+
process.chdir(join(__dirname, '../../'))
38+
39+
const successes = []
40+
const failures = []
41+
42+
for (const v of versions) {
43+
if (SKIP_VERSIONS.includes(v)) {
44+
console.log(`Skipping old version ${v}...`)
45+
continue
46+
}
47+
console.log('')
48+
console.log('=== Building version:', v, '===')
49+
const cmd = `./gradlew :mc:${v}:runServer --stacktrace`
50+
try {
51+
// stream output to the runner logs
52+
cp.execSync(cmd, { stdio: 'inherit' })
53+
successes.push(v)
54+
console.log(`✅ ${v} succeeded`)
55+
} catch (err) {
56+
failures.push(v)
57+
console.error(`❌ ${v} failed (continuing to next version)`)
58+
// continue to next version
59+
}
60+
}
61+
62+
// Write outputs for downstream jobs, if GITHUB_OUTPUT available
63+
const ghOut = process.env.GITHUB_OUTPUT
64+
const latestVersion = versions[versions.length - 1]
65+
const secondLatestVersion = versions[versions.length - 2]
66+
if (ghOut) {
67+
try {
68+
fs.appendFileSync(ghOut, `success_versions=${JSON.stringify(successes)}\n`)
69+
fs.appendFileSync(ghOut, `failed_versions=${JSON.stringify(failures)}\n`)
70+
fs.appendFileSync(ghOut, `latest_version=${latestVersion}\n`)
71+
fs.appendFileSync(ghOut, `second_latest_version=${secondLatestVersion}\n`)
72+
} catch (e) {
73+
console.warn('Could not write to GITHUB_OUTPUT:', e && e.message)
74+
}
75+
} else {
76+
console.log('GITHUB_OUTPUT not found; printing summaries to stdout instead.')
77+
console.log('success_versions=', JSON.stringify(successes))
78+
console.log('failed_versions=', JSON.stringify(failures))
79+
console.log('latest_version=', JSON.stringify(latestVersion))
80+
console.log('second_latest_version=', JSON.stringify(secondLatestVersion))
81+
}
82+
83+
console.log('')
84+
console.log('Summary:')
85+
console.log(' succeeded:', JSON.stringify(successes))
86+
console.log(' failed: ', JSON.stringify(failures))
87+
88+
if (failOnError && failures.length > 0) {
89+
console.error('FAIL_ON_ERROR is true and some builds failed — exiting with non-zero code.')
90+
process.exit(1)
91+
}
92+
93+
// otherwise exit 0 so the workflow continues (Copilot can triage failures)
94+
process.exit(0)
95+
}
96+
97+
main()

.github/workflows/build.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ name: Java CI with Gradle
22
on:
33
push:
44
branches:
5-
- main
5+
- '**'
66
pull_request:
77
branches:
8-
- main
9-
- bump
8+
- '**'
109

1110
permissions:
1211
pull-requests: write
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/customize-the-agent-environment
2+
on:
3+
workflow_dispatch:
4+
push:
5+
paths:
6+
- .github/workflows/copilot-setup-steps.yml
7+
pull_request:
8+
paths:
9+
- .github/workflows/copilot-setup-steps.yml
10+
11+
jobs:
12+
copilot-setup-steps:
13+
name: Build and generate data (single-step loop via Node)
14+
runs-on: ubuntu-latest
15+
timeout-minutes: 20
16+
17+
# Set the permissions to the lowest permissions possible needed for your steps.
18+
# Copilot will be given its own token for its operations.
19+
permissions:
20+
# If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
21+
contents: write
22+
actions: write
23+
pull-requests: write
24+
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
29+
- name: Validate Gradle wrapper
30+
uses: gradle/actions/wrapper-validation@v4
31+
32+
- name: Set up JDK 21
33+
uses: actions/setup-java@v4
34+
with:
35+
java-version: '21'
36+
distribution: 'temurin'
37+
38+
- name: Setup Gradle
39+
uses: gradle/actions/setup-gradle@v4
40+
with:
41+
add-job-summary-as-pr-comment: on-failure
42+
43+
- name: Run Copilot setup script
44+
id: sb
45+
run: node .github/commands/setupCopilot.js
46+
shell: bash
47+
48+
- name: Checkout latest mc code (external repo)
49+
# If the external repo is public, the default token is fine.
50+
# If it's private, create a personal access token with repo access and add it
51+
# to this repo's secrets as EXTRA_REPO_TOKEN.
52+
uses: actions/checkout@v4
53+
with:
54+
repository: extremeheat/extracted_minecraft_data
55+
path: mc-source/${{ steps.sb.outputs.latest_version }}
56+
ref: client${{ steps.sb.outputs.latest_version }}
57+
fetch-depth: 1
58+
59+
- name: Checkout second latest mc code (external repo)
60+
# If the external repo is public, the default token is fine.
61+
# If it's private, create a personal access token with repo access and add it
62+
# to this repo's secrets as EXTRA_REPO_TOKEN.
63+
uses: actions/checkout@v4
64+
with:
65+
repository: extremeheat/extracted_minecraft_data
66+
path: mc-source/${{ steps.sb.outputs.second_latest_version }}
67+
ref: client${{ steps.sb.outputs.second_latest_version }}
68+
fetch-depth: 1
69+
70+
- run: ls mc-source
71+
72+
- name: Write diff
73+
# NOTE: this returns exit code 1 if there are differences
74+
run: git diff --no-index ${{ steps.sb.outputs.second_latest_version }} ${{ steps.sb.outputs.latest_version }} > ${{ steps.sb.outputs.second_latest_version }}_to_${{ steps.sb.outputs.latest_version }}.diff
75+
working-directory: mc-source
76+
continue-on-error: true

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ gradle-app.setting
118118
!gradle-wrapper.jar
119119

120120
bin/
121+
mc-source/
121122

122123
node_modules
123124
package-lock.json

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "This tool generates minecraft-data files based on a running a server on client classpath using a fabric mod. The supported versions can be read in the directory structure. Every version has its own directory.",
55
"main": "index.js",
66
"scripts": {
7-
"fix": "standard --fix",
7+
"fix": "standard --fix .github tools",
88
"bump": "node tools/newVersion.js"
99
},
1010
"author": "",

0 commit comments

Comments
 (0)