@bitmagic/asset-core 0.1.0 → 0.1.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/dist/cover-prompt.d.ts +32 -0
- package/dist/cover-prompt.d.ts.map +1 -0
- package/dist/cover-prompt.js +41 -0
- package/dist/cover-prompt.js.map +1 -0
- package/dist/favicon.d.ts +74 -0
- package/dist/favicon.d.ts.map +1 -0
- package/dist/favicon.js +130 -0
- package/dist/favicon.js.map +1 -0
- package/dist/generators/prop.d.ts +43 -0
- package/dist/generators/prop.d.ts.map +1 -0
- package/dist/generators/prop.js +80 -0
- package/dist/generators/prop.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +15 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cover-art prompt composition, shared by every lane that generates a game's
|
|
3
|
+
* cover image: Creator's Planning Mode and the per-game cover endpoint in
|
|
4
|
+
* game-play-agent, the offline template-cover script, and `bitmagic cover` in
|
|
5
|
+
* the CLI lane. It lives here rather than in any one of them because the style
|
|
6
|
+
* direction is what makes covers from all of them read as the same product —
|
|
7
|
+
* a copy that drifts produces art that visibly does not match.
|
|
8
|
+
*
|
|
9
|
+
* No network, no credentials: this module composes strings. Each lane calls its
|
|
10
|
+
* own image generator with the result.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Shared style direction for every Bitmagic cover image: the polished voxel
|
|
14
|
+
* craft of "if Pixar made a voxel game," kept mood-neutral so the per-scene
|
|
15
|
+
* description sets the tone (cheerful adventure vs. dark horror). Do NOT bake
|
|
16
|
+
* mood/lighting words (golden-hour, cheerful, scary) in here — those belong in
|
|
17
|
+
* the scene description.
|
|
18
|
+
*/
|
|
19
|
+
export declare const PIXAR_VOXEL_STYLE: string;
|
|
20
|
+
/** How much of the design text reaches the image model; the rest is dropped. */
|
|
21
|
+
export declare const MAX_COVER_DESIGN_CHARS = 1500;
|
|
22
|
+
/**
|
|
23
|
+
* Compose the image prompt for a cover image from a game's design text
|
|
24
|
+
* (GAME-DESIGN.md content or, during planning, the pitch/plan doc). Falls back
|
|
25
|
+
* to a generic voxel scene when none is present.
|
|
26
|
+
*
|
|
27
|
+
* The game name is deliberately NEVER injected — naming the game makes image
|
|
28
|
+
* models render the title as on-image text. We describe a wordless scene and
|
|
29
|
+
* append a strong no-text directive.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildCoverArtPrompt(gameDesign: string): string;
|
|
32
|
+
//# sourceMappingURL=cover-prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cover-prompt.d.ts","sourceRoot":"","sources":["../src/cover-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,QAIsD,CAAC;AAErF,gFAAgF;AAChF,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAQ9D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cover-art prompt composition, shared by every lane that generates a game's
|
|
3
|
+
* cover image: Creator's Planning Mode and the per-game cover endpoint in
|
|
4
|
+
* game-play-agent, the offline template-cover script, and `bitmagic cover` in
|
|
5
|
+
* the CLI lane. It lives here rather than in any one of them because the style
|
|
6
|
+
* direction is what makes covers from all of them read as the same product —
|
|
7
|
+
* a copy that drifts produces art that visibly does not match.
|
|
8
|
+
*
|
|
9
|
+
* No network, no credentials: this module composes strings. Each lane calls its
|
|
10
|
+
* own image generator with the result.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Shared style direction for every Bitmagic cover image: the polished voxel
|
|
14
|
+
* craft of "if Pixar made a voxel game," kept mood-neutral so the per-scene
|
|
15
|
+
* description sets the tone (cheerful adventure vs. dark horror). Do NOT bake
|
|
16
|
+
* mood/lighting words (golden-hour, cheerful, scary) in here — those belong in
|
|
17
|
+
* the scene description.
|
|
18
|
+
*/
|
|
19
|
+
export const PIXAR_VOXEL_STYLE = 'highly polished 3D render in the voxel craft of a Pixar-quality animated film, ' +
|
|
20
|
+
'cinematic lighting that fits the scene, soft ambient occlusion, subtle subsurface scattering, ' +
|
|
21
|
+
'rich detail and expressive composition. ' +
|
|
22
|
+
'Wordless illustration, no text, no title, no words, no letters, no logos, no UI.';
|
|
23
|
+
/** How much of the design text reaches the image model; the rest is dropped. */
|
|
24
|
+
export const MAX_COVER_DESIGN_CHARS = 1500;
|
|
25
|
+
/**
|
|
26
|
+
* Compose the image prompt for a cover image from a game's design text
|
|
27
|
+
* (GAME-DESIGN.md content or, during planning, the pitch/plan doc). Falls back
|
|
28
|
+
* to a generic voxel scene when none is present.
|
|
29
|
+
*
|
|
30
|
+
* The game name is deliberately NEVER injected — naming the game makes image
|
|
31
|
+
* models render the title as on-image text. We describe a wordless scene and
|
|
32
|
+
* append a strong no-text directive.
|
|
33
|
+
*/
|
|
34
|
+
export function buildCoverArtPrompt(gameDesign) {
|
|
35
|
+
const excerpt = gameDesign.trim().slice(0, MAX_COVER_DESIGN_CHARS);
|
|
36
|
+
if (!excerpt) {
|
|
37
|
+
return `A charming, inviting voxel adventure game scene, colorful and full of character. ${PIXAR_VOXEL_STYLE}`;
|
|
38
|
+
}
|
|
39
|
+
return `A voxel game scene based on this game design:\n${excerpt}\n\nDepict the world and atmosphere as a single illustrated scene. ${PIXAR_VOXEL_STYLE}`;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=cover-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cover-prompt.js","sourceRoot":"","sources":["../src/cover-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC5B,iFAAiF;IACjF,gGAAgG;IAChG,0CAA0C;IAC1C,kFAAkF,CAAC;AAErF,gFAAgF;AAChF,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAE3C;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;IAEnE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,oFAAoF,iBAAiB,EAAE,CAAC;IACjH,CAAC;IAED,OAAO,kDAAkD,OAAO,sEAAsE,iBAAiB,EAAE,CAAC;AAC5J,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The published game's browser-tab icon: the one `<link>` element, the one storage-key
|
|
3
|
+
* derivation, and the one function that swaps the default out for a game's own.
|
|
4
|
+
*
|
|
5
|
+
* Import path matters: this module is published as the `@bitmagic/asset-core/favicon`
|
|
6
|
+
* subpath so its consumers do not drag in the root barrel's zod / three / forger client.
|
|
7
|
+
* It is node-only (`node:crypto`) — the three consumers are game-play-agent (web publish
|
|
8
|
+
* lane), api-server (CLI publish lane) and the CLI itself. The Creator never imports it;
|
|
9
|
+
* it uploads a source image and lets publish do the deriving.
|
|
10
|
+
*
|
|
11
|
+
* Why this lives in a shared package rather than being duplicated per lane: the two
|
|
12
|
+
* publish lanes must agree on the marker id and on the exact `<link>` they emit, or a
|
|
13
|
+
* game's icon silently reverts to the Bitmagic mark in whichever lane drifted. The pieces
|
|
14
|
+
* where drift breaks correctness are shared here; the sharp resize is NOT (it would drag
|
|
15
|
+
* a heavy native dep into a package the browser-facing subpaths live beside), and is
|
|
16
|
+
* deliberately mirrored in each lane instead.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The id on the default `<link rel="icon">` baked into every game bundle — `game/index.html`
|
|
20
|
+
* for the web lane, `renderIndexHtml()` for CLI projects. Publish finds the element by this
|
|
21
|
+
* id and replaces it wholesale.
|
|
22
|
+
*
|
|
23
|
+
* Replacing rather than appending a second link is deliberate. Two `sizes`-less `rel="icon"`
|
|
24
|
+
* links is ambiguous input: "the last one wins" is browser convention, not spec, and Safari
|
|
25
|
+
* has historically picked differently from Chrome. After `applyFaviconLink` the document
|
|
26
|
+
* carries exactly one icon link, which is something a test can assert.
|
|
27
|
+
*/
|
|
28
|
+
export declare const FAVICON_LINK_ID = "bm-favicon";
|
|
29
|
+
/**
|
|
30
|
+
* Edge length of the derived icon. A retina browser tab renders a 32 CSS px icon at 2x, so
|
|
31
|
+
* 64 is the real ceiling that matters; it also covers bookmark and taskbar use at 48.
|
|
32
|
+
* Browsers downscale cleanly, so a single size beats emitting several `sizes=` variants.
|
|
33
|
+
*/
|
|
34
|
+
export declare const FAVICON_PX = 64;
|
|
35
|
+
/**
|
|
36
|
+
* 32 hex chars of sha256 over the SOURCE URL — not over the source bytes.
|
|
37
|
+
*
|
|
38
|
+
* Hashing the URL is what makes the cache free: the storage key is computable without
|
|
39
|
+
* fetching anything, so a cache hit costs one existence probe and no download. It is sound
|
|
40
|
+
* because every cover/upload URL in both lanes is already timestamp-unique per upload, so
|
|
41
|
+
* new art always produces a new URL and therefore a new key.
|
|
42
|
+
*/
|
|
43
|
+
export declare function faviconContentHash(sourceUrl: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Where the web lane stores an icon derived from `sourceUrl`, relative to the storage
|
|
46
|
+
* prefix (`worlds/v3`). The CLI lane composes its own game-scoped key from
|
|
47
|
+
* `faviconContentHash` instead, because its bucket layout is per-game rather than shared.
|
|
48
|
+
*
|
|
49
|
+
* The `v1` segment and the `-64` suffix are load-bearing: changing the crop or the size
|
|
50
|
+
* must produce a NEW key rather than silently serving the old bytes from an immutable
|
|
51
|
+
* `max-age=31536000` object. Same reasoning as the hand-rolled `-v2` on the watermark logo.
|
|
52
|
+
*/
|
|
53
|
+
export declare function faviconStorageKey(sourceUrl: string): string;
|
|
54
|
+
/** The exact element every lane emits. One definition so the lanes cannot disagree. */
|
|
55
|
+
export declare function renderFaviconLink(href: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Point the document's icon at `href`.
|
|
58
|
+
*
|
|
59
|
+
* Replaces the element carrying `id="bm-favicon"`. When that marker is absent — an older
|
|
60
|
+
* cached bundle, or a CLI project that has not run `bitmagic upgrade` since the marker
|
|
61
|
+
* shipped — falls back to inserting before `</head>`, which is best-effort but never worse
|
|
62
|
+
* than the un-marked status quo.
|
|
63
|
+
*
|
|
64
|
+
* Returns `html` unchanged when `href` is missing or not an allowed scheme, and never
|
|
65
|
+
* throws: a tab icon must not be able to fail a publish.
|
|
66
|
+
*
|
|
67
|
+
* `indexOf` rather than a regex on purpose. The default href is a ~700-char base64 data URI
|
|
68
|
+
* sitting inside a bundle that reaches 20 MB, and the surrounding code (`injectIntoHtml`)
|
|
69
|
+
* is string-insertion for the same reason. Anchored `indexOf` scans are O(n) with tiny
|
|
70
|
+
* constants and have obvious failure semantics; a backtracking regex over that string does
|
|
71
|
+
* not.
|
|
72
|
+
*/
|
|
73
|
+
export declare function applyFaviconLink(html: string, href: string | null | undefined): string;
|
|
74
|
+
//# sourceMappingURL=favicon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favicon.d.ts","sourceRoot":"","sources":["../src/favicon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,eAAe,CAAC;AAE5C;;;;GAIG;AACH,eAAO,MAAM,UAAU,KAAK,CAAC;AAqB7B;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAuBtF"}
|
package/dist/favicon.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The published game's browser-tab icon: the one `<link>` element, the one storage-key
|
|
3
|
+
* derivation, and the one function that swaps the default out for a game's own.
|
|
4
|
+
*
|
|
5
|
+
* Import path matters: this module is published as the `@bitmagic/asset-core/favicon`
|
|
6
|
+
* subpath so its consumers do not drag in the root barrel's zod / three / forger client.
|
|
7
|
+
* It is node-only (`node:crypto`) — the three consumers are game-play-agent (web publish
|
|
8
|
+
* lane), api-server (CLI publish lane) and the CLI itself. The Creator never imports it;
|
|
9
|
+
* it uploads a source image and lets publish do the deriving.
|
|
10
|
+
*
|
|
11
|
+
* Why this lives in a shared package rather than being duplicated per lane: the two
|
|
12
|
+
* publish lanes must agree on the marker id and on the exact `<link>` they emit, or a
|
|
13
|
+
* game's icon silently reverts to the Bitmagic mark in whichever lane drifted. The pieces
|
|
14
|
+
* where drift breaks correctness are shared here; the sharp resize is NOT (it would drag
|
|
15
|
+
* a heavy native dep into a package the browser-facing subpaths live beside), and is
|
|
16
|
+
* deliberately mirrored in each lane instead.
|
|
17
|
+
*/
|
|
18
|
+
import { createHash } from 'node:crypto';
|
|
19
|
+
/**
|
|
20
|
+
* The id on the default `<link rel="icon">` baked into every game bundle — `game/index.html`
|
|
21
|
+
* for the web lane, `renderIndexHtml()` for CLI projects. Publish finds the element by this
|
|
22
|
+
* id and replaces it wholesale.
|
|
23
|
+
*
|
|
24
|
+
* Replacing rather than appending a second link is deliberate. Two `sizes`-less `rel="icon"`
|
|
25
|
+
* links is ambiguous input: "the last one wins" is browser convention, not spec, and Safari
|
|
26
|
+
* has historically picked differently from Chrome. After `applyFaviconLink` the document
|
|
27
|
+
* carries exactly one icon link, which is something a test can assert.
|
|
28
|
+
*/
|
|
29
|
+
export const FAVICON_LINK_ID = 'bm-favicon';
|
|
30
|
+
/**
|
|
31
|
+
* Edge length of the derived icon. A retina browser tab renders a 32 CSS px icon at 2x, so
|
|
32
|
+
* 64 is the real ceiling that matters; it also covers bookmark and taskbar use at 48.
|
|
33
|
+
* Browsers downscale cleanly, so a single size beats emitting several `sizes=` variants.
|
|
34
|
+
*/
|
|
35
|
+
export const FAVICON_PX = 64;
|
|
36
|
+
/** Attribute-safe. The href reaches a public page's `<head>` and may be creator-supplied. */
|
|
37
|
+
function escapeAttr(value) {
|
|
38
|
+
return value
|
|
39
|
+
.replace(/&/g, '&')
|
|
40
|
+
.replace(/"/g, '"')
|
|
41
|
+
.replace(/</g, '<')
|
|
42
|
+
.replace(/>/g, '>');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Only these two forms may become an icon href. Escaping alone is not the whole guard — a
|
|
46
|
+
* `javascript:` URL in a `<link href>` is inert in modern browsers, but this string is
|
|
47
|
+
* assembled from creator-controlled data and baked into a public page, so the allowlist is
|
|
48
|
+
* the guard and the escaping is defence in depth.
|
|
49
|
+
*/
|
|
50
|
+
function isAllowedHref(href) {
|
|
51
|
+
return /^https:\/\//i.test(href) || /^data:image\//i.test(href);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 32 hex chars of sha256 over the SOURCE URL — not over the source bytes.
|
|
55
|
+
*
|
|
56
|
+
* Hashing the URL is what makes the cache free: the storage key is computable without
|
|
57
|
+
* fetching anything, so a cache hit costs one existence probe and no download. It is sound
|
|
58
|
+
* because every cover/upload URL in both lanes is already timestamp-unique per upload, so
|
|
59
|
+
* new art always produces a new URL and therefore a new key.
|
|
60
|
+
*/
|
|
61
|
+
export function faviconContentHash(sourceUrl) {
|
|
62
|
+
return createHash('sha256').update(sourceUrl).digest('hex').slice(0, 32);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Where the web lane stores an icon derived from `sourceUrl`, relative to the storage
|
|
66
|
+
* prefix (`worlds/v3`). The CLI lane composes its own game-scoped key from
|
|
67
|
+
* `faviconContentHash` instead, because its bucket layout is per-game rather than shared.
|
|
68
|
+
*
|
|
69
|
+
* The `v1` segment and the `-64` suffix are load-bearing: changing the crop or the size
|
|
70
|
+
* must produce a NEW key rather than silently serving the old bytes from an immutable
|
|
71
|
+
* `max-age=31536000` object. Same reasoning as the hand-rolled `-v2` on the watermark logo.
|
|
72
|
+
*/
|
|
73
|
+
export function faviconStorageKey(sourceUrl) {
|
|
74
|
+
return `assets/favicons/v1/${faviconContentHash(sourceUrl)}-${FAVICON_PX}.png`;
|
|
75
|
+
}
|
|
76
|
+
/** The exact element every lane emits. One definition so the lanes cannot disagree. */
|
|
77
|
+
export function renderFaviconLink(href) {
|
|
78
|
+
return `<link id="${FAVICON_LINK_ID}" rel="icon" type="image/png" href="${escapeAttr(href)}">`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Point the document's icon at `href`.
|
|
82
|
+
*
|
|
83
|
+
* Replaces the element carrying `id="bm-favicon"`. When that marker is absent — an older
|
|
84
|
+
* cached bundle, or a CLI project that has not run `bitmagic upgrade` since the marker
|
|
85
|
+
* shipped — falls back to inserting before `</head>`, which is best-effort but never worse
|
|
86
|
+
* than the un-marked status quo.
|
|
87
|
+
*
|
|
88
|
+
* Returns `html` unchanged when `href` is missing or not an allowed scheme, and never
|
|
89
|
+
* throws: a tab icon must not be able to fail a publish.
|
|
90
|
+
*
|
|
91
|
+
* `indexOf` rather than a regex on purpose. The default href is a ~700-char base64 data URI
|
|
92
|
+
* sitting inside a bundle that reaches 20 MB, and the surrounding code (`injectIntoHtml`)
|
|
93
|
+
* is string-insertion for the same reason. Anchored `indexOf` scans are O(n) with tiny
|
|
94
|
+
* constants and have obvious failure semantics; a backtracking regex over that string does
|
|
95
|
+
* not.
|
|
96
|
+
*/
|
|
97
|
+
export function applyFaviconLink(html, href) {
|
|
98
|
+
if (!href || !isAllowedHref(href))
|
|
99
|
+
return html;
|
|
100
|
+
const link = renderFaviconLink(href);
|
|
101
|
+
const needle = `id="${FAVICON_LINK_ID}"`;
|
|
102
|
+
for (let at = html.indexOf(needle); at !== -1; at = html.indexOf(needle, at + needle.length)) {
|
|
103
|
+
const open = html.lastIndexOf('<', at);
|
|
104
|
+
const close = html.indexOf('>', at);
|
|
105
|
+
// A marker with no enclosing element is malformed input, not something to guess at.
|
|
106
|
+
if (open === -1 || close === -1)
|
|
107
|
+
continue;
|
|
108
|
+
// It has to be an actual <link> element. The id is also NAMED in prose — the explanatory
|
|
109
|
+
// comment above the default link in game/index.html, this doc block, docs — and matching the
|
|
110
|
+
// first occurrence anywhere replaced a comment instead of the link, which left the real
|
|
111
|
+
// default in place and shipped a page with two icon links. Verified the hard way.
|
|
112
|
+
if (!/^<link[\s/>]/i.test(html.slice(open, open + 6)))
|
|
113
|
+
continue;
|
|
114
|
+
if (isInsideComment(html, open))
|
|
115
|
+
continue;
|
|
116
|
+
return html.slice(0, open) + link + html.slice(close + 1);
|
|
117
|
+
}
|
|
118
|
+
const headClose = html.indexOf('</head>');
|
|
119
|
+
if (headClose === -1)
|
|
120
|
+
return html;
|
|
121
|
+
return html.slice(0, headClose) + link + '\n' + html.slice(headClose);
|
|
122
|
+
}
|
|
123
|
+
/** Is `at` inside an HTML comment? True when the nearest `<!--` behind it is not yet closed. */
|
|
124
|
+
function isInsideComment(html, at) {
|
|
125
|
+
const open = html.lastIndexOf('<!--', at);
|
|
126
|
+
if (open === -1)
|
|
127
|
+
return false;
|
|
128
|
+
return html.lastIndexOf('-->', at) < open;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=favicon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favicon.js","sourceRoot":"","sources":["../src/favicon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { AssetResultBase, GenerateDeps } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* A 3D prop mesh, from a prompt.
|
|
5
|
+
*
|
|
6
|
+
* The odd one out among the generators: it returns NO world.json patches. Every other generator
|
|
7
|
+
* produces a finished asset the host can write straight away, but a prop is only half made when
|
|
8
|
+
* the Asset Forger hands back a GLB — the engine still has to voxelize it, and voxelizing happens
|
|
9
|
+
* in a browser with the game loaded, which is the caller's side of the seam in both lanes. So this
|
|
10
|
+
* returns the GLB URL and stops, and the host decides what to do with it.
|
|
11
|
+
*
|
|
12
|
+
* That is what makes the same code serve the CLI's `bitmagic generate prop` (voxelize in a
|
|
13
|
+
* headless Chrome, upsert the asset locally) and, in principle, the web lane's HQ job — which
|
|
14
|
+
* today reimplements this call inline in `hq-asset-jobs.ts`.
|
|
15
|
+
*
|
|
16
|
+
* The generation is billable the moment the Forger accepts the job: the vendor charges on
|
|
17
|
+
* acceptance, so a downstream failure to produce a URL still costs.
|
|
18
|
+
*/
|
|
19
|
+
export declare const propParamsSchema: z.ZodObject<{
|
|
20
|
+
prompt: z.ZodString;
|
|
21
|
+
/**
|
|
22
|
+
* `prop` matches what the HQ path has always sent. Named rather than hardcoded because the
|
|
23
|
+
* Forger distinguishes props from characters, and a mis-typed model produces a rigged humanoid
|
|
24
|
+
* where a rock was wanted.
|
|
25
|
+
*/
|
|
26
|
+
modelType: z.ZodDefault<z.ZodOptional<z.ZodEnum<["prop"]>>>;
|
|
27
|
+
}, "strict", z.ZodTypeAny, {
|
|
28
|
+
prompt: string;
|
|
29
|
+
modelType: "prop";
|
|
30
|
+
}, {
|
|
31
|
+
prompt: string;
|
|
32
|
+
modelType?: "prop" | undefined;
|
|
33
|
+
}>;
|
|
34
|
+
export type PropParams = z.input<typeof propParamsSchema>;
|
|
35
|
+
export type PropResult = AssetResultBase & {
|
|
36
|
+
/** Where the generated mesh landed. The host voxelizes this. */
|
|
37
|
+
glbUrl?: string;
|
|
38
|
+
billable?: boolean;
|
|
39
|
+
};
|
|
40
|
+
export declare function generateProp(params: PropParams, deps: GenerateDeps & {
|
|
41
|
+
imageToMeshModel?: string;
|
|
42
|
+
}): Promise<PropResult>;
|
|
43
|
+
//# sourceMappingURL=prop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prop.d.ts","sourceRoot":"","sources":["../../src/generators/prop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIjE;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,gBAAgB;;IAI3B;;;;OAIG;;;;;;;;EAEM,CAAC;AAEZ,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG;IACzC,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAcF,wBAAsB,YAAY,CAChC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,YAAY,GAAG;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD,OAAO,CAAC,UAAU,CAAC,CAsDrB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { fail, ok } from '../result.js';
|
|
3
|
+
import { formatZodIssues } from '../validation.js';
|
|
4
|
+
/**
|
|
5
|
+
* A 3D prop mesh, from a prompt.
|
|
6
|
+
*
|
|
7
|
+
* The odd one out among the generators: it returns NO world.json patches. Every other generator
|
|
8
|
+
* produces a finished asset the host can write straight away, but a prop is only half made when
|
|
9
|
+
* the Asset Forger hands back a GLB — the engine still has to voxelize it, and voxelizing happens
|
|
10
|
+
* in a browser with the game loaded, which is the caller's side of the seam in both lanes. So this
|
|
11
|
+
* returns the GLB URL and stops, and the host decides what to do with it.
|
|
12
|
+
*
|
|
13
|
+
* That is what makes the same code serve the CLI's `bitmagic generate prop` (voxelize in a
|
|
14
|
+
* headless Chrome, upsert the asset locally) and, in principle, the web lane's HQ job — which
|
|
15
|
+
* today reimplements this call inline in `hq-asset-jobs.ts`.
|
|
16
|
+
*
|
|
17
|
+
* The generation is billable the moment the Forger accepts the job: the vendor charges on
|
|
18
|
+
* acceptance, so a downstream failure to produce a URL still costs.
|
|
19
|
+
*/
|
|
20
|
+
export const propParamsSchema = z.object({
|
|
21
|
+
prompt: z.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.describe('What the object should be (e.g. "a weathered stone archway covered in moss")'),
|
|
24
|
+
/**
|
|
25
|
+
* `prop` matches what the HQ path has always sent. Named rather than hardcoded because the
|
|
26
|
+
* Forger distinguishes props from characters, and a mis-typed model produces a rigged humanoid
|
|
27
|
+
* where a rock was wanted.
|
|
28
|
+
*/
|
|
29
|
+
modelType: z.enum(['prop']).optional().default('prop'),
|
|
30
|
+
}).strict();
|
|
31
|
+
const ENDPOINT = '/ai/v1/forge3d/jobs';
|
|
32
|
+
/**
|
|
33
|
+
* Kept in step with `hq-asset-jobs.ts`, which is the proven configuration for this endpoint.
|
|
34
|
+
* `rigging: 'false'` is a STRING because that is what the Forger's API accepts.
|
|
35
|
+
*/
|
|
36
|
+
const DEFAULT_IMAGE_TO_MESH_MODEL = 'unified-trellis';
|
|
37
|
+
export async function generateProp(params, deps) {
|
|
38
|
+
const { forger, logger, onProgress } = deps;
|
|
39
|
+
const parsed = propParamsSchema.safeParse(params);
|
|
40
|
+
if (!parsed.success) {
|
|
41
|
+
logger.warn({ err: parsed.error }, '[prop] Invalid parameters');
|
|
42
|
+
return fail(formatZodIssues(parsed.error));
|
|
43
|
+
}
|
|
44
|
+
const input = parsed.data;
|
|
45
|
+
if (!forger.hasCredentials()) {
|
|
46
|
+
logger.error('[prop] Missing Asset Forger credentials');
|
|
47
|
+
return fail(forger.getMissingCredentialsMessage());
|
|
48
|
+
}
|
|
49
|
+
onProgress(`Generating a mesh for: ${input.prompt}`);
|
|
50
|
+
logger.info(`[prop] Starting forge3d for "${input.prompt}"`);
|
|
51
|
+
let response;
|
|
52
|
+
try {
|
|
53
|
+
response = await forger.postJobAndWait(ENDPOINT, {
|
|
54
|
+
model: 'lab',
|
|
55
|
+
prompt: input.prompt,
|
|
56
|
+
parameters: {
|
|
57
|
+
imageToMeshModel: deps.imageToMeshModel ?? DEFAULT_IMAGE_TO_MESH_MODEL,
|
|
58
|
+
modelType: input.modelType,
|
|
59
|
+
rigging: 'false',
|
|
60
|
+
},
|
|
61
|
+
}, 'prop');
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const message = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
65
|
+
logger.error({ err: error }, '[prop] Error during generation');
|
|
66
|
+
return fail(message);
|
|
67
|
+
}
|
|
68
|
+
const glbUrl = response.data?.fileUrl;
|
|
69
|
+
if (!glbUrl) {
|
|
70
|
+
// Billable: the Forger accepted and ran the job, and was paid for it, whatever it answered.
|
|
71
|
+
return { ...fail('Asset Forger returned no file URL for the generated mesh'), billable: true };
|
|
72
|
+
}
|
|
73
|
+
logger.info(`[prop] Generated ${glbUrl}`);
|
|
74
|
+
return ok(`Mesh generated: ${glbUrl}`,
|
|
75
|
+
// Deliberately empty — see the file header. The asset does not exist until the host has
|
|
76
|
+
// voxelized this, and writing a half-made entry would leave world.json describing an asset the
|
|
77
|
+
// engine cannot load.
|
|
78
|
+
[], { glbUrl, billable: true });
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=prop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prop.js","sourceRoot":"","sources":["../../src/generators/prop.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,9 +11,12 @@ export { generateImageAsset, imageAssetParamsSchema } from './generators/image.j
|
|
|
11
11
|
export type { ImageAssetParams, ImageAssetResult } from './generators/image.js';
|
|
12
12
|
export { generateCharacter, characterParamsSchema } from './generators/character.js';
|
|
13
13
|
export type { CharacterParams, CharacterResult } from './generators/character.js';
|
|
14
|
+
export { generateProp, propParamsSchema } from './generators/prop.js';
|
|
15
|
+
export type { PropParams, PropResult } from './generators/prop.js';
|
|
14
16
|
export { generateAnimationAsset, animationParamsSchema, getConfiguredAnimationModel, ANIMATION_MODEL_TEXT_TO_MOTION_3, ANIMATION_MODEL_TEXT_TO_MOTION_2, ANIMATION_MODEL_OLDER, } from './generators/animation.js';
|
|
15
17
|
export type { AnimationParams, AnimationResult } from './generators/animation.js';
|
|
16
18
|
export { fetchContentLength } from './http.js';
|
|
19
|
+
export { PIXAR_VOXEL_STYLE, MAX_COVER_DESIGN_CHARS, buildCoverArtPrompt } from './cover-prompt.js';
|
|
17
20
|
export { TERMINAL_FAILURE_CODES, TERMINAL_FAILURE_VERSION, buildTerminalFailure, isTerminalFailureCode, legacyErrorTypeFor, parseTerminalFailure, } from './terminal-failure.js';
|
|
18
21
|
export type { BuildTerminalFailureInput, LegacyErrorType, TerminalFailure, TerminalFailureCode, TerminalFailureDetail, } from './terminal-failure.js';
|
|
19
22
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,UAAU,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5F,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACnF,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACrF,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,gCAAgC,EAChC,gCAAgC,EAChC,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,UAAU,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5F,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACnF,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACrF,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,gCAAgC,EAChC,gCAAgC,EAChC,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAMnG,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,yBAAyB,EACzB,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,10 @@ export { generateSkybox, skyboxParamsSchema } from './generators/skybox.js';
|
|
|
5
5
|
export { generateSoundEffect, soundEffectParamsSchema } from './generators/sound-effect.js';
|
|
6
6
|
export { generateImageAsset, imageAssetParamsSchema } from './generators/image.js';
|
|
7
7
|
export { generateCharacter, characterParamsSchema } from './generators/character.js';
|
|
8
|
+
export { generateProp, propParamsSchema } from './generators/prop.js';
|
|
8
9
|
export { generateAnimationAsset, animationParamsSchema, getConfiguredAnimationModel, ANIMATION_MODEL_TEXT_TO_MOTION_3, ANIMATION_MODEL_TEXT_TO_MOTION_2, ANIMATION_MODEL_OLDER, } from './generators/animation.js';
|
|
9
10
|
export { fetchContentLength } from './http.js';
|
|
11
|
+
export { PIXAR_VOXEL_STYLE, MAX_COVER_DESIGN_CHARS, buildCoverArtPrompt } from './cover-prompt.js';
|
|
10
12
|
// The agent↔client terminal-failure contract. Also published as the
|
|
11
13
|
// `@bitmagic/asset-core/terminal-failure` subpath: this barrel eagerly pulls in
|
|
12
14
|
// the generators (and therefore zod, the forger client, and node http helpers),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5E,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAE5F,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEnF,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAErF,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,gCAAgC,EAChC,gCAAgC,EAChC,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5E,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAE5F,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEnF,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAErF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEtE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,gCAAgC,EAChC,gCAAgC,EAChC,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEnG,oEAAoE;AACpE,gFAAgF;AAChF,gFAAgF;AAChF,oEAAoE;AACpE,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitmagic/asset-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -12,6 +12,17 @@
|
|
|
12
12
|
"./terminal-failure": {
|
|
13
13
|
"types": "./dist/terminal-failure.d.ts",
|
|
14
14
|
"default": "./dist/terminal-failure.js"
|
|
15
|
+
},
|
|
16
|
+
"./favicon": {
|
|
17
|
+
"types": "./dist/favicon.d.ts",
|
|
18
|
+
"default": "./dist/favicon.js"
|
|
19
|
+
},
|
|
20
|
+
"./animation/*": {
|
|
21
|
+
"default": "./src/animation/*"
|
|
22
|
+
},
|
|
23
|
+
"./animation/authored.mjs": {
|
|
24
|
+
"types": "./src/animation/authored.d.mts",
|
|
25
|
+
"default": "./src/animation/authored.mjs"
|
|
15
26
|
}
|
|
16
27
|
},
|
|
17
28
|
"files": [
|
|
@@ -21,7 +32,8 @@
|
|
|
21
32
|
"access": "public"
|
|
22
33
|
},
|
|
23
34
|
"dependencies": {
|
|
24
|
-
"zod": "^3.25.76"
|
|
35
|
+
"zod": "^3.25.76",
|
|
36
|
+
"three": "^0.185.1"
|
|
25
37
|
},
|
|
26
38
|
"devDependencies": {
|
|
27
39
|
"@eslint/js": "^9.38.0",
|
|
@@ -65,7 +77,7 @@
|
|
|
65
77
|
"scripts": {
|
|
66
78
|
"build": "tsc",
|
|
67
79
|
"check": "pnpm run lint && pnpm run build",
|
|
68
|
-
"lint": "eslint src",
|
|
80
|
+
"lint": "eslint src --cache",
|
|
69
81
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest"
|
|
70
82
|
}
|
|
71
83
|
}
|