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!")
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
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
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
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)
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', '') ))
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)
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)
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)
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
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))
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")
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
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
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
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
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
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)
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
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)
def nbt_to_tree(filename: str) -> Token: nbt = NBTFile(filename) return _to_py(nbt)
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)
def setUp(self): self.nbtfile = NBTFile()
def getnbt(filename): nbtdata = NBTFile(filename) return unpack_nbt(nbtdata)
def testWriteback(self): mynbt = NBTFile(self.filename) mynbt.write_file()
def testWriteBig(self): mynbt = NBTFile(self.filename) output = BytesIO() mynbt.write_file(buffer=output) self.assertEqual(GzipFile(NBTTESTFILE).read(), output.getvalue())
def testReadBig(self): mynbt = NBTFile(self.filename) self.assertTrue(mynbt.filename != None) self.assertEqual(len(mynbt.tags), 11)
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)
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"])