1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| #!/usr/bin/python3 # cocos2d-js资源还原 + 整理输出(忽略 .json 文件,递归 assets) import os import json import shutil import re
# ---------- UUID 解码表 ---------- i = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51] n = '0123456789abcdef' s = [0,1,2,3,4,5,6,7,9,10,11,12,14,15,16,17,19,20,21,22,24,25,26,27,28,29,30,31,32,33,34,35] a_template = ["", "", "", "", "", "", "", "", "-", "", "", "", "", "-", "", "", "", "", "-", "", "", "", "", "-", "", "", "", "", "", "", "", "", "", "", "", ""]
def decode_uuid(t): if len(t) != 22: return t a = a_template.copy() a[0] = t[0] a[1] = t[1] r = 2 for e in range(2, 22, 2): o = i[ord(t[e])] l = i[ord(t[e + 1])] a[s[r]] = n[o >> 2] a[s[r + 1]] = n[(3 & o) << 2 | l >> 4] a[s[r + 2]] = n[15 & l] r += 3 return ''.join(a)
# ---------- 匹配完整 UUID 格式 ---------- uuid_regex = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', re.IGNORECASE)
# ---------- 遍历 assets 下所有 cc.config*.json 文件 ---------- assets_root = "assets" config_files = [] for root, dirs, files in os.walk(assets_root): for file in files: if file.startswith("cc.config") and file.endswith(".json"): config_files.append(os.path.join(root, file))
print(f"找到 {len(config_files)} 个 cc.config.json 文件")
# ---------- 解析 UUID ---------- uuid_map = {} # {uuid: resource_path} for cfg_file in config_files: cfg = json.load(open(cfg_file, "r", encoding="utf-8")) uuids = cfg.get("uuids", []) paths = cfg.get("paths", {}) # 解码 uuids decoded_uuids = [decode_uuid(u) for u in uuids] for k, v in paths.items(): uuid_index = int(k) uuid = decoded_uuids[uuid_index] # 只保留完整 UUID if uuid_regex.match(uuid): resource_path = v[0] # 资源对应的路径名 uuid_map[uuid] = resource_path
print(f"解析出 {len(uuid_map)} 个有效 UUID")
# ---------- 遍历 assets 目录找到对应资源 ---------- found_count = 0 for root, dirs, files in os.walk(assets_root): for file in files: for uuid, resource_path in uuid_map.items(): uuid_compact = uuid.replace("-", "") if uuid_compact in file.replace("-", ""): # 忽略 .json 文件 if file.lower().endswith(".json"): continue src_file = os.path.join(root, file) final_ext = "".join(os.path.splitext(src_file)[1:]) # 支持多点扩展名 final_dir = os.path.join("output", os.path.dirname(resource_path)) os.makedirs(final_dir, exist_ok=True) final_path = os.path.join(final_dir, os.path.basename(resource_path) + final_ext)
# 重名文件加索引 if os.path.exists(final_path): index = 1 while True: new_final = os.path.join(final_dir, f"{os.path.basename(resource_path)}_{index}{final_ext}") if not os.path.exists(new_final): final_path = new_final break index += 1
shutil.copy(src_file, final_path) print(f"{resource_path:40} | {uuid} | {final_path}") found_count += 1 break # 一个文件对应一个 UUID
print(f"整理完成,共还原 {found_count} 个资源文件(忽略 .json 文件,无空目录)")
|