Skip to content

Commit

Permalink
Add chunk unpacker
Browse files Browse the repository at this point in the history
  • Loading branch information
DonoA committed Aug 5, 2018
1 parent 0229c71 commit 69ec49b
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 12 deletions.
20 changes: 8 additions & 12 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import nbt, gzip, zlib, stream, sys
import nbt, gzip, zlib, stream, sys, world

WORLD_FOLDER = "world/"

# with gzip.open(WORLD_FOLDER + "playerdata/47ed23f7-4b2c-4844-82ff-a53220533359.dat", mode="rb") as plr:
# strm = Stream(plr.read())

# data = nbt.parse_nbt(strm)
# data.print()
WORLD_FOLDER = "newWorld/"

# with gzip.open(WORLD_FOLDER + "level.dat", mode="rb") as level:
# strm = stream.Stream(level.read())
Expand Down Expand Up @@ -35,7 +29,9 @@
wrk.write(decompressed)
data = nbt.parse_nbt(stream.Stream(decompressed))
# data.print()

# with open("workrgn.nbt", mode="rb") as workfile:
# data = nbt.parse_nbt(workfile)
# data.print()
chunk = world.Chunk(
data.get("Level").get("xPos").get(),
data.get("Level").get("zPos").get(),
world.Chunk.unpack(data)
)
sys.exit(0)
21 changes: 21 additions & 0 deletions nbt.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ def __init__(self, tag_type, tag_name, tag_value):
def print(self, indent=""):
print(indent + self.tag_type + ": '" + self.tag_name + "' = " + str(self.tag_value))

def get(self):
return self.tag_value

def name(self):
return self.tag_name

class MultiNBTTag:
def __init__(self, tag_type, tag_name):
self.tag_type = tag_type
Expand All @@ -95,6 +101,9 @@ def __init__(self, tag_type, tag_name):

def addChild(self, tag):
self.children.append(tag)

def name(self):
return self.tag_name

def print(self, indent=""):
print(indent + self.tag_type + ": '" + self.tag_name + "' size " + str(len(self.children)))
Expand All @@ -113,6 +122,18 @@ def addChild(self, tag):
def get(self, name):
return self.children[name]

def name(self):
return self.tag_name

def has(self, name):
return name in self.children

def toDict(self):
nd = {}
for p in self.children:
nd[p] = self.children[p].get()
return nd

def print(self, indent=""):
print(indent + self.tag_type + ": '" + self.tag_name + "' size " + str(len(self.children)))
for c in self.children:
Expand Down
62 changes: 62 additions & 0 deletions world.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import sys

class Block:
def __init__(self, name, props):
self.name = name
self.props = props

class Chunk:

def __init__(self, blocks):
self.blocks = {}
for section in blocks:
self.blocks[section] = [[[0 for z in range(16)] for y in range(16)] for x in range(16)]
for y in range(16):
for z in range(16):
for x in range(16):
self.blocks[section][x][y][z] = blocks[section][x + z * 16 + y * 16 ** 2]


# Blockstates are packed based on the number of values in the pallet.
# This selects the pack size, then splits out the ids
def unpack(raw_nbt):
blocks = {}
for section in [raw_nbt.get("Level").get("Sections").children[3]]:
flatstates = [c.get() for c in section.get("BlockStates").children]
pack_size = int((len(flatstates) * 64) / (16**3))
states = [
Chunk._read_width_from_loc(flatstates, pack_size, i) for i in range(16**3)
]
print(pack_size)
states = [
section.get("Palette").children[i] for i in states
]
blocks[section.get("Y").get()] = [
Block(state.get("Name").get(), state.get("Properties").toDict() if state.has("Properties") else {}) for state in states
]

return blocks

def _read_width_from_loc(long_list, width, possition):
offset = possition * width
# refrence the space we want to select from to make things a little easier
search_space = long_list[int(offset/64)]
spc = 64
if int(offset/64) != int((offset + width)/64) and int((offset + width)/64) < len(long_list):
# love ya python!
search_space = (search_space << 64) + long_list[int((offset + width)/64)]
spc = 128

# create a mask of size 'width' of 1 bits
mask = (2 ** width) - 1
# shift it out to where we need for the mask
mask = mask << (offset % 64)
# select the bits we need
comp = search_space & mask
# move them back to where they should be
comp = comp >> (offset % 64)

print(format(search_space, '#0' + str(spc) + 'b'))
print(format(mask, '#0' + str(spc) + 'b'))

return comp

0 comments on commit 69ec49b

Please sign in to comment.