- 106 动画 + 2366 表情包 + 语义标签 - 三层记忆 / 心情系统 / 9 可配置插件 / 10 技能 - DeepSeek 对话直连 + MCP/HTTP 接入 + 接入文档 - 动画随机链 + 物理引擎 + 贴边碰撞校准 - 大资源(动画webp/表情图)由 scripts/ 再生成,不入库
102 lines
3.3 KiB
Python
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'])) |