def makeMaps(worldFolder, outputFolder, serverType, unlimitedTracking=False): nbtMapData = [] if serverType == "bds": # open leveldb db = leveldb.open(os.path.join(worldFolder, "db")) # iterate over all the maps for a in tqdm(leveldb.iterate(db), "leveldb map keys -> nbt".ljust(24), bar_format="{l_bar}{bar}"): key = bytearray(a[0]) if b"map" in key: # get extract an nbt object mapNbtIo = BytesIO(a[1]) mapNbtFile = nbtlib.File.parse(mapNbtIo, byteorder="little") mapNbt = mapNbtFile.root mapId = int(mapNbt["mapId"]) epoch = now nbtMapData.append({"epoch": epoch, "id": mapId, "nbt": mapNbt}) elif serverType == "java": mapDatFiles = findMapFiles(worldFolder) for mapDatFile in tqdm(mapDatFiles, "map_*.dat -> nbt".ljust(24), bar_format="{l_bar}{bar}"): mapNbtFile = nbtlib.load(mapDatFile) mapNbt = mapNbtFile.root["data"] mapId = int(os.path.basename(mapDatFile)[4:-4]) epoch = int(os.path.getmtime(mapDatFile)) nbtMapData.append({"epoch": epoch, "id": mapId, "nbt": mapNbt}) maps = [] os.makedirs(outputFolder, exist_ok=True) mapPngs = getMapPngs(outputFolder) currentMapPngs = filterLatestMapPngsById(mapPngs) currentIdHashes = {(x.mapId, x.mapHash): x for x in currentMapPngs} currentIds = {x.mapId: x for x in currentMapPngs} for nbtMap in tqdm(nbtMapData, "nbt -> png".ljust(24), bar_format="{l_bar}{bar}"): mapId = nbtMap["id"] mapNbt = nbtMap["nbt"] mapEpoch = nbtMap["epoch"] try: mapUnlimitedTracking = mapNbt["unlimitedTracking"] except KeyError: mapUnlimitedTracking = False if mapUnlimitedTracking and not unlimitedTracking: continue scale = int(mapNbt["scale"]) x = int(mapNbt["xCenter"]) z = int(mapNbt["zCenter"]) dimension = mapNbt["dimension"] mapColors = mapNbt["colors"] if type(dimension) == nbtlib.tag.Int: dimension = dimDict[mapNbt["dimension"]] elif type(dimension) == nbtlib.tag.Byte: dimension = dimDict[mapNbt["dimension"]] else: dimension = dimension.strip('"') try: mapBanners = mapNbt["banners"] except KeyError: mapBanners = [] banners = [] for banner in mapBanners: X = int(banner["Pos"]["X"]) Y = int(banner["Pos"]["Y"]) Z = int(banner["Pos"]["Z"]) color = banner["Color"] try: name = json.loads(banner["Name"])["text"] except KeyError: name = "" bannerDict = { "X": X, "Y": Y, "Z": Z, "color": color, "name": name, "dimension": dimension } bannerTuple = BannerTuple(**bannerDict) banners.append(bannerTuple) frames = [] # logging.debug(mapColors) if serverType == "bds": mapImage = Image.frombytes("RGBA", (128, 128), bytes([x % 256 for x in mapColors]), 'raw') elif serverType == "java": colorTuples = [allColors[x % 256] for x in mapColors] mapImage = Image.new("RGBA", (128, 128)) mapImage.putdata(colorTuples) mapHash = hashlib.md5(mapImage.tobytes()).hexdigest() # empty map if mapHash == "fcd6bcb56c1689fcef28b57c22475bad": continue if mapId not in currentIds: # brand new image logging.debug("%s is a new map", mapId) epoch = mapEpoch else: # changed image logging.debug("%s is already known", mapId) epoch = currentIds.get(mapId).epoch if (mapId, mapHash) not in currentIdHashes: epoch = now mapPng = MapPngTuple(mapId=mapId, mapHash=mapHash, epoch=epoch, dimension=dimension, x=x, z=z, scale=scale) if (mapId, mapHash) not in currentIdHashes: logging.debug("%s changed", mapId) mapImage = mapImage.resize((128 * 2**scale, ) * 2, Image.NEAREST) filename = mapPngFilenameFormat.format(**mapPng._asdict()) mapImage.save( os.path.join(outputFolder, filename.replace(":", "@"))) mapData = MapTuple(mapData=mapPng, bannerData=banners, frameData=frames) maps.append(mapData) logging.debug(maps) logging.info("Processed %s maps", len(maps)) return maps
def iterKeys(self, start=None, end=None): yield from ldb.iterate(self.db, start, end)