Ero-Lab部分游戏资源下载脚本

开了也下不了 换俩了 没屏蔽ip的可以下

童話邊境Hspine資源建議只跑新的就好了

舊的Hspine資源建議去找舊的拆包佬的 (有需要我能幫傳 只是我也忘了哪邊開始馬賽克- -…)

現在所有資源都上了馬賽克 (2024以前記得都沒上) (h spine 相關文件 網址 前面都有 still ex:
exlink.txt.zip (87 字节)
這是電腦版的 Android版鏈結不同 )

(這遊戲鑒權在H文本之類的,CG類會解密一直沒很難搞,他也沒弄sha256之類的處理 範例:妖聲和神姬)

(不過號碼我是不太會猜 因為不知道目錄文本在哪 舉例有7XXXX類的 主線 挑戰 的靜態類H都會是特殊數字 )

(這遊戲spine 還分拆了 需要組合再一起 … 很早期 紳士有大佬合併 百度吧後來似乎也有人併 在某佬沒引退前也有他幫併的viewer 地下也有大佬弄得不用併就能跑的viewer 不過被人 盜 賣 了… 不是超熟人也弄不到了吧)

題外抱怨一下 該遊戲營運地方的碼規定 放課後 和 已倒的海賊 都能碼上加碼 真的是越來越嚴格…

http://156.226.180.251:715/resdownloader.exe
2025 06 19 19:30(UTC + 8)
1.26更新
1.26 新增功能:修复了一些已知问题
新增对EroLab - 幻能边境 资源下载支持
新增对dmm童话边境提供解密和仅HSpine下载功能
本体更新检测将独立为一个功能

2 个赞

