mirror of
https://github.com/Shu-Ying/farm_service.git
synced 2026-11-02 10:39:59 +08:00
115 lines
6.9 KiB
Markdown
115 lines
6.9 KiB
Markdown
# 作物目录独立维护与发布
|
||
|
||
`catalogue/source/` 是日常维护的正式来源,不再读取 Farm 仓库或旧作物库。
|
||
首次迁出保留 202 条作物的全部业务字段、768 张图片的原始字节及现有布局。
|
||
原 `assets.zip` 和小型 `land-soils.zip` 字节不变,旧迁移基线保持原样。
|
||
|
||
## 源目录
|
||
|
||
- `plants.json`:根对象仅含 `schema: 1` 和 `plants` 数组。
|
||
- `metadata.json`:维护画布、布局、定位、panel 等绘图配置;发布工具重建
|
||
`plants` 和 `images`,不要手工修改这两个生成字段。
|
||
- `images/<原 ZIP 路径>`:PNG/JPEG 等原始图片,每个文件对应同名 ZIP 成员。
|
||
- `land-soils.zip`:精确包含 `soil/红土地.png`、`soil/黑土地.png`、
|
||
`soil/金土地.png` 三张可解码图片。
|
||
|
||
作物 `id` 为永久编号,不能重排、复用、删除或更名。名称唯一且不超过
|
||
128 字符,不能为 `.`、`..` 或包含 `/`、`\`。数值仅允许 64 位有符号
|
||
范围内非负整数,`id`、`time`、`crop`、
|
||
`harvest` 必须为正;`time` 为小时,转换为秒仍须在范围内。
|
||
`level/buy/vipBuy/experience/price` 分别控制等级、种子普通币价格、点券价格、
|
||
经验和收获物售价。`isVip`、`isBuy` 和可选 `enabled` 仅允许 0 或 1;
|
||
可选 `crop_type` 默认为 1,只有类型 1 可新种植。
|
||
|
||
`phase` 为逗号分隔的正整数秒值,按首次出现去重后须严格递增且至少两项;
|
||
它与 `general/offsetH/offsetW/offsetX/offsetY` 一并生成展示元数据。
|
||
其他已有字段原样保留。图片原有缺图占位行为保留,但不能删除已经发布的
|
||
图片路径;新增作物应同时补充所需阶段图片。
|
||
|
||
发布工具独立校验完整展示契约:30 个地块位置、schema 4 作物放置、
|
||
面板字段及贴图、虫动画、六主题装饰、画布与图片尺寸,以及所有必需
|
||
背景和通用图片引用。schema 不接受布尔值,坐标不接受布尔值或非有限数。
|
||
|
||
## 编辑、检查、生成
|
||
|
||
需要 Python 3.10+ 和 Pillow;发布脚本不安装依赖、不访问网络或玩家数据库。
|
||
从本仓库根目录运行:
|
||
|
||
```text
|
||
python scripts/prepare_catalogue.py --source catalogue/source --output catalogue --version catalogue-20261026-1 --check
|
||
python -m unittest discover -s tests -p test_prepare_catalogue.py
|
||
```
|
||
|
||
`--check` 只读核对源与当前最新发布版本,源已修改时会拒绝,且不会生成
|
||
目录或替换清单。变更后先运行测试,再显式生成:
|
||
|
||
```text
|
||
python scripts/prepare_catalogue.py --source catalogue/source --output catalogue --version catalogue-20261027-1
|
||
python scripts/prepare_catalogue.py --source catalogue/source --output catalogue --version catalogue-20261027-1 --check
|
||
```
|
||
|
||
例如把已有条目的 `price` 改为新售价,或新增从未使用过的 ID;不要把
|
||
旧 ID 改成另一个作物。`isBuy=0` 表示禁售,`enabled=0` 禁止新购买和新播种。
|
||
生成时对照当前已校验版本,拒绝删除/更名旧 ID 或丢失已有图片路径。
|
||
|
||
产物位于 `catalogue/releases/<release>/`,包含清单和精确四个文件:
|
||
`plants.json`、`metadata.json`、`assets.zip`、`land-soils.zip`。
|
||
生成完整目录后,最后原子替换 `catalogue/manifest.json` 发现入口;失败
|
||
不会切换最新版本。已存在版本必须逐字节相同,不能原地覆盖。相同内容
|
||
重复生成须沿用相同版本标签;仅更换标签不能覆盖相同内容的历史清单。
|
||
已经发布的标签也不能用于内容不同的新版本,修改内容时必须使用新标签。
|
||
|
||
发布操作按输出目录同时使用进程内线程锁和系统文件锁,锁覆盖读取最新
|
||
版本、兼容性检查与最终替换,防止并发旧发布删除刚新增的 ID。系统锁在
|
||
进程退出时自动释放;`.publish.lock` 是应保留的空状态锁文件,不应删除,
|
||
仓库已忽略它。`--check` 保持只读,不创建或修改锁文件。
|
||
|
||
ZIP 使用固定成员顺序、2020-01-01 时间、Unix 0644 文件权限和 STORED 格式,
|
||
保留图片原始字节。输出不依赖文件修改时间或 Farm 相邻工作区。
|
||
临时 `.prepare-*` 目录不是有效发布版本,可在确认没有发布进程后清理。
|
||
|
||
## 清单协议与 HTTP
|
||
|
||
清单严格包含 `schema/version/release/files`:schema 固定 1;version 为
|
||
1~64 个字母数字或 `._-`;files 精确对应四文件,每项仅含正整数
|
||
`size_bytes` 和 64 位小写 `sha256`。release 为 files 对象经键排序、紧凑
|
||
UTF-8 JSON 序列化后的 SHA256,不接受 URL 或自定义路径。
|
||
|
||
清单最大 16 KiB;plants 2 MiB;metadata 4 MiB;各 ZIP 64 MiB;两个 ZIP
|
||
解压后图片总量不超过 256 MiB。源发布工具校验业务数据与图片,Rust 服务
|
||
启动校验各历史清单关系、文件大小和摘要;客户端也校验完整版本。
|
||
这些摘要检测不一致和损坏,不构成发布账号被接管时的真实性保证。
|
||
|
||
设置 `FARM_CATALOGUE_DIR=./catalogue` 后,服务启动加载最新清单及所有
|
||
历史版本为不可变内存快照:
|
||
|
||
| 接口 | 行为 |
|
||
|---|---|
|
||
| `GET /v1/catalogue/manifest.json` | 最新清单,`no-cache`,支持 ETag |
|
||
| `GET /v1/catalogue/releases/{release}/{file}` | 精确白名单四文件和该版本 `manifest.json`;一年 immutable 缓存,支持 ETag |
|
||
|
||
接口公开只读,不需要用户资料接口令牌。未配置目录时返回 503;未知版本
|
||
和文件返回 404;无效目录或摘要导致启动失败,并写入既有日志。
|
||
运行中不重读磁盘,发布后须重启 Service。旧素材/字体接口及用户资料鉴权
|
||
保持独立。所有历史版本都会驻留内存,部署前须按版本数量规划内存。
|
||
|
||
GitHub/Gitea 同样从本仓库 raw 根路径的 `catalogue/manifest.json` 和
|
||
`catalogue/releases/<release>/<file>` 获取相同字节。应先发布完整版本目录,
|
||
最后发布发现入口,保留历史版本;本工具仅准备本地文件,不执行提交、
|
||
推送或部署。真实远端下载与生产重启需在发布后另行验证。
|
||
|
||
## 重启生效与兼容回滚
|
||
|
||
机器人仅在启动时检查一次更新,同一次运行使用一个完整版本,失败优先
|
||
回退已校验缓存,再回退插件初始版本。若选定版本无法覆盖玩家已持有或
|
||
已种植的 ID,应拒绝业务初始化,恢复兼容版本后再启动,不能清空玩家数据。
|
||
|
||
新播种使用本次启动目录;已经播种的地块继续使用原结算快照。出售使用
|
||
当前目录售价,调价也会影响旧库存。回滚应从当前源发布一个新兼容版本:
|
||
恢复旧数值,但保留期间新增的全部 ID、名称及图片,需要下架时使用禁售/
|
||
禁播字段。不能把最新清单直接退回缺少新 ID 的老版本。
|
||
|
||
Farm 随包的轻量 bootstrap 由显式同步工具从本地完整 release 刷新,日常
|
||
Service 发布不要求同时改 Farm;三个机器人分发包继续不捆绑大型素材 ZIP。
|
||
字体保持独立发布,不纳入四文件目录版本。
|