Podshot / MCEdit-Unified

Combined MCEdit & Pymclevel repository.
http://podshot.github.io/MCEdit-Unified/
ISC License
485 stars 109 forks source link

Editing chunk data in PE #827

Closed neonerz closed 7 years ago

neonerz commented 7 years ago

I'm trying to edit chunk data from within a filter. Specifically trying to set a chunk's biome.

Looking through levelDB with a level editor (Universal Minecraft Editor) I figured out that the last 256 bytes of Level -> Data2D inside a chunk contains the biome info. I was able to manually edit that data and confirm the biome changed in-game.

Obviously I can't access it like I would for a Java map since it's not NBT data.

chunk = level.getChunk(x,z)
chunk.root_tag["Level"]["Biomes"])

I assume I have to use pymclevel, probably leveldb.py but I just can't figure it out.

Can someone point me in the right direction?

gentlegiantJGC commented 7 years ago

just looking into the pocket support now myself. It looks like pymclevel/leveldbpocket.py is what interfaces with the level using pymclevel/leveldb.py so that is probably the first place to start looking.

PocketLeveldbDatabase._readSubChunk_1plus is where the chunk data is actuall read so my guess is either a method would need to implemented in there to give access to that data or something like it would need to implemented in parrallel in a filter.

I believe in the PC version all the NBT is read in one go as a dictionary which is why you can edit any part of it as you please. In bedrock edition each part is stored in its own key using leveldb and has to be extracted individually

TLDR: I don't think MCedit actually reads that data currently but you could possibly implement the code needed in a filter.

LaChal commented 7 years ago

Downloaded this prog on my side, and it confirms tests I made in MCEdit. The Data2D can't be considered as NBT data at all...

@neonerz What did you do to change the biome type?

gentlegiantJGC commented 7 years ago

isn't it a byte array like block ids and data values? (I haven't checked this)

I was meerly implying it could be read and fed into MCedit so you can interface with it in the same way as you would for PC

LaChal commented 7 years ago

Looks like a byte array, indeed Actually Data2D is 768 bytes long.

Since it's not usable as NBT compound data, we can't know which byte does what :/ The fact is to test access to Data2D in MCEdit, I've changed the code (on my side only) using Mojang's documentation. But I can't find what is contained exactly in the Data2D tag...

PE worlds have a root NBT tag, but no 'Biomes' key here.

gentlegiantJGC commented 7 years ago

First 512 bytes are a heightmap?

https://minecraft.gamepedia.com/User:Jocopa3/Pocket_Level_Format_Test#Data2D

LaChal commented 7 years ago

Ah! Exactly what I was looking for (and search engines did not showed up).

Thanks :smile:

LaChal commented 7 years ago

I finally could change biome type for PE 1+ world in MCEdit.

A push will come once the code cleaned.

neonerz commented 7 years ago

I'm still getting the same error when trying to set the biome.

Exception TypeError: TypeError('No array-type handler for type numpy.type (value: 6) registered',) in <bound method Texture.__del__ of <glutils.Texture object at 0x00000000145D65C0>> ignored
Exception TypeError: TypeError('No array-type handler for type numpy.type (value: 7) registered',) in <bound method Texture.__del__ of <glutils.Texture object at 0x00000000145D6E48>> ignored
Traceback (most recent call last):
  File "C:\Users\gbove\Desktop\mcedit\MCEdit-Unified\editortools\filter.py", line 62, in _func
    func(*args, **kw)
  File "C:\Users\gbove\Desktop\mcedit\MCEdit-Unified\editortools\filter.py", line 891, in confirm
    self.filterOptionsPanel.confirm(self.tool)
  File "C:\Users\gbove\Desktop\mcedit\MCEdit-Unified\editortools\filter.py", line 553, in confirm
    tool.editor.addOperation(op)
  File "C:\Users\gbove\Desktop\mcedit\MCEdit-Unified\leveleditor.py", line 3013, in addOperation
    self.performWithRetry(op)
  File "C:\Users\gbove\Desktop\mcedit\MCEdit-Unified\leveleditor.py", line 3024, in performWithRetry
    op.perform(self.recordUndo)
  File "C:\Users\gbove\Desktop\mcedit\MCEdit-Unified\editortools\filter.py", line 917, in perform
    self.filter.perform(self.level, BoundingBox(self.box), self.options)
  File "C:\Users\gbove\Documents\MCEdit\Filters\setbiome.py", line 160, in perform
    array = chunk.root_tag["Level"]["Biomes"].value
TypeError: 'NoneType' object has no attribute '__getitem__'
gentlegiantJGC commented 7 years ago

LaChal also updated the setbiome filter in his commit which should show how to edit the PE version

https://github.com/Khroki/MCEdit-Unified/commit/6bae3e956d68b97992cfcd76ced05be7a0d4fb94#diff-246cc14462066884ee43f786c2d8874f

LaChal commented 7 years ago

Right. For PE worlds, there's no root_tag['Level']['Biomes'] object for the chunk or level ones.

Just use chunk.Biomes one :smile:

(Thanks to @gentlegiantJGC to point the commit, because something is (really) wrong there. I did not see this despite my tests and code review before pushing :/)

LaChal commented 7 years ago

@neonerz Do you still have the problem?

neonerz commented 7 years ago

Yea, I seen that second commit you made to setbiome.py, but I'm still getting the same error as before.

LaChal commented 7 years ago

Hmmm...

Remove the filter you have in Documents\MCEdit\Filters. Actually, you can remove form this folder all filters which are also in the stock-filters directory of MCEdit, except the ones you modified.

neonerz commented 7 years ago

Yup, that did the trick. I'm not sure why I didn't think of that. You could close this up.

LaChal commented 7 years ago

No problem :smile: