Пример #1
0
def _build_index_from_ab(ab, target_md5):
    # CAUTION: this function doesn't check if this ab has been indexed or not, so callers should check by themselves!
    # create containers
    # fetch first
    try:
        c = get_containers_from_ab(unitypack.load(open(target_md5, 'rb'))).keys()
    except Exception as e:
        logger.exception('get_containers_from_ab error')
        return
        # use set to sure each name add only once
    container_name_set = set(c)
    container_name_list = list(container_name_set)
    # print(len(container_name_set))

    # SQL may be too long, so make smaller sets to execute
    for first in range(0, len(container_name_list), 500):
        # calc containers not in database
        part = container_name_list[first:first + 500]
        part_exclude = set(part) - {i['name'] for i in Container.objects.filter(name__in=part).values('name')}
        # print('exclude:',container_name_exclude_set)
        # then create those not in database
        Container.objects.bulk_create([Container(name=n) for n in part_exclude])
        # query once to add the relations
        ab.container_set.add(*list(Container.objects.filter(name__in=part)))  # filter here

    # create unity objects
    # fetch first
    try:
        objects_list = get_objects_from_ab(unitypack.load(open(target_md5, 'rb')))
    except Exception as e:
        logger.exception('get_objects_from_ab error')
        return

    db_hash_set = {i[3] for i in objects_list}

    # create objects which don't exist
    db_hash_exclude = db_hash_set - {i['db_hash'] for i in
                                     UnityObject.objects.filter(db_hash__in=db_hash_set).values('db_hash')}
    unityobjects = []
    db_hash_used_set = set()  # even in a single file, there may be two objects have same db_hash!
    for name, path_id, data_hash, db_hash, asset_index, object_type in objects_list:
        if db_hash in db_hash_exclude and db_hash not in db_hash_used_set:
            unityobjects.append(UnityObject(name=name, data_hash=data_hash, db_hash=db_hash, type=object_type))
            db_hash_used_set.add(db_hash)
    bulk_result = UnityObject.objects.bulk_create(unityobjects)

    # add relations
    relationships = []
    db_hash_to_db_object = {uo.db_hash: uo for uo in UnityObject.objects.filter(db_hash__in=db_hash_set)}
    for name, path_id, data_hash, db_hash, asset_index, object_type in objects_list:
        relationships.append(
            UnityObjectRelationship(assetbundle=ab, unityobject=db_hash_to_db_object[db_hash],
                                    path_id=path_id, asset_index=asset_index))

    UnityObjectRelationship.objects.bulk_create(relationships)
Пример #2
0
def main():
	p = ArgumentParser()
	p.add_argument("files", nargs="+")
	p.add_argument("-s", "--strip", action="store_true", help="Strip extractable data")
	args = p.parse_args(sys.argv[1:])

	for k, v in unitypack.engine.__dict__.items():
		if isinstance(v, type) and issubclass(v, unitypack.engine.object.Object):
			yaml.add_representer(v, unityobj_representer)

	if args.strip:
		yaml.add_representer(unitypack.engine.mesh.Mesh, mesh_representer)
		yaml.add_representer(unitypack.engine.movie.MovieTexture, movietexture_representer)
		yaml.add_representer(unitypack.engine.text.Shader, shader_representer)
		yaml.add_representer(unitypack.engine.text.TextAsset, textasset_representer)
		yaml.add_representer(unitypack.engine.texture.Texture2D, texture2d_representer)

	for file in args.files:
		if file.endswith(".assets"):
			with open(file, "rb") as f:
				asset = unitypack.Asset.from_file(f)
			handle_asset(asset)
			continue

		with open(file, "rb") as f:
			bundle = unitypack.load(f)

		for asset in bundle.assets:
			handle_asset(asset)
Пример #3
0
	def parse_bundle(self, path):
		if os.path.basename(path) not in self.unity3d_filenames:
			# Only parse files that have a whitelisted name
			return

		with open(path, "rb") as f:
			bundle = unitypack.load(f)
			asset = bundle.assets[0]
			self.info("Processing %r" % (asset))

			if os.path.basename(path) == "dbf.unity3d":
				self.parse_dbf_unity_asset(asset)
				return

			for obj in asset.objects.values():
				if obj.type == "TextAsset":
					d = obj.read()
					if d.name in IGNORE_LOCALES:
						continue
					if d.script.startswith("<CardDefs>"):
						xml = ElementTree.fromstring(d.script)
						self.parse_full_carddefs(xml, d.name)
					elif d.script.startswith("<?xml "):
						xml = ElementTree.fromstring(d.script.encode("utf-8"))
						self.parse_single_entity_xml(xml, d.name, locale=None)
					else:
						self.error("Bad TextAsset: %r" % (d))
