mca-json 1.0.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.
- package/.editorconfig +14 -0
- package/.prettierrc +4 -0
- package/README.md +373 -0
- package/dist/bin/mca-chunks.d.ts +3 -0
- package/dist/bin/mca-chunks.d.ts.map +1 -0
- package/dist/bin/mca-chunks.js +43 -0
- package/dist/bin/mca-chunks.js.map +1 -0
- package/dist/bin/mca-find-chunks-with-signs.d.ts +3 -0
- package/dist/bin/mca-find-chunks-with-signs.d.ts.map +1 -0
- package/dist/bin/mca-find-chunks-with-signs.js +79 -0
- package/dist/bin/mca-find-chunks-with-signs.js.map +1 -0
- package/dist/bin/mca-json.d.ts +3 -0
- package/dist/bin/mca-json.d.ts.map +1 -0
- package/dist/bin/mca-json.js +73 -0
- package/dist/bin/mca-json.js.map +1 -0
- package/dist/bin/mca-trim-chunks-without-signs.d.ts +3 -0
- package/dist/bin/mca-trim-chunks-without-signs.d.ts.map +1 -0
- package/dist/bin/mca-trim-chunks-without-signs.js +117 -0
- package/dist/bin/mca-trim-chunks-without-signs.js.map +1 -0
- package/dist/bin/nbt-get-player-location.d.ts +3 -0
- package/dist/bin/nbt-get-player-location.d.ts.map +1 -0
- package/dist/bin/nbt-get-player-location.js +83 -0
- package/dist/bin/nbt-get-player-location.js.map +1 -0
- package/dist/bin/nbt-json.d.ts +3 -0
- package/dist/bin/nbt-json.d.ts.map +1 -0
- package/dist/bin/nbt-json.js +64 -0
- package/dist/bin/nbt-json.js.map +1 -0
- package/dist/block/banner.d.ts +13 -0
- package/dist/block/banner.d.ts.map +1 -0
- package/dist/block/banner.js +28 -0
- package/dist/block/banner.js.map +1 -0
- package/dist/block/barrel.d.ts +17 -0
- package/dist/block/barrel.d.ts.map +1 -0
- package/dist/block/barrel.js +21 -0
- package/dist/block/barrel.js.map +1 -0
- package/dist/block/beacon.d.ts +14 -0
- package/dist/block/beacon.d.ts.map +1 -0
- package/dist/block/beacon.js +14 -0
- package/dist/block/beacon.js.map +1 -0
- package/dist/block/bed.d.ts +4 -0
- package/dist/block/bed.d.ts.map +1 -0
- package/dist/block/bed.js +4 -0
- package/dist/block/bed.js.map +1 -0
- package/dist/block/beehive.d.ts +9 -0
- package/dist/block/beehive.d.ts.map +1 -0
- package/dist/block/beehive.js +10 -0
- package/dist/block/beehive.js.map +1 -0
- package/dist/block/bell.d.ts +4 -0
- package/dist/block/bell.d.ts.map +1 -0
- package/dist/block/bell.js +4 -0
- package/dist/block/bell.js.map +1 -0
- package/dist/block/block.d.ts +23 -0
- package/dist/block/block.d.ts.map +1 -0
- package/dist/block/block.js +49 -0
- package/dist/block/block.js.map +1 -0
- package/dist/block/generic.d.ts +10 -0
- package/dist/block/generic.d.ts.map +1 -0
- package/dist/block/generic.js +14 -0
- package/dist/block/generic.js.map +1 -0
- package/dist/block/has-entity-data.d.ts +8 -0
- package/dist/block/has-entity-data.d.ts.map +1 -0
- package/dist/block/has-entity-data.js +12 -0
- package/dist/block/has-entity-data.js.map +1 -0
- package/dist/block/mixins/custom-name.d.ts +5 -0
- package/dist/block/mixins/custom-name.d.ts.map +1 -0
- package/dist/block/mixins/custom-name.js +7 -0
- package/dist/block/mixins/custom-name.js.map +1 -0
- package/dist/block/mixins/lock.d.ts +5 -0
- package/dist/block/mixins/lock.d.ts.map +1 -0
- package/dist/block/mixins/lock.js +7 -0
- package/dist/block/mixins/lock.js.map +1 -0
- package/dist/block/mixins/mixin.d.ts +27 -0
- package/dist/block/mixins/mixin.d.ts.map +1 -0
- package/dist/block/mixins/mixin.js +36 -0
- package/dist/block/mixins/mixin.js.map +1 -0
- package/dist/block/sign.d.ts +15 -0
- package/dist/block/sign.d.ts.map +1 -0
- package/dist/block/sign.js +91 -0
- package/dist/block/sign.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/anvil.d.ts +54 -0
- package/dist/lib/anvil.d.ts.map +1 -0
- package/dist/lib/anvil.js +141 -0
- package/dist/lib/anvil.js.map +1 -0
- package/dist/lib/binary-data.d.ts +48 -0
- package/dist/lib/binary-data.d.ts.map +1 -0
- package/dist/lib/binary-data.js +188 -0
- package/dist/lib/binary-data.js.map +1 -0
- package/dist/lib/bit-data.d.ts +16 -0
- package/dist/lib/bit-data.d.ts.map +1 -0
- package/dist/lib/bit-data.js +75 -0
- package/dist/lib/bit-data.js.map +1 -0
- package/dist/lib/block-data.d.ts +20 -0
- package/dist/lib/block-data.d.ts.map +1 -0
- package/dist/lib/block-data.js +125 -0
- package/dist/lib/block-data.js.map +1 -0
- package/dist/lib/chunk.d.ts +112 -0
- package/dist/lib/chunk.d.ts.map +1 -0
- package/dist/lib/chunk.js +299 -0
- package/dist/lib/chunk.js.map +1 -0
- package/dist/nbt/nbt-base.d.ts +20 -0
- package/dist/nbt/nbt-base.d.ts.map +1 -0
- package/dist/nbt/nbt-base.js +30 -0
- package/dist/nbt/nbt-base.js.map +1 -0
- package/dist/nbt/nbt-byte-array.d.ts +13 -0
- package/dist/nbt/nbt-byte-array.d.ts.map +1 -0
- package/dist/nbt/nbt-byte-array.js +30 -0
- package/dist/nbt/nbt-byte-array.js.map +1 -0
- package/dist/nbt/nbt-byte.d.ts +13 -0
- package/dist/nbt/nbt-byte.d.ts.map +1 -0
- package/dist/nbt/nbt-byte.js +25 -0
- package/dist/nbt/nbt-byte.js.map +1 -0
- package/dist/nbt/nbt-compound.d.ts +15 -0
- package/dist/nbt/nbt-compound.d.ts.map +1 -0
- package/dist/nbt/nbt-compound.js +68 -0
- package/dist/nbt/nbt-compound.js.map +1 -0
- package/dist/nbt/nbt-double.d.ts +13 -0
- package/dist/nbt/nbt-double.d.ts.map +1 -0
- package/dist/nbt/nbt-double.js +25 -0
- package/dist/nbt/nbt-double.js.map +1 -0
- package/dist/nbt/nbt-end.d.ts +11 -0
- package/dist/nbt/nbt-end.d.ts.map +1 -0
- package/dist/nbt/nbt-end.js +22 -0
- package/dist/nbt/nbt-end.js.map +1 -0
- package/dist/nbt/nbt-float.d.ts +13 -0
- package/dist/nbt/nbt-float.d.ts.map +1 -0
- package/dist/nbt/nbt-float.js +25 -0
- package/dist/nbt/nbt-float.js.map +1 -0
- package/dist/nbt/nbt-int-array.d.ts +13 -0
- package/dist/nbt/nbt-int-array.d.ts.map +1 -0
- package/dist/nbt/nbt-int-array.js +30 -0
- package/dist/nbt/nbt-int-array.js.map +1 -0
- package/dist/nbt/nbt-int.d.ts +13 -0
- package/dist/nbt/nbt-int.d.ts.map +1 -0
- package/dist/nbt/nbt-int.js +25 -0
- package/dist/nbt/nbt-int.js.map +1 -0
- package/dist/nbt/nbt-list.d.ts +17 -0
- package/dist/nbt/nbt-list.d.ts.map +1 -0
- package/dist/nbt/nbt-list.js +70 -0
- package/dist/nbt/nbt-list.js.map +1 -0
- package/dist/nbt/nbt-long-array.d.ts +13 -0
- package/dist/nbt/nbt-long-array.d.ts.map +1 -0
- package/dist/nbt/nbt-long-array.js +32 -0
- package/dist/nbt/nbt-long-array.js.map +1 -0
- package/dist/nbt/nbt-long.d.ts +13 -0
- package/dist/nbt/nbt-long.d.ts.map +1 -0
- package/dist/nbt/nbt-long.js +25 -0
- package/dist/nbt/nbt-long.js.map +1 -0
- package/dist/nbt/nbt-short.d.ts +13 -0
- package/dist/nbt/nbt-short.d.ts.map +1 -0
- package/dist/nbt/nbt-short.js +25 -0
- package/dist/nbt/nbt-short.js.map +1 -0
- package/dist/nbt/nbt-string.d.ts +13 -0
- package/dist/nbt/nbt-string.d.ts.map +1 -0
- package/dist/nbt/nbt-string.js +27 -0
- package/dist/nbt/nbt-string.js.map +1 -0
- package/dist/nbt/nbt-tag-type.d.ts +16 -0
- package/dist/nbt/nbt-tag-type.d.ts.map +1 -0
- package/dist/nbt/nbt-tag-type.js +17 -0
- package/dist/nbt/nbt-tag-type.js.map +1 -0
- package/dist/nbt/nbt.d.ts +11 -0
- package/dist/nbt/nbt.d.ts.map +1 -0
- package/dist/nbt/nbt.js +57 -0
- package/dist/nbt/nbt.js.map +1 -0
- package/dist/nbt/snbt-data.d.ts +18 -0
- package/dist/nbt/snbt-data.d.ts.map +1 -0
- package/dist/nbt/snbt-data.js +34 -0
- package/dist/nbt/snbt-data.js.map +1 -0
- package/dist/nbt/snbt-parse.d.ts +3 -0
- package/dist/nbt/snbt-parse.d.ts.map +1 -0
- package/dist/nbt/snbt-parse.js +201 -0
- package/dist/nbt/snbt-parse.js.map +1 -0
- package/dist/nbt/snbt-to-nbt.d.ts +7 -0
- package/dist/nbt/snbt-to-nbt.d.ts.map +1 -0
- package/dist/nbt/snbt-to-nbt.js +178 -0
- package/dist/nbt/snbt-to-nbt.js.map +1 -0
- package/dist/types/coords.d.ts +3 -0
- package/dist/types/coords.d.ts.map +1 -0
- package/dist/types/coords.js +2 -0
- package/dist/types/coords.js.map +1 -0
- package/package.json +28 -0
- package/src/bin/mca-chunks.ts +54 -0
- package/src/bin/mca-find-chunks-with-signs.ts +109 -0
- package/src/bin/mca-json.ts +96 -0
- package/src/bin/mca-trim-chunks-without-signs.ts +146 -0
- package/src/bin/nbt-get-player-location.ts +102 -0
- package/src/bin/nbt-json.ts +85 -0
- package/src/block/banner.ts +50 -0
- package/src/block/barrel.ts +34 -0
- package/src/block/beacon.ts +20 -0
- package/src/block/bed.ts +3 -0
- package/src/block/beehive.ts +17 -0
- package/src/block/bell.ts +3 -0
- package/src/block/block.ts +62 -0
- package/src/block/generic.ts +14 -0
- package/src/block/has-entity-data.ts +20 -0
- package/src/block/mixins/custom-name.ts +8 -0
- package/src/block/mixins/lock.ts +8 -0
- package/src/block/mixins/mixin.ts +53 -0
- package/src/block/sign.ts +121 -0
- package/src/index.ts +38 -0
- package/src/lib/anvil.ts +178 -0
- package/src/lib/binary-data.ts +247 -0
- package/src/lib/bit-data.ts +101 -0
- package/src/lib/block-data.ts +180 -0
- package/src/lib/chunk.ts +389 -0
- package/src/nbt/nbt-base.ts +38 -0
- package/src/nbt/nbt-byte-array.ts +38 -0
- package/src/nbt/nbt-byte.ts +31 -0
- package/src/nbt/nbt-compound.ts +95 -0
- package/src/nbt/nbt-double.ts +31 -0
- package/src/nbt/nbt-end.ts +27 -0
- package/src/nbt/nbt-float.ts +31 -0
- package/src/nbt/nbt-int-array.ts +38 -0
- package/src/nbt/nbt-int.ts +31 -0
- package/src/nbt/nbt-list.ts +103 -0
- package/src/nbt/nbt-long-array.ts +40 -0
- package/src/nbt/nbt-long.ts +31 -0
- package/src/nbt/nbt-short.ts +31 -0
- package/src/nbt/nbt-string.ts +35 -0
- package/src/nbt/nbt-tag-type.ts +15 -0
- package/src/nbt/nbt.ts +70 -0
- package/src/nbt/snbt-data.ts +70 -0
- package/src/nbt/snbt-parse.ts +256 -0
- package/src/nbt/snbt-to-nbt.ts +219 -0
- package/src/types/coords.ts +2 -0
- package/src/types/neodoc.d.ts +28 -0
- package/tsconfig.json +25 -0
package/.editorconfig
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Editor configuration, see https://editorconfig.org
|
|
2
|
+
root = true
|
|
3
|
+
|
|
4
|
+
[*]
|
|
5
|
+
charset = utf-8
|
|
6
|
+
end_of_line = lf
|
|
7
|
+
indent_style = space
|
|
8
|
+
indent_size = 4
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
trim_trailing_whitespace = true
|
|
11
|
+
|
|
12
|
+
[*.md]
|
|
13
|
+
max_line_length = off
|
|
14
|
+
trim_trailing_whitespace = true
|
package/.prettierrc
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
MCA Tools
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
Command-line tools to work with Minecraft Anvil files (`*.mca`), from version 1.21.4 or newer. Support could be added to earlier versions incrementally as needed.
|
|
5
|
+
|
|
6
|
+
To install, first you need to install Node.js, then use `npm` to install the package. (Deno and Bun users can use this too, but you'll need to use your tool to do the install.)
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
npm install -g mca-tools
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
After that, you'll have access to all of these fine utilities.
|
|
13
|
+
|
|
14
|
+
This also has an API to include into your own programs. The JavaScript library doesn't require any Node-specific tooling, allowing you to bundle and build it into a browser environment.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Command-Line Tools
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### `mca-json` - Convert MCA to JSON
|
|
21
|
+
|
|
22
|
+
Converts an MCA file to JSON. Both input and output files are optional and it will read from stdin and write to stdout if not provided.
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
# See all of the options available
|
|
26
|
+
mca-json --help
|
|
27
|
+
|
|
28
|
+
# Convert a MCA file to JSON
|
|
29
|
+
mca-json ~/.minecraft/saves/Test_World/region/r.2.1.mca ~/r.2.1.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The output JSON is expected to be quite large. For example, one mostly untouched region used for testing is about 1 gigabyte of JSON. Because of this, there are options to make the output smaller while still being valid JSON. To not pretty-print the result, using `--compact` will reduce the size to roughly 1/10 of the expanded JSON but it's now all one long line. To preserve the majority of the spacing but collapse lists of numbers into a single line while still pretty printing the rest, use `--condense` and that will consume about 3/10 of the expanded size but still be understandable in a text editor.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### `mca-chunks` - List the chunk coordinates within a MCA file
|
|
36
|
+
|
|
37
|
+
Lists the chunk coordinates (not world coordinates) of each chunk contained with a single MCA file. Each chunk's coordinates are listed to the output, one per line in the format "X,Z".
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
# Show all chunk coordinates in a file
|
|
41
|
+
mca-chunks ~/.minecraft/saves/Test_World/region/r.2.1.mca
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This can also read the MCA file from stdin or write the output to a file. See `mca-chunks --help` for usage instructions.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### `mca-trim-chunks-without-signs` - Erase chunks
|
|
48
|
+
|
|
49
|
+
Hides chunks in an MCA file if they do not have signs. If you want to change the seed of your server regularly, you could have players reserve 16x16 chunks by placing a sign anywhere in the chunk with any letters or numbers on it. These signs are different from naturally generating signs. The indexes will be overwritten with zeros to indicate that the data is no longer in the file, so Minecraft will regenerate the chunk the next time it is loaded.
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
# Trim chunks in your region files
|
|
53
|
+
cd ~/.minecraft/saves/Test_World/
|
|
54
|
+
mca-trim-chunks-without-signs region/*.mca DIM1/region/*.mca DIM-1/region/*.mca
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Without using additional flags, this will trim chunks that currently have players. Check the usage with `mca-trim-chunks-without-signs --help` for additional options.
|
|
58
|
+
|
|
59
|
+
For reference, the naturally generating signs will have message like the following.
|
|
60
|
+
|
|
61
|
+
* Chairs in taiga villages: ["", "", "", ""] and ["", "", "", ""]
|
|
62
|
+
* Igloo basements: ["", "<----", "---->", ""] and ["", "", "", ""]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### `nbt-json` - Convert NBT data to JSON
|
|
66
|
+
|
|
67
|
+
This is useful for seeing what's in a player's `*.dat` file. Simply loads and decompresses the NBT, then writes it as a JSON object.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
# See all of the options available
|
|
71
|
+
nbt-json --help
|
|
72
|
+
|
|
73
|
+
# Convert an NBT file to JSON
|
|
74
|
+
nbt-json ~/.minecraft/saves/Test_World/playerdata/b248e729-09c2-40dd-9168-12d191b4f0b8.dat
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## API
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### `class Anvil`
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
import { Anvil } from 'mca-tools';
|
|
85
|
+
import { readFile } from 'node:fs/promises';
|
|
86
|
+
|
|
87
|
+
const data = await readFile('r.0.0.mca');
|
|
88
|
+
const anvil = Anvil.fromBuffer(data.buffer);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
#### `static fromBuffer(buffer: ArrayBufferLike): Anvil`
|
|
93
|
+
|
|
94
|
+
Loads data into an Anvil class.
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
#### `anvil.data`
|
|
98
|
+
|
|
99
|
+
The `ArrayBuffer` used. Nothing gets parsed right away and is all loaded and parsed on demand.
|
|
100
|
+
|
|
101
|
+
#### `anvil.getAllChunks(): Chunk[]`
|
|
102
|
+
|
|
103
|
+
Parses the NBT data and returns an array of `Chunk` instances.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
### `class Chunk`
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
// Continuing example from Anvil class
|
|
110
|
+
const chunks = anvil.getAllChunks();
|
|
111
|
+
const firstChunk = chunks[0];
|
|
112
|
+
console.log(firstChunk.chunkCoordinates()); // [0, 0]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
#### `chunk.blockEntityData(coords: Coords3d): NbtCompound | undefined`
|
|
117
|
+
|
|
118
|
+
Gets associated block entity data from the chunk. For instance, this can get a sign's text or the items in a chest. If the information is not found, this will return `undefined`.
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
#### `chunk.chunkCoordinates(): Coords2d`
|
|
122
|
+
|
|
123
|
+
Returns an array with the X and Z coordinates. The chunk's coordinates are the `xPos` and `yPos` tags, which are absolute chunk coordinates from the world origin, not from the region.
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
#### `chunk.findBlocksByName(name: string): Coords3d[]`
|
|
127
|
+
|
|
128
|
+
Returns an array. Each element in the array is another array of the X, Y, and Z coordinates of blocks. The coordinates are real-world coordinates. This method will need to unpack the block list, so it will first use a palette to see if the decompression and the lengthy scan can be avoided.
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
#### `chunk.getBlock(coords: Coords3d): GenericBlock`
|
|
132
|
+
|
|
133
|
+
Returns a block class that represents the block at the given coordinates. For known blocks, there are additional methods. See "Block Classes" for further information.
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
#### `chunk.inhabitedTime(): bigint | undefined`
|
|
137
|
+
|
|
138
|
+
Shows the number of ticks processed in the chunk. When the player is nearby, this increases at 20 ticks per second. When the player is farther away, the tick count could advance slower. Does not increment when the chunk isn't loaded.
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
#### `chunk.toObject(): object`
|
|
142
|
+
|
|
143
|
+
Converts the internal NBT structure to an object literal, which can be serialized properly with `JSON.stringify()`.
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
#### `chunk.uniqueBlockNames(): Set<string>`
|
|
147
|
+
|
|
148
|
+
Returns a list of all unique block names within a given chunk.
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
#### `chunk.worldCoordinates(): Coords2d`
|
|
152
|
+
|
|
153
|
+
Returns an array with the X and Z real-world coordinates. The chunk will span from X to X+15 (going East) and from Z to Z+15 (going South). The chunk is the entire vertical column of the world.
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
### Block Classes
|
|
157
|
+
|
|
158
|
+
All blocks will inherit from Generic. Other types of blocks are detected by their name. Below are the patterns and the type of block that will be produced if that filter matches. There's a built-in function that will be used to determine if a block is of a specific type. These are static methods on the `Block` class, which all take the name as the only parameter and return a boolean.
|
|
159
|
+
|
|
160
|
+
* `Block.isBanner(name: string): boolean` - Matches all banners
|
|
161
|
+
* `Block.isBarrel(name: string): boolean`
|
|
162
|
+
* `Block.isBeacon(name: string): boolean`
|
|
163
|
+
* `Block.isBed(name: string): boolean`
|
|
164
|
+
* `Block.isBeehive(name: string): boolean` - Matches beehives and bee nests
|
|
165
|
+
* `Block.isBell(name: string): boolean`
|
|
166
|
+
* `Block.isSign(name: string): boolean` - Matches all signs
|
|
167
|
+
|
|
168
|
+
To add to this complexity, there are many blocks that support generic methods, such as `.customName()` and `.lock()`. Those are listed under `generic` in this documentation and called out special because they are not on all block instances.
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
#### `generic.components(): NbtCompound | undefined`
|
|
172
|
+
|
|
173
|
+
Associated data components for this block.
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
#### `generic.coords: Coords3d`
|
|
177
|
+
|
|
178
|
+
The world coordinates of the block.
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
#### `generic.customName(): string | undefined`
|
|
182
|
+
|
|
183
|
+
Returns the custom name, used in the GUI when interacting with the block.
|
|
184
|
+
|
|
185
|
+
*Method only exists if block supports a custom name.*
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
#### `generic.entityData: NbtCompound | undefined`
|
|
189
|
+
|
|
190
|
+
The NBT entity data associated with this block. If there is none, this is left `undefined`.
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
#### `generic.lock(): string | undefined`
|
|
194
|
+
|
|
195
|
+
Returns the item name needed to interact with the block.
|
|
196
|
+
|
|
197
|
+
*Method only exists if block supports locking.*
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
#### `generic.name: string`
|
|
201
|
+
|
|
202
|
+
The name of the block.
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
#### `banner.patterns(): BannerPattern[]`
|
|
206
|
+
|
|
207
|
+
Returns a list of banner pattern information applied to the banner, in order.
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
interface BannerPattern {
|
|
211
|
+
color: string;
|
|
212
|
+
pattern: string | {
|
|
213
|
+
asset_id: string;
|
|
214
|
+
translation_key: string;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
#### `barrel.items(): NbtList<NbtCompound>`
|
|
221
|
+
|
|
222
|
+
The list of items in each slot of the barrel.
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
#### `barrel.lootTable(): string | undefined`
|
|
226
|
+
|
|
227
|
+
The loot table name for generating random contents.
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
#### `barrel.lootTableSeed(): bigint | undefined`
|
|
231
|
+
|
|
232
|
+
The seed to use when generating random contents. 0 means to use a random seed.
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
#### `beacon.primaryEffect(): string | undefined`
|
|
236
|
+
|
|
237
|
+
The primary effect name of the beacon.
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
#### `beacon.secondaryEffect(): string | undefined`
|
|
241
|
+
|
|
242
|
+
The secondary effect name of the beacon.
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
#### `beehive.bees(): NbtList<NbtCompound> | undefined`
|
|
246
|
+
|
|
247
|
+
Information about the bees within the beehive or bee nest.
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
#### `beehive.flowerPos(): Coords3d | undefined`
|
|
251
|
+
|
|
252
|
+
Location of the associated flower.
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
#### `sign.backColor(): string | undefined`
|
|
256
|
+
|
|
257
|
+
Returns the color of the text on the back of the sign for 1.20+. For older versions, this returns `undefined`.
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
#### `sign.backGlowingText(): boolean | undefined`
|
|
261
|
+
|
|
262
|
+
Returns `true` if the sign has glowing text on the back for 1.20+. For older versions, this returns `undefined`.
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
#### `sign.backText(): string[] | undefined`
|
|
266
|
+
|
|
267
|
+
Returns the four lines of text on the back of the sign for 1.20+. For older versions, this returns `undefined`.
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
#### `sign.frontColor(): string | undefined`
|
|
271
|
+
|
|
272
|
+
Returns the color of the text on the front of the sign.
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
#### `sign.frontGlowingText(): boolean | undefined`
|
|
276
|
+
|
|
277
|
+
Returns `true` if the sign has glowing text on the front.
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
#### `sign.frontText(): string[]`
|
|
281
|
+
|
|
282
|
+
Returns the four lines of text on the front of the sign.
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
#### `sign.isWaxed(): boolean`
|
|
286
|
+
|
|
287
|
+
Returns `true` if the sign is waxed and `false` if not for 1.20+. For older versions, this returns `undefined`.
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
### NBT Classes
|
|
291
|
+
|
|
292
|
+
There are several NBT classes that could be retrieved when you want direct access to the chunk's data. They all have a `.toJson()` method that will return an array with the name of the tag as the first element and the tag's data as the second. This is used to facilitate easier transforms into JSON.
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
#### `Nbt.fromBuffer(data: ArrayBufferLike): NbtBase<any>`
|
|
296
|
+
|
|
297
|
+
Parses NBT data. Returns one of the NBT classes below, depending on the tag's type. This does *not* deal with compressed data. It's the responsibility of the container (Anvil) to decompress the data stream before passing it to this parser.
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
#### `Nbt.fromSnbt(snbt: string): NbtBase<any>`
|
|
301
|
+
|
|
302
|
+
Parses SNBT data. Returns the hydrated NBT classes from the string form.
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
#### `Nbt.getTag(binaryData: BinaryData): NbtBase<any>`
|
|
306
|
+
|
|
307
|
+
Reads binary data from the `BinaryData` instance to determine the type, then calls the appropriate reader to provide the NBT tag.
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
#### `NbtBase.readName(binaryData: BinaryData): string`
|
|
311
|
+
|
|
312
|
+
Reads the name portion from a tag. Included in most tags.
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
#### `nbtBase.findChild(path: string): NbtBase<any> | undefined`
|
|
316
|
+
|
|
317
|
+
Finds a child by looking for exact string matches on names. Children can also be matched by using "/" as a separator, such as "Level/sections".
|
|
318
|
+
|
|
319
|
+
Only works on `NbtList` and `NbtCompound` tags. On all others, this will return `undefined`.
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
#### `nbtBase.isCompound(name: string): boolean`
|
|
323
|
+
|
|
324
|
+
Checks if this is a compound tag. If `name` is also given, this checks to see if the compound tag's name also exactly matches. If either condition is not met, this returns `false`.
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
#### `nbtBase.isList(subtype: NbtTagType): boolean`
|
|
328
|
+
|
|
329
|
+
Checks if the tag is a list. If `subtype` is also given, this checks to see if the list tag's subtype also exactly matches. If either condition is not met, this returns `false`.
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
#### `nbtBase.toObject(): any`
|
|
333
|
+
|
|
334
|
+
Returns a plain object form of the tag. If this is a compound or list, then all children are included as well.
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
#### `nbtBase.toSnbt(): string`
|
|
338
|
+
|
|
339
|
+
Converts the tag to SNBT. The conversion will write out into a standard form, not necessarily matching what was parsed. For instance, the byte value "true" would be changed to "1". Strings will all use double quotes. Other minor changes, but the output will be valid SNBT.
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
## Additional Notes
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
### Coordinate Systems
|
|
346
|
+
|
|
347
|
+
A player in Minecraft can easily determine their world coordinates. To convert
|
|
348
|
+
from world coordinates to chunk coordinates, divide the x and z world
|
|
349
|
+
coordinates by 16, rounded down. World coordinates and chunk coordinates also
|
|
350
|
+
relate similarly to regions, which are 32 x 32 chunks. The region coordinates
|
|
351
|
+
are the chunk coordinates divided by 32 and rounded down.
|
|
352
|
+
|
|
353
|
+
| Type | X | Y | Z |
|
|
354
|
+
|:------------------:|:-----:|:-----:|:-----:|
|
|
355
|
+
| World Coordinates | 1234 | 65 | -5678 |
|
|
356
|
+
| Chunk Coordinates | 77 | * | -355 |
|
|
357
|
+
| Region Coordinates | 2 | * | -12 |
|
|
358
|
+
|
|
359
|
+
Special notes about the above example:
|
|
360
|
+
|
|
361
|
+
* Rounding always rounds down. This may be tricky for negative numbers. -5678 / 16 = -354.875, so that rounds down to -355.
|
|
362
|
+
* Chunks span the entire Y column, from bedrock to the build limit.
|
|
363
|
+
* Region coordinates are used in the naming of the anvil file. The coordinates used in the example above would be in the file named `r.2.-12.mca`.
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
### Supported versions
|
|
367
|
+
|
|
368
|
+
This has been loosely tested with the following editions. Other versions should work as well. If not, please supply a test MCA file and a description of the problem, or submit a pull request.
|
|
369
|
+
|
|
370
|
+
* Java, 1.21.4, data version 4189.
|
|
371
|
+
* Java, 1.17.1, data version 2730.
|
|
372
|
+
|
|
373
|
+
Other versions can be supported through pull requests that contain tests to verify loading and processing works.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mca-chunks.d.ts","sourceRoot":"","sources":["../../src/bin/mca-chunks.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import getStdin from 'get-stdin';
|
|
3
|
+
import neodoc from 'neodoc';
|
|
4
|
+
import { Anvil } from '../lib/anvil';
|
|
5
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
6
|
+
async function readInput(filename) {
|
|
7
|
+
if (!filename || filename === '-') {
|
|
8
|
+
return await getStdin.buffer();
|
|
9
|
+
}
|
|
10
|
+
return readFile(filename);
|
|
11
|
+
}
|
|
12
|
+
const args = neodoc.run(`Usage: mca-chunks [OPTIONS] [<input> [<output>]]
|
|
13
|
+
|
|
14
|
+
Lists the chunk coordinates in a Minecraft MCA file, one set of coordinates per
|
|
15
|
+
line. Each line will have "X,Z", such as "-23,14". Both input and output are
|
|
16
|
+
optional. If input is not provided, this reads from stdin. If output is not
|
|
17
|
+
provided, this writes to stdout.
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
-h, --help Show this message.
|
|
21
|
+
`, {
|
|
22
|
+
argv: [...process.argv].slice(2),
|
|
23
|
+
laxPlacement: true,
|
|
24
|
+
});
|
|
25
|
+
readInput(args['<input>'])
|
|
26
|
+
.then((inputBuffer) => {
|
|
27
|
+
if (inputBuffer.length === 0) {
|
|
28
|
+
console.error('No input provided. Use --help for usage.');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const anvilParser = Anvil.fromBuffer(inputBuffer.buffer);
|
|
32
|
+
let chunks = anvilParser.getAllChunks();
|
|
33
|
+
return chunks.map((chunk) => chunk.chunkKey()).join('\n');
|
|
34
|
+
})
|
|
35
|
+
.then((output) => {
|
|
36
|
+
if (args['<output>']) {
|
|
37
|
+
writeFile(args['<output>'], output);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log(output);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=mca-chunks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mca-chunks.js","sourceRoot":"","sources":["../../src/bin/mca-chunks.ts"],"names":[],"mappings":";AAEA,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEvD,KAAK,UAAU,SAAS,CAAC,QAA4B;IACjD,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QAChC,OAAO,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;IACnC,CAAC;IAED,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,IAAI,GAGN,MAAM,CAAC,GAAG,CACd;;;;;;;;;CASC,EACG;IACI,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAChC,YAAY,EAAE,IAAI;CACrB,CACJ,CAAC;AAEF,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;KACrB,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;IAClB,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,MAAqB,CAAC,CAAC;IACxE,IAAI,MAAM,GAAG,WAAW,CAAC,YAAY,EAAE,CAAC;IAExC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC,CAAC;KACD,IAAI,CAAC,CAAC,MAAc,EAAE,EAAE;IACrB,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACnB,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport getStdin from 'get-stdin';\nimport neodoc from 'neodoc';\nimport { Anvil } from '../lib/anvil';\nimport { readFile, writeFile } from 'node:fs/promises';\n\nasync function readInput(filename: string | undefined) {\n if (!filename || filename === '-') {\n return await getStdin.buffer();\n }\n\n return readFile(filename);\n}\n\nconst args: {\n '<input>'?: string;\n '<output>'?: string;\n} = neodoc.run(\n`Usage: mca-chunks [OPTIONS] [<input> [<output>]]\n\nLists the chunk coordinates in a Minecraft MCA file, one set of coordinates per\nline. Each line will have \"X,Z\", such as \"-23,14\". Both input and output are\noptional. If input is not provided, this reads from stdin. If output is not\nprovided, this writes to stdout.\n\nOptions:\n -h, --help Show this message.\n`,\n {\n argv: [...process.argv].slice(2),\n laxPlacement: true,\n }\n);\n\nreadInput(args['<input>'])\n .then((inputBuffer) => {\n if (inputBuffer.length === 0) {\n console.error('No input provided. Use --help for usage.');\n process.exit(1);\n }\n\n const anvilParser = Anvil.fromBuffer(inputBuffer.buffer as ArrayBuffer);\n let chunks = anvilParser.getAllChunks();\n\n return chunks.map((chunk) => chunk.chunkKey()).join('\\n');\n })\n .then((output: string) => {\n if (args['<output>']) {\n writeFile(args['<output>'], output);\n } else {\n console.log(output);\n }\n });\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mca-find-chunks-with-signs.d.ts","sourceRoot":"","sources":["../../src/bin/mca-find-chunks-with-signs.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
import neodoc from 'neodoc';
|
|
4
|
+
import { Anvil } from '../lib/anvil';
|
|
5
|
+
import { Sign } from '../block/sign';
|
|
6
|
+
import { readFile } from 'node:fs/promises';
|
|
7
|
+
const debugLog = debug('mca-find-chunks-with-signs');
|
|
8
|
+
const args = neodoc.run(`Usage: mca-trim-chunks-without-signs [OPTIONS] MCA_FILE...
|
|
9
|
+
|
|
10
|
+
Displays chunk X and Z coordinates, separated by a tab, for all chunks in MCA
|
|
11
|
+
files that contain a sign block. Signs need to have at least one letter or
|
|
12
|
+
number on them to differentiate them from naturally generated signs.
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
-h, --help Show this message.
|
|
16
|
+
-v, --verbose Show more information during processing.
|
|
17
|
+
`, {
|
|
18
|
+
argv: [...process.argv].slice(2),
|
|
19
|
+
laxPlacement: true,
|
|
20
|
+
});
|
|
21
|
+
if (!args.MCA_FILE?.length) {
|
|
22
|
+
console.error('No files specified.');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
for (const file of args.MCA_FILE) {
|
|
26
|
+
try {
|
|
27
|
+
await processFile(file);
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
console.error(`Error processing file ${file}: ${e}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function processFile(filename) {
|
|
35
|
+
debugLog(`Reading file: ${filename}`);
|
|
36
|
+
if (args['--verbose']) {
|
|
37
|
+
console.log(`Reading file: ${filename}`);
|
|
38
|
+
}
|
|
39
|
+
const contents = await readFile(filename);
|
|
40
|
+
const anvil = Anvil.fromBuffer(contents.buffer);
|
|
41
|
+
const chunks = anvil.getAllChunks();
|
|
42
|
+
for (const chunk of chunks) {
|
|
43
|
+
const chunkKey = chunk.chunkKey() || '';
|
|
44
|
+
if (processChunk(chunk)) {
|
|
45
|
+
const coords = chunk.chunkCoordinates();
|
|
46
|
+
if (!coords) {
|
|
47
|
+
throw new Error(`Chunk ${chunkKey} has no coordinates.`);
|
|
48
|
+
}
|
|
49
|
+
console.log(`${coords[0]}\t${coords[1]}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function processChunk(chunk) {
|
|
54
|
+
const blockNames = chunk.uniqueBlockNames();
|
|
55
|
+
for (const blockName of blockNames) {
|
|
56
|
+
if (blockName.match(/^minecraft:.+_sign$/)) {
|
|
57
|
+
debugLog(`Found sign: ${blockName}`);
|
|
58
|
+
for (const coords of chunk.findBlocksByName(blockName)) {
|
|
59
|
+
const block = chunk.getBlock(coords);
|
|
60
|
+
if (!(block instanceof Sign)) {
|
|
61
|
+
throw new Error(`Block is supposed to be a sign: ${block.name}`);
|
|
62
|
+
}
|
|
63
|
+
const front = block.frontText();
|
|
64
|
+
const back = block.backText();
|
|
65
|
+
debugLog(`Front: ${JSON.stringify(front)}`);
|
|
66
|
+
debugLog(`Back: ${JSON.stringify(back)}`);
|
|
67
|
+
if ([...front, ...(back || [])].join('').match(/[a-z0-9]/i)) {
|
|
68
|
+
debugLog(`Found a user-created sign. Preserving chunk.`);
|
|
69
|
+
if (args['--verbose']) {
|
|
70
|
+
console.log(`Found a user-created sign: ${JSON.stringify(front)} and ${JSON.stringify(back)}`);
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=mca-find-chunks-with-signs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mca-find-chunks-with-signs.js","sourceRoot":"","sources":["../../src/bin/mca-find-chunks-with-signs.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport debug from 'debug';\nimport neodoc from 'neodoc';\nimport { Anvil } from '../lib/anvil';\nimport { Chunk } from '../lib/chunk';\nimport { Sign } from '../block/sign';\nimport { readFile } from 'node:fs/promises';\n\nconst debugLog = debug('mca-find-chunks-with-signs');\nconst args: {\n '--verbose'?: boolean;\n MCA_FILE?: string[];\n} = neodoc.run(\n `Usage: mca-trim-chunks-without-signs [OPTIONS] MCA_FILE...\n\nDisplays chunk X and Z coordinates, separated by a tab, for all chunks in MCA\nfiles that contain a sign block. Signs need to have at least one letter or\nnumber on them to differentiate them from naturally generated signs.\n\nOptions:\n -h, --help Show this message.\n -v, --verbose Show more information during processing.\n`,\n {\n argv: [...process.argv].slice(2),\n laxPlacement: true,\n }\n);\n\nif (!args.MCA_FILE?.length) {\n console.error('No files specified.');\n process.exit(1);\n}\n\nfor (const file of args.MCA_FILE) {\n try {\n await processFile(file);\n } catch (e) {\n console.error(`Error processing file ${file}: ${e}`);\n\n process.exit(1);\n }\n}\n\nasync function processFile(filename: string) {\n debugLog(`Reading file: ${filename}`);\n\n if (args['--verbose']) {\n console.log(`Reading file: ${filename}`);\n }\n\n const contents = await readFile(filename);\n const anvil = Anvil.fromBuffer(contents.buffer);\n const chunks = anvil.getAllChunks();\n\n for (const chunk of chunks) {\n const chunkKey = chunk.chunkKey() || '';\n\n if (processChunk(chunk)) {\n const coords = chunk.chunkCoordinates();\n\n if (!coords) {\n throw new Error(`Chunk ${chunkKey} has no coordinates.`);\n }\n\n console.log(`${coords[0]}\\t${coords[1]}`);\n }\n }\n}\n\nfunction processChunk(chunk: Chunk): boolean {\n const blockNames = chunk.uniqueBlockNames();\n\n for (const blockName of blockNames) {\n if (blockName.match(/^minecraft:.+_sign$/)) {\n debugLog(`Found sign: ${blockName}`);\n\n for (const coords of chunk.findBlocksByName(blockName)) {\n const block = chunk.getBlock(coords);\n\n if (!(block instanceof Sign)) {\n throw new Error(\n `Block is supposed to be a sign: ${block.name}`\n );\n }\n\n const front = block.frontText();\n const back = block.backText();\n debugLog(`Front: ${JSON.stringify(front)}`);\n debugLog(`Back: ${JSON.stringify(back)}`);\n\n if ([...front, ...(back || [])].join('').match(/[a-z0-9]/i)) {\n debugLog(`Found a user-created sign. Preserving chunk.`);\n\n if (args['--verbose']) {\n console.log(\n `Found a user-created sign: ${JSON.stringify(front)} and ${JSON.stringify(back)}`\n );\n }\n\n return true;\n }\n }\n }\n }\n\n return false;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mca-json.d.ts","sourceRoot":"","sources":["../../src/bin/mca-json.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import getStdin from 'get-stdin';
|
|
3
|
+
import neodoc from 'neodoc';
|
|
4
|
+
import { Anvil } from '../lib/anvil';
|
|
5
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
6
|
+
async function readInput(filename) {
|
|
7
|
+
if (!filename || filename === '-') {
|
|
8
|
+
return await getStdin.buffer();
|
|
9
|
+
}
|
|
10
|
+
return readFile(filename);
|
|
11
|
+
}
|
|
12
|
+
const args = neodoc.run(`Usage: mca-json [OPTIONS] [<input> [<output>]]
|
|
13
|
+
|
|
14
|
+
Converts a Minecraft MCA file to JSON. Both input and output are optional. If
|
|
15
|
+
input is not provided, this reads from stdin. If output is not provided, this
|
|
16
|
+
writes to stdout.
|
|
17
|
+
|
|
18
|
+
Because MCA files can contain a tremendous amount of information, the tool
|
|
19
|
+
might run out of memory. When that happens, you can dump specific chunks by
|
|
20
|
+
specifying the --chunk-coords option.
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
--chunk-coords=COORDS
|
|
24
|
+
Only write out the chunk at the specified chunk coordinates.
|
|
25
|
+
Chunk coordinates are absolute chunks from the world origin.
|
|
26
|
+
Can be specified multiple times. Coordinates are specified
|
|
27
|
+
as "x,z". Highly recommended to limit the size of the JSON
|
|
28
|
+
that's generated.
|
|
29
|
+
--compact Do not use pretty-printing in the JSON output.
|
|
30
|
+
--condense Condense arrays of bytes, ints, and longs to a single line.
|
|
31
|
+
This significantly cuts down on the size of the generated
|
|
32
|
+
JSON.
|
|
33
|
+
-h, --help Show this message.
|
|
34
|
+
`, {
|
|
35
|
+
argv: [...process.argv].slice(2),
|
|
36
|
+
laxPlacement: true,
|
|
37
|
+
});
|
|
38
|
+
readInput(args['<input>'])
|
|
39
|
+
.then((inputBuffer) => {
|
|
40
|
+
if (inputBuffer.length === 0) {
|
|
41
|
+
console.error('No input provided. Use --help for usage.');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const anvilParser = Anvil.fromBuffer(inputBuffer.buffer);
|
|
45
|
+
let chunks = anvilParser.getAllChunks();
|
|
46
|
+
if (args['--chunk-coords']) {
|
|
47
|
+
if (!Array.isArray(args['--chunk-coords'])) {
|
|
48
|
+
args['--chunk-coords'] = [args['--chunk-coords']];
|
|
49
|
+
}
|
|
50
|
+
const wanted = new Set(args['--chunk-coords']);
|
|
51
|
+
chunks = chunks.filter((chunk) => wanted.has(chunk.chunkKey()));
|
|
52
|
+
}
|
|
53
|
+
let jsonObjects = chunks.map((chunk) => chunk.toObject());
|
|
54
|
+
if (args['--compact']) {
|
|
55
|
+
return JSON.stringify(jsonObjects);
|
|
56
|
+
}
|
|
57
|
+
let content = JSON.stringify(jsonObjects, null, 4);
|
|
58
|
+
if (args['--condense']) {
|
|
59
|
+
content = content.replace(/: \[(\n\s*"?-?\d+"?,?)*\n\s*\]/g, (match) => {
|
|
60
|
+
return match.replace(/\n\s*/g, ' ');
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return content;
|
|
64
|
+
})
|
|
65
|
+
.then((output) => {
|
|
66
|
+
if (args['<output>']) {
|
|
67
|
+
writeFile(args['<output>'], output);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.log(output);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=mca-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mca-json.js","sourceRoot":"","sources":["../../src/bin/mca-json.ts"],"names":[],"mappings":";AAEA,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEvD,KAAK,UAAU,SAAS,CAAC,QAA4B;IACjD,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QAChC,OAAO,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;IACnC,CAAC;IAED,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,IAAI,GAMN,MAAM,CAAC,GAAG,CACd;;;;;;;;;;;;;;;;;;;;;;CAsBC,EACG;IACI,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAChC,YAAY,EAAE,IAAI;CACrB,CACJ,CAAC;AAEF,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;KACrB,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;IAClB,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,MAAqB,CAAC,CAAC;IACxE,IAAI,MAAM,GAAG,WAAW,CAAC,YAAY,EAAE,CAAC;IAExC,IAAI,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,GAAG,CAAqB,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACnE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE1D,IAAI,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEnD,IAAI,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACrB,OAAO,GAAG,OAAO,CAAC,OAAO,CACrB,iCAAiC,EACjC,CAAC,KAAK,EAAE,EAAE;YACN,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACxC,CAAC,CACJ,CAAC;IACN,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;KACD,IAAI,CAAC,CAAC,MAAc,EAAE,EAAE;IACrB,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACnB,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport getStdin from 'get-stdin';\nimport neodoc from 'neodoc';\nimport { Anvil } from '../lib/anvil';\nimport { readFile, writeFile } from 'node:fs/promises';\n\nasync function readInput(filename: string | undefined) {\n if (!filename || filename === '-') {\n return await getStdin.buffer();\n }\n\n return readFile(filename);\n}\n\nconst args: {\n '--chunk-coords'?: string | string[];\n '--compact'?: boolean;\n '--condense'?: boolean;\n '<input>'?: string;\n '<output>'?: string;\n} = neodoc.run(\n`Usage: mca-json [OPTIONS] [<input> [<output>]]\n\nConverts a Minecraft MCA file to JSON. Both input and output are optional. If\ninput is not provided, this reads from stdin. If output is not provided, this\nwrites to stdout.\n\nBecause MCA files can contain a tremendous amount of information, the tool\nmight run out of memory. When that happens, you can dump specific chunks by\nspecifying the --chunk-coords option.\n\nOptions:\n --chunk-coords=COORDS\n Only write out the chunk at the specified chunk coordinates.\n Chunk coordinates are absolute chunks from the world origin.\n Can be specified multiple times. Coordinates are specified\n as \"x,z\". Highly recommended to limit the size of the JSON\n that's generated.\n --compact Do not use pretty-printing in the JSON output.\n --condense Condense arrays of bytes, ints, and longs to a single line.\n This significantly cuts down on the size of the generated\n JSON.\n -h, --help Show this message.\n`,\n {\n argv: [...process.argv].slice(2),\n laxPlacement: true,\n }\n);\n\nreadInput(args['<input>'])\n .then((inputBuffer) => {\n if (inputBuffer.length === 0) {\n console.error('No input provided. Use --help for usage.');\n process.exit(1);\n }\n\n const anvilParser = Anvil.fromBuffer(inputBuffer.buffer as ArrayBuffer);\n let chunks = anvilParser.getAllChunks();\n\n if (args['--chunk-coords']) {\n if (!Array.isArray(args['--chunk-coords'])) {\n args['--chunk-coords'] = [args['--chunk-coords']];\n }\n\n const wanted = new Set<string | undefined>(args['--chunk-coords']);\n chunks = chunks.filter((chunk) => wanted.has(chunk.chunkKey()));\n }\n\n let jsonObjects = chunks.map((chunk) => chunk.toObject());\n\n if (args['--compact']) {\n return JSON.stringify(jsonObjects);\n }\n\n let content = JSON.stringify(jsonObjects, null, 4);\n\n if (args['--condense']) {\n content = content.replace(\n /: \\[(\\n\\s*\"?-?\\d+\"?,?)*\\n\\s*\\]/g,\n (match) => {\n return match.replace(/\\n\\s*/g, ' ');\n }\n );\n }\n\n return content;\n })\n .then((output: string) => {\n if (args['<output>']) {\n writeFile(args['<output>'], output);\n } else {\n console.log(output);\n }\n });\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mca-trim-chunks-without-signs.d.ts","sourceRoot":"","sources":["../../src/bin/mca-trim-chunks-without-signs.ts"],"names":[],"mappings":""}
|