Skip to content

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

GameHardLinkSwitcher

Warning

该项目几乎完全使用 DeepSeek V4 Pro 生成,使用材料:MeiBrowser,Reqable辅助

!全局替换某动漫游戏->Game
基于硬链接与全局 MD5 去重的游戏版本切换器——为某大厂动漫游戏提供秒级版本切换能力。(暂时只支持开放性大世界游戏)

核心原理

源文件 (E:\Game\xxx.dat)     ← 只读,绝不修改
    │ 硬链接 (零拷贝)
    ▼
缓存 (cache/{MD5})                    ← 全局去重,同 MD5 仅存一份
    │ 硬链接 (零拷贝)
    ▼
输出 (E:\Game-Switcher\6.5_CN\)    ← 逻辑视图,目录结构符合目标版本
  • 绝对不可变源:从不修改源目录任何字节
  • 全局 MD5 去重:不同版本/路径中相同内容的文件,物理存储仅一份
  • 硬链接农场:输出目录是纯硬链接集合,零额外磁盘占用

功能特性

功能 说明
同版本切换 本地 pkg_version 解析 → 纯硬链接(秒级)
跨版本切换 Sophon API 获取远程清单 → 缓存命中硬链接 → 差异文件 CDN 下载
版本差异诊断 --diagnose 对比任意两版本的文件 MD5 差异
并行下载 8 线程并发下载 chunk,tqdm 进度条
未压缩 chunk 检测 自动识别 chunkSize == chunkSizeDecompressed 的原始数据
跨盘回退 硬链接失败自动 shutil.copy2 + Warning
交互模式 无参数运行,逐步选择 版本 → 地区 → 语音包

项目结构

GameHardLinkSwitcher/
├── switcher.py          # CLI 入口(argparse + 交互模式)
├── parser.py            # ManifestParser — 解析本地 pkg_version (NDJSON)
├── manager.py           # ManifestManager — 清单加载/合并/枚举
├── cache.py             # CacheManager — MD5 缓存池 + 文件锁
├── linker.py            # LinkExecutor — 硬链接 + 跨盘回退复制
├── sophon.py            # SophonClient — Sophon API (protobuf manifest)
├── dispatch.py          # DispatchClient — GitHub hoyodata.json (NDJSON)
├── downloader.py        # Downloader — CDN chunk 并行下载
├── utils.py             # MD5 / 文件锁 / 格式化 / 常量
├── requirements.txt
├── cache/               # 运行时创建 — 全局 MD5 缓存池
├── manifests/           # 运行时创建 — JSON 清单仓库
│   ├── game/            #   游戏核心清单
│   └── voice/           #   语音包清单
└── outputs/             # 运行时创建 — 硬链接输出目录

安装

pip install -r requirements.txt

依赖:portalocker, requests, zstandard, protobuf, tqdm

使用方法

同版本切换(本地 pkg_version,秒级)

python switcher.py \
  --source "E:\Game_Impact" \
  --product "GameImpact" \
  --target-version "6.7" \
  --target-region "CN" \
  --target-voice "zh-cn" \
  --output "E:\Game-Switcher\GameImpact_6.7_CN" \
  --cache-root "E:\Game-Switcher\cache"

跨版本切换(Sophon API + CDN 下载)

# cache 已健全时可省略 --source
python switcher.py \
  --product "GameImpact" \
  --target-version "6.5" \
  --target-region "CN" \
  --target-voice "zh-cn" \
  --output "E:\Game-Switcher\GameImpact_6.5_CN" \
  --cache-root "E:\Game-Switcher\cache" \
  --download --insecure

诊断两版本差异

python switcher.py --diagnose \
  --diagnose-version-a "6.5" \
  --diagnose-version-b "6.6" \
  --insecure -v

输出示例:

  版本 6.5: 2468 文件
  版本 6.6: 2508 文件
  ─────────────────────────────
  相同 (MD5一致):  1200
  变更 (MD5不同):  1238
  仅 6.5 有: 30
  仅 6.6 有: 70

从 Sophon API 获取远程清单

python switcher.py --sophon-fetch \
  --target-version "6.5" \
  --target-region "CN" \
  --insecure

仅解析本地 pkg_version

python switcher.py --parse-only \
  --source "E:\Game_Impact"

交互模式(无参数)

python switcher.py

按提示选择:游戏目录 → 版本 → 地区 → 语音包 → 确认执行。

命令行参数

参数 说明 默认值
--source 游戏根目录(只读,cache 健全时可省略) 必填(除 --diagnose / --download)
--product 产品标识 GameImpact
--target-version 目标版本号 —
--target-region 目标地区 —
--target-voice 语音包语言代码 —
--output 输出目录 ./outputs/{Product}_{Version}_{Region}
--cache-root 缓存根目录 ./cache
--manifests-dir 清单目录 ./manifests
--download 启用 CDN 下载(跨版本切换必须) 关闭
--dispatch 使用 GitHub Dispatch 模式 关闭(默认 Sophon API)
--insecure 跳过 SSL 证书验证 关闭
--parse-only 仅解析本地,不构建 —
--sophon-fetch 从 API 获取远程清单 —
--diagnose 对比两版本差异 —
--diagnose-version-a 对比版本 A —
--diagnose-version-b 对比版本 B —
-v / --verbose 详细日志 关闭

数据流

同版本切换

pkg_version (NDJSON) → parser.py → manifests/xxx.json
                                    ↓
                              manager.py 加载
                                    ↓
        源文件 → cache.py (硬链接) → linker.py (硬链接) → 输出

跨版本切换

Sophon API → getGameBranches → getBuild(tag=6.5.0)
                                    ↓
                          protobuf manifest (Zstd)
                                    ↓
                          sophon.py 解析 → files[]
                                    ↓
        缓存命中 → linker.py 硬链接
        缓存未命中 → downloader.py → CDN chunk 并行下载 → 入缓存 → 硬链接

存储结构

{Project_Root}/
├── cache/                              # MD5 缓存池(全局去重)
│   ├── a1b2c3d4e5f6...                # 文件名 = MD5(无扩展名)
│   └── ...
├── manifests/
│   ├── game/
│   │   ├── GameImpact_6.6_CN.json   # Sophon 获取的远程清单
│   │   └── GameImpact_local_local.json  # 本地 pkg_version
│   └── voice/
│       └── GameImpact_6.6_CN_zh-cn.json
└── outputs/
    └── GameImpact_6.5_CN_zh-cn/     # 硬链接农场(目录结构完整)

容错策略

场景 处理
跨盘硬链接失败 捕获 OSError → shutil.copy2 + Warning
目标路径不存在 os.makedirs 递归创建父目录
下载中断/校验失败 删除临时文件,重试 3 次
并发写缓存 portalocker 文件锁
SSL 证书错误 --insecure 跳过验证
未压缩 chunk chunkSize == chunkSizeDecompressed 自动检测

验收标准

  • 同版本切换:2750 文件 100% 硬链接,秒级完成
  • fsutil hardlink list 确认多路径共享同一 inode
  • 源目录 E:\Game_Impact 无任何写入
  • 缓存 cache/ 中无重复 MD5 文件
  • 6.5 ↔ 6.6 版本差异诊断:1238 文件变更

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages