def extract_info(src): textures = {} cards = {} for root, dirs, files in os.walk(src): for file_name in files: # generate file_path file_path = os.path.join(root, file_name) # load that file via UnityPy.load env = UnityPy.load(file_path) handle_asset(env, textures) # env = UnityPy.load(src) # handle_asset(env, textures) # handle_gameobject(env, cards) for root, dirs, files in os.walk(src): for file_name in files: # generate file_path file_path = os.path.join(root, file_name) # load that file via UnityPy.load env = UnityPy.load(file_path) handle_gameobject(env, cards) return cards, textures
def main(): # load the original japanese localisation src = os.path.join(root, "522608825") e = UnityPy.load(src) # iterate over all localisation assets for cont, obj in e.container.items(): # read the asset data data = obj.read() # get the localisation data script = json.loads(bytes( data.script)) # bytes wrapper to handle memoryview if hasattr(script, "infos"): continue print(data.name) # translate the localisation for entry in script["infos"]: entry["value"] = translate(entry["value"]) # overwrite the original data.script = json.dumps(script, ensure_ascii=False, indent=4).encode("utf8") # apply the changes data.save() # save the modified Bundle as file with open(os.path.join(root, "522608825_patched"), "wb") as f: f.write(e.file.save())
def processAsset(filePath): offset = {} indexTable = {} imageData = {} dataJson = {} baseName = os.path.basename(filePath) env = UnityPy.load(filePath) for obj in env.objects: data = obj.read() if str(data.type) == 'MonoBehaviour': tree = data.type_tree offset, indexTable = parseMono(tree) if str(data.type) == 'Texture2D': imageData[data.name] = data.image partsData = classifyFaceMouth(indexTable, baseName) dataJson['offset'] = offset dataJson['partsData'] = partsData os.makedirs(os.path.join(OUTPUT, baseName), exist_ok=True) with open(('%s\\%s\\data.json') % (OUTPUT, baseName), 'w', encoding='utf8') as f: json.dump(dataJson, f, indent=2, ensure_ascii=False) if baseName == '100007_01': imageData = loadNhaam(imageData) combineYCbCrA(imageData, baseName) for index in indexTable: combineYCbCrA(imageData, baseName, index, indexTable[index])
def load_files(self, assetfolder, assetnames): print("Loading assets..") paths = [] for f in assetnames: paths.append(os.path.join(assetfolder, f)) print(paths) self.env = UnityPy.load(*paths)
def main(): bf = Fake( signature="UnityFS", version=6, format=6, version_engine="2017.4.30f1", version_player="5.x.x", _class=BundleFile, files={}, ) # load default serialized file and prepare some variables for easier access to key objects env = UnityPy.load(SERIALIZED_PATH) sf = env.file # serialized file or_bp = list(sf.objects.values())[0].__dict__ # object data bf.files["serialized_file"] = sf sf.flags = 4 # remove all unnesessary stuff for key in list(sf.objects.keys()): del sf.objects[key] sf.externals = [] # add all files from DATA_PATH for root, dirs, files in os.walk(DATA_PATH): for f in files: fp = os.path.join(root, f) if f[:3] == "CAB": add_cab(bf, sf, root, f) else: add_object(sf, fp, or_bp) # save edited bundle open("bundle_edited.unity3d", "wb").write(bf.save())
def export_monobehaviours(asset_path: str, trees: dict): for r, d, fs in os.walk(asset_path): for f in fs: try: env = UnityPy.load(os.path.join(r, f)) except: continue for obj in env.objects: if obj.type == "MonoBehaviour": d = obj.read() if obj.serialized_type.nodes: tree = obj.read_typetree() else: if not d.m_Script: continue # RIP, no referenced script # can only dump raw script = d.m_Script.read() # on-demand solution without already dumped tree #nodes = generate_tree( # g, script.m_AssemblyName, script.m_ClassName, script.m_Namespace #) if script.m_ClassName not in trees: # class not found in known trees, # might have to add the classes of the other dlls continue nodes = FakeNode(**trees[script.m_ClassName]) tree = obj.read_typetree(nodes)
def test_sprite(): import UnityPy for f in os.listdir(SAMPLES): env = UnityPy.load(os.path.join(SAMPLES, f)) for obj in env.objects: if obj.type == "Sprite": obj.read().image.save("test.png")
def unpack(source_folder="arknights", destination_folder="arknights_extract"): import UnityPy for root, dirs, files in os.walk(source_folder): for file_name in files: file_path = os.path.join(root, file_name) env = UnityPy.load(file_path) for path, obj in env.container.items(): dest = os.path.join(destination_folder, *path.split("/")) os.makedirs(os.path.dirname(dest), exist_ok=True) dest, ext = os.path.splitext(dest) if obj.type.name in ["Texture2D", "Sprite"]: data = obj.read() dest = dest + ".png" data.image.save(dest) elif obj.type.name == "TextAsset": data = obj.read() dest = dest + ".txt" with open(dest, "wb") as f: f.write(bytes(data.script)) elif obj.type.name == "MonoBehaviour": if obj.serialized_type.nodes: tree = obj.read_typetree() dest = dest + ".json" with open(dest, "wt", encoding="utf8") as f: json.dump(tree, f, ensure_ascii=False, indent=4) else: data = obj.read() dest = dest + ".bin" with open(dest, "wb") as f: f.write(data.raw_data)
def test_audioclip(): import UnityPy import platform env = UnityPy.load(os.path.join(SAMPLES, "char_118_yuki.ab")) for obj in env.objects: if obj.type == "AudioClip": clip = obj.read() assert (len(clip.samples) == 1)
def test_texture2d(): for f in os.listdir(SAMPLES): env = UnityPy.load(os.path.join(SAMPLES, f)) for obj in env.objects: if obj.type == "Texture2D": data = obj.read() data.image.save("test.png") data.image = data.image.transpose(Image.ROTATE_90) data.save()
def loadNhaam(imageData): # missing Nhaam's base Y file env = UnityPy.load( INPUT + '\\assets._gluonresources.images.emotion.story.chara.100007_01.parts\\100007_01_base_y' ) for obj in env.objects: data = obj.read() if str(data.type) == 'Texture2D': imageData[data.name] = data.image return imageData
def test_mesh(): env = UnityPy.load(os.path.join(SAMPLES, "xinzexi_2_n_tex")) with open(os.path.join(SAMPLES, "xinzexi_2_n_tex_mesh"), "rb") as f: wanted = f.read().replace(b"\r", b"") for obj in env.objects: if obj.type == "Mesh": mesh = obj.read() data = mesh.export() if isinstance(data, str): data = data.encode("utf8").replace(b"\r", b"") assert data == wanted
def main(): p = ArgumentParser() p.add_argument("src") args = p.parse_args(sys.argv[1:]) for root, dirs, files in os.walk(args.src): for file_name in files: # generate file_path file_path = os.path.join(root, file_name) # load that file via UnityPy.load env = UnityPy.load(file_path) extract_assets(env)
def test_mesh(): env = UnityPy.load(os.path.join(SAMPLES, "xinzexi_2_n_tex")) with open(os.path.join(SAMPLES, 'xinzexi_2_n_tex_mesh'), 'rb') as f: wanted = f.read().replace(b'\r', b'') for obj in env.objects: if obj.type == "Mesh": mesh = obj.read() data = mesh.export() if isinstance(data, str): data = data.encode('utf8').replace(b'\r', b'') assert data == wanted
def extract_ref_objects(src): for root, dirs, files in os.walk(src): if len(nodes_to_parse) == local_state["total_handled"]: return for file_name in files: if len(nodes_to_parse) == local_state["total_handled"]: return # generate file_path file_path = os.path.join(root, file_name) # load that file via UnityPy.load env = UnityPy.load(file_path) handle_asset(env)
def extract_info(src): audioClips = {} cards = {} for root, dirs, files in os.walk(src): for file_name in files: # generate file_path file_path = os.path.join(root, file_name) # load that file via UnityPy.load env = UnityPy.load(file_path) handle_asset(env, audioClips, cards) for root, dirs, files in os.walk(src): for file_name in files: # generate file_path file_path = os.path.join(root, file_name) # load that file via UnityPy.load env = UnityPy.load(file_path) handle_gameobject(env, audioClips, cards) # if ("card" in bundle.path or "initial_base" in bundle.path) and ("cardtexture" not in bundle.path): return cards
def extract_img_assets(db, dat_path, output_path, query, skip_existing): if not output_path.exists(): os.makedirs(output_path) for name, size, h in db.execute(query): out_file_path = Path(output_path, name.split('/')[-1] + '.png') if skip_existing and out_file_path.exists(): continue ab = UnityPy.load(Path(dat_path, h[:2], h).as_posix()) for obj in ab.objects: if obj.type in [ClassIDType.Texture2D, ClassIDType.Sprite]: data = obj.read() img = data.image # TODO better filter if ('thumb' in data.name or 'tex' in data.name) and img.width == img.height: img = img.resize((int(img.width * 3 / 4), img.height)) img.save(out_file_path)
def extract_assets(src): # load source env = UnityPy.load(src) # iterate over assets for asset in env.assets: # assets without container / internal path will be ignored for now if not asset.container: continue # filter objects and put Texture2Ds at the end of the list objs = sorted( (obj for obj in asset.get_objects() if obj.type.name in TYPES), key=lambda x: 1 if x.type == "Texture2D" else 0) cobjs = sorted(((key, obj) for key, obj in asset.container.items() if obj.type.name in TYPES), key=lambda x: 1 if x[1].type == "Texture2D" else 0) # check which mode we will have to use num_cont = sum(cobjs) num_objs = len(objs) # check if container contains all important assets, if yes, just ignore the container if num_objs <= num_cont * 2: for asset_path, obj in cobjs: fp = os.path.join(DST, *asset_path.split('/')[IGNOR_DIR_COUNT:]) export_obj(obj, fp) # otherwise use the container to generate a path for the normal objects else: extracted = [] # find the most common path occurence_count = Counter( os.path.splitext(asset_path)[0] for asset_path in asset.container.keys()) local_path = os.path.join( DST, *occurence_count.most_common(1)[0][0].split('/') [IGNOR_DIR_COUNT:]) for obj in objs: if obj.path_id not in extracted: extracted.extend( export_obj(obj, local_path, append_name=True))
def main(): path = os.path.dirname(os.path.realpath(__file__)) f = open(os.path.join(path, "asset_index"), "rb") index = read_asset_index(f) blocks = os.path.join(path, "blocks_export") ext = os.path.join(path, "export") for root, dirs, files in os.walk(blocks): for fp in files: env = UnityPy.load(os.path.join(root, fp)) for ref, obj in env.container.items(): if "/" in ref: fp = os.path.join(ext, *ref.split("/")) else: try: fp = os.path.join(ext, *index[int(ref)].split("/")) except KeyError: print(ref) continue if not export_object(obj, fp, False): for obj in env.objects: export_object(obj, fp, True)
def fetch_segment_lines(segment: SegmentData): lines = [] if segment.kind is SegmentKind.TEXT: story_id = str(segment.id).zfill(9) storyline_name = f'storytimeline_{story_id}' storytimeline_path = Path(DATA_ROOT, 'story/data', story_id[:2], story_id[2:6], storyline_name) env = UnityPy.load(storytimeline_path.as_posix()) if not env.assets: raise FileNotFoundError(storytimeline_path) objects = {} timeline = None for obj in env.objects: if obj.type != ClassIDType.MonoBehaviour: continue if not timeline: obj_data = obj.read() if obj_data.name == storyline_name: timeline = obj_data continue objects[obj.path_id] = obj if not timeline: raise Exception( "storytimeline exists, but it's timeline is missing") for block in timeline.type_tree['BlockList']: for clip in block['TextTrack']['ClipList']: obj = objects[clip['m_PathID']] type_tree = obj.read().type_tree lines.append(LineData(type_tree['Name'], type_tree['Text'])) return lines
def extract_assets(src): # load source env = UnityPy.load(src) # iterate over assets for asset in env.assets: # assets without container / internal path will be ignored for now if not asset.container: continue # check which mode we will have to use num_cont = sum(1 for obj in asset.container.values() if obj.type in TYPES) num_objs = sum(1 for obj in asset.objects.values() if obj.type in TYPES) # check if container contains all important assets, if yes, just ignore the container if num_objs <= num_cont * 2: for asset_path, obj in asset.container.items(): fp = os.path.join(DST, *asset_path.split('/') [IGNOR_DIR_COUNT:]) export_obj(obj, fp) # otherwise use the container to generate a path for the normal objects else: extracted = [] # find the most common path occurence_count = Counter(os.path.splitext(asset_path)[ 0] for asset_path in asset.container.keys()) local_path = os.path.join( DST, *occurence_count.most_common(1)[0][0].split('/')[IGNOR_DIR_COUNT:]) for obj in asset.objects.values(): if obj.path_id not in extracted: extracted.extend(export_obj( obj, local_path, append_name=True))
def extract_assets( src: Union[Path, BytesIO, bytes, bytearray], dst: Path, use_container: bool = True, ignore_first_container_dirs: int = 0, append_path_id: bool = False, export_unknown_as_typetree: bool = False, ) -> List[int]: """Extracts all assets from the given source. Args: src (Union[Path, BytesIO, bytes, bytearray]): [description] dst (Path): [description] use_container (bool, optional): [description]. Defaults to True. ignore_first_container_dirs (int, optional): [description]. Defaults to 0. append_path_id (bool, optional): [description]. Defaults to False. export_unknown_as_typetree (bool, optional): [description]. Defaults to False. Returns: List[int]: [description] """ # load source env = UnityPy.load(src) exported = [] export_types_keys = list(EXPORT_TYPES.keys()) def defaulted_export_index(type: ClassIDType): try: return export_types_keys.index(type) except IndexError: return 999 if use_container: container = sorted(env.container, lambda x: defaulted_export_index(x[1].type)) for obj_path, obj in container: # the check of the various sub directories is required to avoid // in the path obj_dest = os.path.join( dst, *(x for x in obj_path.split("/")[:ignore_first_container_dirs] if x), ) os.makedirs(os.path.dirname(obj_dest), exist_ok=True) exported.extend( export_obj( obj, obj_dest, append_path_id=append_path_id, export_unknown_as_typetree=export_unknown_as_typetree, )) else: objects = sorted(env.objects, lambda x: defaulted_export_index(x.type)) for obj in objects: if obj.path_id not in exported: exported.extend( export_obj( obj, dst, append_name=True, append_path_id=append_path_id, export_unknown_as_typetree=export_unknown_as_typetree, )) return exported
ms = info['FileVersionMS'] ls = info['FileVersionLS'] return HIWORD(ms), LOWORD(ms), HIWORD(ls), LOWORD(ls) except: print( '[ERROR:] Failed to fetch EFT Client version! Does getPath.py & config.ini exist in your installation folder?' ) time.sleep(10) exit() return if __name__ == "__main__": ClientVersion = ".".join( [str(i) for i in get_version_number(config['DEFAULT']['clientpath'])]) UnityVersion = UnityPy.load( config['DEFAULT']['unitypath']).objects[0].assets_file.unity_version cookies = {} headers = { 'User-Agent': 'UnityPlayer/' + str(UnityVersion) + ' (UnityWebRequest/1.0, libcurl/7.52.0-DEV)', 'Content-Type': 'application/json', 'App-Version': 'EFT Client ' + str(ClientVersion), 'X-Unity-Version': str(UnityVersion) } print(' ▄') print(' ╓▀▀▄') print(' ╓▐▌▒█▒▌▀▀▄╖ ╓▀▀▀▀╢') print(' ┌▀▀▀▀▒█▌▄▄▐▄▀╠ ╓╢▀▀▀▀▀▀▄') print(' ╒╓▄▄▄▌██▌▐▒█▌▄▄▄ ╓╢▀▀▀▀▀▀▀▀▀')
def test_read_single(): for f in os.listdir(SAMPLES): env = UnityPy.load(os.path.join(SAMPLES, f)) for obj in env.objects: obj.read()
def test_read_batch(): env = UnityPy.load(SAMPLES) for obj in env.objects: obj.read()
def test_read_typetree(): env = UnityPy.load(SAMPLES) for obj in env.objects: obj.read_typetree()
import os import UnityPy from UnityPy.classes import MonoBehaviour, PPtr class ScriptableTexture2D(MonoBehaviour): def __init__(self, reader): # calls the default MonoBehaviour init super().__init__(reader=reader) # here goes the implementation of the extra data self.texture = PPtr(reader) # set the path for the target file root = os.path.dirname(os.path.realpath(__file__)) fp = os.path.join(root, "data.unity3d") env = UnityPy.load(fp) # find the correct asset for obj in env.objects: if obj.type == "MonoBehaviour": data = obj.read() if data.name == "ScriptableTexture2D": # correct obj found # lets read it with the custom class st = ScriptableTexture2D(obj) # read the linked image and save it tex = st.texture.read() print(st.texture.read().name) #tex.image.save(os.path.join(root, f"{tex.name}.png"))
import UnityPy env = UnityPy.load('data_processing/input/signatureabilities', 'data_processing/input/localization') for obj in env.objects: data = obj.read() if data.title == 'Char_Valentine_SUP_CombatClinic_Title': print(data.title) break obj = env.container[ 'assets/characters/valentine/signatureabilities/resources/sa_valentine_sup_combatclinic.prefab'] data = obj.read() tree = data.read_type_tree() tree.to_dict() env.assets['signatureabilities'] env.assets['signatureabilities']['CAB-33795db553e340f803b94491ed8d8bb8'].keys() env.assets['signatureabilities']['CAB-33795db553e340f803b94491ed8d8bb8'][ -4662963343376788019].read().read_type_tree().to_dict() env.assets['signatureabilities']['CAB-33795db553e340f803b94491ed8d8bb8'][ -9170200783047960356].read().read_type_tree().to_dict() env.assets['signatureabilities'].keys() env.objects data = obj.read() tree = data.read_type_tree() tree.to_dict() for obj in env.objects: