Skip to content

Commit

Permalink
Accept CompoundTag for Writing
Browse files Browse the repository at this point in the history
Now you can directly pass in a non `NBTData`-wrapped `CompoundTag` into the Write module methods! This makes things easier if you aren't working with `NBTData` objects directly, and with the bare NBT JavaScript object instead. Wrote more about this in the same-named issue on the repo!

In the demo test file, I simply wrote the same data to a buffer, using both the `NBT.write()` and `NBTWriter.write()` functions, one using the existing `NBTData` parameter call, and the other with only the `CompoundTag` and options config, no `NBTData` for that one. As you can see in the console, no errors, and the same identical buffer data is written! Noice.

Oh yeah, just to verify the value of the `CompoundTag` a little more strictly, I added a `data !== null` check in there too, since `typeof null` will return `"object"`. I think I read that it's a weird JavaScript legacy thing, kind of interesting. I don't want any of the library parameters to accept `null` as an NBT value! That would be confusing, haha.

Oooh! While writing that last sentence, decided to check this in TypeScript, and I'm very happy to say that this doesn't pass, aaah :)
Scared me for a moment, thinking about this possibly working, since `null` is technically an object in JS:
```ts
const thingo: object = null;
// Type 'null' is not assignable to type 'object'.
```
  • Loading branch information
Offroaders123 committed Dec 12, 2022
1 parent c84cb8a commit 00425ac
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class NBTData {
if (compression === undefined) compression = null;
if (bedrockLevel === undefined) bedrockLevel = null;

if (typeof data !== "object"){
if (typeof data !== "object" || data === null){
throw new TypeError("First parameter must be an object");
}
if (typeof name !== "string" && name !== null){
Expand Down
1 change: 0 additions & 1 deletion src/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ export class NBTReader {
}
const value = decoder.decode(this.#data.subarray(this.#byteOffset,this.#byteOffset + length));
this.#byteOffset += length;
console.log(value);
return value;
}

Expand Down
30 changes: 21 additions & 9 deletions src/write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@ export interface WriteOptions {
*
* If a format option isn't specified, the value of the equivalent property on the NBTData object will be used.
*/
export async function write(data: NBTData, { name = data.name, endian = data.endian, compression = data.compression, bedrockLevel = data.bedrockLevel }: WriteOptions = {}){
if (!(data instanceof NBTData)){
throw new TypeError("First parameter must be an NBTData object");
export async function write(data: CompoundTag | NBTData, { name, endian, compression, bedrockLevel }: WriteOptions = {}){
if (data instanceof NBTData){
if (name === undefined) name = data.name;
if (endian === undefined) endian = data.endian;
if (compression === undefined) compression = data.compression;
if (bedrockLevel === undefined) bedrockLevel = data.bedrockLevel;
data = data.data;
}

if (typeof data !== "object" || data === null){
throw new TypeError("First parameter must be an object");
}
if (typeof name !== "string" && name !== null){
throw new TypeError("Name option must be a string or null");
Expand Down Expand Up @@ -72,9 +80,15 @@ export class NBTWriter {
/**
* Initiates the writer over an NBTData object.
*/
write(data: NBTData, { name = data.name, endian = data.endian }: NBTWriterOptions = {}) {
if (!(data instanceof NBTData)){
throw new TypeError("First parameter must be an NBTData object");
write(data: CompoundTag | NBTData, { name, endian }: NBTWriterOptions = {}) {
if (data instanceof NBTData){
if (name === undefined) name = data.name;
if (endian === undefined) endian = data.endian;
data = data.data;
}

if (typeof data !== "object" || data === null){
throw new TypeError("First parameter must be an object");
}
if (typeof name !== "string" && name !== null){
throw new TypeError("Name option must be a string or null");
Expand All @@ -88,11 +102,9 @@ export class NBTWriter {
this.#data = new Uint8Array(1024);
this.#view = new DataView(this.#data.buffer);

const { data: value } = data;

this.#writeTagType(TAG.COMPOUND);
if (name !== null) this.#writeString(name);
this.#writeCompound(value);
this.#writeCompound(data);

this.#accommodate(0);
return this.#data.slice(0,this.#byteOffset);
Expand Down
29 changes: 19 additions & 10 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
// @ts-check

import * as fs from "node:fs/promises";
import { Buffer } from "node:buffer";
import * as NBT from "../dist/index.js";

const data = await fs.readFile(new URL("./nbt/level.dat",import.meta.url));
console.log(data,"\n");
/** @type { NBT.CompoundTag } */
const value = {
IsFancy: new NBT.Byte(0),
Noice: new Int8Array([55,32,4,125,8,99,57,4])
};
console.log(value,"\n");

const result = await NBT.read(data);
/** @type { NBT.WriteOptions } */
const options = { name: null, endian: "little" };
console.log(options,"\n");

const data = new NBT.NBTData(value,options);
// console.log(data,"\n");

const writer = new NBT.NBTWriter();

const result = Buffer.from(writer.write(data));
console.log(result,"\n");

const result2 = await NBT.write(result,{ bedrockLevel: null })
.then(buffer => NBT.read(buffer.slice(0,-1),{ endian: "little" }));
const result2 = Buffer.from(await NBT.write(value,options));
console.log(result2,"\n");

const recompile = Buffer.from(await NBT.write(result2));
console.log(recompile,"\n");

console.log(Buffer.compare(data,recompile));
console.log(Buffer.compare(result,result2));

0 comments on commit 00425ac

Please sign in to comment.