def main():

	# Read map files to sort by scale
	print("Reading map files...")
	mapfiles = []
	for i in range(0,5):
		mapfiles.append([])
	i = 0
	while os.path.isfile(inputDir + "map_" + str(i) + ".dat"):
		# read file
		nbt = NBTFile(inputDir + "map_" + str(i) + ".dat")
		data = nbt["data"]
		if int(data["dimension"].value) == 0:
			scale = data["scale"].value
			print("  Map " + str(i))
			mapfiles[scale].append(i)
		nbt = None
		i = i + 1

	# Process map files in order of scaling, and build image
	print("Processing map files into image...")
	imgwidth = xmax - xmin
	imgheight = zmax - zmin
	img = Image.new('RGBA', (imgwidth, imgheight))
	colormap = getcolormap()
	for s in reversed(range(0,5)):
		for i in mapfiles[s]:

			# get map info
			nbt = NBTFile(inputDir + "map_" + str(i) + ".dat")
			data = nbt["data"]
			scale = 2 ** int(data["scale"].value)
			cx = data["xCenter"].value - (64 * scale)
			cz = data["zCenter"].value - (64 * scale)
			print("  Map " + str(i) + ": Scale = " + str(scale) + ":1, Corner=" + str(cx) + "," + str(cz))

			# get colors
			for mx in range(0,128):
				for mz in range(0,128):
					# color at map pixel
					colorindex = data["colors"][mx + mz * 128]
					if colorindex < 4: # unexplored
						continue
					color = colormap[colorindex]
					# iterate over actual world blocks
					for px in range(0,scale):
						for pz in range(0,scale):
							coords = (cx + (mx * scale) + px, cz + (mz * scale) + pz)
							imgx = coords[0] - xmin
							imgy = coords[1] - zmin
							if imgx >= 0 and imgx < imgwidth and imgy >= 0 and imgy < imgheight:
								img.putpixel((imgx,imgy), color)

			# clean up
			nbt = None
			data = None

	print("Saving image...")
	img.save(outputFile)
	print("Done!")
Example #2
0
def get_last_played_level():
    mc_dir = SETTINGS.value("MinecraftDirectory",
                            utils.get_default_minecraft_dir())
    mc_saves = os.path.join(mc_dir, "saves")

    worlds_recently_modified = sorted(
        [os.path.join(mc_saves, s) for s in os.listdir(mc_saves)],
        key=os.path.getmtime,
        reverse=True)
    for world in worlds_recently_modified:
        try:
            level = NBTFile(os.path.join(world, "level.dat"))
            with open(
                    os.path.join(
                        world, "advancements",
                        os.listdir(os.path.join(world,
                                                "advancements"))[0])) as f:
                advancements = dict(json.load(f))
            break
        except:
            continue

    data = {
        "name": str(level["Data"]["LevelName"]),
        "version": str(level["Data"]["Version"]["Name"]),
        "dataversion": int(str(level["Data"]["DataVersion"])),
        "adv": advancements
    }

    return data
Example #3
0
def generate_level(bytesize=4):
    """Generate a level, which is a given size in bytes."""
    level = NBTFile()  # Blank NBT

    def append_byte_array(name, bytesize=1000):
        bytesize -= len(name)
        bytesize -= 7
        # byte_array = TAG_Byte_Array(name=name, value=bytearray([random.randrange(256) for i in range(bytesize)]))
        # level.append(byte_array)
        byte_array = TAG_Byte_Array(name=name)
        byte_array.value = bytearray(
            [random.randrange(256) for i in range(bytesize)])
        level.tags.append(byte_array)

    random.seed(123456789)  # fixed seed to give predictable results.
    if bytesize < 13:
        raise ValueError("NBT file size is at least 13 bytes")
    # 4 bytes TAG_Compound overhead, 13 bytes TAG_Byte_Array overhead.
    bytesize -= 4  # deduce overhead bytes
    i = 1
    while bytesize > 1500:
        append_byte_array("%06d" % i, 1000)
        i += 1
        bytesize -= 1000
    append_byte_array("last", bytesize)
    return level