Пример #4
0
def parse_file(filename, item_lists):
    with open(filename, 'rb') as f:
        bundle = unitypack.load(f)
        for asset in bundle.assets:
            for _, object in asset.objects.items():
                if object.type == 'TextAsset':
                    parse_object(object, item_lists)
Пример #5
0
	def parse_bundle(self, path):
		import unitypack

		with open(path, "rb") as f:
			bundle = unitypack.load(f)
			asset = bundle.assets[0]
			self.info("Processing %r" % (asset))
			self.parse_dbf_asset(asset)
def main():
    ugru = UnityGameResUnpack(sys.argv[1:])
    for currentPath, dirs, files in os.walk(ugru.apkExtractedPath):
        for nowFile in files:
            try:
                nowFilePath = os.path.join(currentPath, nowFile)
                with open(nowFilePath, 'rb') as file:
                    bundle = unitypack.load(file)
            except NotImplementedError as e:
                pass
            else:
                ugru.handleFile(nowFilePath, currentPath)
Пример #7
0
def main():
	files = sys.argv[1:]
	for file in files:
		if file.endswith(".assets"):
			with open(file, "rb") as f:
				asset = unitypack.Asset.from_file(f)
			handle_asset(asset)
			continue

		with open(file, "rb") as f:
			bundle = unitypack.load(f)

		for asset in bundle.assets:
			handle_asset(asset)
Пример #8
0
def extract_info(files, filter_ids):
    cards = {}
    textures = {}
    env = UnityEnvironment()

    for file in files:
        print("Reading %r" % (file))
        f = open(file, "rb")
        bundle = unitypack.load(f, env)

        for asset in bundle.assets:
            print("Parsing %r" % (asset.name))
            handle_asset(asset, textures, cards, filter_ids)

    return cards, textures
def extract_info(files):
	cards = {}
	textures = {}
	env = UnityEnvironment()

	for file in files:
		print("Reading %r" % (file))
		with open(file, "rb") as f:
			bundle = unitypack.load(f, env)

		for asset in bundle.assets:
			print("Parsing %r" % (asset.name))
			handle_asset(asset, textures, cards)

	return cards, textures
Пример #10
0
def main():
	p = ArgumentParser()
	p.add_argument("files", nargs="+")
	p.add_argument("--output", "-o", required=True)
	p.add_argument("--all", action="store_true")
	p.add_argument("--images", action="store_true")
	p.add_argument("--models", action="store_true")
	p.add_argument("--text", action="store_true")
	p.add_argument("-q", action="store_true")
	p.add_argument("-qq", action="store_true")
	# flip images the "right" way up
	p.add_argument("--flip", action="store_true")
	# option for obj meshes (instead of js)
	p.add_argument("--obj", action="store_true")
	args = p.parse_args(sys.argv[1:])

	utils.Echo.quiet = args.q
	utils.Echo.very_quiet = args.qq

	format_args = {
		"images": "Texture2D",
		"models": "Mesh",
		"text": "TextAsset",
	}
	handle_formats = []
	for a, classname in format_args.items():
		if args.all or getattr(args, a):
			handle_formats.append(classname)

	files = args.files
	if len(args.files) == 1:
		if os.path.isdir(args.files[0]):
			files = glob.glob(args.files[0] + "/*.unity3d")

	for file in files:
		bundle_name = utils.filename_no_ext(file)
		if bundle_name in EXCLUDES:
			info("Skipping %s..." % (bundle_name))
			continue
		info("Extracting %s..." % (bundle_name))
		save_path = os.path.join(args.output, bundle_name)

		with open(file, "rb") as f:
			bundle = unitypack.load(f)

		for asset in bundle.assets:
			handle_asset(asset, handle_formats, save_path,
						 args.flip, args.obj, args.quiet)
