@alexislours/ltd-sharemii 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +35 -0
- package/dist/applyMii.d.ts +21 -0
- package/dist/applyUgc.d.ts +21 -0
- package/dist/codec.d.ts +39 -0
- package/dist/errors.d.ts +6 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1230 -0
- package/dist/index.js.map +1 -0
- package/dist/savAccess.d.ts +10 -0
- package/dist/sidecar.d.ts +12 -0
- package/dist/ugcKinds.d.ts +41 -0
- package/dist/utf16.d.ts +3 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# @alexislours/ltd-sharemii
|
|
2
|
+
|
|
3
|
+
Codec for the game's Mii and UGC (user-generated content) share format. Extracts a Mii or a UGC item (clothing, food, goods, painting, ...) out of a parsed save into a portable share file, and applies a share file back into a save. Depends only on [`@alexislours/ltd-savedata`](../ltd-savedata).
|
|
4
|
+
|
|
5
|
+
A share file is a small binary blob carved out of the save's typed fields. Textures and canvases that don't fit inline travel alongside it as named "sidecar" files. This package owns the binary codec and the apply/extract logic; how sidecars are packed for transport (a zip, a folder of files) is left to the caller.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @alexislours/ltd-sharemii
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { decode, parseSav } from '@alexislours/ltd-savedata';
|
|
17
|
+
import { MII_SCHEMA, PLAYER_SCHEMA } from '@alexislours/ltd-savedata/schema';
|
|
18
|
+
import { extractMii, applyMii, EMPTY_SIDECAR } from '@alexislours/ltd-sharemii';
|
|
19
|
+
|
|
20
|
+
const saves = {
|
|
21
|
+
mii: decode(MII_SCHEMA, parseSav(miiBytes)),
|
|
22
|
+
player: decode(PLAYER_SCHEMA, parseSav(playerBytes)),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const share = extractMii(saves, slot, EMPTY_SIDECAR);
|
|
26
|
+
applyMii(destSaves, destSlot, share.bytes, share.sidecar);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Sidecars
|
|
30
|
+
|
|
31
|
+
The codec speaks `SidecarSource` (a `Map<string, Uint8Array>`) and `SidecarFile`, never files or archives. `isSidecarFileName` and `isJunkArchiveEntry` help a host filter incoming names. Packing those bytes into a zip or reading them from a dropped folder is a transport concern the host owns.
|
|
32
|
+
|
|
33
|
+
## License
|
|
34
|
+
|
|
35
|
+
AGPL-3.0-or-later
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type MiiSaves } from './savAccess.js';
|
|
2
|
+
import { type SidecarFile, type SidecarSource } from './sidecar.js';
|
|
3
|
+
export declare const MII_SLOTS = 70;
|
|
4
|
+
export declare const FP_STATE_UNUSED: number;
|
|
5
|
+
export type MiiSlotInfo = {
|
|
6
|
+
slot: number;
|
|
7
|
+
empty: boolean;
|
|
8
|
+
name: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function listMiiSlots(saves: MiiSaves): MiiSlotInfo[];
|
|
11
|
+
export type ExtractMiiResult = {
|
|
12
|
+
bytes: Uint8Array;
|
|
13
|
+
fileName: string;
|
|
14
|
+
miiName: string;
|
|
15
|
+
facepaint: SidecarFile[];
|
|
16
|
+
};
|
|
17
|
+
export declare function extractMii(saves: MiiSaves, slot: number, sidecar?: SidecarSource): ExtractMiiResult;
|
|
18
|
+
export type ApplyMiiResult = {
|
|
19
|
+
facepaintWrites: SidecarFile[];
|
|
20
|
+
};
|
|
21
|
+
export declare function applyMii(saves: MiiSaves, slot: number, ltdBytes: Uint8Array, sidecar?: SidecarSource): ApplyMiiResult;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type PlayerOnlySaves } from './savAccess.js';
|
|
2
|
+
import { type UgcKind } from './ugcKinds.js';
|
|
3
|
+
import { type SidecarFile, type SidecarSource } from './sidecar.js';
|
|
4
|
+
export type UgcSlotInfo = {
|
|
5
|
+
slot: number;
|
|
6
|
+
empty: boolean;
|
|
7
|
+
name: string;
|
|
8
|
+
isAddNew: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function listUgcSlots(saves: PlayerOnlySaves, kind: UgcKind, sidecar?: SidecarSource): UgcSlotInfo[];
|
|
11
|
+
export type ExtractUgcResult = {
|
|
12
|
+
bytes: Uint8Array;
|
|
13
|
+
fileName: string;
|
|
14
|
+
itemName: string;
|
|
15
|
+
textures: SidecarFile[];
|
|
16
|
+
};
|
|
17
|
+
export declare function extractUgc(saves: PlayerOnlySaves, slot: number, kind: UgcKind, sidecar?: SidecarSource): ExtractUgcResult;
|
|
18
|
+
export type ApplyUgcResult = {
|
|
19
|
+
textureWrites: SidecarFile[];
|
|
20
|
+
};
|
|
21
|
+
export declare function applyUgc(saves: PlayerOnlySaves, slot: number, kind: UgcKind, ltdBytes: Uint8Array, isAdding: boolean, sidecar?: SidecarSource): ApplyUgcResult;
|
package/dist/codec.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type LtdMii = {
|
|
2
|
+
version: number;
|
|
3
|
+
/** Original version from the file before upgradeToV3; v1 has no personality data. */
|
|
4
|
+
originalVersion: number;
|
|
5
|
+
hasCanvas: boolean;
|
|
6
|
+
hasUgcTex: boolean;
|
|
7
|
+
miiBlock: Uint8Array;
|
|
8
|
+
personality: Uint8Array;
|
|
9
|
+
name: Uint8Array;
|
|
10
|
+
pronounce: Uint8Array;
|
|
11
|
+
sexuality: Uint8Array;
|
|
12
|
+
canvasTex: Uint8Array;
|
|
13
|
+
ugcTex: Uint8Array;
|
|
14
|
+
};
|
|
15
|
+
export declare function encodeLtdMii(m: LtdMii): Uint8Array;
|
|
16
|
+
export declare function decodeLtdMii(bytes: Uint8Array): LtdMii;
|
|
17
|
+
export type LtdUgc = {
|
|
18
|
+
kindIndex: number;
|
|
19
|
+
fields: Uint8Array;
|
|
20
|
+
vector: Uint8Array;
|
|
21
|
+
vector2: Uint8Array;
|
|
22
|
+
name: Uint8Array;
|
|
23
|
+
pronounce: Uint8Array;
|
|
24
|
+
goodsText?: Uint8Array;
|
|
25
|
+
goodsPronounce?: Uint8Array;
|
|
26
|
+
canvasTex: Uint8Array;
|
|
27
|
+
ugcTex: Uint8Array;
|
|
28
|
+
thumbTex: Uint8Array;
|
|
29
|
+
};
|
|
30
|
+
export declare function encodeLtdUgc(u: LtdUgc): Uint8Array;
|
|
31
|
+
export type LtdUgcSection = {
|
|
32
|
+
kindIndex: number;
|
|
33
|
+
fieldsAndVectors: Uint8Array;
|
|
34
|
+
namesBlock: Uint8Array;
|
|
35
|
+
canvasTex: Uint8Array;
|
|
36
|
+
ugcTex: Uint8Array;
|
|
37
|
+
thumbTex: Uint8Array;
|
|
38
|
+
};
|
|
39
|
+
export declare function decodeLtdUgc(bytes: Uint8Array): LtdUgcSection;
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type ShareMiiErrorCode = 'mii_not_initialized' | 'no_free_facepaint_slot' | 'ugc_missing_textures' | 'wrong_ugc_kind' | 'subtype_mismatch' | 'cannot_replace_kind' | 'invalid_ltd_file' | 'unsupported_ltd_version' | 'ltd_missing_marker' | 'invalid_ugc_kind_index' | 'invalid_zip' | 'save_format_error' | 'slot_out_of_range';
|
|
2
|
+
export declare class ShareMiiError extends Error {
|
|
3
|
+
readonly code: ShareMiiErrorCode;
|
|
4
|
+
readonly params: Record<string, string | number>;
|
|
5
|
+
constructor(code: ShareMiiErrorCode, params?: Record<string, string | number>);
|
|
6
|
+
}
|
package/dist/index.d.ts
ADDED