Example #4
0
def generate_level():
    level = NBTFile()  # Blank NBT
    level.name = "Data"
    level.tags.extend([
        TAG_Long(name="Time", value=1),
        TAG_Long(name="LastPlayed", value=int(time.time())),
        TAG_Int(name="SpawnX", value=0),
        TAG_Int(name="SpawnY", value=2),
        TAG_Int(name="SpawnZ", value=0),
        TAG_Long(name="SizeOnDisk", value=0),
        TAG_Long(name="RandomSeed", value=random.randrange(1, 9999999999)),
        TAG_Int(name="version", value=19132),
        Tag_String(name="LevelName", value="Testing")
    ])

    player = Tag_Compound()
    player.name = "Player"
    player.tags.extend(
        [TAG_Int(name="Score", value=0),
         TAG_Int(name="Dimension", value=0)])
    inventory = Tag_Compound()
    inventory.name = "Inventory"
    player.tags.append(inventory)
    level.tags.append(player)

    return level
Example #5
0
def getnbt(filename):
    nbtdata = NBTFile(filename)
    unpackedData = unpack_nbt(nbtdata)
    #print(unpackedData)
    position = unpackedData["Pos"]
    dim = unpackedData["Dimension"]
    inv = unpackedData["Inventory"]
    ender = unpackedData["EnderItems"]

    (x1, y1, z1) = tuple(position)
    x1 = int(x1)
    y1 = int(y1)
    z1 = int(z1)

    def makeLine(item, source):
        item = dict(item)
        keyFilter = ["Count", "Slot", "id"]
        newItem = OrderedDict()
        newItem.update({"Source": source})
        for key in sorted(item):
            if key in keyFilter:
                newItem.update({key: item[key]})
                if key == "tag":
                    if "display" in item["tag"]:
                        if "Name" in item["tag"]["display"]:
                            item.update(
                                {"Name": item["tag"]["display"]["Name"]})

        return json.dumps(newItem)

    invLines = [makeLine(a, "i") for a in inv]
    enderLines = [makeLine(a, "e") for a in ender]

    return (dim, x1, y1, z1, invLines, enderLines)
Example #6
0
    def scan(self):
        for file in listdir(self.args.world + '/playerdata/'):
            nbt = NBTFile(self.args.world + '/playerdata/' + file, 'rb')

            inv_items = nbt['Inventory']
            ec_items = nbt['EnderItems']

            if self.args.inventory and len(inv_items) != 0:
                for item in inv_items:
                    _item = Item(item['id'].value, item['Count'].value, item['Damage'].value)
                    if is_scan_item(self.args, _item) and _item.count >= self.args.count:
                        print('Found {0}*{1} in {2}\'s inventory !'.format(
                            _item.count,
                            _item.material,
                            file.replace('.dat', '')
                        ))

            if self.args.enderchest and len(ec_items) != 0:
                for item in ec_items:
                    _item = Item(item['id'].value, item['Count'].value, item['Damage'].value)
                    if is_scan_item(self.args, _item) and _item.count > self.args.count:
                        print('Found {0}*{1} in {2}\'s enderchest !'.format(
                            _item.count,
                            _item.material,
                            file.replace('.dat', '')
                        ))
Example #7
0
    def __init__(self, server, folder):
        self.server = server
        self.folder = folder

        if not os.path.exists(folder) or not os.path.isdir(folder):
            print('The world folder is missing!')
            return

        self.levelData = NBTFile(filename=os.path.join(self.folder, 'level.dat'), buffer='rb')
        self.seed = self.levelData['Data']['RandomSeed'].value
        self.spawn = [
            self.levelData['Data']['SpawnX'].value,
            self.levelData['Data']['SpawnY'].value,
            self.levelData['Data']['SpawnZ'].value
        ]

        self.chunks = {}

        self.test = False

        self.loadWorld()
        print 'Loaded %s chunks' % (len(self.chunks))

        self.clients = []

        self.time = 0

        reactor.callLater(1, self.sendTime)
Example #8
0
    def value(self):
        if self.type_ == list:
            tag = TAG_Compound(self.name)
            tag.tags = [x.value for x in self._value]
            return tag

        if self.type_ == NBTFile:
            x = NBTFile()
            x.name = self.name
            x.tags = [x.value for x in self._value]
            return x

        if self.type_ == TAG_Compound:
            tag = TAG_Compound(name=self.name)
            tag.tags = [x.value for x in self._value]
            tag.name = self.name
            return tag

        if self.type_ == TAG_Int_Array:
            tag = TAG_Int_Array(name=self.name)
            tag.value = self._value
            return tag

        if self.type_ == TAG_List:
            tag = TAG_List(type=self.extra, name=self.name)
            tag.tags = [x.value for x in self._value]
            tag.name = self.name
            return tag

        return self.type_(value=self._value, name=self.name)
