Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,292 changes: 646 additions & 646 deletions data/bedrock/1.16.201/protocol.json

Large diffs are not rendered by default.

1,330 changes: 665 additions & 665 deletions data/bedrock/1.16.210/protocol.json

Large diffs are not rendered by default.

1,476 changes: 738 additions & 738 deletions data/bedrock/1.16.220/protocol.json

Large diffs are not rendered by default.

1,494 changes: 747 additions & 747 deletions data/bedrock/1.17.0/protocol.json

Large diffs are not rendered by default.

1,506 changes: 753 additions & 753 deletions data/bedrock/1.17.10/protocol.json

Large diffs are not rendered by default.

1,520 changes: 760 additions & 760 deletions data/bedrock/1.17.30/protocol.json

Large diffs are not rendered by default.

1,558 changes: 779 additions & 779 deletions data/bedrock/1.17.40/protocol.json

Large diffs are not rendered by default.

1,566 changes: 783 additions & 783 deletions data/bedrock/1.18.0/protocol.json

Large diffs are not rendered by default.

1,636 changes: 818 additions & 818 deletions data/bedrock/1.18.11/protocol.json

Large diffs are not rendered by default.

1,654 changes: 827 additions & 827 deletions data/bedrock/1.18.30/protocol.json

Large diffs are not rendered by default.

1,740 changes: 870 additions & 870 deletions data/bedrock/1.19.1/protocol.json

Large diffs are not rendered by default.

1,754 changes: 877 additions & 877 deletions data/bedrock/1.19.10/protocol.json

Large diffs are not rendered by default.

1,762 changes: 881 additions & 881 deletions data/bedrock/1.19.20/protocol.json

Large diffs are not rendered by default.

1,762 changes: 881 additions & 881 deletions data/bedrock/1.19.21/protocol.json

Large diffs are not rendered by default.

1,772 changes: 886 additions & 886 deletions data/bedrock/1.19.30/protocol.json

Large diffs are not rendered by default.

1,786 changes: 893 additions & 893 deletions data/bedrock/1.19.40/protocol.json

Large diffs are not rendered by default.

1,792 changes: 896 additions & 896 deletions data/bedrock/1.19.50/protocol.json

Large diffs are not rendered by default.

1,792 changes: 896 additions & 896 deletions data/bedrock/1.19.60/protocol.json

Large diffs are not rendered by default.

1,792 changes: 896 additions & 896 deletions data/bedrock/1.19.62/protocol.json

Large diffs are not rendered by default.

1,818 changes: 909 additions & 909 deletions data/bedrock/1.19.70/protocol.json

Large diffs are not rendered by default.

1,824 changes: 912 additions & 912 deletions data/bedrock/1.19.80/protocol.json

Large diffs are not rendered by default.

1,824 changes: 912 additions & 912 deletions data/bedrock/1.20.0/protocol.json

Large diffs are not rendered by default.

1,826 changes: 913 additions & 913 deletions data/bedrock/1.20.10/protocol.json

Large diffs are not rendered by default.

1,832 changes: 916 additions & 916 deletions data/bedrock/1.20.30/protocol.json

Large diffs are not rendered by default.

1,836 changes: 918 additions & 918 deletions data/bedrock/1.20.40/protocol.json

Large diffs are not rendered by default.

1,870 changes: 935 additions & 935 deletions data/bedrock/1.20.50/protocol.json

Large diffs are not rendered by default.

1,868 changes: 934 additions & 934 deletions data/bedrock/1.20.61/protocol.json

Large diffs are not rendered by default.

1,866 changes: 933 additions & 933 deletions data/bedrock/1.20.71/protocol.json

Large diffs are not rendered by default.

1,892 changes: 946 additions & 946 deletions data/bedrock/1.20.80/protocol.json

Large diffs are not rendered by default.

1,912 changes: 956 additions & 956 deletions data/bedrock/1.21.0/protocol.json

Large diffs are not rendered by default.

2,040 changes: 1,020 additions & 1,020 deletions data/bedrock/1.21.100/protocol.json

Large diffs are not rendered by default.

2,062 changes: 1,031 additions & 1,031 deletions data/bedrock/1.21.111/protocol.json

Large diffs are not rendered by default.

2,072 changes: 1,036 additions & 1,036 deletions data/bedrock/1.21.120/protocol.json

Large diffs are not rendered by default.

2,072 changes: 1,036 additions & 1,036 deletions data/bedrock/1.21.124/protocol.json

Large diffs are not rendered by default.

2,184 changes: 1,092 additions & 1,092 deletions data/bedrock/1.21.130/protocol.json

Large diffs are not rendered by default.

1,912 changes: 956 additions & 956 deletions data/bedrock/1.21.2/protocol.json

Large diffs are not rendered by default.

1,934 changes: 967 additions & 967 deletions data/bedrock/1.21.20/protocol.json

Large diffs are not rendered by default.

1,938 changes: 969 additions & 969 deletions data/bedrock/1.21.30/protocol.json

Large diffs are not rendered by default.

1,962 changes: 981 additions & 981 deletions data/bedrock/1.21.42/protocol.json

Large diffs are not rendered by default.

1,986 changes: 993 additions & 993 deletions data/bedrock/1.21.50/protocol.json

Large diffs are not rendered by default.

2,000 changes: 1,000 additions & 1,000 deletions data/bedrock/1.21.60/protocol.json

Large diffs are not rendered by default.

2,020 changes: 1,010 additions & 1,010 deletions data/bedrock/1.21.70/protocol.json

Large diffs are not rendered by default.

2,040 changes: 1,020 additions & 1,020 deletions data/bedrock/1.21.80/protocol.json

Large diffs are not rendered by default.

2,040 changes: 1,020 additions & 1,020 deletions data/bedrock/1.21.90/protocol.json

Large diffs are not rendered by default.

2,040 changes: 1,020 additions & 1,020 deletions data/bedrock/1.21.93/protocol.json

Large diffs are not rendered by default.

2,132 changes: 1,066 additions & 1,066 deletions data/bedrock/1.26.0/protocol.json

Large diffs are not rendered by default.

2,302 changes: 1,151 additions & 1,151 deletions data/bedrock/1.26.10/protocol.json

Large diffs are not rendered by default.

2,336 changes: 1,168 additions & 1,168 deletions data/bedrock/1.26.20/protocol.json

Large diffs are not rendered by default.

2,304 changes: 1,152 additions & 1,152 deletions data/bedrock/1.26.30/protocol.json

Large diffs are not rendered by default.

1,988 changes: 994 additions & 994 deletions data/bedrock/1.26.40/protocol.json

Large diffs are not rendered by default.

338 changes: 169 additions & 169 deletions data/pc/0.30c/protocol.json

Large diffs are not rendered by default.

1,091 changes: 2 additions & 1,089 deletions data/pc/1.10-pre1/proto.yml

Large diffs are not rendered by default.

3,450 changes: 1,725 additions & 1,725 deletions data/pc/1.10-pre1/protocol.json

Large diffs are not rendered by default.

1,063 changes: 1 addition & 1,062 deletions data/pc/1.10/proto.yml

Large diffs are not rendered by default.

3,450 changes: 1,725 additions & 1,725 deletions data/pc/1.10/protocol.json

Large diffs are not rendered by default.

1,045 changes: 4 additions & 1,041 deletions data/pc/1.11/proto.yml

Large diffs are not rendered by default.

3,450 changes: 1,725 additions & 1,725 deletions data/pc/1.11/protocol.json

Large diffs are not rendered by default.

916 changes: 11 additions & 905 deletions data/pc/1.12-pre4/proto.yml

Large diffs are not rendered by default.

3,762 changes: 1,881 additions & 1,881 deletions data/pc/1.12-pre4/protocol.json

Large diffs are not rendered by default.

961 changes: 9 additions & 952 deletions data/pc/1.12.1/proto.yml

Large diffs are not rendered by default.

3,876 changes: 1,938 additions & 1,938 deletions data/pc/1.12.1/protocol.json

Large diffs are not rendered by default.

1,161 changes: 4 additions & 1,157 deletions data/pc/1.12.2/proto.yml

Large diffs are not rendered by default.

3,876 changes: 1,938 additions & 1,938 deletions data/pc/1.12.2/protocol.json

Large diffs are not rendered by default.

916 changes: 17 additions & 899 deletions data/pc/1.12/proto.yml