Пример #11
0
def unpack(infilepath, outpath):
    with open(infilepath, "rb") as f:
        bundle = unitypack.load(f)
        asset = bundle.assets[0]

        ab = asset.objects[1]
        for org_path, b in ab.read()["m_Container"]:
            obj = b["asset"].object
            if obj.type == "TextAsset":
                data = obj.read()
                if isinstance(data.script, str):
                    outfilepath = os.path.join(outpath,
                                               os.path.normpath(org_path))
                    mkdir(os.path.dirname(outfilepath))
                    with open(outfilepath, "wb") as fo:
                        fo.write(data.script.encode('utf-8'))
def main():
	p = ArgumentParser()
	p.add_argument("--outdir", nargs="?", default="")
	p.add_argument("--skip-existing", action="store_true")
	p.add_argument("files", nargs="+")
	args = p.parse_args(sys.argv[1:])

	textures = {}
	cards = {}

	env = unitypack.UnityEnvironment()

	for file in args.files:
		with open(file, "rb") as f:
			bundle = unitypack.load(f, env)

		for asset in bundle.assets:
			if asset.name.startswith("CAB-cards"):
				handle_cards_asset(asset, cards)
			else:
				handle_asset(asset, textures, cards)

	print("Found %i cards, %i textures including %i unique in use." % (
		len(cards), len(textures), len(set(cards.values()))
	))

	for id, path in cards.items():
		if not path:
			print("%r does not have a texture" % (id))
			continue

		if path not in textures:
			print("Path %r not found for %r" % (path, id))
			continue

		pptr = textures[path]
		texture = pptr.resolve()

		png = os.path.join(args.outdir, "%s.png" % (id))
		if args.skip_existing and os.path.exists(png):
			continue
		print("%r -> %r" % (path, png))
		texture.image.save(png)
def main():
	p = ArgumentParser()
	p.add_argument("input")
	p.add_argument("output")
	p.add_argument("--only")
	p.add_argument("--raw", action="store_true")
	p.add_argument("-qq", action="store_true")
	p.add_argument("-q", action="store_true")
	p.add_argument("--trace", action="store_true")
	args = p.parse_args(sys.argv[1:])

	utils.Echo.quiet = args.q
	utils.Echo.very_quiet = args.qq

	files = [args.input]
	if os.path.isdir(args.input):
		files = glob.glob(args.input + "/*")

	redefine_shader()

	for file in files:
		info("Processing %s" % (file))

		with open(file, "rb") as f:
			bundle = unitypack.load(f)

		for asset in bundle.assets:
			for id, obj in asset.objects.items():
				bundle_name = utils.filename_no_ext(file)
				try:
					if obj.type == "Shader":
						d = obj.read()
						if not args.only or (args.only and args.only in d.parsed_form.name):
							save_path = os.path.join(
								args.output,
								bundle_name,
								obj.type
							)
							extract_shader(d, save_path, args.raw)
				except Exception as e:
					error("{0} ({1})".format(e, bundle_name))
					if args.trace:
						raise
Пример #14
0
def extractimg(abpath, extractpath):
    for root, dirs, files in os.walk(abpath):
        for filename in files:
            if filename[:10] == 'character_':
                bundle = unitypack.load(open(abpath + "/" + filename, "rb"))
                for asset in bundle.assets:
                    filenamearray = filename.split(".")[0].split("_")
                    if filenamearray[-1] == 'jpvoice':
                        continue
                    charactername = "_".join(filenamearray[1:])
                    if not os.path.exists(extractpath + "/" + charactername):
                        os.makedirs(extractpath + "/" + charactername)
                    for id, object in asset.objects.items():
                        if object.type == "Texture2D":
                            data = object.read()
                            image = data.image.transpose(Image.FLIP_TOP_BOTTOM)
                            image.save(
                                extractpath + "/" + charactername + "/" +
                                data.name + ".png", "PNG")
def main():
    p = ArgumentParser()
    p.add_argument("--outdir", nargs="?", default="")
    p.add_argument("--skip-existing", action="store_true")
    p.add_argument("files", nargs="+")
    args = p.parse_args(sys.argv[1:])

    textures = {}
    cards = {}

    env = unitypack.UnityEnvironment()

    for file in args.files:
        with open(file, "rb") as f:
            bundle = unitypack.load(f, env)

        for asset in bundle.assets:
            if asset.name.startswith("CAB-cards"):
                handle_cards_asset(asset, cards)
            else:
                handle_asset(asset, textures, cards)

    print("Found %i cards, %i textures including %i unique in use." %
          (len(cards), len(textures), len(set(cards.values()))))

    for id, path in cards.items():
        if not path:
            print("%r does not have a texture" % (id))
            continue

        if path not in textures:
            print("Path %r not found for %r" % (path, id))
            continue

        pptr = textures[path]
        texture = pptr.resolve()

        png = os.path.join(args.outdir, "%s.png" % (id))
        if args.skip_existing and os.path.exists(png):
            continue
        print("%r -> %r" % (path, png))
        texture.image.save(png)
Пример #16
0
def unityfs(fs, outdir):
    dist = os.path.join(outdir, os.path.basename(fs))
    with open(fs, 'rb') as fp:
        try:
            bundle = unitypack.load(fp)
        except Exception as e:
            print(e)
            return
        for asset in bundle.assets:
            try:
                assetobjs = asset.objects.items()
            except Exception as e:
                print(e)
                continue
            for pid, obj in assetobjs:
                try:
                    extract_asset_item(pid, obj, dist)
                except Exception as e:
                    print(e)
                    continue
Пример #17
0
def main():
	p = ArgumentParser()
	p.add_argument("files", nargs="+")
	p.add_argument("--all", action="store_true")
	p.add_argument("--audio", action="store_true")
	p.add_argument("--images", action="store_true")
	p.add_argument("--models", action="store_true")
	p.add_argument("--shaders", action="store_true")
	p.add_argument("--text", action="store_true")
	p.add_argument("--video", action="store_true")
	args = p.parse_args(sys.argv[1:])

	format_args = {
		"audio": "AudioClip",
		"images": "Texture2D",
		"models": "Mesh",
		"shaders": "Shader",
		"text": "TextAsset",
		"video": "MovieTexture",
	}
	handle_formats = []
	for a, classname in format_args.items():
		if args.all or getattr(args, a):
			handle_formats.append(classname)

	for file in args.files:
		if file.endswith(".assets"):
			with open(file, "rb") as f:
				asset = unitypack.Asset.from_file(f)
			handle_asset(asset, handle_formats)
			continue

		with open(file, "rb") as f:
			bundle = unitypack.load(f)

		for asset in bundle.assets:
			handle_asset(asset, handle_formats)
Пример #18
0
def main():
	p = ArgumentParser()
	p.add_argument("files", nargs="+")
	p.add_argument("--all", action="store_true")
	p.add_argument("--audio", action="store_true")
	p.add_argument("--images", action="store_true")
	p.add_argument("--models", action="store_true")
	p.add_argument("--shaders", action="store_true")
	p.add_argument("--text", action="store_true")
	p.add_argument("--video", action="store_true")
	args = p.parse_args(sys.argv[1:])

	format_args = {
		"audio": "AudioClip",
		"images": "Texture2D",
		"models": "Mesh",
		"shaders": "Shader",
		"text": "TextAsset",
		"video": "MovieTexture",
	}
	handle_formats = []
	for a, classname in format_args.items():
		if args.all or getattr(args, a):
			handle_formats.append(classname)

	for file in args.files:
		if file.endswith(".assets"):
			with open(file, "rb") as f:
				asset = unitypack.Asset.from_file(f)
			handle_asset(asset, handle_formats)
			continue

		with open(file, "rb") as f:
			bundle = unitypack.load(f)

		for asset in bundle.assets:
			handle_asset(asset, handle_formats)