Example #9
0
 def testProperlyClosed(self):
     """
     test that files opened from a file name are closed after 
     being written to. i.e. will read correctly in the future
     """
     #open the file
     mynbt = NBTFile(self.filename)
     mynbt['test'] = TAG_Int(123)
     mynbt.write_file()
     if hasattr(mynbt.file, "closed"):
         self.assertTrue(mynbt.file.closed)
     else:  # GZipFile does not yet have a closed attribute in Python 2.6
         self.assertTrue(mynbt.file.fileobj == None)
     # make sure it can be read again directly after closing,
     # and contains the updated contents.
     mynbt = NBTFile(self.filename)
     self.assertEqual(mynbt['test'].value, 123)
Example #10
0
def getKoords():
    level = NBTFile(LEVELDAT, 'rb')

    x = int(float(str(level["Data"]["Player"]["Pos"][0])))
    y = int(float(str(level["Data"]["Player"]["Pos"][1])))
    z = int(float(str(level["Data"]["Player"]["Pos"][2])))
    print(f"x={x} y={y} z={z}")
    return x, y, z
Example #11
0
def main(world_folder, show=True):
    scorefile = world_folder + '/data/scoreboard.dat'
    scores = NBTFile(scorefile, 'rb')

    for player in scores["data"]["PlayerScores"]:
        print(
            "%s: %d %s" %
            (player["Name"], player["Score"].value, player["Objective"].value))
Example #12
0
 def test01ReadChunk(self):
     """Test if a block can be read, even when the file is truncated right after the block data."""
     data = self.region.get_blockdata(
         0, 0)  # This may raise a RegionFileFormatError.
     data = BytesIO(data)
     nbt = NBTFile(buffer=data)
     self.assertEqual(nbt["Time"].value, 1)
     self.assertEqual(nbt["Name"].value, "Test")
Example #13
0
    def parseNBT(raw_data: Union[bytes, str]) -> NBTFile:
        r"""Parses NBT data from the API.

        :param raw_data: The raw encoded NBT data.
        :type raw_data: Union[bytes, str]

        :return: The decoded NBT data.
        :rtype: nbt.nbt.NBTFile"""

        data = NBTFile(fileobj=io.BytesIO(base64.b64decode(raw_data)))
        return data
Example #14
0
def get_last_played_level():
    mc_dir = SETTINGS.value("MinecraftDirectory", utils.get_default_minecraft_dir())
    mc_saves = os.path.join(mc_dir, "saves")

    worlds_recently_modified = sorted([os.path.join(mc_saves, s) for s in os.listdir(mc_saves)], key=os.path.getmtime, reverse=True)
    for w in worlds_recently_modified.copy()[:5]:
        try:
            world = w
            level = NBTFile(os.path.join(world, "level.dat"))
            if not int(str(level["Data"]["Time"])):
                continue
            else:
                break
        except:
            continue

    try:
        with open(os.path.join(world, "stats", os.listdir(os.path.join(world, "stats"))[0]), "r") as f:
            stats = json.load(f)
    except: #* If it's pre 1.7.2
        stats = None

    try:
        seen_credits = bool(int(str(level["Data"]["Player"]["seenCredits"])))
    except: #* If it's pre 1.12 OR a server
        seen_credits = None

    try:
        data = {
            "name": str(level["Data"]["LevelName"]),
            "version": str(level["Data"]["Version"]["Name"]),
            "igt": stats["stat.playOneMinute"] if int(str(level["Data"]["DataVersion"])) < 1451 else stats["stats"]["minecraft:custom"]["minecraft:play_one_minute"],
            "seen_credits": seen_credits,
            "pre17": False
        }
    except: #* If it's pre 1.9
        try:
            data = {
                "name": str(level["Data"]["LevelName"]),
                "version": "Pre 1.9",
                "igt": stats["stat.playOneMinute"],
                "seen_credits": seen_credits,
                "pre17": False
            }
        except: #* If it's pre 1.7.2
            data = {
                "name": str(level["Data"]["LevelName"]),
                "version": "Pre 1.7.2",
                "igt": utils.get_pre17_igt(mc_dir),
                "seen_credits": seen_credits,
                "pre17": True
            }

    return data