Large diffs are not rendered by default.

3,822 changes: 1,911 additions & 1,911 deletions data/pc/1.12/protocol.json

Large diffs are not rendered by default.

1,590 changes: 2 additions & 1,588 deletions data/pc/1.13.1/proto.yml

Large diffs are not rendered by default.

5,210 changes: 2,605 additions & 2,605 deletions data/pc/1.13.1/protocol.json

Large diffs are not rendered by default.

1,583 changes: 4 additions & 1,579 deletions data/pc/1.13.2-pre1/proto.yml

Large diffs are not rendered by default.

5,234 changes: 2,617 additions & 2,617 deletions data/pc/1.13.2-pre1/protocol.json

Large diffs are not rendered by default.

5,234 changes: 2,617 additions & 2,617 deletions data/pc/1.13.2-pre2/protocol.json

Large diffs are not rendered by default.

1,589 changes: 2 additions & 1,587 deletions data/pc/1.13.2/proto.yml

Large diffs are not rendered by default.

5,200 changes: 2,600 additions & 2,600 deletions data/pc/1.13.2/protocol.json

Large diffs are not rendered by default.

870 changes: 87 additions & 783 deletions data/pc/1.13/proto.yml

Large diffs are not rendered by default.

5,210 changes: 2,605 additions & 2,605 deletions data/pc/1.13/protocol.json

Large diffs are not rendered by default.

5,550 changes: 2,775 additions & 2,775 deletions data/pc/1.14.1/protocol.json

Large diffs are not rendered by default.

1,694 changes: 2 additions & 1,692 deletions data/pc/1.14.3/proto.yml

Large diffs are not rendered by default.

5,672 changes: 2,836 additions & 2,836 deletions data/pc/1.14.3/protocol.json

Large diffs are not rendered by default.

1,513 changes: 6 additions & 1,507 deletions data/pc/1.14.4/proto.yml

Large diffs are not rendered by default.

5,666 changes: 2,833 additions & 2,833 deletions data/pc/1.14.4/protocol.json

Large diffs are not rendered by default.

1,255 changes: 65 additions & 1,190 deletions data/pc/1.14/proto.yml

Large diffs are not rendered by default.

5,550 changes: 2,775 additions & 2,775 deletions data/pc/1.14/protocol.json

Large diffs are not rendered by default.

5,628 changes: 2,814 additions & 2,814 deletions data/pc/1.15.1/protocol.json

Large diffs are not rendered by default.

5,628 changes: 2,814 additions & 2,814 deletions data/pc/1.15.2/protocol.json

Large diffs are not rendered by default.

1,484 changes: 14 additions & 1,470 deletions data/pc/1.15/proto.yml

Large diffs are not rendered by default.

5,628 changes: 2,814 additions & 2,814 deletions data/pc/1.15/protocol.json

Large diffs are not rendered by default.

1,363 changes: 34 additions & 1,329 deletions data/pc/1.16-rc1/proto.yml

Large diffs are not rendered by default.

5,602 changes: 2,801 additions & 2,801 deletions data/pc/1.16-rc1/protocol.json

Large diffs are not rendered by default.

5,602 changes: 2,801 additions & 2,801 deletions data/pc/1.16.1/protocol.json

Large diffs are not rendered by default.

1,390 changes: 25 additions & 1,365 deletions data/pc/1.16.2/proto.yml

Large diffs are not rendered by default.

5,916 changes: 2,958 additions & 2,958 deletions data/pc/1.16.2/protocol.json

Large diffs are not rendered by default.

5,602 changes: 2,801 additions & 2,801 deletions data/pc/1.16/protocol.json

Large diffs are not rendered by default.

1,571 changes: 13 additions & 1,558 deletions data/pc/1.17.1/proto.yml

Large diffs are not rendered by default.

7,220 changes: 3,610 additions & 3,610 deletions data/pc/1.17.1/protocol.json

Large diffs are not rendered by default.

1,387 changes: 77 additions & 1,310 deletions data/pc/1.17/proto.yml

Large diffs are not rendered by default.

6,202 changes: 3,101 additions & 3,101 deletions data/pc/1.17/protocol.json

Large diffs are not rendered by default.

