@alexislours/ltd-sharemii 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @alexislours/ltd-sharemii
2
2
 
3
+ <div align="center">
4
+ <a href="https://www.npmjs.com/package/@alexislours/ltd-sharemii"><img alt="npm" src="https://img.shields.io/npm/v/@alexislours/ltd-sharemii?style=for-the-badge&logo=npm"></a>
5
+ <a href="https://github.com/alexislours/ltd-save-editor/actions/workflows/packages-ci.yml"><img alt="ci" src="https://img.shields.io/github/actions/workflow/status/alexislours/ltd-save-editor/packages-ci.yml?branch=dev&label=ci&style=for-the-badge&logo=githubactions"></a>
6
+ <a href="./LICENSE"><img alt="license" src="https://img.shields.io/npm/l/@alexislours/ltd-sharemii?style=for-the-badge&logo=gnu"></a>
7
+ </div>
8
+
3
9
  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
10
 
5
11
  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.
@@ -1,21 +1,46 @@
1
1
  import { type MiiSaves } from './savAccess.js';
2
2
  import { type SidecarFile, type SidecarSource } from './sidecar.js';
3
+ /** Number of regular Mii slots in a save, not counting the in-progress (temp) Mii exposed as slot 0. */
3
4
  export declare const MII_SLOTS = 70;
5
+ /** Facepaint `state` enum value marking a slot as unused; an in-progress Mii's facepaint exists only when its state differs from this. */
4
6
  export declare const FP_STATE_UNUSED: number;
7
+ /** Summary of one Mii slot for slot-picker UIs. */
5
8
  export type MiiSlotInfo = {
9
+ /** Slot number; `0` is the in-progress (temp) Mii, `1` through {@link MII_SLOTS} are the saved Miis. */
6
10
  slot: number;
11
+ /** Whether the slot holds no Mii. */
7
12
  empty: boolean;
13
+ /** The Mii's display name, or `''` when the slot is empty. */
8
14
  name: string;
9
15
  };
16
+ /** List all Mii slots, including the in-progress Mii at slot 0, with their occupancy and names. */
10
17
  export declare function listMiiSlots(saves: MiiSaves): MiiSlotInfo[];
18
+ /** Result of {@link extractMii}: the share file plus any facepaint textures to save next to it. */
11
19
  export type ExtractMiiResult = {
20
+ /** The encoded `.ltd` Mii share file. */
12
21
  bytes: Uint8Array;
22
+ /** Suggested download file name, derived from the Mii's name. */
13
23
  fileName: string;
24
+ /** The Mii's display name (`'Mii'` for the in-progress Mii). */
14
25
  miiName: string;
26
+ /** Facepaint canvas and texture sidecar files, empty when the Mii has no facepaint or its textures were not provided. */
15
27
  facepaint: SidecarFile[];
16
28
  };
29
+ /**
30
+ * Read the Mii at `slot` (0 for the in-progress Mii) and encode it as a `.ltd`
31
+ * share file, pulling any facepaint textures from `sidecar`. Throws
32
+ * `mii_not_initialized` for an empty slot.
33
+ */
17
34
  export declare function extractMii(saves: MiiSaves, slot: number, sidecar?: SidecarSource): ExtractMiiResult;
35
+ /** Result of {@link applyMii}: facepaint texture files the caller must persist alongside the save. */
18
36
  export type ApplyMiiResult = {
37
+ /** Facepaint canvas and texture files to write; already merged into a writable `sidecar`, empty when the Mii has no facepaint. */
19
38
  facepaintWrites: SidecarFile[];
20
39
  };
40
+ /**
41
+ * Decode a `.ltd` Mii share file and write it into `slot` (0 for the in-progress
42
+ * Mii), allocating or releasing a facepaint slot as needed and restoring name,
43
+ * personality, and sexuality for v2+ files. Throws `mii_not_initialized` when
44
+ * targeting an empty saved slot, or `no_free_facepaint_slot` when none is free.
45
+ */
21
46
  export declare function applyMii(saves: MiiSaves, slot: number, ltdBytes: Uint8Array, sidecar?: SidecarSource): ApplyMiiResult;
@@ -1,21 +1,50 @@
1
1
  import { type PlayerOnlySaves } from './savAccess.js';
2
2
  import { type UgcKind } from './ugcKinds.js';
3
3
  import { type SidecarFile, type SidecarSource } from './sidecar.js';
4
+ /** Summary of one UGC slot for slot-picker UIs. */
4
5
  export type UgcSlotInfo = {
6
+ /** One-based slot number. */
5
7
  slot: number;
8
+ /** Whether the slot holds no item. */
6
9
  empty: boolean;
10
+ /** The item's display name, or `''` when empty. */
7
11
  name: string;
12
+ /** Whether this is the single trailing "add new" placeholder rather than an existing item. */
8
13
  isAddNew: boolean;
9
14
  };
15
+ /**
16
+ * List the UGC slots of `kind` that hold an item, plus one trailing "add new"
17
+ * placeholder. Occupancy is judged from `sidecar` files when present, otherwise
18
+ * from filled name fields in the save.
19
+ */
10
20
  export declare function listUgcSlots(saves: PlayerOnlySaves, kind: UgcKind, sidecar?: SidecarSource): UgcSlotInfo[];
21
+ /** Result of {@link extractUgc}: the share file plus the three texture files that belong with it. */
11
22
  export type ExtractUgcResult = {
23
+ /** The encoded `.ltd*` UGC share file. */
12
24
  bytes: Uint8Array;
25
+ /** Suggested download file name, derived from the item's name and its {@link UgcKind} extension. */
13
26
  fileName: string;
27
+ /** The item's display name. */
14
28
  itemName: string;
29
+ /** Canvas, UGC, and thumbnail sidecar files for the item. */
15
30
  textures: SidecarFile[];
16
31
  };
32
+ /**
33
+ * Read the UGC item at `slot` of `kind` and encode it as a `.ltd*` share file,
34
+ * bundling its canvas, UGC, and thumbnail textures from `sidecar`. Throws
35
+ * `ugc_missing_textures` when any of the three textures is absent.
36
+ */
17
37
  export declare function extractUgc(saves: PlayerOnlySaves, slot: number, kind: UgcKind, sidecar?: SidecarSource): ExtractUgcResult;
38
+ /** Result of {@link applyUgc}: the texture files the caller must persist alongside the save. */
18
39
  export type ApplyUgcResult = {
40
+ /** Canvas, UGC, and thumbnail files to write; already merged into a writable `sidecar`. */
19
41
  textureWrites: SidecarFile[];
20
42
  };
43
+ /**
44
+ * Decode a `.ltd*` UGC share file and write it into `slot` of `kind`. When
45
+ * `isAdding` is true the slot is initialized (enable flag, texture source, and
46
+ * content id) rather than overwritten in place. Throws on a kind mismatch, an
47
+ * out-of-range slot, a subtype mismatch (Cloth/Goods replacement), or attempting
48
+ * to replace an Exterior/MapObject.
49
+ */
21
50
  export declare function applyUgc(saves: PlayerOnlySaves, slot: number, kind: UgcKind, ltdBytes: Uint8Array, isAdding: boolean, sidecar?: SidecarSource): ApplyUgcResult;