Example #15
0
    def testProperlyClosed(self):
        """
		test that files opened from a file name are closed after 
		being written to. i.e. will read correctly in the future
		"""
        # copy the file (don't work on the original test file)
        tempdir = tempfile.mkdtemp()
        filename = os.path.join(tempdir, 'bigtest.nbt')
        shutil.copy(NBTTESTFILE, filename)

        #open the file
        f = NBTFile(filename)
        f.write_file()
        # make sure it can be read again directly after
        f = NBTFile(filename)

        # remove the temporary file
        try:
            shutil.rmtree(tempdir)
        except OSError as e:
            raise
Example #16
0
    def handleChunkFile(self, root, name):
        location = os.path.join(root, name)
        root = root.replace(self.folder, '')[1:]

        dirs = root.split(os.sep)
        if len(dirs) != 2:
            return

        a, b = dirs

        chunkFile = name.split('.')
        if len(chunkFile) != 4:
            print("Invalid chunk file: %s" % location)
            return

        if chunkFile[0] != 'c' or chunkFile[3] != 'dat':
            print("Invalid chunk file: %s" % location)
            return

        x, z = chunkFile[1], chunkFile[2]
        x, z = int(x, 36), int(z, 36)
        
        print("Loaded %s %s" % (x, z))

        if a != base36(x & 63):
            print("Invalid chunk file: %s" % location)
            return
        if b != base36(z & 63):
            print("Invalid chunk file: %s" % location)
            return

        nbt = NBTFile(filename=location, buffer='rb')

        if x != nbt['Level']['xPos'].value:
            print("Invalid chunk file: %s" % location)
            return

        if z != nbt['Level']['zPos'].value:
            print("Invalid chunk file: %s" % location)
            return

        chunk = Chunk(
            self.server,
            self,
            x, z,
            nbt['Level']['TerrainPopulated'].value,
            nbt['Level']['Blocks'].value,
            nbt['Level']['Data'].value,
            nbt['Level']['BlockLight'].value,
            nbt['Level']['SkyLight'].value
        )

        self.chunks[(chunkFile[1], chunkFile[2])] = chunk
Example #17
0
def unpack_raw(raw, export=False):
    """Unpack raw b64 encoded gzipped nbt data
    Steps:
        1. Decode base 64
        2. nbt.nbt.NBTFile(fileobj=io.BytesIO())
        3. Walk tree and return it as json/dict
    """
    decoded = base64.b64decode(raw)
    nbtfile = NBTFile(fileobj=io.BytesIO(decoded))
    if export:
        nbtfile.write_file(
            f'nbt{datetime.datetime.now().strftime("%Y%m%d-%H%M%S-%f.nbt")}')
        return
Example #18
0
def convert(nbt_file, function_file, settings):
    """
    Converts an NBT structure files into an mcfunction file.
    `block_name_map` map can be used to change block name
    (for example when creating a bedrock function).
    Blocks are grouped into fills where possible.
    """
    block_name_map = settings.get('block_name_map', {})
    strip_namespace = settings.get('strip_namespace')

    structure = unpack_nbt(NBTFile(nbt_file, 'rb'))

    # create a list of mapped blocks

    blocks = []

    for block in structure['blocks']:
        x, y, z = block['pos']
        block_data = structure['palette'][block['state']]
        name = block_data['Name']
        if strip_namespace:
            _, name = name.split(':')
        if 'Properties' in block_data:
            properties = [
                f'{key}={value}'
                for key, value in block_data['Properties'].items()
                # any properties with `false` values are assumed to be default and are ignored
                if value != 'false'
            ]
            name = f"{name}[{','.join(properties)}]"
        # change the block name if a map exists
        if name in block_name_map:
            name = block_name_map[name]
        if name is not None:
            blocks.append((x, y, z, name))

    # try to group contiguous blocks into fills
    fills = group_blocks_into_fills(blocks, structure['size'])

    if 'order_values' in settings:
        order_values = settings['order_values']
        fills.sort(key=lambda f: order_values.get(f[2], 50))

    # write out the function
    with open(function_file, 'w') as file:
        for min_voxel, max_voxel, name in fills:
            write_fill(file, min_voxel, max_voxel, name)