屏蔽中国ip的如果你的梯子是ssr/v2ay/小猫这种
你要知道你的代理地址(比如http://127.0.0.1:8000)然后填入代理设置中这样下载器才会走代理

2 个赞

Gofile - Cloud Storage Made Simple

含大多舊版的童話前線asset數據包

感谢
我那个下下来有6GB你这个5GB保有量确实多:+1:

1 个赞

V1.27
添加对E服红尘问仙的资源下载支持
注意安装包和图片由于是测试版并没有使用动态实时获取游戏名和图标
是固定了url,如出现apk无法下载自行打开https://game.ero-labs.cool/api/v2/closedBeta/singleClosedBeta/10?lang=cn查看


目前该游戏版本为

0.8.5
感谢@luojun1的支持

1 个赞



用的clash,全局代理tun模式,设置代理地址好像也不行,不显示图标

tun和代理只能设置一个建议tun代理的话真的一堆问题

image
解决了,这两个打开就可以了,开启后,软件的代理服务器设置也要关掉

一个字 绝

大佬,童话边境的分开显示的骨骼可以合并成一个吗





兄弟,你是咋弄的,我按你前面发的那个弄了还是不行 :sob:

选择一个好节点 然后开全局和tun就ok

請求GPT編寫的
將 [童話邊境] 過濾子資料夾名稱內的json、atlas分別依照流水號合併
以防重複執行python時將產出的檔案列入合併

於同目錄產出 子資料夾名稱,json 子資料夾名稱.atlas

僅少數資料夾內部有無流水號檔案被排在最後導致圖層問題
xxx2,json
xxx3.json
xxx.json
手動在json、png、atlas的xxx後方加上數字1並編輯atlas內png指定

有些檔案結構是_s1~_s10、_1~_20、xxx~xxx14等等
有時排序會變成1、10、2、3…這樣
所以只用自然數排序,若產出圖層上下錯位,在自動加上流水號即可

目前只測試童話邊境的json,其他遊戲零碎的spine json或許可以但可能有BUG

不支援skel
!!注意!!產出檔案會=資料夾名稱.json 需合併檔案名稱請避開同資料夾名,或更改資料夾名稱,以防覆蓋 (童話邊境沒這問題,僅其他遊戲)

圖片
skeletonViewer-3.6.53.jar直接執行 資料夾名.json 即可播放

250624-修復了一些BUG

  • dict 合併只合併 key/value
  • list 合併使用 .extend()
  • 不會將 dict 誤當 list
  • 跳過無效 JSON 檔案


經測試大部分都可正常運作
僅類似以下magicmirror.json這種後面無數字的還是會被排到最後

螢幕擷取畫面 2025-06-24 235337

import os
import json
import re

def custom_sort_key(filename):
    name = os.path.splitext(filename)[0]
    match = re.match(r'^(.*?)(?:[_-]?([a-zA-Z]?\d+))?$', name)
    base = match.group(1)
    suffix = match.group(2)
    if suffix is None:
        return (base, '', 0)
    match_suffix = re.match(r'([a-zA-Z]*)(\d+)', suffix)
    if match_suffix:
        prefix = match_suffix.group(1)
        number = int(match_suffix.group(2))
    else:
        prefix = ''
        number = 0
    return (base, prefix, number)

def custom_sort(files):
    return sorted(files, key=custom_sort_key)

def merge_json_files(json_paths):
    merged = {
        "skeleton": None,
        "bones": [],
        "slots": [],
        "skins": {"default": {}},
        "animations": {},
        "ik": [],
        "transform": [],
        "path": []
    }

    seen = {k: set() for k in ["bones", "slots", "ik", "transform", "path"]}
    skin_default = merged["skins"]["default"]

    for path in json_paths:
        with open(path, 'r', encoding='utf-8') as f:
            try:
                data = json.load(f)
            except json.JSONDecodeError as e:
                print(f"⚠ 跳過無效 JSON 檔案:{path},錯誤:{e}")
                continue

        if (not merged["skeleton"] or "spine" not in merged["skeleton"]) and "skeleton" in data:
            s = data["skeleton"]
            if "spine" in s and "hash" in s:
                merged["skeleton"] = s

        for bone in data.get("bones", []):
            if bone["name"] not in seen["bones"]:
                merged["bones"].append(bone)
                seen["bones"].add(bone["name"])

        for slot in data.get("slots", []):
            if slot["name"] not in seen["slots"]:
                merged["slots"].append(slot)
                seen["slots"].add(slot["name"])

        for slot_name, attachments in data.get("skins", {}).get("default", {}).items():
            if slot_name not in skin_default:
                skin_default[slot_name] = attachments
            else:
                for attach_name, value in attachments.items():
                    if attach_name not in skin_default[slot_name]:
                        skin_default[slot_name][attach_name] = value

        for key in ["ik", "transform", "path"]:
            for item in data.get(key, []):
                name = item.get("name")
                if name and name not in seen[key]:
                    merged[key].append(item)
                    seen[key].add(name)

    return merged, seen["bones"], seen["slots"]

def is_valid_animation(anim_data, valid_bones, valid_slots):
    if not anim_data or not isinstance(anim_data, dict):
        return False
    if all(not v for v in anim_data.values()):
        return False

    for bone in anim_data.get("bones", {}):
        if bone not in valid_bones:
            return False
    for slot in anim_data.get("slots", {}):
        if slot not in valid_slots:
            return False
    for deform_skin in anim_data.get("deform", {}):
        for slot in anim_data["deform"][deform_skin]:
            if slot not in valid_slots:
                return False
    if "events" in anim_data and not isinstance(anim_data["events"], list):
        return False
    return True

def merge_animation_data(base, addon):
    for section in ["bones", "slots", "deform", "ik", "transform", "drawOrder", "events"]:
        if section not in addon:
            continue

        if isinstance(addon[section], dict):
            if section not in base:
                base[section] = {}
            for key, value in addon[section].items():
                if key not in base[section]:
                    base[section][key] = value
                else:
                    if isinstance(base[section][key], list) and isinstance(value, list):
                        base[section][key].extend(value)
        elif isinstance(addon[section], list):
            if section not in base or not isinstance(base[section], list):
                base[section] = []
            base[section].extend(addon[section])

def extract_animations(json_paths, valid_bones, valid_slots):
    animations = {}
    for path in json_paths:
        with open(path, 'r', encoding='utf-8') as f:
            try:
                data = json.load(f)
            except json.JSONDecodeError as e:
                print(f"⚠ 跳過動畫解析失敗檔案:{path},錯誤:{e}")
                continue

        for anim_name, anim_data in data.get("animations", {}).items():
            if not is_valid_animation(anim_data, valid_bones, valid_slots):
                print(f"⚠ 跳過無效動畫: {anim_name}")
                continue
            if anim_name not in animations:
                animations[anim_name] = anim_data
            else:
                merge_animation_data(animations[anim_name], anim_data)
    return animations

def merge_atlas_files(atlas_paths):
    contents = []
    for path in atlas_paths:
        with open(path, 'r', encoding='utf-8') as f:
            text = f.read().strip()
            if text:
                contents.append(text)
    return '\n\n'.join(contents)

def process_all_subfolders(root_dir):
    for folder in os.listdir(root_dir):
        folder_path = os.path.join(root_dir, folder)
        if not os.path.isdir(folder_path):
            continue

        target_json = f"{folder}.json"
        target_atlas = f"{folder}.atlas"

        json_files = [f for f in os.listdir(folder_path) if f.endswith('.json') and f != target_json]
        json_files = custom_sort(json_files)
        json_list = [os.path.join(folder_path, f) for f in json_files]

        main_json = os.path.join(folder_path, target_json)
        if os.path.exists(main_json):
            json_list.insert(0, main_json)

        atlas_files = [f for f in os.listdir(folder_path) if f.endswith('.atlas') and f != target_atlas]
        atlas_files = custom_sort(atlas_files)
        atlas_list = [os.path.join(folder_path, f) for f in atlas_files]

        if json_list:
            merged_json, valid_bones, valid_slots = merge_json_files(json_list)
            merged_json["animations"] = extract_animations(json_list, valid_bones, valid_slots)

            out_json = os.path.join(folder_path, target_json)
            with open(out_json, 'w', encoding='utf-8') as f:
                json.dump(merged_json, f, ensure_ascii=False, indent=2)
            print(f"✅ JSON 合併完成:{out_json}")

        if atlas_list:
            merged_atlas = merge_atlas_files(atlas_list)
            out_atlas = os.path.join(folder_path, target_atlas)
            with open(out_atlas, 'w', encoding='utf-8') as f:
                f.write(merged_atlas)
            print(f"✅ ATLAS 合併完成:{out_atlas}")

# ▶ 修改為你的實際根資料夾(如 'Spine-merge')
process_all_subfolders("Spine-merge")
1 个赞

UTC +8 2025/6/26 18:50
V1.28更新
新增对Heavy Metal Babes的资源下载支持

2 个赞

大佬,绅士冒险马上7.31停服了,能搞个脚本吗?

url

很久沒更新的遊戲了 tps://nidg.bhjsj8.com/new_patch/files/index.txt.852550fed47ae553edf7e3b66c935678

ttps://nidg.bhjsj8.com/new_patch/files/assets_resources_honly_baseassets_uiprefabs_simpleprefab_img_hcg_e001_01_hcg1_2.7fa8c079dd7

ttps://www.sbkjl.com/game_list.html

ttps://www.sbkjl.com/game.html?id=1

櫻境和這款除了加密其實差不多 (紳士冒險沒有加密)

nutaku版叫 Lusty Odyssey 已經收了