1,822 changes: 4 additions & 1,818 deletions data/pc/1.18.2/proto.yml

Large diffs are not rendered by default.

6,350 changes: 3,175 additions & 3,175 deletions data/pc/1.18.2/protocol.json

Large diffs are not rendered by default.

1,523 changes: 24 additions & 1,499 deletions data/pc/1.18/proto.yml

Large diffs are not rendered by default.

6,350 changes: 3,175 additions & 3,175 deletions data/pc/1.18/protocol.json

Large diffs are not rendered by default.

1,541 changes: 36 additions & 1,505 deletions data/pc/1.19.2/proto.yml

Large diffs are not rendered by default.

6,748 changes: 3,374 additions & 3,374 deletions data/pc/1.19.2/protocol.json

Large diffs are not rendered by default.

1,231 changes: 81 additions & 1,150 deletions data/pc/1.19.3/proto.yml

Large diffs are not rendered by default.

7,134 changes: 3,567 additions & 3,567 deletions data/pc/1.19.3/protocol.json

Large diffs are not rendered by default.

1,359 changes: 55 additions & 1,304 deletions data/pc/1.19.4/proto.yml

Large diffs are not rendered by default.

8,052 changes: 4,026 additions & 4,026 deletions data/pc/1.19.4/protocol.json

Large diffs are not rendered by default.

1,141 changes: 97 additions & 1,044 deletions data/pc/1.19/proto.yml

Large diffs are not rendered by default.

7,070 changes: 3,535 additions & 3,535 deletions data/pc/1.19/protocol.json

Large diffs are not rendered by default.

1,716 changes: 93 additions & 1,623 deletions data/pc/1.20.2/proto.yml

Large diffs are not rendered by default.

7,668 changes: 3,834 additions & 3,834 deletions data/pc/1.20.2/protocol.json

Large diffs are not rendered by default.

478 changes: 217 additions & 261 deletions data/pc/1.20.3/proto.yml

Large diffs are not rendered by default.

9,292 changes: 4,646 additions & 4,646 deletions data/pc/1.20.3/protocol.json

Large diffs are not rendered by default.

1,237 changes: 81 additions & 1,156 deletions data/pc/1.20.5/proto.yml

Large diffs are not rendered by default.

10,384 changes: 5,192 additions & 5,192 deletions data/pc/1.20.5/protocol.json

Large diffs are not rendered by default.

1,956 changes: 39 additions & 1,917 deletions data/pc/1.20/proto.yml

Large diffs are not rendered by default.

7,426 changes: 3,713 additions & 3,713 deletions data/pc/1.20/protocol.json

Large diffs are not rendered by default.

2,378 changes: 12 additions & 2,366 deletions data/pc/1.21.1/proto.yml

Large diffs are not rendered by default.

10,778 changes: 5,389 additions & 5,389 deletions data/pc/1.21.1/protocol.json

Large diffs are not rendered by default.

3,277 changes: 3 additions & 3,274 deletions data/pc/1.21.11/proto.yml

Large diffs are not rendered by default.

14,624 changes: 7,312 additions & 7,312 deletions data/pc/1.21.11/protocol.json

Large diffs are not rendered by default.

2,031 changes: 42 additions & 1,989 deletions data/pc/1.21.3/proto.yml

Large diffs are not rendered by default.

11,910 changes: 5,955 additions & 5,955 deletions data/pc/1.21.3/protocol.json

Large diffs are not rendered by default.

3,656 changes: 413 additions & 3,243 deletions data/pc/1.21.4/proto.yml

Large diffs are not rendered by default.

11,156 changes: 5,578 additions & 5,578 deletions data/pc/1.21.4/protocol.json

Large diffs are not rendered by default.

1,522 changes: 28 additions & 1,494 deletions data/pc/1.21.5/proto.yml

Large diffs are not rendered by default.

11,840 changes: 5,920 additions & 5,920 deletions data/pc/1.21.5/protocol.json

Large diffs are not rendered by default.

2,196 changes: 18 additions & 2,178 deletions data/pc/1.21.6/proto.yml

Large diffs are not rendered by default.

15,000 changes: 7,500 additions & 7,500 deletions data/pc/1.21.6/protocol.json

Large diffs are not rendered by default.

3,457 changes: 1 addition & 3,456 deletions data/pc/1.21.8/proto.yml

Large diffs are not rendered by default.

14,042 changes: 7,021 additions & 7,021 deletions data/pc/1.21.8/protocol.json

Large diffs are not rendered by default.

2,368 changes: 39 additions & 2,329 deletions data/pc/1.21.9/proto.yml

Large diffs are not rendered by default.

14,020 changes: 7,010 additions & 7,010 deletions data/pc/1.21.9/protocol.json

Large diffs are not rendered by default.

371 changes: 252 additions & 119 deletions data/pc/1.7/proto.yml

Large diffs are not rendered by default.

3,152 changes: 1,576 additions & 1,576 deletions data/pc/1.7/protocol.json

Large diffs are not rendered by default.

500 changes: 161 additions & 339 deletions data/pc/1.8/proto.yml

Large diffs are not rendered by default.

3,724 changes: 1,862 additions & 1,862 deletions data/pc/1.8/protocol.json

Large diffs are not rendered by default.

1,093 changes: 2 additions & 1,091 deletions data/pc/1.9.1-pre2/proto.yml

Large diffs are not rendered by default.

3,482 changes: 1,741 additions & 1,741 deletions data/pc/1.9.1-pre2/protocol.json

Large diffs are not rendered by default.

3,482 changes: 1,741 additions & 1,741 deletions data/pc/1.9.2/protocol.json

Large diffs are not rendered by default.

932 changes: 6 additions & 926 deletions data/pc/1.9.4/proto.yml

Large diffs are not rendered by default.

3,448 changes: 1,724 additions & 1,724 deletions data/pc/1.9.4/protocol.json

Large diffs are not rendered by default.

749 changes: 54 additions & 695 deletions data/pc/1.9/proto.yml

Large diffs are not rendered by default.

3,482 changes: 1,741 additions & 1,741 deletions data/pc/1.9/protocol.json

Large diffs are not rendered by default.

642 changes: 39 additions & 603 deletions data/pc/15w40b/proto.yml

Large diffs are not rendered by default.

4,004 changes: 2,002 additions & 2,002 deletions data/pc/15w40b/protocol.json

Large diffs are not rendered by default.

1,054 changes: 5 additions & 1,049 deletions data/pc/16w20a/proto.yml

Large diffs are not rendered by default.

3,450 changes: 1,725 additions & 1,725 deletions data/pc/16w20a/protocol.json

Large diffs are not rendered by default.

1,054 changes: 5 additions & 1,049 deletions data/pc/16w35a/proto.yml

Large diffs are not rendered by default.

3,452 changes: 1,726 additions & 1,726 deletions data/pc/16w35a/protocol.json

Large diffs are not rendered by default.

842 changes: 19 additions & 823 deletions data/pc/17w15a/proto.yml

Large diffs are not rendered by default.

3,752 changes: 1,876 additions & 1,876 deletions data/pc/17w15a/protocol.json

Large diffs are not rendered by default.

1,114 changes: 9 additions & 1,105 deletions data/pc/17w18b/proto.yml

Large diffs are not rendered by default.

3,724 changes: 1,862 additions & 1,862 deletions data/pc/17w18b/protocol.json

Large diffs are not rendered by default.

934 changes: 36 additions & 898 deletions data/pc/17w50a/proto.yml

Large diffs are not rendered by default.

4,234 changes: 2,117 additions & 2,117 deletions data/pc/17w50a/protocol.json

Large diffs are not rendered by default.

1,517 changes: 15 additions & 1,502 deletions data/pc/20w13b/proto.yml

Large diffs are not rendered by default.

5,456 changes: 2,728 additions & 2,728 deletions data/pc/20w13b/protocol.json

Large diffs are not rendered by default.

1,418 changes: 28 additions & 1,390 deletions data/pc/21w07a/proto.yml

Large diffs are not rendered by default.

5,786 changes: 2,893 additions & 2,893 deletions data/pc/21w07a/protocol.json

Large diffs are not rendered by default.

17,824 changes: 8,912 additions & 8,912 deletions data/pc/26.1/protocol.json

Large diffs are not rendered by default.

2,666 changes: 11 additions & 2,655 deletions data/pc/latest/proto.yml

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions doc/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,23 @@ string: ["pstring",{"countType":"varint"}]

#### Compiling to JSON
Once the protocol YAML files have been updated, run `npm run build` inside `tools/js` to generate protocol.json for each of the protocol YAML files.

#### Delta protocols
Instead of a full copy of the protocol, a version's `proto.yml` can be a **delta** on a previous version by starting with `!base: <version>` (resolved through `dataPaths.json`):

```yml
!version: 1.21.8
!base: 1.21.6

^types:
vec3i: # added
x: varint
y: varint
z: varint
packet_x: ... # redefined wholesale (replaces the base's definition)
OldType: !delete # removed
```

Semantics, per section (`^types`, `^play.toClient.types`, ...): a type present in both is **replaced wholesale** by the delta's definition — there is no deep merge, because mapper values and packet IDs are positional and partial merges would be unsafe; a type only in the base is inherited; a type only in the delta is added. `TypeName: !delete` removes an inherited type, and `^section: !delete` removes a whole section. Versions whose protocol didn't change keep pointing at the previous version's data directory via `dataPaths.json`, as before.

`npm run build` resolves `!base` chains automatically, so deltas compile exactly like full protocols. When updating a protocol, copy the changed/added packet definitions from the previous version's file into the new delta rather than copying the whole file.
177 changes: 177 additions & 0 deletions tools/js/backfillDeltas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/**
* One-time migration: converts full per-version proto.yml files into !base
* deltas (see protoDelta.js).
*
* For each consecutive pair of protocol versions (in dataPaths.json order),
* diffs their proto.yml at the type level and emits a minimal delta for the
* newer version. Before keeping anything it compiles each delta chain and
* verifies the result is deep-equal to the previously committed protocol.json
* (the golden check: key *order* may differ since added types are appended,
* which is not semantically meaningful, but content must match exactly).
*
* Usage:
* node backfillDeltas.js [edition] # dry run (default: pc)
* node backfillDeltas.js [edition] --write
* After --write, run `npm run build` to regenerate the protocol.json files in
* the new key order.
*/
const fs = require('fs')
const { join } = require('path')
const { compile } = require('protodef-yaml')
const { parseProto, splitSectionEntries, resolve, entryValue } = require('./protoDelta')

const DATA = join(__dirname, '../../data')
const DELETE = '!delete'

// Mirror compileProtocol.js: decimal mapper keys are rendered as hex
function visitor (key, value) {
if ((key === 'packet') && (value?.[1]?.[0]?.name === 'name')) {
const mapper = value[1][0].type[1].mappings
for (const k in mapper) {
if (k.startsWith('0x')) continue
mapper['0x' + Number(k).toString(16).padStart(2, '0')] = mapper[k]
delete mapper[k]
}
}
return value
}

// Distinct proto dirs in dataPaths order, with a canonical version id each
function protoChain (edition) {
const dataPaths = JSON.parse(fs.readFileSync(join(DATA, 'dataPaths.json'), 'utf8'))
const chain = []
for (const [versionId, paths] of Object.entries(dataPaths[edition])) {
if (!paths.proto) continue
if (chain.length && chain[chain.length - 1].dir === paths.proto) continue
chain.push({ versionId, dir: paths.proto })
}
return chain
}

// Diff two parsed protos into a delta: added/changed types verbatim, removed
// types as `TypeName: !delete`, removed sections as `^section: !delete`
function buildDelta (prevParsed, curParsed) {
const sections = new Map()
for (const [key, curSection] of curParsed.sections) {
const prevSection = prevParsed.sections.get(key)
const prevEntries = prevSection ? splitSectionEntries(prevSection.body, `${key} (prev)`) : null
const curEntries = splitSectionEntries(curSection.body, `${key} (cur)`)
const ops = []
if (prevEntries) {
for (const typeKey of prevEntries.keys()) {
if (!curEntries.has(typeKey)) ops.push({ lines: [` ${typeKey}: ${DELETE}`] })
}
}
for (const [typeKey, lines] of curEntries) {
const prev = prevEntries && prevEntries.get(typeKey)
if (!prev || prev.join('\n') !== lines.join('\n')) ops.push({ lines })
}
if (ops.length) sections.set(key, { header: curSection.header, ops })
}
for (const key of prevParsed.sections.keys()) {
if (!curParsed.sections.has(key)) sections.set(key, { header: `${key}: ${DELETE}`, ops: [] })
}
if (sections.size === 0) return null // identical protocol: keep the full file
return sections
}