Example #19
0
def main(world_folder, options):
    world = WorldFolder(world_folder)

    if not isinstance(world, nbt.world.AnvilWorldFolder):
        print(world_folder + " is not an Anvil world")
        return 0

    level = NBTFile(os.path.join(world_folder, "level.dat"))
    version = Util.get_version(level)

    print("\nLoading level at " + world_folder)
    if version != "1.8" or options.force:
        if options.force:
            print("[Forcing level conversion attempt]")
        print("Level saved as Minecraft version " + version)
        try:
            total_nbt_edits = 0
            total_block_edits = 0
            for region in world.iter_regions():
                for chunk in region.iter_chunks():
                    chunk, nbt_edits = convert_chunk(chunk)
                    chunk, block_edits = convert_block(chunk)
                    total_nbt_edits += nbt_edits
                    total_block_edits += block_edits
                    if options.save and nbt_edits > 0 or block_edits > 0:
                        save_chunk(region, chunk)
            if total_nbt_edits > 0 or total_block_edits > 0:
                print("%d modifications made to the level nbt" %
                      (total_nbt_edits))
                print("%d modifications made to block section byte arrays" %
                      (total_block_edits))
                if options.save:
                    save_level(level, world_folder)
                else:
                    print("No modifications saved to level (using -n flag)")
            else:
                print("No level data was changed (nothing to modify)")
        except KeyboardInterrupt:
            return 75
    else:
        print("Level is already saved for Minecraft 1.8 (or older)")

    if options.disable_keep_inv and options.save:
        disable_keep_inv(level, world_folder)

    return 0
Example #20
0
def tree_to_nbt(nbt: Token, filename: str):
    nbt_file = NBTFile()
    nbt_file.tags = [x.value for x in nbt._value]  # Fix this
    nbt_file.write_file(filename)
Example #21
0
def nbt_to_tree(filename: str) -> Token:
    nbt = NBTFile(filename)
    return _to_py(nbt)
Example #22
0
def nbt_to_json(filename: str, **dumps_kwargs: dict) -> str:
    nbt = NBTFile(filename)
    py = _to_py(nbt)
    return json.dumps(py.as_dict, **dumps_kwargs)
Example #23
0
 def setUp(self):
     self.nbtfile = NBTFile()
Example #24
0
 def getnbt(filename):
     nbtdata = NBTFile(filename)
     return unpack_nbt(nbtdata)
Example #25
0
 def testWriteback(self):
     mynbt = NBTFile(self.filename)
     mynbt.write_file()
Example #26
0
 def testWriteBig(self):
     mynbt = NBTFile(self.filename)
     output = BytesIO()
     mynbt.write_file(buffer=output)
     self.assertEqual(GzipFile(NBTTESTFILE).read(), output.getvalue())
Example #27
0
 def testReadBig(self):
     mynbt = NBTFile(self.filename)
     self.assertTrue(mynbt.filename != None)
     self.assertEqual(len(mynbt.tags), 11)
Example #28
0
 def setUp(self):
     self.golden_value = b"\x0A\0\x04Test\x08\0\x0Cempty string\0\0\0"
     self.nbtfile = NBTFile(buffer=BytesIO(self.golden_value))
def nbt_to_object(filename):
    ''' return an object from an NBT file'''
    nbtData = NBTFile(filename)

    return unpack_nbt(nbtData)
Example #30
0
position = [ bla.value for bla in nbtdata["Pos"] ]
dimension = nbtdata["Dimension"].value
UUIDleast = nbtdata["UUIDLeast"].value
UUIDmost = nbtdata["UUIDMost"].value
'''


def unpack_nbt(tag):
    """
    Unpack an NBT tag into a native Python data structure.
    """

    if isinstance(tag, TAG_List):
        return [unpack_nbt(i) for i in tag.tags]
    elif isinstance(tag, TAG_Compound):
        return dict((i.name, unpack_nbt(i)) for i in tag.tags)
    else:
        return tag.value


for each in files:

    nbtData = NBTFile(each)

    pp = pprint.PrettyPrinter(depth=1, indent=4, width=10)

    Obj = unpack_nbt(nbtData)

    pp.pprint(Obj)
    #print([a["Players"] for a in Obj["data"]["Teams"] if a["Name"] == "mute"])