package/dist/codec.d.ts CHANGED
@@ -1,4 +1,10 @@
1
+ /**
2
+ * Decoded contents of a `.ltd` Mii share file: the raw Mii block plus the
3
+ * personality, name, pronunciation, and sexuality payloads, and the optional
4
+ * facepaint canvas/UGC textures. Always normalized to the v3 layout when decoded.
5
+ */
1
6
  export type LtdMii = {
7
+ /** File format version of this in-memory record (always 3 after decode). */
2
8
  version: number;
3
9
  /** Original version from the file before upgradeToV3; v1 has no personality data. */
4
10
  originalVersion: number;
@@ -12,9 +18,25 @@ export type LtdMii = {
12
18
  canvasTex: Uint8Array;
13
19
  ugcTex: Uint8Array;
14
20
  };
21
+ /**
22
+ * Serialize a {@link LtdMii} into the v3 `.ltd` byte layout. Throws a plain
23
+ * `Error` if any fixed-width payload (Mii block, personality, name, pronunciation,
24
+ * sexuality) is the wrong length.
25
+ */
15
26
  export declare function encodeLtdMii(m: LtdMii): Uint8Array;
27
+ /**
28
+ * Parse a `.ltd` Mii share file, upgrading v1/v2 payloads to the v3 layout in the
29
+ * process. Throws a {@link ShareMiiError} for truncated data, an unsupported
30
+ * version, or a missing section marker.
31
+ */
16
32
  export declare function decodeLtdMii(bytes: Uint8Array): LtdMii;
33
+ /**
34
+ * Fully-structured source for encoding a `.ltd*` UGC share file, with each field
35
+ * group separated out. Used to build a share file from save data; decoding instead
36
+ * yields the coarser {@link LtdUgcSection}.
37
+ */
17
38
  export type LtdUgc = {
39
+ /** Index of the {@link UgcKind} this item belongs to, written into the file header. */
18
40
  kindIndex: number;
19
41
  fields: Uint8Array;
20
42
  vector: Uint8Array;
@@ -27,8 +49,19 @@ export type LtdUgc = {
27
49
  ugcTex: Uint8Array;
28
50
  thumbTex: Uint8Array;
29
51
  };
52
+ /**
53
+ * Serialize a {@link LtdUgc} into the `.ltd*` UGC byte layout, concatenating the
54
+ * header, scalar fields, vectors, name block, and the three texture sections
55
+ * behind their respective markers. Goods carry two extra name strings.
56
+ */
30
57
  export declare function encodeLtdUgc(u: LtdUgc): Uint8Array;
58
+ /**
59
+ * Decoded `.ltd*` UGC share file split at its section markers. The scalar fields,
60
+ * vectors, and name strings are left as opaque byte runs ({@link LtdUgcSection.fieldsAndVectors},
61
+ * {@link LtdUgcSection.namesBlock}) for the applier to slice per {@link UgcKind}.
62
+ */
31
63
  export type LtdUgcSection = {
64
+ /** Index of the {@link UgcKind} read from the file header. */
32
65
  kindIndex: number;
33
66
  fieldsAndVectors: Uint8Array;
34
67
  namesBlock: Uint8Array;
@@ -36,4 +69,9 @@ export type LtdUgcSection = {
36
69
  ugcTex: Uint8Array;
37
70
  thumbTex: Uint8Array;
38
71
  };
72
+ /**
73
+ * Parse a `.ltd*` UGC share file into its {@link LtdUgcSection} parts by locating
74
+ * the name, canvas, UGC, and thumbnail markers. Throws a {@link ShareMiiError} on
75
+ * truncated data or any missing marker.
76
+ */
39
77
  export declare function decodeLtdUgc(bytes: Uint8Array): LtdUgcSection;
package/dist/errors.d.ts CHANGED
@@ -1,6 +1,19 @@
1
+ /**
2
+ * Stable, machine-readable identifier for every failure {@link ShareMiiError}
3
+ * can raise. Used as the error `message` and exposed via {@link ShareMiiError.code}
4
+ * so callers can branch or localize without parsing prose.
5
+ */
1
6
  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';
7
+ /**
8
+ * Error thrown by every operation in this package when extraction or application
9
+ * fails for a known reason. The {@link ShareMiiErrorCode} carries the cause and
10
+ * {@link ShareMiiError.params} any contextual values for messaging.
11
+ */
2
12
  export declare class ShareMiiError extends Error {
13
+ /** The machine-readable failure cause; also used as the `Error` message. */
3
14
  readonly code: ShareMiiErrorCode;
15
+ /** Contextual values for the failure (slot number, kind, marker name, and so on), suitable for interpolation into a localized message. */
4
16
  readonly params: Record<string, string | number>;
17
+ /** Construct an error for `code`, attaching optional `params` for messaging. */
5
18
  constructor(code: ShareMiiErrorCode, params?: Record<string, string | number>);
6
19
  }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,23 @@
1
+ /**
2
+ * Codec for the game's Mii and user-generated content (UGC) share format.
3
+ *
4
+ * Extract a Mii or a UGC item (food, clothing, treasure, interiors, and so on)
5
+ * from a decoded save into a portable `.ltd*` share file, and apply a share file
6
+ * back into a save. Save reads and writes go through {@link MiiSaves} /
7
+ * {@link PlayerOnlySaves} accessors from `@alexislours/ltd-savedata`; the bulky
8
+ * texture blobs travel alongside as {@link SidecarSource} sidecar files.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { extractMii, applyMii } from '@alexislours/ltd-sharemii';
13
+ *
14
+ * const { bytes, fileName, facepaint } = extractMii(saves, slot, sidecar);
15
+ * // ...later, on another save...
16
+ * applyMii(otherSaves, targetSlot, bytes, sidecar);
17
+ * ```
18
+ *
19
+ * @module
20
+ */
1
21
  export * from './sidecar.js';
2
22
  export * from './errors.js';
3
23
  export * from './utf16.js';
package/dist/index.js CHANGED
@@ -23,8 +23,11 @@ function isJunkArchiveEntry(path) {
23
23
 
24
24
  // src/errors.ts
25
25
  var ShareMiiError = class extends Error {
26
+ /** The machine-readable failure cause; also used as the `Error` message. */
26
27
  code;
28
+ /** Contextual values for the failure (slot number, kind, marker name, and so on), suitable for interpolation into a localized message. */
27
29
  params;
30
+ /** Construct an error for `code`, attaching optional `params` for messaging. */
28
31
  constructor(code, params = {}) {
29
32
  super(code);
30
33
  this.name = "ShareMiiError";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sidecar.ts","../src/errors.ts","../src/utf16.ts","../src/ugcKinds.ts","../src/savAccess.ts","../src/codec.ts","../src/applyMii.ts","../src/applyUgc.ts"],"sourcesContent":["export type SidecarFile = {\n name: string;\n bytes: Uint8Array;\n};\n\nexport type SidecarSource = {\n origin: 'none' | 'folder' | 'zip';\n files: Map<string, Uint8Array>;\n};\n\nexport const EMPTY_SIDECAR: SidecarSource = {\n origin: 'none',\n files: new Map(),\n};\n\nexport function normalizeName(name: string): string {\n const idx = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\\\'));\n return idx >= 0 ? name.slice(idx + 1) : name;\n}\n\nexport function isSidecarFileName(name: string): boolean {\n const lower = name.toLowerCase();\n return lower.endsWith('.canvas.zs') || lower.endsWith('.ugctex.zs');\n}\n\nexport function isJunkArchiveEntry(path: string): boolean {\n if (!path) return true;\n if (path.endsWith('/') || path.endsWith('\\\\')) return true;\n if (path.includes('__MACOSX/') || path.includes('__MACOSX\\\\')) return true;\n const idx = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\\\'));\n const base = idx >= 0 ? path.slice(idx + 1) : path;\n if (!base || base.startsWith('.')) return true;\n return false;\n}\n","export type ShareMiiErrorCode =\n | 'mii_not_initialized'\n | 'no_free_facepaint_slot'\n | 'ugc_missing_textures'\n | 'wrong_ugc_kind'\n | 'subtype_mismatch'\n | 'cannot_replace_kind'\n | 'invalid_ltd_file'\n | 'unsupported_ltd_version'\n | 'ltd_missing_marker'\n | 'invalid_ugc_kind_index'\n | 'invalid_zip'\n | 'save_format_error'\n | 'slot_out_of_range';\n\nexport class ShareMiiError extends Error {\n readonly code: ShareMiiErrorCode;\n readonly params: Record<string, string | number>;\n constructor(code: ShareMiiErrorCode, params: Record<string, string | number> = {}) {\n super(code);\n this.name = 'ShareMiiError';\n this.code = code;\n this.params = params;\n }\n}\n","export function decodeUtf16Name(buf: Uint8Array): string {\n let end = 0;\n while (end + 1 < buf.byteLength) {\n if (buf[end] === 0 && buf[end + 1] === 0) break;\n end += 2;\n }\n const code: number[] = [];\n for (let i = 0; i < end; i += 2) {\n code.push(buf[i] | (buf[i + 1] << 8));\n }\n return String.fromCharCode(...code);\n}\n\nexport function sanitizeFileName(name: string): string {\n const cleaned = name.replace(/[^\\w.-]/g, '_');\n return cleaned.length > 0 ? cleaned : 'mii';\n}\n\nexport function encodeUtf16Name(text: string, byteLen: number): Uint8Array {\n const out = new Uint8Array(byteLen);\n const maxChars = Math.floor((byteLen - 2) / 2);\n const truncated = text.length > maxChars ? text.slice(0, maxChars) : text;\n for (let i = 0; i < truncated.length; i++) {\n const code = truncated.charCodeAt(i);\n out[i * 2] = code & 0xff;\n out[i * 2 + 1] = (code >> 8) & 0xff;\n }\n return out;\n}\n","export type UgcKind =\n | 'Food'\n | 'Cloth'\n | 'Goods'\n | 'Interior'\n | 'Exterior'\n | 'MapObject'\n | 'MapFloor';\n\nexport const UGC_KINDS: readonly UgcKind[] = [\n 'Food',\n 'Cloth',\n 'Goods',\n 'Interior',\n 'Exterior',\n 'MapObject',\n 'MapFloor',\n];\n\nexport const UGC_DISPLAY_LABELS: Record<UgcKind, string> = {\n Food: 'Food',\n Cloth: 'Clothing',\n Goods: 'Treasure',\n Interior: 'Interior',\n Exterior: 'Exterior',\n MapObject: 'Objects',\n MapFloor: 'Landscaping',\n};\n\nexport const UGC_FILE_EXTENSIONS: Record<UgcKind, string> = {\n Food: '.ltdf',\n Cloth: '.ltdc',\n Goods: '.ltdg',\n Interior: '.ltdi',\n Exterior: '.ltde',\n MapObject: '.ltdo',\n MapFloor: '.ltdl',\n};\n\nexport function ugcKindIndex(kind: UgcKind): number {\n return UGC_KINDS.indexOf(kind);\n}\n\nexport const UGC_MAX_SLOTS: Record<UgcKind, number> = {\n Food: 99,\n Cloth: 299,\n Goods: 99,\n Interior: 99,\n Exterior: 99,\n MapObject: 99,\n MapFloor: 99,\n};\n\nfunction ugcFileBase(kind: UgcKind, slot: number): string {\n return `Ugc${kind}${String(slot).padStart(3, '0')}`;\n}\n\nexport function ugcCanvasFileName(kind: UgcKind, slot: number): string {\n return `${ugcFileBase(kind, slot)}.canvas.zs`;\n}\n\nexport function ugcTexFileName(kind: UgcKind, slot: number): string {\n return `${ugcFileBase(kind, slot)}.ugctex.zs`;\n}\n\nexport function ugcThumbFileName(kind: UgcKind, slot: number): string {\n return `${ugcFileBase(kind, slot)}_Thumb.ugctex.zs`;\n}\n\nfunction facepaintFileBase(id: number): string {\n return `UgcFacePaint${String(id).padStart(3, '0')}`;\n}\n\nexport function facepaintCanvasFileName(id: number): string {\n return `${facepaintFileBase(id)}.canvas.zs`;\n}\n\nexport function facepaintTexFileName(id: number): string {\n return `${facepaintFileBase(id)}.ugctex.zs`;\n}\n\nexport type UgcFieldHashes = {\n fields: readonly number[];\n names: readonly number[];\n vector?: number;\n vector2?: number;\n};\n\nexport const UGC_HASHES: Record<UgcKind, UgcFieldHashes> = {\n Food: {\n fields: [\n 0x307feefa, 0x6f93ffbd, 0x5ca9336e, 0xf768620a, 0x5af04beb, 0x2db168c5, 0x634800ae,\n 0xdd8d6c5a, 0xaf1186cf, 0x58e6aad3,\n ],\n names: [0x408494f5, 0xba0f4baf],\n },\n Cloth: {\n fields: [\n 0xc81545fe, 0x2fb9146d, 0x7a31ef97, 0x7eec35e9, 0x5e32fd3f, 0x0dbabe27, 0x71621c98,\n 0x2d271339, 0xcdf31eb5, 0x2823dbd3,\n ],\n names: [0x40710642, 0xcf9a13ea],\n },\n Goods: {\n fields: [\n 0x3faa2222, 0x823f8297, 0x7ecc8a60, 0x88dc1d43, 0x8896ddd6, 0xbff29472, 0x5d965762,\n 0x78d39208, 0x53c762b0, 0x40d2c6fe, 0xc0a6c046, 0xae373b0d, 0x7d5ffbb7, 0x9e978f5e,\n 0xf6349929, 0x9038cdd0, 0x9a59f58a,\n ],\n names: [0x2f793eb1, 0xf655b33a, 0xf36a5a0b, 0xa66367eb],\n vector: 0xf36c4e28,\n },\n Interior: {\n fields: [\n 0xa9116402, 0x835114c1, 0xec65e2e4, 0x0a7cf2c5, 0x662cd807, 0x01b3661e, 0x5af4a09f,\n 0x41ff2201,\n ],\n names: [0x3de2c5dd, 0x85a37b90],\n },\n Exterior: {\n fields: [\n 0xed95cf0f, 0x43f509ba, 0xa7a0773c, 0xa7a0773c, 0x34ba6119, 0x5e6e9f8c, 0x2907c040,\n 0x97865d6b, 0x609f197d, 0x47a50525, 0x71ea7734,\n ],\n names: [0x27c875d6, 0x0e15e3f8],\n vector: 0x3c14025e,\n vector2: 0xb9d21b4f,\n },\n MapObject: {\n fields: [\n 0x274659d1, 0xdce826fc, 0xe04e1e6b, 0x056f2f20, 0xbc7d7e30, 0x3c2bc52f, 0xcffeccc2,\n 0x5c15e339, 0x5eff5e0e, 0x9838264b, 0x48778de6, 0x62ad5137, 0xd1b3b197,\n ],\n names: [0x56f99338, 0xee921ae2],\n vector: 0x27f2ecde,\n vector2: 0x2f96203b,\n },\n MapFloor: {\n fields: [\n 0x21d582d9, 0xde7cb924, 0xe8bd8c89, 0xc35b8b0f, 0x60e280fb, 0x7ec3836a, 0xf209e2f9,\n 0x6d842acc,\n ],\n names: [0x918875a9, 0x503490e0],\n },\n};\n\nexport const UGC_ENABLE_HASHES: Record<UgcKind, number> = {\n Food: 0xf4a39965,\n Cloth: 0xaf129c33,\n Goods: 0x1a9c00fe,\n Interior: 0xa39744e9,\n Exterior: 0xf4beadc2,\n MapObject: 0x5951050b,\n MapFloor: 0xa1126d32,\n};\n\nexport const UGC_TEXTURE_HASHES: Record<UgcKind, number> = {\n Food: 0x3558b77f,\n Cloth: 0x59bfa9d3,\n Goods: 0x70d10a48,\n Interior: 0xe7f9d439,\n Exterior: 0x16227c50,\n MapObject: 0xa9c5cfb8,\n MapFloor: 0x06a7a14c,\n};\n\nexport const UGC_HASH_ID_HASHES: Record<UgcKind, number> = {\n Food: 0x6d48f8e2,\n Cloth: 0x89f25cac,\n Goods: 0x56202100,\n Interior: 0x7fef7f7d,\n Exterior: 0x38d72795,\n MapObject: 0x1b28b170,\n MapFloor: 0x816d50a3,\n};\n\nexport const UGC_TEX_DATA = new Uint8Array([\n 0x41, 0x49, 0x93, 0x56, 0xe3, 0xc2, 0x2f, 0xb4, 0x41, 0x49, 0x93, 0x56, 0xe3, 0xc2, 0x2f, 0xb4,\n 0xe3, 0xc2, 0x2f, 0xb4, 0xe3, 0xc2, 0x2f, 0xb4, 0xe3, 0xc2, 0x2f, 0xb4,\n]);\n\nexport const UGC_HASH_INDICES: Record<UgcKind, number> = {\n Food: 1,\n Cloth: 3,\n Goods: 2,\n Interior: 6,\n Exterior: 7,\n MapObject: 4,\n MapFloor: 5,\n};\n\nexport const FACEPAINT_HASHES = {\n price: 0x4c9819e4,\n textureSourceType: 0xdecc8954,\n state: 0x23135bc5,\n unknown: 0xffc750b6,\n hash: 0xa56e42ec,\n};\n\nexport const MII_HASHES = {\n facePaintIndex: 0x5e32adf4,\n tempSlotMii: 0x114eff89,\n names: 0x2499bfda,\n pronunciation: 0x3a5eda05,\n rawMii: 0x881ca27a,\n isLoveGender: 0xdfc82223,\n satisfyLevel: 0x9999b7d9,\n personality: [\n 0x43cd364f, 0xcd8dbaf8, 0x25b48224, 0x607ba160, 0x68e1134e, 0x4913ae1a, 0x141ee086, 0x07b9d175,\n 0x81cf470a, 0x4d78e262, 0xfbc3ffb0, 0x236e2d73, 0xf3c3de59, 0x660c5247, 0x5d7d3f45, 0xab8ae08b,\n 0x2545e583, 0x6cf484f4,\n ] as const,\n};\n\nexport const UGC_NAME_HASHES: Record<UgcKind, number> = {\n Food: 0x408494f5,\n Cloth: 0x40710642,\n Goods: 0x2f793eb1,\n Interior: 0x3de2c5dd,\n Exterior: 0x27c875d6,\n MapObject: 0x56f99338,\n MapFloor: 0x918875a9,\n};\n","import { DataType, type Accessor, buildHashMap } from '@alexislours/ltd-savedata';\nimport { MII_SCHEMA, PLAYER_SCHEMA, type SchemaLeaf } from '@alexislours/ltd-savedata/schema';\nimport { ShareMiiError } from './errors.js';\n\nexport type MiiSaves = {\n player: Accessor<'player'>;\n mii: Accessor<'mii'>;\n};\n\nexport type PlayerOnlySaves = { player: Accessor<'player'> };\n\nexport function leafByHashOrThrow<T extends DataType>(\n schema: typeof PLAYER_SCHEMA | typeof MII_SCHEMA,\n hash: number,\n label: string,\n expected: T,\n): SchemaLeaf<T> {\n const leaf = buildHashMap(schema).get(hash >>> 0);\n if (!leaf) throw new ShareMiiError('save_format_error', { label });\n if (leaf.type !== expected) {\n throw new ShareMiiError('save_format_error', { label });\n }\n return leaf as SchemaLeaf<T>;\n}\n","import { ShareMiiError } from './errors.js';\n\nconst MII_BLOCK = 156;\nconst PERSONALITY_LEN = 18 * 4;\nconst NAME_LEN = 64;\nconst PRONOUNCE_LEN = 128;\nconst SEXUALITY_LEN = 4;\n\nconst MARK_CANVAS = new Uint8Array([0xa3, 0xa3, 0xa3, 0xa3]);\nconst MARK_UGC = new Uint8Array([0xa4, 0xa4, 0xa4, 0xa4]);\nconst MARK_NAME = new Uint8Array([0xa2, 0xa2, 0xa2, 0xa2]);\nconst MARK_THUMB = new Uint8Array([0xa5, 0xa5, 0xa5, 0xa5]);\n\nexport type LtdMii = {\n version: number;\n /** Original version from the file before upgradeToV3; v1 has no personality data. */\n originalVersion: number;\n hasCanvas: boolean;\n hasUgcTex: boolean;\n miiBlock: Uint8Array;\n personality: Uint8Array;\n name: Uint8Array;\n pronounce: Uint8Array;\n sexuality: Uint8Array;\n canvasTex: Uint8Array;\n ugcTex: Uint8Array;\n};\n\nexport function encodeLtdMii(m: LtdMii): Uint8Array {\n if (m.miiBlock.byteLength !== MII_BLOCK) throw new Error('miiBlock must be 156 bytes');\n if (m.personality.byteLength !== PERSONALITY_LEN) throw new Error('personality must be 72 bytes');\n if (m.name.byteLength !== NAME_LEN) throw new Error('name must be 64 bytes');\n if (m.pronounce.byteLength !== PRONOUNCE_LEN) throw new Error('pronounce must be 128 bytes');\n if (m.sexuality.byteLength !== SEXUALITY_LEN) throw new Error('sexuality must be 4 bytes');\n\n const total =\n 4 +\n MII_BLOCK +\n PERSONALITY_LEN +\n NAME_LEN +\n PRONOUNCE_LEN +\n SEXUALITY_LEN +\n 4 +\n m.canvasTex.byteLength +\n 4 +\n m.ugcTex.byteLength;\n const out = new Uint8Array(total);\n let p = 0;\n out[p++] = m.version & 0xff;\n out[p++] = m.hasCanvas ? 1 : 0;\n out[p++] = m.hasUgcTex ? 1 : 0;\n out[p++] = 0;\n out.set(m.miiBlock, p);\n p += MII_BLOCK;\n out.set(m.personality, p);\n p += PERSONALITY_LEN;\n out.set(m.name, p);\n p += NAME_LEN;\n out.set(m.pronounce, p);\n p += PRONOUNCE_LEN;\n out.set(m.sexuality, p);\n p += SEXUALITY_LEN;\n out.set(MARK_CANVAS, p);\n p += 4;\n out.set(m.canvasTex, p);\n p += m.canvasTex.byteLength;\n out.set(MARK_UGC, p);\n p += 4;\n out.set(m.ugcTex, p);\n return out;\n}\n\nexport function decodeLtdMii(bytes: Uint8Array): LtdMii {\n if (bytes.byteLength < 4) throw new ShareMiiError('invalid_ltd_file');\n let buf: Uint8Array = new Uint8Array(bytes);\n const originalVersion = buf[0];\n let version = originalVersion;\n if (version < 1 || version > 3) {\n throw new ShareMiiError('unsupported_ltd_version', { version });\n }\n\n if (version < 3) {\n buf = upgradeToV3(buf);\n version = 3;\n }\n\n const hasCanvas = buf[1] !== 0;\n const hasUgcTex = buf[2] !== 0;\n let p = 4;\n const miiBlock = buf.slice(p, p + MII_BLOCK);\n p += MII_BLOCK;\n const personality = buf.slice(p, p + PERSONALITY_LEN);\n p += PERSONALITY_LEN;\n const name = buf.slice(p, p + NAME_LEN);\n p += NAME_LEN;\n const pronounce = buf.slice(p, p + PRONOUNCE_LEN);\n p += PRONOUNCE_LEN;\n const sexuality = buf.slice(p, p + SEXUALITY_LEN);\n p += SEXUALITY_LEN;\n\n const canvasStart = findMarker(buf, MARK_CANVAS, p);\n if (canvasStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'canvas' });\n const ugcStart = findMarker(buf, MARK_UGC, canvasStart + 4);\n if (ugcStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'ugc' });\n\n const canvasTex = buf.slice(canvasStart + 4, ugcStart);\n const ugcTex = buf.slice(ugcStart + 4);\n\n return {\n version,\n originalVersion,\n hasCanvas,\n hasUgcTex,\n miiBlock,\n personality,\n name,\n pronounce,\n sexuality,\n canvasTex,\n ugcTex,\n };\n}\n\nfunction upgradeToV3(input: Uint8Array): Uint8Array {\n const mii = Array.from(input);\n const originalVersion = mii[0];\n mii.splice(4, 1);\n if (originalVersion === 2) {\n mii.splice(427, 0, 0);\n const canvasMarkerStart = findMarkerArr(mii, [0xa3, 0xa3, 0xa3]);\n if (canvasMarkerStart < 0)\n throw new ShareMiiError('ltd_missing_marker', { marker: 'v2_canvas' });\n const canvasStart = canvasMarkerStart + 3;\n const ugcMarkerStart = lastFindMarkerArr(mii, [0xa3, 0xa3, 0xa3]);\n mii.splice(canvasStart, 0, 0xa3);\n mii[ugcMarkerStart + 1] = 0xa4;\n mii[ugcMarkerStart + 2] = 0xa4;\n mii[ugcMarkerStart + 3] = 0xa4;\n mii.splice(ugcMarkerStart + 3, 0, 0xa4);\n }\n mii[0] = 3;\n return new Uint8Array(mii);\n}\n\nfunction findMarker(buf: Uint8Array, marker: Uint8Array, from: number): number {\n outer: for (let i = from; i <= buf.byteLength - marker.byteLength; i++) {\n for (let j = 0; j < marker.byteLength; j++) {\n if (buf[i + j] !== marker[j]) continue outer;\n }\n return i;\n }\n return -1;\n}\n\nfunction findMarkerArr(buf: number[], marker: number[]): number {\n outer: for (let i = 0; i <= buf.length - marker.length; i++) {\n for (let j = 0; j < marker.length; j++) {\n if (buf[i + j] !== marker[j]) continue outer;\n }\n return i;\n }\n return -1;\n}\n\nfunction lastFindMarkerArr(buf: number[], marker: number[]): number {\n outer: for (let i = buf.length - marker.length; i >= 0; i--) {\n for (let j = 0; j < marker.length; j++) {\n if (buf[i + j] !== marker[j]) continue outer;\n }\n return i;\n }\n return -1;\n}\n\nexport type LtdUgc = {\n kindIndex: number;\n fields: Uint8Array;\n vector: Uint8Array;\n vector2: Uint8Array;\n name: Uint8Array;\n pronounce: Uint8Array;\n goodsText?: Uint8Array;\n goodsPronounce?: Uint8Array;\n canvasTex: Uint8Array;\n ugcTex: Uint8Array;\n thumbTex: Uint8Array;\n};\n\nexport function encodeLtdUgc(u: LtdUgc): Uint8Array {\n const ltdHeader = new Uint8Array([u.kindIndex & 0xff, 0, 0, 0]);\n const namesBlock = u.goodsText\n ? concat(u.name, u.pronounce, u.goodsText, u.goodsPronounce ?? new Uint8Array(0))\n : concat(u.name, u.pronounce);\n\n return concat(\n ltdHeader,\n u.fields,\n u.vector,\n u.vector2,\n MARK_NAME,\n namesBlock,\n MARK_CANVAS,\n u.canvasTex,\n MARK_UGC,\n u.ugcTex,\n MARK_THUMB,\n u.thumbTex,\n );\n}\n\nexport type LtdUgcSection = {\n kindIndex: number;\n fieldsAndVectors: Uint8Array;\n namesBlock: Uint8Array;\n canvasTex: Uint8Array;\n ugcTex: Uint8Array;\n thumbTex: Uint8Array;\n};\n\nexport function decodeLtdUgc(bytes: Uint8Array): LtdUgcSection {\n if (bytes.byteLength < 4) throw new ShareMiiError('invalid_ltd_file');\n const kindIndex = bytes[0];\n\n const nameStart = findMarker(bytes, MARK_NAME, 4);\n if (nameStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'name' });\n const canvasStart = findMarker(bytes, MARK_CANVAS, nameStart + 4);\n if (canvasStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'canvas' });\n const ugcStart = findMarker(bytes, MARK_UGC, canvasStart + 4);\n if (ugcStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'ugc' });\n const thumbStart = findMarker(bytes, MARK_THUMB, ugcStart + 4);\n if (thumbStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'thumb' });\n\n return {\n kindIndex,\n fieldsAndVectors: bytes.slice(4, nameStart),\n namesBlock: bytes.slice(nameStart + 4, canvasStart),\n canvasTex: bytes.slice(canvasStart + 4, ugcStart),\n ugcTex: bytes.slice(ugcStart + 4, thumbStart),\n thumbTex: bytes.slice(thumbStart + 4),\n };\n}\n\nfunction concat(...parts: Uint8Array[]): Uint8Array {\n let total = 0;\n for (const p of parts) total += p.byteLength;\n const out = new Uint8Array(total);\n let off = 0;\n for (const p of parts) {\n out.set(p, off);\n off += p.byteLength;\n }\n return out;\n}\n","import { DataType, type Accessor, buildHashMap } from '@alexislours/ltd-savedata';\nimport { MII_SCHEMA, PLAYER_SCHEMA, type SchemaLeaf } from '@alexislours/ltd-savedata/schema';\nimport { decodeLtdMii, encodeLtdMii, type LtdMii } from './codec.js';\nimport { ShareMiiError } from './errors.js';\nimport { leafByHashOrThrow, type MiiSaves } from './savAccess.js';\nimport {\n FACEPAINT_HASHES,\n MII_HASHES,\n facepaintCanvasFileName,\n facepaintTexFileName,\n} from './ugcKinds.js';\nimport { decodeUtf16Name, encodeUtf16Name, sanitizeFileName } from './utf16.js';\nimport { EMPTY_SIDECAR, type SidecarFile, type SidecarSource } from './sidecar.js';\n\nexport const MII_SLOTS = 70;\nconst MII_BLOCK_LEN = 156;\nconst MII_DATA_LEN = 152;\n\nfunction wrapMiiBlock(data: Uint8Array): Uint8Array {\n const out = new Uint8Array(MII_BLOCK_LEN);\n new DataView(out.buffer).setUint32(0, MII_DATA_LEN, true);\n out.set(data, 4);\n return out;\n}\n\nfunction unwrapMiiBlock(block: Uint8Array): Uint8Array {\n return block.slice(4, MII_BLOCK_LEN);\n}\n\nconst FP_TEX_SRC_USED = 0x56934941 | 0;\nconst FP_TEX_SRC_UNUSED = 0xb6eede09 | 0;\nconst FP_STATE_USED = 0x1d7fadf4 | 0;\nexport const FP_STATE_UNUSED = 0xafff8aa5 | 0;\nconst FP_UNKNOWN_USED = 0x00008000 | 0;\nconst FP_UNKNOWN_UNUSED = 0x00000000 | 0;\nconst FP_PRICE = 0x000001f4;\nconst FP_HASH_UNUSED = 0x00000000 | 0;\nconst FP_INDEX_UNUSED = -1;\n\nfunction fpHashValue(facepaintId: number): number {\n return (8 << 16) | facepaintId | 0;\n}\n\nconst PLAYER_LEAVES = {\n fpPrice: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.price,\n 'Facepaint.Price',\n DataType.IntArray,\n ),\n fpTexSrc: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.textureSourceType,\n 'Facepaint.TextureSourceType',\n DataType.EnumArray,\n ),\n fpState: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.state,\n 'Facepaint.State',\n DataType.EnumArray,\n ),\n fpUnknown: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.unknown,\n 'Facepaint.Unknown',\n DataType.UIntArray,\n ),\n fpHash: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.hash,\n 'Facepaint.Hash',\n DataType.UIntArray,\n ),\n tempSlot: leafByHashOrThrow(\n PLAYER_SCHEMA,\n MII_HASHES.tempSlotMii,\n 'Player.TempSlotMii',\n DataType.Binary,\n ),\n} as const;\n\nconst MII_LEAVES = {\n facePaintIndex: leafByHashOrThrow(\n MII_SCHEMA,\n MII_HASHES.facePaintIndex,\n 'Mii.FacePaintIndex',\n DataType.IntArray,\n ),\n names: leafByHashOrThrow(MII_SCHEMA, MII_HASHES.names, 'Mii.Names', DataType.WString32Array),\n pronunciation: leafByHashOrThrow(\n MII_SCHEMA,\n MII_HASHES.pronunciation,\n 'Mii.Pronunciation',\n DataType.WString64Array,\n ),\n rawMii: leafByHashOrThrow(MII_SCHEMA, MII_HASHES.rawMii, 'Mii.Raw', DataType.BinaryArray),\n isLoveGender: leafByHashOrThrow(\n MII_SCHEMA,\n MII_HASHES.isLoveGender,\n 'Mii.IsLoveGender',\n DataType.BoolArray,\n ),\n satisfyLevel: leafByHashOrThrow(\n MII_SCHEMA,\n MII_HASHES.satisfyLevel,\n 'Mii.SatisfyInfo.Level',\n DataType.IntArray,\n ),\n personality: MII_HASHES.personality.map((h, i) => {\n const leaf = buildHashMap(MII_SCHEMA).get(h >>> 0);\n if (!leaf) throw new ShareMiiError('save_format_error', { label: `Personality[${i}]` });\n if (leaf.type !== DataType.IntArray && leaf.type !== DataType.EnumArray) {\n throw new ShareMiiError('save_format_error', { label: `Personality[${i}]` });\n }\n return leaf as SchemaLeaf<DataType.IntArray> | SchemaLeaf<DataType.EnumArray>;\n }) as readonly (SchemaLeaf<DataType.IntArray> | SchemaLeaf<DataType.EnumArray>)[],\n} as const;\n\nfunction getPersonalityElement(\n mii: Accessor<'mii'>,\n leaf: SchemaLeaf<DataType.IntArray> | SchemaLeaf<DataType.EnumArray>,\n i: number,\n): number {\n if (leaf.type === DataType.IntArray) return mii.getElement(leaf, i);\n return mii.getElement(leaf, i);\n}\n\nfunction setPersonalityElement(\n mii: Accessor<'mii'>,\n leaf: SchemaLeaf<DataType.IntArray> | SchemaLeaf<DataType.EnumArray>,\n i: number,\n v: number,\n): void {\n if (leaf.type === DataType.IntArray) mii.setElement(leaf, i, v);\n else mii.setElement(leaf, i, v >>> 0);\n}\n\nexport type MiiSlotInfo = {\n slot: number;\n empty: boolean;\n name: string;\n};\n\nexport function listMiiSlots(saves: MiiSaves): MiiSlotInfo[] {\n const out: MiiSlotInfo[] = [];\n out.push({ slot: 0, empty: false, name: 'In-Progress Mii' });\n for (let s = 0; s < MII_SLOTS; s++) {\n const data = saves.mii.getElement(MII_LEAVES.rawMii, s);\n const empty = isEmptyDataBlock(data);\n const name = saves.mii.getElement(MII_LEAVES.names, s);\n out.push({ slot: s + 1, empty, name: empty ? '' : name });\n }\n return out;\n}\n\nfunction isEmptyDataBlock(data: Uint8Array): boolean {\n if (data.byteLength !== MII_DATA_LEN) return false;\n for (const b of data) if (b !== 0) return false;\n return true;\n}\n\nfunction isEmptyMiiBlock(block: Uint8Array): boolean {\n if (block.byteLength !== MII_BLOCK_LEN) return false;\n let sum = 0;\n for (const b of block) sum += b;\n return sum === 152;\n}\n\nfunction readMiiBlock(saves: MiiSaves, isTemp: boolean, slotIdx: number): Uint8Array {\n if (isTemp) {\n const data = saves.player.get(PLAYER_LEAVES.tempSlot);\n if (data.byteLength < MII_DATA_LEN) throw new ShareMiiError('mii_not_initialized');\n return wrapMiiBlock(data.subarray(0, MII_DATA_LEN));\n }\n const data = saves.mii.getElement(MII_LEAVES.rawMii, slotIdx);\n if (data.byteLength !== MII_DATA_LEN) {\n throw new ShareMiiError('save_format_error', { label: 'Mii.Raw' });\n }\n return wrapMiiBlock(data);\n}\n\nfunction writeMiiBlock(saves: MiiSaves, isTemp: boolean, slotIdx: number, block: Uint8Array): void {\n const data = unwrapMiiBlock(block);\n if (isTemp) {\n const buf = saves.player.get(PLAYER_LEAVES.tempSlot);\n buf.set(data, 0);\n saves.player.set(PLAYER_LEAVES.tempSlot, buf);\n } else {\n saves.mii.setElement(MII_LEAVES.rawMii, slotIdx, data);\n }\n}\n\nexport type ExtractMiiResult = {\n bytes: Uint8Array;\n fileName: string;\n miiName: string;\n facepaint: SidecarFile[];\n};\n\nexport function extractMii(\n saves: MiiSaves,\n slot: number,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): ExtractMiiResult {\n const isTemp = slot === 0;\n const slotIdx = slot - 1;\n\n const block = readMiiBlock(saves, isTemp, slotIdx);\n if (isEmptyMiiBlock(block)) {\n throw new ShareMiiError('mii_not_initialized');\n }\n\n let facepaintId: number | null = null;\n if (isTemp) {\n if (saves.player.getElement(PLAYER_LEAVES.fpState, 70) !== FP_STATE_UNUSED) facepaintId = 70;\n } else {\n const id = saves.mii.getElement(MII_LEAVES.facePaintIndex, slotIdx);\n if (id !== FP_INDEX_UNUSED) facepaintId = id;\n }\n\n const personality = new Uint8Array(72);\n const dv = new DataView(personality.buffer);\n for (let i = 0; i < 18; i++) {\n const v = isTemp ? 0 : getPersonalityElement(saves.mii, MII_LEAVES.personality[i], slotIdx);\n dv.setInt32(i * 4, v | 0, true);\n }\n\n const name = new Uint8Array(64);\n let decodedName: string;\n if (isTemp) {\n const tempName = new TextEncoder().encode('Temp');\n for (let i = 0; i < tempName.length; i++) name[i * 2] = tempName[i];\n decodedName = 'Mii';\n } else {\n const nameStr = saves.mii.getElement(MII_LEAVES.names, slotIdx);\n name.set(encodeUtf16Name(nameStr, 64));\n decodedName = decodeUtf16Name(name);\n }\n\n const pronounce = new Uint8Array(128);\n if (!isTemp) {\n const pStr = saves.mii.getElement(MII_LEAVES.pronunciation, slotIdx);\n pronounce.set(encodeUtf16Name(pStr, 128));\n }\n\n const sexuality = new Uint8Array(4);\n if (!isTemp) {\n const base = slotIdx * 3;\n sexuality[0] = saves.mii.getElement(MII_LEAVES.isLoveGender, base) ? 1 : 0;\n sexuality[1] = saves.mii.getElement(MII_LEAVES.isLoveGender, base + 1) ? 1 : 0;\n sexuality[2] = saves.mii.getElement(MII_LEAVES.isLoveGender, base + 2) ? 1 : 0;\n }\n\n let canvasTex = new Uint8Array(0);\n let ugcTex = new Uint8Array(0);\n const facepaint: SidecarFile[] = [];\n if (facepaintId !== null) {\n const canvasName = facepaintCanvasFileName(facepaintId);\n const texName = facepaintTexFileName(facepaintId);\n const c = sidecar.files.get(canvasName);\n const t = sidecar.files.get(texName);\n if (c && t) {\n canvasTex = new Uint8Array(c);\n ugcTex = new Uint8Array(t);\n facepaint.push({ name: canvasName, bytes: canvasTex }, { name: texName, bytes: ugcTex });\n }\n }\n\n const ltd: LtdMii = {\n version: isTemp ? 1 : 3,\n originalVersion: isTemp ? 1 : 3,\n hasCanvas: canvasTex.byteLength > 0,\n hasUgcTex: ugcTex.byteLength > 0,\n miiBlock: block.slice(),\n personality,\n name,\n pronounce,\n sexuality,\n canvasTex,\n ugcTex,\n };\n const bytes = encodeLtdMii(ltd);\n\n const baseName = isTemp ? 'Mii' : sanitizeFileName(decodedName);\n return {\n bytes,\n fileName: `${baseName}.ltd`,\n miiName: decodedName || 'Mii',\n facepaint,\n };\n}\n\nexport type ApplyMiiResult = {\n facepaintWrites: SidecarFile[];\n};\n\nexport function applyMii(\n saves: MiiSaves,\n slot: number,\n ltdBytes: Uint8Array,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): ApplyMiiResult {\n const ltd = decodeLtdMii(ltdBytes);\n\n const isTemp = slot === 0;\n const slotIdx = slot - 1;\n\n if (!isTemp && isEmptyMiiBlock(readMiiBlock(saves, isTemp, slotIdx))) {\n throw new ShareMiiError('mii_not_initialized');\n }\n\n writeMiiBlock(saves, isTemp, slotIdx, ltd.miiBlock);\n\n const facepaintAvailable: 'inline' | null = ltd.hasCanvas && ltd.hasUgcTex ? 'inline' : null;\n\n const prevFacepaintId = isTemp\n ? FP_INDEX_UNUSED\n : saves.mii.getElement(MII_LEAVES.facePaintIndex, slotIdx);\n\n let facepaintId = prevFacepaintId;\n const facepaintWrites: SidecarFile[] = [];\n\n if (facepaintAvailable === 'inline') {\n if (isTemp) {\n facepaintId = 70;\n } else if (facepaintId === FP_INDEX_UNUSED) {\n facepaintId = pickFacepaintId(saves.mii);\n saves.mii.setElement(MII_LEAVES.facePaintIndex, slotIdx, facepaintId);\n }\n saves.player.setElement(PLAYER_LEAVES.fpPrice, facepaintId, FP_PRICE);\n saves.player.setElement(PLAYER_LEAVES.fpTexSrc, facepaintId, FP_TEX_SRC_USED);\n saves.player.setElement(PLAYER_LEAVES.fpState, facepaintId, FP_STATE_USED);\n saves.player.setElement(PLAYER_LEAVES.fpUnknown, facepaintId, FP_UNKNOWN_USED);\n saves.player.setElement(PLAYER_LEAVES.fpHash, facepaintId, fpHashValue(facepaintId));\n\n facepaintWrites.push({\n name: facepaintCanvasFileName(facepaintId),\n bytes: ltd.canvasTex,\n });\n facepaintWrites.push({\n name: facepaintTexFileName(facepaintId),\n bytes: ltd.ugcTex,\n });\n } else if (prevFacepaintId !== FP_INDEX_UNUSED) {\n if (!isTemp) {\n saves.mii.setElement(MII_LEAVES.facePaintIndex, slotIdx, FP_INDEX_UNUSED);\n }\n saves.player.setElement(PLAYER_LEAVES.fpPrice, prevFacepaintId, 0);\n saves.player.setElement(PLAYER_LEAVES.fpTexSrc, prevFacepaintId, FP_TEX_SRC_UNUSED);\n saves.player.setElement(PLAYER_LEAVES.fpState, prevFacepaintId, FP_STATE_UNUSED);\n saves.player.setElement(PLAYER_LEAVES.fpUnknown, prevFacepaintId, FP_UNKNOWN_UNUSED);\n saves.player.setElement(PLAYER_LEAVES.fpHash, prevFacepaintId, FP_HASH_UNUSED);\n }\n\n if (ltd.originalVersion >= 2 && !isTemp) {\n const sdv = new DataView(\n ltd.personality.buffer,\n ltd.personality.byteOffset,\n ltd.personality.byteLength,\n );\n for (let i = 0; i < 18; i++) {\n setPersonalityElement(\n saves.mii,\n MII_LEAVES.personality[i],\n slotIdx,\n sdv.getInt32(i * 4, true),\n );\n }\n saves.mii.setElement(MII_LEAVES.names, slotIdx, decodeUtf16Name(ltd.name));\n saves.mii.setElement(MII_LEAVES.pronunciation, slotIdx, decodeUtf16Name(ltd.pronounce));\n\n if (saves.mii.getElement(MII_LEAVES.satisfyLevel, slotIdx) < 2) {\n const base = slotIdx * 3;\n saves.mii.setElement(MII_LEAVES.isLoveGender, base, (ltd.sexuality[0] & 1) === 1);\n saves.mii.setElement(MII_LEAVES.isLoveGender, base + 1, (ltd.sexuality[1] & 1) === 1);\n saves.mii.setElement(MII_LEAVES.isLoveGender, base + 2, (ltd.sexuality[2] & 1) === 1);\n }\n }\n\n if (sidecar.origin !== 'none' && facepaintWrites.length > 0) {\n for (const f of facepaintWrites) sidecar.files.set(f.name, f.bytes);\n }\n\n return { facepaintWrites };\n}\n\nfunction pickFacepaintId(mii: Accessor<'mii'>): number {\n const used = new Set<number>();\n for (let s = 0; s < MII_SLOTS; s++) {\n const id = mii.getElement(MII_LEAVES.facePaintIndex, s);\n if (id !== FP_INDEX_UNUSED) used.add(id);\n }\n for (let i = 0; i < MII_SLOTS; i++) {\n if (!used.has(i)) return i;\n }\n throw new ShareMiiError('no_free_facepaint_slot');\n}\n","import { arrayElementSize, DataType, type Accessor, buildHashMap } from '@alexislours/ltd-savedata';\nimport { PLAYER_SCHEMA, type SchemaLeaf } from '@alexislours/ltd-savedata/schema';\nimport { decodeLtdUgc, encodeLtdUgc, type LtdUgc } from './codec.js';\nimport { ShareMiiError } from './errors.js';\nimport { leafByHashOrThrow, type PlayerOnlySaves } from './savAccess.js';\nimport {\n UGC_ENABLE_HASHES,\n UGC_FILE_EXTENSIONS,\n UGC_HASHES,\n UGC_HASH_ID_HASHES,\n UGC_HASH_INDICES,\n UGC_MAX_SLOTS,\n UGC_NAME_HASHES,\n UGC_TEX_DATA,\n UGC_TEXTURE_HASHES,\n type UgcKind,\n ugcCanvasFileName,\n ugcKindIndex,\n ugcTexFileName,\n ugcThumbFileName,\n} from './ugcKinds.js';\nimport { decodeUtf16Name, encodeUtf16Name, sanitizeFileName } from './utf16.js';\nimport { EMPTY_SIDECAR, type SidecarFile, type SidecarSource } from './sidecar.js';\n\nconst ENABLE_USED = 0x1d7fadf4 >>> 0;\n\ntype ScalarFieldType =\n | DataType.IntArray\n | DataType.UIntArray\n | DataType.EnumArray\n | DataType.FloatArray\n | DataType.BoolArray;\n\ntype NameType = DataType.WString32Array | DataType.WString64Array;\n\ntype UgcLeaves = {\n fields: SchemaLeaf<ScalarFieldType>[];\n names: SchemaLeaf<NameType>[];\n vector: SchemaLeaf<DataType.Vector3Array> | null;\n vector2: SchemaLeaf<DataType.Vector2Array> | null;\n enable: SchemaLeaf<DataType.EnumArray>;\n texture: SchemaLeaf<DataType.EnumArray>;\n hashId: SchemaLeaf<DataType.UIntArray>;\n};\n\nfunction resolveScalarFieldLeaf(hash: number, label: string): SchemaLeaf<ScalarFieldType> {\n const leaf = buildHashMap(PLAYER_SCHEMA).get(hash >>> 0);\n if (!leaf) throw new ShareMiiError('save_format_error', { label });\n const t = leaf.type;\n if (\n t !== DataType.IntArray &&\n t !== DataType.UIntArray &&\n t !== DataType.EnumArray &&\n t !== DataType.FloatArray &&\n t !== DataType.BoolArray\n ) {\n throw new ShareMiiError('save_format_error', { label });\n }\n return leaf as SchemaLeaf<ScalarFieldType>;\n}\n\nfunction resolveNameLeaf(hash: number, label: string): SchemaLeaf<NameType> {\n const leaf = buildHashMap(PLAYER_SCHEMA).get(hash >>> 0);\n if (!leaf) throw new ShareMiiError('save_format_error', { label });\n const t = leaf.type;\n if (t !== DataType.WString32Array && t !== DataType.WString64Array) {\n throw new ShareMiiError('save_format_error', { label });\n }\n return leaf as SchemaLeaf<NameType>;\n}\n\nfunction resolveUgcLeaves(kind: UgcKind): UgcLeaves {\n const h = UGC_HASHES[kind];\n return {\n fields: h.fields.map((hash, i) => resolveScalarFieldLeaf(hash, `${kind}.field[${i}]`)),\n names: h.names.map((hash, i) => resolveNameLeaf(hash, `${kind}.name[${i}]`)),\n vector: h.vector\n ? leafByHashOrThrow(PLAYER_SCHEMA, h.vector, `${kind}.vector`, DataType.Vector3Array)\n : null,\n vector2: h.vector2\n ? leafByHashOrThrow(PLAYER_SCHEMA, h.vector2, `${kind}.vector2`, DataType.Vector2Array)\n : null,\n enable: leafByHashOrThrow(\n PLAYER_SCHEMA,\n UGC_ENABLE_HASHES[kind],\n `${kind}.enable`,\n DataType.EnumArray,\n ),\n texture: leafByHashOrThrow(\n PLAYER_SCHEMA,\n UGC_TEXTURE_HASHES[kind],\n `${kind}.texture`,\n DataType.EnumArray,\n ),\n hashId: leafByHashOrThrow(\n PLAYER_SCHEMA,\n UGC_HASH_ID_HASHES[kind],\n `${kind}.hashId`,\n DataType.UIntArray,\n ),\n };\n}\n\nfunction ugcSlotCapacity(saves: PlayerOnlySaves, leaves: UgcLeaves, kind: UgcKind): number {\n const player = saves.player;\n let cap = UGC_MAX_SLOTS[kind];\n for (const leaf of leaves.fields) cap = Math.min(cap, (player.get(leaf) as unknown[]).length);\n for (const leaf of leaves.names) cap = Math.min(cap, (player.get(leaf) as unknown[]).length);\n if (leaves.vector) cap = Math.min(cap, (player.get(leaves.vector) as unknown[]).length);\n if (leaves.vector2) cap = Math.min(cap, (player.get(leaves.vector2) as unknown[]).length);\n cap = Math.min(cap, (player.get(leaves.enable) as unknown[]).length);\n cap = Math.min(cap, (player.get(leaves.texture) as unknown[]).length);\n cap = Math.min(cap, (player.get(leaves.hashId) as unknown[]).length);\n return cap;\n}\n\nfunction readField4(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<ScalarFieldType>,\n slotIdx: number,\n): Uint8Array {\n const out = new Uint8Array(4);\n const dv = new DataView(out.buffer);\n switch (leaf.type) {\n case DataType.IntArray:\n dv.setInt32(0, player.getElement(leaf as SchemaLeaf<DataType.IntArray>, slotIdx) | 0, true);\n return out;\n case DataType.UIntArray:\n dv.setUint32(\n 0,\n player.getElement(leaf as SchemaLeaf<DataType.UIntArray>, slotIdx) >>> 0,\n true,\n );\n return out;\n case DataType.EnumArray:\n dv.setUint32(\n 0,\n player.getElement(leaf as SchemaLeaf<DataType.EnumArray>, slotIdx) >>> 0,\n true,\n );\n return out;\n case DataType.FloatArray:\n dv.setFloat32(0, player.getElement(leaf as SchemaLeaf<DataType.FloatArray>, slotIdx), true);\n return out;\n case DataType.BoolArray:\n out[0] = player.getElement(leaf as SchemaLeaf<DataType.BoolArray>, slotIdx) ? 1 : 0;\n return out;\n }\n}\n\nfunction writeField4(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<ScalarFieldType>,\n slotIdx: number,\n src: Uint8Array,\n): void {\n const dv = new DataView(src.buffer, src.byteOffset, 4);\n switch (leaf.type) {\n case DataType.IntArray:\n player.setElement(leaf as SchemaLeaf<DataType.IntArray>, slotIdx, dv.getInt32(0, true) | 0);\n return;\n case DataType.UIntArray:\n player.setElement(\n leaf as SchemaLeaf<DataType.UIntArray>,\n slotIdx,\n dv.getUint32(0, true) >>> 0,\n );\n return;\n case DataType.EnumArray:\n player.setElement(\n leaf as SchemaLeaf<DataType.EnumArray>,\n slotIdx,\n dv.getUint32(0, true) >>> 0,\n );\n return;\n case DataType.FloatArray:\n player.setElement(leaf as SchemaLeaf<DataType.FloatArray>, slotIdx, dv.getFloat32(0, true));\n return;\n case DataType.BoolArray:\n player.setElement(\n leaf as SchemaLeaf<DataType.BoolArray>,\n slotIdx,\n (src[0] | src[1] | src[2] | src[3]) !== 0,\n );\n return;\n }\n}\n\nfunction nameByteLen(leaf: SchemaLeaf<NameType>): 64 | 128 {\n const sz = arrayElementSize(leaf.type);\n if (sz !== 64 && sz !== 128) {\n throw new ShareMiiError('save_format_error', { label: 'name' });\n }\n return sz as 64 | 128;\n}\n\nfunction readNameBlock(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<NameType>,\n slotIdx: number,\n): Uint8Array {\n const str = player.getElement(leaf, slotIdx);\n return encodeUtf16Name(str, nameByteLen(leaf));\n}\n\nfunction writeNameBlock(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<NameType>,\n slotIdx: number,\n src: Uint8Array,\n): void {\n player.setElement(leaf, slotIdx, decodeUtf16Name(src));\n}\n\nfunction readVector3(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<DataType.Vector3Array>,\n slotIdx: number,\n): Uint8Array {\n const v = player.getElement(leaf, slotIdx);\n const out = new Uint8Array(12);\n const dv = new DataView(out.buffer);\n dv.setFloat32(0, v.x, true);\n dv.setFloat32(4, v.y, true);\n dv.setFloat32(8, v.z, true);\n return out;\n}\n\nfunction writeVector3(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<DataType.Vector3Array>,\n slotIdx: number,\n src: Uint8Array,\n): void {\n const dv = new DataView(src.buffer, src.byteOffset, 12);\n player.setElement(leaf, slotIdx, {\n x: dv.getFloat32(0, true),\n y: dv.getFloat32(4, true),\n z: dv.getFloat32(8, true),\n });\n}\n\nfunction readVector2(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<DataType.Vector2Array>,\n slotIdx: number,\n): Uint8Array {\n const v = player.getElement(leaf, slotIdx);\n const out = new Uint8Array(8);\n const dv = new DataView(out.buffer);\n dv.setFloat32(0, v.x, true);\n dv.setFloat32(4, v.y, true);\n return out;\n}\n\nfunction writeVector2(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<DataType.Vector2Array>,\n slotIdx: number,\n src: Uint8Array,\n): void {\n const dv = new DataView(src.buffer, src.byteOffset, 8);\n player.setElement(leaf, slotIdx, {\n x: dv.getFloat32(0, true),\n y: dv.getFloat32(4, true),\n });\n}\n\nexport type UgcSlotInfo = {\n slot: number;\n empty: boolean;\n name: string;\n isAddNew: boolean;\n};\n\nexport function listUgcSlots(\n saves: PlayerOnlySaves,\n kind: UgcKind,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): UgcSlotInfo[] {\n const out: UgcSlotInfo[] = [];\n let max = UGC_MAX_SLOTS[kind];\n let nameLeaf: SchemaLeaf<NameType> | null;\n try {\n const leaves = resolveUgcLeaves(kind);\n nameLeaf = resolveNameLeaf(UGC_NAME_HASHES[kind], `${kind}.names`);\n max = ugcSlotCapacity(saves, leaves, kind);\n } catch {\n nameLeaf = null;\n }\n\n let foundAddSlot = false;\n for (let i = 0; i < max; i++) {\n const fileName = ugcCanvasFileName(kind, i);\n const exists = sidecar.files.has(fileName);\n const decoded = nameLeaf ? saves.player.getElement(nameLeaf, i) : '';\n const looksFilled = decoded.length > 0;\n\n if (exists || (sidecar.origin === 'none' && looksFilled)) {\n out.push({ slot: i + 1, empty: false, name: decoded, isAddNew: false });\n } else if (!foundAddSlot) {\n out.push({ slot: i + 1, empty: true, name: '', isAddNew: true });\n foundAddSlot = true;\n }\n }\n return out;\n}\n\nexport type ExtractUgcResult = {\n bytes: Uint8Array;\n fileName: string;\n itemName: string;\n textures: SidecarFile[];\n};\n\nexport function extractUgc(\n saves: PlayerOnlySaves,\n slot: number,\n kind: UgcKind,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): ExtractUgcResult {\n const leaves = resolveUgcLeaves(kind);\n const player = saves.player;\n const slotIdx = slot - 1;\n const kindIndex = ugcKindIndex(kind);\n\n const fields = new Uint8Array(leaves.fields.length * 4);\n for (let i = 0; i < leaves.fields.length; i++) {\n fields.set(readField4(player, leaves.fields[i], slotIdx), i * 4);\n }\n const vector = leaves.vector ? readVector3(player, leaves.vector, slotIdx) : new Uint8Array(12);\n const vector2 = leaves.vector2 ? readVector2(player, leaves.vector2, slotIdx) : new Uint8Array(8);\n const name = readNameBlock(player, leaves.names[0], slotIdx);\n const pronounce = readNameBlock(player, leaves.names[1], slotIdx);\n\n let goodsText: Uint8Array | undefined;\n let goodsPronounce: Uint8Array | undefined;\n if (kind === 'Goods' && leaves.names[2] !== undefined && leaves.names[3] !== undefined) {\n goodsText = readNameBlock(player, leaves.names[2], slotIdx);\n goodsPronounce = readNameBlock(player, leaves.names[3], slotIdx);\n }\n\n const canvasName = ugcCanvasFileName(kind, slotIdx);\n const texName = ugcTexFileName(kind, slotIdx);\n const thumbName = ugcThumbFileName(kind, slotIdx);\n const canvasTex = sidecar.files.get(canvasName);\n const ugcTex = sidecar.files.get(texName);\n const thumbTex = sidecar.files.get(thumbName);\n\n if (!canvasTex || !ugcTex || !thumbTex) {\n throw new ShareMiiError('ugc_missing_textures');\n }\n\n const ltd: LtdUgc = {\n kindIndex,\n fields,\n vector,\n vector2,\n name,\n pronounce,\n goodsText,\n goodsPronounce,\n canvasTex,\n ugcTex,\n thumbTex,\n };\n const bytes = encodeLtdUgc(ltd);\n const decodedName = decodeUtf16Name(name) || `Ugc${kind}${slotIdx}`;\n const fileName = `${sanitizeFileName(decodedName)}${UGC_FILE_EXTENSIONS[kind]}`;\n return {\n bytes,\n fileName,\n itemName: decodedName,\n textures: [\n { name: canvasName, bytes: canvasTex },\n { name: texName, bytes: ugcTex },\n { name: thumbName, bytes: thumbTex },\n ],\n };\n}\n\nexport type ApplyUgcResult = {\n textureWrites: SidecarFile[];\n};\n\nexport function applyUgc(\n saves: PlayerOnlySaves,\n slot: number,\n kind: UgcKind,\n ltdBytes: Uint8Array,\n isAdding: boolean,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): ApplyUgcResult {\n const decoded = decodeLtdUgc(ltdBytes);\n const expected = ugcKindIndex(kind);\n if (decoded.kindIndex !== expected) {\n throw new ShareMiiError('wrong_ugc_kind', { got: decoded.kindIndex, expected });\n }\n\n const leaves = resolveUgcLeaves(kind);\n const player = saves.player;\n const slotIdx = slot - 1;\n const capacity = ugcSlotCapacity(saves, leaves, kind);\n if (slotIdx < 0 || slotIdx >= capacity) {\n throw new ShareMiiError('slot_out_of_range', { slot, kind, capacity });\n }\n\n if ((kind === 'Cloth' || kind === 'Goods') && !isAdding) {\n const existing = readField4(player, leaves.fields[0], slotIdx);\n const incoming = decoded.fieldsAndVectors.subarray(0, 4);\n if (!buffersEqual(existing, incoming)) {\n throw new ShareMiiError('subtype_mismatch');\n }\n }\n if ((kind === 'Exterior' || kind === 'MapObject') && !isAdding) {\n throw new ShareMiiError('cannot_replace_kind', { kind });\n }\n\n for (let i = 0; i < leaves.fields.length; i++) {\n const src = decoded.fieldsAndVectors.subarray(i * 4, i * 4 + 4);\n writeField4(player, leaves.fields[i], slotIdx, src);\n }\n\n if (isAdding) {\n player.setElement(leaves.enable, slotIdx, ENABLE_USED);\n const texDv = new DataView(\n UGC_TEX_DATA.buffer,\n UGC_TEX_DATA.byteOffset,\n UGC_TEX_DATA.byteLength,\n );\n const texVal = texDv.getUint32(expected * 4, true) >>> 0;\n player.setElement(leaves.texture, slotIdx, texVal);\n const hashIdVal = ((slotIdx & 0xff) | ((UGC_HASH_INDICES[kind] & 0xff) << 16)) >>> 0;\n player.setElement(leaves.hashId, slotIdx, hashIdVal);\n }\n\n const namesBlock = decoded.namesBlock;\n writeNameBlock(player, leaves.names[0], slotIdx, namesBlock.subarray(0, 128));\n writeNameBlock(player, leaves.names[1], slotIdx, namesBlock.subarray(128, 256));\n if (kind === 'Goods' && leaves.names[2] !== undefined && leaves.names[3] !== undefined) {\n writeNameBlock(player, leaves.names[2], slotIdx, namesBlock.subarray(256, 320));\n writeNameBlock(player, leaves.names[3], slotIdx, namesBlock.subarray(320, 448));\n }\n\n const fav = decoded.fieldsAndVectors;\n if (leaves.vector) {\n const vStart = fav.byteLength - 20;\n writeVector3(player, leaves.vector, slotIdx, fav.subarray(vStart, vStart + 12));\n }\n if (leaves.vector2) {\n const v2Start = fav.byteLength - 8;\n writeVector2(player, leaves.vector2, slotIdx, fav.subarray(v2Start, v2Start + 8));\n }\n\n const writes: SidecarFile[] = [\n { name: ugcCanvasFileName(kind, slotIdx), bytes: decoded.canvasTex },\n { name: ugcTexFileName(kind, slotIdx), bytes: decoded.ugcTex },\n { name: ugcThumbFileName(kind, slotIdx), bytes: decoded.thumbTex },\n ];\n if (sidecar.origin !== 'none') {\n for (const f of writes) sidecar.files.set(f.name, f.bytes);\n }\n\n return { textureWrites: writes };\n}\n\nfunction buffersEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.byteLength !== b.byteLength) return false;\n for (let i = 0; i < a.byteLength; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n"],"mappings":"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","names":["DataType","buildHashMap","MII_SCHEMA","PLAYER_SCHEMA","PLAYER_SCHEMA","DataType","MII_SCHEMA","buildHashMap","data","DataType","buildHashMap","PLAYER_SCHEMA","buildHashMap","PLAYER_SCHEMA","DataType"]}
1
+ {"version":3,"sources":["../src/sidecar.ts","../src/errors.ts","../src/utf16.ts","../src/ugcKinds.ts","../src/savAccess.ts","../src/codec.ts","../src/applyMii.ts","../src/applyUgc.ts"],"sourcesContent":["/**\n * A single named texture blob that travels alongside a share file, keyed by its\n * in-save file name (for example `UgcFood000.canvas.zs`).\n */\nexport type SidecarFile = {\n /** In-save file name, used as the lookup key inside a {@link SidecarSource}. */\n name: string;\n /** Raw, still-compressed file contents. */\n bytes: Uint8Array;\n};\n\n/**\n * A pool of texture files accompanying a save, indexed by file name. `origin`\n * records where it came from so writes can be skipped when there is nowhere to\n * persist them (`'none'`).\n */\nexport type SidecarSource = {\n /** Where the files were loaded from; `'none'` means there is no backing store to write to. */\n origin: 'none' | 'folder' | 'zip';\n /** File name to raw bytes. Mutated in place when applying a share file with a writable origin. */\n files: Map<string, Uint8Array>;\n};\n\n/** A shared, empty {@link SidecarSource} (`origin: 'none'`) used as the default when no textures are supplied. */\nexport const EMPTY_SIDECAR: SidecarSource = {\n origin: 'none',\n files: new Map(),\n};\n\n/** Strip any directory prefix from `name`, returning just the final path segment (handles both `/` and `\\` separators). */\nexport function normalizeName(name: string): string {\n const idx = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\\\'));\n return idx >= 0 ? name.slice(idx + 1) : name;\n}\n\n/** Whether `name` is a recognized sidecar texture file (a `.canvas.zs` or `.ugctex.zs` blob), case-insensitively. */\nexport function isSidecarFileName(name: string): boolean {\n const lower = name.toLowerCase();\n return lower.endsWith('.canvas.zs') || lower.endsWith('.ugctex.zs');\n}\n\n/**\n * Whether an archive entry should be ignored when ingesting a folder or zip:\n * directory entries, `__MACOSX` cruft, dotfiles, and empty paths all count as junk.\n */\nexport function isJunkArchiveEntry(path: string): boolean {\n if (!path) return true;\n if (path.endsWith('/') || path.endsWith('\\\\')) return true;\n if (path.includes('__MACOSX/') || path.includes('__MACOSX\\\\')) return true;\n const idx = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\\\'));\n const base = idx >= 0 ? path.slice(idx + 1) : path;\n if (!base || base.startsWith('.')) return true;\n return false;\n}\n","/**\n * Stable, machine-readable identifier for every failure {@link ShareMiiError}\n * can raise. Used as the error `message` and exposed via {@link ShareMiiError.code}\n * so callers can branch or localize without parsing prose.\n */\nexport type ShareMiiErrorCode =\n | 'mii_not_initialized'\n | 'no_free_facepaint_slot'\n | 'ugc_missing_textures'\n | 'wrong_ugc_kind'\n | 'subtype_mismatch'\n | 'cannot_replace_kind'\n | 'invalid_ltd_file'\n | 'unsupported_ltd_version'\n | 'ltd_missing_marker'\n | 'invalid_ugc_kind_index'\n | 'invalid_zip'\n | 'save_format_error'\n | 'slot_out_of_range';\n\n/**\n * Error thrown by every operation in this package when extraction or application\n * fails for a known reason. The {@link ShareMiiErrorCode} carries the cause and\n * {@link ShareMiiError.params} any contextual values for messaging.\n */\nexport class ShareMiiError extends Error {\n /** The machine-readable failure cause; also used as the `Error` message. */\n readonly code: ShareMiiErrorCode;\n /** Contextual values for the failure (slot number, kind, marker name, and so on), suitable for interpolation into a localized message. */\n readonly params: Record<string, string | number>;\n /** Construct an error for `code`, attaching optional `params` for messaging. */\n constructor(code: ShareMiiErrorCode, params: Record<string, string | number> = {}) {\n super(code);\n this.name = 'ShareMiiError';\n this.code = code;\n this.params = params;\n }\n}\n","/**\n * Decode a fixed-width little-endian UTF-16 name buffer into a string, stopping\n * at the first NUL code unit (the in-save string terminator).\n */\nexport function decodeUtf16Name(buf: Uint8Array): string {\n let end = 0;\n while (end + 1 < buf.byteLength) {\n if (buf[end] === 0 && buf[end + 1] === 0) break;\n end += 2;\n }\n const code: number[] = [];\n for (let i = 0; i < end; i += 2) {\n code.push(buf[i] | (buf[i + 1] << 8));\n }\n return String.fromCharCode(...code);\n}\n\n/**\n * Reduce a display name to a safe file-name stem by replacing every character\n * outside `[A-Za-z0-9_.-]` with `_`, falling back to `'mii'` when nothing remains.\n */\nexport function sanitizeFileName(name: string): string {\n const cleaned = name.replace(/[^\\w.-]/g, '_');\n return cleaned.length > 0 ? cleaned : 'mii';\n}\n\n/**\n * Encode `text` as little-endian UTF-16 into a fresh `byteLen`-byte buffer,\n * truncating to fit while always leaving room for the trailing NUL terminator.\n */\nexport function encodeUtf16Name(text: string, byteLen: number): Uint8Array {\n const out = new Uint8Array(byteLen);\n const maxChars = Math.floor((byteLen - 2) / 2);\n const truncated = text.length > maxChars ? text.slice(0, maxChars) : text;\n for (let i = 0; i < truncated.length; i++) {\n const code = truncated.charCodeAt(i);\n out[i * 2] = code & 0xff;\n out[i * 2 + 1] = (code >> 8) & 0xff;\n }\n return out;\n}\n","/** The seven categories of user-generated content the game stores and this codec can share. */\nexport type UgcKind =\n | 'Food'\n | 'Cloth'\n | 'Goods'\n | 'Interior'\n | 'Exterior'\n | 'MapObject'\n | 'MapFloor';\n\n/** Every {@link UgcKind} in canonical order; the array index is the kind's on-disk index (see {@link ugcKindIndex}). */\nexport const UGC_KINDS: readonly UgcKind[] = [\n 'Food',\n 'Cloth',\n 'Goods',\n 'Interior',\n 'Exterior',\n 'MapObject',\n 'MapFloor',\n];\n\n/** Human-facing label for each {@link UgcKind}, which differs from the internal name (for example `Goods` is shown as \"Treasure\"). */\nexport const UGC_DISPLAY_LABELS: Record<UgcKind, string> = {\n Food: 'Food',\n Cloth: 'Clothing',\n Goods: 'Treasure',\n Interior: 'Interior',\n Exterior: 'Exterior',\n MapObject: 'Objects',\n MapFloor: 'Landscaping',\n};\n\n/** Share-file extension for each {@link UgcKind} (for example `Food` exports as `.ltdf`). */\nexport const UGC_FILE_EXTENSIONS: Record<UgcKind, string> = {\n Food: '.ltdf',\n Cloth: '.ltdc',\n Goods: '.ltdg',\n Interior: '.ltdi',\n Exterior: '.ltde',\n MapObject: '.ltdo',\n MapFloor: '.ltdl',\n};\n\n/** The on-disk index of `kind`, that is, its position in {@link UGC_KINDS}. */\nexport function ugcKindIndex(kind: UgcKind): number {\n return UGC_KINDS.indexOf(kind);\n}\n\n/** Maximum number of slots the game allocates per {@link UgcKind}; the actual capacity may be lower and is clamped against the save's array lengths. */\nexport const UGC_MAX_SLOTS: Record<UgcKind, number> = {\n Food: 99,\n Cloth: 299,\n Goods: 99,\n Interior: 99,\n Exterior: 99,\n MapObject: 99,\n MapFloor: 99,\n};\n\nfunction ugcFileBase(kind: UgcKind, slot: number): string {\n return `Ugc${kind}${String(slot).padStart(3, '0')}`;\n}\n\n/** In-save file name of the editable canvas texture for a UGC `slot` of `kind` (for example `UgcFood003.canvas.zs`). */\nexport function ugcCanvasFileName(kind: UgcKind, slot: number): string {\n return `${ugcFileBase(kind, slot)}.canvas.zs`;\n}\n\n/** In-save file name of the rendered UGC texture for a `slot` of `kind` (for example `UgcFood003.ugctex.zs`). */\nexport function ugcTexFileName(kind: UgcKind, slot: number): string {\n return `${ugcFileBase(kind, slot)}.ugctex.zs`;\n}\n\n/** In-save file name of the thumbnail texture for a `slot` of `kind` (for example `UgcFood003_Thumb.ugctex.zs`). */\nexport function ugcThumbFileName(kind: UgcKind, slot: number): string {\n return `${ugcFileBase(kind, slot)}_Thumb.ugctex.zs`;\n}\n\nfunction facepaintFileBase(id: number): string {\n return `UgcFacePaint${String(id).padStart(3, '0')}`;\n}\n\n/** In-save file name of the canvas texture for facepaint `id` (for example `UgcFacePaint012.canvas.zs`). */\nexport function facepaintCanvasFileName(id: number): string {\n return `${facepaintFileBase(id)}.canvas.zs`;\n}\n\n/** In-save file name of the rendered texture for facepaint `id` (for example `UgcFacePaint012.ugctex.zs`). */\nexport function facepaintTexFileName(id: number): string {\n return `${facepaintFileBase(id)}.ugctex.zs`;\n}\n\n/** The set of save-field hashes that make up one {@link UgcKind}: its scalar fields, name strings, and optional position vectors. */\nexport type UgcFieldHashes = {\n /** Hashes of the scalar (int/uint/enum/float/bool) fields, in serialization order. */\n fields: readonly number[];\n /** Hashes of the name string fields (name, pronunciation, and for Goods two extra strings). */\n names: readonly number[];\n /** Hash of the optional `Vector3` field, when the kind has one. */\n vector?: number;\n /** Hash of the optional `Vector2` field, when the kind has one. */\n vector2?: number;\n};\n\n/** Per-{@link UgcKind} map of the save-field hashes ({@link UgcFieldHashes}) the codec reads and writes for that kind. */\nexport const UGC_HASHES: Record<UgcKind, UgcFieldHashes> = {\n Food: {\n fields: [\n 0x307feefa, 0x6f93ffbd, 0x5ca9336e, 0xf768620a, 0x5af04beb, 0x2db168c5, 0x634800ae,\n 0xdd8d6c5a, 0xaf1186cf, 0x58e6aad3,\n ],\n names: [0x408494f5, 0xba0f4baf],\n },\n Cloth: {\n fields: [\n 0xc81545fe, 0x2fb9146d, 0x7a31ef97, 0x7eec35e9, 0x5e32fd3f, 0x0dbabe27, 0x71621c98,\n 0x2d271339, 0xcdf31eb5, 0x2823dbd3,\n ],\n names: [0x40710642, 0xcf9a13ea],\n },\n Goods: {\n fields: [\n 0x3faa2222, 0x823f8297, 0x7ecc8a60, 0x88dc1d43, 0x8896ddd6, 0xbff29472, 0x5d965762,\n 0x78d39208, 0x53c762b0, 0x40d2c6fe, 0xc0a6c046, 0xae373b0d, 0x7d5ffbb7, 0x9e978f5e,\n 0xf6349929, 0x9038cdd0, 0x9a59f58a,\n ],\n names: [0x2f793eb1, 0xf655b33a, 0xf36a5a0b, 0xa66367eb],\n vector: 0xf36c4e28,\n },\n Interior: {\n fields: [\n 0xa9116402, 0x835114c1, 0xec65e2e4, 0x0a7cf2c5, 0x662cd807, 0x01b3661e, 0x5af4a09f,\n 0x41ff2201,\n ],\n names: [0x3de2c5dd, 0x85a37b90],\n },\n Exterior: {\n fields: [\n 0xed95cf0f, 0x43f509ba, 0xa7a0773c, 0xa7a0773c, 0x34ba6119, 0x5e6e9f8c, 0x2907c040,\n 0x97865d6b, 0x609f197d, 0x47a50525, 0x71ea7734,\n ],\n names: [0x27c875d6, 0x0e15e3f8],\n vector: 0x3c14025e,\n vector2: 0xb9d21b4f,\n },\n MapObject: {\n fields: [\n 0x274659d1, 0xdce826fc, 0xe04e1e6b, 0x056f2f20, 0xbc7d7e30, 0x3c2bc52f, 0xcffeccc2,\n 0x5c15e339, 0x5eff5e0e, 0x9838264b, 0x48778de6, 0x62ad5137, 0xd1b3b197,\n ],\n names: [0x56f99338, 0xee921ae2],\n vector: 0x27f2ecde,\n vector2: 0x2f96203b,\n },\n MapFloor: {\n fields: [\n 0x21d582d9, 0xde7cb924, 0xe8bd8c89, 0xc35b8b0f, 0x60e280fb, 0x7ec3836a, 0xf209e2f9,\n 0x6d842acc,\n ],\n names: [0x918875a9, 0x503490e0],\n },\n};\n\n/** Hash of the per-{@link UgcKind} \"slot enabled\" enum field, set when a newly added item should be marked as in use. */\nexport const UGC_ENABLE_HASHES: Record<UgcKind, number> = {\n Food: 0xf4a39965,\n Cloth: 0xaf129c33,\n Goods: 0x1a9c00fe,\n Interior: 0xa39744e9,\n Exterior: 0xf4beadc2,\n MapObject: 0x5951050b,\n MapFloor: 0xa1126d32,\n};\n\n/** Hash of the per-{@link UgcKind} texture-source enum field, set to the value derived from {@link UGC_TEX_DATA} when adding an item. */\nexport const UGC_TEXTURE_HASHES: Record<UgcKind, number> = {\n Food: 0x3558b77f,\n Cloth: 0x59bfa9d3,\n Goods: 0x70d10a48,\n Interior: 0xe7f9d439,\n Exterior: 0x16227c50,\n MapObject: 0xa9c5cfb8,\n MapFloor: 0x06a7a14c,\n};\n\n/** Hash of the per-{@link UgcKind} content-id field, set to a value combining the slot index and {@link UGC_HASH_INDICES} when adding an item. */\nexport const UGC_HASH_ID_HASHES: Record<UgcKind, number> = {\n Food: 0x6d48f8e2,\n Cloth: 0x89f25cac,\n Goods: 0x56202100,\n Interior: 0x7fef7f7d,\n Exterior: 0x38d72795,\n MapObject: 0x1b28b170,\n MapFloor: 0x816d50a3,\n};\n\n/** Packed little-endian table of texture-source enum values, indexed by {@link ugcKindIndex} times 4, applied to {@link UGC_TEXTURE_HASHES} when adding an item. */\nexport const UGC_TEX_DATA: Uint8Array = new Uint8Array([\n 0x41, 0x49, 0x93, 0x56, 0xe3, 0xc2, 0x2f, 0xb4, 0x41, 0x49, 0x93, 0x56, 0xe3, 0xc2, 0x2f, 0xb4,\n 0xe3, 0xc2, 0x2f, 0xb4, 0xe3, 0xc2, 0x2f, 0xb4, 0xe3, 0xc2, 0x2f, 0xb4,\n]);\n\n/** Per-{@link UgcKind} tag packed into the high byte of the content-id field (see {@link UGC_HASH_ID_HASHES}) when adding an item. */\nexport const UGC_HASH_INDICES: Record<UgcKind, number> = {\n Food: 1,\n Cloth: 3,\n Goods: 2,\n Interior: 6,\n Exterior: 7,\n MapObject: 4,\n MapFloor: 5,\n};\n\n/** Save-field hashes for the facepaint slot arrays in the `player` save: price, texture source, state, and bookkeeping fields toggled when a Mii's facepaint is added or cleared. */\nexport const FACEPAINT_HASHES = {\n price: 0x4c9819e4,\n textureSourceType: 0xdecc8954,\n state: 0x23135bc5,\n unknown: 0xffc750b6,\n hash: 0xa56e42ec,\n};\n\n/** Save-field hashes for the Mii data this codec reads and writes: facepaint index, the temp slot, name/pronunciation, raw Mii block, love-gender flags, satisfaction level, and the eighteen personality fields. */\nexport const MII_HASHES = {\n facePaintIndex: 0x5e32adf4,\n tempSlotMii: 0x114eff89,\n names: 0x2499bfda,\n pronunciation: 0x3a5eda05,\n rawMii: 0x881ca27a,\n isLoveGender: 0xdfc82223,\n satisfyLevel: 0x9999b7d9,\n personality: [\n 0x43cd364f, 0xcd8dbaf8, 0x25b48224, 0x607ba160, 0x68e1134e, 0x4913ae1a, 0x141ee086, 0x07b9d175,\n 0x81cf470a, 0x4d78e262, 0xfbc3ffb0, 0x236e2d73, 0xf3c3de59, 0x660c5247, 0x5d7d3f45, 0xab8ae08b,\n 0x2545e583, 0x6cf484f4,\n ] as const,\n};\n\n/** Hash of the primary display-name field for each {@link UgcKind}, used to detect filled slots when listing items. */\nexport const UGC_NAME_HASHES: Record<UgcKind, number> = {\n Food: 0x408494f5,\n Cloth: 0x40710642,\n Goods: 0x2f793eb1,\n Interior: 0x3de2c5dd,\n Exterior: 0x27c875d6,\n MapObject: 0x56f99338,\n MapFloor: 0x918875a9,\n};\n","import { DataType, type Accessor, buildHashMap } from '@alexislours/ltd-savedata';\nimport { MII_SCHEMA, PLAYER_SCHEMA, type SchemaLeaf } from '@alexislours/ltd-savedata/schema';\nimport { ShareMiiError } from './errors.js';\n\n/** The pair of save accessors a Mii operation needs: the `player` save and the `mii` save. */\nexport type MiiSaves = {\n /** Accessor over the `player` save data. */\n player: Accessor<'player'>;\n /** Accessor over the `mii` save data. */\n mii: Accessor<'mii'>;\n};\n\n/** The single save accessor a UGC operation needs: UGC items live entirely in the `player` save. */\nexport type PlayerOnlySaves = { player: Accessor<'player'> };\n\n/**\n * Resolve a schema leaf by its field hash and assert its {@link DataType}, throwing\n * a `save_format_error` {@link ShareMiiError} (carrying `label`) if the field is\n * absent or has an unexpected type.\n */\nexport function leafByHashOrThrow<T extends DataType>(\n schema: typeof PLAYER_SCHEMA | typeof MII_SCHEMA,\n hash: number,\n label: string,\n expected: T,\n): SchemaLeaf<T> {\n const leaf = buildHashMap(schema).get(hash >>> 0);\n if (!leaf) throw new ShareMiiError('save_format_error', { label });\n if (leaf.type !== expected) {\n throw new ShareMiiError('save_format_error', { label });\n }\n return leaf as SchemaLeaf<T>;\n}\n","import { ShareMiiError } from './errors.js';\n\nconst MII_BLOCK = 156;\nconst PERSONALITY_LEN = 18 * 4;\nconst NAME_LEN = 64;\nconst PRONOUNCE_LEN = 128;\nconst SEXUALITY_LEN = 4;\n\nconst MARK_CANVAS = new Uint8Array([0xa3, 0xa3, 0xa3, 0xa3]);\nconst MARK_UGC = new Uint8Array([0xa4, 0xa4, 0xa4, 0xa4]);\nconst MARK_NAME = new Uint8Array([0xa2, 0xa2, 0xa2, 0xa2]);\nconst MARK_THUMB = new Uint8Array([0xa5, 0xa5, 0xa5, 0xa5]);\n\n/**\n * Decoded contents of a `.ltd` Mii share file: the raw Mii block plus the\n * personality, name, pronunciation, and sexuality payloads, and the optional\n * facepaint canvas/UGC textures. Always normalized to the v3 layout when decoded.\n */\nexport type LtdMii = {\n /** File format version of this in-memory record (always 3 after decode). */\n version: number;\n /** Original version from the file before upgradeToV3; v1 has no personality data. */\n originalVersion: number;\n hasCanvas: boolean;\n hasUgcTex: boolean;\n miiBlock: Uint8Array;\n personality: Uint8Array;\n name: Uint8Array;\n pronounce: Uint8Array;\n sexuality: Uint8Array;\n canvasTex: Uint8Array;\n ugcTex: Uint8Array;\n};\n\n/**\n * Serialize a {@link LtdMii} into the v3 `.ltd` byte layout. Throws a plain\n * `Error` if any fixed-width payload (Mii block, personality, name, pronunciation,\n * sexuality) is the wrong length.\n */\nexport function encodeLtdMii(m: LtdMii): Uint8Array {\n if (m.miiBlock.byteLength !== MII_BLOCK) throw new Error('miiBlock must be 156 bytes');\n if (m.personality.byteLength !== PERSONALITY_LEN) throw new Error('personality must be 72 bytes');\n if (m.name.byteLength !== NAME_LEN) throw new Error('name must be 64 bytes');\n if (m.pronounce.byteLength !== PRONOUNCE_LEN) throw new Error('pronounce must be 128 bytes');\n if (m.sexuality.byteLength !== SEXUALITY_LEN) throw new Error('sexuality must be 4 bytes');\n\n const total =\n 4 +\n MII_BLOCK +\n PERSONALITY_LEN +\n NAME_LEN +\n PRONOUNCE_LEN +\n SEXUALITY_LEN +\n 4 +\n m.canvasTex.byteLength +\n 4 +\n m.ugcTex.byteLength;\n const out = new Uint8Array(total);\n let p = 0;\n out[p++] = m.version & 0xff;\n out[p++] = m.hasCanvas ? 1 : 0;\n out[p++] = m.hasUgcTex ? 1 : 0;\n out[p++] = 0;\n out.set(m.miiBlock, p);\n p += MII_BLOCK;\n out.set(m.personality, p);\n p += PERSONALITY_LEN;\n out.set(m.name, p);\n p += NAME_LEN;\n out.set(m.pronounce, p);\n p += PRONOUNCE_LEN;\n out.set(m.sexuality, p);\n p += SEXUALITY_LEN;\n out.set(MARK_CANVAS, p);\n p += 4;\n out.set(m.canvasTex, p);\n p += m.canvasTex.byteLength;\n out.set(MARK_UGC, p);\n p += 4;\n out.set(m.ugcTex, p);\n return out;\n}\n\n/**\n * Parse a `.ltd` Mii share file, upgrading v1/v2 payloads to the v3 layout in the\n * process. Throws a {@link ShareMiiError} for truncated data, an unsupported\n * version, or a missing section marker.\n */\nexport function decodeLtdMii(bytes: Uint8Array): LtdMii {\n if (bytes.byteLength < 4) throw new ShareMiiError('invalid_ltd_file');\n let buf: Uint8Array = new Uint8Array(bytes);\n const originalVersion = buf[0];\n let version = originalVersion;\n if (version < 1 || version > 3) {\n throw new ShareMiiError('unsupported_ltd_version', { version });\n }\n\n if (version < 3) {\n buf = upgradeToV3(buf);\n version = 3;\n }\n\n const hasCanvas = buf[1] !== 0;\n const hasUgcTex = buf[2] !== 0;\n let p = 4;\n const miiBlock = buf.slice(p, p + MII_BLOCK);\n p += MII_BLOCK;\n const personality = buf.slice(p, p + PERSONALITY_LEN);\n p += PERSONALITY_LEN;\n const name = buf.slice(p, p + NAME_LEN);\n p += NAME_LEN;\n const pronounce = buf.slice(p, p + PRONOUNCE_LEN);\n p += PRONOUNCE_LEN;\n const sexuality = buf.slice(p, p + SEXUALITY_LEN);\n p += SEXUALITY_LEN;\n\n const canvasStart = findMarker(buf, MARK_CANVAS, p);\n if (canvasStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'canvas' });\n const ugcStart = findMarker(buf, MARK_UGC, canvasStart + 4);\n if (ugcStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'ugc' });\n\n const canvasTex = buf.slice(canvasStart + 4, ugcStart);\n const ugcTex = buf.slice(ugcStart + 4);\n\n return {\n version,\n originalVersion,\n hasCanvas,\n hasUgcTex,\n miiBlock,\n personality,\n name,\n pronounce,\n sexuality,\n canvasTex,\n ugcTex,\n };\n}\n\nfunction upgradeToV3(input: Uint8Array): Uint8Array {\n const mii = Array.from(input);\n const originalVersion = mii[0];\n mii.splice(4, 1);\n if (originalVersion === 2) {\n mii.splice(427, 0, 0);\n const canvasMarkerStart = findMarkerArr(mii, [0xa3, 0xa3, 0xa3]);\n if (canvasMarkerStart < 0)\n throw new ShareMiiError('ltd_missing_marker', { marker: 'v2_canvas' });\n const canvasStart = canvasMarkerStart + 3;\n const ugcMarkerStart = lastFindMarkerArr(mii, [0xa3, 0xa3, 0xa3]);\n mii.splice(canvasStart, 0, 0xa3);\n mii[ugcMarkerStart + 1] = 0xa4;\n mii[ugcMarkerStart + 2] = 0xa4;\n mii[ugcMarkerStart + 3] = 0xa4;\n mii.splice(ugcMarkerStart + 3, 0, 0xa4);\n }\n mii[0] = 3;\n return new Uint8Array(mii);\n}\n\nfunction findMarker(buf: Uint8Array, marker: Uint8Array, from: number): number {\n outer: for (let i = from; i <= buf.byteLength - marker.byteLength; i++) {\n for (let j = 0; j < marker.byteLength; j++) {\n if (buf[i + j] !== marker[j]) continue outer;\n }\n return i;\n }\n return -1;\n}\n\nfunction findMarkerArr(buf: number[], marker: number[]): number {\n outer: for (let i = 0; i <= buf.length - marker.length; i++) {\n for (let j = 0; j < marker.length; j++) {\n if (buf[i + j] !== marker[j]) continue outer;\n }\n return i;\n }\n return -1;\n}\n\nfunction lastFindMarkerArr(buf: number[], marker: number[]): number {\n outer: for (let i = buf.length - marker.length; i >= 0; i--) {\n for (let j = 0; j < marker.length; j++) {\n if (buf[i + j] !== marker[j]) continue outer;\n }\n return i;\n }\n return -1;\n}\n\n/**\n * Fully-structured source for encoding a `.ltd*` UGC share file, with each field\n * group separated out. Used to build a share file from save data; decoding instead\n * yields the coarser {@link LtdUgcSection}.\n */\nexport type LtdUgc = {\n /** Index of the {@link UgcKind} this item belongs to, written into the file header. */\n kindIndex: number;\n fields: Uint8Array;\n vector: Uint8Array;\n vector2: Uint8Array;\n name: Uint8Array;\n pronounce: Uint8Array;\n goodsText?: Uint8Array;\n goodsPronounce?: Uint8Array;\n canvasTex: Uint8Array;\n ugcTex: Uint8Array;\n thumbTex: Uint8Array;\n};\n\n/**\n * Serialize a {@link LtdUgc} into the `.ltd*` UGC byte layout, concatenating the\n * header, scalar fields, vectors, name block, and the three texture sections\n * behind their respective markers. Goods carry two extra name strings.\n */\nexport function encodeLtdUgc(u: LtdUgc): Uint8Array {\n const ltdHeader = new Uint8Array([u.kindIndex & 0xff, 0, 0, 0]);\n const namesBlock = u.goodsText\n ? concat(u.name, u.pronounce, u.goodsText, u.goodsPronounce ?? new Uint8Array(0))\n : concat(u.name, u.pronounce);\n\n return concat(\n ltdHeader,\n u.fields,\n u.vector,\n u.vector2,\n MARK_NAME,\n namesBlock,\n MARK_CANVAS,\n u.canvasTex,\n MARK_UGC,\n u.ugcTex,\n MARK_THUMB,\n u.thumbTex,\n );\n}\n\n/**\n * Decoded `.ltd*` UGC share file split at its section markers. The scalar fields,\n * vectors, and name strings are left as opaque byte runs ({@link LtdUgcSection.fieldsAndVectors},\n * {@link LtdUgcSection.namesBlock}) for the applier to slice per {@link UgcKind}.\n */\nexport type LtdUgcSection = {\n /** Index of the {@link UgcKind} read from the file header. */\n kindIndex: number;\n fieldsAndVectors: Uint8Array;\n namesBlock: Uint8Array;\n canvasTex: Uint8Array;\n ugcTex: Uint8Array;\n thumbTex: Uint8Array;\n};\n\n/**\n * Parse a `.ltd*` UGC share file into its {@link LtdUgcSection} parts by locating\n * the name, canvas, UGC, and thumbnail markers. Throws a {@link ShareMiiError} on\n * truncated data or any missing marker.\n */\nexport function decodeLtdUgc(bytes: Uint8Array): LtdUgcSection {\n if (bytes.byteLength < 4) throw new ShareMiiError('invalid_ltd_file');\n const kindIndex = bytes[0];\n\n const nameStart = findMarker(bytes, MARK_NAME, 4);\n if (nameStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'name' });\n const canvasStart = findMarker(bytes, MARK_CANVAS, nameStart + 4);\n if (canvasStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'canvas' });\n const ugcStart = findMarker(bytes, MARK_UGC, canvasStart + 4);\n if (ugcStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'ugc' });\n const thumbStart = findMarker(bytes, MARK_THUMB, ugcStart + 4);\n if (thumbStart < 0) throw new ShareMiiError('ltd_missing_marker', { marker: 'thumb' });\n\n return {\n kindIndex,\n fieldsAndVectors: bytes.slice(4, nameStart),\n namesBlock: bytes.slice(nameStart + 4, canvasStart),\n canvasTex: bytes.slice(canvasStart + 4, ugcStart),\n ugcTex: bytes.slice(ugcStart + 4, thumbStart),\n thumbTex: bytes.slice(thumbStart + 4),\n };\n}\n\nfunction concat(...parts: Uint8Array[]): Uint8Array {\n let total = 0;\n for (const p of parts) total += p.byteLength;\n const out = new Uint8Array(total);\n let off = 0;\n for (const p of parts) {\n out.set(p, off);\n off += p.byteLength;\n }\n return out;\n}\n","import { DataType, type Accessor, buildHashMap } from '@alexislours/ltd-savedata';\nimport { MII_SCHEMA, PLAYER_SCHEMA, type SchemaLeaf } from '@alexislours/ltd-savedata/schema';\nimport { decodeLtdMii, encodeLtdMii, type LtdMii } from './codec.js';\nimport { ShareMiiError } from './errors.js';\nimport { leafByHashOrThrow, type MiiSaves } from './savAccess.js';\nimport {\n FACEPAINT_HASHES,\n MII_HASHES,\n facepaintCanvasFileName,\n facepaintTexFileName,\n} from './ugcKinds.js';\nimport { decodeUtf16Name, encodeUtf16Name, sanitizeFileName } from './utf16.js';\nimport { EMPTY_SIDECAR, type SidecarFile, type SidecarSource } from './sidecar.js';\n\n/** Number of regular Mii slots in a save, not counting the in-progress (temp) Mii exposed as slot 0. */\nexport const MII_SLOTS = 70;\nconst MII_BLOCK_LEN = 156;\nconst MII_DATA_LEN = 152;\n\nfunction wrapMiiBlock(data: Uint8Array): Uint8Array {\n const out = new Uint8Array(MII_BLOCK_LEN);\n new DataView(out.buffer).setUint32(0, MII_DATA_LEN, true);\n out.set(data, 4);\n return out;\n}\n\nfunction unwrapMiiBlock(block: Uint8Array): Uint8Array {\n return block.slice(4, MII_BLOCK_LEN);\n}\n\nconst FP_TEX_SRC_USED = 0x56934941 | 0;\nconst FP_TEX_SRC_UNUSED = 0xb6eede09 | 0;\nconst FP_STATE_USED = 0x1d7fadf4 | 0;\n/** Facepaint `state` enum value marking a slot as unused; an in-progress Mii's facepaint exists only when its state differs from this. */\nexport const FP_STATE_UNUSED = 0xafff8aa5 | 0;\nconst FP_UNKNOWN_USED = 0x00008000 | 0;\nconst FP_UNKNOWN_UNUSED = 0x00000000 | 0;\nconst FP_PRICE = 0x000001f4;\nconst FP_HASH_UNUSED = 0x00000000 | 0;\nconst FP_INDEX_UNUSED = -1;\n\nfunction fpHashValue(facepaintId: number): number {\n return (8 << 16) | facepaintId | 0;\n}\n\nconst PLAYER_LEAVES = {\n fpPrice: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.price,\n 'Facepaint.Price',\n DataType.IntArray,\n ),\n fpTexSrc: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.textureSourceType,\n 'Facepaint.TextureSourceType',\n DataType.EnumArray,\n ),\n fpState: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.state,\n 'Facepaint.State',\n DataType.EnumArray,\n ),\n fpUnknown: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.unknown,\n 'Facepaint.Unknown',\n DataType.UIntArray,\n ),\n fpHash: leafByHashOrThrow(\n PLAYER_SCHEMA,\n FACEPAINT_HASHES.hash,\n 'Facepaint.Hash',\n DataType.UIntArray,\n ),\n tempSlot: leafByHashOrThrow(\n PLAYER_SCHEMA,\n MII_HASHES.tempSlotMii,\n 'Player.TempSlotMii',\n DataType.Binary,\n ),\n} as const;\n\nconst MII_LEAVES = {\n facePaintIndex: leafByHashOrThrow(\n MII_SCHEMA,\n MII_HASHES.facePaintIndex,\n 'Mii.FacePaintIndex',\n DataType.IntArray,\n ),\n names: leafByHashOrThrow(MII_SCHEMA, MII_HASHES.names, 'Mii.Names', DataType.WString32Array),\n pronunciation: leafByHashOrThrow(\n MII_SCHEMA,\n MII_HASHES.pronunciation,\n 'Mii.Pronunciation',\n DataType.WString64Array,\n ),\n rawMii: leafByHashOrThrow(MII_SCHEMA, MII_HASHES.rawMii, 'Mii.Raw', DataType.BinaryArray),\n isLoveGender: leafByHashOrThrow(\n MII_SCHEMA,\n MII_HASHES.isLoveGender,\n 'Mii.IsLoveGender',\n DataType.BoolArray,\n ),\n satisfyLevel: leafByHashOrThrow(\n MII_SCHEMA,\n MII_HASHES.satisfyLevel,\n 'Mii.SatisfyInfo.Level',\n DataType.IntArray,\n ),\n personality: MII_HASHES.personality.map((h, i) => {\n const leaf = buildHashMap(MII_SCHEMA).get(h >>> 0);\n if (!leaf) throw new ShareMiiError('save_format_error', { label: `Personality[${i}]` });\n if (leaf.type !== DataType.IntArray && leaf.type !== DataType.EnumArray) {\n throw new ShareMiiError('save_format_error', { label: `Personality[${i}]` });\n }\n return leaf as SchemaLeaf<DataType.IntArray> | SchemaLeaf<DataType.EnumArray>;\n }) as readonly (SchemaLeaf<DataType.IntArray> | SchemaLeaf<DataType.EnumArray>)[],\n} as const;\n\nfunction getPersonalityElement(\n mii: Accessor<'mii'>,\n leaf: SchemaLeaf<DataType.IntArray> | SchemaLeaf<DataType.EnumArray>,\n i: number,\n): number {\n if (leaf.type === DataType.IntArray) return mii.getElement(leaf, i);\n return mii.getElement(leaf, i);\n}\n\nfunction setPersonalityElement(\n mii: Accessor<'mii'>,\n leaf: SchemaLeaf<DataType.IntArray> | SchemaLeaf<DataType.EnumArray>,\n i: number,\n v: number,\n): void {\n if (leaf.type === DataType.IntArray) mii.setElement(leaf, i, v);\n else mii.setElement(leaf, i, v >>> 0);\n}\n\n/** Summary of one Mii slot for slot-picker UIs. */\nexport type MiiSlotInfo = {\n /** Slot number; `0` is the in-progress (temp) Mii, `1` through {@link MII_SLOTS} are the saved Miis. */\n slot: number;\n /** Whether the slot holds no Mii. */\n empty: boolean;\n /** The Mii's display name, or `''` when the slot is empty. */\n name: string;\n};\n\n/** List all Mii slots, including the in-progress Mii at slot 0, with their occupancy and names. */\nexport function listMiiSlots(saves: MiiSaves): MiiSlotInfo[] {\n const out: MiiSlotInfo[] = [];\n out.push({ slot: 0, empty: false, name: 'In-Progress Mii' });\n for (let s = 0; s < MII_SLOTS; s++) {\n const data = saves.mii.getElement(MII_LEAVES.rawMii, s);\n const empty = isEmptyDataBlock(data);\n const name = saves.mii.getElement(MII_LEAVES.names, s);\n out.push({ slot: s + 1, empty, name: empty ? '' : name });\n }\n return out;\n}\n\nfunction isEmptyDataBlock(data: Uint8Array): boolean {\n if (data.byteLength !== MII_DATA_LEN) return false;\n for (const b of data) if (b !== 0) return false;\n return true;\n}\n\nfunction isEmptyMiiBlock(block: Uint8Array): boolean {\n if (block.byteLength !== MII_BLOCK_LEN) return false;\n let sum = 0;\n for (const b of block) sum += b;\n return sum === 152;\n}\n\nfunction readMiiBlock(saves: MiiSaves, isTemp: boolean, slotIdx: number): Uint8Array {\n if (isTemp) {\n const data = saves.player.get(PLAYER_LEAVES.tempSlot);\n if (data.byteLength < MII_DATA_LEN) throw new ShareMiiError('mii_not_initialized');\n return wrapMiiBlock(data.subarray(0, MII_DATA_LEN));\n }\n const data = saves.mii.getElement(MII_LEAVES.rawMii, slotIdx);\n if (data.byteLength !== MII_DATA_LEN) {\n throw new ShareMiiError('save_format_error', { label: 'Mii.Raw' });\n }\n return wrapMiiBlock(data);\n}\n\nfunction writeMiiBlock(saves: MiiSaves, isTemp: boolean, slotIdx: number, block: Uint8Array): void {\n const data = unwrapMiiBlock(block);\n if (isTemp) {\n const buf = saves.player.get(PLAYER_LEAVES.tempSlot);\n buf.set(data, 0);\n saves.player.set(PLAYER_LEAVES.tempSlot, buf);\n } else {\n saves.mii.setElement(MII_LEAVES.rawMii, slotIdx, data);\n }\n}\n\n/** Result of {@link extractMii}: the share file plus any facepaint textures to save next to it. */\nexport type ExtractMiiResult = {\n /** The encoded `.ltd` Mii share file. */\n bytes: Uint8Array;\n /** Suggested download file name, derived from the Mii's name. */\n fileName: string;\n /** The Mii's display name (`'Mii'` for the in-progress Mii). */\n miiName: string;\n /** Facepaint canvas and texture sidecar files, empty when the Mii has no facepaint or its textures were not provided. */\n facepaint: SidecarFile[];\n};\n\n/**\n * Read the Mii at `slot` (0 for the in-progress Mii) and encode it as a `.ltd`\n * share file, pulling any facepaint textures from `sidecar`. Throws\n * `mii_not_initialized` for an empty slot.\n */\nexport function extractMii(\n saves: MiiSaves,\n slot: number,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): ExtractMiiResult {\n const isTemp = slot === 0;\n const slotIdx = slot - 1;\n\n const block = readMiiBlock(saves, isTemp, slotIdx);\n if (isEmptyMiiBlock(block)) {\n throw new ShareMiiError('mii_not_initialized');\n }\n\n let facepaintId: number | null = null;\n if (isTemp) {\n if (saves.player.getElement(PLAYER_LEAVES.fpState, 70) !== FP_STATE_UNUSED) facepaintId = 70;\n } else {\n const id = saves.mii.getElement(MII_LEAVES.facePaintIndex, slotIdx);\n if (id !== FP_INDEX_UNUSED) facepaintId = id;\n }\n\n const personality = new Uint8Array(72);\n const dv = new DataView(personality.buffer);\n for (let i = 0; i < 18; i++) {\n const v = isTemp ? 0 : getPersonalityElement(saves.mii, MII_LEAVES.personality[i], slotIdx);\n dv.setInt32(i * 4, v | 0, true);\n }\n\n const name = new Uint8Array(64);\n let decodedName: string;\n if (isTemp) {\n const tempName = new TextEncoder().encode('Temp');\n for (let i = 0; i < tempName.length; i++) name[i * 2] = tempName[i];\n decodedName = 'Mii';\n } else {\n const nameStr = saves.mii.getElement(MII_LEAVES.names, slotIdx);\n name.set(encodeUtf16Name(nameStr, 64));\n decodedName = decodeUtf16Name(name);\n }\n\n const pronounce = new Uint8Array(128);\n if (!isTemp) {\n const pStr = saves.mii.getElement(MII_LEAVES.pronunciation, slotIdx);\n pronounce.set(encodeUtf16Name(pStr, 128));\n }\n\n const sexuality = new Uint8Array(4);\n if (!isTemp) {\n const base = slotIdx * 3;\n sexuality[0] = saves.mii.getElement(MII_LEAVES.isLoveGender, base) ? 1 : 0;\n sexuality[1] = saves.mii.getElement(MII_LEAVES.isLoveGender, base + 1) ? 1 : 0;\n sexuality[2] = saves.mii.getElement(MII_LEAVES.isLoveGender, base + 2) ? 1 : 0;\n }\n\n let canvasTex = new Uint8Array(0);\n let ugcTex = new Uint8Array(0);\n const facepaint: SidecarFile[] = [];\n if (facepaintId !== null) {\n const canvasName = facepaintCanvasFileName(facepaintId);\n const texName = facepaintTexFileName(facepaintId);\n const c = sidecar.files.get(canvasName);\n const t = sidecar.files.get(texName);\n if (c && t) {\n canvasTex = new Uint8Array(c);\n ugcTex = new Uint8Array(t);\n facepaint.push({ name: canvasName, bytes: canvasTex }, { name: texName, bytes: ugcTex });\n }\n }\n\n const ltd: LtdMii = {\n version: isTemp ? 1 : 3,\n originalVersion: isTemp ? 1 : 3,\n hasCanvas: canvasTex.byteLength > 0,\n hasUgcTex: ugcTex.byteLength > 0,\n miiBlock: block.slice(),\n personality,\n name,\n pronounce,\n sexuality,\n canvasTex,\n ugcTex,\n };\n const bytes = encodeLtdMii(ltd);\n\n const baseName = isTemp ? 'Mii' : sanitizeFileName(decodedName);\n return {\n bytes,\n fileName: `${baseName}.ltd`,\n miiName: decodedName || 'Mii',\n facepaint,\n };\n}\n\n/** Result of {@link applyMii}: facepaint texture files the caller must persist alongside the save. */\nexport type ApplyMiiResult = {\n /** Facepaint canvas and texture files to write; already merged into a writable `sidecar`, empty when the Mii has no facepaint. */\n facepaintWrites: SidecarFile[];\n};\n\n/**\n * Decode a `.ltd` Mii share file and write it into `slot` (0 for the in-progress\n * Mii), allocating or releasing a facepaint slot as needed and restoring name,\n * personality, and sexuality for v2+ files. Throws `mii_not_initialized` when\n * targeting an empty saved slot, or `no_free_facepaint_slot` when none is free.\n */\nexport function applyMii(\n saves: MiiSaves,\n slot: number,\n ltdBytes: Uint8Array,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): ApplyMiiResult {\n const ltd = decodeLtdMii(ltdBytes);\n\n const isTemp = slot === 0;\n const slotIdx = slot - 1;\n\n if (!isTemp && isEmptyMiiBlock(readMiiBlock(saves, isTemp, slotIdx))) {\n throw new ShareMiiError('mii_not_initialized');\n }\n\n writeMiiBlock(saves, isTemp, slotIdx, ltd.miiBlock);\n\n const facepaintAvailable: 'inline' | null = ltd.hasCanvas && ltd.hasUgcTex ? 'inline' : null;\n\n const prevFacepaintId = isTemp\n ? FP_INDEX_UNUSED\n : saves.mii.getElement(MII_LEAVES.facePaintIndex, slotIdx);\n\n let facepaintId = prevFacepaintId;\n const facepaintWrites: SidecarFile[] = [];\n\n if (facepaintAvailable === 'inline') {\n if (isTemp) {\n facepaintId = 70;\n } else if (facepaintId === FP_INDEX_UNUSED) {\n facepaintId = pickFacepaintId(saves.mii);\n saves.mii.setElement(MII_LEAVES.facePaintIndex, slotIdx, facepaintId);\n }\n saves.player.setElement(PLAYER_LEAVES.fpPrice, facepaintId, FP_PRICE);\n saves.player.setElement(PLAYER_LEAVES.fpTexSrc, facepaintId, FP_TEX_SRC_USED);\n saves.player.setElement(PLAYER_LEAVES.fpState, facepaintId, FP_STATE_USED);\n saves.player.setElement(PLAYER_LEAVES.fpUnknown, facepaintId, FP_UNKNOWN_USED);\n saves.player.setElement(PLAYER_LEAVES.fpHash, facepaintId, fpHashValue(facepaintId));\n\n facepaintWrites.push({\n name: facepaintCanvasFileName(facepaintId),\n bytes: ltd.canvasTex,\n });\n facepaintWrites.push({\n name: facepaintTexFileName(facepaintId),\n bytes: ltd.ugcTex,\n });\n } else if (prevFacepaintId !== FP_INDEX_UNUSED) {\n if (!isTemp) {\n saves.mii.setElement(MII_LEAVES.facePaintIndex, slotIdx, FP_INDEX_UNUSED);\n }\n saves.player.setElement(PLAYER_LEAVES.fpPrice, prevFacepaintId, 0);\n saves.player.setElement(PLAYER_LEAVES.fpTexSrc, prevFacepaintId, FP_TEX_SRC_UNUSED);\n saves.player.setElement(PLAYER_LEAVES.fpState, prevFacepaintId, FP_STATE_UNUSED);\n saves.player.setElement(PLAYER_LEAVES.fpUnknown, prevFacepaintId, FP_UNKNOWN_UNUSED);\n saves.player.setElement(PLAYER_LEAVES.fpHash, prevFacepaintId, FP_HASH_UNUSED);\n }\n\n if (ltd.originalVersion >= 2 && !isTemp) {\n const sdv = new DataView(\n ltd.personality.buffer,\n ltd.personality.byteOffset,\n ltd.personality.byteLength,\n );\n for (let i = 0; i < 18; i++) {\n setPersonalityElement(\n saves.mii,\n MII_LEAVES.personality[i],\n slotIdx,\n sdv.getInt32(i * 4, true),\n );\n }\n saves.mii.setElement(MII_LEAVES.names, slotIdx, decodeUtf16Name(ltd.name));\n saves.mii.setElement(MII_LEAVES.pronunciation, slotIdx, decodeUtf16Name(ltd.pronounce));\n\n if (saves.mii.getElement(MII_LEAVES.satisfyLevel, slotIdx) < 2) {\n const base = slotIdx * 3;\n saves.mii.setElement(MII_LEAVES.isLoveGender, base, (ltd.sexuality[0] & 1) === 1);\n saves.mii.setElement(MII_LEAVES.isLoveGender, base + 1, (ltd.sexuality[1] & 1) === 1);\n saves.mii.setElement(MII_LEAVES.isLoveGender, base + 2, (ltd.sexuality[2] & 1) === 1);\n }\n }\n\n if (sidecar.origin !== 'none' && facepaintWrites.length > 0) {\n for (const f of facepaintWrites) sidecar.files.set(f.name, f.bytes);\n }\n\n return { facepaintWrites };\n}\n\nfunction pickFacepaintId(mii: Accessor<'mii'>): number {\n const used = new Set<number>();\n for (let s = 0; s < MII_SLOTS; s++) {\n const id = mii.getElement(MII_LEAVES.facePaintIndex, s);\n if (id !== FP_INDEX_UNUSED) used.add(id);\n }\n for (let i = 0; i < MII_SLOTS; i++) {\n if (!used.has(i)) return i;\n }\n throw new ShareMiiError('no_free_facepaint_slot');\n}\n","import { arrayElementSize, DataType, type Accessor, buildHashMap } from '@alexislours/ltd-savedata';\nimport { PLAYER_SCHEMA, type SchemaLeaf } from '@alexislours/ltd-savedata/schema';\nimport { decodeLtdUgc, encodeLtdUgc, type LtdUgc } from './codec.js';\nimport { ShareMiiError } from './errors.js';\nimport { leafByHashOrThrow, type PlayerOnlySaves } from './savAccess.js';\nimport {\n UGC_ENABLE_HASHES,\n UGC_FILE_EXTENSIONS,\n UGC_HASHES,\n UGC_HASH_ID_HASHES,\n UGC_HASH_INDICES,\n UGC_MAX_SLOTS,\n UGC_NAME_HASHES,\n UGC_TEX_DATA,\n UGC_TEXTURE_HASHES,\n type UgcKind,\n ugcCanvasFileName,\n ugcKindIndex,\n ugcTexFileName,\n ugcThumbFileName,\n} from './ugcKinds.js';\nimport { decodeUtf16Name, encodeUtf16Name, sanitizeFileName } from './utf16.js';\nimport { EMPTY_SIDECAR, type SidecarFile, type SidecarSource } from './sidecar.js';\n\nconst ENABLE_USED = 0x1d7fadf4 >>> 0;\n\ntype ScalarFieldType =\n | DataType.IntArray\n | DataType.UIntArray\n | DataType.EnumArray\n | DataType.FloatArray\n | DataType.BoolArray;\n\ntype NameType = DataType.WString32Array | DataType.WString64Array;\n\ntype UgcLeaves = {\n fields: SchemaLeaf<ScalarFieldType>[];\n names: SchemaLeaf<NameType>[];\n vector: SchemaLeaf<DataType.Vector3Array> | null;\n vector2: SchemaLeaf<DataType.Vector2Array> | null;\n enable: SchemaLeaf<DataType.EnumArray>;\n texture: SchemaLeaf<DataType.EnumArray>;\n hashId: SchemaLeaf<DataType.UIntArray>;\n};\n\nfunction resolveScalarFieldLeaf(hash: number, label: string): SchemaLeaf<ScalarFieldType> {\n const leaf = buildHashMap(PLAYER_SCHEMA).get(hash >>> 0);\n if (!leaf) throw new ShareMiiError('save_format_error', { label });\n const t = leaf.type;\n if (\n t !== DataType.IntArray &&\n t !== DataType.UIntArray &&\n t !== DataType.EnumArray &&\n t !== DataType.FloatArray &&\n t !== DataType.BoolArray\n ) {\n throw new ShareMiiError('save_format_error', { label });\n }\n return leaf as SchemaLeaf<ScalarFieldType>;\n}\n\nfunction resolveNameLeaf(hash: number, label: string): SchemaLeaf<NameType> {\n const leaf = buildHashMap(PLAYER_SCHEMA).get(hash >>> 0);\n if (!leaf) throw new ShareMiiError('save_format_error', { label });\n const t = leaf.type;\n if (t !== DataType.WString32Array && t !== DataType.WString64Array) {\n throw new ShareMiiError('save_format_error', { label });\n }\n return leaf as SchemaLeaf<NameType>;\n}\n\nfunction resolveUgcLeaves(kind: UgcKind): UgcLeaves {\n const h = UGC_HASHES[kind];\n return {\n fields: h.fields.map((hash, i) => resolveScalarFieldLeaf(hash, `${kind}.field[${i}]`)),\n names: h.names.map((hash, i) => resolveNameLeaf(hash, `${kind}.name[${i}]`)),\n vector: h.vector\n ? leafByHashOrThrow(PLAYER_SCHEMA, h.vector, `${kind}.vector`, DataType.Vector3Array)\n : null,\n vector2: h.vector2\n ? leafByHashOrThrow(PLAYER_SCHEMA, h.vector2, `${kind}.vector2`, DataType.Vector2Array)\n : null,\n enable: leafByHashOrThrow(\n PLAYER_SCHEMA,\n UGC_ENABLE_HASHES[kind],\n `${kind}.enable`,\n DataType.EnumArray,\n ),\n texture: leafByHashOrThrow(\n PLAYER_SCHEMA,\n UGC_TEXTURE_HASHES[kind],\n `${kind}.texture`,\n DataType.EnumArray,\n ),\n hashId: leafByHashOrThrow(\n PLAYER_SCHEMA,\n UGC_HASH_ID_HASHES[kind],\n `${kind}.hashId`,\n DataType.UIntArray,\n ),\n };\n}\n\nfunction ugcSlotCapacity(saves: PlayerOnlySaves, leaves: UgcLeaves, kind: UgcKind): number {\n const player = saves.player;\n let cap = UGC_MAX_SLOTS[kind];\n for (const leaf of leaves.fields) cap = Math.min(cap, (player.get(leaf) as unknown[]).length);\n for (const leaf of leaves.names) cap = Math.min(cap, (player.get(leaf) as unknown[]).length);\n if (leaves.vector) cap = Math.min(cap, (player.get(leaves.vector) as unknown[]).length);\n if (leaves.vector2) cap = Math.min(cap, (player.get(leaves.vector2) as unknown[]).length);\n cap = Math.min(cap, (player.get(leaves.enable) as unknown[]).length);\n cap = Math.min(cap, (player.get(leaves.texture) as unknown[]).length);\n cap = Math.min(cap, (player.get(leaves.hashId) as unknown[]).length);\n return cap;\n}\n\nfunction readField4(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<ScalarFieldType>,\n slotIdx: number,\n): Uint8Array {\n const out = new Uint8Array(4);\n const dv = new DataView(out.buffer);\n switch (leaf.type) {\n case DataType.IntArray:\n dv.setInt32(0, player.getElement(leaf as SchemaLeaf<DataType.IntArray>, slotIdx) | 0, true);\n return out;\n case DataType.UIntArray:\n dv.setUint32(\n 0,\n player.getElement(leaf as SchemaLeaf<DataType.UIntArray>, slotIdx) >>> 0,\n true,\n );\n return out;\n case DataType.EnumArray:\n dv.setUint32(\n 0,\n player.getElement(leaf as SchemaLeaf<DataType.EnumArray>, slotIdx) >>> 0,\n true,\n );\n return out;\n case DataType.FloatArray:\n dv.setFloat32(0, player.getElement(leaf as SchemaLeaf<DataType.FloatArray>, slotIdx), true);\n return out;\n case DataType.BoolArray:\n out[0] = player.getElement(leaf as SchemaLeaf<DataType.BoolArray>, slotIdx) ? 1 : 0;\n return out;\n }\n}\n\nfunction writeField4(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<ScalarFieldType>,\n slotIdx: number,\n src: Uint8Array,\n): void {\n const dv = new DataView(src.buffer, src.byteOffset, 4);\n switch (leaf.type) {\n case DataType.IntArray:\n player.setElement(leaf as SchemaLeaf<DataType.IntArray>, slotIdx, dv.getInt32(0, true) | 0);\n return;\n case DataType.UIntArray:\n player.setElement(\n leaf as SchemaLeaf<DataType.UIntArray>,\n slotIdx,\n dv.getUint32(0, true) >>> 0,\n );\n return;\n case DataType.EnumArray:\n player.setElement(\n leaf as SchemaLeaf<DataType.EnumArray>,\n slotIdx,\n dv.getUint32(0, true) >>> 0,\n );\n return;\n case DataType.FloatArray:\n player.setElement(leaf as SchemaLeaf<DataType.FloatArray>, slotIdx, dv.getFloat32(0, true));\n return;\n case DataType.BoolArray:\n player.setElement(\n leaf as SchemaLeaf<DataType.BoolArray>,\n slotIdx,\n (src[0] | src[1] | src[2] | src[3]) !== 0,\n );\n return;\n }\n}\n\nfunction nameByteLen(leaf: SchemaLeaf<NameType>): 64 | 128 {\n const sz = arrayElementSize(leaf.type);\n if (sz !== 64 && sz !== 128) {\n throw new ShareMiiError('save_format_error', { label: 'name' });\n }\n return sz as 64 | 128;\n}\n\nfunction readNameBlock(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<NameType>,\n slotIdx: number,\n): Uint8Array {\n const str = player.getElement(leaf, slotIdx);\n return encodeUtf16Name(str, nameByteLen(leaf));\n}\n\nfunction writeNameBlock(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<NameType>,\n slotIdx: number,\n src: Uint8Array,\n): void {\n player.setElement(leaf, slotIdx, decodeUtf16Name(src));\n}\n\nfunction readVector3(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<DataType.Vector3Array>,\n slotIdx: number,\n): Uint8Array {\n const v = player.getElement(leaf, slotIdx);\n const out = new Uint8Array(12);\n const dv = new DataView(out.buffer);\n dv.setFloat32(0, v.x, true);\n dv.setFloat32(4, v.y, true);\n dv.setFloat32(8, v.z, true);\n return out;\n}\n\nfunction writeVector3(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<DataType.Vector3Array>,\n slotIdx: number,\n src: Uint8Array,\n): void {\n const dv = new DataView(src.buffer, src.byteOffset, 12);\n player.setElement(leaf, slotIdx, {\n x: dv.getFloat32(0, true),\n y: dv.getFloat32(4, true),\n z: dv.getFloat32(8, true),\n });\n}\n\nfunction readVector2(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<DataType.Vector2Array>,\n slotIdx: number,\n): Uint8Array {\n const v = player.getElement(leaf, slotIdx);\n const out = new Uint8Array(8);\n const dv = new DataView(out.buffer);\n dv.setFloat32(0, v.x, true);\n dv.setFloat32(4, v.y, true);\n return out;\n}\n\nfunction writeVector2(\n player: Accessor<'player'>,\n leaf: SchemaLeaf<DataType.Vector2Array>,\n slotIdx: number,\n src: Uint8Array,\n): void {\n const dv = new DataView(src.buffer, src.byteOffset, 8);\n player.setElement(leaf, slotIdx, {\n x: dv.getFloat32(0, true),\n y: dv.getFloat32(4, true),\n });\n}\n\n/** Summary of one UGC slot for slot-picker UIs. */\nexport type UgcSlotInfo = {\n /** One-based slot number. */\n slot: number;\n /** Whether the slot holds no item. */\n empty: boolean;\n /** The item's display name, or `''` when empty. */\n name: string;\n /** Whether this is the single trailing \"add new\" placeholder rather than an existing item. */\n isAddNew: boolean;\n};\n\n/**\n * List the UGC slots of `kind` that hold an item, plus one trailing \"add new\"\n * placeholder. Occupancy is judged from `sidecar` files when present, otherwise\n * from filled name fields in the save.\n */\nexport function listUgcSlots(\n saves: PlayerOnlySaves,\n kind: UgcKind,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): UgcSlotInfo[] {\n const out: UgcSlotInfo[] = [];\n let max = UGC_MAX_SLOTS[kind];\n let nameLeaf: SchemaLeaf<NameType> | null;\n try {\n const leaves = resolveUgcLeaves(kind);\n nameLeaf = resolveNameLeaf(UGC_NAME_HASHES[kind], `${kind}.names`);\n max = ugcSlotCapacity(saves, leaves, kind);\n } catch {\n nameLeaf = null;\n }\n\n let foundAddSlot = false;\n for (let i = 0; i < max; i++) {\n const fileName = ugcCanvasFileName(kind, i);\n const exists = sidecar.files.has(fileName);\n const decoded = nameLeaf ? saves.player.getElement(nameLeaf, i) : '';\n const looksFilled = decoded.length > 0;\n\n if (exists || (sidecar.origin === 'none' && looksFilled)) {\n out.push({ slot: i + 1, empty: false, name: decoded, isAddNew: false });\n } else if (!foundAddSlot) {\n out.push({ slot: i + 1, empty: true, name: '', isAddNew: true });\n foundAddSlot = true;\n }\n }\n return out;\n}\n\n/** Result of {@link extractUgc}: the share file plus the three texture files that belong with it. */\nexport type ExtractUgcResult = {\n /** The encoded `.ltd*` UGC share file. */\n bytes: Uint8Array;\n /** Suggested download file name, derived from the item's name and its {@link UgcKind} extension. */\n fileName: string;\n /** The item's display name. */\n itemName: string;\n /** Canvas, UGC, and thumbnail sidecar files for the item. */\n textures: SidecarFile[];\n};\n\n/**\n * Read the UGC item at `slot` of `kind` and encode it as a `.ltd*` share file,\n * bundling its canvas, UGC, and thumbnail textures from `sidecar`. Throws\n * `ugc_missing_textures` when any of the three textures is absent.\n */\nexport function extractUgc(\n saves: PlayerOnlySaves,\n slot: number,\n kind: UgcKind,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): ExtractUgcResult {\n const leaves = resolveUgcLeaves(kind);\n const player = saves.player;\n const slotIdx = slot - 1;\n const kindIndex = ugcKindIndex(kind);\n\n const fields = new Uint8Array(leaves.fields.length * 4);\n for (let i = 0; i < leaves.fields.length; i++) {\n fields.set(readField4(player, leaves.fields[i], slotIdx), i * 4);\n }\n const vector = leaves.vector ? readVector3(player, leaves.vector, slotIdx) : new Uint8Array(12);\n const vector2 = leaves.vector2 ? readVector2(player, leaves.vector2, slotIdx) : new Uint8Array(8);\n const name = readNameBlock(player, leaves.names[0], slotIdx);\n const pronounce = readNameBlock(player, leaves.names[1], slotIdx);\n\n let goodsText: Uint8Array | undefined;\n let goodsPronounce: Uint8Array | undefined;\n if (kind === 'Goods' && leaves.names[2] !== undefined && leaves.names[3] !== undefined) {\n goodsText = readNameBlock(player, leaves.names[2], slotIdx);\n goodsPronounce = readNameBlock(player, leaves.names[3], slotIdx);\n }\n\n const canvasName = ugcCanvasFileName(kind, slotIdx);\n const texName = ugcTexFileName(kind, slotIdx);\n const thumbName = ugcThumbFileName(kind, slotIdx);\n const canvasTex = sidecar.files.get(canvasName);\n const ugcTex = sidecar.files.get(texName);\n const thumbTex = sidecar.files.get(thumbName);\n\n if (!canvasTex || !ugcTex || !thumbTex) {\n throw new ShareMiiError('ugc_missing_textures');\n }\n\n const ltd: LtdUgc = {\n kindIndex,\n fields,\n vector,\n vector2,\n name,\n pronounce,\n goodsText,\n goodsPronounce,\n canvasTex,\n ugcTex,\n thumbTex,\n };\n const bytes = encodeLtdUgc(ltd);\n const decodedName = decodeUtf16Name(name) || `Ugc${kind}${slotIdx}`;\n const fileName = `${sanitizeFileName(decodedName)}${UGC_FILE_EXTENSIONS[kind]}`;\n return {\n bytes,\n fileName,\n itemName: decodedName,\n textures: [\n { name: canvasName, bytes: canvasTex },\n { name: texName, bytes: ugcTex },\n { name: thumbName, bytes: thumbTex },\n ],\n };\n}\n\n/** Result of {@link applyUgc}: the texture files the caller must persist alongside the save. */\nexport type ApplyUgcResult = {\n /** Canvas, UGC, and thumbnail files to write; already merged into a writable `sidecar`. */\n textureWrites: SidecarFile[];\n};\n\n/**\n * Decode a `.ltd*` UGC share file and write it into `slot` of `kind`. When\n * `isAdding` is true the slot is initialized (enable flag, texture source, and\n * content id) rather than overwritten in place. Throws on a kind mismatch, an\n * out-of-range slot, a subtype mismatch (Cloth/Goods replacement), or attempting\n * to replace an Exterior/MapObject.\n */\nexport function applyUgc(\n saves: PlayerOnlySaves,\n slot: number,\n kind: UgcKind,\n ltdBytes: Uint8Array,\n isAdding: boolean,\n sidecar: SidecarSource = EMPTY_SIDECAR,\n): ApplyUgcResult {\n const decoded = decodeLtdUgc(ltdBytes);\n const expected = ugcKindIndex(kind);\n if (decoded.kindIndex !== expected) {\n throw new ShareMiiError('wrong_ugc_kind', { got: decoded.kindIndex, expected });\n }\n\n const leaves = resolveUgcLeaves(kind);\n const player = saves.player;\n const slotIdx = slot - 1;\n const capacity = ugcSlotCapacity(saves, leaves, kind);\n if (slotIdx < 0 || slotIdx >= capacity) {\n throw new ShareMiiError('slot_out_of_range', { slot, kind, capacity });\n }\n\n if ((kind === 'Cloth' || kind === 'Goods') && !isAdding) {\n const existing = readField4(player, leaves.fields[0], slotIdx);\n const incoming = decoded.fieldsAndVectors.subarray(0, 4);\n if (!buffersEqual(existing, incoming)) {\n throw new ShareMiiError('subtype_mismatch');\n }\n }\n if ((kind === 'Exterior' || kind === 'MapObject') && !isAdding) {\n throw new ShareMiiError('cannot_replace_kind', { kind });\n }\n\n for (let i = 0; i < leaves.fields.length; i++) {\n const src = decoded.fieldsAndVectors.subarray(i * 4, i * 4 + 4);\n writeField4(player, leaves.fields[i], slotIdx, src);\n }\n\n if (isAdding) {\n player.setElement(leaves.enable, slotIdx, ENABLE_USED);\n const texDv = new DataView(\n UGC_TEX_DATA.buffer,\n UGC_TEX_DATA.byteOffset,\n UGC_TEX_DATA.byteLength,\n );\n const texVal = texDv.getUint32(expected * 4, true) >>> 0;\n player.setElement(leaves.texture, slotIdx, texVal);\n const hashIdVal = ((slotIdx & 0xff) | ((UGC_HASH_INDICES[kind] & 0xff) << 16)) >>> 0;\n player.setElement(leaves.hashId, slotIdx, hashIdVal);\n }\n\n const namesBlock = decoded.namesBlock;\n writeNameBlock(player, leaves.names[0], slotIdx, namesBlock.subarray(0, 128));\n writeNameBlock(player, leaves.names[1], slotIdx, namesBlock.subarray(128, 256));\n if (kind === 'Goods' && leaves.names[2] !== undefined && leaves.names[3] !== undefined) {\n writeNameBlock(player, leaves.names[2], slotIdx, namesBlock.subarray(256, 320));\n writeNameBlock(player, leaves.names[3], slotIdx, namesBlock.subarray(320, 448));\n }\n\n const fav = decoded.fieldsAndVectors;\n if (leaves.vector) {\n const vStart = fav.byteLength - 20;\n writeVector3(player, leaves.vector, slotIdx, fav.subarray(vStart, vStart + 12));\n }\n if (leaves.vector2) {\n const v2Start = fav.byteLength - 8;\n writeVector2(player, leaves.vector2, slotIdx, fav.subarray(v2Start, v2Start + 8));\n }\n\n const writes: SidecarFile[] = [\n { name: ugcCanvasFileName(kind, slotIdx), bytes: decoded.canvasTex },\n { name: ugcTexFileName(kind, slotIdx), bytes: decoded.ugcTex },\n { name: ugcThumbFileName(kind, slotIdx), bytes: decoded.thumbTex },\n ];\n if (sidecar.origin !== 'none') {\n for (const f of writes) sidecar.files.set(f.name, f.bytes);\n }\n\n return { textureWrites: writes };\n}\n\nfunction buffersEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.byteLength !== b.byteLength) return false;\n for (let i = 0; i < a.byteLength; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n"],"mappings":";AAwBO,IAAM,gBAA+B;AAAA,EAC1C,QAAQ;AAAA,EACR,OAAO,oBAAI,IAAI;AACjB;AAGO,SAAS,cAAc,MAAsB;AAClD,QAAM,MAAM,KAAK,IAAI,KAAK,YAAY,GAAG,GAAG,KAAK,YAAY,IAAI,CAAC;AAClE,SAAO,OAAO,IAAI,KAAK,MAAM,MAAM,CAAC,IAAI;AAC1C;AAGO,SAAS,kBAAkB,MAAuB;AACvD,QAAM,QAAQ,KAAK,YAAY;AAC/B,SAAO,MAAM,SAAS,YAAY,KAAK,MAAM,SAAS,YAAY;AACpE;AAMO,SAAS,mBAAmB,MAAuB;AACxD,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,IAAI,EAAG,QAAO;AACtD,MAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,YAAY,EAAG,QAAO;AACtE,QAAM,MAAM,KAAK,IAAI,KAAK,YAAY,GAAG,GAAG,KAAK,YAAY,IAAI,CAAC;AAClE,QAAM,OAAO,OAAO,IAAI,KAAK,MAAM,MAAM,CAAC,IAAI;AAC9C,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,EAAG,QAAO;AAC1C,SAAO;AACT;;;AC5BO,IAAM,gBAAN,cAA4B,MAAM;AAAA;AAAA,EAE9B;AAAA;AAAA,EAEA;AAAA;AAAA,EAET,YAAY,MAAyB,SAA0C,CAAC,GAAG;AACjF,UAAM,IAAI;AACV,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;;;ACjCO,SAAS,gBAAgB,KAAyB;AACvD,MAAI,MAAM;AACV,SAAO,MAAM,IAAI,IAAI,YAAY;AAC/B,QAAI,IAAI,GAAG,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAG;AAC1C,WAAO;AAAA,EACT;AACA,QAAM,OAAiB,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG;AAC/B,SAAK,KAAK,IAAI,CAAC,IAAK,IAAI,IAAI,CAAC,KAAK,CAAE;AAAA,EACtC;AACA,SAAO,OAAO,aAAa,GAAG,IAAI;AACpC;AAMO,SAAS,iBAAiB,MAAsB;AACrD,QAAM,UAAU,KAAK,QAAQ,YAAY,GAAG;AAC5C,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAMO,SAAS,gBAAgB,MAAc,SAA6B;AACzE,QAAM,MAAM,IAAI,WAAW,OAAO;AAClC,QAAM,WAAW,KAAK,OAAO,UAAU,KAAK,CAAC;AAC7C,QAAM,YAAY,KAAK,SAAS,WAAW,KAAK,MAAM,GAAG,QAAQ,IAAI;AACrE,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,OAAO,UAAU,WAAW,CAAC;AACnC,QAAI,IAAI,CAAC,IAAI,OAAO;AACpB,QAAI,IAAI,IAAI,CAAC,IAAK,QAAQ,IAAK;AAAA,EACjC;AACA,SAAO;AACT;;;AC7BO,IAAM,YAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,qBAA8C;AAAA,EACzD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AACZ;AAGO,IAAM,sBAA+C;AAAA,EAC1D,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AACZ;AAGO,SAAS,aAAa,MAAuB;AAClD,SAAO,UAAU,QAAQ,IAAI;AAC/B;AAGO,IAAM,gBAAyC;AAAA,EACpD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AACZ;AAEA,SAAS,YAAY,MAAe,MAAsB;AACxD,SAAO,MAAM,IAAI,GAAG,OAAO,IAAI,EAAE,SAAS,GAAG,GAAG,CAAC;AACnD;AAGO,SAAS,kBAAkB,MAAe,MAAsB;AACrE,SAAO,GAAG,YAAY,MAAM,IAAI,CAAC;AACnC;AAGO,SAAS,eAAe,MAAe,MAAsB;AAClE,SAAO,GAAG,YAAY,MAAM,IAAI,CAAC;AACnC;AAGO,SAAS,iBAAiB,MAAe,MAAsB;AACpE,SAAO,GAAG,YAAY,MAAM,IAAI,CAAC;AACnC;AAEA,SAAS,kBAAkB,IAAoB;AAC7C,SAAO,eAAe,OAAO,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AACnD;AAGO,SAAS,wBAAwB,IAAoB;AAC1D,SAAO,GAAG,kBAAkB,EAAE,CAAC;AACjC;AAGO,SAAS,qBAAqB,IAAoB;AACvD,SAAO,GAAG,kBAAkB,EAAE,CAAC;AACjC;AAeO,IAAM,aAA8C;AAAA,EACzD,MAAM;AAAA,IACJ,QAAQ;AAAA,MACN;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MACxE;AAAA,MAAY;AAAA,MAAY;AAAA,IAC1B;AAAA,IACA,OAAO,CAAC,YAAY,UAAU;AAAA,EAChC;AAAA,EACA,OAAO;AAAA,IACL,QAAQ;AAAA,MACN;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MACxE;AAAA,MAAY;AAAA,MAAY;AAAA,IAC1B;AAAA,IACA,OAAO,CAAC,YAAY,UAAU;AAAA,EAChC;AAAA,EACA,OAAO;AAAA,IACL,QAAQ;AAAA,MACN;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MACxE;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MACxE;AAAA,MAAY;AAAA,MAAY;AAAA,IAC1B;AAAA,IACA,OAAO,CAAC,WAAY,YAAY,YAAY,UAAU;AAAA,IACtD,QAAQ;AAAA,EACV;AAAA,EACA,UAAU;AAAA,IACR,QAAQ;AAAA,MACN;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MACxE;AAAA,IACF;AAAA,IACA,OAAO,CAAC,YAAY,UAAU;AAAA,EAChC;AAAA,EACA,UAAU;AAAA,IACR,QAAQ;AAAA,MACN;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MACxE;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,IACtC;AAAA,IACA,OAAO,CAAC,WAAY,SAAU;AAAA,IAC9B,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AAAA,EACA,WAAW;AAAA,IACT,QAAQ;AAAA,MACN;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MACxE;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,IAC9D;AAAA,IACA,OAAO,CAAC,YAAY,UAAU;AAAA,IAC9B,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,QAAQ;AAAA,MACN;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MAAY;AAAA,MACxE;AAAA,IACF;AAAA,IACA,OAAO,CAAC,YAAY,UAAU;AAAA,EAChC;AACF;AAGO,IAAM,oBAA6C;AAAA,EACxD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AACZ;AAGO,IAAM,qBAA8C;AAAA,EACzD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AACZ;AAGO,IAAM,qBAA8C;AAAA,EACzD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AACZ;AAGO,IAAM,eAA2B,IAAI,WAAW;AAAA,EACrD;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AACpE,CAAC;AAGM,IAAM,mBAA4C;AAAA,EACvD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AACZ;AAGO,IAAM,mBAAmB;AAAA,EAC9B,OAAO;AAAA,EACP,mBAAmB;AAAA,EACnB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AACR;AAGO,IAAM,aAAa;AAAA,EACxB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,OAAO;AAAA,EACP,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,cAAc;AAAA,EACd,aAAa;AAAA,IACX;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IACpF;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IACpF;AAAA,IAAY;AAAA,EACd;AACF;AAGO,IAAM,kBAA2C;AAAA,EACtD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AACZ;;;ACvPA,SAAkC,oBAAoB;AACtD,OAA2D;AAmBpD,SAAS,kBACd,QACA,MACA,OACA,UACe;AACf,QAAM,OAAO,aAAa,MAAM,EAAE,IAAI,SAAS,CAAC;AAChD,MAAI,CAAC,KAAM,OAAM,IAAI,cAAc,qBAAqB,EAAE,MAAM,CAAC;AACjE,MAAI,KAAK,SAAS,UAAU;AAC1B,UAAM,IAAI,cAAc,qBAAqB,EAAE,MAAM,CAAC;AAAA,EACxD;AACA,SAAO;AACT;;;AC9BA,IAAM,YAAY;AAClB,IAAM,kBAAkB,KAAK;AAC7B,IAAM,WAAW;AACjB,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AAEtB,IAAM,cAAc,IAAI,WAAW,CAAC,KAAM,KAAM,KAAM,GAAI,CAAC;AAC3D,IAAM,WAAW,IAAI,WAAW,CAAC,KAAM,KAAM,KAAM,GAAI,CAAC;AACxD,IAAM,YAAY,IAAI,WAAW,CAAC,KAAM,KAAM,KAAM,GAAI,CAAC;AACzD,IAAM,aAAa,IAAI,WAAW,CAAC,KAAM,KAAM,KAAM,GAAI,CAAC;AA4BnD,SAAS,aAAa,GAAuB;AAClD,MAAI,EAAE,SAAS,eAAe,UAAW,OAAM,IAAI,MAAM,4BAA4B;AACrF,MAAI,EAAE,YAAY,eAAe,gBAAiB,OAAM,IAAI,MAAM,8BAA8B;AAChG,MAAI,EAAE,KAAK,eAAe,SAAU,OAAM,IAAI,MAAM,uBAAuB;AAC3E,MAAI,EAAE,UAAU,eAAe,cAAe,OAAM,IAAI,MAAM,6BAA6B;AAC3F,MAAI,EAAE,UAAU,eAAe,cAAe,OAAM,IAAI,MAAM,2BAA2B;AAEzF,QAAM,QACJ,IACA,YACA,kBACA,WACA,gBACA,gBACA,IACA,EAAE,UAAU,aACZ,IACA,EAAE,OAAO;AACX,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,IAAI;AACR,MAAI,GAAG,IAAI,EAAE,UAAU;AACvB,MAAI,GAAG,IAAI,EAAE,YAAY,IAAI;AAC7B,MAAI,GAAG,IAAI,EAAE,YAAY,IAAI;AAC7B,MAAI,GAAG,IAAI;AACX,MAAI,IAAI,EAAE,UAAU,CAAC;AACrB,OAAK;AACL,MAAI,IAAI,EAAE,aAAa,CAAC;AACxB,OAAK;AACL,MAAI,IAAI,EAAE,MAAM,CAAC;AACjB,OAAK;AACL,MAAI,IAAI,EAAE,WAAW,CAAC;AACtB,OAAK;AACL,MAAI,IAAI,EAAE,WAAW,CAAC;AACtB,OAAK;AACL,MAAI,IAAI,aAAa,CAAC;AACtB,OAAK;AACL,MAAI,IAAI,EAAE,WAAW,CAAC;AACtB,OAAK,EAAE,UAAU;AACjB,MAAI,IAAI,UAAU,CAAC;AACnB,OAAK;AACL,MAAI,IAAI,EAAE,QAAQ,CAAC;AACnB,SAAO;AACT;AAOO,SAAS,aAAa,OAA2B;AACtD,MAAI,MAAM,aAAa,EAAG,OAAM,IAAI,cAAc,kBAAkB;AACpE,MAAI,MAAkB,IAAI,WAAW,KAAK;AAC1C,QAAM,kBAAkB,IAAI,CAAC;AAC7B,MAAI,UAAU;AACd,MAAI,UAAU,KAAK,UAAU,GAAG;AAC9B,UAAM,IAAI,cAAc,2BAA2B,EAAE,QAAQ,CAAC;AAAA,EAChE;AAEA,MAAI,UAAU,GAAG;AACf,UAAM,YAAY,GAAG;AACrB,cAAU;AAAA,EACZ;AAEA,QAAM,YAAY,IAAI,CAAC,MAAM;AAC7B,QAAM,YAAY,IAAI,CAAC,MAAM;AAC7B,MAAI,IAAI;AACR,QAAM,WAAW,IAAI,MAAM,GAAG,IAAI,SAAS;AAC3C,OAAK;AACL,QAAM,cAAc,IAAI,MAAM,GAAG,IAAI,eAAe;AACpD,OAAK;AACL,QAAM,OAAO,IAAI,MAAM,GAAG,IAAI,QAAQ;AACtC,OAAK;AACL,QAAM,YAAY,IAAI,MAAM,GAAG,IAAI,aAAa;AAChD,OAAK;AACL,QAAM,YAAY,IAAI,MAAM,GAAG,IAAI,aAAa;AAChD,OAAK;AAEL,QAAM,cAAc,WAAW,KAAK,aAAa,CAAC;AAClD,MAAI,cAAc,EAAG,OAAM,IAAI,cAAc,sBAAsB,EAAE,QAAQ,SAAS,CAAC;AACvF,QAAM,WAAW,WAAW,KAAK,UAAU,cAAc,CAAC;AAC1D,MAAI,WAAW,EAAG,OAAM,IAAI,cAAc,sBAAsB,EAAE,QAAQ,MAAM,CAAC;AAEjF,QAAM,YAAY,IAAI,MAAM,cAAc,GAAG,QAAQ;AACrD,QAAM,SAAS,IAAI,MAAM,WAAW,CAAC;AAErC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,YAAY,OAA+B;AAClD,QAAM,MAAM,MAAM,KAAK,KAAK;AAC5B,QAAM,kBAAkB,IAAI,CAAC;AAC7B,MAAI,OAAO,GAAG,CAAC;AACf,MAAI,oBAAoB,GAAG;AACzB,QAAI,OAAO,KAAK,GAAG,CAAC;AACpB,UAAM,oBAAoB,cAAc,KAAK,CAAC,KAAM,KAAM,GAAI,CAAC;AAC/D,QAAI,oBAAoB;AACtB,YAAM,IAAI,cAAc,sBAAsB,EAAE,QAAQ,YAAY,CAAC;AACvE,UAAM,cAAc,oBAAoB;AACxC,UAAM,iBAAiB,kBAAkB,KAAK,CAAC,KAAM,KAAM,GAAI,CAAC;AAChE,QAAI,OAAO,aAAa,GAAG,GAAI;AAC/B,QAAI,iBAAiB,CAAC,IAAI;AAC1B,QAAI,iBAAiB,CAAC,IAAI;AAC1B,QAAI,iBAAiB,CAAC,IAAI;AAC1B,QAAI,OAAO,iBAAiB,GAAG,GAAG,GAAI;AAAA,EACxC;AACA,MAAI,CAAC,IAAI;AACT,SAAO,IAAI,WAAW,GAAG;AAC3B;AAEA,SAAS,WAAW,KAAiB,QAAoB,MAAsB;AAC7E,QAAO,UAAS,IAAI,MAAM,KAAK,IAAI,aAAa,OAAO,YAAY,KAAK;AACtE,aAAS,IAAI,GAAG,IAAI,OAAO,YAAY,KAAK;AAC1C,UAAI,IAAI,IAAI,CAAC,MAAM,OAAO,CAAC,EAAG,UAAS;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,cAAc,KAAe,QAA0B;AAC9D,QAAO,UAAS,IAAI,GAAG,KAAK,IAAI,SAAS,OAAO,QAAQ,KAAK;AAC3D,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAI,IAAI,IAAI,CAAC,MAAM,OAAO,CAAC,EAAG,UAAS;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,KAAe,QAA0B;AAClE,QAAO,UAAS,IAAI,IAAI,SAAS,OAAO,QAAQ,KAAK,GAAG,KAAK;AAC3D,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAI,IAAI,IAAI,CAAC,MAAM,OAAO,CAAC,EAAG,UAAS;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AA2BO,SAAS,aAAa,GAAuB;AAClD,QAAM,YAAY,IAAI,WAAW,CAAC,EAAE,YAAY,KAAM,GAAG,GAAG,CAAC,CAAC;AAC9D,QAAM,aAAa,EAAE,YACjB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,IAAI,WAAW,CAAC,CAAC,IAC9E,OAAO,EAAE,MAAM,EAAE,SAAS;AAE9B,SAAO;AAAA,IACL;AAAA,IACA,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE;AAAA,IACF;AAAA,IACA,EAAE;AAAA,IACF;AAAA,IACA,EAAE;AAAA,EACJ;AACF;AAsBO,SAAS,aAAa,OAAkC;AAC7D,MAAI,MAAM,aAAa,EAAG,OAAM,IAAI,cAAc,kBAAkB;AACpE,QAAM,YAAY,MAAM,CAAC;AAEzB,QAAM,YAAY,WAAW,OAAO,WAAW,CAAC;AAChD,MAAI,YAAY,EAAG,OAAM,IAAI,cAAc,sBAAsB,EAAE,QAAQ,OAAO,CAAC;AACnF,QAAM,cAAc,WAAW,OAAO,aAAa,YAAY,CAAC;AAChE,MAAI,cAAc,EAAG,OAAM,IAAI,cAAc,sBAAsB,EAAE,QAAQ,SAAS,CAAC;AACvF,QAAM,WAAW,WAAW,OAAO,UAAU,cAAc,CAAC;AAC5D,MAAI,WAAW,EAAG,OAAM,IAAI,cAAc,sBAAsB,EAAE,QAAQ,MAAM,CAAC;AACjF,QAAM,aAAa,WAAW,OAAO,YAAY,WAAW,CAAC;AAC7D,MAAI,aAAa,EAAG,OAAM,IAAI,cAAc,sBAAsB,EAAE,QAAQ,QAAQ,CAAC;AAErF,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB,MAAM,MAAM,GAAG,SAAS;AAAA,IAC1C,YAAY,MAAM,MAAM,YAAY,GAAG,WAAW;AAAA,IAClD,WAAW,MAAM,MAAM,cAAc,GAAG,QAAQ;AAAA,IAChD,QAAQ,MAAM,MAAM,WAAW,GAAG,UAAU;AAAA,IAC5C,UAAU,MAAM,MAAM,aAAa,CAAC;AAAA,EACtC;AACF;AAEA,SAAS,UAAU,OAAiC;AAClD,MAAI,QAAQ;AACZ,aAAW,KAAK,MAAO,UAAS,EAAE;AAClC,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,MAAM;AACV,aAAW,KAAK,OAAO;AACrB,QAAI,IAAI,GAAG,GAAG;AACd,WAAO,EAAE;AAAA,EACX;AACA,SAAO;AACT;;;AClSA,SAAS,YAAAA,WAAyB,gBAAAC,qBAAoB;AACtD,SAAS,cAAAC,aAAY,iBAAAC,sBAAsC;AAcpD,IAAM,YAAY;AACzB,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAErB,SAAS,aAAa,MAA8B;AAClD,QAAM,MAAM,IAAI,WAAW,aAAa;AACxC,MAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,cAAc,IAAI;AACxD,MAAI,IAAI,MAAM,CAAC;AACf,SAAO;AACT;AAEA,SAAS,eAAe,OAA+B;AACrD,SAAO,MAAM,MAAM,GAAG,aAAa;AACrC;AAEA,IAAM,kBAAkB,aAAa;AACrC,IAAM,oBAAoB,aAAa;AACvC,IAAM,gBAAgB,YAAa;AAE5B,IAAM,kBAAkB,aAAa;AAC5C,IAAM,kBAAkB,QAAa;AACrC,IAAM,oBAAoB,IAAa;AACvC,IAAM,WAAW;AACjB,IAAM,iBAAiB,IAAa;AACpC,IAAM,kBAAkB;AAExB,SAAS,YAAY,aAA6B;AAChD,SAAQ,KAAK,KAAM,cAAc;AACnC;AAEA,IAAM,gBAAgB;AAAA,EACpB,SAAS;AAAA,IACPC;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACAC,UAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACRD;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACAC,UAAS;AAAA,EACX;AAAA,EACA,SAAS;AAAA,IACPD;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACAC,UAAS;AAAA,EACX;AAAA,EACA,WAAW;AAAA,IACTD;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACAC,UAAS;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,IACND;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACAC,UAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACRD;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACAC,UAAS;AAAA,EACX;AACF;AAEA,IAAM,aAAa;AAAA,EACjB,gBAAgB;AAAA,IACdC;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACAD,UAAS;AAAA,EACX;AAAA,EACA,OAAO,kBAAkBC,aAAY,WAAW,OAAO,aAAaD,UAAS,cAAc;AAAA,EAC3F,eAAe;AAAA,IACbC;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACAD,UAAS;AAAA,EACX;AAAA,EACA,QAAQ,kBAAkBC,aAAY,WAAW,QAAQ,WAAWD,UAAS,WAAW;AAAA,EACxF,cAAc;AAAA,IACZC;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACAD,UAAS;AAAA,EACX;AAAA,EACA,cAAc;AAAA,IACZC;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACAD,UAAS;AAAA,EACX;AAAA,EACA,aAAa,WAAW,YAAY,IAAI,CAAC,GAAG,MAAM;AAChD,UAAM,OAAOE,cAAaD,WAAU,EAAE,IAAI,MAAM,CAAC;AACjD,QAAI,CAAC,KAAM,OAAM,IAAI,cAAc,qBAAqB,EAAE,OAAO,eAAe,CAAC,IAAI,CAAC;AACtF,QAAI,KAAK,SAASD,UAAS,YAAY,KAAK,SAASA,UAAS,WAAW;AACvE,YAAM,IAAI,cAAc,qBAAqB,EAAE,OAAO,eAAe,CAAC,IAAI,CAAC;AAAA,IAC7E;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,sBACP,KACA,MACA,GACQ;AACR,MAAI,KAAK,SAASA,UAAS,SAAU,QAAO,IAAI,WAAW,MAAM,CAAC;AAClE,SAAO,IAAI,WAAW,MAAM,CAAC;AAC/B;AAEA,SAAS,sBACP,KACA,MACA,GACA,GACM;AACN,MAAI,KAAK,SAASA,UAAS,SAAU,KAAI,WAAW,MAAM,GAAG,CAAC;AAAA,MACzD,KAAI,WAAW,MAAM,GAAG,MAAM,CAAC;AACtC;AAaO,SAAS,aAAa,OAAgC;AAC3D,QAAM,MAAqB,CAAC;AAC5B,MAAI,KAAK,EAAE,MAAM,GAAG,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAC3D,WAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,UAAM,OAAO,MAAM,IAAI,WAAW,WAAW,QAAQ,CAAC;AACtD,UAAM,QAAQ,iBAAiB,IAAI;AACnC,UAAM,OAAO,MAAM,IAAI,WAAW,WAAW,OAAO,CAAC;AACrD,QAAI,KAAK,EAAE,MAAM,IAAI,GAAG,OAAO,MAAM,QAAQ,KAAK,KAAK,CAAC;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAA2B;AACnD,MAAI,KAAK,eAAe,aAAc,QAAO;AAC7C,aAAW,KAAK,KAAM,KAAI,MAAM,EAAG,QAAO;AAC1C,SAAO;AACT;AAEA,SAAS,gBAAgB,OAA4B;AACnD,MAAI,MAAM,eAAe,cAAe,QAAO;AAC/C,MAAI,MAAM;AACV,aAAW,KAAK,MAAO,QAAO;AAC9B,SAAO,QAAQ;AACjB;AAEA,SAAS,aAAa,OAAiB,QAAiB,SAA6B;AACnF,MAAI,QAAQ;AACV,UAAMG,QAAO,MAAM,OAAO,IAAI,cAAc,QAAQ;AACpD,QAAIA,MAAK,aAAa,aAAc,OAAM,IAAI,cAAc,qBAAqB;AACjF,WAAO,aAAaA,MAAK,SAAS,GAAG,YAAY,CAAC;AAAA,EACpD;AACA,QAAM,OAAO,MAAM,IAAI,WAAW,WAAW,QAAQ,OAAO;AAC5D,MAAI,KAAK,eAAe,cAAc;AACpC,UAAM,IAAI,cAAc,qBAAqB,EAAE,OAAO,UAAU,CAAC;AAAA,EACnE;AACA,SAAO,aAAa,IAAI;AAC1B;AAEA,SAAS,cAAc,OAAiB,QAAiB,SAAiB,OAAyB;AACjG,QAAM,OAAO,eAAe,KAAK;AACjC,MAAI,QAAQ;AACV,UAAM,MAAM,MAAM,OAAO,IAAI,cAAc,QAAQ;AACnD,QAAI,IAAI,MAAM,CAAC;AACf,UAAM,OAAO,IAAI,cAAc,UAAU,GAAG;AAAA,EAC9C,OAAO;AACL,UAAM,IAAI,WAAW,WAAW,QAAQ,SAAS,IAAI;AAAA,EACvD;AACF;AAmBO,SAAS,WACd,OACA,MACA,UAAyB,eACP;AAClB,QAAM,SAAS,SAAS;AACxB,QAAM,UAAU,OAAO;AAEvB,QAAM,QAAQ,aAAa,OAAO,QAAQ,OAAO;AACjD,MAAI,gBAAgB,KAAK,GAAG;AAC1B,UAAM,IAAI,cAAc,qBAAqB;AAAA,EAC/C;AAEA,MAAI,cAA6B;AACjC,MAAI,QAAQ;AACV,QAAI,MAAM,OAAO,WAAW,cAAc,SAAS,EAAE,MAAM,gBAAiB,eAAc;AAAA,EAC5F,OAAO;AACL,UAAM,KAAK,MAAM,IAAI,WAAW,WAAW,gBAAgB,OAAO;AAClE,QAAI,OAAO,gBAAiB,eAAc;AAAA,EAC5C;AAEA,QAAM,cAAc,IAAI,WAAW,EAAE;AACrC,QAAM,KAAK,IAAI,SAAS,YAAY,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,IAAI,SAAS,IAAI,sBAAsB,MAAM,KAAK,WAAW,YAAY,CAAC,GAAG,OAAO;AAC1F,OAAG,SAAS,IAAI,GAAG,IAAI,GAAG,IAAI;AAAA,EAChC;AAEA,QAAM,OAAO,IAAI,WAAW,EAAE;AAC9B,MAAI;AACJ,MAAI,QAAQ;AACV,UAAM,WAAW,IAAI,YAAY,EAAE,OAAO,MAAM;AAChD,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAK,MAAK,IAAI,CAAC,IAAI,SAAS,CAAC;AAClE,kBAAc;AAAA,EAChB,OAAO;AACL,UAAM,UAAU,MAAM,IAAI,WAAW,WAAW,OAAO,OAAO;AAC9D,SAAK,IAAI,gBAAgB,SAAS,EAAE,CAAC;AACrC,kBAAc,gBAAgB,IAAI;AAAA,EACpC;AAEA,QAAM,YAAY,IAAI,WAAW,GAAG;AACpC,MAAI,CAAC,QAAQ;AACX,UAAM,OAAO,MAAM,IAAI,WAAW,WAAW,eAAe,OAAO;AACnE,cAAU,IAAI,gBAAgB,MAAM,GAAG,CAAC;AAAA,EAC1C;AAEA,QAAM,YAAY,IAAI,WAAW,CAAC;AAClC,MAAI,CAAC,QAAQ;AACX,UAAM,OAAO,UAAU;AACvB,cAAU,CAAC,IAAI,MAAM,IAAI,WAAW,WAAW,cAAc,IAAI,IAAI,IAAI;AACzE,cAAU,CAAC,IAAI,MAAM,IAAI,WAAW,WAAW,cAAc,OAAO,CAAC,IAAI,IAAI;AAC7E,cAAU,CAAC,IAAI,MAAM,IAAI,WAAW,WAAW,cAAc,OAAO,CAAC,IAAI,IAAI;AAAA,EAC/E;AAEA,MAAI,YAAY,IAAI,WAAW,CAAC;AAChC,MAAI,SAAS,IAAI,WAAW,CAAC;AAC7B,QAAM,YAA2B,CAAC;AAClC,MAAI,gBAAgB,MAAM;AACxB,UAAM,aAAa,wBAAwB,WAAW;AACtD,UAAM,UAAU,qBAAqB,WAAW;AAChD,UAAM,IAAI,QAAQ,MAAM,IAAI,UAAU;AACtC,UAAM,IAAI,QAAQ,MAAM,IAAI,OAAO;AACnC,QAAI,KAAK,GAAG;AACV,kBAAY,IAAI,WAAW,CAAC;AAC5B,eAAS,IAAI,WAAW,CAAC;AACzB,gBAAU,KAAK,EAAE,MAAM,YAAY,OAAO,UAAU,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,CAAC;AAAA,IACzF;AAAA,EACF;AAEA,QAAM,MAAc;AAAA,IAClB,SAAS,SAAS,IAAI;AAAA,IACtB,iBAAiB,SAAS,IAAI;AAAA,IAC9B,WAAW,UAAU,aAAa;AAAA,IAClC,WAAW,OAAO,aAAa;AAAA,IAC/B,UAAU,MAAM,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,aAAa,GAAG;AAE9B,QAAM,WAAW,SAAS,QAAQ,iBAAiB,WAAW;AAC9D,SAAO;AAAA,IACL;AAAA,IACA,UAAU,GAAG,QAAQ;AAAA,IACrB,SAAS,eAAe;AAAA,IACxB;AAAA,EACF;AACF;AAcO,SAAS,SACd,OACA,MACA,UACA,UAAyB,eACT;AAChB,QAAM,MAAM,aAAa,QAAQ;AAEjC,QAAM,SAAS,SAAS;AACxB,QAAM,UAAU,OAAO;AAEvB,MAAI,CAAC,UAAU,gBAAgB,aAAa,OAAO,QAAQ,OAAO,CAAC,GAAG;AACpE,UAAM,IAAI,cAAc,qBAAqB;AAAA,EAC/C;AAEA,gBAAc,OAAO,QAAQ,SAAS,IAAI,QAAQ;AAElD,QAAM,qBAAsC,IAAI,aAAa,IAAI,YAAY,WAAW;AAExF,QAAM,kBAAkB,SACpB,kBACA,MAAM,IAAI,WAAW,WAAW,gBAAgB,OAAO;AAE3D,MAAI,cAAc;AAClB,QAAM,kBAAiC,CAAC;AAExC,MAAI,uBAAuB,UAAU;AACnC,QAAI,QAAQ;AACV,oBAAc;AAAA,IAChB,WAAW,gBAAgB,iBAAiB;AAC1C,oBAAc,gBAAgB,MAAM,GAAG;AACvC,YAAM,IAAI,WAAW,WAAW,gBAAgB,SAAS,WAAW;AAAA,IACtE;AACA,UAAM,OAAO,WAAW,cAAc,SAAS,aAAa,QAAQ;AACpE,UAAM,OAAO,WAAW,cAAc,UAAU,aAAa,eAAe;AAC5E,UAAM,OAAO,WAAW,cAAc,SAAS,aAAa,aAAa;AACzE,UAAM,OAAO,WAAW,cAAc,WAAW,aAAa,eAAe;AAC7E,UAAM,OAAO,WAAW,cAAc,QAAQ,aAAa,YAAY,WAAW,CAAC;AAEnF,oBAAgB,KAAK;AAAA,MACnB,MAAM,wBAAwB,WAAW;AAAA,MACzC,OAAO,IAAI;AAAA,IACb,CAAC;AACD,oBAAgB,KAAK;AAAA,MACnB,MAAM,qBAAqB,WAAW;AAAA,MACtC,OAAO,IAAI;AAAA,IACb,CAAC;AAAA,EACH,WAAW,oBAAoB,iBAAiB;AAC9C,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,WAAW,WAAW,gBAAgB,SAAS,eAAe;AAAA,IAC1E;AACA,UAAM,OAAO,WAAW,cAAc,SAAS,iBAAiB,CAAC;AACjE,UAAM,OAAO,WAAW,cAAc,UAAU,iBAAiB,iBAAiB;AAClF,UAAM,OAAO,WAAW,cAAc,SAAS,iBAAiB,eAAe;AAC/E,UAAM,OAAO,WAAW,cAAc,WAAW,iBAAiB,iBAAiB;AACnF,UAAM,OAAO,WAAW,cAAc,QAAQ,iBAAiB,cAAc;AAAA,EAC/E;AAEA,MAAI,IAAI,mBAAmB,KAAK,CAAC,QAAQ;AACvC,UAAM,MAAM,IAAI;AAAA,MACd,IAAI,YAAY;AAAA,MAChB,IAAI,YAAY;AAAA,MAChB,IAAI,YAAY;AAAA,IAClB;AACA,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B;AAAA,QACE,MAAM;AAAA,QACN,WAAW,YAAY,CAAC;AAAA,QACxB;AAAA,QACA,IAAI,SAAS,IAAI,GAAG,IAAI;AAAA,MAC1B;AAAA,IACF;AACA,UAAM,IAAI,WAAW,WAAW,OAAO,SAAS,gBAAgB,IAAI,IAAI,CAAC;AACzE,UAAM,IAAI,WAAW,WAAW,eAAe,SAAS,gBAAgB,IAAI,SAAS,CAAC;AAEtF,QAAI,MAAM,IAAI,WAAW,WAAW,cAAc,OAAO,IAAI,GAAG;AAC9D,YAAM,OAAO,UAAU;AACvB,YAAM,IAAI,WAAW,WAAW,cAAc,OAAO,IAAI,UAAU,CAAC,IAAI,OAAO,CAAC;AAChF,YAAM,IAAI,WAAW,WAAW,cAAc,OAAO,IAAI,IAAI,UAAU,CAAC,IAAI,OAAO,CAAC;AACpF,YAAM,IAAI,WAAW,WAAW,cAAc,OAAO,IAAI,IAAI,UAAU,CAAC,IAAI,OAAO,CAAC;AAAA,IACtF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,UAAU,gBAAgB,SAAS,GAAG;AAC3D,eAAW,KAAK,gBAAiB,SAAQ,MAAM,IAAI,EAAE,MAAM,EAAE,KAAK;AAAA,EACpE;AAEA,SAAO,EAAE,gBAAgB;AAC3B;AAEA,SAAS,gBAAgB,KAA8B;AACrD,QAAM,OAAO,oBAAI,IAAY;AAC7B,WAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,UAAM,KAAK,IAAI,WAAW,WAAW,gBAAgB,CAAC;AACtD,QAAI,OAAO,gBAAiB,MAAK,IAAI,EAAE;AAAA,EACzC;AACA,WAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,QAAI,CAAC,KAAK,IAAI,CAAC,EAAG,QAAO;AAAA,EAC3B;AACA,QAAM,IAAI,cAAc,wBAAwB;AAClD;;;ACtaA,SAAS,kBAAkB,YAAAC,WAAyB,gBAAAC,qBAAoB;AACxE,SAAS,iBAAAC,sBAAsC;AAuB/C,IAAM,cAAc,cAAe;AAqBnC,SAAS,uBAAuB,MAAc,OAA4C;AACxF,QAAM,OAAOC,cAAaC,cAAa,EAAE,IAAI,SAAS,CAAC;AACvD,MAAI,CAAC,KAAM,OAAM,IAAI,cAAc,qBAAqB,EAAE,MAAM,CAAC;AACjE,QAAM,IAAI,KAAK;AACf,MACE,MAAMC,UAAS,YACf,MAAMA,UAAS,aACf,MAAMA,UAAS,aACf,MAAMA,UAAS,cACf,MAAMA,UAAS,WACf;AACA,UAAM,IAAI,cAAc,qBAAqB,EAAE,MAAM,CAAC;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,MAAc,OAAqC;AAC1E,QAAM,OAAOF,cAAaC,cAAa,EAAE,IAAI,SAAS,CAAC;AACvD,MAAI,CAAC,KAAM,OAAM,IAAI,cAAc,qBAAqB,EAAE,MAAM,CAAC;AACjE,QAAM,IAAI,KAAK;AACf,MAAI,MAAMC,UAAS,kBAAkB,MAAMA,UAAS,gBAAgB;AAClE,UAAM,IAAI,cAAc,qBAAqB,EAAE,MAAM,CAAC;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAA0B;AAClD,QAAM,IAAI,WAAW,IAAI;AACzB,SAAO;AAAA,IACL,QAAQ,EAAE,OAAO,IAAI,CAAC,MAAM,MAAM,uBAAuB,MAAM,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC;AAAA,IACrF,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,MAAM,gBAAgB,MAAM,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC;AAAA,IAC3E,QAAQ,EAAE,SACN,kBAAkBD,gBAAe,EAAE,QAAQ,GAAG,IAAI,WAAWC,UAAS,YAAY,IAClF;AAAA,IACJ,SAAS,EAAE,UACP,kBAAkBD,gBAAe,EAAE,SAAS,GAAG,IAAI,YAAYC,UAAS,YAAY,IACpF;AAAA,IACJ,QAAQ;AAAA,MACND;AAAA,MACA,kBAAkB,IAAI;AAAA,MACtB,GAAG,IAAI;AAAA,MACPC,UAAS;AAAA,IACX;AAAA,IACA,SAAS;AAAA,MACPD;AAAA,MACA,mBAAmB,IAAI;AAAA,MACvB,GAAG,IAAI;AAAA,MACPC,UAAS;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,MACND;AAAA,MACA,mBAAmB,IAAI;AAAA,MACvB,GAAG,IAAI;AAAA,MACPC,UAAS;AAAA,IACX;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,OAAwB,QAAmB,MAAuB;AACzF,QAAM,SAAS,MAAM;AACrB,MAAI,MAAM,cAAc,IAAI;AAC5B,aAAW,QAAQ,OAAO,OAAQ,OAAM,KAAK,IAAI,KAAM,OAAO,IAAI,IAAI,EAAgB,MAAM;AAC5F,aAAW,QAAQ,OAAO,MAAO,OAAM,KAAK,IAAI,KAAM,OAAO,IAAI,IAAI,EAAgB,MAAM;AAC3F,MAAI,OAAO,OAAQ,OAAM,KAAK,IAAI,KAAM,OAAO,IAAI,OAAO,MAAM,EAAgB,MAAM;AACtF,MAAI,OAAO,QAAS,OAAM,KAAK,IAAI,KAAM,OAAO,IAAI,OAAO,OAAO,EAAgB,MAAM;AACxF,QAAM,KAAK,IAAI,KAAM,OAAO,IAAI,OAAO,MAAM,EAAgB,MAAM;AACnE,QAAM,KAAK,IAAI,KAAM,OAAO,IAAI,OAAO,OAAO,EAAgB,MAAM;AACpE,QAAM,KAAK,IAAI,KAAM,OAAO,IAAI,OAAO,MAAM,EAAgB,MAAM;AACnE,SAAO;AACT;AAEA,SAAS,WACP,QACA,MACA,SACY;AACZ,QAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAM,KAAK,IAAI,SAAS,IAAI,MAAM;AAClC,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAKA,UAAS;AACZ,SAAG,SAAS,GAAG,OAAO,WAAW,MAAuC,OAAO,IAAI,GAAG,IAAI;AAC1F,aAAO;AAAA,IACT,KAAKA,UAAS;AACZ,SAAG;AAAA,QACD;AAAA,QACA,OAAO,WAAW,MAAwC,OAAO,MAAM;AAAA,QACvE;AAAA,MACF;AACA,aAAO;AAAA,IACT,KAAKA,UAAS;AACZ,SAAG;AAAA,QACD;AAAA,QACA,OAAO,WAAW,MAAwC,OAAO,MAAM;AAAA,QACvE;AAAA,MACF;AACA,aAAO;AAAA,IACT,KAAKA,UAAS;AACZ,SAAG,WAAW,GAAG,OAAO,WAAW,MAAyC,OAAO,GAAG,IAAI;AAC1F,aAAO;AAAA,IACT,KAAKA,UAAS;AACZ,UAAI,CAAC,IAAI,OAAO,WAAW,MAAwC,OAAO,IAAI,IAAI;AAClF,aAAO;AAAA,EACX;AACF;AAEA,SAAS,YACP,QACA,MACA,SACA,KACM;AACN,QAAM,KAAK,IAAI,SAAS,IAAI,QAAQ,IAAI,YAAY,CAAC;AACrD,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAKA,UAAS;AACZ,aAAO,WAAW,MAAuC,SAAS,GAAG,SAAS,GAAG,IAAI,IAAI,CAAC;AAC1F;AAAA,IACF,KAAKA,UAAS;AACZ,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,GAAG,UAAU,GAAG,IAAI,MAAM;AAAA,MAC5B;AACA;AAAA,IACF,KAAKA,UAAS;AACZ,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,GAAG,UAAU,GAAG,IAAI,MAAM;AAAA,MAC5B;AACA;AAAA,IACF,KAAKA,UAAS;AACZ,aAAO,WAAW,MAAyC,SAAS,GAAG,WAAW,GAAG,IAAI,CAAC;AAC1F;AAAA,IACF,KAAKA,UAAS;AACZ,aAAO;AAAA,QACL;AAAA,QACA;AAAA,SACC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO;AAAA,MAC1C;AACA;AAAA,EACJ;AACF;AAEA,SAAS,YAAY,MAAsC;AACzD,QAAM,KAAK,iBAAiB,KAAK,IAAI;AACrC,MAAI,OAAO,MAAM,OAAO,KAAK;AAC3B,UAAM,IAAI,cAAc,qBAAqB,EAAE,OAAO,OAAO,CAAC;AAAA,EAChE;AACA,SAAO;AACT;AAEA,SAAS,cACP,QACA,MACA,SACY;AACZ,QAAM,MAAM,OAAO,WAAW,MAAM,OAAO;AAC3C,SAAO,gBAAgB,KAAK,YAAY,IAAI,CAAC;AAC/C;AAEA,SAAS,eACP,QACA,MACA,SACA,KACM;AACN,SAAO,WAAW,MAAM,SAAS,gBAAgB,GAAG,CAAC;AACvD;AAEA,SAAS,YACP,QACA,MACA,SACY;AACZ,QAAM,IAAI,OAAO,WAAW,MAAM,OAAO;AACzC,QAAM,MAAM,IAAI,WAAW,EAAE;AAC7B,QAAM,KAAK,IAAI,SAAS,IAAI,MAAM;AAClC,KAAG,WAAW,GAAG,EAAE,GAAG,IAAI;AAC1B,KAAG,WAAW,GAAG,EAAE,GAAG,IAAI;AAC1B,KAAG,WAAW,GAAG,EAAE,GAAG,IAAI;AAC1B,SAAO;AACT;AAEA,SAAS,aACP,QACA,MACA,SACA,KACM;AACN,QAAM,KAAK,IAAI,SAAS,IAAI,QAAQ,IAAI,YAAY,EAAE;AACtD,SAAO,WAAW,MAAM,SAAS;AAAA,IAC/B,GAAG,GAAG,WAAW,GAAG,IAAI;AAAA,IACxB,GAAG,GAAG,WAAW,GAAG,IAAI;AAAA,IACxB,GAAG,GAAG,WAAW,GAAG,IAAI;AAAA,EAC1B,CAAC;AACH;AAEA,SAAS,YACP,QACA,MACA,SACY;AACZ,QAAM,IAAI,OAAO,WAAW,MAAM,OAAO;AACzC,QAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAM,KAAK,IAAI,SAAS,IAAI,MAAM;AAClC,KAAG,WAAW,GAAG,EAAE,GAAG,IAAI;AAC1B,KAAG,WAAW,GAAG,EAAE,GAAG,IAAI;AAC1B,SAAO;AACT;AAEA,SAAS,aACP,QACA,MACA,SACA,KACM;AACN,QAAM,KAAK,IAAI,SAAS,IAAI,QAAQ,IAAI,YAAY,CAAC;AACrD,SAAO,WAAW,MAAM,SAAS;AAAA,IAC/B,GAAG,GAAG,WAAW,GAAG,IAAI;AAAA,IACxB,GAAG,GAAG,WAAW,GAAG,IAAI;AAAA,EAC1B,CAAC;AACH;AAmBO,SAAS,aACd,OACA,MACA,UAAyB,eACV;AACf,QAAM,MAAqB,CAAC;AAC5B,MAAI,MAAM,cAAc,IAAI;AAC5B,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,iBAAiB,IAAI;AACpC,eAAW,gBAAgB,gBAAgB,IAAI,GAAG,GAAG,IAAI,QAAQ;AACjE,UAAM,gBAAgB,OAAO,QAAQ,IAAI;AAAA,EAC3C,QAAQ;AACN,eAAW;AAAA,EACb;AAEA,MAAI,eAAe;AACnB,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,UAAM,WAAW,kBAAkB,MAAM,CAAC;AAC1C,UAAM,SAAS,QAAQ,MAAM,IAAI,QAAQ;AACzC,UAAM,UAAU,WAAW,MAAM,OAAO,WAAW,UAAU,CAAC,IAAI;AAClE,UAAM,cAAc,QAAQ,SAAS;AAErC,QAAI,UAAW,QAAQ,WAAW,UAAU,aAAc;AACxD,UAAI,KAAK,EAAE,MAAM,IAAI,GAAG,OAAO,OAAO,MAAM,SAAS,UAAU,MAAM,CAAC;AAAA,IACxE,WAAW,CAAC,cAAc;AACxB,UAAI,KAAK,EAAE,MAAM,IAAI,GAAG,OAAO,MAAM,MAAM,IAAI,UAAU,KAAK,CAAC;AAC/D,qBAAe;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAmBO,SAAS,WACd,OACA,MACA,MACA,UAAyB,eACP;AAClB,QAAM,SAAS,iBAAiB,IAAI;AACpC,QAAM,SAAS,MAAM;AACrB,QAAM,UAAU,OAAO;AACvB,QAAM,YAAY,aAAa,IAAI;AAEnC,QAAM,SAAS,IAAI,WAAW,OAAO,OAAO,SAAS,CAAC;AACtD,WAAS,IAAI,GAAG,IAAI,OAAO,OAAO,QAAQ,KAAK;AAC7C,WAAO,IAAI,WAAW,QAAQ,OAAO,OAAO,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;AAAA,EACjE;AACA,QAAM,SAAS,OAAO,SAAS,YAAY,QAAQ,OAAO,QAAQ,OAAO,IAAI,IAAI,WAAW,EAAE;AAC9F,QAAM,UAAU,OAAO,UAAU,YAAY,QAAQ,OAAO,SAAS,OAAO,IAAI,IAAI,WAAW,CAAC;AAChG,QAAM,OAAO,cAAc,QAAQ,OAAO,MAAM,CAAC,GAAG,OAAO;AAC3D,QAAM,YAAY,cAAc,QAAQ,OAAO,MAAM,CAAC,GAAG,OAAO;AAEhE,MAAI;AACJ,MAAI;AACJ,MAAI,SAAS,WAAW,OAAO,MAAM,CAAC,MAAM,UAAa,OAAO,MAAM,CAAC,MAAM,QAAW;AACtF,gBAAY,cAAc,QAAQ,OAAO,MAAM,CAAC,GAAG,OAAO;AAC1D,qBAAiB,cAAc,QAAQ,OAAO,MAAM,CAAC,GAAG,OAAO;AAAA,EACjE;AAEA,QAAM,aAAa,kBAAkB,MAAM,OAAO;AAClD,QAAM,UAAU,eAAe,MAAM,OAAO;AAC5C,QAAM,YAAY,iBAAiB,MAAM,OAAO;AAChD,QAAM,YAAY,QAAQ,MAAM,IAAI,UAAU;AAC9C,QAAM,SAAS,QAAQ,MAAM,IAAI,OAAO;AACxC,QAAM,WAAW,QAAQ,MAAM,IAAI,SAAS;AAE5C,MAAI,CAAC,aAAa,CAAC,UAAU,CAAC,UAAU;AACtC,UAAM,IAAI,cAAc,sBAAsB;AAAA,EAChD;AAEA,QAAM,MAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,aAAa,GAAG;AAC9B,QAAM,cAAc,gBAAgB,IAAI,KAAK,MAAM,IAAI,GAAG,OAAO;AACjE,QAAM,WAAW,GAAG,iBAAiB,WAAW,CAAC,GAAG,oBAAoB,IAAI,CAAC;AAC7E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,MACR,EAAE,MAAM,YAAY,OAAO,UAAU;AAAA,MACrC,EAAE,MAAM,SAAS,OAAO,OAAO;AAAA,MAC/B,EAAE,MAAM,WAAW,OAAO,SAAS;AAAA,IACrC;AAAA,EACF;AACF;AAeO,SAAS,SACd,OACA,MACA,MACA,UACA,UACA,UAAyB,eACT;AAChB,QAAM,UAAU,aAAa,QAAQ;AACrC,QAAM,WAAW,aAAa,IAAI;AAClC,MAAI,QAAQ,cAAc,UAAU;AAClC,UAAM,IAAI,cAAc,kBAAkB,EAAE,KAAK,QAAQ,WAAW,SAAS,CAAC;AAAA,EAChF;AAEA,QAAM,SAAS,iBAAiB,IAAI;AACpC,QAAM,SAAS,MAAM;AACrB,QAAM,UAAU,OAAO;AACvB,QAAM,WAAW,gBAAgB,OAAO,QAAQ,IAAI;AACpD,MAAI,UAAU,KAAK,WAAW,UAAU;AACtC,UAAM,IAAI,cAAc,qBAAqB,EAAE,MAAM,MAAM,SAAS,CAAC;AAAA,EACvE;AAEA,OAAK,SAAS,WAAW,SAAS,YAAY,CAAC,UAAU;AACvD,UAAM,WAAW,WAAW,QAAQ,OAAO,OAAO,CAAC,GAAG,OAAO;AAC7D,UAAM,WAAW,QAAQ,iBAAiB,SAAS,GAAG,CAAC;AACvD,QAAI,CAAC,aAAa,UAAU,QAAQ,GAAG;AACrC,YAAM,IAAI,cAAc,kBAAkB;AAAA,IAC5C;AAAA,EACF;AACA,OAAK,SAAS,cAAc,SAAS,gBAAgB,CAAC,UAAU;AAC9D,UAAM,IAAI,cAAc,uBAAuB,EAAE,KAAK,CAAC;AAAA,EACzD;AAEA,WAAS,IAAI,GAAG,IAAI,OAAO,OAAO,QAAQ,KAAK;AAC7C,UAAM,MAAM,QAAQ,iBAAiB,SAAS,IAAI,GAAG,IAAI,IAAI,CAAC;AAC9D,gBAAY,QAAQ,OAAO,OAAO,CAAC,GAAG,SAAS,GAAG;AAAA,EACpD;AAEA,MAAI,UAAU;AACZ,WAAO,WAAW,OAAO,QAAQ,SAAS,WAAW;AACrD,UAAM,QAAQ,IAAI;AAAA,MAChB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AACA,UAAM,SAAS,MAAM,UAAU,WAAW,GAAG,IAAI,MAAM;AACvD,WAAO,WAAW,OAAO,SAAS,SAAS,MAAM;AACjD,UAAM,aAAc,UAAU,OAAU,iBAAiB,IAAI,IAAI,QAAS,QAAS;AACnF,WAAO,WAAW,OAAO,QAAQ,SAAS,SAAS;AAAA,EACrD;AAEA,QAAM,aAAa,QAAQ;AAC3B,iBAAe,QAAQ,OAAO,MAAM,CAAC,GAAG,SAAS,WAAW,SAAS,GAAG,GAAG,CAAC;AAC5E,iBAAe,QAAQ,OAAO,MAAM,CAAC,GAAG,SAAS,WAAW,SAAS,KAAK,GAAG,CAAC;AAC9E,MAAI,SAAS,WAAW,OAAO,MAAM,CAAC,MAAM,UAAa,OAAO,MAAM,CAAC,MAAM,QAAW;AACtF,mBAAe,QAAQ,OAAO,MAAM,CAAC,GAAG,SAAS,WAAW,SAAS,KAAK,GAAG,CAAC;AAC9E,mBAAe,QAAQ,OAAO,MAAM,CAAC,GAAG,SAAS,WAAW,SAAS,KAAK,GAAG,CAAC;AAAA,EAChF;AAEA,QAAM,MAAM,QAAQ;AACpB,MAAI,OAAO,QAAQ;AACjB,UAAM,SAAS,IAAI,aAAa;AAChC,iBAAa,QAAQ,OAAO,QAAQ,SAAS,IAAI,SAAS,QAAQ,SAAS,EAAE,CAAC;AAAA,EAChF;AACA,MAAI,OAAO,SAAS;AAClB,UAAM,UAAU,IAAI,aAAa;AACjC,iBAAa,QAAQ,OAAO,SAAS,SAAS,IAAI,SAAS,SAAS,UAAU,CAAC,CAAC;AAAA,EAClF;AAEA,QAAM,SAAwB;AAAA,IAC5B,EAAE,MAAM,kBAAkB,MAAM,OAAO,GAAG,OAAO,QAAQ,UAAU;AAAA,IACnE,EAAE,MAAM,eAAe,MAAM,OAAO,GAAG,OAAO,QAAQ,OAAO;AAAA,IAC7D,EAAE,MAAM,iBAAiB,MAAM,OAAO,GAAG,OAAO,QAAQ,SAAS;AAAA,EACnE;AACA,MAAI,QAAQ,WAAW,QAAQ;AAC7B,eAAW,KAAK,OAAQ,SAAQ,MAAM,IAAI,EAAE,MAAM,EAAE,KAAK;AAAA,EAC3D;AAEA,SAAO,EAAE,eAAe,OAAO;AACjC;AAEA,SAAS,aAAa,GAAe,GAAwB;AAC3D,MAAI,EAAE,eAAe,EAAE,WAAY,QAAO;AAC1C,WAAS,IAAI,GAAG,IAAI,EAAE,YAAY,KAAK;AACrC,QAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAG,QAAO;AAAA,EAC5B;AACA,SAAO;AACT;","names":["DataType","buildHashMap","MII_SCHEMA","PLAYER_SCHEMA","PLAYER_SCHEMA","DataType","MII_SCHEMA","buildHashMap","data","DataType","buildHashMap","PLAYER_SCHEMA","buildHashMap","PLAYER_SCHEMA","DataType"]}
@@ -1,10 +1,19 @@
1
1
  import { DataType, type Accessor } from '@alexislours/ltd-savedata';
2
2
  import { MII_SCHEMA, PLAYER_SCHEMA, type SchemaLeaf } from '@alexislours/ltd-savedata/schema';
3
+ /** The pair of save accessors a Mii operation needs: the `player` save and the `mii` save. */
3
4
  export type MiiSaves = {
5
+ /** Accessor over the `player` save data. */
4
6
  player: Accessor<'player'>;
7
+ /** Accessor over the `mii` save data. */
5
8
  mii: Accessor<'mii'>;
6
9
  };
10
+ /** The single save accessor a UGC operation needs: UGC items live entirely in the `player` save. */
7
11
  export type PlayerOnlySaves = {
8
12
  player: Accessor<'player'>;
9
13
  };
14
+ /**
15
+ * Resolve a schema leaf by its field hash and assert its {@link DataType}, throwing
16
+ * a `save_format_error` {@link ShareMiiError} (carrying `label`) if the field is
17
+ * absent or has an unexpected type.
18
+ */
10
19
  export declare function leafByHashOrThrow<T extends DataType>(schema: typeof PLAYER_SCHEMA | typeof MII_SCHEMA, hash: number, label: string, expected: T): SchemaLeaf<T>;
package/dist/sidecar.d.ts CHANGED
@@ -1,12 +1,32 @@
1
+ /**
2
+ * A single named texture blob that travels alongside a share file, keyed by its
3
+ * in-save file name (for example `UgcFood000.canvas.zs`).
4
+ */
1
5
  export type SidecarFile = {
6
+ /** In-save file name, used as the lookup key inside a {@link SidecarSource}. */
2
7
  name: string;
8
+ /** Raw, still-compressed file contents. */
3
9
  bytes: Uint8Array;
4
10
  };
11
+ /**
12
+ * A pool of texture files accompanying a save, indexed by file name. `origin`
13
+ * records where it came from so writes can be skipped when there is nowhere to
14
+ * persist them (`'none'`).
15
+ */
5
16
  export type SidecarSource = {
17
+ /** Where the files were loaded from; `'none'` means there is no backing store to write to. */
6
18
  origin: 'none' | 'folder' | 'zip';
19
+ /** File name to raw bytes. Mutated in place when applying a share file with a writable origin. */
7
20
  files: Map<string, Uint8Array>;
8
21
  };
22
+ /** A shared, empty {@link SidecarSource} (`origin: 'none'`) used as the default when no textures are supplied. */
9
23
  export declare const EMPTY_SIDECAR: SidecarSource;
24
+ /** Strip any directory prefix from `name`, returning just the final path segment (handles both `/` and `\` separators). */
10
25
  export declare function normalizeName(name: string): string;
26
+ /** Whether `name` is a recognized sidecar texture file (a `.canvas.zs` or `.ugctex.zs` blob), case-insensitively. */
11
27
  export declare function isSidecarFileName(name: string): boolean;
28
+ /**
29
+ * Whether an archive entry should be ignored when ingesting a folder or zip:
30
+ * directory entries, `__MACOSX` cruft, dotfiles, and empty paths all count as junk.
31
+ */
12
32
  export declare function isJunkArchiveEntry(path: string): boolean;
@@ -1,26 +1,49 @@
1
+ /** The seven categories of user-generated content the game stores and this codec can share. */
1
2
  export type UgcKind = 'Food' | 'Cloth' | 'Goods' | 'Interior' | 'Exterior' | 'MapObject' | 'MapFloor';
3
+ /** Every {@link UgcKind} in canonical order; the array index is the kind's on-disk index (see {@link ugcKindIndex}). */
2
4
  export declare const UGC_KINDS: readonly UgcKind[];
5
+ /** Human-facing label for each {@link UgcKind}, which differs from the internal name (for example `Goods` is shown as "Treasure"). */
3
6
  export declare const UGC_DISPLAY_LABELS: Record<UgcKind, string>;
7
+ /** Share-file extension for each {@link UgcKind} (for example `Food` exports as `.ltdf`). */
4
8
  export declare const UGC_FILE_EXTENSIONS: Record<UgcKind, string>;
9
+ /** The on-disk index of `kind`, that is, its position in {@link UGC_KINDS}. */
5
10
  export declare function ugcKindIndex(kind: UgcKind): number;
11
+ /** Maximum number of slots the game allocates per {@link UgcKind}; the actual capacity may be lower and is clamped against the save's array lengths. */
6
12
  export declare const UGC_MAX_SLOTS: Record<UgcKind, number>;
13
+ /** In-save file name of the editable canvas texture for a UGC `slot` of `kind` (for example `UgcFood003.canvas.zs`). */
7
14
  export declare function ugcCanvasFileName(kind: UgcKind, slot: number): string;
15
+ /** In-save file name of the rendered UGC texture for a `slot` of `kind` (for example `UgcFood003.ugctex.zs`). */
8
16
  export declare function ugcTexFileName(kind: UgcKind, slot: number): string;
17
+ /** In-save file name of the thumbnail texture for a `slot` of `kind` (for example `UgcFood003_Thumb.ugctex.zs`). */
9
18
  export declare function ugcThumbFileName(kind: UgcKind, slot: number): string;
19
+ /** In-save file name of the canvas texture for facepaint `id` (for example `UgcFacePaint012.canvas.zs`). */
10
20
  export declare function facepaintCanvasFileName(id: number): string;
21
+ /** In-save file name of the rendered texture for facepaint `id` (for example `UgcFacePaint012.ugctex.zs`). */
11
22
  export declare function facepaintTexFileName(id: number): string;
23
+ /** The set of save-field hashes that make up one {@link UgcKind}: its scalar fields, name strings, and optional position vectors. */
12
24
  export type UgcFieldHashes = {
25
+ /** Hashes of the scalar (int/uint/enum/float/bool) fields, in serialization order. */
13
26
  fields: readonly number[];
27
+ /** Hashes of the name string fields (name, pronunciation, and for Goods two extra strings). */
14
28
  names: readonly number[];
29
+ /** Hash of the optional `Vector3` field, when the kind has one. */
15
30
  vector?: number;
31
+ /** Hash of the optional `Vector2` field, when the kind has one. */
16
32
  vector2?: number;
17
33
  };
34
+ /** Per-{@link UgcKind} map of the save-field hashes ({@link UgcFieldHashes}) the codec reads and writes for that kind. */
18
35
  export declare const UGC_HASHES: Record<UgcKind, UgcFieldHashes>;
36
+ /** Hash of the per-{@link UgcKind} "slot enabled" enum field, set when a newly added item should be marked as in use. */
19
37
  export declare const UGC_ENABLE_HASHES: Record<UgcKind, number>;
38
+ /** Hash of the per-{@link UgcKind} texture-source enum field, set to the value derived from {@link UGC_TEX_DATA} when adding an item. */
20
39
  export declare const UGC_TEXTURE_HASHES: Record<UgcKind, number>;
40
+ /** Hash of the per-{@link UgcKind} content-id field, set to a value combining the slot index and {@link UGC_HASH_INDICES} when adding an item. */
21
41
  export declare const UGC_HASH_ID_HASHES: Record<UgcKind, number>;
22
- export declare const UGC_TEX_DATA: Uint8Array<ArrayBuffer>;
42
+ /** Packed little-endian table of texture-source enum values, indexed by {@link ugcKindIndex} times 4, applied to {@link UGC_TEXTURE_HASHES} when adding an item. */
43
+ export declare const UGC_TEX_DATA: Uint8Array;
44
+ /** Per-{@link UgcKind} tag packed into the high byte of the content-id field (see {@link UGC_HASH_ID_HASHES}) when adding an item. */
23
45
  export declare const UGC_HASH_INDICES: Record<UgcKind, number>;
46
+ /** Save-field hashes for the facepaint slot arrays in the `player` save: price, texture source, state, and bookkeeping fields toggled when a Mii's facepaint is added or cleared. */
24
47
  export declare const FACEPAINT_HASHES: {
25
48
  price: number;
26
49
  textureSourceType: number;
@@ -28,6 +51,7 @@ export declare const FACEPAINT_HASHES: {
28
51
  unknown: number;
29
52
  hash: number;
30
53
  };
54
+ /** Save-field hashes for the Mii data this codec reads and writes: facepaint index, the temp slot, name/pronunciation, raw Mii block, love-gender flags, satisfaction level, and the eighteen personality fields. */
31
55
  export declare const MII_HASHES: {
32
56
  facePaintIndex: number;
33
57
  tempSlotMii: number;
@@ -38,4 +62,5 @@ export declare const MII_HASHES: {
38
62
  satisfyLevel: number;
39
63
  personality: readonly [1137522255, 3448617720, 632586788, 1618714976, 1759581006, 1226026522, 337567878, 129618293, 2177845002, 1299767906, 4223926192, 594423155, 4089699929, 1712083527, 1568489285, 2878005387, 625337731, 1827964148];
40
64
  };
65
+ /** Hash of the primary display-name field for each {@link UgcKind}, used to detect filled slots when listing items. */
41
66
  export declare const UGC_NAME_HASHES: Record<UgcKind, number>;
package/dist/utf16.d.ts CHANGED
@@ -1,3 +1,15 @@
1
+ /**
2
+ * Decode a fixed-width little-endian UTF-16 name buffer into a string, stopping
3
+ * at the first NUL code unit (the in-save string terminator).
4
+ */
1
5
  export declare function decodeUtf16Name(buf: Uint8Array): string;
6
+ /**
7
+ * Reduce a display name to a safe file-name stem by replacing every character
8
+ * outside `[A-Za-z0-9_.-]` with `_`, falling back to `'mii'` when nothing remains.
9
+ */
2
10
  export declare function sanitizeFileName(name: string): string;
11
+ /**
12
+ * Encode `text` as little-endian UTF-16 into a fresh `byteLen`-byte buffer,
13
+ * truncating to fit while always leaving room for the trailing NUL terminator.
14
+ */
3
15
  export declare function encodeUtf16Name(text: string, byteLen: number): Uint8Array;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexislours/ltd-sharemii",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Codec for the game's Mii and UGC share format: extract a Mii or user-generated content item from a save into a portable share file and apply it back. Depends only on @alexislours/ltd-savedata.",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "author": "Alexis Lours",