minecraft-data 3.35.0 → 3.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -374,19 +374,19 @@
374
374
  {
375
375
  "compareTo": "$compareTo",
376
376
  "fields": {
377
- "0": "i8",
378
- "1": "varint",
379
- "2": "varlong",
380
- "3": "f32",
381
- "4": "string",
382
- "5": "string",
383
- "6": [
377
+ "byte": "i8",
378
+ "int": "varint",
379
+ "long": "varlong",
380
+ "float": "f32",
381
+ "string": "string",
382
+ "component": "string",
383
+ "optional_component": [
384
384
  "option",
385
385
  "string"
386
386
  ],
387
- "7": "slot",
388
- "8": "bool",
389
- "9": [
387
+ "item_stack": "slot",
388
+ "boolean": "bool",
389
+ "rotations": [
390
390
  "container",
391
391
  [
392
392
  {
@@ -403,21 +403,21 @@
403
403
  }
404
404
  ]
405
405
  ],
406
- "10": "position",
407
- "11": [
406
+ "block_pos": "position",
407
+ "optional_block_pos": [
408
408
  "option",
409
409
  "position"
410
410
  ],
411
- "12": "varint",
412
- "13": [
411
+ "direction": "varint",
412
+ "optional_uuid": [
413
413
  "option",
414
414
  "UUID"
415
415
  ],
416
- "14": "varint",
417
- "15": "optvarint",
418
- "16": "nbt",
419
- "17": "particle",
420
- "18": [
416
+ "block_state": "varint",
417
+ "optional_block_state": "optvarint",
418
+ "compound_tag": "nbt",
419
+ "particle": "particle",
420
+ "villager_data": [
421
421
  "container",
422
422
  [
423
423
  {
@@ -434,18 +434,18 @@
434
434
  }
435
435
  ]
436
436
  ],
437
- "19": "optvarint",
438
- "20": "varint",
439
- "21": "varint",
440
- "22": "varint",
441
- "23": [
437
+ "optional_unsigned_int": "optvarint",
438
+ "pose": "varint",
439
+ "cat_variant": "varint",
440
+ "frog_variant": "varint",
441
+ "optional_global_pos": [
442
442
  "option",
443
443
  "string"
444
444
  ],
445
- "24": "varint",
446
- "25": "varint",
447
- "26": "vec3f",
448
- "27": "vec4f"
445
+ "painting_variant": "varint",
446
+ "sniffer_state": "varint",
447
+ "vector3": "vec3f",
448
+ "quaternion": "vec4f"
449
449
  }
450
450
  }
451
451
  ],
@@ -457,19 +457,46 @@
457
457
  "container",
458
458
  [
459
459
  {
460
- "anon": true,
460
+ "name": "key",
461
+ "type": "u8"
462
+ },
463
+ {
464
+ "name": "type",
461
465
  "type": [
462
- "container",
463
- [
464
- {
465
- "name": "key",
466
- "type": "u8"
467
- },
468
- {
469
- "name": "type",
470
- "type": "varint"
466
+ "mapper",
467
+ {
468
+ "type": "varint",
469
+ "mappings": {
470
+ "0": "byte",
471
+ "1": "int",
472
+ "2": "long",
473
+ "3": "float",
474
+ "4": "string",
475
+ "5": "component",
476
+ "6": "optional_component",
477
+ "7": "item_stack",
478
+ "8": "boolean",
479
+ "9": "rotations",
480
+ "10": "block_pos",
481
+ "11": "optional_block_pos",
482
+ "12": "direction",
483
+ "13": "optional_uuid",
484
+ "14": "block_state",
485
+ "15": "optional_block_state",
486
+ "16": "compound_tag",
487
+ "17": "particle",
488
+ "18": "villager_data",
489
+ "19": "optional_unsigned_int",
490
+ "20": "pose",
491
+ "21": "cat_variant",
492
+ "22": "frog_variant",
493
+ "23": "optional_global_pos",
494
+ "24": "painting_variant",
495
+ "25": "sniffer_state",
496
+ "26": "vector3",
497
+ "27": "quaternion"
471
498
  }
472
- ]
499
+ }
473
500
  ]
474
501
  },
475
502
  {
@@ -6731,4 +6758,4 @@
6731
6758
  }
6732
6759
  }
6733
6760
  }
6734
- }
6761
+ }
@@ -721,5 +721,10 @@
721
721
  "name": "hasBundlePacket",
722
722
  "description": "Has a Bundle Packet to group packets for processing at once",
723
723
  "versions": ["1.19.4", "latest"]
724
+ },
725
+ {
726
+ "name": "mcDataHasEntityMetadata",
727
+ "description": "Entity Metadata is defined in mcdata",
728
+ "versions": ["1.19.4", "latest"]
724
729
  }
725
730
  ]
@@ -1,3 +1,6 @@
1
+ ## 3.36.0
2
+ * pc: add entity metadata (@extremeheat)
3
+
1
4
  ## 3.35.0
2
5
  * Add bedrock 1.20.0 protocol data
3
6
 
@@ -60,6 +60,13 @@
60
60
  "category": {
61
61
  "description": "The category of an entity : a semantic category",
62
62
  "type": "string"
63
+ },
64
+ "metadataKeys": {
65
+ "description": "The pc metadata tags of an entity. (Naming is via mc code, with data_ and id_ prefixes stripped)",
66
+ "type": "array",
67
+ "items": {
68
+ "type": "string"
69
+ }
63
70
  }
64
71
  },
