@linxin666/dsh-pet 0.3.2 → 0.3.4
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.i18n.yaml +2 -2
- package/README.md +25 -7
- package/README.zh.md +25 -7
- package/assets/ouo-neko/pet.json +31 -0
- package/assets/ouo-neko/previews/failed.gif +0 -0
- package/assets/ouo-neko/previews/idle.gif +0 -0
- package/assets/ouo-neko/previews/jumping.gif +0 -0
- package/assets/ouo-neko/previews/review.gif +0 -0
- package/assets/ouo-neko/previews/running-left.gif +0 -0
- package/assets/ouo-neko/previews/running-right.gif +0 -0
- package/assets/ouo-neko/previews/running.gif +0 -0
- package/assets/ouo-neko/previews/waiting.gif +0 -0
- package/assets/ouo-neko/previews/waving.gif +0 -0
- package/assets/ouo-neko/spritesheet.webp +0 -0
- package/contracts/pet-manifest-v2.schema.json +102 -1
- package/lib/client.js +830 -26
- package/lib/client.js.map +1 -1
- package/lib/index.js +1226 -24
- package/lib/types/client/PetDockEntry.d.ts +3 -0
- package/lib/types/client/PetDockEntry.d.ts.map +1 -1
- package/lib/types/client/PetDockEntry.js +18 -2
- package/lib/types/client/PetSprite.d.ts +23 -0
- package/lib/types/client/PetSprite.d.ts.map +1 -1
- package/lib/types/client/PetSprite.js +34 -29
- package/lib/types/client/PluginSettingsCard.d.ts +2 -0
- package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PluginSettingsCard.js +2 -2
- package/lib/types/client/drag-stream.d.ts +19 -0
- package/lib/types/client/drag-stream.d.ts.map +1 -0
- package/lib/types/client/drag-stream.js +26 -0
- package/lib/types/client/gameplay-hud.d.ts +50 -0
- package/lib/types/client/gameplay-hud.d.ts.map +1 -0
- package/lib/types/client/gameplay-hud.js +274 -0
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +16 -0
- package/lib/types/client/locales.d.ts +34 -0
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +36 -0
- package/lib/types/client/pet-store.d.ts +7 -1
- package/lib/types/client/pet-store.d.ts.map +1 -1
- package/lib/types/client/pet-store.js +4 -0
- package/lib/types/client/renderers/Frames2dVisualMount.d.ts +29 -0
- package/lib/types/client/renderers/Frames2dVisualMount.d.ts.map +1 -0
- package/lib/types/client/renderers/Frames2dVisualMount.js +83 -0
- package/lib/types/client/renderers/PetRendererSwitch.d.ts +6 -0
- package/lib/types/client/renderers/PetRendererSwitch.d.ts.map +1 -1
- package/lib/types/client/renderers/PetRendererSwitch.js +14 -1
- package/lib/types/client/renderers/frames2d.d.ts +36 -0
- package/lib/types/client/renderers/frames2d.d.ts.map +1 -0
- package/lib/types/client/renderers/frames2d.js +196 -0
- package/lib/types/client/settings-form.d.ts +1 -1
- package/lib/types/client/settings-form.js +1 -1
- package/lib/types/client/telemetry.d.ts +27 -0
- package/lib/types/client/telemetry.d.ts.map +1 -0
- package/lib/types/client/telemetry.js +97 -0
- package/lib/types/defaults.d.ts +6 -0
- package/lib/types/defaults.d.ts.map +1 -0
- package/lib/types/defaults.js +5 -0
- package/lib/types/dsh-home.d.ts.map +1 -1
- package/lib/types/dsh-home.js +9 -3
- package/lib/types/gameplay.d.ts +182 -0
- package/lib/types/gameplay.d.ts.map +1 -0
- package/lib/types/gameplay.js +618 -0
- package/lib/types/http.d.ts +1 -1
- package/lib/types/http.js +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.js +1 -1
- package/lib/types/ledger.d.ts +14 -0
- package/lib/types/ledger.d.ts.map +1 -1
- package/lib/types/ledger.js +30 -0
- package/lib/types/loopback.d.ts +1 -1
- package/lib/types/loopback.js +1 -1
- package/lib/types/manifest-v2.d.ts +38 -1
- package/lib/types/manifest-v2.d.ts.map +1 -1
- package/lib/types/manifest-v2.js +182 -2
- package/lib/types/mount-once.d.ts +1 -1
- package/lib/types/mount-once.js +2 -2
- package/lib/types/persist.d.ts +4 -4
- package/lib/types/persist.d.ts.map +1 -1
- package/lib/types/persist.js +41 -4
- package/lib/types/registry.d.ts +29 -0
- package/lib/types/registry.d.ts.map +1 -1
- package/lib/types/registry.js +170 -1
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +22 -0
- package/lib/types/service.d.ts +56 -0
- package/lib/types/service.d.ts.map +1 -1
- package/lib/types/service.js +181 -0
- package/package.json +6 -3
- package/src/client/PetDockEntry.test.tsx +6 -0
- package/src/client/PetDockEntry.tsx +32 -1
- package/src/client/PetSprite.test.tsx +36 -6
- package/src/client/PetSprite.tsx +42 -21
- package/src/client/PluginSettingsCard.tsx +4 -2
- package/src/client/drag-stream.ts +35 -0
- package/src/client/gameplay-hud.test.tsx +338 -0
- package/src/client/gameplay-hud.tsx +403 -0
- package/src/client/index.ts +23 -2
- package/src/client/locales.ts +36 -0
- package/src/client/pet-store.ts +10 -1
- package/src/client/pet.module.css +192 -29
- package/src/client/renderers/Frames2dVisualMount.tsx +111 -0
- package/src/client/renderers/PetRendererSwitch.tsx +28 -1
- package/src/client/renderers/frames2d.test.ts +137 -0
- package/src/client/renderers/frames2d.ts +216 -0
- package/src/client/settings-card.module.css +5 -0
- package/src/client/settings-form.ts +1 -1
- package/src/client/telemetry.ts +105 -0
- package/src/defaults.ts +7 -0
- package/src/dsh-home.ts +9 -3
- package/src/gameplay.test.ts +239 -0
- package/src/gameplay.ts +692 -0
- package/src/http.ts +1 -1
- package/src/index.ts +1 -1
- package/src/ledger.test.ts +16 -0
- package/src/ledger.ts +31 -0
- package/src/loopback.ts +1 -1
- package/src/manifest-v2.test.ts +130 -1
- package/src/manifest-v2.ts +181 -2
- package/src/mount-once.ts +2 -2
- package/src/persist.test.ts +3 -0
- package/src/persist.ts +43 -6
- package/src/registry.test.ts +168 -1
- package/src/registry.ts +199 -1
- package/src/routes.ts +19 -0
- package/src/service.ts +208 -0
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { type ReactElement } from 'react';
|
|
14
14
|
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
15
15
|
import type { PetStoreInstance } from './pet-store.ts';
|
|
16
|
+
import { type GameplayApi } from './gameplay-hud.tsx';
|
|
16
17
|
import { NS } from './locales.ts';
|
|
17
18
|
/** Injected actions handed to the dock entry component. */
|
|
18
19
|
export interface PetInjected {
|
|
@@ -36,6 +37,8 @@ export interface PetInjected {
|
|
|
36
37
|
openSession: (sessionId: string) => void;
|
|
37
38
|
/** Clear the reaction bubble. */
|
|
38
39
|
feedbackDone: () => void;
|
|
40
|
+
/** Gameplay verb API (miku-pet generalization); wired but unused for pets without a gameplay block. */
|
|
41
|
+
gameplay: GameplayApi;
|
|
39
42
|
}
|
|
40
43
|
/** Composed props of the global pet entry (locale + injected; no slot runtime share). */
|
|
41
44
|
export type PetDockEntryProps = PetInjected & PropsLocale<typeof NS>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PetDockEntry.d.ts","sourceRoot":"","sources":["../../../src/client/PetDockEntry.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"PetDockEntry.d.ts","sourceRoot":"","sources":["../../../src/client/PetDockEntry.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAA2C,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAItD,OAAO,EAAe,KAAK,WAAW,EAAoB,MAAM,oBAAoB,CAAA;AACpF,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAGjC,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC1B,6EAA6E;IAC7E,KAAK,EAAE,gBAAgB,CAAA;IACvB,kFAAkF;IAClF,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,8BAA8B;IAC9B,GAAG,EAAE,MAAM,IAAI,CAAA;IACf,uBAAuB;IACvB,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,uBAAuB;IACvB,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,qCAAqC;IACrC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,+BAA+B;IAC/B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAChD,uDAAuD;IACvD,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,2DAA2D;IAC3D,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,iCAAiC;IACjC,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,uGAAuG;IACvG,QAAQ,EAAE,WAAW,CAAA;CACtB;AAED,yFAAyF;AACzF,MAAM,MAAM,iBAAiB,GAC3B,WAAW,GACT,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;AAI1B;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CAwFnE"}
|
|
@@ -11,9 +11,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
11
11
|
* the registry list — no per-pet component exists.
|
|
12
12
|
* @module @linxin666/dsh-pet/client/PetDockEntry
|
|
13
13
|
*/
|
|
14
|
-
import { useEffect, useSyncExternalStore } from 'react';
|
|
14
|
+
import { useEffect, useRef, useSyncExternalStore } from 'react';
|
|
15
15
|
import { PetSprite } from "./PetSprite.js";
|
|
16
16
|
import { PetRendererSwitch } from "./renderers/PetRendererSwitch.js";
|
|
17
|
+
import { createDragStream } from "./drag-stream.js";
|
|
18
|
+
import { GameplayHud } from "./gameplay-hud.js";
|
|
17
19
|
import styles from './pet.module.css';
|
|
18
20
|
const DEFAULT_DISPLAY = { visible: true, size: 160, right: 24, bottom: 20 };
|
|
19
21
|
/**
|
|
@@ -33,10 +35,24 @@ export function PetDockEntry(props) {
|
|
|
33
35
|
useEffect(() => {
|
|
34
36
|
ensure();
|
|
35
37
|
}, [ensure]);
|
|
38
|
+
// Per-pet gameplay wiring: the coordination bus (HUD taps <-> chrome,
|
|
39
|
+
// HUD track overrides <-> frames2d mount) and the shared drag stream.
|
|
40
|
+
const auxRef = useRef(null);
|
|
41
|
+
if (definition !== null && (auxRef.current === null || auxRef.current.id !== definition.id)) {
|
|
42
|
+
auxRef.current = { id: definition.id, bus: {}, drag: createDragStream() };
|
|
43
|
+
}
|
|
44
|
+
const aux = auxRef.current;
|
|
45
|
+
const gameplay = definition?.gameplay;
|
|
36
46
|
if (visible) {
|
|
37
47
|
return (_jsx("span", { "data-pet-dock": true, "data-testid": "pet-dock", children: snapshot === null || definition === null
|
|
38
48
|
? null
|
|
39
|
-
: (_jsx(PetRendererSwitch, { definition: definition, phase: snapshot?.phase ?? 'idle', onPet: props.pet, t: props.t, children: _jsx(PetSprite, { snapshot: snapshot, definition: definition, display: snapshot.display, feedback: feedback, onPet: props.pet, onFeed: props.feed, onHide: props.hide, onDragEnd: props.dragEnd, onRename: props.rename, onOpenSession: props.openSession, onFeedbackDone: props.feedbackDone,
|
|
49
|
+
: (_jsx(PetRendererSwitch, { definition: definition, phase: snapshot?.phase ?? 'idle', onPet: props.pet, ...(aux === null ? {} : { drag: aux.drag, bus: aux.bus }), t: props.t, children: _jsx(PetSprite, { snapshot: snapshot, definition: definition, display: snapshot.display, feedback: feedback, onPet: props.pet, onFeed: props.feed, onHide: props.hide, onDragEnd: props.dragEnd, onRename: props.rename, onOpenSession: props.openSession, onFeedbackDone: props.feedbackDone, dragDisabled: snapshot.gameplay?.mode === 'work', ...(gameplay === undefined || aux === null
|
|
50
|
+
? {}
|
|
51
|
+
: {
|
|
52
|
+
onGameplayTap: (fx, fy) => aux.bus.tap?.(fx, fy),
|
|
53
|
+
onGameplayMenu: () => aux.bus.openCard?.(),
|
|
54
|
+
hud: (_jsx(GameplayHud, { definition: definition, store: store, api: props.gameplay, bus: aux.bus, drag: aux.drag, t: props.t })),
|
|
55
|
+
}), t: props.t }) })) }));
|
|
40
56
|
}
|
|
41
57
|
const display = snapshot?.display ?? DEFAULT_DISPLAY;
|
|
42
58
|
return (_jsx("button", { type: "button", className: styles.summon, style: {
|
|
@@ -33,6 +33,8 @@ export interface PetSpriteProps {
|
|
|
33
33
|
onHide: () => void;
|
|
34
34
|
/** Persist a drag position. */
|
|
35
35
|
onDragEnd: (right: number, bottom: number) => void;
|
|
36
|
+
/** Drag gesture notifications for renderers with a drag track (frames2d). */
|
|
37
|
+
onDraggingChange?: (dragging: boolean) => void;
|
|
36
38
|
/** Rename the selected pet (persisted by the host). */
|
|
37
39
|
onRename: (name: string) => void;
|
|
38
40
|
/** Navigate to the session one status bubble reports on. */
|
|
@@ -45,6 +47,27 @@ export interface PetSpriteProps {
|
|
|
45
47
|
* renders inside the sprite box, and the atlas load + frame loop skip.
|
|
46
48
|
*/
|
|
47
49
|
visual?: ReactNode;
|
|
50
|
+
/**
|
|
51
|
+
* Gameplay overlay (miku-pet generalization): rendered inside the float
|
|
52
|
+
* container so hover containment and stacking work unchanged. Absent for
|
|
53
|
+
* pets without a gameplay block.
|
|
54
|
+
*/
|
|
55
|
+
hud?: ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* Gameplay tap sink: receives the tap point as sprite-box fractions
|
|
58
|
+
* (0..1). When present the chrome reports the tap IN ADDITION to the
|
|
59
|
+
* affinity pet; the HUD decides zones/no-ops.
|
|
60
|
+
*/
|
|
61
|
+
onGameplayTap?: (fractionX: number, fractionY: number) => void;
|
|
62
|
+
/**
|
|
63
|
+
* Gameplay entry (miku-pet generalization): when present the hover panel
|
|
64
|
+
* renders a 玩法 action that opens/closes the gameplay card. The chrome
|
|
65
|
+
* wires it to the HUD through the per-pet bus (openCard), mirroring the
|
|
66
|
+
* onGameplayTap sink. Absent for pets without a gameplay block.
|
|
67
|
+
*/
|
|
68
|
+
onGameplayMenu?: () => void;
|
|
69
|
+
/** Disable the drag gesture (gameplay work mode blocks dragging). */
|
|
70
|
+
dragDisabled?: boolean;
|
|
48
71
|
/** Locale translate seat (namespace-bound). */
|
|
49
72
|
t: TranslateNS<typeof NS>;
|
|
50
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PetSprite.d.ts","sourceRoot":"","sources":["../../../src/client/PetSprite.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAkE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAIjD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAGjC,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;IAC7B,8EAA8E;IAC9E,UAAU,EAAE,aAAa,CAAA;IACzB,qDAAqD;IACrD,OAAO,EAAE,gBAAgB,CAAA;IACzB,sCAAsC;IACtC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,sCAAsC;IACtC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,sCAAsC;IACtC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,+BAA+B;IAC/B,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAClD,uDAAuD;IACvD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,4DAA4D;IAC5D,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,2DAA2D;IAC3D,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,+CAA+C;IAC/C,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;CAC1B;AAgGD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"PetSprite.d.ts","sourceRoot":"","sources":["../../../src/client/PetSprite.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAkE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAIjD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAGjC,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;IAC7B,8EAA8E;IAC9E,UAAU,EAAE,aAAa,CAAA;IACzB,qDAAqD;IACrD,OAAO,EAAE,gBAAgB,CAAA;IACzB,sCAAsC;IACtC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,sCAAsC;IACtC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,sCAAsC;IACtC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,+BAA+B;IAC/B,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAClD,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9C,uDAAuD;IACvD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,4DAA4D;IAC5D,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,2DAA2D;IAC3D,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB;;;;OAIG;IACH,GAAG,CAAC,EAAE,SAAS,CAAA;IACf;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9D;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,qEAAqE;IACrE,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,+CAA+C;IAC/C,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;CAC1B;AAgGD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,WAAW,CAwiB5D"}
|
|
@@ -312,6 +312,8 @@ export function PetSprite(props) {
|
|
|
312
312
|
// "window is not defined" (slow-runner timing, PetSprite.test.tsx).
|
|
313
313
|
useEffect(() => () => clearHideTimer(), []);
|
|
314
314
|
const onPointerDown = (e) => {
|
|
315
|
+
if (props.dragDisabled === true)
|
|
316
|
+
return;
|
|
315
317
|
e.preventDefault();
|
|
316
318
|
e.target.setPointerCapture?.(e.pointerId);
|
|
317
319
|
const current = dragPos ?? { right: display.right, bottom: display.bottom };
|
|
@@ -325,8 +327,11 @@ export function PetSprite(props) {
|
|
|
325
327
|
return;
|
|
326
328
|
const dx = e.clientX - drag.startX;
|
|
327
329
|
const dy = e.clientY - drag.startY;
|
|
328
|
-
if (Math.abs(dx) > 4 || Math.abs(dy) > 4)
|
|
330
|
+
if (Math.abs(dx) > 4 || Math.abs(dy) > 4) {
|
|
331
|
+
if (!draggedRef.current)
|
|
332
|
+
props.onDraggingChange?.(true);
|
|
329
333
|
draggedRef.current = true;
|
|
334
|
+
}
|
|
330
335
|
const right = clampOffset(drag.right - dx, window.innerWidth - 40);
|
|
331
336
|
const bottom = clampOffset(drag.bottom - dy, window.innerHeight - 40);
|
|
332
337
|
setDragPos({ right, bottom });
|
|
@@ -335,6 +340,8 @@ export function PetSprite(props) {
|
|
|
335
340
|
if (dragRef.current === null)
|
|
336
341
|
return;
|
|
337
342
|
dragRef.current = null;
|
|
343
|
+
if (draggedRef.current)
|
|
344
|
+
props.onDraggingChange?.(false);
|
|
338
345
|
if (dragPos !== null)
|
|
339
346
|
props.onDragEnd(dragPos.right, dragPos.bottom);
|
|
340
347
|
};
|
|
@@ -416,33 +423,31 @@ export function PetSprite(props) {
|
|
|
416
423
|
return;
|
|
417
424
|
clearHideTimer();
|
|
418
425
|
hideTimerRef.current = window.setTimeout(() => setHovered(false), 300);
|
|
419
|
-
}, children: [
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
props.onHide();
|
|
445
|
-
}, children: "\u00D7" })] }), feedback !== null && (_jsx("div", { ref: bubbleRef, className: clsx(styles.bubble, feedback.kind === 'feed' ? styles.bubbleFeed : styles.bubblePet), children: feedback.text }, feedback.at)), feedback === null && (sessionBubbles.length > 0 || statusBubble !== undefined || whisper !== undefined) && (_jsxs("div", { ref: bubbleRef, className: styles.bubbleStack, onPointerEnter: () => setStackPeek(true), onPointerLeave: () => setStackPeek(false), children: [visibleSessions.map((session, index) => {
|
|
426
|
+
}, children: [_jsx("div", { className: styles.spriteWrap, style: { width: spriteWidth, height: spriteHeight }, children: _jsx("div", { ref: spriteRef, className: styles.sprite, style: {
|
|
427
|
+
width: spriteWidth,
|
|
428
|
+
height: spriteHeight,
|
|
429
|
+
...(props.visual === undefined
|
|
430
|
+
? {
|
|
431
|
+
backgroundImage: imageReady ? 'url(' + definition.atlasUrl + ')' : undefined,
|
|
432
|
+
backgroundSize: (cell.width * columns * spriteScale) + 'px ' + (cell.height * (definition.atlasRows ?? rows.length) * spriteScale) + 'px',
|
|
433
|
+
backgroundRepeat: 'no-repeat',
|
|
434
|
+
backgroundPosition: '0 0',
|
|
435
|
+
}
|
|
436
|
+
: {}),
|
|
437
|
+
cursor: dragRef.current === null ? 'grab' : 'grabbing',
|
|
438
|
+
}, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onClick: (e) => {
|
|
439
|
+
// A pointer sequence that moved (dragged) still fires a trailing
|
|
440
|
+
// click; skip the pet when that happened.
|
|
441
|
+
if (draggedRef.current)
|
|
442
|
+
return;
|
|
443
|
+
if (props.onGameplayTap !== undefined && spriteRef.current !== null) {
|
|
444
|
+
const rect = spriteRef.current.getBoundingClientRect();
|
|
445
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
446
|
+
props.onGameplayTap((e.clientX - rect.left) / rect.width, (e.clientY - rect.top) / rect.height);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
props.onPet();
|
|
450
|
+
}, role: "button", "aria-label": definition.displayName, children: props.visual }) }), props.hud, feedback !== null && (_jsx("div", { ref: bubbleRef, className: clsx(styles.bubble, feedback.kind === 'feed' ? styles.bubbleFeed : styles.bubblePet), children: feedback.text }, feedback.at)), feedback === null && (sessionBubbles.length > 0 || statusBubble !== undefined || whisper !== undefined) && (_jsxs("div", { ref: bubbleRef, className: styles.bubbleStack, onPointerEnter: () => setStackPeek(true), onPointerLeave: () => setStackPeek(false), children: [visibleSessions.map((session, index) => {
|
|
446
451
|
// The whisper rides the display session's bubble — the stack's
|
|
447
452
|
// primary entry (DOM-first, rendered bottom-most by the reversed
|
|
448
453
|
// column so it stays glued to the sprite when extras open above).
|
|
@@ -500,6 +505,6 @@ export function PetSprite(props) {
|
|
|
500
505
|
clearHideTimer();
|
|
501
506
|
setNameDraft(displayName);
|
|
502
507
|
setRenaming(true);
|
|
503
|
-
}, children: panelLabel('rename', props.t('pet.rename')) })), panelShows('hide') && (_jsx("button", { type: "button", className: styles.action, onClick: props.onHide, children: panelLabel('hide', props.t('pet.hide')) }))] })] })) }))] }));
|
|
508
|
+
}, children: panelLabel('rename', props.t('pet.rename')) })), panelShows('hide') && (_jsx("button", { type: "button", className: styles.action, onClick: props.onHide, children: panelLabel('hide', props.t('pet.hide')) })), props.onGameplayMenu !== undefined && (_jsx("button", { type: "button", className: styles.action, onClick: props.onGameplayMenu, children: props.t('pet.gameplay.menu') }))] })] })) }))] }));
|
|
504
509
|
return createPortal(float, document.body);
|
|
505
510
|
}
|
|
@@ -22,6 +22,8 @@ export interface PluginSettingsCardProps<TKey extends string = string> {
|
|
|
22
22
|
titleKey: TKey;
|
|
23
23
|
/** Locale key of the line describing what this plugin's settings govern. */
|
|
24
24
|
descriptionKey: TKey;
|
|
25
|
+
/** Optional rich header description rendered instead of the plain t(descriptionKey) text (the plain text stays as the tooltip). */
|
|
26
|
+
descriptionNode?: ReactNode;
|
|
25
27
|
/** The card's form state: availability, writability, and what a save would do. */
|
|
26
28
|
state: CardShell;
|
|
27
29
|
/** Write every staged edit. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -40,8 +40,8 @@ export function PluginSettingsCard(props) {
|
|
|
40
40
|
// With alwaysOpen the nav entry already provides the selection, so the
|
|
41
41
|
// header is a static title row instead of a disclosure button.
|
|
42
42
|
const header = alwaysOpen === true
|
|
43
|
-
? (_jsxs("div", { className: css.headerStatic, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, title: title, children: title }), _jsx("span", { className: css.description, title: description, children: description })] }), state.dirty ? _jsx("span", { className: css.pending, title: props.t('settings.unsaved'), children: props.t('settings.unsaved') }) : null] }))
|
|
44
|
-
: (_jsxs("button", { type: "button", className: css.header, "aria-expanded": open, "aria-label": `${props.t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`, onClick: () => { setOpen(!open); }, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, title: title, children: title }), _jsx("span", { className: css.description, title: description, children: description })] }), state.dirty ? _jsx("span", { className: css.pending, title: props.t('settings.unsaved'), children: props.t('settings.unsaved') }) : null, _jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: open ? `${css.chevron} ${css.chevronOpen}` : css.chevron, children: _jsx("path", { d: "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z", fill: "currentColor" }) })] }));
|
|
43
|
+
? (_jsxs("div", { className: css.headerStatic, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, title: title, children: title }), _jsx("span", { className: css.description, title: description, children: props.descriptionNode ?? description })] }), state.dirty ? _jsx("span", { className: css.pending, title: props.t('settings.unsaved'), children: props.t('settings.unsaved') }) : null] }))
|
|
44
|
+
: (_jsxs("button", { type: "button", className: css.header, "aria-expanded": open, "aria-label": `${props.t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`, onClick: () => { setOpen(!open); }, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, title: title, children: title }), _jsx("span", { className: css.description, title: description, children: props.descriptionNode ?? description })] }), state.dirty ? _jsx("span", { className: css.pending, title: props.t('settings.unsaved'), children: props.t('settings.unsaved') }) : null, _jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: open ? `${css.chevron} ${css.chevronOpen}` : css.chevron, children: _jsx("path", { d: "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z", fill: "currentColor" }) })] }));
|
|
45
45
|
// The namespace exists but the Host does not serve it to this client (the
|
|
46
46
|
// official settings allowlist omits third-party namespaces): show a card
|
|
47
47
|
// that explains the gap instead of vanishing, so a missing card never
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drag stream — bridges the chrome's pointer drag state onto the renderer
|
|
3
|
+
* contract's { get, subscribe } shape, so renderers with a dedicated drag
|
|
4
|
+
* track (frames2d) can follow the chrome-owned drag gesture. Dispatch is
|
|
5
|
+
* change-only, mirroring the phase stream.
|
|
6
|
+
* @module @linxin666/dsh-pet/client/drag-stream
|
|
7
|
+
*/
|
|
8
|
+
/** The renderer-facing drag stream. */
|
|
9
|
+
export interface DragStream {
|
|
10
|
+
/** Whether the chrome reports an active drag gesture. */
|
|
11
|
+
get(): boolean;
|
|
12
|
+
/** Subscribe to drag state changes; returns the unsubscribe. */
|
|
13
|
+
subscribe(listener: (dragging: boolean) => void): () => void;
|
|
14
|
+
/** Feed a fresh drag state; no-op when unchanged. */
|
|
15
|
+
push(dragging: boolean): void;
|
|
16
|
+
}
|
|
17
|
+
/** Create the stream (one per pet activation, owned by the renderer switch). */
|
|
18
|
+
export declare function createDragStream(): DragStream;
|
|
19
|
+
//# sourceMappingURL=drag-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drag-stream.d.ts","sourceRoot":"","sources":["../../../src/client/drag-stream.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,uCAAuC;AACvC,MAAM,WAAW,UAAU;IACzB,yDAAyD;IACzD,GAAG,IAAI,OAAO,CAAA;IACd,gEAAgE;IAChE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IAC5D,qDAAqD;IACrD,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAA;CAC9B;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,IAAI,UAAU,CAe7C"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drag stream — bridges the chrome's pointer drag state onto the renderer
|
|
3
|
+
* contract's { get, subscribe } shape, so renderers with a dedicated drag
|
|
4
|
+
* track (frames2d) can follow the chrome-owned drag gesture. Dispatch is
|
|
5
|
+
* change-only, mirroring the phase stream.
|
|
6
|
+
* @module @linxin666/dsh-pet/client/drag-stream
|
|
7
|
+
*/
|
|
8
|
+
/** Create the stream (one per pet activation, owned by the renderer switch). */
|
|
9
|
+
export function createDragStream() {
|
|
10
|
+
let current = false;
|
|
11
|
+
const listeners = new Set();
|
|
12
|
+
return {
|
|
13
|
+
get: () => current,
|
|
14
|
+
subscribe(listener) {
|
|
15
|
+
listeners.add(listener);
|
|
16
|
+
return () => { listeners.delete(listener); };
|
|
17
|
+
},
|
|
18
|
+
push(dragging) {
|
|
19
|
+
if (dragging === current)
|
|
20
|
+
return;
|
|
21
|
+
current = dragging;
|
|
22
|
+
for (const listener of [...listeners])
|
|
23
|
+
listener(dragging);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gameplay HUD — the client half of the manifest 'gameplay' block (miku-pet
|
|
3
|
+
* generalization). One component owns everything the block needs: the stat
|
|
4
|
+
* bars and shop card (menu / shop pages), the touch-zone tap
|
|
5
|
+
* handling, the idle director rolls, the work and sleep loops, and the
|
|
6
|
+
* float-text toasts. It talks to the host through the injected verb API,
|
|
7
|
+
* writes results straight back into the store (the 2 s poll stays the
|
|
8
|
+
* backstop), and steers the frames2d renderer through the per-pet bus.
|
|
9
|
+
* @module @linxin666/dsh-pet/client/GameplayHud
|
|
10
|
+
*/
|
|
11
|
+
import { type ReactElement } from 'react';
|
|
12
|
+
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
13
|
+
import type { PetDefinition } from '../registry.ts';
|
|
14
|
+
import type { PetGameplayVerbResult } from '../service.ts';
|
|
15
|
+
import type { PetStoreInstance } from './pet-store.ts';
|
|
16
|
+
import type { DragStream } from './drag-stream.ts';
|
|
17
|
+
import type { NS } from './locales.ts';
|
|
18
|
+
/** The gameplay verb API the plugin apply body injects (host-authoritative). */
|
|
19
|
+
export interface GameplayApi {
|
|
20
|
+
touch: (zone?: string) => Promise<PetGameplayVerbResult>;
|
|
21
|
+
setMode: (mode: 'work' | 'sleep' | null) => Promise<PetGameplayVerbResult>;
|
|
22
|
+
workTick: () => Promise<PetGameplayVerbResult>;
|
|
23
|
+
buy: (item: string) => Promise<PetGameplayVerbResult>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The per-pet coordination bus. The frames2d visual mount registers the
|
|
27
|
+
* track override (setTrack); the HUD registers the sprite tap handler; the
|
|
28
|
+
* chrome calls into whatever is registered. Optional chaining everywhere —
|
|
29
|
+
* either side may be mid-remount during a hot reload.
|
|
30
|
+
*/
|
|
31
|
+
export interface GameplayBus {
|
|
32
|
+
setTrack?: (track?: string) => void;
|
|
33
|
+
tap?: (fx: number, fy: number) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Card open/close request from the chrome (the hover panel's 玩法 action):
|
|
36
|
+
* the HUD registers this, and calling it with no argument toggles the card
|
|
37
|
+
* while a boolean pins the state (same chrome -> HUD direction as tap).
|
|
38
|
+
*/
|
|
39
|
+
openCard?: (open?: boolean) => void;
|
|
40
|
+
}
|
|
41
|
+
/** The gameplay overlay for one frames2d pet that declares 'gameplay'. */
|
|
42
|
+
export declare function GameplayHud(props: {
|
|
43
|
+
definition: PetDefinition;
|
|
44
|
+
store: PetStoreInstance;
|
|
45
|
+
api: GameplayApi;
|
|
46
|
+
bus: GameplayBus;
|
|
47
|
+
drag: DragStream;
|
|
48
|
+
t: PropsLocale<typeof NS>['t'];
|
|
49
|
+
}): ReactElement | null;
|
|
50
|
+
//# sourceMappingURL=gameplay-hud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gameplay-hud.d.ts","sourceRoot":"","sources":["../../../src/client/gameplay-hud.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAsE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AAC7G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAGtC,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;IACxD,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;IAC1E,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,CAAC,CAAA;IAC9C,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;CACtD;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CACpC;AAYD,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,UAAU,EAAE,aAAa,CAAA;IACzB,KAAK,EAAE,gBAAgB,CAAA;IACvB,GAAG,EAAE,WAAW,CAAA;IAChB,GAAG,EAAE,WAAW,CAAA;IAChB,IAAI,EAAE,UAAU,CAAA;IAChB,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;CAC/B,GAAG,YAAY,GAAG,IAAI,CAkVtB"}
|