@bitmagic/cli 0.1.47 → 0.1.48
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 +4 -0
- package/dist/config/environments.js +5 -4
- package/dist/config/environments.js.map +1 -1
- package/dist/editor/boot-loader.d.ts +40 -0
- package/dist/editor/boot-loader.js +166 -0
- package/dist/editor/boot-loader.js.map +1 -0
- package/dist/editor/shell-page.js +84 -6
- package/dist/editor/shell-page.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -314,6 +314,10 @@ The reason it opens rather than only printing: agents are told to start `bitmagi
|
|
|
314
314
|
background task, which means everything it prints — including the URL — lands in a log the creator
|
|
315
315
|
never reads. A dev server nobody opened is worth exactly as much as one nobody started.
|
|
316
316
|
|
|
317
|
+
While the game boots, the mark hops over the stage — the first time only. Later reloads hold it
|
|
318
|
+
still, and only if the reload is slow enough to be worth explaining. If a boot fails it stays put,
|
|
319
|
+
says what went wrong and offers to try again, instead of leaving you a black rectangle.
|
|
320
|
+
|
|
317
321
|
Put the page beside your agent's window. It is one page with
|
|
318
322
|
two tabs over the same running game, so switching costs nothing and does not restart anything:
|
|
319
323
|
|
|
@@ -8,6 +8,10 @@ const DEV_AUTH0_AUDIENCE = 'https://api.bitmagic.cloud';
|
|
|
8
8
|
// Verified end to end against the staging tenant: the device-flow access token carries the
|
|
9
9
|
// https://bitmagic.ai/roles claim, so the api-server Admin gate accepts it.
|
|
10
10
|
const DEV_AUTH0_CLIENT_ID = 'wEp5Jsw43MyExDT1DfMCFyQSi8II0mSu';
|
|
11
|
+
// The same application in the production tenant (bitmagic-v3), public for the same reason.
|
|
12
|
+
// Its two non-default settings are the ones whose absence fails obscurely: Grant Types →
|
|
13
|
+
// Device Code on the application, and Allow Offline Access on the https://api.bitmagic.ai API.
|
|
14
|
+
const PROD_AUTH0_CLIENT_ID = 'KT5oOSeyzN0fhckhGo5CWrUOqnam31mo';
|
|
11
15
|
export const ENVIRONMENTS = {
|
|
12
16
|
dev: {
|
|
13
17
|
name: 'dev',
|
|
@@ -21,10 +25,7 @@ export const ENVIRONMENTS = {
|
|
|
21
25
|
apiUrl: 'https://bitmagic.ai',
|
|
22
26
|
auth0Domain: 'bitmagic-v3.us.auth0.com',
|
|
23
27
|
auth0Audience: 'https://api.bitmagic.ai',
|
|
24
|
-
|
|
25
|
-
// before any network call, naming BITMAGIC_AUTH0_CLIENT_ID. Prod delivery of the pro lane
|
|
26
|
-
// is deferred anyway: prod has no engine bucket and no manifest.
|
|
27
|
-
auth0ClientId: '',
|
|
28
|
+
auth0ClientId: PROD_AUTH0_CLIENT_ID,
|
|
28
29
|
},
|
|
29
30
|
// There is no local Auth0. Pointing local at the dev tenant is deliberate: minting a fake
|
|
30
31
|
// local identity would reintroduce the localhost-bypass hazard the CLI auth design rejected.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environments.js","sourceRoot":"","sources":["../../src/config/environments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAa1D,MAAM,gBAAgB,GAAG,kCAAkC,CAAC;AAC5D,MAAM,kBAAkB,GAAG,4BAA4B,CAAC;AAExD,8FAA8F;AAC9F,8FAA8F;AAC9F,2FAA2F;AAC3F,4EAA4E;AAC5E,MAAM,mBAAmB,GAAG,kCAAkC,CAAC;AAE/D,MAAM,CAAC,MAAM,YAAY,GAAyC;IAChE,GAAG,EAAE;QACH,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,oCAAoC;QAC5C,WAAW,EAAE,gBAAgB;QAC7B,aAAa,EAAE,kBAAkB;QACjC,aAAa,EAAE,mBAAmB;KACnC;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,qBAAqB;QAC7B,WAAW,EAAE,0BAA0B;QACvC,aAAa,EAAE,yBAAyB;QACxC,
|
|
1
|
+
{"version":3,"file":"environments.js","sourceRoot":"","sources":["../../src/config/environments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The boot loader's CSS and markup, composed into `shell-page.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Split out for the same reason `asset-detail-panel.ts` is: that file is the busiest in the
|
|
5
|
+
* package, and a stylesheet plus a static SVG carry no closure state, so they can leave without
|
|
6
|
+
* threading anything across a boundary. The loader's *behaviour* stays inline there, because
|
|
7
|
+
* showing and hiding it needs `generation`, `setStatus` and `start` from the enclosing IIFE.
|
|
8
|
+
*
|
|
9
|
+
* ── Why the brandmark is coloured from the stylesheet ────────────────────────────────────────
|
|
10
|
+
*
|
|
11
|
+
* `__tests__/shell-page.test.ts` reads the <style> block to catch a colour that left the palette,
|
|
12
|
+
* which means a `fill="#fff"` on a path would be exactly the kind of literal it exists to catch and
|
|
13
|
+
* exactly the kind it cannot see. So every node here carries a class and no paint attribute: the
|
|
14
|
+
* body is `currentColor` off the svg's own `color`, and the wand is a token. It also makes the
|
|
15
|
+
* failed state one CSS rule rather than a JS attribute write.
|
|
16
|
+
*
|
|
17
|
+
* ── The one thing that must not be renamed back ──────────────────────────────────────────────
|
|
18
|
+
*
|
|
19
|
+
* The artwork this is ported from names its classes `.spin` / `.hop` and its keyframes `spin` /
|
|
20
|
+
* `hop`. `shell-page.ts` ALREADY has `.spin` and `@keyframes spin`, live on the forge step glyphs
|
|
21
|
+
* and the job thumbnails. A duplicate `@keyframes` does not error — the later one silently wins —
|
|
22
|
+
* so a verbatim port would leave every spinner in the assets panel doing a 1.9s double backflip.
|
|
23
|
+
* Hence `bm-bird-` on the classes and `bird-` on the keyframes. There is a test.
|
|
24
|
+
*
|
|
25
|
+
* Same template-literal rules as its host: **no backticks**, anywhere.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Styles for `#boot`, appended to the shell's stylesheet.
|
|
29
|
+
*
|
|
30
|
+
* The 1.9s cycle and every keyframe stop below are the artwork's, unchanged. What is Bitmagic's
|
|
31
|
+
* rather than the artwork's: the surface it stands on, the wand's colour, and the still variant.
|
|
32
|
+
*/
|
|
33
|
+
export declare const BOOT_LOADER_CSS = "\n /* Over the GAME, not over the page: the bar and the assets panel stay live while a boot is in\n flight, because a forge ticking in the panel is exactly what a creator watches during one.\n z-index 5 keeps it under #hq-overlay (10) and #asset-overlay (11) \u2014 both are fixed, in the root\n stacking context \u2014 so a preview opened from a row mid-boot is not trapped behind it. */\n #boot { position: absolute; inset: 0; z-index: 5; overflow: hidden;\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n background: radial-gradient(120% 120% at 50% 42%, var(--bm-surface), var(--bm-bg));\n opacity: 0; visibility: hidden;\n transition: opacity .2s ease, visibility 0s linear .2s; }\n #boot.show { opacity: 1; visibility: visible; transition: opacity .2s ease; }\n\n /* The mark's stage, at the proportions it was drawn at. Nothing here clips: the hop's apex rises\n about 47px above this box on purpose, which is what #boot's overflow is for. */\n #boot-stage { position: relative; width: 220px; height: 320px; }\n @media (max-height: 560px) { #boot-stage { transform: scale(.72); } }\n\n /* The ground shadow carries the weight of the hop \u2014 without it the mark reads as sliding rather\n than landing. The lifted centre of the gradient above is the only reason a black ellipse is\n visible at all on a near-black surface. */\n .bm-bird-shadow { position: absolute; bottom: 44px; left: 50%; width: 120px; height: 26px;\n margin-left: -60px; border-radius: 50%; background: #000000; opacity: .55;\n filter: blur(4px);\n animation: bird-shadow 1.9s cubic-bezier(.5,0,.5,1) infinite; }\n\n /* Vertical arc and squash, origin at the feet. */\n .bm-bird-hop { position: absolute; bottom: 60px; left: 50%; width: 150px; height: 150px;\n margin-left: -75px; transform-origin: 50% 100%;\n animation: bird-hop 1.9s infinite; }\n /* The two backflips, around the mark's own centre. Named apart from the shell's .spin \u2014 see the\n header. */\n .bm-bird-flip { width: 100%; height: 100%; transform-origin: 50% 50%;\n animation: bird-flip 1.9s infinite; }\n\n .bm-bird-svg { display: block; width: 100%; height: 100%; overflow: visible;\n color: var(--bm-text); }\n .bm-bird-svg .body { fill: currentColor; }\n .bm-bird-svg .detail { fill: #000000; }\n .bm-bird-svg .iris { fill: none; stroke: currentColor; }\n .bm-bird-svg .iris-edge { fill: none; stroke: #000000; }\n /* The wand is the only colour on the mark, and it is Aquamarine: DESIGN.md spends that accent on\n creation. The artwork draws it in a pink that on this surface already means discard or failed,\n so it is retuned rather than copied. */\n .bm-bird-svg .wand { fill: none; stroke: var(--bm-aqua); }\n\n /* Content voice: sentence case, muted, one line. The negative margin reclaims the empty air the\n stage reserves under the shadow, so the mark and its line read as one block. */\n #boot-message { margin: -56px 0 0; max-width: 420px; text-align: center; font-size: 13px;\n color: var(--bm-text-muted); }\n #boot-retry { display: none; margin-top: 16px; }\n\n /* Still, dim, no ground pulse. What every boot after the first gets: the animation is a first\n impression, not a progress bar, and an agent reloading forty times an hour should not be shown\n forty backflips. The shadow stays drawn \u2014 a mark with no ground under it reads as a layout\n mistake rather than as a rest pose. */\n Held at .55 rather than lower: further down the white mark stops reading as the brandmark and\n starts reading as a disabled control, which is the one thing a loading state must not look\n like. */\n #boot.quiet #boot-stage { opacity: .55; }\n #boot.quiet .bm-bird-hop, #boot.quiet .bm-bird-flip,\n #boot.quiet .bm-bird-shadow { animation: none; }\n\n /* A boot that ended badly keeps the stage rather than handing back a blank iframe. The 8px dot in\n the bar is easy to miss, and both failures here name a command the creator should run next.\n failBoot() sets .quiet too, so the mark is already still and at the same weight \u2014 the message\n and the pill are what make this state different, which is as much difference as it needs. */\n #boot.failed #boot-message { color: var(--bm-pink-hover); }\n #boot.failed #boot-retry { display: inline-block; }\n /* No magic trick on a failure: the wand goes out, so the only accent left is the one the message\n is written in. DESIGN.md does not stack two accents in one component. */\n #boot.failed .bm-bird-svg .wand { stroke: var(--bm-text-dim); }\n\n /* Full brightness, no motion: dimming means \"this is a repeat boot\", not \"you asked for less\n movement\". */\n @media (prefers-reduced-motion: reduce) {\n .bm-bird-hop, .bm-bird-flip, .bm-bird-shadow { animation: none; }\n #boot { transition: none; }\n }\n\n @keyframes bird-hop {\n 0%,6% { transform: translateY(0) scale(1,1); animation-timing-function: cubic-bezier(.35,0,.35,1); }\n 14% { transform: translateY(10%) scale(1.16,.80); animation-timing-function: cubic-bezier(.2,.9,.35,1); }\n 22% { transform: translateY(-14%) scale(.82,1.22); animation-timing-function: cubic-bezier(.12,.62,.35,1); }\n 50% { transform: translateY(-105%) scale(1,1); animation-timing-function: cubic-bezier(.6,0,.85,.35); }\n 80% { transform: translateY(-4%) scale(.9,1.12); animation-timing-function: cubic-bezier(.3,.5,.5,1); }\n 88% { transform: translateY(8%) scale(1.24,.72); animation-timing-function: cubic-bezier(.2,.2,.3,1); }\n 94% { transform: translateY(-3%) scale(.93,1.08); animation-timing-function: cubic-bezier(.3,0,.4,1); }\n 100% { transform: translateY(0) scale(1,1); }\n }\n @keyframes bird-flip {\n 0%,20% { transform: rotate(0deg); animation-timing-function: cubic-bezier(.3,.1,.3,1); }\n 84%,100% { transform: rotate(-720deg); }\n }\n @keyframes bird-shadow {\n 0%,6% { transform: scale(1); opacity: .55; }\n 50% { transform: scale(.5); opacity: .25; }\n 88% { transform: scale(1.18); opacity: .6; }\n 100% { transform: scale(1); opacity: .55; }\n }\n";
|
|
34
|
+
/**
|
|
35
|
+
* The overlay, placed inside `#viewport` so it covers the game and nothing else.
|
|
36
|
+
*
|
|
37
|
+
* The path data is the brandmark, verbatim from the artwork; only the paint attributes are gone,
|
|
38
|
+
* replaced by the classes the stylesheet above paints.
|
|
39
|
+
*/
|
|
40
|
+
export declare const BOOT_LOADER_HTML = "\n <div id=\"boot\" aria-live=\"polite\">\n <div id=\"boot-stage\">\n <div class=\"bm-bird-shadow\"></div>\n <div class=\"bm-bird-hop\">\n <div class=\"bm-bird-flip\">\n <svg class=\"bm-bird-svg\" viewBox=\"0 0 325.98 286.58\" role=\"img\" aria-label=\"Bitmagic\">\n <path class=\"body\" d=\"M189.35,43.3c-18.08,0-38.95,7.71-48.75,24.5-12.41,21.25.75,39.51-14.27,56.28-14.67,16.37-35.49,6.27-49.25,23.66-9.53,12.06-9.42,29.43-6.22,40.71,11.9,41.87,80.72,50.03,88.1,50.82,4.41.47,12.56,1.33,22.54,1.33,22.34,0,53.82-4.33,72.88-27.11,41.89-50.08-1.78-158.91-54.06-169.17-3.44-.68-7.14-1.02-10.96-1.02\"/>\n <path class=\"body\" d=\"M84.96,155.05s-35.24-11.29-29.46-25.64c5.78-14.35,28.91,21.38,28.91,21.38\"/>\n <path class=\"body\" d=\"M82.66,157.28s-24.58-32.65-10.23-41.72c14.35-9.07,12.44,37.58,12.44,37.58\"/>\n <path class=\"detail\" d=\"M135.5,135.43c-4.56,6.82-5.76,7.24-13.55,4.67,6.82,4.56,7.24,5.76,4.67,13.55,4.56-6.82,5.76-7.24,13.55-4.67-6.82-4.56-7.24-5.76-4.67-13.55Z\"/>\n <path class=\"detail\" d=\"M160.11,84.01c-4.56,6.82-5.76,7.24-13.55,4.67,6.82,4.56,7.24,5.76,4.67,13.55,4.56-6.82,5.76-7.24,13.55-4.67-6.82-4.56-7.24-5.76-4.67-13.55Z\"/>\n <path class=\"detail\" d=\"M159.7,167.94c-2.6,3.89-3.28,4.12-7.72,2.66,3.89,2.6,4.12,3.28,2.66,7.72,2.6-3.89,3.28-4.12,7.72-2.66-3.89-2.6-4.12-3.28-2.66-7.72Z\"/>\n <path class=\"detail\" d=\"M189.27,58.59c-2.6,3.89-3.28,4.12-7.72,2.66,3.89,2.6,4.12,3.28,2.66,7.72,2.6-3.89,3.28-4.12,7.72-2.66-3.89-2.6-4.12-3.28-2.66-7.72Z\"/>\n <path class=\"detail\" d=\"M162.41,113.42c-4.26,6.37-5.38,6.76-12.66,4.36,6.37,4.26,6.76,5.38,4.36,12.66,4.26-6.37,5.38-6.76,12.66-4.36-6.37-4.26-6.76-5.38-4.36-12.66Z\"/>\n <circle class=\"detail\" cx=\"206.9\" cy=\"115.82\" r=\"23.31\" transform=\"translate(-10.12 20.3) rotate(-5.48)\"/>\n <circle class=\"iris\" stroke-width=\"12.08\" stroke-miterlimit=\"10\" cx=\"206.9\" cy=\"115.82\" r=\"23.31\" transform=\"translate(-10.12 20.3) rotate(-5.48)\"/>\n <circle class=\"iris-edge\" stroke-width=\"2.99\" stroke-miterlimit=\"10\" cx=\"206.89\" cy=\"115.73\" r=\"28.36\" transform=\"translate(-25.72 161.42) rotate(-40.34)\"/>\n <line class=\"wand\" stroke-linecap=\"round\" stroke-width=\"15.33\" stroke-miterlimit=\"10\" x1=\"238.54\" y1=\"82.17\" x2=\"264.66\" y2=\"53.95\"/>\n </svg>\n </div>\n </div>\n </div>\n <p id=\"boot-message\">Bringing your world to life…</p>\n <button id=\"boot-retry\" class=\"bm-pill bm-pill--ghost\" type=\"button\">Try again</button>\n </div>\n";
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The boot loader's CSS and markup, composed into `shell-page.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Split out for the same reason `asset-detail-panel.ts` is: that file is the busiest in the
|
|
5
|
+
* package, and a stylesheet plus a static SVG carry no closure state, so they can leave without
|
|
6
|
+
* threading anything across a boundary. The loader's *behaviour* stays inline there, because
|
|
7
|
+
* showing and hiding it needs `generation`, `setStatus` and `start` from the enclosing IIFE.
|
|
8
|
+
*
|
|
9
|
+
* ── Why the brandmark is coloured from the stylesheet ────────────────────────────────────────
|
|
10
|
+
*
|
|
11
|
+
* `__tests__/shell-page.test.ts` reads the <style> block to catch a colour that left the palette,
|
|
12
|
+
* which means a `fill="#fff"` on a path would be exactly the kind of literal it exists to catch and
|
|
13
|
+
* exactly the kind it cannot see. So every node here carries a class and no paint attribute: the
|
|
14
|
+
* body is `currentColor` off the svg's own `color`, and the wand is a token. It also makes the
|
|
15
|
+
* failed state one CSS rule rather than a JS attribute write.
|
|
16
|
+
*
|
|
17
|
+
* ── The one thing that must not be renamed back ──────────────────────────────────────────────
|
|
18
|
+
*
|
|
19
|
+
* The artwork this is ported from names its classes `.spin` / `.hop` and its keyframes `spin` /
|
|
20
|
+
* `hop`. `shell-page.ts` ALREADY has `.spin` and `@keyframes spin`, live on the forge step glyphs
|
|
21
|
+
* and the job thumbnails. A duplicate `@keyframes` does not error — the later one silently wins —
|
|
22
|
+
* so a verbatim port would leave every spinner in the assets panel doing a 1.9s double backflip.
|
|
23
|
+
* Hence `bm-bird-` on the classes and `bird-` on the keyframes. There is a test.
|
|
24
|
+
*
|
|
25
|
+
* Same template-literal rules as its host: **no backticks**, anywhere.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Styles for `#boot`, appended to the shell's stylesheet.
|
|
29
|
+
*
|
|
30
|
+
* The 1.9s cycle and every keyframe stop below are the artwork's, unchanged. What is Bitmagic's
|
|
31
|
+
* rather than the artwork's: the surface it stands on, the wand's colour, and the still variant.
|
|
32
|
+
*/
|
|
33
|
+
export const BOOT_LOADER_CSS = `
|
|
34
|
+
/* Over the GAME, not over the page: the bar and the assets panel stay live while a boot is in
|
|
35
|
+
flight, because a forge ticking in the panel is exactly what a creator watches during one.
|
|
36
|
+
z-index 5 keeps it under #hq-overlay (10) and #asset-overlay (11) — both are fixed, in the root
|
|
37
|
+
stacking context — so a preview opened from a row mid-boot is not trapped behind it. */
|
|
38
|
+
#boot { position: absolute; inset: 0; z-index: 5; overflow: hidden;
|
|
39
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
40
|
+
background: radial-gradient(120% 120% at 50% 42%, var(--bm-surface), var(--bm-bg));
|
|
41
|
+
opacity: 0; visibility: hidden;
|
|
42
|
+
transition: opacity .2s ease, visibility 0s linear .2s; }
|
|
43
|
+
#boot.show { opacity: 1; visibility: visible; transition: opacity .2s ease; }
|
|
44
|
+
|
|
45
|
+
/* The mark's stage, at the proportions it was drawn at. Nothing here clips: the hop's apex rises
|
|
46
|
+
about 47px above this box on purpose, which is what #boot's overflow is for. */
|
|
47
|
+
#boot-stage { position: relative; width: 220px; height: 320px; }
|
|
48
|
+
@media (max-height: 560px) { #boot-stage { transform: scale(.72); } }
|
|
49
|
+
|
|
50
|
+
/* The ground shadow carries the weight of the hop — without it the mark reads as sliding rather
|
|
51
|
+
than landing. The lifted centre of the gradient above is the only reason a black ellipse is
|
|
52
|
+
visible at all on a near-black surface. */
|
|
53
|
+
.bm-bird-shadow { position: absolute; bottom: 44px; left: 50%; width: 120px; height: 26px;
|
|
54
|
+
margin-left: -60px; border-radius: 50%; background: #000000; opacity: .55;
|
|
55
|
+
filter: blur(4px);
|
|
56
|
+
animation: bird-shadow 1.9s cubic-bezier(.5,0,.5,1) infinite; }
|
|
57
|
+
|
|
58
|
+
/* Vertical arc and squash, origin at the feet. */
|
|
59
|
+
.bm-bird-hop { position: absolute; bottom: 60px; left: 50%; width: 150px; height: 150px;
|
|
60
|
+
margin-left: -75px; transform-origin: 50% 100%;
|
|
61
|
+
animation: bird-hop 1.9s infinite; }
|
|
62
|
+
/* The two backflips, around the mark's own centre. Named apart from the shell's .spin — see the
|
|
63
|
+
header. */
|
|
64
|
+
.bm-bird-flip { width: 100%; height: 100%; transform-origin: 50% 50%;
|
|
65
|
+
animation: bird-flip 1.9s infinite; }
|
|
66
|
+
|
|
67
|
+
.bm-bird-svg { display: block; width: 100%; height: 100%; overflow: visible;
|
|
68
|
+
color: var(--bm-text); }
|
|
69
|
+
.bm-bird-svg .body { fill: currentColor; }
|
|
70
|
+
.bm-bird-svg .detail { fill: #000000; }
|
|
71
|
+
.bm-bird-svg .iris { fill: none; stroke: currentColor; }
|
|
72
|
+
.bm-bird-svg .iris-edge { fill: none; stroke: #000000; }
|
|
73
|
+
/* The wand is the only colour on the mark, and it is Aquamarine: DESIGN.md spends that accent on
|
|
74
|
+
creation. The artwork draws it in a pink that on this surface already means discard or failed,
|
|
75
|
+
so it is retuned rather than copied. */
|
|
76
|
+
.bm-bird-svg .wand { fill: none; stroke: var(--bm-aqua); }
|
|
77
|
+
|
|
78
|
+
/* Content voice: sentence case, muted, one line. The negative margin reclaims the empty air the
|
|
79
|
+
stage reserves under the shadow, so the mark and its line read as one block. */
|
|
80
|
+
#boot-message { margin: -56px 0 0; max-width: 420px; text-align: center; font-size: 13px;
|
|
81
|
+
color: var(--bm-text-muted); }
|
|
82
|
+
#boot-retry { display: none; margin-top: 16px; }
|
|
83
|
+
|
|
84
|
+
/* Still, dim, no ground pulse. What every boot after the first gets: the animation is a first
|
|
85
|
+
impression, not a progress bar, and an agent reloading forty times an hour should not be shown
|
|
86
|
+
forty backflips. The shadow stays drawn — a mark with no ground under it reads as a layout
|
|
87
|
+
mistake rather than as a rest pose. */
|
|
88
|
+
Held at .55 rather than lower: further down the white mark stops reading as the brandmark and
|
|
89
|
+
starts reading as a disabled control, which is the one thing a loading state must not look
|
|
90
|
+
like. */
|
|
91
|
+
#boot.quiet #boot-stage { opacity: .55; }
|
|
92
|
+
#boot.quiet .bm-bird-hop, #boot.quiet .bm-bird-flip,
|
|
93
|
+
#boot.quiet .bm-bird-shadow { animation: none; }
|
|
94
|
+
|
|
95
|
+
/* A boot that ended badly keeps the stage rather than handing back a blank iframe. The 8px dot in
|
|
96
|
+
the bar is easy to miss, and both failures here name a command the creator should run next.
|
|
97
|
+
failBoot() sets .quiet too, so the mark is already still and at the same weight — the message
|
|
98
|
+
and the pill are what make this state different, which is as much difference as it needs. */
|
|
99
|
+
#boot.failed #boot-message { color: var(--bm-pink-hover); }
|
|
100
|
+
#boot.failed #boot-retry { display: inline-block; }
|
|
101
|
+
/* No magic trick on a failure: the wand goes out, so the only accent left is the one the message
|
|
102
|
+
is written in. DESIGN.md does not stack two accents in one component. */
|
|
103
|
+
#boot.failed .bm-bird-svg .wand { stroke: var(--bm-text-dim); }
|
|
104
|
+
|
|
105
|
+
/* Full brightness, no motion: dimming means "this is a repeat boot", not "you asked for less
|
|
106
|
+
movement". */
|
|
107
|
+
@media (prefers-reduced-motion: reduce) {
|
|
108
|
+
.bm-bird-hop, .bm-bird-flip, .bm-bird-shadow { animation: none; }
|
|
109
|
+
#boot { transition: none; }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@keyframes bird-hop {
|
|
113
|
+
0%,6% { transform: translateY(0) scale(1,1); animation-timing-function: cubic-bezier(.35,0,.35,1); }
|
|
114
|
+
14% { transform: translateY(10%) scale(1.16,.80); animation-timing-function: cubic-bezier(.2,.9,.35,1); }
|
|
115
|
+
22% { transform: translateY(-14%) scale(.82,1.22); animation-timing-function: cubic-bezier(.12,.62,.35,1); }
|
|
116
|
+
50% { transform: translateY(-105%) scale(1,1); animation-timing-function: cubic-bezier(.6,0,.85,.35); }
|
|
117
|
+
80% { transform: translateY(-4%) scale(.9,1.12); animation-timing-function: cubic-bezier(.3,.5,.5,1); }
|
|
118
|
+
88% { transform: translateY(8%) scale(1.24,.72); animation-timing-function: cubic-bezier(.2,.2,.3,1); }
|
|
119
|
+
94% { transform: translateY(-3%) scale(.93,1.08); animation-timing-function: cubic-bezier(.3,0,.4,1); }
|
|
120
|
+
100% { transform: translateY(0) scale(1,1); }
|
|
121
|
+
}
|
|
122
|
+
@keyframes bird-flip {
|
|
123
|
+
0%,20% { transform: rotate(0deg); animation-timing-function: cubic-bezier(.3,.1,.3,1); }
|
|
124
|
+
84%,100% { transform: rotate(-720deg); }
|
|
125
|
+
}
|
|
126
|
+
@keyframes bird-shadow {
|
|
127
|
+
0%,6% { transform: scale(1); opacity: .55; }
|
|
128
|
+
50% { transform: scale(.5); opacity: .25; }
|
|
129
|
+
88% { transform: scale(1.18); opacity: .6; }
|
|
130
|
+
100% { transform: scale(1); opacity: .55; }
|
|
131
|
+
}
|
|
132
|
+
`;
|
|
133
|
+
/**
|
|
134
|
+
* The overlay, placed inside `#viewport` so it covers the game and nothing else.
|
|
135
|
+
*
|
|
136
|
+
* The path data is the brandmark, verbatim from the artwork; only the paint attributes are gone,
|
|
137
|
+
* replaced by the classes the stylesheet above paints.
|
|
138
|
+
*/
|
|
139
|
+
export const BOOT_LOADER_HTML = `
|
|
140
|
+
<div id="boot" aria-live="polite">
|
|
141
|
+
<div id="boot-stage">
|
|
142
|
+
<div class="bm-bird-shadow"></div>
|
|
143
|
+
<div class="bm-bird-hop">
|
|
144
|
+
<div class="bm-bird-flip">
|
|
145
|
+
<svg class="bm-bird-svg" viewBox="0 0 325.98 286.58" role="img" aria-label="Bitmagic">
|
|
146
|
+
<path class="body" d="M189.35,43.3c-18.08,0-38.95,7.71-48.75,24.5-12.41,21.25.75,39.51-14.27,56.28-14.67,16.37-35.49,6.27-49.25,23.66-9.53,12.06-9.42,29.43-6.22,40.71,11.9,41.87,80.72,50.03,88.1,50.82,4.41.47,12.56,1.33,22.54,1.33,22.34,0,53.82-4.33,72.88-27.11,41.89-50.08-1.78-158.91-54.06-169.17-3.44-.68-7.14-1.02-10.96-1.02"/>
|
|
147
|
+
<path class="body" d="M84.96,155.05s-35.24-11.29-29.46-25.64c5.78-14.35,28.91,21.38,28.91,21.38"/>
|
|
148
|
+
<path class="body" d="M82.66,157.28s-24.58-32.65-10.23-41.72c14.35-9.07,12.44,37.58,12.44,37.58"/>
|
|
149
|
+
<path class="detail" d="M135.5,135.43c-4.56,6.82-5.76,7.24-13.55,4.67,6.82,4.56,7.24,5.76,4.67,13.55,4.56-6.82,5.76-7.24,13.55-4.67-6.82-4.56-7.24-5.76-4.67-13.55Z"/>
|
|
150
|
+
<path class="detail" d="M160.11,84.01c-4.56,6.82-5.76,7.24-13.55,4.67,6.82,4.56,7.24,5.76,4.67,13.55,4.56-6.82,5.76-7.24,13.55-4.67-6.82-4.56-7.24-5.76-4.67-13.55Z"/>
|
|
151
|
+
<path class="detail" d="M159.7,167.94c-2.6,3.89-3.28,4.12-7.72,2.66,3.89,2.6,4.12,3.28,2.66,7.72,2.6-3.89,3.28-4.12,7.72-2.66-3.89-2.6-4.12-3.28-2.66-7.72Z"/>
|
|
152
|
+
<path class="detail" d="M189.27,58.59c-2.6,3.89-3.28,4.12-7.72,2.66,3.89,2.6,4.12,3.28,2.66,7.72,2.6-3.89,3.28-4.12,7.72-2.66-3.89-2.6-4.12-3.28-2.66-7.72Z"/>
|
|
153
|
+
<path class="detail" d="M162.41,113.42c-4.26,6.37-5.38,6.76-12.66,4.36,6.37,4.26,6.76,5.38,4.36,12.66,4.26-6.37,5.38-6.76,12.66-4.36-6.37-4.26-6.76-5.38-4.36-12.66Z"/>
|
|
154
|
+
<circle class="detail" cx="206.9" cy="115.82" r="23.31" transform="translate(-10.12 20.3) rotate(-5.48)"/>
|
|
155
|
+
<circle class="iris" stroke-width="12.08" stroke-miterlimit="10" cx="206.9" cy="115.82" r="23.31" transform="translate(-10.12 20.3) rotate(-5.48)"/>
|
|
156
|
+
<circle class="iris-edge" stroke-width="2.99" stroke-miterlimit="10" cx="206.89" cy="115.73" r="28.36" transform="translate(-25.72 161.42) rotate(-40.34)"/>
|
|
157
|
+
<line class="wand" stroke-linecap="round" stroke-width="15.33" stroke-miterlimit="10" x1="238.54" y1="82.17" x2="264.66" y2="53.95"/>
|
|
158
|
+
</svg>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
<p id="boot-message">Bringing your world to life…</p>
|
|
163
|
+
<button id="boot-retry" class="bm-pill bm-pill--ghost" type="button">Try again</button>
|
|
164
|
+
</div>
|
|
165
|
+
`;
|
|
166
|
+
//# sourceMappingURL=boot-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boot-loader.js","sourceRoot":"","sources":["../../src/editor/boot-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmG9B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;CA0B/B,CAAC"}
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
import { decodeForgeMapHeights, renderForgeMapRgba, } from '@bitmagic/world-forger/pipeline/forge-map-render.js';
|
|
52
52
|
import { FORGE_MAP_PALETTE } from '@bitmagic/world-forger/pipeline/layout-map.js';
|
|
53
53
|
import { ASSET_DETAIL_CSS, ASSET_DETAIL_HTML } from './asset-detail-panel.js';
|
|
54
|
+
import { BOOT_LOADER_CSS, BOOT_LOADER_HTML } from './boot-loader.js';
|
|
54
55
|
import { BITMAGIC_CONTROLS_CSS, BITMAGIC_FONT_LINK, BITMAGIC_TOKENS_CSS } from './design.js';
|
|
55
56
|
/** How often the shell asks the engine whether anything changed. A `Set` read; effectively free. */
|
|
56
57
|
const POLL_INTERVAL_MS = 500;
|
|
@@ -152,7 +153,10 @@ ${BITMAGIC_CONTROLS_CSS}
|
|
|
152
153
|
/* The game and the panel share one row, so the panel takes width from the game rather than
|
|
153
154
|
overlaying it — an overlay would cover the thing you opened the panel to watch. */
|
|
154
155
|
#stage { flex: 1; display: flex; min-height: 0; }
|
|
155
|
-
|
|
156
|
+
/* The boot loader is positioned against this rather than against #stage, so it covers the game
|
|
157
|
+
and leaves the assets panel alone — a forge ticking there is what you watch during a boot. */
|
|
158
|
+
#viewport { position: relative; flex: 1; min-width: 0; }
|
|
159
|
+
#frame { display: block; width: 100%; height: 100%; border: 0; }
|
|
156
160
|
#assets { width: 280px; flex: none; overflow-y: auto; background: var(--bm-surface);
|
|
157
161
|
border-left: 1px solid var(--bm-border-muted); }
|
|
158
162
|
body.assets-closed #assets { display: none; }
|
|
@@ -224,6 +228,7 @@ ${BITMAGIC_CONTROLS_CSS}
|
|
|
224
228
|
#hq-note code { display: block; margin-top: 6px; color: var(--bm-aqua);
|
|
225
229
|
font-family: var(--bm-font-mono); word-break: break-all; }
|
|
226
230
|
${ASSET_DETAIL_CSS}
|
|
231
|
+
${BOOT_LOADER_CSS}
|
|
227
232
|
</style>
|
|
228
233
|
</head>
|
|
229
234
|
<body>
|
|
@@ -258,7 +263,10 @@ ${ASSET_DETAIL_CSS}
|
|
|
258
263
|
<button id="terrain-discard" class="bm-pill bm-pill--destructive" type="button">Discard terrain edits</button>
|
|
259
264
|
</div>
|
|
260
265
|
<div id="stage">
|
|
261
|
-
<
|
|
266
|
+
<div id="viewport">
|
|
267
|
+
<iframe id="frame" allow="autoplay; fullscreen; xr-spatial-tracking; clipboard-write"></iframe>
|
|
268
|
+
${BOOT_LOADER_HTML}
|
|
269
|
+
</div>
|
|
262
270
|
<aside id="assets">
|
|
263
271
|
<div id="assets-head" class="bm-label">Assets<span class="count" id="assets-count"></span></div>
|
|
264
272
|
<div id="assets-jobs"></div>
|
|
@@ -302,6 +310,8 @@ ${ASSET_DETAIL_HTML}
|
|
|
302
310
|
var banner = document.getElementById('banner');
|
|
303
311
|
var terrainBanner = document.getElementById('terrain-banner');
|
|
304
312
|
var buildBanner = document.getElementById('build-banner');
|
|
313
|
+
var bootOverlay = document.getElementById('boot');
|
|
314
|
+
var bootMessage = document.getElementById('boot-message');
|
|
305
315
|
var autoToggle = document.getElementById('auto-toggle');
|
|
306
316
|
var tabButtons = document.querySelectorAll('.tab');
|
|
307
317
|
|
|
@@ -318,6 +328,15 @@ ${ASSET_DETAIL_HTML}
|
|
|
318
328
|
// two polling loops running against one iframe.
|
|
319
329
|
var generation = 0;
|
|
320
330
|
|
|
331
|
+
// Boots so far in this page load. The animation is a first impression, not a progress bar: it
|
|
332
|
+
// plays on the first boot and never again. bitmagic reload is wired to the agent's Stop hook, so
|
|
333
|
+
// an agent working for an hour would otherwise be forty backflips.
|
|
334
|
+
var bootCount = 0;
|
|
335
|
+
// How slow a later boot has to be before its still mark is worth showing at all. A reload that
|
|
336
|
+
// beats this never flashes anything.
|
|
337
|
+
var BOOT_REVEAL_MS = 600;
|
|
338
|
+
var bootTimer = null;
|
|
339
|
+
|
|
321
340
|
// The engine's own view of itself, from GAME_STATE_CHANGED. The Game tab needs it to tell
|
|
322
341
|
// "never started" (START_GAME) from "paused for the editor" (unpause) — see applyTab.
|
|
323
342
|
var gameState = '';
|
|
@@ -644,6 +663,47 @@ ${ASSET_DETAIL_HTML}
|
|
|
644
663
|
runLoop();
|
|
645
664
|
}
|
|
646
665
|
|
|
666
|
+
/**
|
|
667
|
+
* Show the loader for the boot that is starting.
|
|
668
|
+
*
|
|
669
|
+
* The first boot of a page load gets the animation, and gets it at once: there is nothing else on
|
|
670
|
+
* the stage to look at and the wait is real. Every boot after it gets the same mark, still and
|
|
671
|
+
* dimmed, and only once the reload has taken long enough to be worth explaining.
|
|
672
|
+
*/
|
|
673
|
+
function showBoot() {
|
|
674
|
+
bootCount += 1;
|
|
675
|
+
var first = bootCount === 1;
|
|
676
|
+
if (bootTimer) { clearTimeout(bootTimer); bootTimer = null; }
|
|
677
|
+
bootOverlay.classList.remove('failed');
|
|
678
|
+
bootOverlay.classList.toggle('quiet', !first);
|
|
679
|
+
bootMessage.textContent = first
|
|
680
|
+
? 'Bringing your world to life…'
|
|
681
|
+
: 'Picking up the latest changes…';
|
|
682
|
+
if (first) { bootOverlay.classList.add('show'); return; }
|
|
683
|
+
bootTimer = setTimeout(function () { bootOverlay.classList.add('show'); }, BOOT_REVEAL_MS);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function hideBoot() {
|
|
687
|
+
if (bootTimer) { clearTimeout(bootTimer); bootTimer = null; }
|
|
688
|
+
bootOverlay.classList.remove('show');
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* A boot that ended badly keeps the stage instead of handing back a blank iframe.
|
|
693
|
+
*
|
|
694
|
+
* Owns the bar's status as well as the overlay, so the two cannot disagree. Both failures below
|
|
695
|
+
* name a command the creator is meant to run next, which is worth more than a stale frame of
|
|
696
|
+
* nothing and an 8px dot they have to notice.
|
|
697
|
+
*/
|
|
698
|
+
function failBoot(text) {
|
|
699
|
+
if (bootTimer) { clearTimeout(bootTimer); bootTimer = null; }
|
|
700
|
+
setStatus('error', text);
|
|
701
|
+
bootMessage.textContent = text;
|
|
702
|
+
bootOverlay.classList.add('quiet');
|
|
703
|
+
bootOverlay.classList.add('failed');
|
|
704
|
+
bootOverlay.classList.add('show');
|
|
705
|
+
}
|
|
706
|
+
|
|
647
707
|
async function boot(gen) {
|
|
648
708
|
loaded = false;
|
|
649
709
|
markersDirty = false;
|
|
@@ -654,11 +714,26 @@ ${ASSET_DETAIL_HTML}
|
|
|
654
714
|
banner.classList.remove('show');
|
|
655
715
|
terrainBanner.classList.remove('show');
|
|
656
716
|
setStatus('', 'Loading…');
|
|
717
|
+
showBoot();
|
|
657
718
|
|
|
658
|
-
var response
|
|
719
|
+
var response;
|
|
720
|
+
try {
|
|
721
|
+
response = await fetch('/api/game-data');
|
|
722
|
+
} catch (error) {
|
|
723
|
+
// The sidecar is this page's own server, so a fetch that fails outright means it is gone and
|
|
724
|
+
// every later step would fail the same way. Say so rather than rejecting: boot() is called
|
|
725
|
+
// from start()'s .then with no .catch, so a rejection here skips runLoop() forever and leaves
|
|
726
|
+
// the page on "Loading…" with nothing in the console to explain it.
|
|
727
|
+
if (gen !== generation) return;
|
|
728
|
+
failBoot('Lost the connection to bitmagic dev — is it still running?');
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
// A superseded boot must touch NOTHING here. A newer boot() has already called showBoot() and
|
|
732
|
+
// owns the overlay: hiding would blank its loader, and failing would paint an error over a game
|
|
733
|
+
// that has since loaded fine. Same for the two guards further down.
|
|
659
734
|
if (gen !== generation) return;
|
|
660
735
|
if (!response.ok) {
|
|
661
|
-
|
|
736
|
+
failBoot('Could not read the project');
|
|
662
737
|
return;
|
|
663
738
|
}
|
|
664
739
|
var project = await response.json();
|
|
@@ -672,7 +747,7 @@ ${ASSET_DETAIL_HTML}
|
|
|
672
747
|
var ready = await templateReady;
|
|
673
748
|
if (gen !== generation) return;
|
|
674
749
|
if (!ready) {
|
|
675
|
-
|
|
750
|
+
failBoot('The game never finished booting — try "bitmagic verify"');
|
|
676
751
|
return;
|
|
677
752
|
}
|
|
678
753
|
// currentTab is honoured by the engine's own LOAD_GAME handler, which sets the camera and
|
|
@@ -687,11 +762,12 @@ ${ASSET_DETAIL_HTML}
|
|
|
687
762
|
var started = await gameLoaded;
|
|
688
763
|
if (gen !== generation) return;
|
|
689
764
|
if (!started) {
|
|
690
|
-
|
|
765
|
+
failBoot('The world never loaded — try "bitmagic verify"');
|
|
691
766
|
return;
|
|
692
767
|
}
|
|
693
768
|
|
|
694
769
|
loaded = true;
|
|
770
|
+
hideBoot();
|
|
695
771
|
applyTab(activeTab);
|
|
696
772
|
// A boot almost always follows a world.json change, so the list has moved with it. Deliberately
|
|
697
773
|
// not resetting the seen-ids set: the asset that caused the reload is exactly the one worth
|
|
@@ -1717,6 +1793,8 @@ ${ASSET_DETAIL_HTML}
|
|
|
1717
1793
|
|
|
1718
1794
|
shotButton.addEventListener('click', takeScreenshot);
|
|
1719
1795
|
document.getElementById('reload').addEventListener('click', function () { start(); });
|
|
1796
|
+
// Same thing the bar's Reload does, put where a creator is already looking when a boot fails.
|
|
1797
|
+
document.getElementById('boot-retry').addEventListener('click', function () { start(); });
|
|
1720
1798
|
document.getElementById('banner-reload').addEventListener('click', function () { start(); });
|
|
1721
1799
|
document.getElementById('terrain-discard').addEventListener('click', function () {
|
|
1722
1800
|
post('REVERT_TERRAIN_CHANGES');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-page.js","sourceRoot":"","sources":["../../src/editor/shell-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EACL,qBAAqB,EAAE,kBAAkB,GAC1C,MAAM,qDAAqD,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE7F,oGAAoG;AACpG,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;;;;;;;;;GAYG;AACH,SAAS,sBAAsB;IAC7B,OAAO;QACL,6BAA6B,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,GAAG;QACjE,iCAAiC,qBAAqB,CAAC,QAAQ,EAAE,GAAG;QACpE,8BAA8B,kBAAkB,CAAC,QAAQ,EAAE,GAAG;KAC/D,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC,kGAAkG;AAClG,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AASD,MAAM,UAAU,iBAAiB,CAAC,OAA2B;IAC3D,MAAM,OAAO,GAAG,oBAAoB,OAAO,CAAC,QAAQ,2BAA2B,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IACpH,OAAO;;;;wBAIe,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;EAChD,kBAAkB;;EAElB,mBAAmB;EACnB,qBAAqB
|
|
1
|
+
{"version":3,"file":"shell-page.js","sourceRoot":"","sources":["../../src/editor/shell-page.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAw/C3B,CAAC;AACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitmagic/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"description": "Build Bitmagic games from your own agent tool",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"author": "Bitmagic Oy",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"fflate": "^0.8.2",
|
|
24
24
|
"playwright-core": "^1.59.1",
|
|
25
25
|
"tar": "^7.4.3",
|
|
26
|
-
"@bitmagic/animation-forger": "0.1.
|
|
27
|
-
"@bitmagic/asset-core": "0.2.
|
|
28
|
-
"@bitmagic/world-forger": "0.1.
|
|
26
|
+
"@bitmagic/animation-forger": "0.1.3",
|
|
27
|
+
"@bitmagic/asset-core": "0.2.3",
|
|
28
|
+
"@bitmagic/world-forger": "0.1.8"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@eslint/js": "^9.38.0",
|