function renderDelta (version, baseVersion, sections) {
const lines = [`!version: ${version}`, `!base: ${baseVersion}`]
for (const section of sections.values()) {
lines.push('', section.header)
if (section.header.endsWith(DELETE)) continue
let first = true
for (const op of section.ops) {
if (!first) lines.push('')
lines.push(...op.lines)
first = false
}
}
return lines.join('\n') + '\n'
}

function sortKeys (v) {
if (Array.isArray(v)) return v.map(sortKeys)
if (v && typeof v === 'object') {
const o = {}
for (const k of Object.keys(v).sort()) o[k] = sortKeys(v[k])
return o
}
return v
}

function main () {
const edition = process.argv[2] && !process.argv[2].startsWith('-') ? process.argv[2] : 'pc'
const write = process.argv.includes('--write')
const chain = protoChain(edition)
console.log(`${edition}: ${chain.length} distinct protocol dirs`)

let converted = 0
let failed = 0
// Full (chain-resolved) text of the previous version's protocol: diffs are
// always computed against the full previous protocol, never a delta file
let prevFullText = null
for (let i = 1; i < chain.length; i++) {
const prev = chain[i - 1]
const cur = chain[i]
const curDir = join(DATA, cur.dir)
const curPath = join(curDir, 'proto.yml')
const prevPath = join(DATA, prev.dir, 'proto.yml')
if (prevFullText === null) {
prevFullText = parseProto(fs.readFileSync(prevPath, 'utf8'), prevPath).directives.has('!base')
? resolve(edition, prevPath, DATA).main
: fs.readFileSync(prevPath, 'utf8')
}
const original = fs.readFileSync(curPath, 'utf8')
const curIsDelta = parseProto(original, curPath).directives.has('!base')
const curFullText = curIsDelta ? resolve(edition, curPath, DATA).main : original
const curParsed = parseProto(curFullText, curPath)

const sections = buildDelta(parseProto(prevFullText, prevPath), curParsed)
if (!sections) {
console.log(`= ${cur.versionId}: identical to ${prev.versionId}, keeping full file`)
prevFullText = curFullText
continue
}

// golden check: write the delta, resolve the chain, compile, compare with
// the committed protocol.json, then restore unless we are writing
const versionLine = (curParsed.directives.get('!version') || [])[0] || ''
const version = entryValue(versionLine.trim())
if (!version) throw Error(`No !version in ${curPath}`)
const deltaText = renderDelta(version, prev.versionId, sections)
fs.writeFileSync(curPath, deltaText)
let err = null
let mergedMain = null
try {
const files = resolve(edition, curPath, DATA)
const json = compile(files)
const goldenPath = join(curDir, 'protocol.json')
if (fs.existsSync(goldenPath)) {
const expected = JSON.parse(fs.readFileSync(goldenPath, 'utf8'))
const actual = JSON.parse(JSON.stringify(json, visitor, 2))
if (JSON.stringify(sortKeys(actual)) !== JSON.stringify(sortKeys(expected))) {
err = 'compiled protocol differs from committed protocol.json'
}
} // else: unreleased version (pc/latest), nothing committed to compare with
mergedMain = files.main
} catch (e) {
err = e.stack ? e.stack.split('\n').slice(0, 4).join(' | ') : e.message
}
if (err || !write) fs.writeFileSync(curPath, original)
prevFullText = err ? curFullText : mergedMain

if (err) {
failed++
console.log(`✗ ${cur.versionId}: ${err}`)
continue
}
converted++
const ops = [...sections.values()].reduce((n, s) => n + s.ops.length, 0)
console.log(`✓ ${cur.versionId}: delta on ${prev.versionId} (${ops} type ops, ${deltaText.split('\n').length} lines)`)
}
console.log(`\n${converted} converted, ${failed} failed${write ? '' : ' (dry run: deltas NOT kept)'}`)
if (failed) process.exit(1)
}

