snbt-js 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/snbt.d.ts +1 -1
- package/src/snbt.js +19 -5
- package/test/boolean-tests.js +81 -0
- package/test/path-access-tests.js +176 -0
package/package.json
CHANGED
package/src/snbt.d.ts
CHANGED
package/src/snbt.js
CHANGED
|
@@ -43,7 +43,11 @@ export class NbtObject {
|
|
|
43
43
|
if (args.length == 1) {
|
|
44
44
|
return this.childs[args[0]];
|
|
45
45
|
} else if (args.length > 1) {
|
|
46
|
-
|
|
46
|
+
var child = this.childs[args[0]];
|
|
47
|
+
if (child === undefined) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return child.get(args.slice(1));
|
|
47
51
|
} else {
|
|
48
52
|
return this;
|
|
49
53
|
};
|
|
@@ -55,7 +59,10 @@ export class NbtObject {
|
|
|
55
59
|
if (index.length == 1) {
|
|
56
60
|
this.childs[index[0]] = value;
|
|
57
61
|
} else if (index.length > 1) {
|
|
58
|
-
this.get(index.slice(0, -1))
|
|
62
|
+
var parent = this.get(index.slice(0, -1));
|
|
63
|
+
if (parent !== undefined) {
|
|
64
|
+
parent.set(index.slice(-1), value);
|
|
65
|
+
}
|
|
59
66
|
};
|
|
60
67
|
};
|
|
61
68
|
};
|
|
@@ -94,7 +101,11 @@ export class NbtList {
|
|
|
94
101
|
if (args.length == 1) {
|
|
95
102
|
return this.childs[args[0]];
|
|
96
103
|
} else if (args.length > 1) {
|
|
97
|
-
|
|
104
|
+
var child = this.childs[args[0]];
|
|
105
|
+
if (child === undefined) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return child.get(args.slice(1));
|
|
98
109
|
} else {
|
|
99
110
|
return this;
|
|
100
111
|
};
|
|
@@ -106,7 +117,10 @@ export class NbtList {
|
|
|
106
117
|
if (index.length == 1) {
|
|
107
118
|
this.childs[index[0]] = value;
|
|
108
119
|
} else if (index.length > 1) {
|
|
109
|
-
this.get(index.slice(0, -1))
|
|
120
|
+
var parent = this.get(index.slice(0, -1));
|
|
121
|
+
if (parent !== undefined) {
|
|
122
|
+
parent.set(index.slice(-1), value);
|
|
123
|
+
}
|
|
110
124
|
};
|
|
111
125
|
};
|
|
112
126
|
};
|
|
@@ -251,7 +265,7 @@ export class NbtString {
|
|
|
251
265
|
|
|
252
266
|
export class NbtBool {
|
|
253
267
|
constructor(value) {
|
|
254
|
-
this.value = value
|
|
268
|
+
this.value = !!value;
|
|
255
269
|
this.text = function (ispretty) {
|
|
256
270
|
if (ispretty) {
|
|
257
271
|
return highlightCode(`${this.value}`, "bool")
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { parseNbtString, NbtBool, NbtObject } from '../src/snbt.js';
|
|
3
|
+
|
|
4
|
+
describe('NbtBool Tests', () => {
|
|
5
|
+
it('should store boolean value as boolean, not string', () => {
|
|
6
|
+
const boolTrue = new NbtBool(true);
|
|
7
|
+
const boolFalse = new NbtBool(false);
|
|
8
|
+
|
|
9
|
+
expect(boolTrue.value).to.be.a('boolean');
|
|
10
|
+
expect(boolTrue.value).to.equal(true);
|
|
11
|
+
|
|
12
|
+
expect(boolFalse.value).to.be.a('boolean');
|
|
13
|
+
expect(boolFalse.value).to.equal(false);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should parse true boolean from SNBT', () => {
|
|
17
|
+
const result = parseNbtString('{ flag: true }');
|
|
18
|
+
const flag = result.get('flag');
|
|
19
|
+
|
|
20
|
+
expect(flag).to.be.instanceOf(NbtBool);
|
|
21
|
+
expect(flag.value).to.be.a('boolean');
|
|
22
|
+
expect(flag.value).to.equal(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should parse false boolean from SNBT', () => {
|
|
26
|
+
const result = parseNbtString('{ flag: false }');
|
|
27
|
+
const flag = result.get('flag');
|
|
28
|
+
|
|
29
|
+
expect(flag).to.be.instanceOf(NbtBool);
|
|
30
|
+
expect(flag.value).to.be.a('boolean');
|
|
31
|
+
expect(flag.value).to.equal(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should convert truthy values to true', () => {
|
|
35
|
+
const bool1 = new NbtBool(1);
|
|
36
|
+
const bool2 = new NbtBool("yes");
|
|
37
|
+
const bool3 = new NbtBool({});
|
|
38
|
+
|
|
39
|
+
expect(bool1.value).to.equal(true);
|
|
40
|
+
expect(bool2.value).to.equal(true);
|
|
41
|
+
expect(bool3.value).to.equal(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should convert falsy values to false', () => {
|
|
45
|
+
const bool1 = new NbtBool(0);
|
|
46
|
+
const bool2 = new NbtBool("");
|
|
47
|
+
const bool3 = new NbtBool(null);
|
|
48
|
+
const bool4 = new NbtBool(undefined);
|
|
49
|
+
|
|
50
|
+
expect(bool1.value).to.equal(false);
|
|
51
|
+
expect(bool2.value).to.equal(false);
|
|
52
|
+
expect(bool3.value).to.equal(false);
|
|
53
|
+
expect(bool4.value).to.equal(false);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should output boolean as string in text() method', () => {
|
|
57
|
+
const boolTrue = new NbtBool(true);
|
|
58
|
+
const boolFalse = new NbtBool(false);
|
|
59
|
+
|
|
60
|
+
expect(boolTrue.text()).to.equal('true');
|
|
61
|
+
expect(boolFalse.text()).to.equal('false');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should handle boolean in nested objects', () => {
|
|
65
|
+
const result = parseNbtString(`{
|
|
66
|
+
player: {
|
|
67
|
+
isAlive: true,
|
|
68
|
+
isFlying: false
|
|
69
|
+
}
|
|
70
|
+
}`);
|
|
71
|
+
|
|
72
|
+
const isAlive = result.get('player.isAlive');
|
|
73
|
+
const isFlying = result.get('player.isFlying');
|
|
74
|
+
|
|
75
|
+
expect(isAlive.value).to.be.a('boolean');
|
|
76
|
+
expect(isAlive.value).to.equal(true);
|
|
77
|
+
|
|
78
|
+
expect(isFlying.value).to.be.a('boolean');
|
|
79
|
+
expect(isFlying.value).to.equal(false);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { parseNbtString, NbtObject, NbtList, NbtString, NbtNumber } from '../src/snbt.js';
|
|
3
|
+
|
|
4
|
+
describe('Path Access Tests', () => {
|
|
5
|
+
describe('NbtObject.get() with non-existent paths', () => {
|
|
6
|
+
it('should return undefined when accessing non-existent key', () => {
|
|
7
|
+
const nbt = new NbtObject({
|
|
8
|
+
'minecraft:enchantments': new NbtObject()
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const result = nbt.get(['minecraft:enchantments', 'levels']);
|
|
12
|
+
expect(result).to.be.undefined;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return undefined when accessing nested non-existent path', () => {
|
|
16
|
+
const nbt = parseNbtString(`{
|
|
17
|
+
player: {
|
|
18
|
+
name: "Steve"
|
|
19
|
+
}
|
|
20
|
+
}`);
|
|
21
|
+
|
|
22
|
+
const result = nbt.get(['player', 'inventory', 0]);
|
|
23
|
+
expect(result).to.be.undefined;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should return undefined when accessing non-existent top-level key', () => {
|
|
27
|
+
const nbt = new NbtObject({
|
|
28
|
+
name: new NbtString('Steve')
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const result = nbt.get('age');
|
|
32
|
+
expect(result).to.be.undefined;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return undefined when using dot notation on non-existent path', () => {
|
|
36
|
+
const nbt = parseNbtString(`{ player: { name: "Steve" } }`);
|
|
37
|
+
|
|
38
|
+
const result = nbt.get('player.health');
|
|
39
|
+
expect(result).to.be.undefined;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should return undefined when accessing deeply nested non-existent path', () => {
|
|
43
|
+
const nbt = parseNbtString(`{
|
|
44
|
+
level1: {
|
|
45
|
+
level2: {
|
|
46
|
+
level3: "value"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}`);
|
|
50
|
+
|
|
51
|
+
const result = nbt.get(['level1', 'level2', 'level4', 'level5']);
|
|
52
|
+
expect(result).to.be.undefined;
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('NbtList.get() with non-existent paths', () => {
|
|
57
|
+
it('should return undefined when accessing non-existent index in nested list', () => {
|
|
58
|
+
const nbt = parseNbtString(`{
|
|
59
|
+
items: [
|
|
60
|
+
{ id: "diamond" }
|
|
61
|
+
]
|
|
62
|
+
}`);
|
|
63
|
+
|
|
64
|
+
const result = nbt.get(['items', 5, 'id']);
|
|
65
|
+
expect(result).to.be.undefined;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return undefined when accessing property on undefined array element', () => {
|
|
69
|
+
const nbt = new NbtObject({
|
|
70
|
+
inventory: new NbtList([
|
|
71
|
+
new NbtObject({ id: new NbtString('sword') })
|
|
72
|
+
])
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const result = nbt.get(['inventory', 10, 'id']);
|
|
76
|
+
expect(result).to.be.undefined;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should return undefined when list element exists but nested path does not', () => {
|
|
80
|
+
const nbt = parseNbtString(`{
|
|
81
|
+
items: [
|
|
82
|
+
{ name: "item1" },
|
|
83
|
+
{ name: "item2" }
|
|
84
|
+
]
|
|
85
|
+
}`);
|
|
86
|
+
|
|
87
|
+
const result = nbt.get(['items', 0, 'count']);
|
|
88
|
+
expect(result).to.be.undefined;
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('NbtObject.set() with non-existent paths', () => {
|
|
93
|
+
it('should not throw error when setting on non-existent intermediate path', () => {
|
|
94
|
+
const nbt = new NbtObject({
|
|
95
|
+
player: new NbtObject()
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// This should not throw an error, but also should not set the value
|
|
99
|
+
// since 'inventory' doesn't exist on the player object (parent is undefined)
|
|
100
|
+
expect(() => {
|
|
101
|
+
nbt.set(['player', 'inventory', 'count'], new NbtNumber(5));
|
|
102
|
+
}).to.not.throw();
|
|
103
|
+
|
|
104
|
+
// Verify the value was not set (because 'inventory' doesn't exist)
|
|
105
|
+
const result = nbt.get(['player', 'inventory', 'count']);
|
|
106
|
+
expect(result).to.be.undefined;
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should handle setting on deeply nested non-existent path gracefully', () => {
|
|
110
|
+
const nbt = parseNbtString(`{ level1: { level2: {} } }`);
|
|
111
|
+
|
|
112
|
+
expect(() => {
|
|
113
|
+
nbt.set(['level1', 'level2', 'level3', 'value'], new NbtString('test'));
|
|
114
|
+
}).to.not.throw();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('NbtList.set() with non-existent paths', () => {
|
|
119
|
+
it('should not throw error when setting on non-existent array index path', () => {
|
|
120
|
+
const nbt = new NbtObject({
|
|
121
|
+
items: new NbtList([
|
|
122
|
+
new NbtObject({ id: new NbtString('item1') })
|
|
123
|
+
])
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(() => {
|
|
127
|
+
nbt.set(['items', 5, 'id'], new NbtString('item2'));
|
|
128
|
+
}).to.not.throw();
|
|
129
|
+
|
|
130
|
+
// The value at index 5 should still be undefined
|
|
131
|
+
const result = nbt.get(['items', 5]);
|
|
132
|
+
expect(result).to.be.undefined;
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe('Valid path access should still work', () => {
|
|
137
|
+
it('should correctly access existing nested paths', () => {
|
|
138
|
+
const nbt = parseNbtString(`{
|
|
139
|
+
"minecraft:enchantments": {
|
|
140
|
+
levels: {
|
|
141
|
+
sharpness: 5
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}`);
|
|
145
|
+
|
|
146
|
+
const result = nbt.get(['minecraft:enchantments', 'levels', 'sharpness']);
|
|
147
|
+
expect(result).to.not.be.undefined;
|
|
148
|
+
expect(result.value).to.equal(5);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should correctly access array elements', () => {
|
|
152
|
+
const nbt = parseNbtString(`{
|
|
153
|
+
items: [
|
|
154
|
+
{ id: "diamond", count: 5 },
|
|
155
|
+
{ id: "gold", count: 10 }
|
|
156
|
+
]
|
|
157
|
+
}`);
|
|
158
|
+
|
|
159
|
+
const result = nbt.get(['items', 1, 'id']);
|
|
160
|
+
expect(result).to.not.be.undefined;
|
|
161
|
+
expect(result.value).to.equal('gold');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should correctly set values on existing paths', () => {
|
|
165
|
+
const nbt = new NbtObject({
|
|
166
|
+
player: new NbtObject({
|
|
167
|
+
health: new NbtNumber(20)
|
|
168
|
+
})
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
nbt.set(['player', 'health'], new NbtNumber(15));
|
|
172
|
+
const result = nbt.get(['player', 'health']);
|
|
173
|
+
expect(result.value).to.equal(15);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
});
|