Carpet

Carpet

2M Downloads

[Scarpet bug?] Can't insert maps into a list in NBT data directly

altrisi opened this issue ยท 8 comments

commented

So I've been messing around with Scarpet and, since NBT maps can't be directly passed into a for loop, I decided to convert one to a list, since it was only a numerical ID. While doing that, I've discovered that you can't do that directly, but instead you have to decode it into a Scarpet list and then encode it again into NBT. I thought the following would work directly:

a = nbt('[{A:1}]');
put(a,null,{['test',1],['not','working']},'insert');
a

But instead it only returns the initial list ([{A:1}]). However, doing it with a 'regular' Scarpet list (or by parsing the NBT) works, but then you have to encode it back later:

initial = nbt('[{A:1}]');
a = parse_nbt(initial);
put(a,null,{['test',1],['it\'s','working']},'insert');
final = encode_nbt(a)

Returns [{A:1},{['test',1],['it's','working']}].

Tested in 1.16.1 with carpet/scarpet 1.4 (can't get 1.4.1 to start).

commented

That secind has errors because you put the accents jn tne wrong plsces. Youre meanto do a = nbt({'List':[{a:"b",b:"c"}]});

commented

Also, trying read elements of an NBT list inside an NBT field will return null, with something like:

a = nbt('{List:[{a:"b",b:"c"}]}');
a:'List':1

Same with the get() function.
Again it works if you parse_nbt the list element (a:'List').
The problem here seems to be that it's considering the list as a String, since length(a:'List') returns exactly 15 in this case.
Edit: And type(a:'List') returns string.

commented

First: It's correct. You are meant to encase the full NBT string inside of simple quotes since you are passing a string to the nbt() function.
Second: Even if it was that (that is not, just pasted in /script run and it can't evaluate because of that) what I've written here is just a simple example, not actual used code. This happens with "autogenerated" (made by nesting a new object into an empty NBT tag) NBT objects in Scarpet too.

commented

well, it seems like my attempts to make nbts more mutable made the less mutable in 1.4. Definitely broken, needs fixin asap

commented

well, going back to the original question, 'insert' is not a supported option for NBT's put. Addressing and access of containers of different types (lists, maps and nbts) never gonna be the same due to supported operations and different access to them.

Besides - I don't even know if access to tags different than compound in the top level is actually supported by the mc engine.

So this works, by boxing your tag in a compound tag that can be addressed:

/script run a = nbt('{lst:[{a:1}]}'); put(a,'lst',nbt('{b:2}'),-1); put(a,'lst',nbt('{c:3}'),-1); a
commented

but that will show up in 1.3.32 and below and 1.4.2, since I messed up nbt serialization a little in recent versions.

commented

Thanks, that's working in the last commit built for 20w28a in the 1.16 branch.
But still (maybe it's just me not knowing how) I can't get the elements in the list by just accessing them with the : access operator or the get() function (see #364 (comment)).
It's still considering the list as a string when reading it via a:'lst' so looking for :1, :0 (or any address, via a:'lst':address) returns null (tested type(a:'lst'), and it returns it is a string. length(a:'lst') also returns the length of the list as if it was a string instead of the number of elements).

commented

you have to address nbts with nbt paths - these are not normal lists, it doesn't work this way. In normal world its json and json_path