Stewared/MiiJS
GitHub: Stewared/MiiJS
MiiJS 是一个综合 JavaScript 库,用于解决任天堂 Mii 角色数据在不同设备和格式间的读取、写入、转换和渲染问题。
Stars: 22 | Forks: 3
# MiiJS
MiiJS 是一个功能全面的 JavaScript 库,用于读取、写入、转换和渲染 Nintendo Mii 数据。
支持 Wii、DS、3DS、Wii U、Switch、Switch 2、Amiibo、Tomodachi Life、Miitomo、二维码、Studio 代码、特殊 Mii 以及几乎每一种已知的 Mii 格式。
一次构建,即可处理来自任何游戏机的 Mii。
为网站 [https://infinimii.com/](InfiniMii) 提供支持,该网站允许您通过图形用户界面完成 MiiJS 的所有功能。
*渲染功能由 [FFL.js](https://github.com/ariankordi/FFL.js/) 驱动*
## 安装说明
MiiJS 可在浏览器和 Node.js 中运行,同时支持 ESM 和 CJS 模块格式。
### Node
`npm install miijs` || `npm i miijs`
- `import MiiJS from "miijs";`
- `import {Mii} from "miijs";`
- `const MiiJS = require("miijs");`
- `const {Mii} = require("miijs");`
### 浏览器
下载最新的发布压缩包,并以您喜欢的方式提供解压后的文件,将路径替换为您的相关路径。
```
```
### 构建
仅在开发本地更改以支持 CJS 和/或浏览器环境时才需要构建,此时只需运行 `npm run build`。
## 使用示例
```
import fs from "fs";
import {Mii, ConsoleFormats, MiiFormats, makeMiiChild, kidomatic, miiHeightToMeasurements, miiWeightToMeasurements, imperialHeightWeightToMiiWeight, centimetersToMiiHeight} from "miijs";
//Manipulation
let JohnDoe = await Mii.create("./JohnDoe.charinfo");//Initialize JohnDoe.charinfo from the FS into the Mii class
JohnDoe.fields.meta.type="Special";//Modify fields as necessary
JohnDoe.set("name","Johnny");//Modify fields by friendly human name
JohnDoe.set({meta:{creatorName:"John Sr."}});//Modify fields by an object
await JohnDoe.setAs(ConsoleFormats["3DS"],"hair.type",[9,1,2]);//Set the hairstyle to the one that is, if you were on 3DS (or Wii U), on the 9th page, 1 from the left, 2 from the top. For non paginated values, only two values are necessary. Friendly human names also available.
await JohnDoe.getAs(ConsoleFormats.WII,"hair.type");//Return the friendly name as if viewing from a Wii, same as setAs. Friendly human names also available.
//Writing
fs.writeFileSync("./JohnDoe.rsd", JohnDoe.encode(MiiFormats.RSD));//Backport and write a Wii file for use on Wiimotes (.mii is the widely known name, but not advised for use)
fs.writeFileSync("./John.json",JSON.stringify(JohnDoe.toJSON(),null,4));//Write the representation of fields MiiJS is using for JohnDoe to a JSON file
console.log(JohnDoe);//Mii.toString() will automatically encode as an MNMS/Studio Code string, you can call JohnDoe.toString(MiiFormats.FORMAT) to get a hex string for a different format
const JohnImg = await JohnDoe.render();//Return a buffer containing an image of the Mii
fs.writeFileSync(`./JohnnysFace.png`,JohnImg);
const JohnQR = await JohnDoe.toQR();//Return a buffer containing an image of the Mii QR.
fs.writeFileSync(`./JohhnysQR.png`,JohnQR);
//Instruction Generation
const instrs=await JohnDoe.toInstructions(ConsoleFormats.DS);//Make a JSON object of the Mii, with human friendly instructions to recreate on that console, backporting if necessary (DS editor in this case is treated as Tomodachi Collection)
console.log(instrs.hair.type);//Human friendly text for how to find the hair type, in this case, on the DS editor
fs.writeFileSync("./JohnInstrs.txt",JSON.stringify(instrs,null,4));//Write a file with the JSON instructions
fs.writeFileSync("./JohnInstrs.json",JSON.stringify(instrs,null,4));
//Amiibo Manipulation
let exampleAmiibo = fs.readFileSync("./Amiibo.ntag");
let miiOnAmiibo = await Mii.create(exampleAmiibo);//Automatically detect as Amiibo and extract Mii from it
exampleAmiibo = await JohnDoe.insertIntoAmiibo(exampleAmiibo);//Insert into the Amiibo, return the buffer
fs.writeFileSync(`./JohnOnAmiibo.ntag`,exampleAmiibo);//Write a new Amiibo file back
//Other Functions
//Kidomatic
const kidStages = await kidomatic(JohnDoe);//Returns an array with six stages of life represented as raw JSON for the provided Mii.
let toddlerJohn = await Mii.create(kidStages[1]);
console.log(toddlerJohn.fields.meta.name);
//Baby
const child = await makeMiiChild(miiOnAmiibo, JohnDoe);//Returns an array with six stages of life represented as raw JSON for the generated baby.
let newborn = await Mii.create(child[0]);
let fullGrown = await Mii.create(child[5]);
console.log(fullGrown.fields.meta.name);
// Height/Weight Conversion
console.log((await miiHeightToMeasurements(JohnDoe.fields.general.height)).totalInches);//Returns a JSON object with various human measurements (imperial, metric) converted from Mii measurements
console.log((await miiWeightToMeasurements(JohnDoe.fields.general.height)).pounds);
JohnDoe.set("weight", await imperialHeightWeightToMiiWeight(70, 150));//Set JohnDoe's Weight to a good Mii weight for a person who's 5'10" (70 inches), and 150lbs (metric version also available).
JohnDoe.set("height", await centimetersToMiiHeight(175));//Set JohnDoe's Height to a good Mii height for a person who's 175cm (imperial version also available).
```
### 枚举类型
- MiiFormats | 所有可用于解码和编码的 Mii 格式的枚举。
- ConsoleFormats | 所有游戏机类型的枚举,适用于需要特定游戏机(如 getAs/setAs、说明)的函数。
- FFLExpression | Mii 面部可渲染的不同表情类型的枚举。由 FFL.js(见致谢)传递,MiiJS 依赖它进行渲染。
- FavoriteColors | Mii 喜爱颜色 ID 的人类可读名称数组。
## 完整的函数/变量列表
路径可以是 `meta.name` 或仅仅是 `name`。对于 `hairType` 或 `hair.type` 等。要获取所有可能的友好名称完整列表,请运行 `Object.keys(mappings).filter(a=>mappings[a]!=="SKIP").join(", ")`(我会将输出放在这里,但它非常庞大,而这篇 README 已经很长了)。
控制台 (Console) 在所有情况下都将是 ConsoleFormats 中的一个。
格式 (Format) 在所有情况下都将是 MiiFormats 中的一个。
调试值 (Debug) 启用额外日志记录,以帮助确定某物为何中断以及中断位置。
- Mii
- new Mii(anyKnownWayToRepresentAMii) | 此方法无法用于搜索 URL 或文件路径,其他方面与 Mii.create 相同。
- async Mii.create(anyKnownWayToRepresentAMii) | 自动从几乎任何有效的 Mii 中检测其格式,并将其读取到 Mii 对象中。
- Mii.toString(format) | 与 Mii.encode 相同,但返回十六进制字符串。
- Mii.toBuffer(format) | 与 Mii.encode 相同,用于某些函数的自动编码,推荐使用 Mii.encode。
- Mii.toJSON() | 返回 Mii.fields。
- Mii.set(objOrPath, value) | `Mii.set({meta:{name:"RickAstley"}})`、`Mii.set("name", "RickAstley")` 和 `Mii.set("meta.name", "RickAstley")` 都会执行相同的操作。
- Mii.get(path) | 返回值。
- async Mii.setAs(console, path, value) | 设置方式类似于在该游戏机的 Mii 制作器中选择一项,value 是 [page, countFromTheLeft, countFromTheTop] 或 [countFromTheLeft, countFromTheTop]。
- async Mii.getAs(console, path) | 获取值的方式类似于在该游戏机的 Mii 制作器中查看某项,返回值参见 setAs。
- Mii.encode(format) | 将 Mii 编码为指定的二进制格式。仅为可选的异步编码器(如加密二维码格式)返回 Promise。
- async Mii.toQR(options) | 返回一个包含该 Mii 二维码的缓冲区,可由 3DS 或 Wii U 扫描。如果 FFLResHigh.dat 存在,则将 Mii 渲染为二维码的图标。
- 选项值包括:size(分辨率)、image(使用的图标)、noRenderMii(设为 true 则不渲染 Mii 图标)、label(使用的标签文本,替代 Mii 名称)。以及来自 [qr-code-styling](https://github.com/kozakdenys/qr-code-styling) 的额外透传选项:qrOptions、dotsOptions、cornersSquareOptions、cornersDotsOptions、backgroundOptions。更多可用选项参见 Mii.render。
- async Mii.render(fullBodyRender, options) | 返回一个包含该 Mii 渲染图像的缓冲区,前提是项目目录中存在 FFLResHigh.dat。
- 选项值包括:fullBody(渲染 Mii 的全身而非仅头部)、expression(FFLExpression)、size(图像大小)。bodyPath(用于身体模型的路径,替代默认值)。fflResBuffer(包含 FFL 资源的缓冲区)。fflResPath(FFL 资源位置的路径)。
- async Mii.insertIntoAmiibo(amiiboDump) | 提供一个包含原始标签数据的 Amiibo 缓冲区,此函数将返回一个插入了您的 Mii 的相同 Amiibo。
- async Mii.toInstructions(console) | 提供一个包含人类可读句子和操作说明的 JSON 对象,用于在该游戏机上重现该 Mii。
- async insertMiiIntoAmiibo(amiiboDump, mii) | 参见 Mii.insertIntoAmiibo。
- async extractMiiFromAmiibo(amiiboDump) | 返回 Amiibo 内部的 Mii 二进制数据,然后可使用任何提供的解码函数进行解码。
- MiiFormats | 参见枚举类型。
- ConsoleFormats | 参见枚举类型。
- mappings | 友好名称到 JSON 路径的映射。
- defaultMappings | 当您将 Mii 编码为一种格式时,如果该格式需要一个其来源格式所没有的字段,则使用这些默认值。
- async makeMiiChild(mii1, mii2, options) | 向此函数提供两个 Mii,该函数将返回一个包含六个 JSON 对象的数组,代表一个潜在后代在 Tomodachi Life 风格中生命所有阶段的形象。
- 选项值包括:name(结果 Mii 的名称)、creatorName(输出的创建者名称)、gender(孩子的性别,0 男性,1 女性,与所有 Mii 输出代码中的含义相同)、favoriteColor(输出孩子的喜爱颜色)。
- async kidomatic(mii, hairGroupIndex) | 向此函数提供一个 Mii,该函数将返回一个包含六个 JSON 对象的数组,代表该 Mii 在 Tomodachi Life 风格中童年所有阶段的形象。
- hairGroupIndex 是可选的,建议在没有特定用例时省略。如果省略或为负值,`kidomatic` 将根据 Mii 当前的发型和性别推断一个合适的儿童发型组。
- async decryptMii(miiBuffer) | 从二维码格式解密 Mii。
- async encryptMii(miiBuffer) | 将 Mii 加密为二维码格式。
- async makeInstructions(mii, console) | 参见 Mii.toInstructions。
- async getAs(mii, console, path) | 参见 Mii.getAs。
- async setAs(mii, console, path, value) | 参见 Mii.setAs。
- async miiHeightToMeasurements(miiHeight) | 输入 Mii 的身高(0-127),输出 { totalInches, inches, feet, centimeters }。
- async miiWeightToMeasurements(miiHeight, miiWeight) | 输入 Mii 的身高和体重(值范围 0-127),输出 {pounds, kilograms}。
- async inchesToMiiHeight(totalInches) | 提供总英寸数,输出 Mii 身高。
- async centimetersToMiiHeight(totalCentimeters) | 提供总厘米数,输出 Mii 身高。
- async imperialHeightWeightToMiiWeight(totalInches, totalPounds) | 提供总英寸数和总磅数,输出 Mii 体重。
- async metricHeightWeightToMiiWeight(totalCentimeters, totalKilograms) | 提供总厘米数和总公斤数,输出 Mii 体重。
- isMiiInFormat(miiBuffer, format) | 检查缓冲区是否为指定格式,返回 true 或 false。
- detectMiiFormat(miiBuffer, debug) | 返回一个 MiiFormats 数组,表示此 Mii 可能属于的格式。如果我们有其结构定义,它将验证每个单独的值是否在该格式的边界内。
- decodeMii(miiOfAnyKnownWayOfRepresentingIt, debug) | 参见 Mii.create。仅为可选的异步解码器(如图像二维码、加密二维码或 Amiibo 数据)返回 Promise。
- encodeMii(MiiClassOrJSON, format) | 参见 Mii.encode。仅为可选的异步编码器(如加密二维码格式)返回 Promise。
- async renderMii(mii, options) | 参见 Mii.render。
- FFLExpression | 参见枚举类型。
- scanQR(buffer) | 提供一个包含二维码的缓冲区,返回二维码所代表的数据缓冲区。
- async makeQR(buffer, options) | 提供一个缓冲区,输出一个包含该缓冲区数据的二维码。如果缓冲区是可识别的 Mii 且 FFLResHigh.dat 存在,则该 Mii 将被渲染为二维码的图标。选项参见 Mii.toQR。
- getNestedValue(object, path) | 沿路径获取对象的值,如果路径中的任何步骤未定义,则返回 null。
- setNestedValue(object, path, value) | 沿路径设置对象的值,如果未定义则创建任何必要的步骤。
- deleteNestedValue(object, path) | 沿路径删除对象的键。
- getKeyByValue(object, value) | 返回与该值关联的键,对于反向追踪枚举很有用。
- FavoriteColors | 参见枚举类型。
## FFLResHigh.dat
FFLResHigh.dat 提供了构建 Mii 3D 模型所需的模型和纹理。该库不会提供此文件,但可以通过将其放置在调用 MiiJS 的项目目录中来提供。通过提供 FFLResHigh.dat,您可以本地渲染 Mii 而无需使用 Studio。如果您没有或未向本地项目提供 FFLResHigh.dat,目前无法通过 MiiJS 进行渲染。
### 查找 FFLResHigh.dat
任何版本的 AFLResHigh.dat 也可以工作,只需重命名为 FFLResHigh.dat。
您可以在安装了 FTP 程序的 Wii U 上找到 FFLResHigh,路径为 `sys/title/0005001b/10056000/content/FFLResHigh.dat`。从 Miitomo 安装中,它可以在缓存中找到,路径为 `res/asset/model/character/mii/AFLResHigh_2_3.dat`。
### 身体渲染
目前正在进行动态提取身体的研究。作为临时解决方案,这些文件在此处提供,因为最终的最佳查找来源是 [Arian Kordi 的这个仓库](https://github.com/ariankordi/ffl-raylib-samples/tree/master/models)。目前它们可以工作,但请记住,在我能尽快管理的近期,这些文件将从仓库中移除,届时您需要类似提取 FFLResHigh 一样来提取它们。
## 故障排除
- 特殊 Mii **__必须__** 将 `meta.originalDevice` 字段设置为 **匹配的** 设备。在所有其他情况下,3DS 可以扫描 originalDevice 为 4 的二维码,Wii 可以扫描 originalDevice 为 3 的二维码。然而,在特殊 Mii 的情况下,要在 3DS 上扫描,您 **__必须__** 将 `originalDevice` 设置为 **3**,要在 Wii U 上扫描,您 **__必须__** 将其设置为 **4**。如果您使用 Mii 类,MiiJS 会自动处理此问题,只需确保告诉 `Mii.toQR` 函数您打算在 3DS 或 Wii U 上扫描(参见 ConsoleFormats 枚举)。
- ~~特殊 Mii 要求 3DS 和 Wii U 上的“共享”功能关闭~~ MiiJS 应会自动处理。
- ~~特殊 Mii 要求 Wii 上的“混音”功能关闭~~ MiiJS 应会自动处理。
- 即使不是特殊 Mii,有时为其他游戏机编码的二维码也无法扫描。我不确定其中的关联性,但确保告诉 `Mii.toQR` 函数您将在哪个游戏机上扫描它应该是万无一失的。如果您使用 `makeQR`,则为 3DS 编码为 `MiiFormats.CFED`,为 Wii U 编码为 `MiiFormats.FFED`。这些强制确保 `meta.originalDevice` 分别为 3 和 4,这应该可以防止所有扫描问题。此外,如果存在 Tomodachi Life 字段,并且您使用 `Mii.toQR` 并指定 3DS 二维码,则会自动编码为 Tomodachi Life 二维码。如果使用 `makeQR`,则编码为 `MiiFormats.TLE`。
## 支持的类型
按游戏机发布顺序排列。C 与 S 的区别分别表示无校验和与有校验和。
### Nintendo DS
- .ncd, .nsd
- DS Mii,与 Wii 对应格式相同,但有部分字节序交换。
### Wii
- .rcd, .rsd
- Wii Mii。
### 3DS
- .cfcd, .cfsd
- 解密/内部 3DS Mii,与其 FFCD/FFSD 对应格式在单个数字后相同(仅对特殊 Mii 有影响)。
- .cfed
- 用于二维码目的的加密 CFSD。与 FFED 无异。
- .png, .jpg
- 二维码可被扫描并重新创建。
- .tl, .tl_alt, .tomodachilife
- Tomodachi Life 二维码 Mii 数据解密后的各种大小/别名。
- .tle
- Tomodachi Life 二维码加密数据。
### Wii U
- .ffcd, .ffsd
- 解密/内部 Wii U Mii,与其 CFCD/CFSD 对应格式在单个数字后相同(仅对特殊 Mii 有影响)。
- .ffed
- 用于二维码目的的加密 FFSD。与 CFED 无异。
- .png, .jpg
- 二维码可被扫描并重新创建。
### Amiibo
- .ntag, .ntag_alt
- 各种大小的 Amiibo 文件。
- .ntag_internal
- 解密的 Amiibo 文件。
### Miitomo(未经测试)
- .mt, .miitomo
- Miitomo 二维码 Mii 数据解密后。
### Switch/2
- .nfcd, .nfsd .switchdb
- Switch NAND 格式,用于 Mii Maker 小程序。
- .charinfo
- 游戏使用的 Switch 格式。
### My Nintendo Mii Studio/浏览器
- .mnms, .studio, .localstorage
- Mii Studio 网站存储在 localStorage 中的格式。
### 其他
这些格式可以解码和编码,但不推荐用作文件扩展名,因为其他格式完全等效,而这些特定名称要么不具体,要么很少使用,要么已过时。
- .ver3
- .mii, .mae, .miigx
- .ufsd, .sampledb
- UFSD, MII, MIIGX, MAE 是社区的非官方名称。
- MNMS 和 NCD/NSD 是来自 [HEYimHeroic](https://github.com/HEYimHeroic) 的 [Mii 数据文件仓库](https://github.com/HEYimHeroic/MiiDataFiles) 的非官方名称,同样也记录了 CFCD/FFCD、NFSD/NFCD,它们很可能是官方名称,但目前尚未在任何官方场合使用。
- CFED/FFED、TL/TL_ALT/TLE/TOMODACHILIFE、MT/MIITOMO、STUDIO/LOCALSTORAGE 是库作者提出的非官方名称,因为没有其他官方名称被认可,但又必须加以区分。
## 与 MiiJS 配合使用的其他有用工具
每一项都至少由库作者之一亲自使用和验证过。
- 我们自己的 [WiimoteBridge](https://github.com/Stewared/WiimoteBridge) 是我们一直在开发的一个工具,旨在让连接 Wiimote 到您的设备(例如在 Wii 上传输 Mii)变得更加容易。
- [InfiniMii 的 Wiimote 工具页面](https://infinimii.com/wiimote) 是一个适用于 Chromium 浏览器的工具,用于在 Wiimote 上传输 Mii。
- [Tagmo](https://play.google.com/store/apps/details?id=com.hiddenramblings.tagmo.eightbit) 适用于 Android,可用于在您的 Amiibo 上传输文件。有 iPhone 的替代品,但由于掠夺性的订阅或微交易模式,我们目前觉得不适合推荐。
- [Nintendo 的 Mii Studio](https://accounts.nintendo.com/mii_studio) 是唯一官方的在线 Mii 制作器,任何拥有 Nintendo Account 的人都可访问。(必须先登录 [Nintendo 在线门户](https://accounts.nintendo.com/) 才能访问 Mii Studio 链接)
- [HEYimHeroic](https://github.com/HEYimHeroic) 的 [Mii Studio Mii Loader](https://github.com/HEYimHeroic/MiiStudioMiiLoader) 浏览器扩展让您可以轻松地从 Mii Studio 导入和导出 Mii。
## 致谢
- [HEYimHeroic](https://github.com/HEYimHeroic) 多年来跨越多篇文章的各项工作和文档是并将继续是 MiiJS 开发的宝贵资源。
- [Arian K.](https://github.com/ariankordi) 的 [JSFiddles](https://jsfiddle.net/u/arian_/fiddles/) (+ [仓库](https://github.com/ariankordi/my-jsfiddles)) 对于发现隐藏的流程提供了巨大帮助,他的 [FFL.js](https://github.com/ariankordi/FFL.js/) 使得渲染成为可能。
## 免责声明
Mii、DS、Wii、3DS、Wii U、Amiibo、Tomodachi Life、Miitomo、Switch、Switch 2、My Nintendo、Mii Studio 及其他类似内容完全由任天堂所有,本库及其作者不代表任天堂。
MiiJS 的设计初衷绝非取代或使在其原始硬件上制作 Mii 变得过时。MiiJS 专门用于增强 Mii 以及 Mii 的乐趣和可用性。MiiJS 不提供任何受版权保护的材料,如果任何时候无意中提供了受版权保护的材料,请务必联系作者以立即将其删除。
标签:3DS平台, Amiibo, CJS, DS平台, ESM, FFL.js, GNU通用公共许可证, JavaScript工具, JavaScript库, Miitomo, MITM代理, Node.js, Switch2平台, Switch平台, WiiU平台, Wii平台, 二维码, 任天堂Mii, 图形渲染, 工作室代码, 开源库, 搜索引擎爬虫, 数据可视化, 数据解析, 数据转换, 朋友生活, 浏览器兼容, 渲染引擎, 游戏开发, 游戏数据格式, 游戏机数据, 特殊Mii, 自定义脚本, 角色创建, 读写操作, 跨平台开发, 跨平台支持