Пример #19
0
def main():
	p = ArgumentParser()
	p.add_argument("bundles", nargs="+", type=FileType("rb"))
	p.add_argument("-o", "--outfile", nargs=1, type=FileType("wb"))
	p.add_argument("--dbf", nargs="?", type=FileType("r"))
	args = p.parse_args(sys.argv[1:])

	build = detect_build(args.bundles[0].name)

	carddefs = {}
	entities = {}
	textures = {}
	whitelist = [
		"cards.unity3d",
		"cards0.unity3d",
		"cards1.unity3d",
		"cards2.unity3d",
		"cardxml0.unity3d",
	]

	for f in args.bundles:
		if os.path.basename(f.name) not in whitelist:
			f.close()
			continue
		bundle = unitypack.load(f)
		asset = bundle.assets[0]
		print("Processing %r" % (asset))
		for obj in asset.objects.values():
			if obj.type == "TextAsset":
				d = obj.read()
				if d.name in IGNORE_LOCALES:
					continue
				if d.script.startswith("<CardDefs>"):
					carddefs[d.name] = ElementTree.fromstring(d.script)
				elif d.script.startswith("<?xml "):
					entities[d.name] = ElementTree.fromstring(d.script)
				else:
					raise Exception("Bad TextAsset %r" % (d))
			elif obj.type in ("CardDef", "MonoScript"):
				d = obj.read()
				if "m_GameObject" not in d:
					# We check for MonoScript because type checks through asset
					# references does not return the real class name yet.
					# This means we have to check for GameObject in the obj to
					# make sure it's actually a card.
					continue
				if d["m_GameObject"] is None:
					print("Missing m_GameObject for %r" % (obj))
					continue
				cardid = d["m_GameObject"].resolve().name
				if "m_PortraitTexture" in d:
					ptr = d["m_PortraitTexture"]
					if not ptr:
						continue
					try:
						texture = ptr.resolve().name
					except NotImplementedError:
						texture = ""
				else:
					texture = reverse_texture_path(d.get("m_PortraitTexturePath", ""))
				if texture:
					textures[cardid] = texture

	if carddefs:
		xml = merge_locale_assets(carddefs)
	else:
		xml = merge_card_assets(entities, build)

	hero_powers = {}
	if args.dbf:
		print("Processing DBF %r" % (args.dbf.name))
		dbfxml = ElementTree.parse(args.dbf)
		guids, hero_powers = load_dbf(dbfxml)

		clean_entourage_ids(xml, guids)

	if build < 6024:
		SHROUDED = "Can't be targeted by Spells or Hero Powers."
	else:
		SHROUDED = "Can't be targeted by spells or Hero Powers."

	SPARE_PART_RE = re.compile(r"PART_\d+")

	for entity in xml.findall("Entity"):
		id = entity.attrib["CardID"]
		description = entity.find("Tag[@enumID='184']/enUS")
		description = description.text if description is not None else ""

		# Clean up MasterPower whitespace
		power = entity.find("MasterPower")
		if power is not None:
			power.text = power.text.strip()
			if not power.text:
				entity.remove(power)

		overload = entity.find("Tag[@enumID='215']")
		if overload is not None:
			overload.attrib["value"] = str(guess_overload(description))

		spellpower = entity.find("Tag[@enumID='192']")
		if spellpower is not None:
			spellpower.attrib["value"] = str(guess_spellpower(description))
			spellpower.attrib["type"] = "Int"

		if SHROUDED in description:
			set_tag(entity, GameTag.CANT_BE_TARGETED_BY_ABILITIES, 1, type="Bool")
			set_tag(entity, GameTag.CANT_BE_TARGETED_BY_HERO_POWERS, 1, type="Bool")

		if "Can't attack." in description or "Can't Attack." in description:
			set_tag(entity, GameTag.CANT_ATTACK, 1, type="Bool")

		if SPARE_PART_RE.match(id):
			set_tag(entity, GameTag.SPARE_PART, 1, type="Bool")

		if id in textures:
			e = ElementTree.Element("Texture")
			e.text = textures[id]
			entity.append(e)

		if id in hero_powers:
			e = ElementTree.Element("HeroPower")
			e.attrib["cardID"] = hero_powers[id]
			entity.append(e)

	xml.attrib["build"] = str(build)

	print("Writing to %r" % (args.outfile[0].name))
	args.outfile[0].write(pretty_xml(xml))
