From 272f3bc14a0c64326978e59fa9b0b5fc653251fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9B=AE=E6=A3=83?= Date: Mon, 11 Nov 2024 11:59:38 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20=E6=B7=BB=E5=8A=A0UIGF4=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- docs/UIGF.md | 445 +++++++++++++++++++++++++++++++++++--------------- docs/UIGF3.md | 190 +++++++++++++++++++++ 3 files changed, 506 insertions(+), 135 deletions(-) create mode 100644 docs/UIGF3.md diff --git a/README.md b/README.md index 1e05bad0..2fb7e93c 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ Author: 目棃 Description: 说明文档 Date: 2023-03-05 -Update: 2024-10-31 +Update: 2024-11-11 --- > 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-03-05 14:41:55` > -> 更新于 `2024-10-31 17:39:57` +> 更新于 `2024-11-11 11:59:05` ![](https://img.shields.io/github/last-commit/BTMuli/TeyvatGuide?style=for-the-badge) ![](https://img.shields.io/github/commits-since/BTMuli/TeyvatGuide/latest?include_prereleases&style=for-the-badge) @@ -93,7 +93,7 @@ Game Tool for Genshin Impact player, supports Windows and macOS. - Changelog: [CHANGELOG](CHANGELOG.md) - 资源来源:[项目资源说明](docs/项目资源说明.md) - UIAF:[UIAF v1.1](docs/UIAF.md) -- UIGF:[UIGF v3.0](docs/UIGF.md) +- UIGF:[UIGF v3.0](docs/UIGF3.md),[UIGF v4.0](docs/UIGF.md) - [macOS 平台门禁属性导致应用无法打开应用的修复指引](docs/macos-gatekeeper/README.md) ## 特定项目 / Special Project diff --git a/docs/UIGF.md b/docs/UIGF.md index 6a079b64..27d28933 100644 --- a/docs/UIGF.md +++ b/docs/UIGF.md @@ -1,190 +1,371 @@ --- Author: 目棃 -Description: UIGF v2.4 Backup -Date: 2023-11-15 -Update: 2024-03-13 +Description: UIGF v4 Backup +Date: 2024-11-11 +Update: 2024-11-11 --- -> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-11-15 20:58:36` +> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-11-11 11:57:27` > -> 更新于 `2024-03-13 15:50:36` +> 更新于 `2024-11-11 11:57:27` -> 本文档为 [UIGF v3.0](https://github.com/UIGF-org/UIGF-org.github.io/blob/main/docs/zh/standards/UIGF.md) 的备份,仅供参考。 +> 本文档为 [UIGF v4.0](https://github.com/UIGF-org/UIGF-org.github.io/blob/main/docs/zh/standards/uigf.md) 的备份,仅供参考。 -# 统一可交换抽卡记录标准 v3.0 +# 统一可交换抽卡记录标准 v4.0 -> Uniformed Interchangeable GachaLog Format standard (UIGF) v3.0 -> -> ::: warning UIGF 标准使用声明 -> 应用必须在同时支持 UIGF 数据格式**导入**和**导出**功能并在相关功能区域或文档中提供跳转至 [UIGF-Org](https://uigf.org) 的超链接后声明支持 UIGF 格式 +> Uniformed Interchangeable GachaLog Format standard (UIGF) v4.0 -仅包含导入或导出功能降低了用户数据可流通性,且将数据至于用户不可控的风险中,不符合 UIGF-Org 设计的初衷。 +::: warning 中断性更新警告 +`UIGF v4.0 及更高版本` 对于 `UIGF v3.0 及更低版本` 和 `SRGF v1.0` **不具备向下兼容性**。UIGF/SRGF 合作项目如需适配,需重新认证。 ::: ## 更新记录 -| 版本 | 说明 | 兼容 | -| ----------------------------- | ---------------------------------------------------------- | -------------- | -| `v2.0` | 首个正式版本 | v2.0 | -| `v2.1` | 简化了部分语言表述,与 v2.0在数据格式上完全一致 | v2.1 and lower | -| [`v2.2`](UIGF-legacy-v2.2.md) | 新增 `info.export_timestamp` 填充 UNIX 时间戳 | v2.2 and lower | -| [`v2.3`](UIGF-legacy-v2.3.md) | 扩充至非中文语境,使用 Json Schema 表述。移除了 Excel 格式 | v2.3 and lower | -| [`v2.4`](UIGF-legacy-v2.4.md) | 新增 `info.region_time_zone` 支持时区处理 | v2.4 and lower | -| `v3.0` | 新增 集录祈愿类型支持 | v3.0 and lower | +| 版本 | 说明 | 兼容 | +| ------ | --------------------------------- | --------------- | +| `v3.0` | 低版本的更新日志请查看历史版本 | v3.0 及更低版本 | +| `v4.0` | 合并 SRGF,新增绝区零抽卡格式支持 | v4.0 | -### v3.0 更新内容 +## 前言 -- `gacha_type` 增加新枚举项 - - 在 `gacha_type` 枚举新增值为 `500` 的项,用于表示集录祈愿类型 +为了统一不同应用、不同游戏、不同账号间的抽卡记录导入导出行为,我们决定将所有支持的游戏抽卡格式合并入 UIGF 中。不同的游戏、不同的账号将能够以单个文件或字符串的形式进行表示,导入与导出操作对用户而言将变得史无前例的简单。 -## `info` 字段说明 +## 实现与认证 -### `region_time_zone` +实现 `UIGF v4.0 及更高版本`格式的导入导出并不意味着需要移除对 `UIGF v3.0 及更低版本`或 `SRGF v1.0` 的导入导出支持。但是,不建议对 `UIGF v4.0 和更高版本` 与 `UIGF v3.0 及更低版本`或 `SRGF v1.0` 使用同一套导入导出逻辑。 -由于在获取祈愿记录时得到的`time`为服务器时间,为了准确判断时间的时区偏移,引入此字段。 +导出方可以选择性地填充针对每个游戏的字段或直接忽略;导入方可以选择性地读取针对每个游戏的字段或直接忽略。 -与 SRGF 不同,由于无法直接从服务器获取`region_time_zone`,在导出方未提供此字段时,需要根据 `uid` 进行推断。 +针对对某一款游戏的支持,必须同时实现数据的导入和导出功能,否则将无法通过认证。 -#### 映射关系 +::: info UIGF 标准使用声明 +请在应用内提供跳转至 [UIGF-Org](https://uigf.org) 的超链接,声明支持 UIGF 数据格式。 -| `uid`首个字符 | `region_time_zone` | 游戏服务器 | -| ------------- | ------------------ | --------------------------------- | -| `'6'` | `-5` | os_usa | -| `'7'` | `1` | os_euro | -| 剩余情况 | `8` | os_cht, os_asia, cn_gf01, cn_qd01 | - -App 不应假定 `region_time_zone` 的值为上表中给出的值,应具有处理非标准 `region_time_zone` 值的能力。 -若 `region_time_zone` 的值与 `uid` 推断结果不一致,则优先选择 `region_time_zone` 给出的值。 - -## `list` 字段说明 - -### `id` - -物品内包含了一项较为特殊的字段: `id`,为原神官方 API 中包含的,代表每条抽卡记录唯一性的 `id`。App 导出 UIGF 时 - -- 需要确保每个物品都有一个有效的唯一 `id` -- 若有记录中不包含`id`,则应从下一个自带有效 `id` 的物品开始,为每条缺失`id`字段的数据补全`id`。 - 赋值数据向前(时间排序)依次递减,每次递减的值应保持为 `1` - -### `gacha_type` - -由于存在会共享保底与概率的卡池,所以需要一个额外的字段来界定 -我们在 `UIGF` 的所有格式中注入了 `uigf_gacha_type` 字段 -在导出到 `UIGF` 格式时需要注意添加对应的 `uigf_gacha_type` 字段 - -#### 映射关系 - -| `uigf_gacha_type` | `gacha_type` | -| ----------------- | -------------- | -| `100` | `100` | -| `200` | `200` | -| `301` | `301` or `400` | -| `302` | `302` | -| `500` | `500` | - -### `item_id` - -物品游戏内ID,你可以通过 [UIGF API](../API.md) 获取这一数据 +仅包含导入或导出功能降低了用户数据的流通性,且将数据置于用户不可控的风险中,不符合 UIGF-Org 设计的初衷。 +::: ## Json Schema -> UIGF-Org 提供[Json Schema](/schema/uigf.json) 用于验证 +> UIGF-Org 提供下述 Json Schema 以用于验证资料结构的正确性。 + +::: warning 注意字段类型 +开发者务必遵循 Schema 内定义的字段类型。使用错误的类型可能会导致其他由强类型编程语言编写的工具在解析 Json 文件时产生错误,进而导致数据转移失败。 + +为了避免这类问题,我们建议您针对 UIGF 格式设计专用的数据结构。同时,设计相关的单元测试以确保导入导出的一致性。 + +我们也提供 [UIGF 格式校验工具](https://schema.uigf.org/?schema=uigf)来帮助你校验 Json 文件。 +::: ```json { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "info": { "type": "object", "properties": { - "uid": { - "type": "string", - "title": "导出记录的 UID" - }, - "lang": { - "type": "string", - "title": "语言 languagecode2-country/regioncode2" - }, "export_timestamp": { - "type": "number", - "title": "导出 UNIX 时间戳(秒)" - }, - "export_time": { - "type": "string", - "title": "导出时间", - "description": "yyyy-MM-dd HH:mm:ss" + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ], + "description": "导出档案的时间戳,秒级" }, "export_app": { "type": "string", - "title": "导出 App 名称" + "description": "导出档案的 App 名称" }, "export_app_version": { "type": "string", - "title": "导出 App 版本" + "description": "导出档案的 App 版本" }, - "uigf_version": { + "version": { "type": "string", - "title": "UIGF 版本号", - "pattern": "v\\d+\\.\\d+" - }, - "region_time_zone": { - "type": "number", - "title": "区域时区偏移" + "pattern": "^v\\d+\\.\\d+$", + "description": "导出档案的 UIGF 版本号,格式为 'v{major}.{minor}',如 v4.0" } }, - "required": ["uid", "uigf_version"], - "title": "UIGF 导出信息" + "required": ["export_timestamp", "export_app", "export_app_version", "version"] }, - "list": { + "hk4e": { "type": "array", "items": { "type": "object", "properties": { - "uigf_gacha_type": { - "type": "string", - "title": "UIGF 卡池类型", - "description": "用于区分卡池类型不同,但卡池保底计算相同的物品" + "uid": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ], + "description": "UID" }, - "gacha_type": { - "type": "string", - "title": "卡池类型" + "timezone": { + "type": "integer", + "description": "时区偏移,由米哈游 API 返回,若与服务器时区不同请注意 list 中 time 的转换" }, - "item_id": { + "lang": { "type": "string", - "title": "物品的内部 ID" + "description": "语言代码", + "enum": [ + "de-de", + "en-us", + "es-es", + "fr-fr", + "id-id", + "it-it", + "ja-jp", + "ko-kr", + "pt-pt", + "ru-ru", + "th-th", + "tr-tr", + "vi-vn", + "zh-cn", + "zh-tw" + ] }, - "count": { - "type": "string", - "title": "个数,一般为1" - }, - "time": { - "type": "string", - "title": "获取物品的时间" - }, - "name": { - "type": "string", - "title": "物品名称" - }, - "item_type": { - "type": "string", - "title": "物品类型" - }, - "rank_type": { - "type": "string", - "title": "物品等级" - }, - "id": { - "type": "string", - "title": "记录内部 ID" + "list": { + "type": "array", + "items": { + "type": "object", + "properties": { + "uigf_gacha_type": { + "type": "string", + "description": "UIGF 卡池类型,用于区分卡池类型不同,但卡池保底计算相同的物品", + "enum": ["100", "200", "301", "302", "500"] + }, + "gacha_type": { + "type": "string", + "description": "卡池类型,米哈游 API 返回", + "enum": ["100", "200", "301", "302", "400", "500"] + }, + "item_id": { + "type": "string", + "description": "物品的内部 ID" + }, + "count": { + "type": "string", + "description": "物品个数,一般为1,米哈游 API 返回" + }, + "time": { + "type": "string", + "description": "抽取物品时对应时区(timezone)下的当地时间" + }, + "name": { + "type": "string", + "description": "物品名称,米哈游 API 返回" + }, + "item_type": { + "type": "string", + "description": "物品类型,米哈游 API 返回" + }, + "rank_type": { + "type": "string", + "description": "物品等级,米哈游 API 返回" + }, + "id": { + "type": "string", + "description": "记录内部 ID,米哈游 API 返回" + } + }, + "required": ["uigf_gacha_type", "gacha_type", "item_id", "time", "id"] + } } }, - "required": ["uigf_gacha_type", "gacha_type", "id", "item_id", "time"], - "title": "UIGF 物品" - }, - "title": "物品列表" + "required": ["uid", "timezone", "list"] + } + }, + "hkrpg": { + "type": "array", + "items": { + "type": "object", + "properties": { + "uid": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ], + "description": "UID" + }, + "timezone": { + "type": "integer", + "description": "时区偏移,由米哈游 API 返回,若与服务器时区不同请注意 list 中 time 的转换" + }, + "lang": { + "type": "string", + "description": "语言代码", + "enum": [ + "de-de", + "en-us", + "es-es", + "fr-fr", + "id-id", + "it-it", + "ja-jp", + "ko-kr", + "pt-pt", + "ru-ru", + "th-th", + "tr-tr", + "vi-vn", + "zh-cn", + "zh-tw" + ] + }, + "list": { + "type": "array", + "items": { + "type": "object", + "properties": { + "gacha_id": { + "type": "string", + "description": "卡池 Id" + }, + "gacha_type": { + "type": "string", + "description": "卡池类型", + "enum": ["1", "2", "11", "12"] + }, + "item_id": { + "type": "string", + "description": "物品的内部 ID" + }, + "count": { + "type": "string", + "description": "物品个数,一般为1,米哈游 API 返回" + }, + "time": { + "type": "string", + "description": "抽取物品时对应时区(timezone)下的当地时间" + }, + "name": { + "type": "string", + "description": "物品名称,米哈游 API 返回" + }, + "item_type": { + "type": "string", + "description": "物品类型,米哈游 API 返回" + }, + "rank_type": { + "type": "string", + "description": "物品等级,米哈游 API 返回" + }, + "id": { + "type": "string", + "description": "记录内部 ID,米哈游 API 返回" + } + }, + "required": ["gacha_type", "gacha_id", "time", "item_id", "id"] + } + } + }, + "required": ["uid", "timezone", "list"] + } + }, + "nap": { + "type": "array", + "items": { + "type": "object", + "properties": { + "uid": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ], + "description": "UID" + }, + "timezone": { + "type": "integer", + "description": "时区偏移,由米哈游 API 返回,若与服务器时区不同请注意 list 中 time 的转换" + }, + "lang": { + "type": "string", + "description": "语言代码", + "enum": [ + "de-de", + "en-us", + "es-es", + "fr-fr", + "id-id", + "it-it", + "ja-jp", + "ko-kr", + "pt-pt", + "ru-ru", + "th-th", + "tr-tr", + "vi-vn", + "zh-cn", + "zh-tw" + ] + }, + "list": { + "type": "array", + "items": { + "type": "object", + "properties": { + "gacha_id": { + "type": "string", + "description": "卡池 Id" + }, + "gacha_type": { + "type": "string", + "description": "卡池类型", + "enum": ["1", "2", "3", "5"] + }, + "item_id": { + "type": "string", + "description": "物品的内部 ID" + }, + "count": { + "type": "string", + "description": "物品个数,一般为1,米哈游 API 返回" + }, + "time": { + "type": "string", + "description": "抽取物品时对应时区(timezone)下的当地时间" + }, + "name": { + "type": "string", + "description": "物品名称,米哈游 API 返回" + }, + "item_type": { + "type": "string", + "description": "物品类型,米哈游 API 返回" + }, + "rank_type": { + "type": "string", + "description": "物品等级,米哈游 API 返回" + }, + "id": { + "type": "string", + "description": "记录内部 ID,米哈游 API 返回" + } + }, + "required": ["gacha_type", "item_id", "time", "id"] + } + } + }, + "required": ["uid", "timezone", "list"] + } } }, - "required": ["info", "list"], - "title": "UIGF 根对象" + "required": ["info"] } ``` diff --git a/docs/UIGF3.md b/docs/UIGF3.md new file mode 100644 index 00000000..4c7161e0 --- /dev/null +++ b/docs/UIGF3.md @@ -0,0 +1,190 @@ +--- +Author: 目棃 +Description: UIGF v3 Backup +Date: 2023-11-15 +Update: 2024-11-11 +--- + +> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-11-15 20:58:36` +> +> 更新于 `2024-11-11 11:56:11` + +> 本文档为 [UIGF v3.0](https://github.com/UIGF-org/UIGF-org.github.io/blob/main/docs/zh/standards/uigf-legacy-v3.0.md) 的备份,仅供参考。 + +# 统一可交换抽卡记录标准 v3.0 + +> Uniformed Interchangeable GachaLog Format standard (UIGF) v3.0 +> +> ::: warning UIGF 标准使用声明 +> 应用必须在同时支持 UIGF 数据格式**导入**和**导出**功能并在相关功能区域或文档中提供跳转至 [UIGF-Org](https://uigf.org) 的超链接后声明支持 UIGF 格式 + +仅包含导入或导出功能降低了用户数据可流通性,且将数据至于用户不可控的风险中,不符合 UIGF-Org 设计的初衷。 +::: + +## 更新记录 + +| 版本 | 说明 | 兼容 | +| ----------------------------- | ---------------------------------------------------------- | -------------- | +| `v2.0` | 首个正式版本 | v2.0 | +| `v2.1` | 简化了部分语言表述,与 v2.0在数据格式上完全一致 | v2.1 and lower | +| [`v2.2`](UIGF-legacy-v2.2.md) | 新增 `info.export_timestamp` 填充 UNIX 时间戳 | v2.2 and lower | +| [`v2.3`](UIGF-legacy-v2.3.md) | 扩充至非中文语境,使用 Json Schema 表述。移除了 Excel 格式 | v2.3 and lower | +| [`v2.4`](UIGF-legacy-v2.4.md) | 新增 `info.region_time_zone` 支持时区处理 | v2.4 and lower | +| `v3.0` | 新增 集录祈愿类型支持 | v3.0 and lower | + +### v3.0 更新内容 + +- `gacha_type` 增加新枚举项 + - 在 `gacha_type` 枚举新增值为 `500` 的项,用于表示集录祈愿类型 + +## `info` 字段说明 + +### `region_time_zone` + +由于在获取祈愿记录时得到的`time`为服务器时间,为了准确判断时间的时区偏移,引入此字段。 + +与 SRGF 不同,由于无法直接从服务器获取`region_time_zone`,在导出方未提供此字段时,需要根据 `uid` 进行推断。 + +#### 映射关系 + +| `uid`首个字符 | `region_time_zone` | 游戏服务器 | +| ------------- | ------------------ | --------------------------------- | +| `'6'` | `-5` | os_usa | +| `'7'` | `1` | os_euro | +| 剩余情况 | `8` | os_cht, os_asia, cn_gf01, cn_qd01 | + +App 不应假定 `region_time_zone` 的值为上表中给出的值,应具有处理非标准 `region_time_zone` 值的能力。 +若 `region_time_zone` 的值与 `uid` 推断结果不一致,则优先选择 `region_time_zone` 给出的值。 + +## `list` 字段说明 + +### `id` + +物品内包含了一项较为特殊的字段: `id`,为原神官方 API 中包含的,代表每条抽卡记录唯一性的 `id`。App 导出 UIGF 时 + +- 需要确保每个物品都有一个有效的唯一 `id` +- 若有记录中不包含`id`,则应从下一个自带有效 `id` 的物品开始,为每条缺失`id`字段的数据补全`id`。 + 赋值数据向前(时间排序)依次递减,每次递减的值应保持为 `1` + +### `gacha_type` + +由于存在会共享保底与概率的卡池,所以需要一个额外的字段来界定 +我们在 `UIGF` 的所有格式中注入了 `uigf_gacha_type` 字段 +在导出到 `UIGF` 格式时需要注意添加对应的 `uigf_gacha_type` 字段 + +#### 映射关系 + +| `uigf_gacha_type` | `gacha_type` | +| ----------------- | -------------- | +| `100` | `100` | +| `200` | `200` | +| `301` | `301` or `400` | +| `302` | `302` | +| `500` | `500` | + +### `item_id` + +物品游戏内ID,你可以通过 [UIGF API](../API.md) 获取这一数据 + +## Json Schema + +> UIGF-Org 提供[Json Schema](/schema/uigf.json) 用于验证 + +```json +{ + "type": "object", + "properties": { + "info": { + "type": "object", + "properties": { + "uid": { + "type": "string", + "title": "导出记录的 UID" + }, + "lang": { + "type": "string", + "title": "语言 languagecode2-country/regioncode2" + }, + "export_timestamp": { + "type": "number", + "title": "导出 UNIX 时间戳(秒)" + }, + "export_time": { + "type": "string", + "title": "导出时间", + "description": "yyyy-MM-dd HH:mm:ss" + }, + "export_app": { + "type": "string", + "title": "导出 App 名称" + }, + "export_app_version": { + "type": "string", + "title": "导出 App 版本" + }, + "uigf_version": { + "type": "string", + "title": "UIGF 版本号", + "pattern": "v\\d+\\.\\d+" + }, + "region_time_zone": { + "type": "number", + "title": "区域时区偏移" + } + }, + "required": ["uid", "uigf_version"], + "title": "UIGF 导出信息" + }, + "list": { + "type": "array", + "items": { + "type": "object", + "properties": { + "uigf_gacha_type": { + "type": "string", + "title": "UIGF 卡池类型", + "description": "用于区分卡池类型不同,但卡池保底计算相同的物品" + }, + "gacha_type": { + "type": "string", + "title": "卡池类型" + }, + "item_id": { + "type": "string", + "title": "物品的内部 ID" + }, + "count": { + "type": "string", + "title": "个数,一般为1" + }, + "time": { + "type": "string", + "title": "获取物品的时间" + }, + "name": { + "type": "string", + "title": "物品名称" + }, + "item_type": { + "type": "string", + "title": "物品类型" + }, + "rank_type": { + "type": "string", + "title": "物品等级" + }, + "id": { + "type": "string", + "title": "记录内部 ID" + } + }, + "required": ["uigf_gacha_type", "gacha_type", "id", "item_id", "time"], + "title": "UIGF 物品" + }, + "title": "物品列表" + } + }, + "required": ["info", "list"], + "title": "UIGF 根对象" +} +```