try { main() } catch (e) { console.error(e); process.exit(1) }
47 changes: 38 additions & 9 deletions tools/js/compileProtocol.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@
const fs = require('fs')
const { join } = require('path')
const { parse, compile } = require('protodef-yaml')
const { resolveProtoDelta } = require('./protoDelta')

function getJSON (path) {
return JSON.parse(fs.readFileSync(path, 'utf-8'))
}

// Parse the YML files and turn to JSON
function genProtoSchema (createPacketMap) {
function genProtoSchema (createPacketMap, edition) {
// If proto.yml is a !base delta, resolve the chain into a full protocol
// file set first (no-op for full protos, which keep using the file on disk)
const delta = resolveProtoDelta(edition, process.cwd(), join(__dirname, '../../data'))
const protoInput = delta ? delta.files : './proto.yml'

// Create the packet_map.yml from proto.yml
const parsed = parse('./proto.yml')
const parsed = parse(protoInput)
const version = parsed['!version']

if (createPacketMap) {
Expand Down Expand Up @@ -41,7 +47,12 @@ function genProtoSchema (createPacketMap) {
fs.writeFileSync('./packet_map.yml', t)
}

const json = compile('./proto.yml')
if (delta && fs.existsSync('./packet_map.yml')) {
// protodef-yaml only resolves !imports from disk for file inputs; feed the
// generated packet map into the resolved file set
delta.files['packet_map.yml'] = fs.readFileSync('./packet_map.yml', 'utf8')
}
const json = compile(protoInput)
fs.rmSync('./packet_map.yml', { force: true }) // temp file
return [version, json]
}
Expand All @@ -59,22 +70,40 @@ function visitor (key, value) {
return value
}

// Render object keys in sorted order so regenerated files are byte-stable
// regardless of the source order (JSON object key order carries no meaning
// for ProtoDef compilation). The top-level section order is preserved:
// protodef-validator registers the global `types` namespace before the
// per-state namespaces, so `types` must stay ahead of them no matter how the
// source was assembled.
function sortKeys (value, isTopLevel = false) {
if (Array.isArray(value)) return value.map(v => sortKeys(v))
if (value && typeof value === 'object') {
const keys = Object.keys(value)
if (!isTopLevel) keys.sort()
const out = {}
for (const key of keys) out[key] = sortKeys(value[key])
return out
}
return value
}

function convert (edition, ver, path) {
process.chdir(path || join(__dirname, `../../data/${edition}/${ver}`))
const [version, json] = genProtoSchema(edition === 'bedrock')
const [version, json] = genProtoSchema(edition === 'bedrock', edition)
fs.mkdirSync(`../${version}`, { recursive: true })
if (edition === 'bedrock') {
fs.writeFileSync(`../${version}/protocol.json`, JSON.stringify({ types: json }, visitor, 2))
fs.writeFileSync(`../${version}/protocol.json`, JSON.stringify({ types: sortKeys(json, true) }, visitor, 2))
} else if (edition === 'pc') {
fs.writeFileSync(`../${version}/protocol.json`, JSON.stringify(json, visitor, 2))
fs.writeFileSync(`../${version}/protocol.json`, JSON.stringify(sortKeys(json, true), visitor, 2))
}
return version
}

function validate (edition, ver, path) {
process.chdir(path || join(__dirname, `../../data/${edition}/${ver}`))
// console.log(process.cwd())
const [version, json] = genProtoSchema(edition === 'bedrock')
const [version, json] = genProtoSchema(edition === 'bedrock', edition)

if (path.endsWith('latest')) {
if (fs.existsSync(join(__dirname, `../../data/${edition}/${version}/proto.yml`))) {
Expand All @@ -83,8 +112,8 @@ function validate (edition, ver, path) {
}

const expected = edition === 'bedrock'
? JSON.stringify({ types: json }, visitor, 2)
: JSON.stringify(json, visitor, 2)
? JSON.stringify({ types: sortKeys(json, true) }, visitor, 2)
: JSON.stringify(sortKeys(json, true), visitor, 2)

// If you crash here, no protocol.json was generated - run `npm run build`
const actual = JSON.stringify(getJSON(`../${version}/protocol.json`), null, 2)
Expand Down
Loading
Loading