Пример #20
0
    def unpackTexture(self, filePath: str):
        ret = []
        filePathPath, filePathFile = os.path.split(filePath)
        _, ifpainting = os.path.split(filePathPath)
        # print(ifpainting,filePathFile[-3:])
        if filePathFile[-3:] == "tex":
            needPintu = True
        else:
            needPintu = False
        savePath = os.path.join(self.outPath, filePath)
        self.makeDirs(savePath)
        with open(filePath, "rb") as f:
            # print(f.read(5))
            try:
                bundle = unitypack.load(f)
            except NotImplementedError as e:
                # self.handdled += 1
                # print(f"{self.handdled}/{self.fileCount} handdled")
                return ret

            # does
            # not start
            # with b'Unity'
            for asset in bundle.assets:
                needRemove = False
                # print("%s: %s:: %i objects" % (bundle, asset, len(asset.objects)))
                for id, object in asset.objects.items():
                    # print(object.type)
                    # Let's say we only want TextAsset objects
                    # print(object.type)
                    if (object.type == "Texture2D"):
                        d = object.read()
                        # print(d.name)
                        try:
                            if d.format in ETC_SERIES:
                                # self.waitHanddle.append(d)
                                # continue
                                needRemove = True
                                TMP_PKM_FNAME = os.path.join(
                                    savePath,
                                    str(id) + TMP_PKM_FNAME_0)
                                TMP_PPM_FNAME = os.path.join(
                                    savePath,
                                    str(id) + TMP_PPM_FNAME_0)
                                bin_data = self.get_pkm_header(
                                    d.width, d.height, d.format) + d.image_data
                                with open(TMP_PKM_FNAME, 'wb') as f:
                                    f.write(bin_data)
                                cmd = ' '.join([
                                    ETCPACK_CMD, TMP_PKM_FNAME, TMP_PPM_FNAME,
                                    ">/dev/null 2>&1"
                                ])
                                if sys.platform == "win32":
                                    cmd = ' '.join([
                                        ETCPACK_CMD, TMP_PKM_FNAME,
                                        TMP_PPM_FNAME
                                    ])
                                # print(cmd)
                                ret0 = subprocess.check_output(cmd, shell=True)
                                img = Image.open(TMP_PPM_FNAME)
                                # img.show()
                            else:
                                try:
                                    img = d.image
                                except Exception as e:
                                    print(filePath, str(e))
                                    continue
                        except:
                            try:
                                img = d.image
                            except Exception as e:
                                print(filePath, str(e))
                                continue
                        if (img.mode not in ('RGBA', 'LA')):
                            saveFileName = f"{d.name}.jpeg"
                            savePathFile = os.path.join(savePath, saveFileName)
                            img = ImageOps.flip(img)

                            img.save(savePathFile,
                                     "JPEG",
                                     quality=self.QUALITY,
                                     optimize=True,
                                     progressive=True)
                            if needPintu:
                                pintuImgPath = savePathFile
                            else:
                                ret.append(savePathFile)
                                print("    ->extract " + savePathFile)
                        else:
                            saveFileName = f"{d.name}.png"
                            savePathFile = os.path.join(savePath, saveFileName)
                            img = ImageOps.flip(img)
                            img.save(savePathFile, "PNG")
                            if needPintu:
                                pintuImgPath = savePathFile
                            else:
                                ret.append(savePathFile)
                                print("    ->extract " + savePathFile)
                    elif object.type == "Mesh":
                        d = object.read()
                        try:
                            mesh_data = OBJMesh(d).export()
                            savePathFile = os.path.join(savePath, d.name)
                            savePathFile = savePathFile + ".obj"
                            self.write_to_file(savePathFile,
                                               mesh_data,
                                               mode="w")
                        except NotImplementedError as e:
                            print("WARNING: Could not extract %r (%s)" %
                                  (d, e))
                            mesh_data = pickle.dumps(d._obj)
                            savePathFile = os.path.join(savePath, d.name)
                            savePathFile = savePathFile + ".Mesh.pickle"
                            self.write_to_file(savePathFile,
                                               mesh_data,
                                               mode="wb")
                        if needPintu:
                            pintuMeshPath = savePathFile
                if needRemove:
                    try:
                        # pass
                        os.remove(TMP_PKM_FNAME)
                        os.remove(TMP_PPM_FNAME)
                    except:
                        pass

            if needPintu:
                pinPic = az_paint_restore(pintuMeshPath, pintuImgPath)
                pintuImgSavePath = ".".join(
                    pintuImgPath.split(".")[:-1]) + ".png"
                pinPic.save(pintuImgSavePath, "PNG")
                ret.append(pintuImgSavePath)
                print("    ->extract " + pintuImgSavePath)
        # self.handdled += 1
        # print(f"{self.handdled}/{self.fileCount} handdled")
        return ret