65
72
  "required": [
@@ -0,0 +1,153 @@
1
+ const fs = require('fs')
2
+ const cp = require('child_process')
3
+ const { globSync } = require('glob')
4
+ const version = process.argv[2] || '1.19.4'
5
+ if (!version) {
6
+ console.log('Usage: node extractEntityMetadata.js <version>')
7
+ process.exit(1)
8
+ }
9
+
10
+ if (!fs.existsSync(version)) {
11
+ cp.execSync(`git clone -b client${version} https://github.com/extremeheat/extracted_minecraft_data.git ${version} --depth 1`, { stdio: 'inherit' })
12
+ }
13
+
14
+ function getEntityTypes () {
15
+ const entityTypes = fs.readFileSync(`./${version}/client/net/minecraft/world/entity/EntityType.java`, 'utf8')
16
+ const entityTypesLines = entityTypes.split(';')
17
+ const classNameTo = {}
18
+ for (const line of entityTypesLines) {
19
+ if (line.includes('= register(')) {
20
+ // Given the line: public static final EntityType<Allay> ALLAY = register( "allay", EntityType.Builder.<Allay>of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).clientTrackingRange(8).updateInterval(2) );
21
+ // we extract Allay and "allay"
22
+ const regex = line.match(/EntityType<(.*)> (.*) = register\(\W+"([a-z0-9_]+)"/)
23
+ if (regex) {
24
+ const [, type, , name] = regex
25
+ classNameTo[type] = name
26
+ }
27
+ }
28
+ }
29
+ return classNameTo
30
+ }
31
+
32
+ function getEntityMetadataSerializers () {
33
+ const output = []
34
+ const entityTypes = fs.readFileSync(`./${version}/client/net/minecraft/network/syncher/EntityDataSerializers.java`, 'utf8')
35
+ const entityTypesLines = entityTypes.split(';')
36
+ for (const line of entityTypesLines) {
37
+ if (line.includes('registerSerializer')) {
38
+ // From: registerSerializer(BYTE);
39
+ // We extract: BYTE
40
+ const regex = line.match(/ {2}registerSerializer\((.*)\)/)
41
+ if (regex) {
42
+ const [, type] = regex
43
+ output.push(type)
44
+ }
45
+ }
46
+ }
47
+ return output.map(e => e.toLowerCase())
48
+ }
49
+
50
+ const serializers = getEntityMetadataSerializers()
51
+ const classNameToRegistryName = getEntityTypes()
52
+
53
+ const allEntityFiles = globSync(`${version}/**/entity/**/*.java`)
54
+ const allEntityFileCodes = Object.fromEntries(allEntityFiles.map(file => [
55
+ file.split(/\\|\//g).pop().replace('.java', ''),
56
+ fs.readFileSync(file, 'utf8')
57
+ ]))
58
+
59
+ const entityPreTree = []
60
+ const metadatas = {}
61
+
62
+ for (const file in allEntityFileCodes) {
63
+ const code = allEntityFileCodes[file]
64
+ const lines = code.split(';')
65
+ let lastClass
66
+ for (const line of lines) {
67
+ let lineWithoutGenerics = line.replace(/<.*>/g, '')
68
+ const bloatMods = ['abstract', 'static']
69
+ for (const mod of bloatMods) lineWithoutGenerics = lineWithoutGenerics.replace(` ${mod} `, ' ')
70
+
71
+ if (lineWithoutGenerics.includes('public class ')) {
72
+ const className = lineWithoutGenerics.split('public class ')[1]?.split(' ')[0]
73
+ lastClass = className
74
+ const extend = lineWithoutGenerics.split('extends ')[1]?.split(' ')[0]
75
+ if (className === file) {
76
+ if (extend) entityPreTree.push([extend, file])
77
+ else entityPreTree.push([file])
78
+ } else if (extend === file) {
79
+ lastClass = `${file}.${className}`
80
+ entityPreTree.push([file, lastClass])
81
+ }
82
+ }
83
+
84
+ if (line.includes('SynchedEntityData.defineId(')) {
85
+ // from: private static final EntityDataAccessor<Sniffer.State> DATA_STATE = SynchedEntityData.defineId(Sniffer.class, EntityDataSerializers.SNIFFER_STATE);
86
+ // extract: DATA_STATE, SNIFFER_STATE
87
+ const r = line.match(/> ([A-Z_0-9]+) = .*EntityDataSerializers.([A-Z_0-9]+)/s)
88
+ if (r) {
89
+ const [, data, serializer] = r
90
+ ; (metadatas[lastClass] ??= []).push([data, serializer])
91
+ } else {
92
+ throw new Error('Failed to parse line: ' + line)
93
+ }
94
+ }
95
+ }
96
+ }
97
+
98
+ const tree = {}
99
+ const flat = {}
100
+ const handledNames = []
101
+ function build (ele, root = tree, arr = []) {
102
+ const name = classNameToRegistryName[ele]
103
+ const metadata = metadatas[ele]
104
+ root[ele] = { children: {}, name, metadata }
105
+ if (name) flat[name] = arr.concat(metadata ?? [])
106
+ handledNames.push(ele)
107
+ for (const [key, val] of entityPreTree) {
108
+ if (key === ele) {
109
+ build(val, root[key].children, arr.concat(metadata ?? []))
110
+ }
111
+ }
112
+ }
113
+ build('Entity')
114
+
115
+ for (const key in classNameToRegistryName) {
116
+ if (!handledNames.includes(key)) throw new Error('Unhandled entity ' + key)
117
+ }
118
+
119
+ function updateMcDataEntitiesJSON () {
120
+ const presentMcDataPath = `../../data/pc/${version}/entities.json`
121
+ const presentMcData = require(presentMcDataPath)
122
+ for (const entry of presentMcData) {
123
+ entry.metadataKeys = flat[entry.name].map(e => e[0].replace('DATA_', '').replace('_ID', '').replace('ID_', '').toLowerCase())
124
+ }
125
+ fs.writeFileSync(presentMcDataPath, JSON.stringify(presentMcData, null, 2))
126
+ }
127
+
128
+ function updateMcDataProtocolJSON () {
129
+ const presentMcDataPath = `../../data/pc/${version}/protocol.json`
130
+ const mcdata = require(presentMcDataPath)
131
+ const mapper = { type: 'varint', mappings: {} }
132
+ for (let i = 0; i < serializers.length; i++) {
133
+ mapper.mappings[i] = serializers[i].toLowerCase()
134
+ }
135
+ mcdata.types.entityMetadata[1].type[1] = [
136
+ { name: 'key', type: 'u8' },
137
+ { name: 'type', type: ['mapper', mapper] },
138
+ { name: 'value', type: ['entityMetadataItem', { compareTo: 'type' }] }
139
+ ]
140
+ // One time code to remap integers to strings in protocol.json for the entityMetadataItem type
141
+ // const metadataItems = mcdata.types.entityMetadataItem[1].fields
142
+ // const next = {}
143
+ // for (const key in metadataItems) {
144
+ // next[serializers[key]] = metadataItems[key]
145
+ // }
146
+ // mcdata.types.entityMetadataItem[1].fields = next
147
+ fs.writeFileSync(presentMcDataPath, JSON.stringify(mcdata, null, 2))
148
+ }
149
+
150
+ // fs.writeFileSync(`./entityTree.json`, JSON.stringify(tree, null, 2))
151
+ // fs.writeFileSync(`./entityFlat.json`, JSON.stringify(flat, null, 2))
152
+ updateMcDataEntitiesJSON()
153
+ updateMcDataProtocolJSON()
@@ -13,7 +13,8 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "ajv": "^6.5.4",
16
- "mocha": "5.2.0",
16
+ "glob": "^10.2.6",
17
+ "mocha": "^10.2.0",
17
18
  "protodef-validator": "^1.2.2",
18
19
  "protodef-yaml": "^1.2.2",
19
20
  "standard": "^16.0.3"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minecraft-data",
3
- "version": "3.35.0",
3
+ "version": "3.36.0",
4
4
  "description": "Provide easy access to minecraft data in node.js",
5
5
  "main": "index.js",
6
6
  "tonicExampleFilename": "example.js",
@@ -8,9 +8,9 @@
8
8
  "generate:types": "node typings/generate-typings.js",
9
9
  "generate:data": "node ./bin/generate_data.js",
10
10
  "test:types": "tsc typings/test-typings && node typings/test-typings.js",
11
- "test": "require-self && npm run generate:types && npm run generate:data && npm run lint && npm run test:types && mocha",
11
+ "test": "npm run generate:types && npm run generate:data && npm run lint && npm run test:types && mocha",
12
12
  "lint": "standard",
13
- "prepare": "require-self && npm run generate:data && npm run generate:types",
13
+ "prepare": "npm run generate:data && npm run generate:types",
14
14
  "fix": "standard --fix"
15
15
  },
16
16
  "standard": {
@@ -33,11 +33,11 @@
33
33
  "url": "https://github.com/PrismarineJS/node-minecraft-data/issues"
34
34
  },
35
35
  "devDependencies": {
36
+ "minecraft-data": ".",
36
37
  "@types/node": "^20.2.1",
37
38
  "json-schema-to-typescript": "11.0.5",
38
39
  "minecraft-packets": "^1.4.0",
39
40
  "mocha": "^10.0.0",
40
- "require-self": "^0.2.3",
41
41
  "standard": "^17.0.0",
42
42
  "typescript": "~5.0.4"
43
43
  },