├── .editorconfig ├── .gitignore ├── .jshintrc ├── .travis.yml ├── Changelog.md ├── License.md ├── Makefile ├── Readme.md ├── docs ├── fonts │ ├── OpenSans-Bold-webfont.eot │ ├── OpenSans-Bold-webfont.svg │ ├── OpenSans-Bold-webfont.woff │ ├── OpenSans-BoldItalic-webfont.eot │ ├── OpenSans-BoldItalic-webfont.svg │ ├── OpenSans-BoldItalic-webfont.woff │ ├── OpenSans-Italic-webfont.eot │ ├── OpenSans-Italic-webfont.svg │ ├── OpenSans-Italic-webfont.woff │ ├── OpenSans-Light-webfont.eot │ ├── OpenSans-Light-webfont.svg │ ├── OpenSans-Light-webfont.woff │ ├── OpenSans-LightItalic-webfont.eot │ ├── OpenSans-LightItalic-webfont.svg │ ├── OpenSans-LightItalic-webfont.woff │ ├── OpenSans-Regular-webfont.eot │ ├── OpenSans-Regular-webfont.svg │ └── OpenSans-Regular-webfont.woff ├── index.html ├── module-nbt.Reader.html ├── module-nbt.Writer.html ├── module-nbt.html ├── nbt.js.html ├── scripts │ ├── linenumber.js │ └── prettify │ │ ├── Apache-License-2.0.txt │ │ ├── lang-css.js │ │ └── prettify.js └── styles │ ├── jsdoc-default.css │ ├── prettify-jsdoc.css │ └── prettify-tomorrow.css ├── fixtures ├── bigtest.json ├── bigtest.json.js ├── bigtest.nbt ├── bigtest.nbt.gz ├── bigtest.nbt.gz.js ├── bigtest.nbt.js └── longArrayTest.nbt.gz ├── nbt.d.ts ├── nbt.js ├── package.json ├── sample ├── .jshintrc └── sample.js └── test ├── .jshintrc ├── nbt-spec.js ├── polyfills.js ├── reader-spec.js ├── test.html └── writer-spec.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | 7 | [Makefile] 8 | indent_style = tab 9 | indent_size = 8 10 | max_line_length = 78 11 | 12 | [{nbt.js,sample/*.js,test/*.js}] 13 | indent_style = tab 14 | indent_size = 4 15 | max_line_length = 78 16 | 17 | [{package.json,.travis.yml}] 18 | indent_style = space 19 | indent_size = 2 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | *.swp 4 | results.txt 5 | 6 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "window": true, 4 | "exports": true, 5 | "require": true, 6 | "Buffer": true, 7 | "ArrayBuffer": true, 8 | "DataView": true, 9 | "Uint8Array": true 10 | }, 11 | 12 | "camelcase": true, 13 | "curly": true, 14 | "eqeqeq": true, 15 | "forin": true, 16 | "latedef": true, 17 | "noarg": true, 18 | "nonbsp": true, 19 | "nonew": true, 20 | "smarttabs": true, 21 | "strict": true, 22 | "sub": true, 23 | "trailing": true, 24 | "unused": true, 25 | "undef": true 26 | } 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | 0.8.1 (2018-12-16) 5 | ----------------- 6 | 7 | * Fixed version in package.json 8 | 9 | 0.8.0 (2018-12-16) 10 | ------------------ 11 | 12 | * New: longArray data type (thanks sourcehunter). 13 | * Change: dropped linting tools and PhantomJS tests. 14 | 15 | 0.7.0 16 | ----- 17 | 18 | * Feature: browser support, simply include nbt.js as-is. 19 | * Feature: new Reader/Writer.ubyte() for unsigned bytes. 20 | * Improvement: JSDoc documentation added. 21 | * Improvement: updated dependencies and upgraded to Node 6. 22 | * Improvement: simplified build by using make instead of grunt. 23 | * Improvement: added .editorconfig. 24 | * Improvement: automated code style checking with eclint. 25 | * Improvement: automatic NPM deployments with Travis CI. 26 | 27 | 0.6.0 28 | ----- 29 | 30 | The big change here is that `parse()` now returns a consistent format again: 31 | 32 | parse(foo); // -> { name: 'Level', value: { ... } } 33 | 34 | Similarly, that's what `writeUncompressed()` as well now: 35 | 36 | writeUncompressed({ name: 'Level', value: { ... } }); 37 | 38 | * Improvement: dropped unused jasmine package dependency. 39 | * Improvement: [#13] read() and write() cycles are now guaranteed to be 40 | idempotent. 41 | * Improvement: [#14] back to consistent structure for parse() result. 42 | * Improvement: [#15] `writer.byteArray()` now accepts both arrays and 43 | `Buffer`s. 44 | * Fix: parse() would always throw when used on non-gzipped data. 45 | 46 | 0.5.0 47 | ----- 48 | 49 | A merge and slight rework of the terrific improvements by the people at 50 | [ProsmarineJS](https://github.com/PrismarineJS/prismarine-nbt). 51 | 52 | * Feature: support for writing archives (to a `Buffer`). 53 | * Improvement: switch to Mocha testing framwork. 54 | * Improvement: `Reader.offset` is now exposed. 55 | * Improvement: 64 bit values now represented as [upper, lower] pairs for 56 | better portability. 57 | * Improvement: exposed `nbt.writeUncompressed`, which is sync as opposed 58 | to its unzipping counterpart. 59 | * Improvement: lists and compounds now return type information. This creates 60 | a symetry because this output can be fed into the writer as-is. 61 | 62 | 0.4.0 63 | ----- 64 | 65 | * Feature: the `Reader` constructor is now public and can be used eo read 66 | individual NBT elements from a buffer. 67 | * Feature: support for `npm test` using the previously built testing 68 | infrastructure. 69 | * Improvement: greatly expanded test coverage. 70 | * Improvement: byte array values are now returned as arrays rather than 71 | Buffer objects. 72 | * Improvement: continuous integration with Travis now runs test against the 73 | GitHub repository. 74 | * Improvement: added a changelog. 75 | * Fix: the long reader returned incorrect values due to an operator 76 | precedence issue. 77 | 78 | 0.3.0 79 | ----- 80 | 81 | * Improvement: jshint Grunt task for checking code quality. 82 | * Improvement: small fixes throughout based on jshint tips. 83 | * Improvement: added various unit tests with Jasmine. 84 | * Improvement: added links in documentation for easy lookup. 85 | * Improvement: dropped bundled binary library for built-in `Buffer`. 86 | 87 | 0.2.0 88 | ----- 89 | 90 | * Feature: support for gzipped archives. 91 | * Feature: support for int arrays (type 11). 92 | * Improvement: when the root node is a compound with no name, only the value 93 | is returned. 94 | * Improvement: better documentation. 95 | * Improvement: when an error occurs, an Error is thrown rather than as 96 | string. 97 | 98 | 0.1.0 99 | ----- 100 | 101 | Initial release. 102 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | I, the copyright holder of this work, hereby release it into the public 2 | domain. This applies worldwide. 3 | 4 | In case this is not legally possible: I grant anyone the right to use this 5 | work for any purpose, without any conditions, unless such conditions are 6 | required by law. 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NODE = node 2 | JSTEST = node_modules/.bin/mocha 3 | JSDOC = node_modules/.bin/jsdoc 4 | 5 | .PHONY: check doc watch 6 | 7 | all: 8 | @echo "Run 'make check' to lint and run tests." 9 | 10 | check: 11 | cd sample && $(NODE) sample.js > /dev/null 12 | $(JSTEST) test/*-spec.js 13 | 14 | doc: 15 | rm -rf docs/ 16 | $(JSDOC) -d docs/ Readme.md nbt.js 17 | 18 | watch: 19 | while true; do clear; $(MAKE) check; sleep 4; done 20 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | **Note:** this repository is archived. 2 | 3 | When I started this project, I was deeply involved with both Minecraft 4 | and JavaScript. Since then, my involvement with both has waned and the 5 | JavaScript landscape has moved at an incredible pace. 6 | 7 | Without a clear vision and no dogfooding, I'm no longer the right 8 | maintainer for this project and hence have archived this repository. 9 | There are a good few forks out there which I encourage anyone to seek 10 | out and give a try. 11 | 12 | Apologetically yours, 13 | 14 | Sijmen 15 | ___ 16 | 17 | NBT.js [![Build Status](https://travis-ci.org/sjmulder/nbt-js.png)](https://travis-ci.org/sjmulder/nbt-js) 18 | ====== 19 | 20 | By Sijmen Mulder and a host of wonderful contributors. 21 | 22 | NBT.js is a JavaScript parser and serializer for [NBT](http://wiki.vg/NBT) 23 | archives, for use with [Node.js](http://nodejs.org/) or the browser. 24 | 25 | 26 | Usage 27 | ----- 28 | 29 | After `var nbt = require('nbt')` or ``, you can 30 | use `nbt.parse(data, callback)` to convert NBT data into a regular JavaScript 31 | object. 32 | 33 | ```js 34 | var fs = require('fs'), 35 | nbt = require('nbt'); 36 | 37 | var data = fs.readFileSync('fixtures/bigtest.nbt.gz'); 38 | nbt.parse(data, function(error, data) { 39 | if (error) { throw error; } 40 | 41 | console.log(data.value.stringTest.value); 42 | console.log(data.value['nested compound test'].value); 43 | }); 44 | ``` 45 | 46 | If the data is gzipped, it is automatically decompressed first. When running 47 | in the browser, `window.zlib` is required for this to work. 48 | 49 | Tag names are copied verbatim, and as some names are not valid JavaScript 50 | names, use of the indexer may be required – such as with the nested 51 | compound test in the example above. 52 | 53 | 54 | API documentation 55 | ----------------- 56 | 57 | The full documentation generated with JSDoc is available in the docs/ 58 | directory and online: 59 | 60 | http://sjmulder.github.io/nbt-js/ 61 | 62 | 63 | Development and testing 64 | ----------------------- 65 | 66 | ```bash 67 | npm install # Install development dependencies 68 | make check # Check code quality with jshint and run tests 69 | make watch # Automatically runs 'make check' every few seconds 70 | make doc # Regenerate the documentation in docs/ 71 | ``` 72 | 73 | Copyright 74 | --------- 75 | 76 | I, the copyright holder of this work, hereby release it into the public 77 | domain. This applies worldwide. 78 | 79 | In case this is not legally possible: I grant anyone the right to use this 80 | work for any purpose, without any conditions, unless such conditions are 81 | required by law. 82 | -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-BoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-BoldItalic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-BoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-BoldItalic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Italic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-Italic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Italic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-Italic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-LightItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-LightItalic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-LightItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-LightItalic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/docs/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Home 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Home

21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |

30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |

NBT.js Build Status

By Sijmen Mulder and a host of wonderful contributors.

47 |

NBT.js is a JavaScript parser and serializer for NBT 48 | archives, for use with Node.js or the browser.

49 |

Usage

After var nbt = require('nbt') or <script src="nbt.js"></script>, you can 50 | use nbt.parse(data, callback) to convert NBT data into a regular JavaScript 51 | object.

52 |
var fs = require('fs'),
53 |     nbt = require('nbt');
54 | 
55 | var data = fs.readFileSync('fixtures/bigtest.nbt.gz');
56 | nbt.parse(data, function(error, data) {
57 |     if (error) { throw error; }
58 | 
59 |     console.log(data.value.stringTest.value);
60 |     console.log(data.value['nested compound test'].value);
61 | });

If the data is gzipped, it is automatically decompressed first. When running 62 | in the browser, window.zlib is required for this to work.

63 |

Tag names are copied verbatim, and as some names are not valid JavaScript 64 | names, use of the indexer may be required – such as with the nested 65 | compound test in the example above.

66 |

API documentation

The full documentation generated with JSDoc is available in the docs/ 67 | directory and online:

68 |

http://sjmulder.github.io/nbt-js/

69 |

Development and testing

npm install  # Install development dependencies
70 | make check   # Check code quality with jshint and run tests
71 | make watch   # Automatically runs 'make check' every few seconds
72 | make doc     # Regenerate the documentation in docs/

Copyright

I, the copyright holder of this work, hereby release it into the public 73 | domain. This applies worldwide.

74 |

In case this is not legally possible: I grant anyone the right to use this 75 | work for any purpose, without any conditions, unless such conditions are 76 | required by law.

77 |
78 | 79 | 80 | 81 | 82 | 83 | 84 |
85 | 86 | 89 | 90 |
91 | 92 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/module-nbt.Reader.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Class: Reader 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Class: Reader

21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 |

32 | nbt.Reader()

33 | 34 | 35 |
36 | 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |

new Reader()

46 | 47 | 48 | 49 | 50 | 51 | 52 |
53 | In addition to the named writing methods documented below, 54 | the same methods are indexed by the NBT type number as well, 55 | as shown in the example below. 56 |
57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 |
Source:
98 |
101 | 102 | 103 | 104 | 105 | 106 |
See:
107 |
108 | 111 |
112 | 113 | 114 | 115 |
116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 |
Example
134 | 135 |
var reader = new nbt.Reader(buf);
 136 | int x = reader.int();
 137 | int y = reader[3]();
 138 | int z = reader[nbt.tagTypes.int]();
139 | 140 | 141 | 142 | 143 |
144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 |

Members

159 | 160 | 161 | 162 |

offset :number

163 | 164 | 165 | 166 | 167 |
168 | The current location in the buffer. Can be freely changed 169 | within the bounds of the buffer. 170 |
171 | 172 | 173 | 174 |
Type:
175 |
    176 |
  • 177 | 178 | number 179 | 180 | 181 |
  • 182 |
183 | 184 | 185 | 186 | 187 | 188 |
189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 |
Source:
216 |
219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 |
227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 |

Methods

238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 |

byte() → {number}

246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 |
265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 |
Source:
292 |
295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 |
303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 |
Returns:
317 | 318 | 319 |
320 | the read byte 321 |
322 | 323 | 324 | 325 |
326 |
327 | Type 328 |
329 |
330 | 331 | number 332 | 333 | 334 |
335 |
336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 |

byte() → {number}

350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 |
369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 |
Source:
396 |
399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 |
407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 |
Returns:
421 | 422 | 423 |
424 | the read unsigned byte 425 |
426 | 427 | 428 | 429 |
430 |
431 | Type 432 |
433 |
434 | 435 | number 436 | 437 | 438 |
439 |
440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 |

byteArray() → {Array.<number>}

454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 |
473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 |
Source:
500 |
503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 |
511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 |
Returns:
525 | 526 | 527 |
528 | the read array 529 |
530 | 531 | 532 | 533 |
534 |
535 | Type 536 |
537 |
538 | 539 | Array.<number> 540 | 541 | 542 |
543 |
544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 |

compound() → {Object.<string, {type: string, value}>}

558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 |
577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 |
Source:
604 |
607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 |
615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 |
Returns:
629 | 630 | 631 | 632 | 633 |
634 |
635 | Type 636 |
637 |
638 | 639 | Object.<string, {type: string, value}> 640 | 641 | 642 |
643 |
644 | 645 | 646 | 647 | 648 | 649 | 650 |
Example
651 | 652 |
reader.compound();
 653 | // -> { foo: { type: int, value: 42 },
 654 | //      bar: { type: string, value: 'Hello! }}
655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 |

double() → {number}

665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 |
684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 |
Source:
711 |
714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 |
722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 |
Returns:
736 | 737 | 738 |
739 | the read signed 64-bit float 740 |
741 | 742 | 743 | 744 |
745 |
746 | Type 747 |
748 |
749 | 750 | number 751 | 752 | 753 |
754 |
755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 |

float() → {number}

769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 |
788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 |
Source:
815 |
818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 |
826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 |
Returns:
840 | 841 | 842 |
843 | the read signed 32-bit float 844 |
845 | 846 | 847 | 848 |
849 |
850 | Type 851 |
852 |
853 | 854 | number 855 | 856 | 857 |
858 |
859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 |

int() → {number}

873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 |
892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 |
Source:
919 |
922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 |
930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 |
Returns:
944 | 945 | 946 |
947 | the read signed 32-bit integer 948 |
949 | 950 | 951 | 952 |
953 |
954 | Type 955 |
956 |
957 | 958 | number 959 | 960 | 961 |
962 |
963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 |

intArray() → {Array.<number>}

977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 |
996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 |
Source:
1023 |
1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 |
1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 |
Returns:
1048 | 1049 | 1050 |
1051 | the read array of 32-bit ints 1052 |
1053 | 1054 | 1055 | 1056 |
1057 |
1058 | Type 1059 |
1060 |
1061 | 1062 | Array.<number> 1063 | 1064 | 1065 |
1066 |
1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 |

list() → {Object}

1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 |
1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 |
Source:
1127 |
1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 |
1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 |
Returns:
1152 | 1153 | 1154 | 1155 | 1156 |
1157 |
1158 | Type 1159 |
1160 |
1161 | 1162 | Object 1163 | 1164 | 1165 |
1166 |
1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 |
Example
1174 | 1175 |
reader.list();
1176 | // -> { type: 'string', values: ['foo', 'bar'] }
1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 |

long() → {Array.<number>}

1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 |
1194 | As JavaScript does not not natively support 64-bit 1195 | integers, the value is returned as an array of two 1196 | 32-bit integers, the upper and the lower. 1197 |
1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 |
1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 |
Source:
1239 |
1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 |
1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 |
Returns:
1264 | 1265 | 1266 |
1267 | [upper, lower] 1268 |
1269 | 1270 | 1271 | 1272 |
1273 |
1274 | Type 1275 |
1276 |
1277 | 1278 | Array.<number> 1279 | 1280 | 1281 |
1282 |
1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 |

longArray() → {Array.<number>}

1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 |
1304 | As JavaScript does not not natively support 64-bit 1305 | integers, the value is returned as an array of arrays of two 1306 | 32-bit integers, the upper and the lower. 1307 |
1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | 1321 |
1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 |
Source:
1349 |
1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 |
1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 |
Returns:
1374 | 1375 | 1376 |
1377 | the read array of 64-bit ints 1378 | split into [upper, lower] 1379 |
1380 | 1381 | 1382 | 1383 |
1384 |
1385 | Type 1386 |
1387 |
1388 | 1389 | Array.<number> 1390 | 1391 | 1392 |
1393 |
1394 | 1395 | 1396 | 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1407 |

short() → {number}

1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 |
1427 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1437 | 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1445 | 1446 | 1447 | 1448 | 1449 | 1450 | 1451 | 1452 | 1453 |
Source:
1454 |
1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 |
1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 |
Returns:
1479 | 1480 | 1481 |
1482 | the read signed 16-bit short 1483 |
1484 | 1485 | 1486 | 1487 |
1488 |
1489 | Type 1490 |
1491 |
1492 | 1493 | number 1494 | 1495 | 1496 |
1497 |
1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 |

string() → {string}

1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 |
1531 | 1532 | 1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 |
Source:
1558 |
1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1567 | 1568 |
1569 | 1570 | 1571 | 1572 | 1573 | 1574 | 1575 | 1576 | 1577 | 1578 | 1579 | 1580 | 1581 | 1582 |
Returns:
1583 | 1584 | 1585 |
1586 | the read string 1587 |
1588 | 1589 | 1590 | 1591 |
1592 |
1593 | Type 1594 |
1595 |
1596 | 1597 | string 1598 | 1599 | 1600 |
1601 |
1602 | 1603 | 1604 | 1605 | 1606 | 1607 | 1608 | 1609 | 1610 | 1611 | 1612 | 1613 | 1614 | 1615 |
1616 | 1617 |
1618 | 1619 | 1620 | 1621 | 1622 |
1623 | 1624 | 1627 | 1628 |
1629 | 1630 | 1633 | 1634 | 1635 | 1636 | 1637 | -------------------------------------------------------------------------------- /docs/module-nbt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Module: nbt 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Module: nbt

21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 |
34 | 35 |
36 |
37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 |

Classes

50 | 51 |
52 |
Reader
53 |
54 | 55 |
Writer
56 |
57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |

Members

68 | 69 | 70 | 71 |

(static) tagTypeNames :Object.<number, string>

72 | 73 | 74 | 75 | 76 |
77 | A mapping from NBT type numbers to type names. 78 |
79 | 80 | 81 | 82 |
Type:
83 |
    84 |
  • 85 | 86 | Object.<number, string> 87 | 88 | 89 |
  • 90 |
91 | 92 | 93 | 94 | 95 | 96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 |
Source:
124 |
127 | 128 | 129 | 130 | 131 | 132 |
See:
133 |
134 | 137 |
138 | 139 | 140 | 141 |
142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 |

(static) tagTypes :Object.<string, number>

151 | 152 | 153 | 154 | 155 |
156 | A mapping from type names to NBT type numbers. 157 | module:nbt.Writer and module:nbt.Reader 158 | have correspoding methods (e.g. module:nbt.Writer#int) 159 | for every type. 160 |
161 | 162 | 163 | 164 |
Type:
165 |
    166 |
  • 167 | 168 | Object.<string, number> 169 | 170 | 171 |
  • 172 |
173 | 174 | 175 | 176 | 177 | 178 |
179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 |
Source:
206 |
209 | 210 | 211 | 212 | 213 | 214 |
See:
215 |
216 | 219 |
220 | 221 | 222 | 223 |
224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 |

Methods

235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 |

(static) parse(data, callback)

243 | 244 | 245 | 246 | 247 | 248 | 249 |
250 | This accepts both gzipped and uncompressd NBT archives. 251 | If the archive is uncompressed, the callback will be 252 | called directly from this method. For gzipped files, the 253 | callback is async. 254 | 255 | For use in the browser, window.zlib must be defined to decode 256 | compressed archives. It will be passed a Buffer if the type is 257 | available, or an Uint8Array otherwise. 258 |
259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 |
Parameters:
269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 |
NameTypeDescription
data 297 | 298 | 299 | ArrayBuffer 300 | | 301 | 302 | Buffer 303 | 304 | 305 | 306 | gzipped or uncompressed data
callback 323 | 324 | 325 | parseCallback 326 | 327 | 328 | 329 |
341 | 342 | 343 | 344 | 345 | 346 | 347 |
348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 |
Source:
375 |
378 | 379 | 380 | 381 | 382 | 383 |
See:
384 |
385 | 390 |
391 | 392 | 393 | 394 |
395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 |
Example
413 | 414 |
nbt.parse(buf, function(error, results) {
 415 |     if (error) {
 416 |         throw error;
 417 |     }
 418 |     console.log(result.name);
 419 |     console.log(result.value.foo);
 420 | });
421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 |

(static) parseUncompressed(data) → {Object}

431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 |
Parameters:
446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 |
NameTypeDescription
data 474 | 475 | 476 | ArrayBuffer 477 | | 478 | 479 | Buffer 480 | 481 | 482 | 483 | an uncompressed NBT archive
495 | 496 | 497 | 498 | 499 | 500 | 501 |
502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 |
Source:
529 |
532 | 533 | 534 | 535 | 536 | 537 |
See:
538 |
539 | 544 |
545 | 546 | 547 | 548 |
549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 |
Returns:
563 | 564 | 565 |
566 | a named compound 567 |
568 | 569 | 570 | 571 |
572 |
573 | Type 574 |
575 |
576 | 577 | Object 578 | 579 | 580 |
581 |
582 | 583 | 584 | 585 | 586 | 587 | 588 |
Example
589 | 590 |
nbt.readUncompressed(buf);
 591 | // -> { name: 'My Level',
 592 | //      value: { foo: { type: int, value: 42 },
 593 | //               bar: { type: string, value: 'Hi!' }}}
594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 |

(static) writeUncompressed(value) → {ArrayBuffer}

604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 |
Parameters:
619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 654 | 655 | 656 | 657 | 658 | 659 | 732 | 733 | 734 | 735 | 736 |
NameTypeDescription
value 647 | 648 | 649 | Object 650 | 651 | 652 | 653 | a named compound 660 |
Properties
661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 |
NameTypeDescription
name 689 | 690 | 691 | string 692 | 693 | 694 | 695 | the top-level name
value 712 | 713 | 714 | Object 715 | 716 | 717 | 718 | a compound
730 | 731 |
737 | 738 | 739 | 740 | 741 | 742 | 743 |
744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 |
Source:
771 |
774 | 775 | 776 | 777 | 778 | 779 |
See:
780 |
781 | 786 |
787 | 788 | 789 | 790 |
791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 |
Returns:
805 | 806 | 807 | 808 | 809 |
810 |
811 | Type 812 |
813 |
814 | 815 | ArrayBuffer 816 | 817 | 818 |
819 |
820 | 821 | 822 | 823 | 824 | 825 | 826 |
Example
827 | 828 |
nbt.writeUncompressed({
 829 |     name: 'My Level',
 830 |     value: {
 831 |         foo: { type: int, value: 42 },
 832 |         bar: { type: string, value: 'Hi!' }
 833 |     }
 834 | });
835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 |

Type Definitions

843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 |

parseCallback(error, result)

851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 |
Parameters:
866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 924 | 925 | 926 | 927 | 928 | 929 | 1002 | 1003 | 1004 | 1005 | 1006 |
NameTypeDescription
error 894 | 895 | 896 | Object 897 | 898 | 899 | 900 |
result 917 | 918 | 919 | Object 920 | 921 | 922 | 923 | a named compound 930 |
Properties
931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 |
NameTypeDescription
name 959 | 960 | 961 | string 962 | 963 | 964 | 965 | the top-level name
value 982 | 983 | 984 | Object 985 | 986 | 987 | 988 | the top-level compound
1000 | 1001 |
1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 |
1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 |
Source:
1041 |
1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 |
1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 |
1075 | 1076 |
1077 | 1078 | 1079 | 1080 | 1081 |
1082 | 1083 | 1086 | 1087 |
1088 | 1089 | 1092 | 1093 | 1094 | 1095 | 1096 | -------------------------------------------------------------------------------- /docs/nbt.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Source: nbt.js 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Source: nbt.js

21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
/*
 30 | 	NBT.js - a JavaScript parser for NBT archives
 31 | 	by Sijmen Mulder
 32 | 
 33 | 	I, the copyright holder of this work, hereby release it into the public
 34 | 	domain. This applies worldwide.
 35 | 
 36 | 	In case this is not legally possible: I grant anyone the right to use this
 37 | 	work for any purpose, without any conditions, unless such conditions are
 38 | 	required by law.
 39 | */
 40 | 
 41 | (function() {
 42 | 	'use strict';
 43 | 
 44 | 	if (typeof ArrayBuffer === 'undefined') {
 45 | 		throw new Error('Missing required type ArrayBuffer');
 46 | 	}
 47 | 	if (typeof DataView === 'undefined') {
 48 | 		throw new Error('Missing required type DataView');
 49 | 	}
 50 | 	if (typeof Uint8Array === 'undefined') {
 51 | 		throw new Error('Missing required type Uint8Array');
 52 | 	}
 53 | 
 54 | 	/** @exports nbt */
 55 | 
 56 | 	var nbt = this;
 57 | 	var zlib = typeof require !== 'undefined' ? require('zlib') : window.zlib;
 58 | 
 59 | 	/**
 60 | 	 * A mapping from type names to NBT type numbers.
 61 | 	 * {@link module:nbt.Writer} and {@link module:nbt.Reader}
 62 | 	 * have correspoding methods (e.g. {@link module:nbt.Writer#int})
 63 | 	 * for every type.
 64 | 	 *
 65 | 	 * @type Object<string, number>
 66 | 	 * @see module:nbt.tagTypeNames */
 67 | 	nbt.tagTypes = {
 68 | 		'end': 0,
 69 | 		'byte': 1,
 70 | 		'short': 2,
 71 | 		'int': 3,
 72 | 		'long': 4,
 73 | 		'float': 5,
 74 | 		'double': 6,
 75 | 		'byteArray': 7,
 76 | 		'string': 8,
 77 | 		'list': 9,
 78 | 		'compound': 10,
 79 | 		'intArray': 11,
 80 | 		'longArray': 12
 81 | 	};
 82 | 
 83 | 	/**
 84 | 	 * A mapping from NBT type numbers to type names.
 85 | 	 *
 86 | 	 * @type Object<number, string>
 87 | 	 * @see module:nbt.tagTypes */
 88 | 	nbt.tagTypeNames = {};
 89 | 	(function() {
 90 | 		for (var typeName in nbt.tagTypes) {
 91 | 			if (nbt.tagTypes.hasOwnProperty(typeName)) {
 92 | 				nbt.tagTypeNames[nbt.tagTypes[typeName]] = typeName;
 93 | 			}
 94 | 		}
 95 | 	})();
 96 | 
 97 | 	function hasGzipHeader(data) {
 98 | 		var head = new Uint8Array(data.slice(0, 2));
 99 | 		return head.length === 2 && head[0] === 0x1f && head[1] === 0x8b;
100 | 	}
101 | 
102 | 	function encodeUTF8(str) {
103 | 		var array = [], i, c;
104 | 		for (i = 0; i < str.length; i++) {
105 | 			c = str.charCodeAt(i);
106 | 			if (c < 0x80) {
107 | 				array.push(c);
108 | 			} else if (c < 0x800) {
109 | 				array.push(0xC0 | c >> 6);
110 | 				array.push(0x80 | c         & 0x3F);
111 | 			} else if (c < 0x10000) {
112 | 				array.push(0xE0 |  c >> 12);
113 | 				array.push(0x80 | (c >>  6) & 0x3F);
114 | 				array.push(0x80 |  c        & 0x3F);
115 | 			} else {
116 | 				array.push(0xF0 | (c >> 18) & 0x07);
117 | 				array.push(0x80 | (c >> 12) & 0x3F);
118 | 				array.push(0x80 | (c >>  6) & 0x3F);
119 | 				array.push(0x80 |  c        & 0x3F);
120 | 			}
121 | 		}
122 | 		return array;
123 | 	}
124 | 
125 | 	function decodeUTF8(array) {
126 | 		var codepoints = [], i;
127 | 		for (i = 0; i < array.length; i++) {
128 | 			if ((array[i] & 0x80) === 0) {
129 | 				codepoints.push(array[i] & 0x7F);
130 | 			} else if (i+1 < array.length &&
131 | 						(array[i]   & 0xE0) === 0xC0 &&
132 | 						(array[i+1] & 0xC0) === 0x80) {
133 | 				codepoints.push(
134 | 					((array[i]   & 0x1F) << 6) |
135 | 					( array[i+1] & 0x3F));
136 | 			} else if (i+2 < array.length &&
137 | 						(array[i]   & 0xF0) === 0xE0 &&
138 | 						(array[i+1] & 0xC0) === 0x80 &&
139 | 						(array[i+2] & 0xC0) === 0x80) {
140 | 				codepoints.push(
141 | 					((array[i]   & 0x0F) << 12) |
142 | 					((array[i+1] & 0x3F) <<  6) |
143 | 					( array[i+2] & 0x3F));
144 | 			} else if (i+3 < array.length &&
145 | 						(array[i]   & 0xF8) === 0xF0 &&
146 | 						(array[i+1] & 0xC0) === 0x80 &&
147 | 						(array[i+2] & 0xC0) === 0x80 &&
148 | 						(array[i+3] & 0xC0) === 0x80) {
149 | 				codepoints.push(
150 | 					((array[i]   & 0x07) << 18) |
151 | 					((array[i+1] & 0x3F) << 12) |
152 | 					((array[i+2] & 0x3F) <<  6) |
153 | 					( array[i+3] & 0x3F));
154 | 			}
155 | 		}
156 | 		return String.fromCharCode.apply(null, codepoints);
157 | 	}
158 | 
159 | 	/* Not all environments, in particular PhantomJS, supply
160 | 	   Uint8Array.slice() */
161 | 	function sliceUint8Array(array, begin, end) {
162 | 		if ('slice' in array) {
163 | 			return array.slice(begin, end);
164 | 		} else {
165 | 			return new Uint8Array([].slice.call(array, begin, end));
166 | 		}
167 | 	}
168 | 
169 | 	/**
170 | 	 * In addition to the named writing methods documented below,
171 | 	 * the same methods are indexed by the NBT type number as well,
172 | 	 * as shown in the example below.
173 | 	 *
174 | 	 * @constructor
175 | 	 * @see module:nbt.Reader
176 | 	 *
177 | 	 * @example
178 | 	 * var writer = new nbt.Writer();
179 | 	 *
180 | 	 * // all equivalent
181 | 	 * writer.int(42);
182 | 	 * writer[3](42);
183 | 	 * writer(nbt.tagTypes.int)(42);
184 | 	 *
185 | 	 * // overwrite the second int
186 | 	 * writer.offset = 0;
187 | 	 * writer.int(999);
188 | 	 *
189 | 	 * return writer.buffer; */
190 | 	nbt.Writer = function() {
191 | 		var self = this;
192 | 
193 | 		/* Will be resized (x2) on write if necessary. */
194 | 		var buffer = new ArrayBuffer(1024);
195 | 
196 | 		/* These are recreated when the buffer is */
197 | 		var dataView = new DataView(buffer);
198 | 		var arrayView = new Uint8Array(buffer);
199 | 
200 | 		/**
201 | 		 * The location in the buffer where bytes are written or read.
202 | 		 * This increases after every write, but can be freely changed.
203 | 		 * The buffer will be resized when necessary.
204 | 		 *
205 | 		 * @type number */
206 | 		this.offset = 0;
207 | 
208 | 		// Ensures that the buffer is large enough to write `size` bytes
209 | 		// at the current `self.offset`.
210 | 		function accommodate(size) {
211 | 			var requiredLength = self.offset + size;
212 | 			if (buffer.byteLength >= requiredLength) {
213 | 				return;
214 | 			}
215 | 
216 | 			var newLength = buffer.byteLength;
217 | 			while (newLength < requiredLength) {
218 | 				newLength *= 2;
219 | 			}
220 | 
221 | 			var newBuffer = new ArrayBuffer(newLength);
222 | 			var newArrayView = new Uint8Array(newBuffer);
223 | 			newArrayView.set(arrayView);
224 | 
225 | 			// If there's a gap between the end of the old buffer
226 | 			// and the start of the new one, we need to zero it out
227 | 			if (self.offset > buffer.byteLength) {
228 | 				newArrayView.fill(0, buffer.byteLength, self.offset);
229 | 			}
230 | 
231 | 			buffer = newBuffer;
232 | 			dataView = new DataView(newBuffer);
233 | 			arrayView = newArrayView;
234 | 		}
235 | 
236 | 		function write(dataType, size, value) {
237 | 			accommodate(size);
238 | 			dataView['set' + dataType](self.offset, value);
239 | 			self.offset += size;
240 | 			return self;
241 | 		}
242 | 
243 | 		/**
244 | 		 * Returns the writen data as a slice from the internal buffer,
245 | 		 * cutting off any padding at the end.
246 | 		 *
247 | 		 * @returns {ArrayBuffer} a [0, offset] slice of the interal buffer */
248 | 		this.getData = function() {
249 | 			accommodate(0);  /* make sure the offset is inside the buffer */
250 | 			return buffer.slice(0, self.offset);
251 | 		};
252 | 
253 | 		/**
254 | 		 * @method module:nbt.Writer#byte
255 | 		 * @param {number} value - a signed byte
256 | 		 * @returns {module:nbt.Writer} itself */
257 | 		this[nbt.tagTypes.byte] = write.bind(this, 'Int8', 1);
258 | 
259 | 		/**
260 | 		 * @method module:nbt.Writer#ubyte
261 | 		 * @param {number} value - an unsigned byte
262 | 		 * @returns {module:nbt.Writer} itself */
263 | 		this.ubyte = write.bind(this, 'Uint8', 1);
264 | 
265 | 		/**
266 | 		 * @method module:nbt.Writer#short
267 | 		 * @param {number} value - a signed 16-bit integer
268 | 		 * @returns {module:nbt.Writer} itself */
269 | 		this[nbt.tagTypes.short] = write.bind(this, 'Int16', 2);
270 | 
271 | 		/**
272 | 		 * @method module:nbt.Writer#int
273 | 		 * @param {number} value - a signed 32-bit integer
274 | 		 * @returns {module:nbt.Writer} itself */
275 | 		this[nbt.tagTypes.int] = write.bind(this, 'Int32', 4);
276 | 
277 | 		/**
278 | 		 * @method module:nbt.Writer#float
279 | 		 * @param {number} value - a signed 32-bit float
280 | 		 * @returns {module:nbt.Writer} itself */
281 | 		this[nbt.tagTypes.float] = write.bind(this, 'Float32', 4);
282 | 
283 | 		/**
284 | 		 * @method module:nbt.Writer#float
285 | 		 * @param {number} value - a signed 64-bit float
286 | 		 * @returns {module:nbt.Writer} itself */
287 | 		this[nbt.tagTypes.double] = write.bind(this, 'Float64', 8);
288 | 
289 | 		/**
290 | 		 * As JavaScript does not support 64-bit integers natively, this
291 | 		 * method takes an array of two 32-bit integers that make up the
292 | 		 * upper and lower halves of the long.
293 | 		 *
294 | 		 * @method module:nbt.Writer#long
295 | 		 * @param {Array.<number>} value - [upper, lower]
296 | 		 * @returns {module:nbt.Writer} itself */
297 | 		this[nbt.tagTypes.long] = function(value) {
298 | 			self.int(value[0]);
299 | 			self.int(value[1]);
300 | 			return self;
301 | 		};
302 | 
303 | 		/**
304 | 		 * @method module:nbt.Writer#byteArray
305 | 		 * @param {Array.<number>|Uint8Array|Buffer} value
306 | 		 * @returns {module:nbt.Writer} itself */
307 | 		this[nbt.tagTypes.byteArray] = function(value) {
308 | 			this.int(value.length);
309 | 			accommodate(value.length);
310 | 			arrayView.set(value, this.offset);
311 | 			this.offset += value.length;
312 | 			return this;
313 | 		};
314 | 
315 | 		/**
316 | 		 * @method module:nbt.Writer#intArray
317 | 		 * @param {Array.<number>} value
318 | 		 * @returns {module:nbt.Writer} itself */
319 | 		this[nbt.tagTypes.intArray] = function(value) {
320 | 			this.int(value.length);
321 | 			var i;
322 | 			for (i = 0; i < value.length; i++) {
323 | 				this.int(value[i]);
324 | 			}
325 | 			return this;
326 | 		};
327 | 
328 | 		/**
329 | 		 * @method module:nbt.Writer#longArray
330 | 		 * @param {Array.<number>} value
331 | 		 * @returns {module:nbt.Writer} itself */
332 | 		this[nbt.tagTypes.longArray] = function(value) {
333 | 			this.int(value.length);
334 | 			var i;
335 | 			for (i = 0; i < value.length; i++) {
336 | 				this.long(value[i]);
337 | 			}
338 | 			return this;
339 | 		};
340 | 
341 | 		/**
342 | 		 * @method module:nbt.Writer#string
343 | 		 * @param {string} value
344 | 		 * @returns {module:nbt.Writer} itself */
345 | 		this[nbt.tagTypes.string] = function(value) {
346 | 			var bytes = encodeUTF8(value);
347 | 			this.short(bytes.length);
348 | 			accommodate(bytes.length);
349 | 			arrayView.set(bytes, this.offset);
350 | 			this.offset += bytes.length;
351 | 			return this;
352 | 		};
353 | 
354 | 		/**
355 | 		 * @method module:nbt.Writer#list
356 | 		 * @param {Object} value
357 | 		 * @param {number} value.type - the NBT type number
358 | 		 * @param {Array} value.value - an array of values
359 | 		 * @returns {module:nbt.Writer} itself */
360 | 		this[nbt.tagTypes.list] = function(value) {
361 | 			this.byte(nbt.tagTypes[value.type]);
362 | 			this.int(value.value.length);
363 | 			var i;
364 | 			for (i = 0; i < value.value.length; i++) {
365 | 				this[value.type](value.value[i]);
366 | 			}
367 | 			return this;
368 | 		};
369 | 
370 | 		/**
371 | 		 * @method module:nbt.Writer#compound
372 | 		 * @param {Object} value - a key/value map
373 | 		 * @param {Object} value.KEY
374 | 		 * @param {string} value.KEY.type - the NBT type number
375 | 		 * @param {Object} value.KEY.value - a value matching the type
376 | 		 * @returns {module:nbt.Writer} itself
377 | 		 *
378 | 		 * @example
379 | 		 * writer.compound({
380 | 		 *     foo: { type: 'int', value: 12 },
381 | 		 *     bar: { type: 'string', value: 'Hello, World!' }
382 | 		 * }); */
383 | 		this[nbt.tagTypes.compound] = function(value) {
384 | 			var self = this;
385 | 			Object.keys(value).map(function (key) {
386 | 				self.byte(nbt.tagTypes[value[key].type]);
387 | 				self.string(key);
388 | 				self[value[key].type](value[key].value);
389 | 			});
390 | 			this.byte(nbt.tagTypes.end);
391 | 			return this;
392 | 		};
393 | 
394 | 		var typeName;
395 | 		for (typeName in nbt.tagTypes) {
396 | 			if (nbt.tagTypes.hasOwnProperty(typeName)) {
397 | 				this[typeName] = this[nbt.tagTypes[typeName]];
398 | 			}
399 | 		}
400 | 	};
401 | 
402 | 	/**
403 | 	 * In addition to the named writing methods documented below,
404 | 	 * the same methods are indexed by the NBT type number as well,
405 | 	 * as shown in the example below.
406 | 	 *
407 | 	 * @constructor
408 | 	 * @see module:nbt.Writer
409 | 	 *
410 | 	 * @example
411 | 	 * var reader = new nbt.Reader(buf);
412 | 	 * int x = reader.int();
413 | 	 * int y = reader[3]();
414 | 	 * int z = reader[nbt.tagTypes.int](); */
415 | 	nbt.Reader = function(buffer) {
416 | 		if (!buffer) { throw new Error('Argument "buffer" is falsy'); }
417 | 
418 | 		var self = this;
419 | 
420 | 		/**
421 | 		 * The current location in the buffer. Can be freely changed
422 | 		 * within the bounds of the buffer.
423 | 		 *
424 | 		 * @type number */
425 | 		this.offset = 0;
426 | 
427 | 		var arrayView = new Uint8Array(buffer);
428 | 		var dataView = new DataView(arrayView.buffer);
429 | 
430 | 		function read(dataType, size) {
431 | 			var val = dataView['get' + dataType](self.offset);
432 | 			self.offset += size;
433 | 			return val;
434 | 		}
435 | 
436 | 		/**
437 | 		 * @method module:nbt.Reader#byte
438 | 		 * @returns {number} the read byte */
439 | 		this[nbt.tagTypes.byte] = read.bind(this, 'Int8', 1);
440 | 
441 | 		/**
442 | 		 * @method module:nbt.Reader#byte
443 | 		 * @returns {number} the read unsigned byte */
444 | 		this.ubyte = read.bind(this, 'Uint8', 1);
445 | 
446 | 		/**
447 | 		 * @method module:nbt.Reader#short
448 | 		 * @returns {number} the read signed 16-bit short  */
449 | 		this[nbt.tagTypes.short] = read.bind(this, 'Int16', 2);
450 | 
451 | 		/**
452 | 		 * @method module:nbt.Reader#int
453 | 		 * @returns {number} the read signed 32-bit integer */
454 | 		this[nbt.tagTypes.int] = read.bind(this, 'Int32', 4);
455 | 
456 | 		/**
457 | 		 * @method module:nbt.Reader#float
458 | 		 * @returns {number} the read signed 32-bit float */
459 | 		this[nbt.tagTypes.float] = read.bind(this, 'Float32', 4);
460 | 
461 | 		/**
462 | 		 * @method module:nbt.Reader#double
463 | 		 * @returns {number} the read signed 64-bit float */
464 | 		this[nbt.tagTypes.double] = read.bind(this, 'Float64', 8);
465 | 
466 | 		/**
467 | 		 * As JavaScript does not not natively support 64-bit
468 | 		 * integers, the value is returned as an array of two
469 | 		 * 32-bit integers, the upper and the lower.
470 | 		 *
471 | 		 * @method module:nbt.Reader#long
472 | 		 * @returns {Array.<number>} [upper, lower] */
473 | 		this[nbt.tagTypes.long] = function() {
474 | 			return [this.int(), this.int()];
475 | 		};
476 | 
477 | 		/**
478 | 		 * @method module:nbt.Reader#byteArray
479 | 		 * @returns {Array.<number>} the read array */
480 | 		this[nbt.tagTypes.byteArray] = function() {
481 | 			var length = this.int();
482 | 			var bytes = [];
483 | 			var i;
484 | 			for (i = 0; i < length; i++) {
485 | 				bytes.push(this.byte());
486 | 			}
487 | 			return bytes;
488 | 		};
489 | 
490 | 		/**
491 | 		 * @method module:nbt.Reader#intArray
492 | 		 * @returns {Array.<number>} the read array of 32-bit ints */
493 | 		this[nbt.tagTypes.intArray] = function() {
494 | 			var length = this.int();
495 | 			var ints = [];
496 | 			var i;
497 | 			for (i = 0; i < length; i++) {
498 | 				ints.push(this.int());
499 | 			}
500 | 			return ints;
501 | 		};
502 | 
503 | 		/**
504 | 		 * As JavaScript does not not natively support 64-bit
505 | 		 * integers, the value is returned as an array of arrays of two
506 | 		 * 32-bit integers, the upper and the lower.
507 | 		 *
508 | 		 * @method module:nbt.Reader#longArray
509 | 		 * @returns {Array.<number>} the read array of 64-bit ints
510 | 		 *     split into [upper, lower] */
511 | 		this[nbt.tagTypes.longArray] = function() {
512 | 			var length = this.int();
513 | 			var longs = [];
514 | 			var i;
515 | 			for (i = 0; i < length; i++) {
516 | 				longs.push(this.long());
517 | 			}
518 | 			return longs;
519 | 		};
520 | 
521 | 		/**
522 | 		 * @method module:nbt.Reader#string
523 | 		 * @returns {string} the read string */
524 | 		this[nbt.tagTypes.string] = function() {
525 | 			var length = this.short();
526 | 			var slice = sliceUint8Array(arrayView, this.offset,
527 | 				this.offset + length);
528 | 			this.offset += length;
529 | 			return decodeUTF8(slice);
530 | 		};
531 | 
532 | 		/**
533 | 		 * @method module:nbt.Reader#list
534 | 		 * @returns {{type: string, value: Array}}
535 | 		 *
536 | 		 * @example
537 | 		 * reader.list();
538 | 		 * // -> { type: 'string', values: ['foo', 'bar'] } */
539 | 		this[nbt.tagTypes.list] = function() {
540 | 			var type = this.byte();
541 | 			var length = this.int();
542 | 			var values = [];
543 | 			var i;
544 | 			for (i = 0; i < length; i++) {
545 | 				values.push(this[type]());
546 | 			}
547 | 			return { type: nbt.tagTypeNames[type], value: values };
548 | 		};
549 | 
550 | 		/**
551 | 		 * @method module:nbt.Reader#compound
552 | 		 * @returns {Object.<string, { type: string, value }>}
553 | 		 *
554 | 		 * @example
555 | 		 * reader.compound();
556 | 		 * // -> { foo: { type: int, value: 42 },
557 | 		 * //      bar: { type: string, value: 'Hello! }} */
558 | 		this[nbt.tagTypes.compound] = function() {
559 | 			var values = {};
560 | 			while (true) {
561 | 				var type = this.byte();
562 | 				if (type === nbt.tagTypes.end) {
563 | 					break;
564 | 				}
565 | 				var name = this.string();
566 | 				var value = this[type]();
567 | 				values[name] = { type: nbt.tagTypeNames[type], value: value };
568 | 			}
569 | 			return values;
570 | 		};
571 | 
572 | 		var typeName;
573 | 		for (typeName in nbt.tagTypes) {
574 | 			if (nbt.tagTypes.hasOwnProperty(typeName)) {
575 | 				this[typeName] = this[nbt.tagTypes[typeName]];
576 | 			}
577 | 		}
578 | 	};
579 | 
580 | 	/**
581 | 	 * @param {Object} value - a named compound
582 | 	 * @param {string} value.name - the top-level name
583 | 	 * @param {Object} value.value - a compound
584 | 	 * @returns {ArrayBuffer}
585 | 	 *
586 | 	 * @see module:nbt.parseUncompressed
587 | 	 * @see module:nbt.Writer#compound
588 | 	 *
589 | 	 * @example
590 | 	 * nbt.writeUncompressed({
591 | 	 *     name: 'My Level',
592 | 	 *     value: {
593 | 	 *         foo: { type: int, value: 42 },
594 | 	 *         bar: { type: string, value: 'Hi!' }
595 | 	 *     }
596 | 	 * }); */
597 | 	nbt.writeUncompressed = function(value) {
598 | 		if (!value) { throw new Error('Argument "value" is falsy'); }
599 | 
600 | 		var writer = new nbt.Writer();
601 | 
602 | 		writer.byte(nbt.tagTypes.compound);
603 | 		writer.string(value.name);
604 | 		writer.compound(value.value);
605 | 
606 | 		return writer.getData();
607 | 	};
608 | 
609 | 	/**
610 | 	 * @param {ArrayBuffer|Buffer} data - an uncompressed NBT archive
611 | 	 * @returns {{name: string, value: Object.<string, Object>}}
612 | 	 *     a named compound
613 | 	 *
614 | 	 * @see module:nbt.parse
615 | 	 * @see module:nbt.writeUncompressed
616 | 	 *
617 | 	 * @example
618 | 	 * nbt.readUncompressed(buf);
619 | 	 * // -> { name: 'My Level',
620 | 	 * //      value: { foo: { type: int, value: 42 },
621 | 	 * //               bar: { type: string, value: 'Hi!' }}} */
622 | 	nbt.parseUncompressed = function(data) {
623 | 		if (!data) { throw new Error('Argument "data" is falsy'); }
624 | 
625 | 		var reader = new nbt.Reader(data);
626 | 
627 | 		var type = reader.byte();
628 | 		if (type !== nbt.tagTypes.compound) {
629 | 			throw new Error('Top tag should be a compound');
630 | 		}
631 | 
632 | 		return {
633 | 			name: reader.string(),
634 | 			value: reader.compound()
635 | 		};
636 | 	};
637 | 
638 | 	/**
639 | 	 * @callback parseCallback
640 | 	 * @param {Object} error
641 | 	 * @param {Object} result - a named compound
642 | 	 * @param {string} result.name - the top-level name
643 | 	 * @param {Object} result.value - the top-level compound */
644 | 
645 | 	/**
646 | 	 * This accepts both gzipped and uncompressd NBT archives.
647 | 	 * If the archive is uncompressed, the callback will be
648 | 	 * called directly from this method. For gzipped files, the
649 | 	 * callback is async.
650 | 	 *
651 | 	 * For use in the browser, window.zlib must be defined to decode
652 | 	 * compressed archives. It will be passed a Buffer if the type is
653 | 	 * available, or an Uint8Array otherwise.
654 | 	 *
655 | 	 * @param {ArrayBuffer|Buffer} data - gzipped or uncompressed data
656 | 	 * @param {parseCallback} callback
657 | 	 *
658 | 	 * @see module:nbt.parseUncompressed
659 | 	 * @see module:nbt.Reader#compound
660 | 	 *
661 | 	 * @example
662 | 	 * nbt.parse(buf, function(error, results) {
663 | 	 *     if (error) {
664 | 	 *         throw error;
665 | 	 *     }
666 | 	 *     console.log(result.name);
667 | 	 *     console.log(result.value.foo);
668 | 	 * }); */
669 | 	nbt.parse = function(data, callback) {
670 | 		if (!data) { throw new Error('Argument "data" is falsy'); }
671 | 
672 | 		var self = this;
673 | 
674 | 		if (!hasGzipHeader(data)) {
675 | 			callback(null, self.parseUncompressed(data));
676 | 		} else if (!zlib) {
677 | 			callback(new Error('NBT archive is compressed but zlib is not ' +
678 | 				'available'), null);
679 | 		} else {
680 | 			/* zlib.gunzip take a Buffer, at least in Node, so try to convert
681 | 			   if possible. */
682 | 			var buffer;
683 | 			if (data.length) {
684 | 				buffer = data;
685 | 			} else if (typeof Buffer !== 'undefined') {
686 | 				buffer = new Buffer(data);
687 | 			} else {
688 | 				/* In the browser? Unknown zlib library. Let's settle for
689 | 				   Uint8Array and see what happens. */
690 | 				buffer = new Uint8Array(data);
691 | 			}
692 | 
693 | 			zlib.gunzip(buffer, function(error, uncompressed) {
694 | 				if (error) {
695 | 					callback(error, null);
696 | 				} else {
697 | 					callback(null, self.parseUncompressed(uncompressed));
698 | 				}
699 | 			});
700 | 		}
701 | 	};
702 | }).apply(typeof exports !== 'undefined' ? exports : (window.nbt = {}));
703 | 
704 |
705 |
706 | 707 | 708 | 709 | 710 |
711 | 712 | 715 | 716 |
717 | 718 | 721 | 722 | 723 | 724 | 725 | 726 | -------------------------------------------------------------------------------- /docs/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (function() { 3 | var source = document.getElementsByClassName('prettyprint source linenums'); 4 | var i = 0; 5 | var lineNumber = 0; 6 | var lineId; 7 | var lines; 8 | var totalLines; 9 | var anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = 'line' + lineNumber; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /docs/scripts/prettify/Apache-License-2.0.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /docs/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /docs/scripts/prettify/prettify.js: -------------------------------------------------------------------------------- 1 | var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; 2 | (function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= 3 | [],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), 9 | l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, 10 | q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, 11 | q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, 12 | "");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), 13 | a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} 14 | for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], 18 | "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], 19 | H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], 20 | J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ 21 | I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), 22 | ["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", 23 | /^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), 24 | ["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", 25 | hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= 26 | !k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p th:last-child { border-right: 1px solid #ddd; } 224 | 225 | .ancestors, .attribs { color: #999; } 226 | .ancestors a, .attribs a 227 | { 228 | color: #999 !important; 229 | text-decoration: none; 230 | } 231 | 232 | .clear 233 | { 234 | clear: both; 235 | } 236 | 237 | .important 238 | { 239 | font-weight: bold; 240 | color: #950B02; 241 | } 242 | 243 | .yes-def { 244 | text-indent: -1000px; 245 | } 246 | 247 | .type-signature { 248 | color: #aaa; 249 | } 250 | 251 | .name, .signature { 252 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 253 | } 254 | 255 | .details { margin-top: 14px; border-left: 2px solid #DDD; } 256 | .details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } 257 | .details dd { margin-left: 70px; } 258 | .details ul { margin: 0; } 259 | .details ul { list-style-type: none; } 260 | .details li { margin-left: 30px; padding-top: 6px; } 261 | .details pre.prettyprint { margin: 0 } 262 | .details .object-value { padding-top: 0; } 263 | 264 | .description { 265 | margin-bottom: 1em; 266 | margin-top: 1em; 267 | } 268 | 269 | .code-caption 270 | { 271 | font-style: italic; 272 | font-size: 107%; 273 | margin: 0; 274 | } 275 | 276 | .prettyprint 277 | { 278 | border: 1px solid #ddd; 279 | width: 80%; 280 | overflow: auto; 281 | } 282 | 283 | .prettyprint.source { 284 | width: inherit; 285 | } 286 | 287 | .prettyprint code 288 | { 289 | font-size: 100%; 290 | line-height: 18px; 291 | display: block; 292 | padding: 4px 12px; 293 | margin: 0; 294 | background-color: #fff; 295 | color: #4D4E53; 296 | } 297 | 298 | .prettyprint code span.line 299 | { 300 | display: inline-block; 301 | } 302 | 303 | .prettyprint.linenums 304 | { 305 | padding-left: 70px; 306 | -webkit-user-select: none; 307 | -moz-user-select: none; 308 | -ms-user-select: none; 309 | user-select: none; 310 | } 311 | 312 | .prettyprint.linenums ol 313 | { 314 | padding-left: 0; 315 | } 316 | 317 | .prettyprint.linenums li 318 | { 319 | border-left: 3px #ddd solid; 320 | } 321 | 322 | .prettyprint.linenums li.selected, 323 | .prettyprint.linenums li.selected * 324 | { 325 | background-color: lightyellow; 326 | } 327 | 328 | .prettyprint.linenums li * 329 | { 330 | -webkit-user-select: text; 331 | -moz-user-select: text; 332 | -ms-user-select: text; 333 | user-select: text; 334 | } 335 | 336 | .params .name, .props .name, .name code { 337 | color: #4D4E53; 338 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 339 | font-size: 100%; 340 | } 341 | 342 | .params td.description > p:first-child, 343 | .props td.description > p:first-child 344 | { 345 | margin-top: 0; 346 | padding-top: 0; 347 | } 348 | 349 | .params td.description > p:last-child, 350 | .props td.description > p:last-child 351 | { 352 | margin-bottom: 0; 353 | padding-bottom: 0; 354 | } 355 | 356 | .disabled { 357 | color: #454545; 358 | } 359 | -------------------------------------------------------------------------------- /docs/styles/prettify-jsdoc.css: -------------------------------------------------------------------------------- 1 | /* JSDoc prettify.js theme */ 2 | 3 | /* plain text */ 4 | .pln { 5 | color: #000000; 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | /* string content */ 11 | .str { 12 | color: #006400; 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | 17 | /* a keyword */ 18 | .kwd { 19 | color: #000000; 20 | font-weight: bold; 21 | font-style: normal; 22 | } 23 | 24 | /* a comment */ 25 | .com { 26 | font-weight: normal; 27 | font-style: italic; 28 | } 29 | 30 | /* a type name */ 31 | .typ { 32 | color: #000000; 33 | font-weight: normal; 34 | font-style: normal; 35 | } 36 | 37 | /* a literal value */ 38 | .lit { 39 | color: #006400; 40 | font-weight: normal; 41 | font-style: normal; 42 | } 43 | 44 | /* punctuation */ 45 | .pun { 46 | color: #000000; 47 | font-weight: bold; 48 | font-style: normal; 49 | } 50 | 51 | /* lisp open bracket */ 52 | .opn { 53 | color: #000000; 54 | font-weight: bold; 55 | font-style: normal; 56 | } 57 | 58 | /* lisp close bracket */ 59 | .clo { 60 | color: #000000; 61 | font-weight: bold; 62 | font-style: normal; 63 | } 64 | 65 | /* a markup tag name */ 66 | .tag { 67 | color: #006400; 68 | font-weight: normal; 69 | font-style: normal; 70 | } 71 | 72 | /* a markup attribute name */ 73 | .atn { 74 | color: #006400; 75 | font-weight: normal; 76 | font-style: normal; 77 | } 78 | 79 | /* a markup attribute value */ 80 | .atv { 81 | color: #006400; 82 | font-weight: normal; 83 | font-style: normal; 84 | } 85 | 86 | /* a declaration */ 87 | .dec { 88 | color: #000000; 89 | font-weight: bold; 90 | font-style: normal; 91 | } 92 | 93 | /* a variable name */ 94 | .var { 95 | color: #000000; 96 | font-weight: normal; 97 | font-style: normal; 98 | } 99 | 100 | /* a function name */ 101 | .fun { 102 | color: #000000; 103 | font-weight: bold; 104 | font-style: normal; 105 | } 106 | 107 | /* Specify class=linenums on a pre to get line numbering */ 108 | ol.linenums { 109 | margin-top: 0; 110 | margin-bottom: 0; 111 | } 112 | -------------------------------------------------------------------------------- /docs/styles/prettify-tomorrow.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #4d4d4c; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #718c00; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #8959a8; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #8e908c; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #4271ae; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #f5871f; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #4d4d4c; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #4d4d4c; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #4d4d4c; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #c82829; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #f5871f; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #3e999f; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #f5871f; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #c82829; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #4271ae; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | /* 99 | pre.prettyprint { 100 | background: white; 101 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 102 | font-size: 12px; 103 | line-height: 1.5; 104 | border: 1px solid #ccc; 105 | padding: 10px; } 106 | */ 107 | 108 | /* Specify class=linenums on a pre to get line numbering */ 109 | ol.linenums { 110 | margin-top: 0; 111 | margin-bottom: 0; } 112 | 113 | /* IE indents via margin-left */ 114 | li.L0, 115 | li.L1, 116 | li.L2, 117 | li.L3, 118 | li.L4, 119 | li.L5, 120 | li.L6, 121 | li.L7, 122 | li.L8, 123 | li.L9 { 124 | /* */ } 125 | 126 | /* Alternate shading for lines */ 127 | li.L1, 128 | li.L3, 129 | li.L5, 130 | li.L7, 131 | li.L9 { 132 | /* */ } 133 | -------------------------------------------------------------------------------- /fixtures/bigtest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Level", 3 | "value": { 4 | "longTest": { 5 | "type": "long", 6 | "value": [ 7 | 2147483647, 8 | -1 9 | ] 10 | }, 11 | "shortTest": { 12 | "type": "short", 13 | "value": 32767 14 | }, 15 | "stringTest": { 16 | "type": "string", 17 | "value": "HELLO WORLD THIS IS A TEST STRING ÅÄÖ!" 18 | }, 19 | "floatTest": { 20 | "type": "float", 21 | "value": 0.4982314705848694 22 | }, 23 | "intTest": { 24 | "type": "int", 25 | "value": 2147483647 26 | }, 27 | "nested compound test": { 28 | "type": "compound", 29 | "value": { 30 | "ham": { 31 | "type": "compound", 32 | "value": { 33 | "name": { 34 | "type": "string", 35 | "value": "Hampus" 36 | }, 37 | "value": { 38 | "type": "float", 39 | "value": 0.75 40 | } 41 | } 42 | }, 43 | "egg": { 44 | "type": "compound", 45 | "value": { 46 | "name": { 47 | "type": "string", 48 | "value": "Eggbert" 49 | }, 50 | "value": { 51 | "type": "float", 52 | "value": 0.5 53 | } 54 | } 55 | } 56 | } 57 | }, 58 | "listTest (long)": { 59 | "type": "list", 60 | "value": { 61 | "type": "long", 62 | "value": [ 63 | [ 64 | 0, 65 | 11 66 | ], 67 | [ 68 | 0, 69 | 12 70 | ], 71 | [ 72 | 0, 73 | 13 74 | ], 75 | [ 76 | 0, 77 | 14 78 | ], 79 | [ 80 | 0, 81 | 15 82 | ] 83 | ] 84 | } 85 | }, 86 | "listTest (compound)": { 87 | "type": "list", 88 | "value": { 89 | "type": "compound", 90 | "value": [ 91 | { 92 | "name": { 93 | "type": "string", 94 | "value": "Compound tag #0" 95 | }, 96 | "created-on": { 97 | "type": "long", 98 | "value": [ 99 | 294, 100 | 1379390861 101 | ] 102 | } 103 | }, 104 | { 105 | "name": { 106 | "type": "string", 107 | "value": "Compound tag #1" 108 | }, 109 | "created-on": { 110 | "type": "long", 111 | "value": [ 112 | 294, 113 | 1379390861 114 | ] 115 | } 116 | } 117 | ] 118 | } 119 | }, 120 | "byteTest": { 121 | "type": "byte", 122 | "value": 127 123 | }, 124 | "byteArrayTest (the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...))": { 125 | "type": "byteArray", 126 | "value": [ 127 | 0, 128 | 62, 129 | 34, 130 | 16, 131 | 8, 132 | 10, 133 | 22, 134 | 44, 135 | 76, 136 | 18, 137 | 70, 138 | 32, 139 | 4, 140 | 86, 141 | 78, 142 | 80, 143 | 92, 144 | 14, 145 | 46, 146 | 88, 147 | 40, 148 | 2, 149 | 74, 150 | 56, 151 | 48, 152 | 50, 153 | 62, 154 | 84, 155 | 16, 156 | 58, 157 | 10, 158 | 72, 159 | 44, 160 | 26, 161 | 18, 162 | 20, 163 | 32, 164 | 54, 165 | 86, 166 | 28, 167 | 80, 168 | 42, 169 | 14, 170 | 96, 171 | 88, 172 | 90, 173 | 2, 174 | 24, 175 | 56, 176 | 98, 177 | 50, 178 | 12, 179 | 84, 180 | 66, 181 | 58, 182 | 60, 183 | 72, 184 | 94, 185 | 26, 186 | 68, 187 | 20, 188 | 82, 189 | 54, 190 | 36, 191 | 28, 192 | 30, 193 | 42, 194 | 64, 195 | 96, 196 | 38, 197 | 90, 198 | 52, 199 | 24, 200 | 6, 201 | 98, 202 | 0, 203 | 12, 204 | 34, 205 | 66, 206 | 8, 207 | 60, 208 | 22, 209 | 94, 210 | 76, 211 | 68, 212 | 70, 213 | 82, 214 | 4, 215 | 36, 216 | 78, 217 | 30, 218 | 92, 219 | 64, 220 | 46, 221 | 38, 222 | 40, 223 | 52, 224 | 74, 225 | 6, 226 | 48, 227 | 0, 228 | 62, 229 | 34, 230 | 16, 231 | 8, 232 | 10, 233 | 22, 234 | 44, 235 | 76, 236 | 18, 237 | 70, 238 | 32, 239 | 4, 240 | 86, 241 | 78, 242 | 80, 243 | 92, 244 | 14, 245 | 46, 246 | 88, 247 | 40, 248 | 2, 249 | 74, 250 | 56, 251 | 48, 252 | 50, 253 | 62, 254 | 84, 255 | 16, 256 | 58, 257 | 10, 258 | 72, 259 | 44, 260 | 26, 261 | 18, 262 | 20, 263 | 32, 264 | 54, 265 | 86, 266 | 28, 267 | 80, 268 | 42, 269 | 14, 270 | 96, 271 | 88, 272 | 90, 273 | 2, 274 | 24, 275 | 56, 276 | 98, 277 | 50, 278 | 12, 279 | 84, 280 | 66, 281 | 58, 282 | 60, 283 | 72, 284 | 94, 285 | 26, 286 | 68, 287 | 20, 288 | 82, 289 | 54, 290 | 36, 291 | 28, 292 | 30, 293 | 42, 294 | 64, 295 | 96, 296 | 38, 297 | 90, 298 | 52, 299 | 24, 300 | 6, 301 | 98, 302 | 0, 303 | 12, 304 | 34, 305 | 66, 306 | 8, 307 | 60, 308 | 22, 309 | 94, 310 | 76, 311 | 68, 312 | 70, 313 | 82, 314 | 4, 315 | 36, 316 | 78, 317 | 30, 318 | 92, 319 | 64, 320 | 46, 321 | 38, 322 | 40, 323 | 52, 324 | 74, 325 | 6, 326 | 48, 327 | 0, 328 | 62, 329 | 34, 330 | 16, 331 | 8, 332 | 10, 333 | 22, 334 | 44, 335 | 76, 336 | 18, 337 | 70, 338 | 32, 339 | 4, 340 | 86, 341 | 78, 342 | 80, 343 | 92, 344 | 14, 345 | 46, 346 | 88, 347 | 40, 348 | 2, 349 | 74, 350 | 56, 351 | 48, 352 | 50, 353 | 62, 354 | 84, 355 | 16, 356 | 58, 357 | 10, 358 | 72, 359 | 44, 360 | 26, 361 | 18, 362 | 20, 363 | 32, 364 | 54, 365 | 86, 366 | 28, 367 | 80, 368 | 42, 369 | 14, 370 | 96, 371 | 88, 372 | 90, 373 | 2, 374 | 24, 375 | 56, 376 | 98, 377 | 50, 378 | 12, 379 | 84, 380 | 66, 381 | 58, 382 | 60, 383 | 72, 384 | 94, 385 | 26, 386 | 68, 387 | 20, 388 | 82, 389 | 54, 390 | 36, 391 | 28, 392 | 30, 393 | 42, 394 | 64, 395 | 96, 396 | 38, 397 | 90, 398 | 52, 399 | 24, 400 | 6, 401 | 98, 402 | 0, 403 | 12, 404 | 34, 405 | 66, 406 | 8, 407 | 60, 408 | 22, 409 | 94, 410 | 76, 411 | 68, 412 | 70, 413 | 82, 414 | 4, 415 | 36, 416 | 78, 417 | 30, 418 | 92, 419 | 64, 420 | 46, 421 | 38, 422 | 40, 423 | 52, 424 | 74, 425 | 6, 426 | 48, 427 | 0, 428 | 62, 429 | 34, 430 | 16, 431 | 8, 432 | 10, 433 | 22, 434 | 44, 435 | 76, 436 | 18, 437 | 70, 438 | 32, 439 | 4, 440 | 86, 441 | 78, 442 | 80, 443 | 92, 444 | 14, 445 | 46, 446 | 88, 447 | 40, 448 | 2, 449 | 74, 450 | 56, 451 | 48, 452 | 50, 453 | 62, 454 | 84, 455 | 16, 456 | 58, 457 | 10, 458 | 72, 459 | 44, 460 | 26, 461 | 18, 462 | 20, 463 | 32, 464 | 54, 465 | 86, 466 | 28, 467 | 80, 468 | 42, 469 | 14, 470 | 96, 471 | 88, 472 | 90, 473 | 2, 474 | 24, 475 | 56, 476 | 98, 477 | 50, 478 | 12, 479 | 84, 480 | 66, 481 | 58, 482 | 60, 483 | 72, 484 | 94, 485 | 26, 486 | 68, 487 | 20, 488 | 82, 489 | 54, 490 | 36, 491 | 28, 492 | 30, 493 | 42, 494 | 64, 495 | 96, 496 | 38, 497 | 90, 498 | 52, 499 | 24, 500 | 6, 501 | 98, 502 | 0, 503 | 12, 504 | 34, 505 | 66, 506 | 8, 507 | 60, 508 | 22, 509 | 94, 510 | 76, 511 | 68, 512 | 70, 513 | 82, 514 | 4, 515 | 36, 516 | 78, 517 | 30, 518 | 92, 519 | 64, 520 | 46, 521 | 38, 522 | 40, 523 | 52, 524 | 74, 525 | 6, 526 | 48, 527 | 0, 528 | 62, 529 | 34, 530 | 16, 531 | 8, 532 | 10, 533 | 22, 534 | 44, 535 | 76, 536 | 18, 537 | 70, 538 | 32, 539 | 4, 540 | 86, 541 | 78, 542 | 80, 543 | 92, 544 | 14, 545 | 46, 546 | 88, 547 | 40, 548 | 2, 549 | 74, 550 | 56, 551 | 48, 552 | 50, 553 | 62, 554 | 84, 555 | 16, 556 | 58, 557 | 10, 558 | 72, 559 | 44, 560 | 26, 561 | 18, 562 | 20, 563 | 32, 564 | 54, 565 | 86, 566 | 28, 567 | 80, 568 | 42, 569 | 14, 570 | 96, 571 | 88, 572 | 90, 573 | 2, 574 | 24, 575 | 56, 576 | 98, 577 | 50, 578 | 12, 579 | 84, 580 | 66, 581 | 58, 582 | 60, 583 | 72, 584 | 94, 585 | 26, 586 | 68, 587 | 20, 588 | 82, 589 | 54, 590 | 36, 591 | 28, 592 | 30, 593 | 42, 594 | 64, 595 | 96, 596 | 38, 597 | 90, 598 | 52, 599 | 24, 600 | 6, 601 | 98, 602 | 0, 603 | 12, 604 | 34, 605 | 66, 606 | 8, 607 | 60, 608 | 22, 609 | 94, 610 | 76, 611 | 68, 612 | 70, 613 | 82, 614 | 4, 615 | 36, 616 | 78, 617 | 30, 618 | 92, 619 | 64, 620 | 46, 621 | 38, 622 | 40, 623 | 52, 624 | 74, 625 | 6, 626 | 48, 627 | 0, 628 | 62, 629 | 34, 630 | 16, 631 | 8, 632 | 10, 633 | 22, 634 | 44, 635 | 76, 636 | 18, 637 | 70, 638 | 32, 639 | 4, 640 | 86, 641 | 78, 642 | 80, 643 | 92, 644 | 14, 645 | 46, 646 | 88, 647 | 40, 648 | 2, 649 | 74, 650 | 56, 651 | 48, 652 | 50, 653 | 62, 654 | 84, 655 | 16, 656 | 58, 657 | 10, 658 | 72, 659 | 44, 660 | 26, 661 | 18, 662 | 20, 663 | 32, 664 | 54, 665 | 86, 666 | 28, 667 | 80, 668 | 42, 669 | 14, 670 | 96, 671 | 88, 672 | 90, 673 | 2, 674 | 24, 675 | 56, 676 | 98, 677 | 50, 678 | 12, 679 | 84, 680 | 66, 681 | 58, 682 | 60, 683 | 72, 684 | 94, 685 | 26, 686 | 68, 687 | 20, 688 | 82, 689 | 54, 690 | 36, 691 | 28, 692 | 30, 693 | 42, 694 | 64, 695 | 96, 696 | 38, 697 | 90, 698 | 52, 699 | 24, 700 | 6, 701 | 98, 702 | 0, 703 | 12, 704 | 34, 705 | 66, 706 | 8, 707 | 60, 708 | 22, 709 | 94, 710 | 76, 711 | 68, 712 | 70, 713 | 82, 714 | 4, 715 | 36, 716 | 78, 717 | 30, 718 | 92, 719 | 64, 720 | 46, 721 | 38, 722 | 40, 723 | 52, 724 | 74, 725 | 6, 726 | 48, 727 | 0, 728 | 62, 729 | 34, 730 | 16, 731 | 8, 732 | 10, 733 | 22, 734 | 44, 735 | 76, 736 | 18, 737 | 70, 738 | 32, 739 | 4, 740 | 86, 741 | 78, 742 | 80, 743 | 92, 744 | 14, 745 | 46, 746 | 88, 747 | 40, 748 | 2, 749 | 74, 750 | 56, 751 | 48, 752 | 50, 753 | 62, 754 | 84, 755 | 16, 756 | 58, 757 | 10, 758 | 72, 759 | 44, 760 | 26, 761 | 18, 762 | 20, 763 | 32, 764 | 54, 765 | 86, 766 | 28, 767 | 80, 768 | 42, 769 | 14, 770 | 96, 771 | 88, 772 | 90, 773 | 2, 774 | 24, 775 | 56, 776 | 98, 777 | 50, 778 | 12, 779 | 84, 780 | 66, 781 | 58, 782 | 60, 783 | 72, 784 | 94, 785 | 26, 786 | 68, 787 | 20, 788 | 82, 789 | 54, 790 | 36, 791 | 28, 792 | 30, 793 | 42, 794 | 64, 795 | 96, 796 | 38, 797 | 90, 798 | 52, 799 | 24, 800 | 6, 801 | 98, 802 | 0, 803 | 12, 804 | 34, 805 | 66, 806 | 8, 807 | 60, 808 | 22, 809 | 94, 810 | 76, 811 | 68, 812 | 70, 813 | 82, 814 | 4, 815 | 36, 816 | 78, 817 | 30, 818 | 92, 819 | 64, 820 | 46, 821 | 38, 822 | 40, 823 | 52, 824 | 74, 825 | 6, 826 | 48, 827 | 0, 828 | 62, 829 | 34, 830 | 16, 831 | 8, 832 | 10, 833 | 22, 834 | 44, 835 | 76, 836 | 18, 837 | 70, 838 | 32, 839 | 4, 840 | 86, 841 | 78, 842 | 80, 843 | 92, 844 | 14, 845 | 46, 846 | 88, 847 | 40, 848 | 2, 849 | 74, 850 | 56, 851 | 48, 852 | 50, 853 | 62, 854 | 84, 855 | 16, 856 | 58, 857 | 10, 858 | 72, 859 | 44, 860 | 26, 861 | 18, 862 | 20, 863 | 32, 864 | 54, 865 | 86, 866 | 28, 867 | 80, 868 | 42, 869 | 14, 870 | 96, 871 | 88, 872 | 90, 873 | 2, 874 | 24, 875 | 56, 876 | 98, 877 | 50, 878 | 12, 879 | 84, 880 | 66, 881 | 58, 882 | 60, 883 | 72, 884 | 94, 885 | 26, 886 | 68, 887 | 20, 888 | 82, 889 | 54, 890 | 36, 891 | 28, 892 | 30, 893 | 42, 894 | 64, 895 | 96, 896 | 38, 897 | 90, 898 | 52, 899 | 24, 900 | 6, 901 | 98, 902 | 0, 903 | 12, 904 | 34, 905 | 66, 906 | 8, 907 | 60, 908 | 22, 909 | 94, 910 | 76, 911 | 68, 912 | 70, 913 | 82, 914 | 4, 915 | 36, 916 | 78, 917 | 30, 918 | 92, 919 | 64, 920 | 46, 921 | 38, 922 | 40, 923 | 52, 924 | 74, 925 | 6, 926 | 48, 927 | 0, 928 | 62, 929 | 34, 930 | 16, 931 | 8, 932 | 10, 933 | 22, 934 | 44, 935 | 76, 936 | 18, 937 | 70, 938 | 32, 939 | 4, 940 | 86, 941 | 78, 942 | 80, 943 | 92, 944 | 14, 945 | 46, 946 | 88, 947 | 40, 948 | 2, 949 | 74, 950 | 56, 951 | 48, 952 | 50, 953 | 62, 954 | 84, 955 | 16, 956 | 58, 957 | 10, 958 | 72, 959 | 44, 960 | 26, 961 | 18, 962 | 20, 963 | 32, 964 | 54, 965 | 86, 966 | 28, 967 | 80, 968 | 42, 969 | 14, 970 | 96, 971 | 88, 972 | 90, 973 | 2, 974 | 24, 975 | 56, 976 | 98, 977 | 50, 978 | 12, 979 | 84, 980 | 66, 981 | 58, 982 | 60, 983 | 72, 984 | 94, 985 | 26, 986 | 68, 987 | 20, 988 | 82, 989 | 54, 990 | 36, 991 | 28, 992 | 30, 993 | 42, 994 | 64, 995 | 96, 996 | 38, 997 | 90, 998 | 52, 999 | 24, 1000 | 6, 1001 | 98, 1002 | 0, 1003 | 12, 1004 | 34, 1005 | 66, 1006 | 8, 1007 | 60, 1008 | 22, 1009 | 94, 1010 | 76, 1011 | 68, 1012 | 70, 1013 | 82, 1014 | 4, 1015 | 36, 1016 | 78, 1017 | 30, 1018 | 92, 1019 | 64, 1020 | 46, 1021 | 38, 1022 | 40, 1023 | 52, 1024 | 74, 1025 | 6, 1026 | 48, 1027 | 0, 1028 | 62, 1029 | 34, 1030 | 16, 1031 | 8, 1032 | 10, 1033 | 22, 1034 | 44, 1035 | 76, 1036 | 18, 1037 | 70, 1038 | 32, 1039 | 4, 1040 | 86, 1041 | 78, 1042 | 80, 1043 | 92, 1044 | 14, 1045 | 46, 1046 | 88, 1047 | 40, 1048 | 2, 1049 | 74, 1050 | 56, 1051 | 48, 1052 | 50, 1053 | 62, 1054 | 84, 1055 | 16, 1056 | 58, 1057 | 10, 1058 | 72, 1059 | 44, 1060 | 26, 1061 | 18, 1062 | 20, 1063 | 32, 1064 | 54, 1065 | 86, 1066 | 28, 1067 | 80, 1068 | 42, 1069 | 14, 1070 | 96, 1071 | 88, 1072 | 90, 1073 | 2, 1074 | 24, 1075 | 56, 1076 | 98, 1077 | 50, 1078 | 12, 1079 | 84, 1080 | 66, 1081 | 58, 1082 | 60, 1083 | 72, 1084 | 94, 1085 | 26, 1086 | 68, 1087 | 20, 1088 | 82, 1089 | 54, 1090 | 36, 1091 | 28, 1092 | 30, 1093 | 42, 1094 | 64, 1095 | 96, 1096 | 38, 1097 | 90, 1098 | 52, 1099 | 24, 1100 | 6, 1101 | 98, 1102 | 0, 1103 | 12, 1104 | 34, 1105 | 66, 1106 | 8, 1107 | 60, 1108 | 22, 1109 | 94, 1110 | 76, 1111 | 68, 1112 | 70, 1113 | 82, 1114 | 4, 1115 | 36, 1116 | 78, 1117 | 30, 1118 | 92, 1119 | 64, 1120 | 46, 1121 | 38, 1122 | 40, 1123 | 52, 1124 | 74, 1125 | 6, 1126 | 48 1127 | ] 1128 | }, 1129 | "doubleTest": { 1130 | "type": "double", 1131 | "value": 0.4931287132182315 1132 | } 1133 | } 1134 | } 1135 | -------------------------------------------------------------------------------- /fixtures/bigtest.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/fixtures/bigtest.nbt -------------------------------------------------------------------------------- /fixtures/bigtest.nbt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/fixtures/bigtest.nbt.gz -------------------------------------------------------------------------------- /fixtures/bigtest.nbt.gz.js: -------------------------------------------------------------------------------- 1 | ; window['fixtures/bigtest.nbt.gz'] = new Uint32Array([ 2 | /* jsinc-1.0 */ 3 | 0x00088B1F, 0x00000000, 0x54ED0000, 0x411A4FCF, 0x02C27E14, 0xB18296CB, 4 | 0xCC6310C4, 0xA584B5AB, 0x1142CDDB, 0x1688B189, 0x1A0D9A2C, 0x8631A8D8, 5 | 0x82C32BB8, 0x7766BB2E, 0x4BD4F1B0, 0xEB7A6C7B, 0x7F23D33F, 0xF6BDCF43, 6 | 0x2FC3A0BF, 0xBDCF697B, 0xF7C932F0, 0xE66FBDE6, 0x79266F7B, 0x72540402, 7 | 0x780E2C4F, 0x8D4DB1CB, 0x70E3F478, 0x7B083E62, 0x93A5C71D, 0x47820F18, 8 | 0x0284EEDD, 0xAAA2B562, 0x5C7678C7, 0x55A8CB57, 0xD6C81B0F, 0x86956A1E, 9 | 0x7EAD0D86, 0x838F7B58, 0x834F83CF, 0x1003CF6F, 0x3E8E5B6E, 0x4C38A5BE, 10 | 0xEA10FD64, 0x23A674DA, 0x2E66DC40, 0xD3B5E169, 0x76FA73BB, 0x0BDB290B, 11 | 0x3DE8EFE0, 0xEF5B381E, 0xF5560811, 0x0BDF5DDE, 0xB75EE040, 0x04B764FA, 12 | 0x4C418C00, 0x5508C673, 0x2E20D34C, 0xC8C0A47D, 0xBAB310C2, 0x530B58DE, 13 | 0x8E44EEA3, 0xB1300345, 0x4C8C5327, 0xA314E9F1, 0xE1858C53, 0xB3E39FD9, 14 | 0xA58144F2, 0xD8DD337C, 0x75AAC7BB, 0x1C285F13, 0xD12ED708, 0x1DAF3F59, 15 | 0x5921601B, 0x05F1FADF, 0xFCCEC1FE, 0xBC00BD9D, 0xF8C940F1, 0x46404285, 16 | 0xEAEB9EFE, 0x683A930F, 0xEBBB6087, 0x28A33732, 0xF5BB8E0A, 0xCA6369D0, 17 | 0xECE9DB4E, 0x3B2BE6E6, 0x64BE25BD, 0xAA3D0949, 0x18FD94BB, 0x0ED2E87E, 18 | 0x4C156FDA, 0x2B3E68B1, 0x849C9BE1, 0x0584BC99, 0x16596509, 0x2FFF0045, 19 | 0xF22FAE28, 0x2EA4B2C2, 0x5A77201D, 0xCA8CB93B, 0x51DF29E7, 0xB516C941, 20 | 0x2AA16DC5, 0x31C52CAD, 0x927ABA7F, 0x5F9D5E8E, 0x230512F8, 0xB7F6D11B, 21 | 0x95CDAA77, 0xDF9EBC72, 0x974B5D58, 0xB91792AE, 0xC880D044, 0xB3BF3EFA, 22 | 0x07CB54DC, 0xB6A36E75, 0x93925976, 0x5051DCA9, 0x35CC6B99, 0x57FF1AE6, 23 | 0xCB420823, 0x78D61BE9, 0xFCFEECC2, 0x787DFB7A, 0xD4DF84D3, 0x08FBA4F2, 24 | 0x00000006 25 | ]).buffer.slice(0, 507); 26 | -------------------------------------------------------------------------------- /fixtures/bigtest.nbt.js: -------------------------------------------------------------------------------- 1 | ; window['fixtures/bigtest.nbt'] = new Uint32Array([ 2 | /* jsinc-1.0 */ 3 | 0x4C05000A, 0x6C657665, 0x6C080004, 0x54676E6F, 0x7F747365, 0xFFFFFFFF, 4 | 0x02FFFFFF, 0x68730900, 0x5474726F, 0x7F747365, 0x0A0008FF, 0x69727473, 5 | 0x6554676E, 0x29007473, 0x4C4C4548, 0x4F57204F, 0x20444C52, 0x53494854, 6 | 0x20534920, 0x45542041, 0x53205453, 0x4E495254, 0x85C32047, 0x96C384C3, 7 | 0x09000521, 0x616F6C66, 0x73655474, 0x18FF3E74, 0x07000332, 0x54746E69, 8 | 0x7F747365, 0x0AFFFFFF, 0x656E1400, 0x64657473, 0x6D6F6320, 0x6E756F70, 9 | 0x65742064, 0x000A7473, 0x6D616803, 0x6E040008, 0x00656D61, 0x6D614806, 10 | 0x05737570, 0x61760500, 0x3F65756C, 0x00000040, 0x6503000A, 0x00086767, 11 | 0x6D616E04, 0x45070065, 0x65626767, 0x00057472, 0x6C617605, 0x003F6575, 12 | 0x00000000, 0x6C0F0009, 0x54747369, 0x20747365, 0x6E6F6C28, 0x00042967, 13 | 0x00050000, 0x00000000, 0x000B0000, 0x00000000, 0x000C0000, 0x00000000, 14 | 0x000D0000, 0x00000000, 0x000E0000, 0x00000000, 0x090F0000, 0x696C1300, 15 | 0x65547473, 0x28207473, 0x706D6F63, 0x646E756F, 0x00000A29, 0x00080200, 16 | 0x6D616E04, 0x430F0065, 0x6F706D6F, 0x20646E75, 0x20676174, 0x00043023, 17 | 0x6572630A, 0x64657461, 0x006E6F2D, 0x52260100, 0x008DD537, 0x6E040008, 18 | 0x00656D61, 0x6D6F430F, 0x6E756F70, 0x61742064, 0x31232067, 0x630A0004, 19 | 0x74616572, 0x6F2D6465, 0x0100006E, 0xD5375226, 0x0001008D, 0x74796208, 20 | 0x73655465, 0x00077F74, 0x74796265, 0x72724165, 0x65547961, 0x28207473, 21 | 0x20656874, 0x73726966, 0x30312074, 0x76203030, 0x65756C61, 0x666F2073, 22 | 0x2A6E2820, 0x35322A6E, 0x2A6E2B35, 0x31252937, 0x202C3030, 0x72617473, 23 | 0x676E6974, 0x74697720, 0x3D6E2068, 0x30282030, 0x3236202C, 0x3433202C, 24 | 0x3631202C, 0x2C38202C, 0x2E2E2E20, 0x00002929, 0x3E00E803, 0x0A081022, 25 | 0x124C2C16, 0x56042046, 0x0E5C504E, 0x0228582E, 0x3230384A, 0x3A10543E, 26 | 0x1A2C480A, 0x36201412, 0x2A501C56, 0x5A58600E, 0x62381802, 0x42540C32, 27 | 0x5E483C3A, 0x5214441A, 0x1E1C2436, 0x2660402A, 0x0618345A, 0x220C0062, 28 | 0x163C0842, 0x46444C5E, 0x4E240452, 0x2E405C1E, 0x4A342826, 0x3E003006, 29 | 0x0A081022, 0x124C2C16, 0x56042046, 0x0E5C504E, 0x0228582E, 0x3230384A, 30 | 0x3A10543E, 0x1A2C480A, 0x36201412, 0x2A501C56, 0x5A58600E, 0x62381802, 31 | 0x42540C32, 0x5E483C3A, 0x5214441A, 0x1E1C2436, 0x2660402A, 0x0618345A, 32 | 0x220C0062, 0x163C0842, 0x46444C5E, 0x4E240452, 0x2E405C1E, 0x4A342826, 33 | 0x3E003006, 0x0A081022, 0x124C2C16, 0x56042046, 0x0E5C504E, 0x0228582E, 34 | 0x3230384A, 0x3A10543E, 0x1A2C480A, 0x36201412, 0x2A501C56, 0x5A58600E, 35 | 0x62381802, 0x42540C32, 0x5E483C3A, 0x5214441A, 0x1E1C2436, 0x2660402A, 36 | 0x0618345A, 0x220C0062, 0x163C0842, 0x46444C5E, 0x4E240452, 0x2E405C1E, 37 | 0x4A342826, 0x3E003006, 0x0A081022, 0x124C2C16, 0x56042046, 0x0E5C504E, 38 | 0x0228582E, 0x3230384A, 0x3A10543E, 0x1A2C480A, 0x36201412, 0x2A501C56, 39 | 0x5A58600E, 0x62381802, 0x42540C32, 0x5E483C3A, 0x5214441A, 0x1E1C2436, 40 | 0x2660402A, 0x0618345A, 0x220C0062, 0x163C0842, 0x46444C5E, 0x4E240452, 41 | 0x2E405C1E, 0x4A342826, 0x3E003006, 0x0A081022, 0x124C2C16, 0x56042046, 42 | 0x0E5C504E, 0x0228582E, 0x3230384A, 0x3A10543E, 0x1A2C480A, 0x36201412, 43 | 0x2A501C56, 0x5A58600E, 0x62381802, 0x42540C32, 0x5E483C3A, 0x5214441A, 44 | 0x1E1C2436, 0x2660402A, 0x0618345A, 0x220C0062, 0x163C0842, 0x46444C5E, 45 | 0x4E240452, 0x2E405C1E, 0x4A342826, 0x3E003006, 0x0A081022, 0x124C2C16, 46 | 0x56042046, 0x0E5C504E, 0x0228582E, 0x3230384A, 0x3A10543E, 0x1A2C480A, 47 | 0x36201412, 0x2A501C56, 0x5A58600E, 0x62381802, 0x42540C32, 0x5E483C3A, 48 | 0x5214441A, 0x1E1C2436, 0x2660402A, 0x0618345A, 0x220C0062, 0x163C0842, 49 | 0x46444C5E, 0x4E240452, 0x2E405C1E, 0x4A342826, 0x3E003006, 0x0A081022, 50 | 0x124C2C16, 0x56042046, 0x0E5C504E, 0x0228582E, 0x3230384A, 0x3A10543E, 51 | 0x1A2C480A, 0x36201412, 0x2A501C56, 0x5A58600E, 0x62381802, 0x42540C32, 52 | 0x5E483C3A, 0x5214441A, 0x1E1C2436, 0x2660402A, 0x0618345A, 0x220C0062, 53 | 0x163C0842, 0x46444C5E, 0x4E240452, 0x2E405C1E, 0x4A342826, 0x3E003006, 54 | 0x0A081022, 0x124C2C16, 0x56042046, 0x0E5C504E, 0x0228582E, 0x3230384A, 55 | 0x3A10543E, 0x1A2C480A, 0x36201412, 0x2A501C56, 0x5A58600E, 0x62381802, 56 | 0x42540C32, 0x5E483C3A, 0x5214441A, 0x1E1C2436, 0x2660402A, 0x0618345A, 57 | 0x220C0062, 0x163C0842, 0x46444C5E, 0x4E240452, 0x2E405C1E, 0x4A342826, 58 | 0x3E003006, 0x0A081022, 0x124C2C16, 0x56042046, 0x0E5C504E, 0x0228582E, 59 | 0x3230384A, 0x3A10543E, 0x1A2C480A, 0x36201412, 0x2A501C56, 0x5A58600E, 60 | 0x62381802, 0x42540C32, 0x5E483C3A, 0x5214441A, 0x1E1C2436, 0x2660402A, 61 | 0x0618345A, 0x220C0062, 0x163C0842, 0x46444C5E, 0x4E240452, 0x2E405C1E, 62 | 0x4A342826, 0x3E003006, 0x0A081022, 0x124C2C16, 0x56042046, 0x0E5C504E, 63 | 0x0228582E, 0x3230384A, 0x3A10543E, 0x1A2C480A, 0x36201412, 0x2A501C56, 64 | 0x5A58600E, 0x62381802, 0x42540C32, 0x5E483C3A, 0x5214441A, 0x1E1C2436, 65 | 0x2660402A, 0x0618345A, 0x220C0062, 0x163C0842, 0x46444C5E, 0x4E240452, 66 | 0x2E405C1E, 0x4A342826, 0x00063006, 0x756F640A, 0x54656C62, 0x3F747365, 67 | 0xBB6B8FDF, 0x005E6AFF 68 | ]).buffer; 69 | -------------------------------------------------------------------------------- /fixtures/longArrayTest.nbt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjmulder/nbt-js/655f8f7a2995a7b37f73320fd91102829cb87762/fixtures/longArrayTest.nbt.gz -------------------------------------------------------------------------------- /nbt.d.ts: -------------------------------------------------------------------------------- 1 | export as namespace nbt; 2 | /** 3 | * A mapping from type names to NBT type numbers. 4 | * {@link nbt.Writer} and {@link nbt.Reader} 5 | * have correspoding methods (e.g. {@link nbt.Writer.prototype.int}) 6 | * for every type. 7 | */ 8 | export const tagTypes: { 9 | readonly end: 0; 10 | readonly byte: 1; 11 | readonly short: 2; 12 | readonly int: 3; 13 | readonly long: 4; 14 | readonly float: 5; 15 | readonly double: 6; 16 | readonly byteArray: 7; 17 | readonly string: 8; 18 | readonly list: 9; 19 | readonly compound: 10; 20 | readonly intArray: 11; 21 | readonly longArray: 12; 22 | }; 23 | export type tagTypes = typeof tagTypes; 24 | export type TagType = tagTypes[keyof tagTypes]; 25 | /** 26 | * A mapping from NBT type numbers to type names. 27 | */ 28 | export const tagTypeNames: { 29 | 0: "end"; 30 | 1: "byte"; 31 | 2: "short"; 32 | 3: "int"; 33 | 4: "long"; 34 | 5: "float"; 35 | 6: "double"; 36 | 7: "byteArray"; 37 | 8: "string"; 38 | 9: "list"; 39 | 10: "compound"; 40 | 11: "intArray"; 41 | 12: "longArray"; 42 | }; 43 | export type tagTypeNames = typeof tagTypeNames; 44 | export type TagTypeName = tagTypeNames[keyof tagTypeNames]; 45 | export interface RootTag { 46 | name: string; 47 | value: CompoundTag["value"]; 48 | } 49 | export type Tag = ByteTag | ShortTag | IntTag | LongTag | FloatTag | DoubleTag | ByteArrayTag | StringTag | ListTag | CompoundTag | IntArrayTag | LongArrayTag; 50 | export interface ByteTag { 51 | type: tagTypeNames[tagTypes["byte"]]; 52 | value: number; 53 | } 54 | export interface ShortTag { 55 | type: tagTypeNames[tagTypes["short"]]; 56 | value: number; 57 | } 58 | export interface IntTag { 59 | type: tagTypeNames[tagTypes["int"]]; 60 | value: number; 61 | } 62 | export interface LongTag { 63 | type: tagTypeNames[tagTypes["long"]]; 64 | value: [number, number]; 65 | } 66 | export interface FloatTag { 67 | type: tagTypeNames[tagTypes["float"]]; 68 | value: number; 69 | } 70 | export interface DoubleTag { 71 | type: tagTypeNames[tagTypes["double"]]; 72 | value: number; 73 | } 74 | export interface ByteArrayTag { 75 | type: tagTypeNames[tagTypes["byteArray"]]; 76 | value: number[]; 77 | } 78 | export interface StringTag { 79 | type: tagTypeNames[tagTypes["string"]]; 80 | value: string; 81 | } 82 | export interface ListTag { 83 | type: tagTypeNames[tagTypes["list"]]; 84 | value: { 85 | type: T["type"]; 86 | value: T["value"][]; 87 | }; 88 | } 89 | export interface CompoundTag { 90 | type: tagTypeNames[tagTypes["compound"]]; 91 | value: { 92 | [name: string]: Tag; 93 | }; 94 | } 95 | export interface IntArrayTag { 96 | type: tagTypeNames[tagTypes["intArray"]]; 97 | value: number[]; 98 | } 99 | export interface LongArrayTag { 100 | type: tagTypeNames[tagTypes["longArray"]]; 101 | value: LongTag["value"][]; 102 | } 103 | export type WriterDataType = { 104 | [K in keyof DataView]: K extends `set${infer T}` ? T extends `Big${string}` ? never : T : never; 105 | }[keyof DataView]; 106 | /** 107 | * In addition to the named writing methods documented below, 108 | * the same methods are indexed by the NBT type number as well, 109 | * as shown in the example below. 110 | * 111 | * @see {@link nbt.Reader} 112 | * 113 | * @example 114 | * var writer = new nbt.Writer(); 115 | * 116 | * // all equivalent 117 | * writer.int(42); 118 | * writer[3](42); 119 | * writer(nbt.tagTypes.int)(42); 120 | * 121 | * // overwrite the second int 122 | * writer.offset = 0; 123 | * writer.int(999); 124 | * 125 | * return writer.buffer; */ 126 | export class Writer { 127 | /** Will be resized (x2) on write if necessary. */ 128 | buffer: ArrayBuffer; 129 | /** This is recreated when the buffer is */ 130 | dataView: DataView; 131 | /** This is recreated when the buffer is */ 132 | arrayView: Uint8Array; 133 | /** 134 | * The location in the buffer where bytes are written or read. 135 | * This increases after every write, but can be freely changed. 136 | * The buffer will be resized when necessary. 137 | */ 138 | offset: number; 139 | /** 140 | * Returns the writen data as a slice from the internal buffer, 141 | * cutting off any padding at the end. 142 | * 143 | * @returns a [0, offset] slice of the interal buffer */ 144 | getData(): ArrayBuffer; 145 | /** 146 | * @param value - a signed byte 147 | * @returns itself */ 148 | byte: (value: number) => this; 149 | [tagTypes.byte]: (value: number) => this; 150 | /** 151 | * @param value - an unsigned byte 152 | * @returns itself */ 153 | ubyte: (value: number) => this; 154 | /** 155 | * @param value - a signed 16-bit integer 156 | * @returns itself */ 157 | short: (value: number) => this; 158 | [tagTypes.short]: (value: number) => this; 159 | /** 160 | * @param value - a signed 32-bit integer 161 | * @returns itself */ 162 | int: (value: number) => this; 163 | [tagTypes.int]: (value: number) => this; 164 | /** 165 | * @param value - a signed 32-bit float 166 | * @returns itself */ 167 | float: (value: number) => this; 168 | [tagTypes.float]: (value: number) => this; 169 | /** 170 | * @param value - a signed 64-bit float 171 | * @returns itself */ 172 | double: (value: number) => this; 173 | [tagTypes.double]: (value: number) => this; 174 | /** 175 | * As JavaScript does not support 64-bit integers natively, this 176 | * method takes an array of two 32-bit integers that make up the 177 | * upper and lower halves of the long. 178 | * 179 | * @param value - [upper, lower] 180 | * @returns itself */ 181 | long: (value: LongTag["value"]) => this; 182 | [tagTypes.long](value: LongTag["value"]): this; 183 | /** 184 | * @returns itself */ 185 | byteArray: (value: ByteArrayTag["value"] | Uint8Array) => this; 186 | [tagTypes.byteArray](value: ByteArrayTag["value"] | Uint8Array): this; 187 | /** 188 | * @returns itself */ 189 | intArray: (value: IntArrayTag["value"]) => this; 190 | [tagTypes.intArray](value: IntArrayTag["value"]): this; 191 | /** 192 | * @returns itself */ 193 | longArray: (value: LongArrayTag["value"]) => this; 194 | [tagTypes.longArray](value: LongArrayTag["value"]): this; 195 | /** 196 | * @returns itself */ 197 | string: (value: StringTag["value"]) => this; 198 | [tagTypes.string](value: StringTag["value"]): this; 199 | /** 200 | * @param value 201 | * @param value.type - the NBT type number 202 | * @param value.value - an array of values 203 | * @returns itself */ 204 | list: (value: ListTag["value"]) => this; 205 | [tagTypes.list](value: ListTag["value"]): this; 206 | /** 207 | * @param value - a key/value map 208 | * @param value.KEY 209 | * @param value.KEY.type - the NBT type number 210 | * @param value.KEY.value - a value matching the type 211 | * @returns itself 212 | * 213 | * @example 214 | * writer.compound({ 215 | * foo: { type: 'int', value: 12 }, 216 | * bar: { type: 'string', value: 'Hello, World!' } 217 | * }); */ 218 | compound: (value: CompoundTag["value"]) => this; 219 | [tagTypes.compound](value: CompoundTag["value"]): this; 220 | } 221 | export type ReaderDataType = { 222 | [K in keyof DataView]: K extends `get${infer T}` ? T extends `Big${string}` ? never : T : never; 223 | }[keyof DataView]; 224 | /** 225 | * In addition to the named writing methods documented below, 226 | * the same methods are indexed by the NBT type number as well, 227 | * as shown in the example below. 228 | * 229 | * @see {@link nbt.Writer} 230 | * 231 | * @example 232 | * var reader = new nbt.Reader(buf); 233 | * int x = reader.int(); 234 | * int y = reader[3](); 235 | * int z = reader[nbt.tagTypes.int](); */ 236 | export class Reader { 237 | constructor(buffer: ArrayBuffer | Uint8Array); 238 | /** 239 | * The current location in the buffer. Can be freely changed 240 | * within the bounds of the buffer. */ 241 | offset: number; 242 | buffer: ArrayBuffer | Uint8Array; 243 | arrayView: Uint8Array; 244 | dataView: DataView; 245 | read(dataType: ReaderDataType, size: number): number; 246 | /** 247 | * @returns the read byte */ 248 | byte: () => number; 249 | [tagTypes.byte]: () => number; 250 | /** 251 | * @returns the read unsigned byte */ 252 | ubyte: () => number; 253 | /** 254 | * @returns the read signed 16-bit short */ 255 | short: () => number; 256 | [tagTypes.short]: () => number; 257 | /** 258 | * @returns the read signed 32-bit integer */ 259 | int: () => number; 260 | [tagTypes.int]: () => number; 261 | /** 262 | * @returns the read signed 32-bit float */ 263 | float: () => number; 264 | [tagTypes.float]: () => number; 265 | /** 266 | * @returns the read signed 64-bit float */ 267 | double: () => number; 268 | [tagTypes.double]: () => number; 269 | /** 270 | * As JavaScript does not not natively support 64-bit 271 | * integers, the value is returned as an array of two 272 | * 32-bit integers, the upper and the lower. 273 | * 274 | * @returns [upper, lower] */ 275 | long: () => LongTag["value"]; 276 | [tagTypes.long](): LongTag["value"]; 277 | /** 278 | * @returns the read array */ 279 | byteArray: () => ByteArrayTag["value"]; 280 | [tagTypes.byteArray](): ByteArrayTag["value"]; 281 | /** 282 | * @returns the read array of 32-bit ints */ 283 | intArray: () => IntArrayTag["value"]; 284 | [tagTypes.intArray](): IntArrayTag["value"]; 285 | /** 286 | * As JavaScript does not not natively support 64-bit 287 | * integers, the value is returned as an array of arrays of two 288 | * 32-bit integers, the upper and the lower. 289 | * 290 | * @returns the read array of 64-bit ints 291 | * split into [upper, lower] */ 292 | longArray: () => LongArrayTag["value"]; 293 | [tagTypes.longArray](): LongArrayTag["value"]; 294 | /** 295 | * @returns the read string */ 296 | string: () => StringTag["value"]; 297 | [tagTypes.string](): StringTag["value"]; 298 | /** 299 | * @example 300 | * reader.list(); 301 | * // -> { type: 'string', values: ['foo', 'bar'] } */ 302 | list: () => ListTag["value"]; 303 | [tagTypes.list](): ListTag["value"]; 304 | /** 305 | * @example 306 | * reader.compound(); 307 | * // -> { foo: { type: int, value: 42 }, 308 | * // bar: { type: string, value: 'Hello! }} */ 309 | compound: () => CompoundTag["value"]; 310 | [tagTypes.compound](): CompoundTag["value"]; 311 | } 312 | /** 313 | * @param value a named compound 314 | * @param value.name the top-level name 315 | * @param value.value a compound 316 | * 317 | * @see {@link nbt.parseUncompressed} 318 | * @see {@link nbt.Writer.prototype.compound} 319 | * 320 | * @example 321 | * nbt.writeUncompressed({ 322 | * name: 'My Level', 323 | * value: { 324 | * foo: { type: int, value: 42 }, 325 | * bar: { type: string, value: 'Hi!' } 326 | * } 327 | * }); */ 328 | export function writeUncompressed(value: RootTag): ArrayBuffer; 329 | /** 330 | * @param data an uncompressed NBT archive 331 | * @returns a named compound 332 | * 333 | * @see {@link nbt.parse} 334 | * @see {@link nbt.writeUncompressed} 335 | * 336 | * @example 337 | * nbt.readUncompressed(buf); 338 | * // -> { name: 'My Level', 339 | * // value: { foo: { type: int, value: 42 }, 340 | * // bar: { type: string, value: 'Hi!' }}} */ 341 | export function parseUncompressed(data: ArrayBuffer | Uint8Array): RootTag; 342 | /** 343 | * @param result a named compound 344 | * @param result.name the top-level name 345 | * @param result.value the top-level compound 346 | */ 347 | export type parseCallback = { 348 | (error: Error, result: null): void; 349 | (error: null, result: RootTag): void; 350 | }; 351 | /** 352 | * This accepts both gzipped and uncompressd NBT archives. 353 | * If the archive is uncompressed, the callback will be 354 | * called directly from this method. For gzipped files, the 355 | * callback is async. 356 | * 357 | * For use in the browser, window.zlib must be defined to decode 358 | * compressed archives. It will be passed a Buffer if the type is 359 | * available, or an Uint8Array otherwise. 360 | * 361 | * @param data gzipped or uncompressed data 362 | * 363 | * @see {@link nbt.parseUncompressed} 364 | * @see {@link nbt.Reader.prototype.compound} 365 | * 366 | * @example 367 | * nbt.parse(buf, function(error, results) { 368 | * if (error) { 369 | * throw error; 370 | * } 371 | * console.log(result.name); 372 | * console.log(result.value.foo); 373 | * }); */ 374 | export function parse(data: ArrayBuffer | Uint8Array, callback: parseCallback): void; 375 | -------------------------------------------------------------------------------- /nbt.js: -------------------------------------------------------------------------------- 1 | /* 2 | NBT.js - a JavaScript parser for NBT archives 3 | by Sijmen Mulder 4 | 5 | I, the copyright holder of this work, hereby release it into the public 6 | domain. This applies worldwide. 7 | 8 | In case this is not legally possible: I grant anyone the right to use this 9 | work for any purpose, without any conditions, unless such conditions are 10 | required by law. 11 | */ 12 | 13 | (function() { 14 | 'use strict'; 15 | 16 | if (typeof ArrayBuffer === 'undefined') { 17 | throw new Error('Missing required type ArrayBuffer'); 18 | } 19 | if (typeof DataView === 'undefined') { 20 | throw new Error('Missing required type DataView'); 21 | } 22 | if (typeof Uint8Array === 'undefined') { 23 | throw new Error('Missing required type Uint8Array'); 24 | } 25 | 26 | /** @exports nbt */ 27 | 28 | var nbt = this; 29 | var zlib = typeof require !== 'undefined' ? require('zlib') : window.zlib; 30 | 31 | /** 32 | * A mapping from type names to NBT type numbers. 33 | * {@link module:nbt.Writer} and {@link module:nbt.Reader} 34 | * have correspoding methods (e.g. {@link module:nbt.Writer#int}) 35 | * for every type. 36 | * 37 | * @type Object 38 | * @see module:nbt.tagTypeNames */ 39 | nbt.tagTypes = { 40 | 'end': 0, 41 | 'byte': 1, 42 | 'short': 2, 43 | 'int': 3, 44 | 'long': 4, 45 | 'float': 5, 46 | 'double': 6, 47 | 'byteArray': 7, 48 | 'string': 8, 49 | 'list': 9, 50 | 'compound': 10, 51 | 'intArray': 11, 52 | 'longArray': 12 53 | }; 54 | 55 | /** 56 | * A mapping from NBT type numbers to type names. 57 | * 58 | * @type Object 59 | * @see module:nbt.tagTypes */ 60 | nbt.tagTypeNames = {}; 61 | (function() { 62 | for (var typeName in nbt.tagTypes) { 63 | if (nbt.tagTypes.hasOwnProperty(typeName)) { 64 | nbt.tagTypeNames[nbt.tagTypes[typeName]] = typeName; 65 | } 66 | } 67 | })(); 68 | 69 | function hasGzipHeader(data) { 70 | var head = new Uint8Array(data.slice(0, 2)); 71 | return head.length === 2 && head[0] === 0x1f && head[1] === 0x8b; 72 | } 73 | 74 | function encodeUTF8(str) { 75 | var array = [], i, c; 76 | for (i = 0; i < str.length; i++) { 77 | c = str.charCodeAt(i); 78 | if (c < 0x80) { 79 | array.push(c); 80 | } else if (c < 0x800) { 81 | array.push(0xC0 | c >> 6); 82 | array.push(0x80 | c & 0x3F); 83 | } else if (c < 0x10000) { 84 | array.push(0xE0 | c >> 12); 85 | array.push(0x80 | (c >> 6) & 0x3F); 86 | array.push(0x80 | c & 0x3F); 87 | } else { 88 | array.push(0xF0 | (c >> 18) & 0x07); 89 | array.push(0x80 | (c >> 12) & 0x3F); 90 | array.push(0x80 | (c >> 6) & 0x3F); 91 | array.push(0x80 | c & 0x3F); 92 | } 93 | } 94 | return array; 95 | } 96 | 97 | function decodeUTF8(array) { 98 | var codepoints = [], i; 99 | for (i = 0; i < array.length; i++) { 100 | if ((array[i] & 0x80) === 0) { 101 | codepoints.push(array[i] & 0x7F); 102 | } else if (i+1 < array.length && 103 | (array[i] & 0xE0) === 0xC0 && 104 | (array[i+1] & 0xC0) === 0x80) { 105 | codepoints.push( 106 | ((array[i] & 0x1F) << 6) | 107 | ( array[i+1] & 0x3F)); 108 | } else if (i+2 < array.length && 109 | (array[i] & 0xF0) === 0xE0 && 110 | (array[i+1] & 0xC0) === 0x80 && 111 | (array[i+2] & 0xC0) === 0x80) { 112 | codepoints.push( 113 | ((array[i] & 0x0F) << 12) | 114 | ((array[i+1] & 0x3F) << 6) | 115 | ( array[i+2] & 0x3F)); 116 | } else if (i+3 < array.length && 117 | (array[i] & 0xF8) === 0xF0 && 118 | (array[i+1] & 0xC0) === 0x80 && 119 | (array[i+2] & 0xC0) === 0x80 && 120 | (array[i+3] & 0xC0) === 0x80) { 121 | codepoints.push( 122 | ((array[i] & 0x07) << 18) | 123 | ((array[i+1] & 0x3F) << 12) | 124 | ((array[i+2] & 0x3F) << 6) | 125 | ( array[i+3] & 0x3F)); 126 | } 127 | } 128 | return String.fromCharCode.apply(null, codepoints); 129 | } 130 | 131 | /* Not all environments, in particular PhantomJS, supply 132 | Uint8Array.slice() */ 133 | function sliceUint8Array(array, begin, end) { 134 | if ('slice' in array) { 135 | return array.slice(begin, end); 136 | } else { 137 | return new Uint8Array([].slice.call(array, begin, end)); 138 | } 139 | } 140 | 141 | /** 142 | * In addition to the named writing methods documented below, 143 | * the same methods are indexed by the NBT type number as well, 144 | * as shown in the example below. 145 | * 146 | * @constructor 147 | * @see module:nbt.Reader 148 | * 149 | * @example 150 | * var writer = new nbt.Writer(); 151 | * 152 | * // all equivalent 153 | * writer.int(42); 154 | * writer[3](42); 155 | * writer(nbt.tagTypes.int)(42); 156 | * 157 | * // overwrite the second int 158 | * writer.offset = 0; 159 | * writer.int(999); 160 | * 161 | * return writer.buffer; */ 162 | nbt.Writer = function() { 163 | var self = this; 164 | 165 | /* Will be resized (x2) on write if necessary. */ 166 | var buffer = new ArrayBuffer(1024); 167 | 168 | /* These are recreated when the buffer is */ 169 | var dataView = new DataView(buffer); 170 | var arrayView = new Uint8Array(buffer); 171 | 172 | /** 173 | * The location in the buffer where bytes are written or read. 174 | * This increases after every write, but can be freely changed. 175 | * The buffer will be resized when necessary. 176 | * 177 | * @type number */ 178 | this.offset = 0; 179 | 180 | // Ensures that the buffer is large enough to write `size` bytes 181 | // at the current `self.offset`. 182 | function accommodate(size) { 183 | var requiredLength = self.offset + size; 184 | if (buffer.byteLength >= requiredLength) { 185 | return; 186 | } 187 | 188 | var newLength = buffer.byteLength; 189 | while (newLength < requiredLength) { 190 | newLength *= 2; 191 | } 192 | 193 | var newBuffer = new ArrayBuffer(newLength); 194 | var newArrayView = new Uint8Array(newBuffer); 195 | newArrayView.set(arrayView); 196 | 197 | // If there's a gap between the end of the old buffer 198 | // and the start of the new one, we need to zero it out 199 | if (self.offset > buffer.byteLength) { 200 | newArrayView.fill(0, buffer.byteLength, self.offset); 201 | } 202 | 203 | buffer = newBuffer; 204 | dataView = new DataView(newBuffer); 205 | arrayView = newArrayView; 206 | } 207 | 208 | function write(dataType, size, value) { 209 | accommodate(size); 210 | dataView['set' + dataType](self.offset, value); 211 | self.offset += size; 212 | return self; 213 | } 214 | 215 | /** 216 | * Returns the writen data as a slice from the internal buffer, 217 | * cutting off any padding at the end. 218 | * 219 | * @returns {ArrayBuffer} a [0, offset] slice of the interal buffer */ 220 | this.getData = function() { 221 | accommodate(0); /* make sure the offset is inside the buffer */ 222 | return buffer.slice(0, self.offset); 223 | }; 224 | 225 | /** 226 | * @method module:nbt.Writer#byte 227 | * @param {number} value - a signed byte 228 | * @returns {module:nbt.Writer} itself */ 229 | this[nbt.tagTypes.byte] = write.bind(this, 'Int8', 1); 230 | 231 | /** 232 | * @method module:nbt.Writer#ubyte 233 | * @param {number} value - an unsigned byte 234 | * @returns {module:nbt.Writer} itself */ 235 | this.ubyte = write.bind(this, 'Uint8', 1); 236 | 237 | /** 238 | * @method module:nbt.Writer#short 239 | * @param {number} value - a signed 16-bit integer 240 | * @returns {module:nbt.Writer} itself */ 241 | this[nbt.tagTypes.short] = write.bind(this, 'Int16', 2); 242 | 243 | /** 244 | * @method module:nbt.Writer#int 245 | * @param {number} value - a signed 32-bit integer 246 | * @returns {module:nbt.Writer} itself */ 247 | this[nbt.tagTypes.int] = write.bind(this, 'Int32', 4); 248 | 249 | /** 250 | * @method module:nbt.Writer#float 251 | * @param {number} value - a signed 32-bit float 252 | * @returns {module:nbt.Writer} itself */ 253 | this[nbt.tagTypes.float] = write.bind(this, 'Float32', 4); 254 | 255 | /** 256 | * @method module:nbt.Writer#float 257 | * @param {number} value - a signed 64-bit float 258 | * @returns {module:nbt.Writer} itself */ 259 | this[nbt.tagTypes.double] = write.bind(this, 'Float64', 8); 260 | 261 | /** 262 | * As JavaScript does not support 64-bit integers natively, this 263 | * method takes an array of two 32-bit integers that make up the 264 | * upper and lower halves of the long. 265 | * 266 | * @method module:nbt.Writer#long 267 | * @param {Array.} value - [upper, lower] 268 | * @returns {module:nbt.Writer} itself */ 269 | this[nbt.tagTypes.long] = function(value) { 270 | self.int(value[0]); 271 | self.int(value[1]); 272 | return self; 273 | }; 274 | 275 | /** 276 | * @method module:nbt.Writer#byteArray 277 | * @param {Array.|Uint8Array|Buffer} value 278 | * @returns {module:nbt.Writer} itself */ 279 | this[nbt.tagTypes.byteArray] = function(value) { 280 | this.int(value.length); 281 | accommodate(value.length); 282 | arrayView.set(value, this.offset); 283 | this.offset += value.length; 284 | return this; 285 | }; 286 | 287 | /** 288 | * @method module:nbt.Writer#intArray 289 | * @param {Array.} value 290 | * @returns {module:nbt.Writer} itself */ 291 | this[nbt.tagTypes.intArray] = function(value) { 292 | this.int(value.length); 293 | var i; 294 | for (i = 0; i < value.length; i++) { 295 | this.int(value[i]); 296 | } 297 | return this; 298 | }; 299 | 300 | /** 301 | * @method module:nbt.Writer#longArray 302 | * @param {Array.} value 303 | * @returns {module:nbt.Writer} itself */ 304 | this[nbt.tagTypes.longArray] = function(value) { 305 | this.int(value.length); 306 | var i; 307 | for (i = 0; i < value.length; i++) { 308 | this.long(value[i]); 309 | } 310 | return this; 311 | }; 312 | 313 | /** 314 | * @method module:nbt.Writer#string 315 | * @param {string} value 316 | * @returns {module:nbt.Writer} itself */ 317 | this[nbt.tagTypes.string] = function(value) { 318 | var bytes = encodeUTF8(value); 319 | this.short(bytes.length); 320 | accommodate(bytes.length); 321 | arrayView.set(bytes, this.offset); 322 | this.offset += bytes.length; 323 | return this; 324 | }; 325 | 326 | /** 327 | * @method module:nbt.Writer#list 328 | * @param {Object} value 329 | * @param {number} value.type - the NBT type number 330 | * @param {Array} value.value - an array of values 331 | * @returns {module:nbt.Writer} itself */ 332 | this[nbt.tagTypes.list] = function(value) { 333 | this.byte(nbt.tagTypes[value.type]); 334 | this.int(value.value.length); 335 | var i; 336 | for (i = 0; i < value.value.length; i++) { 337 | this[value.type](value.value[i]); 338 | } 339 | return this; 340 | }; 341 | 342 | /** 343 | * @method module:nbt.Writer#compound 344 | * @param {Object} value - a key/value map 345 | * @param {Object} value.KEY 346 | * @param {string} value.KEY.type - the NBT type number 347 | * @param {Object} value.KEY.value - a value matching the type 348 | * @returns {module:nbt.Writer} itself 349 | * 350 | * @example 351 | * writer.compound({ 352 | * foo: { type: 'int', value: 12 }, 353 | * bar: { type: 'string', value: 'Hello, World!' } 354 | * }); */ 355 | this[nbt.tagTypes.compound] = function(value) { 356 | var self = this; 357 | Object.keys(value).map(function (key) { 358 | self.byte(nbt.tagTypes[value[key].type]); 359 | self.string(key); 360 | self[value[key].type](value[key].value); 361 | }); 362 | this.byte(nbt.tagTypes.end); 363 | return this; 364 | }; 365 | 366 | var typeName; 367 | for (typeName in nbt.tagTypes) { 368 | if (nbt.tagTypes.hasOwnProperty(typeName)) { 369 | this[typeName] = this[nbt.tagTypes[typeName]]; 370 | } 371 | } 372 | }; 373 | 374 | /** 375 | * In addition to the named writing methods documented below, 376 | * the same methods are indexed by the NBT type number as well, 377 | * as shown in the example below. 378 | * 379 | * @constructor 380 | * @see module:nbt.Writer 381 | * 382 | * @example 383 | * var reader = new nbt.Reader(buf); 384 | * int x = reader.int(); 385 | * int y = reader[3](); 386 | * int z = reader[nbt.tagTypes.int](); */ 387 | nbt.Reader = function(buffer) { 388 | if (!buffer) { throw new Error('Argument "buffer" is falsy'); } 389 | 390 | var self = this; 391 | 392 | /** 393 | * The current location in the buffer. Can be freely changed 394 | * within the bounds of the buffer. 395 | * 396 | * @type number */ 397 | this.offset = 0; 398 | 399 | var arrayView = new Uint8Array(buffer); 400 | var dataView = new DataView(arrayView.buffer); 401 | 402 | function read(dataType, size) { 403 | var val = dataView['get' + dataType](self.offset); 404 | self.offset += size; 405 | return val; 406 | } 407 | 408 | /** 409 | * @method module:nbt.Reader#byte 410 | * @returns {number} the read byte */ 411 | this[nbt.tagTypes.byte] = read.bind(this, 'Int8', 1); 412 | 413 | /** 414 | * @method module:nbt.Reader#byte 415 | * @returns {number} the read unsigned byte */ 416 | this.ubyte = read.bind(this, 'Uint8', 1); 417 | 418 | /** 419 | * @method module:nbt.Reader#short 420 | * @returns {number} the read signed 16-bit short */ 421 | this[nbt.tagTypes.short] = read.bind(this, 'Int16', 2); 422 | 423 | /** 424 | * @method module:nbt.Reader#int 425 | * @returns {number} the read signed 32-bit integer */ 426 | this[nbt.tagTypes.int] = read.bind(this, 'Int32', 4); 427 | 428 | /** 429 | * @method module:nbt.Reader#float 430 | * @returns {number} the read signed 32-bit float */ 431 | this[nbt.tagTypes.float] = read.bind(this, 'Float32', 4); 432 | 433 | /** 434 | * @method module:nbt.Reader#double 435 | * @returns {number} the read signed 64-bit float */ 436 | this[nbt.tagTypes.double] = read.bind(this, 'Float64', 8); 437 | 438 | /** 439 | * As JavaScript does not not natively support 64-bit 440 | * integers, the value is returned as an array of two 441 | * 32-bit integers, the upper and the lower. 442 | * 443 | * @method module:nbt.Reader#long 444 | * @returns {Array.} [upper, lower] */ 445 | this[nbt.tagTypes.long] = function() { 446 | return [this.int(), this.int()]; 447 | }; 448 | 449 | /** 450 | * @method module:nbt.Reader#byteArray 451 | * @returns {Array.} the read array */ 452 | this[nbt.tagTypes.byteArray] = function() { 453 | var length = this.int(); 454 | var bytes = []; 455 | var i; 456 | for (i = 0; i < length; i++) { 457 | bytes.push(this.byte()); 458 | } 459 | return bytes; 460 | }; 461 | 462 | /** 463 | * @method module:nbt.Reader#intArray 464 | * @returns {Array.} the read array of 32-bit ints */ 465 | this[nbt.tagTypes.intArray] = function() { 466 | var length = this.int(); 467 | var ints = []; 468 | var i; 469 | for (i = 0; i < length; i++) { 470 | ints.push(this.int()); 471 | } 472 | return ints; 473 | }; 474 | 475 | /** 476 | * As JavaScript does not not natively support 64-bit 477 | * integers, the value is returned as an array of arrays of two 478 | * 32-bit integers, the upper and the lower. 479 | * 480 | * @method module:nbt.Reader#longArray 481 | * @returns {Array.} the read array of 64-bit ints 482 | * split into [upper, lower] */ 483 | this[nbt.tagTypes.longArray] = function() { 484 | var length = this.int(); 485 | var longs = []; 486 | var i; 487 | for (i = 0; i < length; i++) { 488 | longs.push(this.long()); 489 | } 490 | return longs; 491 | }; 492 | 493 | /** 494 | * @method module:nbt.Reader#string 495 | * @returns {string} the read string */ 496 | this[nbt.tagTypes.string] = function() { 497 | var length = this.short(); 498 | var slice = sliceUint8Array(arrayView, this.offset, 499 | this.offset + length); 500 | this.offset += length; 501 | return decodeUTF8(slice); 502 | }; 503 | 504 | /** 505 | * @method module:nbt.Reader#list 506 | * @returns {{type: string, value: Array}} 507 | * 508 | * @example 509 | * reader.list(); 510 | * // -> { type: 'string', values: ['foo', 'bar'] } */ 511 | this[nbt.tagTypes.list] = function() { 512 | var type = this.byte(); 513 | var length = this.int(); 514 | var values = []; 515 | var i; 516 | for (i = 0; i < length; i++) { 517 | values.push(this[type]()); 518 | } 519 | return { type: nbt.tagTypeNames[type], value: values }; 520 | }; 521 | 522 | /** 523 | * @method module:nbt.Reader#compound 524 | * @returns {Object.} 525 | * 526 | * @example 527 | * reader.compound(); 528 | * // -> { foo: { type: int, value: 42 }, 529 | * // bar: { type: string, value: 'Hello! }} */ 530 | this[nbt.tagTypes.compound] = function() { 531 | var values = {}; 532 | while (true) { 533 | var type = this.byte(); 534 | if (type === nbt.tagTypes.end) { 535 | break; 536 | } 537 | var name = this.string(); 538 | var value = this[type](); 539 | values[name] = { type: nbt.tagTypeNames[type], value: value }; 540 | } 541 | return values; 542 | }; 543 | 544 | var typeName; 545 | for (typeName in nbt.tagTypes) { 546 | if (nbt.tagTypes.hasOwnProperty(typeName)) { 547 | this[typeName] = this[nbt.tagTypes[typeName]]; 548 | } 549 | } 550 | }; 551 | 552 | /** 553 | * @param {Object} value - a named compound 554 | * @param {string} value.name - the top-level name 555 | * @param {Object} value.value - a compound 556 | * @returns {ArrayBuffer} 557 | * 558 | * @see module:nbt.parseUncompressed 559 | * @see module:nbt.Writer#compound 560 | * 561 | * @example 562 | * nbt.writeUncompressed({ 563 | * name: 'My Level', 564 | * value: { 565 | * foo: { type: int, value: 42 }, 566 | * bar: { type: string, value: 'Hi!' } 567 | * } 568 | * }); */ 569 | nbt.writeUncompressed = function(value) { 570 | if (!value) { throw new Error('Argument "value" is falsy'); } 571 | 572 | var writer = new nbt.Writer(); 573 | 574 | writer.byte(nbt.tagTypes.compound); 575 | writer.string(value.name); 576 | writer.compound(value.value); 577 | 578 | return writer.getData(); 579 | }; 580 | 581 | /** 582 | * @param {ArrayBuffer|Buffer} data - an uncompressed NBT archive 583 | * @returns {{name: string, value: Object.}} 584 | * a named compound 585 | * 586 | * @see module:nbt.parse 587 | * @see module:nbt.writeUncompressed 588 | * 589 | * @example 590 | * nbt.readUncompressed(buf); 591 | * // -> { name: 'My Level', 592 | * // value: { foo: { type: int, value: 42 }, 593 | * // bar: { type: string, value: 'Hi!' }}} */ 594 | nbt.parseUncompressed = function(data) { 595 | if (!data) { throw new Error('Argument "data" is falsy'); } 596 | 597 | var reader = new nbt.Reader(data); 598 | 599 | var type = reader.byte(); 600 | if (type !== nbt.tagTypes.compound) { 601 | throw new Error('Top tag should be a compound'); 602 | } 603 | 604 | return { 605 | name: reader.string(), 606 | value: reader.compound() 607 | }; 608 | }; 609 | 610 | /** 611 | * @callback parseCallback 612 | * @param {Object} error 613 | * @param {Object} result - a named compound 614 | * @param {string} result.name - the top-level name 615 | * @param {Object} result.value - the top-level compound */ 616 | 617 | /** 618 | * This accepts both gzipped and uncompressd NBT archives. 619 | * If the archive is uncompressed, the callback will be 620 | * called directly from this method. For gzipped files, the 621 | * callback is async. 622 | * 623 | * For use in the browser, window.zlib must be defined to decode 624 | * compressed archives. It will be passed a Buffer if the type is 625 | * available, or an Uint8Array otherwise. 626 | * 627 | * @param {ArrayBuffer|Buffer} data - gzipped or uncompressed data 628 | * @param {parseCallback} callback 629 | * 630 | * @see module:nbt.parseUncompressed 631 | * @see module:nbt.Reader#compound 632 | * 633 | * @example 634 | * nbt.parse(buf, function(error, results) { 635 | * if (error) { 636 | * throw error; 637 | * } 638 | * console.log(result.name); 639 | * console.log(result.value.foo); 640 | * }); */ 641 | nbt.parse = function(data, callback) { 642 | if (!data) { throw new Error('Argument "data" is falsy'); } 643 | 644 | var self = this; 645 | 646 | if (!hasGzipHeader(data)) { 647 | callback(null, self.parseUncompressed(data)); 648 | } else if (!zlib) { 649 | callback(new Error('NBT archive is compressed but zlib is not ' + 650 | 'available'), null); 651 | } else { 652 | /* zlib.gunzip take a Buffer, at least in Node, so try to convert 653 | if possible. */ 654 | var buffer; 655 | if (data.length) { 656 | buffer = data; 657 | } else if (typeof Buffer !== 'undefined') { 658 | buffer = new Buffer(data); 659 | } else { 660 | /* In the browser? Unknown zlib library. Let's settle for 661 | Uint8Array and see what happens. */ 662 | buffer = new Uint8Array(data); 663 | } 664 | 665 | zlib.gunzip(buffer, function(error, uncompressed) { 666 | if (error) { 667 | callback(error, null); 668 | } else { 669 | callback(null, self.parseUncompressed(uncompressed)); 670 | } 671 | }); 672 | } 673 | }; 674 | }).apply(typeof exports !== 'undefined' ? exports : (window.nbt = {})); 675 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nbt", 3 | "version": "0.8.1", 4 | "description": "A parser and serializer for NBT archives", 5 | "keywords": [ 6 | "nbt", 7 | "minecraft" 8 | ], 9 | "homepage": "https://github.com/sjmulder/nbt-js", 10 | "author": "Sijmen Mulder ", 11 | "license": "SEE LICENSE IN License.md", 12 | "main": "nbt", 13 | "types": "nbt", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/sjmulder/nbt-js.git" 17 | }, 18 | "devDependencies": { 19 | "chai": "^3.5.0", 20 | "jsdoc": "^3.4.3", 21 | "mocha": "^5.2.0" 22 | }, 23 | "scripts": { 24 | "test": "make check" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sample/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "window": true 4 | }, 5 | 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "forin": true, 10 | "latedef": true, 11 | "noarg": true, 12 | "nonbsp": true, 13 | "nonew": true, 14 | "smarttabs": true, 15 | "strict": true, 16 | "sub": true, 17 | "trailing": true, 18 | "unused": true, 19 | "undef": true, 20 | 21 | "node": true 22 | } 23 | -------------------------------------------------------------------------------- /sample/sample.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'), 4 | nbt = require('../nbt'); 5 | 6 | var data = fs.readFileSync('../fixtures/bigtest.nbt.gz'); 7 | nbt.parse(data, function(error, data) { 8 | if (error) { throw error; } 9 | 10 | console.log(data.value.stringTest.value); 11 | console.log(data.value['nested compound test'].value); 12 | }); 13 | -------------------------------------------------------------------------------- /test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "window": true 4 | }, 5 | 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "forin": true, 10 | "latedef": true, 11 | "noarg": true, 12 | "nonbsp": true, 13 | "nonew": true, 14 | "smarttabs": true, 15 | "strict": true, 16 | "sub": true, 17 | "trailing": true, 18 | "unused": true, 19 | "undef": true, 20 | 21 | "node": true, 22 | "mocha": true 23 | } 24 | -------------------------------------------------------------------------------- /test/nbt-spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'), 4 | nbt = require('../nbt'), 5 | expect = require('chai').expect; 6 | 7 | describe('nbt.parse', function() { 8 | function checkBigtest(data) { 9 | expect(data.value.stringTest.value).to.equal( 10 | 'HELLO WORLD THIS IS A TEST STRING ÅÄÖ!'); 11 | expect(data.value['nested compound test'].value).to.deep.equal({ 12 | ham: { 13 | type: "compound", 14 | value: { 15 | name: { type: "string", value: "Hampus" }, 16 | value: { type: "float", value: 0.75 } 17 | } 18 | }, 19 | egg: { 20 | type: "compound", 21 | value: { 22 | name: { type: "string", value: 'Eggbert' }, 23 | value: { type: "float", value: 0.5 } 24 | } 25 | } 26 | }); 27 | } 28 | 29 | if (typeof zlib !== 'undefined') { 30 | it('parses a compressed NBT file', function(done) { 31 | var data = fs.readFileSync('fixtures/bigtest.nbt.gz'); 32 | nbt.parse(data, function(err, data) { 33 | if (err) { throw err; } 34 | checkBigtest(data); 35 | done(); 36 | }); 37 | }); 38 | } 39 | 40 | if (typeof zlib !== 'undefined' && typeof Buffer !== 'undefined') { 41 | /* Only applicable on Node where fs.readFile returns a Buffer object 42 | which has an ArrayBuffer .buffer attribute. */ 43 | it('parses a compressed NBT ArrayBuffer', function(done) { 44 | var data = fs.readFileSync('fixtures/bigtest.nbt.gz'); 45 | var buffer = data.buffer; 46 | nbt.parse(buffer, function(err, data) { 47 | if (err) { throw err; } 48 | checkBigtest(data); 49 | done(); 50 | }); 51 | }); 52 | } 53 | 54 | it('parses an uncompressed NBT file through parse()', function(done) { 55 | var data = fs.readFileSync('fixtures/bigtest.nbt'); 56 | nbt.parse(data, function(error, data) { 57 | if (error) { throw error; } 58 | checkBigtest(data); 59 | done(); 60 | }); 61 | }); 62 | 63 | it('parses an NBT file contining a long array', function(done) { 64 | var data = fs.readFileSync('fixtures/longArrayTest.nbt.gz'); 65 | nbt.parse(data, function(error, data) { 66 | if (error) { throw error; } 67 | expect(data.value).to.deep.equal({ 68 | LongArray: { 69 | type: 'longArray', 70 | value: [[1, 15], [538976288, 269488144], [84281096, 16909060]] // should be value: [[15, 1], [269488144, 538976288], [16909060, 84281096]] 71 | } 72 | }); 73 | done(); 74 | }); 75 | }); 76 | }); 77 | 78 | describe('nbt.write', function() { 79 | it('writes an uncompressed NBT file', function() { 80 | var nbtData = fs.readFileSync('fixtures/bigtest.nbt'); 81 | var jsonStr = fs.readFileSync('fixtures/bigtest.json', 'utf8'); 82 | var input = JSON.parse(jsonStr); 83 | var output = nbt.writeUncompressed(input); 84 | expect(new Uint8Array(output)).to.deep.equal( 85 | new Uint8Array(nbtData)); 86 | }); 87 | 88 | it('re-encodes it input perfectly', function() { 89 | var jsonStr = fs.readFileSync('fixtures/bigtest.json', 'utf8'); 90 | var input = JSON.parse(jsonStr); 91 | var output = nbt.writeUncompressed(input); 92 | var decodedOutput = nbt.parseUncompressed(output); 93 | expect(new Uint8Array(decodedOutput)).to.deep.equal( 94 | new Uint8Array(input)); 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /test/polyfills.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | /* Polyfills of a handful of interfaces to run the unit tests almost 5 | unmodified in the browser. */ 6 | 7 | function decodeUTF8(array) { 8 | var codepoints = [], i; 9 | for (i = 0; i < array.length; i++) { 10 | if ((array[i] & 0x80) === 0) { 11 | codepoints.push(array[i] & 0x7F); 12 | } else if (i+1 < array.length && 13 | (array[i] & 0xE0) === 0xC0 && 14 | (array[i+1] & 0xC0) === 0x80) { 15 | codepoints.push( 16 | ((array[i] & 0x1F) << 6) | 17 | ( array[i+1] & 0x3F)); 18 | } else if (i+2 < array.length && 19 | (array[i] & 0xF0) === 0xE0 && 20 | (array[i+1] & 0xC0) === 0x80 && 21 | (array[i+2] & 0xC0) === 0x80) { 22 | codepoints.push( 23 | ((array[i] & 0x0F) << 12) | 24 | ((array[i+1] & 0x3F) << 6) | 25 | ( array[i+2] & 0x3F)); 26 | } else if (i+3 < array.length && 27 | (array[i] & 0xF8) === 0xF0 && 28 | (array[i+1] & 0xC0) === 0x80 && 29 | (array[i+2] & 0xC0) === 0x80 && 30 | (array[i+3] & 0xC0) === 0x80) { 31 | codepoints.push( 32 | ((array[i] & 0x07) << 18) | 33 | ((array[i+1] & 0x3F) << 12) | 34 | ((array[i+2] & 0x3F) << 6) | 35 | ( array[i+3] & 0x3F)); 36 | } 37 | } 38 | return String.fromCharCode.apply(null, codepoints); 39 | } 40 | 41 | /* Simply returns window[] */ 42 | window.require = function(module) { 43 | return window[module]; 44 | }; 45 | 46 | /* Returns window[], converted to UTF8 if the 'utf8' encoding 47 | is requested. 48 | 49 | Use jsinc to convert files to a .js file that can be included with 50 | a script file and used here: 51 | 52 | jsinc myfile.dat > myfile.dat.js 53 | 54 | 55 | 58 | */ 59 | window.fs = {}; 60 | window.fs.readFileSync = function(filename, encoding) { 61 | var data = window[filename]; 62 | if (!data) { 63 | throw new Error('Unregistered file for readFileSync polyfill: ' + 64 | filename); 65 | } else if (encoding === 'utf8') { 66 | return decodeUTF8(new Uint8Array(data)); 67 | } else { 68 | return data; 69 | } 70 | }; 71 | 72 | /* ArrayBuffer.prototype.slice() is missing in PhantomJS < 2.0 but 73 | required for the jsinc files. */ 74 | if (!('slice' in ArrayBuffer.prototype)) { 75 | ArrayBuffer.prototype.slice = function(begin, end) { 76 | if (!end) { end = this.byteLength; } 77 | if (begin > end) { return new ArrayBuffer(0); } 78 | var ret = new ArrayBuffer(end - begin); 79 | new Uint8Array(ret).set(new Uint8Array(this, begin, end - begin)); 80 | return ret; 81 | }; 82 | } 83 | })(); 84 | -------------------------------------------------------------------------------- /test/reader-spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var nbt = require('../nbt'), 4 | expect = require('chai').expect; 5 | 6 | describe('nbt.Reader', function() { 7 | it('is constructed with a Uint8Array', function() { 8 | nbt.Reader(new Uint8Array([1, 2, 3])); 9 | }); 10 | 11 | it('reads 8-bit bytes', function() { 12 | var reader = new nbt.Reader(new Uint8Array([0, 127, -127])); 13 | expect(reader.byte()).to.equal(0); 14 | expect(reader.byte()).to.equal(127); 15 | expect(reader.byte()).to.equal(-127); 16 | }); 17 | 18 | it('reads 8-bit unsigned bytes', function() { 19 | var reader = new nbt.Reader(new Uint8Array([0, 127, 255])); 20 | expect(reader.ubyte()).to.equal(0); 21 | expect(reader.ubyte()).to.equal(127); 22 | expect(reader.ubyte()).to.equal(255); 23 | }); 24 | 25 | it('reads 16-bit shorts', function() { 26 | var reader = new nbt.Reader(new Uint8Array([ 27 | 0,0, 0,255, -127,255 28 | ])); 29 | expect(reader.short()).to.equal(0); 30 | expect(reader.short()).to.equal(255); 31 | expect(reader.short()).to.equal((-127 << 8) | 255); 32 | }); 33 | 34 | it('reads 32-bit ints', function() { 35 | var reader = new nbt.Reader(new Uint8Array([ 36 | 0,0,0,0, 37 | 0,0,0,255, 38 | -127,0,0,0 39 | ])); 40 | expect(reader.int()).to.equal(0); 41 | expect(reader.int()).to.equal(255); 42 | expect(reader.int()).to.equal(-127 << 24); 43 | }); 44 | 45 | it('reads 64-bit longs', function() { 46 | var reader = new nbt.Reader(new Uint8Array([ 47 | 0,0,0,0,0,0,0,0, 48 | 0,0,0,0,0,0,0,255, 49 | -127,0,0,0,0,0,0,0 50 | ])); 51 | expect(reader.long()).to.deep.equal([0, 0]); 52 | expect(reader.long()).to.deep.equal([0, 255]); 53 | expect(reader.long()).to.deep.equal([-127 << 24, 0]); 54 | }); 55 | 56 | it('reads 32-bit floats', function() { 57 | var reader = new nbt.Reader(new Uint8Array([ 58 | 0x00,0x00,0x00,0x00, 59 | 0x3f,0x80,0x00,0x00 60 | ])); 61 | expect(reader.float()).to.equal(0); 62 | expect(reader.float()).to.equal(1); 63 | }); 64 | 65 | it('reads 64-bit doubles', function() { 66 | var reader = new nbt.Reader(new Uint8Array([ 67 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 68 | 0x3f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00 69 | ])); 70 | expect(reader.double()).to.equal(0); 71 | expect(reader.double()).to.equal(1); 72 | }); 73 | 74 | it('reads 8-bit byte arrays', function() { 75 | var reader = new nbt.Reader(new Uint8Array([ 76 | 0,0,0,2, 1,2, 77 | 0,0,0,4, 3,4,5,6 78 | ])); 79 | expect(reader.byteArray()).to.deep.equal([1, 2]); 80 | expect(reader.byteArray()).to.deep.equal([3, 4, 5, 6]); 81 | }); 82 | 83 | it('reads 32-bit int arrays', function() { 84 | var reader = new nbt.Reader(new Uint8Array([ 85 | 0,0,0,2, 0,0,0,1, 0,0,0,2, 86 | 0,0,0,4, 0,0,0,3, 0,0,0,4, 0,0,0,5, 0,0,0,6, 87 | ])); 88 | expect(reader.intArray()).to.deep.equal([1, 2]); 89 | expect(reader.intArray()).to.deep.equal([3, 4, 5, 6]); 90 | }); 91 | 92 | it('reads 64-bit int arrays', function() { 93 | var reader = new nbt.Reader(new Uint8Array([ 94 | 0,0,0,1, 0,0,0,15, 0,0,0,1, 95 | 0,0,0,2, 16,16,16,16, 32,32,32,32, 1,2,3,4, 5,6,7,8, 96 | ])); 97 | expect(reader.longArray()).to.deep.equal([[15, 1]]); 98 | expect(reader.longArray()).to.deep.equal([[269488144, 538976288], [16909060, 84281096]]); 99 | }); 100 | 101 | it('reads strings', function() { 102 | var reader = new nbt.Reader(new Uint8Array([ 103 | 0,6, 0x48,0x65,0x6C,0x6C,0x6F,0x21, 104 | 0,16, 0xE3,0x81,0x93,0xE3,0x82,0x93,0xE3,0x81, 105 | 0xAB,0xE3,0x81,0xA1,0xE3,0x81,0xAF,0x21 106 | ])); 107 | expect(reader.string()).to.equal('Hello!'); 108 | expect(reader.string()).to.equal('こんにちは!'); 109 | }); 110 | 111 | it('reads lists', function() { 112 | var reader = new nbt.Reader(new Uint8Array([ 113 | 1, 0,0,0,3, 1, 2, 3, 114 | 8, 0,0,0,2, 0,5, 0x48,0x65,0x6C,0x6C,0x6F, 115 | 0,5, 0x57,0x6F,0x72,0x6C,0x64 116 | ])); 117 | expect(reader.list()).to.deep.equal( 118 | { type: "byte", value: [1, 2, 3] }); 119 | expect(reader.list()).to.deep.equal( 120 | { type: "string", value: ['Hello', 'World'] }); 121 | }); 122 | 123 | it('reads compounds', function() { 124 | var reader = new nbt.Reader(new Uint8Array([ 125 | 1, 0,2, 0x61,0x61, 1, 126 | 9, 0,2, 0x62,0x62, 1, 0,0,0,3, 1, 2, 3, 127 | 0, 128 | 1, 0,2, 0x63,0x63, 2, 129 | 0 130 | ])); 131 | expect(reader.compound()).to.deep.equal({ 132 | aa: { type: "byte", value: 1 }, 133 | bb: { type: "list", value: { type: "byte", value: [1, 2, 3] } } 134 | }); 135 | expect(reader.compound()).to.deep.equal({ 136 | cc: { type: "byte", value: 2 } 137 | }); 138 | }); 139 | 140 | it('tracks the cursor location', function() { 141 | var reader = new nbt.Reader(new Uint8Array([ 142 | 0, 0,0,0,0,0,0,0,0 143 | ])); 144 | expect(reader.offset).to.equal(0); 145 | reader.byte(); 146 | reader.long(); 147 | expect(reader.offset).to.equal(9); 148 | }); 149 | 150 | it('can change the cursor location', function() { 151 | var reader = new nbt.Reader(new Uint8Array([1, 2])); 152 | expect(reader.byte()).to.equal(1); 153 | reader.offset = 0; 154 | expect(reader.byte()).to.equal(1); 155 | }); 156 | 157 | if (typeof Buffer !== 'undefined') { 158 | it('is supports Buffer input', function() { 159 | var reader = new nbt.Reader(new Uint8Array([1, 2, 3])); 160 | expect(reader.byte()).to.equal(1); 161 | expect(reader.byte()).to.equal(2); 162 | expect(reader.byte()).to.equal(3); 163 | }); 164 | } 165 | }); 166 | -------------------------------------------------------------------------------- /test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NBT.js test runner 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /test/writer-spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var nbt = require('../nbt'), 4 | expect = require('chai').expect; 5 | 6 | describe('nbt.Writer', function() { 7 | it('is constructed with no arguments', function() { 8 | nbt.Writer(); 9 | }); 10 | 11 | it('writes 8-bit bytes', function() { 12 | var writer = new nbt.Writer(); 13 | writer.byte(0); 14 | writer.byte(127); 15 | writer.byte(-127); 16 | 17 | expect(new Uint8Array(writer.getData())).to.deep.equal( 18 | new Uint8Array([ 19 | 0, 127, 129 20 | ])); 21 | }); 22 | 23 | it('writes 8-bit unsigned bytes', function() { 24 | var writer = new nbt.Writer(); 25 | writer.ubyte(0); 26 | writer.ubyte(127); 27 | writer.ubyte(255); 28 | 29 | expect(new Uint8Array(writer.getData())).to.deep.equal( 30 | new Uint8Array([ 31 | 0, 127, 255 32 | ])); 33 | }); 34 | 35 | it('writes 16-bit shorts', function() { 36 | var writer = new nbt.Writer(); 37 | writer.short(0); 38 | writer.short(255); 39 | writer.short((-127 << 8) | 255); 40 | 41 | expect(new Uint8Array(writer.getData())).to.deep.equal( 42 | new Uint8Array([ 43 | 0, 0, 44 | 0, 255, 45 | 129, 255 46 | ])); 47 | }); 48 | 49 | it('writes 32-bit ints', function() { 50 | var writer = new nbt.Writer(); 51 | writer.int(0); 52 | writer.int(255); 53 | writer.int(-127 << 24); 54 | 55 | expect(new Uint8Array(writer.getData())).to.deep.equal( 56 | new Uint8Array([ 57 | 0, 0, 0, 0, 58 | 0, 0, 0, 255, 59 | 129, 0, 0, 0 60 | ])); 61 | }); 62 | 63 | it('writes 64-bit longs', function() { 64 | var writer = new nbt.Writer(); 65 | writer.long([0, 0]); 66 | writer.long([0, 255]); 67 | writer.long([-127 << 24, 0]); 68 | 69 | expect(new Uint8Array(writer.getData())).to.deep.equal( 70 | new Uint8Array([ 71 | 0, 0, 0, 0, 0, 0, 0, 0, 72 | 0, 0, 0, 0, 0, 0, 0, 255, 73 | 129, 0, 0, 0, 0, 0, 0, 0 74 | ])); 75 | }); 76 | 77 | it('writes 32-bit floats', function() { 78 | var writer = new nbt.Writer(); 79 | writer.float(0); 80 | writer.float(1); 81 | 82 | expect(new Uint8Array(writer.getData())).to.deep.equal( 83 | new Uint8Array([ 84 | 0x00, 0x00, 0x00, 0x00, 85 | 0x3F, 0x80, 0x00, 0x00 86 | ])); 87 | }); 88 | 89 | it('writes 64-bit doubles', function() { 90 | var writer = new nbt.Writer(); 91 | writer.double(0); 92 | writer.double(1); 93 | 94 | expect(new Uint8Array(writer.getData())).to.deep.equal( 95 | new Uint8Array([ 96 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 97 | 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 | ])); 99 | }); 100 | 101 | it('writes 8-bit byte arrays from typed arrays', function() { 102 | var writer = new nbt.Writer(); 103 | writer.byteArray(new Uint8Array([1, 2])); 104 | writer.byteArray(new Uint8Array([3,4, 5, 6])); 105 | 106 | expect(new Uint8Array(writer.getData())).to.deep.equal( 107 | new Uint8Array([ 108 | 0,0,0,2, 1,2, 109 | 0,0,0,4, 3,4,5,6 110 | ])); 111 | }); 112 | 113 | it('writes 8-bit byte arrays from plain arrays', function() { 114 | var writer = new nbt.Writer(); 115 | writer.byteArray([1, 2]); 116 | writer.byteArray([3,4, 5, 6]); 117 | 118 | expect(new Uint8Array(writer.getData())).to.deep.equal( 119 | new Uint8Array([ 120 | 0,0,0,2, 1,2, 121 | 0,0,0,4, 3,4,5,6 122 | ])); 123 | }); 124 | 125 | it('writes 32-bit int arrays', function() { 126 | var writer = new nbt.Writer(); 127 | writer.intArray([1, 2]); 128 | writer.intArray([3,4, 5, 6]); 129 | 130 | expect(new Uint8Array(writer.getData())).to.deep.equal( 131 | new Uint8Array([ 132 | 0,0,0,2, 0,0,0,1, 0,0,0,2, 133 | 0,0,0,4, 0,0,0,3, 0,0,0,4, 0,0,0,5, 0,0,0,6, 134 | ])); 135 | }); 136 | 137 | it('writes 64-bit int arrays', function() { 138 | var writer = new nbt.Writer(); 139 | writer.longArray([[15, 1]]); 140 | writer.longArray([[269488144, 538976288], [16909060, 84281096]]); 141 | 142 | expect(new Uint8Array(writer.getData())).to.deep.equal( 143 | new Uint8Array([ 144 | 0,0,0,1, 0,0,0,15, 0,0,0,1, 145 | 0,0,0,2, 16,16,16,16, 32,32,32,32, 1,2,3,4, 5,6,7,8, 146 | ])); 147 | }); 148 | 149 | it('writes strings', function() { 150 | var writer = new nbt.Writer(); 151 | writer.string('Hello!'); 152 | writer.string('こんにちは!'); 153 | 154 | expect(new Uint8Array(writer.getData())).to.deep.equal( 155 | new Uint8Array([ 156 | 0,6, 0x48,0x65,0x6C,0x6C,0x6F,0x21, 157 | 0,16, 0xE3,0x81,0x93,0xE3,0x82,0x93,0xE3,0x81, 158 | 0xAB,0xE3,0x81,0xA1,0xE3,0x81,0xAF,0x21 159 | ])); 160 | }); 161 | 162 | it('writes lists', function() { 163 | var writer = new nbt.Writer(); 164 | writer.list({ type: "byte", value: [1, 2, 3] }); 165 | writer.list({ type: "string", value: ['Hello', 'World'] }); 166 | 167 | expect(new Uint8Array(writer.getData())).to.deep.equal( 168 | new Uint8Array([ 169 | 1, 0,0,0,3, 1, 2, 3, 170 | 8, 0,0,0,2, 0,5, 0x48,0x65,0x6C,0x6C,0x6F, 171 | 0,5, 0x57,0x6F,0x72,0x6C,0x64 172 | ])); 173 | }); 174 | 175 | it('writes compounds', function() { 176 | var writer = new nbt.Writer(); 177 | 178 | writer.compound({ 179 | aa: { type: "byte", value: 1 }, 180 | bb: { type: "list", value: { type: "byte", value: [1, 2, 3] } } 181 | }); 182 | 183 | writer.compound({ 184 | cc: { type: "byte", value: 2 } 185 | }); 186 | 187 | expect(new Uint8Array(writer.getData())).to.deep.equal( 188 | new Uint8Array([ 189 | 1, 0,2, 0x61,0x61, 1, 190 | 9, 0,2, 0x62,0x62, 1, 0,0,0,3, 1, 2, 3, 191 | 0, 192 | 1, 0,2, 0x63,0x63, 2, 193 | 0 194 | ])); 195 | }); 196 | 197 | it('tracks the number of bytes written', function() { 198 | var writer = new nbt.Writer(); 199 | expect(writer.offset).to.equal(0); 200 | writer.byte(12); 201 | writer.long([34, 56]); 202 | expect(writer.offset).to.equal(9); 203 | }); 204 | 205 | it('can seek to a location within the buffer', function() { 206 | var writer = new nbt.Writer(); 207 | writer.short(0x1234); 208 | writer.offset = 1; 209 | writer.short(0x5678); 210 | 211 | expect(new Uint8Array(writer.getData())).to.deep.equal( 212 | new Uint8Array([ 213 | 0x12, 0x56, 0x78 214 | ])); 215 | }); 216 | 217 | it('can seek to a location beyond the buffer', function() { 218 | var writer = new nbt.Writer(); 219 | writer.short(0x1234); 220 | writer.offset = 1024; 221 | writer.short(0x5678); 222 | 223 | var data = writer.getData(); 224 | var array = new Uint8Array(data); 225 | expect(array.length).to.equal(1026); 226 | expect(array[0]).to.equal(0x12); 227 | expect(array[1]).to.equal(0x34); 228 | expect(array[2]).to.equal(0); 229 | expect(array[1023]).to.equal(0); 230 | expect(array[1024]).to.equal(0x56); 231 | expect(array[1025]).to.equal(0x78); 232 | }); 233 | }); 234 | 235 | --------------------------------------------------------------------------------