Пример #21
0
async def get_sleeve_names() -> dict:
    global _sleeve_names
    if _sleeve_names is not None:
        return _sleeve_names

    sleeve_master = None
    sleevenametext = None

    res_ver = os.environ["RES_VER"]
    url = f"https://shadowverse.akamaized.net/dl/Manifest/{res_ver}/Eng/Windows/master_assetmanifest"
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            text = await response.text()

    for line in text.splitlines():
        fields = line.split(",")
        if len(fields) < 2:
            continue
        [name, hexcode, *_] = fields

        if name == "master_sleeve_master.unity3d":
            url = f"https://shadowverse.akamaized.net/dl/Resource/Eng/Windows/{hexcode}"
            async with aiohttp.ClientSession() as session:
                async with session.get(url) as response:
                    data = await response.read()

            data = io.BytesIO(data)
            data.name = ""
            bundle = unitypack.load(data)
            for asset in bundle.assets:
                for _, obj in asset.objects.items():
                    if obj.type == "TextAsset":
                        d = obj.read()
                        if d.name == "sleeve_master":
                            sleeve_master = d.script
                            break
                if sleeve_master is not None:
                    break

        elif name == "master_sleevenametext.unity3d":
            url = f"https://shadowverse.akamaized.net/dl/Resource/Eng/Windows/{hexcode}"
            async with aiohttp.ClientSession() as session:
                async with session.get(url) as response:
                    data = await response.read()

            data = io.BytesIO(data)
            data.name = ""
            bundle = unitypack.load(data)
            for asset in bundle.assets:
                for _, obj in asset.objects.items():
                    if obj.type == "TextAsset":
                        d = obj.read()
                        if d.name == "sleevenametext":
                            sleevenametext = d.script
                            break
                if sleevenametext is not None:
                    break

    sleevenametext = json.loads(sleevenametext)
    sleevenametext = sleevenametext["sleevenametext"]["Eng"]

    ret = {}
    lines = sleeve_master.splitlines()
    for line in lines[1:]:
        fields = line.split(",")
        if len(fields) < 2:
            continue
        [sleeve_id, sleeve_name, *_] = fields
        if not sleeve_id.isdigit():
            continue
        sleeve_id = int(sleeve_id)
        ret[sleeve_id] = sleevenametext[sleeve_name]

    _sleeve_names = ret
    return ret
Пример #22
0
import unitypack

with open('D:\\misc\\Hearthstone\\Data\Win\\cardxml0.unity3d') as f:
    bundle = unitypack.load(f)

    #for asset in bundle.assets:
    #    print("%s: %s:: %i objects" % (bundle, asset, len(asset.objects)))
def main():
	# setup the command arguments
	arg_parser = argparse.ArgumentParser()
	arg_parser.add_argument("input",
		help="the directory containing the unity3d files")
	arg_parser.add_argument("cache",
		help="the directory containing the cache files")
	arg_parser.add_argument("search",
		help="the search string, case insensitive")
	arg_parser.add_argument("--cache-only", action="store_true",
		help="only use cached files, do not try to build anything")
	arg_parser.add_argument("-q", action="store_true")
	arg_parser.add_argument("-qq", action="store_true")
	arg_parser.add_argument("--hide-errors", action="store_true",
		help="display any errors encountered reading an asset")
	args = arg_parser.parse_args(sys.argv[1:])

	Echo.quiet = args.q
	Echo.very_quiet = args.qq
	Echo.hide_errors = args.hide_errors

	if os.path.isdir(args.input):
	    files = glob.glob(args.input + "/*.unity3d")
	else:
		files = [args.input]

	results = []
	search_term = args.search.lower()

	for file in files:
		file_name = filename_no_ext(file)
		# try and get the file from the cache
		cache = get_bundle_cache(args.cache, file_name)
		# if its not cached, created it or skip it
		if not cache:
			if args.cache_only:
				# if only interested in cached files, try the next file
				continue
			go_dict = {}
			with open(file, "rb") as f:
				bundle = unitypack.load(f)
			for asset in bundle.assets:
				asset_bundle_name = f"{file_name}/{asset.name}"
				# build the game object dict
				go_dict.update(build_dict(asset_bundle_name, asset))
			# skip this file if dict is empty
			if len(go_dict) <= 0:
				continue
			# save dict as file cache
			cache = go_dict
			save_bundle_cache(args.cache, file_name, cache)
		# search this file
		for name in cache.keys():
			if search_term in name:
				results.extend(cache[name])

	if (len(results) > 0):
		for r in results:
			print(f"{r.id:22} {r.bundle:<16}{r.name}")
	else:
		print(f"No Results for '{search_term}'")
