twoolie / NBT

Python Parser/Writer for the NBT file format, and it's container the RegionFile.
MIT License
362 stars 74 forks source link

Can't save Arrays #134

Open JakobDev opened 4 years ago

JakobDev commented 4 years ago

I'm unable to save arrays:

import nbt
f = nbt.nbt.NBTFile()
f.tags.append(nbt.nbt.TAG_Int_Array([1,2,3]))
f.write_file("test.dat")

This gives me this error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.5/dist-packages/nbt/nbt.py", line 693, in write_file
    self._render_buffer(self.file)
  File "/usr/local/lib/python3.5/dist-packages/nbt/nbt.py", line 498, in _render_buffer
    TAG_String(tag.name)._render_buffer(buffer)
  File "/usr/local/lib/python3.5/dist-packages/nbt/nbt.py", line 356, in _render_buffer
    save_val = self.value.encode("utf-8")
AttributeError: 'list' object has no attribute 'encode'

Same with Byte Array.

jlsajfj commented 3 years ago

Please format your declaration of the TAG_Int_Array like Tag_Int_Array(name='nameoftag',[1,2,3]).

Your current code sets the array [1,2,3] as the name of the tag.

Dob-The-Duilder commented 1 year ago

I'm getting the error AttributeError: 'list' object has no attribute 'read' with pretty much the same code as the one above.

data = TAG_Compound(name="data")
data.tags.append(TAG_Int_Array('colors', [1,2,3]))
mapFile.tags.append(data)
Traceback (most recent call last):
  File "C:\Users\USER\Desktop\minecraft-map-to-image\reverse\mapGen.py", line 104, in <module>
    generate_map([1,2])
  File "C:\Users\USER\Desktop\minecraft-map-to-image\reverse\mapGen.py", line 87, in generate_map
    data.tags.append(TAG_Int_Array('colors', [1,2,3]))
  File "C:\Users\USER\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\nbt\nbt.py", line 245, in __init__
    self._parse_buffer(buffer)
  File "C:\Users\USER\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\nbt\nbt.py", line 253, in _parse_buffer
    length = TAG_Int(buffer=buffer).value
  File "C:\Users\USER\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\nbt\nbt.py", line 109, in __init__
    self._parse_buffer(buffer)
  File "C:\Users\USER\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\nbt\nbt.py", line 115, in _parse_buffer
    self.value = self.fmt.unpack(buffer.read(self.fmt.size))[0]
AttributeError: 'list' object has no attribute 'read'
NebulaBC commented 1 year ago

I hate to say this took me far too long to figure out, because TAG_Int_Array/TAG_Byte_Array is poorly (wrongly) documented. You must use a BytesIO object. Here's an example of how to use it:

nbtfile = nbt.nbt.NBTFile()
byte_array = nbt.nbt.TAG_Byte_Array(name="name", buffer=BytesIO(b"1 2 3 4"))
nbtfile.tags.append(byte_array)

I very much hope this helps someone else avoid spending as much time as I did getting this to work.

(I might also suggest you check out Amulet-NBT, it's more up to date and is a more straightforward library. I switched to it after this library was randomly removing four bytes from my array with no explanation)