Files
mtfyun 7d2e8fed8e 小鲸娘 v1.0:悬浮宠物完整工程
- 106 动画 + 2366 表情包 + 语义标签
- 三层记忆 / 心情系统 / 9 可配置插件 / 10 技能
- DeepSeek 对话直连 + MCP/HTTP 接入 + 接入文档
- 动画随机链 + 物理引擎 + 贴边碰撞校准
- 大资源(动画webp/表情图)由 scripts/ 再生成,不入库
2026-11-08 08:07:09 +00:00

102 lines
3.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
从 dsh-pet 的 config.jsonc + anim_index.json 重建 config.json 的「动画」部分。
注意:本脚本只重建动画结构(idle/turn/drag/clicks/moves/categories/events),
不会动 memes 列表(表情包条目由 download_memes.py 维护,避免相互覆盖)。
因此它「读出旧 config 的 memes、写入新配置时原样保留」。
用法:
DSH_PET=/path/to/dsh-pet python3 scripts/gen_config.py
依赖:dsh-pet 的 assets/config.jsonc(动画定义)与 scripts/anim_index.json(名称→文件名)。
"""
import json
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(HERE)
DSH_PET = os.environ.get("DSH_PET", "/root/projects/.dsh/profiles/web/node_modules/dsh-pet")
CFG = os.path.join(DSH_PET, "assets", "config.jsonc")
IDX = os.path.join(HERE, "anim_index.json")
OUT = os.path.join(ROOT, "app", "src", "main", "assets_common", "config.json")
def strip_jsonc(t):
out = []
i, n, ins = 0, len(t), False
while i < n:
c = t[i]
if ins:
out.append(c)
if c == '\\' and i + 1 < n:
out.append(t[i + 1]); i += 2; continue
if c == '"':
ins = False
i += 1; continue
if c == '"':
ins = True; out.append(c); i += 1; continue
if c == '/' and i + 1 < n and t[i + 1] == '/':
while i < n and t[i] != '\n':
i += 1
continue
if c == '/' and i + 1 < n and t[i + 1] == '*':
i += 2
while i + 1 < n and not (t[i] == '*' and t[i + 1] == '/'):
i += 1
i += 2; continue
out.append(c); i += 1
return ''.join(out)
cfg = json.loads(strip_jsonc(open(CFG, encoding='utf-8').read()))
index = json.load(open(IDX, encoding='utf-8'))
by = {a['name']: a for a in index}
def to_list(names):
return [{'name': n, 'file': by[n]['file'], 'ms': by[n]['ms']} for n in names]
a = cfg['animations']
animations = {
'idle': to_list(a['idle']),
'turn': to_list(a['turn']),
'drag': to_list(a['drag']),
'clicks': to_list(a['clicks']),
'moves': {
'default': a['moves']['default'],
'actions': [
{'name': m['name'], 'params': m.get('params', {}),
'file': by[m['name']]['file'], 'ms': by[m['name']]['ms']}
for m in a['moves']['actions']
]
},
'categories': [
{'id': c['id'], 'weight': c['weight'], 'noMirror': c.get('noMirror', False),
'actions': to_list(c['actions'])}
for c in a['categories']
],
'events': {k: to_list(v) for k, v in a['events'].items()}
}
# 保留旧 config 的 memes(表情包条目不在本脚本维护范围)
old = {}
if os.path.exists(OUT):
old = json.load(open(OUT, encoding='utf-8'))
out = {
'version': 1,
'baseWidth': cfg['pets'][0]['size'],
'physics': cfg['physics'],
'font': cfg['font'],
'animationWeights': cfg['animationWeights'],
'animations': animations,
'index': index,
'fonts': old.get('fonts', {}),
'memes': old.get('memes', [])
}
json.dump(out, open(OUT, 'w', encoding='utf-8'), ensure_ascii=False, separators=(',', ':'))
print('wrote', OUT, '| index entries =', len(index), '| 保留 memes =', len(out['memes']))