Пример #24
0
def main():
    p = ArgumentParser()
    p.add_argument("bundles", nargs="+", type=FileType("rb"))
    p.add_argument("-o", "--outfile", nargs=1, type=FileType("wb"))
    p.add_argument("--dbf", nargs="?", type=FileType("r"))
    args = p.parse_args(sys.argv[1:])

    build = detect_build(args.bundles[0].name)

    carddefs = {}
    entities = {}
    textures = {}
    whitelist = [
        "cards.unity3d",
        "cards0.unity3d",
        "cards1.unity3d",
        "cards2.unity3d",
        "cardxml0.unity3d",
    ]

    for f in args.bundles:
        if os.path.basename(f.name) not in whitelist:
            f.close()
            continue
        bundle = unitypack.load(f)
        asset = bundle.assets[0]
        print("Processing %r" % (asset))
        for obj in asset.objects.values():
            if obj.type == "TextAsset":
                d = obj.read()
                if d.name in IGNORE_LOCALES:
                    continue
                if d.script.startswith("<CardDefs>"):
                    carddefs[d.name] = ElementTree.fromstring(d.script)
                elif d.script.startswith("<?xml "):
                    entities[d.name] = ElementTree.fromstring(d.script)
                else:
                    raise Exception("Bad TextAsset %r" % (d))
            elif obj.type in ("CardDef", "MonoScript"):
                d = obj.read()
                if "m_GameObject" not in d:
                    # We check for MonoScript because type checks through asset
                    # references does not return the real class name yet.
                    # This means we have to check for GameObject in the obj to
                    # make sure it's actually a card.
                    continue
                if d["m_GameObject"] is None:
                    print("Missing m_GameObject for %r" % (obj))
                    continue
                cardid = d["m_GameObject"].resolve().name
                if "m_PortraitTexture" in d:
                    ptr = d["m_PortraitTexture"]
                    if not ptr:
                        continue
                    try:
                        texture = ptr.resolve().name
                    except NotImplementedError:
                        texture = ""
                else:
                    texture = reverse_texture_path(
                        d.get("m_PortraitTexturePath", ""))
                if texture:
                    textures[cardid] = texture

    if carddefs:
        xml = merge_locale_assets(carddefs)
    else:
        xml = merge_card_assets(entities, build)

    hero_powers = {}
    if args.dbf:
        print("Processing DBF %r" % (args.dbf.name))
        dbfxml = ElementTree.parse(args.dbf)
        guids, hero_powers = load_dbf(dbfxml)

        clean_entourage_ids(xml, guids)

    if build < 6024:
        SHROUDED = "Can't be targeted by Spells or Hero Powers."
    else:
        SHROUDED = "Can't be targeted by spells or Hero Powers."

    SPARE_PART_RE = re.compile(r"PART_\d+")

    for entity in xml.findall("Entity"):
        id = entity.attrib["CardID"]
        description = entity.find("Tag[@enumID='184']/enUS")
        description = description.text if description is not None else ""

        # Clean up MasterPower whitespace
        power = entity.find("MasterPower")
        if power is not None:
            power.text = power.text.strip()
            if not power.text:
                entity.remove(power)

        overload = entity.find("Tag[@enumID='215']")
        if overload is not None:
            overload.attrib["value"] = str(guess_overload(description))

        spellpower = entity.find("Tag[@enumID='192']")
        if spellpower is not None:
            spellpower.attrib["value"] = str(guess_spellpower(description))
            spellpower.attrib["type"] = "Int"

        if SHROUDED in description:
            set_tag(entity,
                    GameTag.CANT_BE_TARGETED_BY_ABILITIES,
                    1,
                    type="Bool")
            set_tag(entity,
                    GameTag.CANT_BE_TARGETED_BY_HERO_POWERS,
                    1,
                    type="Bool")

        if "Can't attack." in description or "Can't Attack." in description:
            set_tag(entity, GameTag.CANT_ATTACK, 1, type="Bool")

        if SPARE_PART_RE.match(id):
            set_tag(entity, GameTag.SPARE_PART, 1, type="Bool")

        if id in textures:
            e = ElementTree.Element("Texture")
            e.text = textures[id]
            entity.append(e)

        if id in hero_powers:
            e = ElementTree.Element("HeroPower")
            e.attrib["cardID"] = hero_powers[id]
            entity.append(e)

    xml.attrib["build"] = str(build)

    print("Writing to %r" % (args.outfile[0].name))
    args.outfile[0].write(pretty_xml(xml))