@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
|
@@ -8,14 +8,27 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
8
8
|
* diagnostic card instead of blanking.
|
|
9
9
|
* @module @linxin666/dsh-pet/client/renderers/PetRendererSwitch
|
|
10
10
|
*/
|
|
11
|
-
import { cloneElement, isValidElement } from 'react';
|
|
11
|
+
import { cloneElement, isValidElement, useRef } from 'react';
|
|
12
|
+
import { createDragStream } from "../drag-stream.js";
|
|
12
13
|
import { defaultPetRendererRegistry } from "./registry.js";
|
|
13
14
|
import { Live2dVisualMount } from "./live2d/Live2dVisualMount.js";
|
|
15
|
+
import { Frames2dVisualMount } from "./Frames2dVisualMount.js";
|
|
14
16
|
/** Dispatch one pet definition to its renderer; unknown kinds get a card. */
|
|
15
17
|
export function PetRendererSwitch(props) {
|
|
16
18
|
const renderer = props.definition.renderer ?? 'sprite2d';
|
|
19
|
+
// The frames2d drag stream lives one level up: the chrome (PetSprite)
|
|
20
|
+
// reports the gesture through onDraggingChange, the visual subscribes.
|
|
21
|
+
const dragRef = useRef(null);
|
|
22
|
+
if (dragRef.current === null || dragRef.current.id !== props.definition.id) {
|
|
23
|
+
dragRef.current = { id: props.definition.id, stream: createDragStream() };
|
|
24
|
+
}
|
|
25
|
+
const drag = props.drag ?? dragRef.current.stream;
|
|
17
26
|
if (renderer === 'sprite2d')
|
|
18
27
|
return _jsx(_Fragment, { children: props.children });
|
|
28
|
+
if (renderer === 'frames2d' && defaultPetRendererRegistry.has('frames2d') && isValidElement(props.children)) {
|
|
29
|
+
const visual = (_jsx(Frames2dVisualMount, { definition: props.definition, phase: props.phase, onPet: props.onPet, drag: drag, ...(props.bus === undefined ? {} : { bus: props.bus }), t: props.t }));
|
|
30
|
+
return cloneElement(props.children, { visual, onDraggingChange: (dragging) => drag.push(dragging) });
|
|
31
|
+
}
|
|
19
32
|
if (renderer === 'live2d' && defaultPetRendererRegistry.has('live2d') && isValidElement(props.children)) {
|
|
20
33
|
const visual = (_jsx(Live2dVisualMount, { definition: props.definition, phase: props.phase, onPet: props.onPet, t: props.t }));
|
|
21
34
|
return cloneElement(props.children, { visual });
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* frames2d renderer — plays the free-form named frame-sequence tracks of a
|
|
3
|
+
* frames2d pet (manifest v2 'frames2d' block). The pet center picks the
|
|
4
|
+
* track from the ActivityPhase stream (phase -> track map, idle fallback);
|
|
5
|
+
* the gameplay driver may force a track through the handle's setState
|
|
6
|
+
* override (drag/work/sleep/shop...), and a finished non-loop track settles
|
|
7
|
+
* into its fallback, releasing the override when the fallback matches the
|
|
8
|
+
* phase-mapped track. Rendering never throws: a broken track list degrades
|
|
9
|
+
* to the first decodable frame, and the 1.2 s stall watchdog re-kicks the
|
|
10
|
+
* playback chain after timer throttling.
|
|
11
|
+
* @module @linxin666/dsh-pet/client/renderers/frames2d
|
|
12
|
+
*/
|
|
13
|
+
import { type PetRenderer, type PetRendererHandle } from '../../contracts/renderer.ts';
|
|
14
|
+
import type { ActivityPhase } from '../../state.ts';
|
|
15
|
+
/** One track as served inside the pet definition (browser URLs). */
|
|
16
|
+
export interface Frames2dTrackConfig {
|
|
17
|
+
frames: string[];
|
|
18
|
+
durations: number[];
|
|
19
|
+
loop: boolean;
|
|
20
|
+
fallback?: string;
|
|
21
|
+
}
|
|
22
|
+
/** The frames2d block as served inside the pet definition. */
|
|
23
|
+
export interface PetFrames2dConfig {
|
|
24
|
+
tracks: Record<string, Frames2dTrackConfig>;
|
|
25
|
+
phases: Partial<Record<ActivityPhase, string>> & {
|
|
26
|
+
idle: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export interface Frames2dRendererHandle extends PetRendererHandle {
|
|
30
|
+
/** Force a track id (gameplay override); undefined returns to phase mapping. */
|
|
31
|
+
setState(track: string | undefined): void;
|
|
32
|
+
/** The track currently playing (diagnostics and tests). */
|
|
33
|
+
currentTrack(): string;
|
|
34
|
+
}
|
|
35
|
+
export declare const frames2dRenderer: PetRenderer<PetFrames2dConfig>;
|
|
36
|
+
//# sourceMappingURL=frames2d.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frames2d.d.ts","sourceRoot":"","sources":["../../../../src/client/renderers/frames2d.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAA4B,KAAK,WAAW,EAA2B,KAAK,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AACzI,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,oEAAoE;AACpE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,8DAA8D;AAC9D,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAC3C,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAClE;AAED,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAA;IACzC,2DAA2D;IAC3D,YAAY,IAAI,MAAM,CAAA;CACvB;AAoCD,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,iBAAiB,CAgJ3D,CAAA"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* frames2d renderer — plays the free-form named frame-sequence tracks of a
|
|
3
|
+
* frames2d pet (manifest v2 'frames2d' block). The pet center picks the
|
|
4
|
+
* track from the ActivityPhase stream (phase -> track map, idle fallback);
|
|
5
|
+
* the gameplay driver may force a track through the handle's setState
|
|
6
|
+
* override (drag/work/sleep/shop...), and a finished non-loop track settles
|
|
7
|
+
* into its fallback, releasing the override when the fallback matches the
|
|
8
|
+
* phase-mapped track. Rendering never throws: a broken track list degrades
|
|
9
|
+
* to the first decodable frame, and the 1.2 s stall watchdog re-kicks the
|
|
10
|
+
* playback chain after timer throttling.
|
|
11
|
+
* @module @linxin666/dsh-pet/client/renderers/frames2d
|
|
12
|
+
*/
|
|
13
|
+
import { PET_RENDERER_API_VERSION } from "../../contracts/renderer.js";
|
|
14
|
+
/** Stall watchdog period: a looping track stuck longer re-kicks its chain. */
|
|
15
|
+
const WATCHDOG_MS = 1200;
|
|
16
|
+
function isRecord(value) {
|
|
17
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
18
|
+
}
|
|
19
|
+
/** Fail-closed client-side validation of the served frames2d block. */
|
|
20
|
+
function validateFrames2dConfig(config) {
|
|
21
|
+
if (!isRecord(config) || !isRecord(config.tracks) || !isRecord(config.phases)) {
|
|
22
|
+
throw new Error('frames2d config requires tracks and phases objects');
|
|
23
|
+
}
|
|
24
|
+
const tracks = {};
|
|
25
|
+
for (const [name, raw] of Object.entries(config.tracks)) {
|
|
26
|
+
if (!isRecord(raw) || !Array.isArray(raw.frames) || raw.frames.length === 0
|
|
27
|
+
|| raw.frames.some(f => typeof f !== 'string' || f === '')
|
|
28
|
+
|| !Array.isArray(raw.durations) || raw.durations.length !== raw.frames.length
|
|
29
|
+
|| raw.durations.some(d => typeof d !== 'number' || !(d > 0))) {
|
|
30
|
+
throw new Error('frames2d track ' + JSON.stringify(name) + ' needs same-length frames/durations');
|
|
31
|
+
}
|
|
32
|
+
tracks[name] = {
|
|
33
|
+
frames: raw.frames,
|
|
34
|
+
durations: raw.durations,
|
|
35
|
+
loop: raw.loop !== false,
|
|
36
|
+
...(typeof raw.fallback === 'string' ? { fallback: raw.fallback } : {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const phases = config.phases;
|
|
40
|
+
if (typeof phases.idle !== 'string' || tracks[phases.idle] === undefined) {
|
|
41
|
+
throw new Error('frames2d phases.idle must name an existing track');
|
|
42
|
+
}
|
|
43
|
+
return { tracks, phases: phases };
|
|
44
|
+
}
|
|
45
|
+
export const frames2dRenderer = {
|
|
46
|
+
id: 'frames2d',
|
|
47
|
+
apiVersion: PET_RENDERER_API_VERSION,
|
|
48
|
+
validateConfig: validateFrames2dConfig,
|
|
49
|
+
mount(ctx, config) {
|
|
50
|
+
const reducedMotion = typeof window !== 'undefined'
|
|
51
|
+
&& typeof window.matchMedia === 'function'
|
|
52
|
+
&& window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
53
|
+
const img = document.createElement('img');
|
|
54
|
+
img.dataset.dshPetFrames2d = ctx.petId;
|
|
55
|
+
img.alt = '';
|
|
56
|
+
img.draggable = false;
|
|
57
|
+
img.style.width = '100%';
|
|
58
|
+
img.style.height = '100%';
|
|
59
|
+
img.style.objectFit = 'contain';
|
|
60
|
+
img.style.pointerEvents = 'none';
|
|
61
|
+
ctx.container.appendChild(img);
|
|
62
|
+
// Warm the browser cache for every frame up front (same-origin, small
|
|
63
|
+
// webp files); playback itself swaps img.src without React state.
|
|
64
|
+
for (const track of Object.values(config.tracks)) {
|
|
65
|
+
for (const url of track.frames) {
|
|
66
|
+
const pre = new Image();
|
|
67
|
+
pre.src = url;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
let disposed = false;
|
|
71
|
+
let timer;
|
|
72
|
+
let watchdog;
|
|
73
|
+
let track = config.phases.idle;
|
|
74
|
+
let frameIndex = 0;
|
|
75
|
+
let lastAdvance = Date.now();
|
|
76
|
+
let override;
|
|
77
|
+
const trackForPhase = (phase) => {
|
|
78
|
+
const mapped = config.phases[phase];
|
|
79
|
+
return mapped !== undefined && config.tracks[mapped] !== undefined ? mapped : config.phases.idle;
|
|
80
|
+
};
|
|
81
|
+
const show = (trackId, index) => {
|
|
82
|
+
const def = config.tracks[trackId];
|
|
83
|
+
const url = def?.frames[index];
|
|
84
|
+
if (url !== undefined && img.getAttribute('src') !== url)
|
|
85
|
+
img.src = url;
|
|
86
|
+
};
|
|
87
|
+
const schedule = (ms) => {
|
|
88
|
+
if (disposed)
|
|
89
|
+
return;
|
|
90
|
+
timer = setTimeout(tick, ms);
|
|
91
|
+
};
|
|
92
|
+
function tick() {
|
|
93
|
+
if (disposed)
|
|
94
|
+
return;
|
|
95
|
+
const def = config.tracks[track];
|
|
96
|
+
if (def === undefined || def.frames.length === 0)
|
|
97
|
+
return;
|
|
98
|
+
lastAdvance = Date.now();
|
|
99
|
+
const next = frameIndex + 1;
|
|
100
|
+
if (next < def.frames.length) {
|
|
101
|
+
frameIndex = next;
|
|
102
|
+
show(track, frameIndex);
|
|
103
|
+
schedule(def.durations[frameIndex] ?? 200);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (def.loop) {
|
|
107
|
+
frameIndex = 0;
|
|
108
|
+
show(track, frameIndex);
|
|
109
|
+
schedule(def.durations[frameIndex] ?? 200);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Non-loop completion: settle into the fallback; when the fallback is
|
|
113
|
+
// what the phase map would play anyway, release the gameplay override.
|
|
114
|
+
const target = def.fallback !== undefined && config.tracks[def.fallback] !== undefined
|
|
115
|
+
? def.fallback
|
|
116
|
+
: config.phases.idle;
|
|
117
|
+
if (target === trackForPhase(ctx.phase.get()))
|
|
118
|
+
override = undefined;
|
|
119
|
+
play(target);
|
|
120
|
+
}
|
|
121
|
+
function play(trackId) {
|
|
122
|
+
if (disposed)
|
|
123
|
+
return;
|
|
124
|
+
if (config.tracks[trackId] === undefined)
|
|
125
|
+
trackId = config.phases.idle;
|
|
126
|
+
if (timer !== undefined)
|
|
127
|
+
clearTimeout(timer);
|
|
128
|
+
track = trackId;
|
|
129
|
+
frameIndex = 0;
|
|
130
|
+
lastAdvance = Date.now();
|
|
131
|
+
show(track, frameIndex);
|
|
132
|
+
if (reducedMotion)
|
|
133
|
+
return;
|
|
134
|
+
const def = config.tracks[track];
|
|
135
|
+
schedule(def.durations[0] ?? 200);
|
|
136
|
+
}
|
|
137
|
+
const unsubscribe = ctx.phase.subscribe((phase) => {
|
|
138
|
+
if (override !== undefined)
|
|
139
|
+
return;
|
|
140
|
+
const target = trackForPhase(phase);
|
|
141
|
+
if (target !== track)
|
|
142
|
+
play(target);
|
|
143
|
+
});
|
|
144
|
+
// Watchdog: a throttled-away timer (background tab) leaves the chain
|
|
145
|
+
// dead; re-kick when a looping track has not advanced on schedule.
|
|
146
|
+
if (!reducedMotion) {
|
|
147
|
+
watchdog = setInterval(() => {
|
|
148
|
+
if (disposed)
|
|
149
|
+
return;
|
|
150
|
+
const def = config.tracks[track];
|
|
151
|
+
if (def === undefined || !def.loop)
|
|
152
|
+
return;
|
|
153
|
+
const expected = (def.durations[frameIndex] ?? 200) + WATCHDOG_MS;
|
|
154
|
+
if (Date.now() - lastAdvance > expected)
|
|
155
|
+
tick();
|
|
156
|
+
}, WATCHDOG_MS);
|
|
157
|
+
}
|
|
158
|
+
play(track);
|
|
159
|
+
let disposedOnce = false;
|
|
160
|
+
const dispose = () => {
|
|
161
|
+
if (disposedOnce)
|
|
162
|
+
return;
|
|
163
|
+
disposedOnce = true;
|
|
164
|
+
disposed = true;
|
|
165
|
+
unsubscribe();
|
|
166
|
+
if (timer !== undefined)
|
|
167
|
+
clearTimeout(timer);
|
|
168
|
+
if (watchdog !== undefined)
|
|
169
|
+
clearInterval(watchdog);
|
|
170
|
+
img.remove();
|
|
171
|
+
};
|
|
172
|
+
ctx.onCleanup(dispose);
|
|
173
|
+
return {
|
|
174
|
+
dispose,
|
|
175
|
+
setState(next) {
|
|
176
|
+
if (disposed)
|
|
177
|
+
return;
|
|
178
|
+
if (next === undefined) {
|
|
179
|
+
override = undefined;
|
|
180
|
+
const target = trackForPhase(ctx.phase.get());
|
|
181
|
+
if (target !== track)
|
|
182
|
+
play(target);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (config.tracks[next] === undefined)
|
|
186
|
+
return;
|
|
187
|
+
override = next;
|
|
188
|
+
if (next !== track)
|
|
189
|
+
play(next);
|
|
190
|
+
},
|
|
191
|
+
currentTrack() {
|
|
192
|
+
return track;
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
},
|
|
196
|
+
};
|
|
@@ -173,7 +173,7 @@ export declare class CardForm<T> {
|
|
|
173
173
|
/**
|
|
174
174
|
* Write every staged edit, then re-seed from what the Host accepted.
|
|
175
175
|
*
|
|
176
|
-
* When the scope carries the optional batch surface (the dsh-web
|
|
176
|
+
* When the scope carries the optional batch surface (the dsh-web
|
|
177
177
|
* bridge scope), every planned write rides one mutation so cross-field
|
|
178
178
|
* validate hooks (baseURL+model) judge the batch as a unit instead of
|
|
179
179
|
* deadlocking on per-field writes. Otherwise the per-field loop runs.
|
|
@@ -170,7 +170,7 @@ export class CardForm {
|
|
|
170
170
|
/**
|
|
171
171
|
* Write every staged edit, then re-seed from what the Host accepted.
|
|
172
172
|
*
|
|
173
|
-
* When the scope carries the optional batch surface (the dsh-web
|
|
173
|
+
* When the scope carries the optional batch surface (the dsh-web
|
|
174
174
|
* bridge scope), every planned write rides one mutation so cross-field
|
|
175
175
|
* validate hooks (baseURL+model) judge the batch as a unit instead of
|
|
176
176
|
* deadlocking on per-field writes. Otherwise the per-field loop runs.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anonymous install telemetry shared by the DSH Web UI family plugins.
|
|
3
|
+
*
|
|
4
|
+
* Once per UTC day per browser, each wired plugin sends one heartbeat to
|
|
5
|
+
* the dsh-market edge API listing its package name (and version when known).
|
|
6
|
+
* The payload carries no conversation data and no identifiers beyond a random
|
|
7
|
+
* UUID generated in localStorage; the server hashes it with a deployment salt
|
|
8
|
+
* before storage and never persists IP addresses. Sends are fire-and-forget:
|
|
9
|
+
* failures stay silent and simply retry on a later mount or day. The system
|
|
10
|
+
* is documented in docs/telemetry.md.
|
|
11
|
+
*/
|
|
12
|
+
export type TelemetryChannel = 'market' | 'npm' | 'unknown';
|
|
13
|
+
export interface TelemetryItem {
|
|
14
|
+
/** npm package name or asset id, e.g. "@linxin666/dsh-pet" or "skin:harbor". */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Installed version when known; omitted otherwise. */
|
|
17
|
+
version?: string;
|
|
18
|
+
/** Install channel when determinable (market = Workshop install). */
|
|
19
|
+
channel?: TelemetryChannel;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Fire the daily heartbeat for the given items at most once per UTC day per
|
|
23
|
+
* browser. Never throws and never blocks the caller. Items without an explicit
|
|
24
|
+
* version inherit the bundle's baked build version.
|
|
25
|
+
*/
|
|
26
|
+
export declare function reportDailyHeartbeat(items: readonly TelemetryItem[]): void;
|
|
27
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../../src/client/telemetry.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAA;AAE3D,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC3B;AA+CD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CA8B1E"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Generated by scripts/sync-shared.mjs from shared/client/telemetry.ts. Do not edit this copy; edit the shared source and run "node scripts/sync-shared.mjs".
|
|
2
|
+
/**
|
|
3
|
+
* Anonymous install telemetry shared by the DSH Web UI family plugins.
|
|
4
|
+
*
|
|
5
|
+
* Once per UTC day per browser, each wired plugin sends one heartbeat to
|
|
6
|
+
* the dsh-market edge API listing its package name (and version when known).
|
|
7
|
+
* The payload carries no conversation data and no identifiers beyond a random
|
|
8
|
+
* UUID generated in localStorage; the server hashes it with a deployment salt
|
|
9
|
+
* before storage and never persists IP addresses. Sends are fire-and-forget:
|
|
10
|
+
* failures stay silent and simply retry on a later mount or day. The system
|
|
11
|
+
* is documented in docs/telemetry.md.
|
|
12
|
+
*/
|
|
13
|
+
const VISITOR_KEY = 'dsh-web-ui-telemetry-visitor';
|
|
14
|
+
const DAY_KEY_PREFIX = 'dsh-web-ui-telemetry-day:';
|
|
15
|
+
const ENDPOINT = 'https://dsh-market.com/api/telemetry/event';
|
|
16
|
+
/** The building package's version, when the bundle carries it. */
|
|
17
|
+
function bakedVersion() {
|
|
18
|
+
try {
|
|
19
|
+
return typeof __DSH_PKG_VERSION__ === 'string' && __DSH_PKG_VERSION__ !== ''
|
|
20
|
+
? __DSH_PKG_VERSION__
|
|
21
|
+
: undefined;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Read or lazily create the anonymous visitor id; null when storage is unavailable. */
|
|
28
|
+
function visitorId() {
|
|
29
|
+
try {
|
|
30
|
+
const existing = localStorage.getItem(VISITOR_KEY);
|
|
31
|
+
if (existing && /^[A-Za-z0-9_-]{16,64}$/.test(existing))
|
|
32
|
+
return existing;
|
|
33
|
+
const fresh = crypto.randomUUID().replaceAll('-', '');
|
|
34
|
+
localStorage.setItem(VISITOR_KEY, fresh);
|
|
35
|
+
return fresh;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Storage unavailable (privacy mode, sandboxed frame): report nothing.
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Drop stale per-day dedup keys so localStorage does not grow forever. */
|
|
43
|
+
function pruneDayKeys(today) {
|
|
44
|
+
try {
|
|
45
|
+
for (let index = localStorage.length - 1; index >= 0; index -= 1) {
|
|
46
|
+
const key = localStorage.key(index);
|
|
47
|
+
if (key !== null && key.startsWith(DAY_KEY_PREFIX) && key !== DAY_KEY_PREFIX + today) {
|
|
48
|
+
localStorage.removeItem(key);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch { /* best effort */ }
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Fire the daily heartbeat for the given items at most once per UTC day per
|
|
56
|
+
* browser. Never throws and never blocks the caller. Items without an explicit
|
|
57
|
+
* version inherit the bundle's baked build version.
|
|
58
|
+
*/
|
|
59
|
+
export function reportDailyHeartbeat(items) {
|
|
60
|
+
try {
|
|
61
|
+
if (items.length === 0)
|
|
62
|
+
return;
|
|
63
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
64
|
+
// Automation contexts (CDP-driven QA browsers, fresh isolated profiles)
|
|
65
|
+
// mint a new visitor id per run and would inflate instance counts.
|
|
66
|
+
if (navigator.webdriver)
|
|
67
|
+
return;
|
|
68
|
+
if (localStorage.getItem(DAY_KEY_PREFIX + today) !== null)
|
|
69
|
+
return;
|
|
70
|
+
const visitor = visitorId();
|
|
71
|
+
if (visitor === null)
|
|
72
|
+
return;
|
|
73
|
+
pruneDayKeys(today);
|
|
74
|
+
const payloadItems = items.map((item) => {
|
|
75
|
+
const out = { name: item.name };
|
|
76
|
+
const version = item.version ?? bakedVersion();
|
|
77
|
+
if (version !== undefined)
|
|
78
|
+
out.version = version;
|
|
79
|
+
if (item.channel !== undefined)
|
|
80
|
+
out.channel = item.channel;
|
|
81
|
+
return out;
|
|
82
|
+
});
|
|
83
|
+
const body = JSON.stringify({ kind: 'heartbeat', visitor, items: payloadItems });
|
|
84
|
+
void fetch(ENDPOINT, {
|
|
85
|
+
method: 'POST',
|
|
86
|
+
headers: { 'content-type': 'application/json' },
|
|
87
|
+
body,
|
|
88
|
+
keepalive: true,
|
|
89
|
+
}).then((response) => {
|
|
90
|
+
// Mark the day only after an accepted send, so offline browsers retry
|
|
91
|
+
// on a later mount instead of going dark until tomorrow.
|
|
92
|
+
if (response.ok)
|
|
93
|
+
localStorage.setItem(DAY_KEY_PREFIX + today, '1');
|
|
94
|
+
}).catch(() => { });
|
|
95
|
+
}
|
|
96
|
+
catch { /* never break the host UI over telemetry */ }
|
|
97
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Shared defaults used by registry selection and persisted-state migration. */
|
|
2
|
+
/** Pet id that legacy single-pet installs and fresh registries resolve to. */
|
|
3
|
+
export declare const DEFAULT_PET_ID = "whale-girl";
|
|
4
|
+
/** Default pet name used only when a manifest carries no displayName. */
|
|
5
|
+
export declare const DEFAULT_PET_NAME = "\u9CB8\u9C7C\u5A18";
|
|
6
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/defaults.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,8EAA8E;AAC9E,eAAO,MAAM,cAAc,eAAe,CAAA;AAE1C,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,uBAAQ,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Shared defaults used by registry selection and persisted-state migration. */
|
|
2
|
+
/** Pet id that legacy single-pet installs and fresh registries resolve to. */
|
|
3
|
+
export const DEFAULT_PET_ID = 'whale-girl';
|
|
4
|
+
/** Default pet name used only when a manifest carries no displayName. */
|
|
5
|
+
export const DEFAULT_PET_NAME = '鲸鱼娘';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dsh-home.d.ts","sourceRoot":"","sources":["../../src/dsh-home.ts"],"names":[],"mappings":"AACA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"dsh-home.d.ts","sourceRoot":"","sources":["../../src/dsh-home.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAMH,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,CAMzE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,CAUrG;AAED,gEAAgE;AAChE,wBAAgB,OAAO,IAAI,MAAM,CAEhC"}
|
package/lib/types/dsh-home.js
CHANGED
|
@@ -6,12 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { homedir } from 'node:os';
|
|
8
8
|
import { isAbsolute, join } from 'node:path';
|
|
9
|
+
import { isAbsolute as posixIsAbsolute, join as posixJoin } from 'node:path/posix';
|
|
9
10
|
/** Expand a leading ~ (or ~user) in a path, platform-style. */
|
|
10
11
|
export function expandHome(path, home = homedir()) {
|
|
12
|
+
const isPosix = home.startsWith('/');
|
|
13
|
+
const j = isPosix ? posixJoin : join;
|
|
11
14
|
if (path === '~')
|
|
12
15
|
return home;
|
|
13
16
|
if (path.startsWith('~/') || path.startsWith('~\\'))
|
|
14
|
-
return
|
|
17
|
+
return j(home, path.slice(2));
|
|
15
18
|
return path;
|
|
16
19
|
}
|
|
17
20
|
/**
|
|
@@ -21,12 +24,15 @@ export function expandHome(path, home = homedir()) {
|
|
|
21
24
|
* @returns the absolute DSH home path.
|
|
22
25
|
*/
|
|
23
26
|
export function resolveDshHome(env = process.env, home = homedir()) {
|
|
27
|
+
const isPosix = home.startsWith('/');
|
|
28
|
+
const j = isPosix ? posixJoin : join;
|
|
29
|
+
const isAbs = isPosix ? posixIsAbsolute : isAbsolute;
|
|
24
30
|
const raw = env.DSH_HOME;
|
|
25
31
|
if (raw !== undefined && raw.trim() !== '') {
|
|
26
32
|
const expanded = expandHome(raw.trim(), home);
|
|
27
|
-
return
|
|
33
|
+
return isAbs(expanded) ? expanded : j(process.cwd(), expanded);
|
|
28
34
|
}
|
|
29
|
-
return
|
|
35
|
+
return j(home, '.dsh');
|
|
30
36
|
}
|
|
31
37
|
/** Resolve the DSH home directory from the live environment. */
|
|
32
38
|
export function dshHome() {
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pet gameplay — the optional manifest 'gameplay' block and its host engine.
|
|
3
|
+
* The block layers an opt-in mini-game over any frames2d pet: decaying stat
|
|
4
|
+
* bars, currencies, a weighted idle director, touch zones, a work loop, a
|
|
5
|
+
* sleep loop, passive income and a shop (issue: miku-pet generalization).
|
|
6
|
+
*
|
|
7
|
+
* Discipline split matches manifest-v2: STRUCTURE is fail-closed (types,
|
|
8
|
+
* ranges, references into stats/tracks); the host engine is pure — every
|
|
9
|
+
* verb takes an explicit clock and rng so tests stay deterministic. Decay,
|
|
10
|
+
* passive income and sleep restore are lazy-settled on read (the treats.ts
|
|
11
|
+
* discipline): the host runs no timers for gameplay.
|
|
12
|
+
* @module @linxin666/dsh-pet/gameplay
|
|
13
|
+
*/
|
|
14
|
+
/** One gameplay effect: add amount to a declared stat or a currency. */
|
|
15
|
+
export interface PetGameplayEffect {
|
|
16
|
+
stat?: string;
|
|
17
|
+
currency?: string;
|
|
18
|
+
amount: number;
|
|
19
|
+
}
|
|
20
|
+
/** One roll branch inside a touch zone; uncovered roll mass is a no-op. */
|
|
21
|
+
export interface PetGameplayTouchBranch {
|
|
22
|
+
probability: number;
|
|
23
|
+
effects?: PetGameplayEffect[];
|
|
24
|
+
/** Track played on hit (held for stateMs, then the renderer settles). */
|
|
25
|
+
state?: string;
|
|
26
|
+
stateMs?: number;
|
|
27
|
+
/** Bubble phrase pool; one is picked on hit. */
|
|
28
|
+
phrases?: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface PetGameplayTouchZone {
|
|
31
|
+
name: string;
|
|
32
|
+
/** Vertical slice of the hit box (fractions, y0 < y1). */
|
|
33
|
+
y0: number;
|
|
34
|
+
y1: number;
|
|
35
|
+
branches: PetGameplayTouchBranch[];
|
|
36
|
+
}
|
|
37
|
+
export interface PetGameplayStatDef {
|
|
38
|
+
max: number;
|
|
39
|
+
initial?: number;
|
|
40
|
+
decayPerMinute?: number;
|
|
41
|
+
/** Decay rate while the work mode is active (defaults to decayPerMinute). */
|
|
42
|
+
workingDecayPerMinute?: number;
|
|
43
|
+
/** Extra decay rate while no session is active. */
|
|
44
|
+
idleDecayPerMinute?: number;
|
|
45
|
+
}
|
|
46
|
+
export interface PetGameplayShopItem {
|
|
47
|
+
id: string;
|
|
48
|
+
label: string;
|
|
49
|
+
/** Optional frame path (manifest-relative) shown as the item icon. */
|
|
50
|
+
image?: string;
|
|
51
|
+
price: number;
|
|
52
|
+
currency: string;
|
|
53
|
+
effects?: PetGameplayEffect[];
|
|
54
|
+
lottery?: {
|
|
55
|
+
effects?: PetGameplayEffect[];
|
|
56
|
+
/** Default currency the prize is paid in (tiers may override). */
|
|
57
|
+
currency?: string;
|
|
58
|
+
tiers: {
|
|
59
|
+
probability: number;
|
|
60
|
+
prize: number;
|
|
61
|
+
currency?: string;
|
|
62
|
+
}[];
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** The validated manifest 'gameplay' block. */
|
|
66
|
+
export interface PetGameplayManifest {
|
|
67
|
+
idleDirector?: {
|
|
68
|
+
intervalMs: number;
|
|
69
|
+
maxMiss: number;
|
|
70
|
+
idleWeight: number;
|
|
71
|
+
acts: {
|
|
72
|
+
track: string;
|
|
73
|
+
weight: number;
|
|
74
|
+
phrases?: string[];
|
|
75
|
+
}[];
|
|
76
|
+
};
|
|
77
|
+
stats?: Record<string, PetGameplayStatDef>;
|
|
78
|
+
/** Click hit box inside the sprite box (fractions). */
|
|
79
|
+
hitBox?: {
|
|
80
|
+
x0: number;
|
|
81
|
+
y0: number;
|
|
82
|
+
x1: number;
|
|
83
|
+
y1: number;
|
|
84
|
+
};
|
|
85
|
+
touch?: {
|
|
86
|
+
zones: PetGameplayTouchZone[];
|
|
87
|
+
/** Plain-click effect while a touch animation holds (miku: mood +0..3). */
|
|
88
|
+
clickBoost?: {
|
|
89
|
+
stat: string;
|
|
90
|
+
min: number;
|
|
91
|
+
max: number;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
work?: {
|
|
95
|
+
state: string;
|
|
96
|
+
successState: string;
|
|
97
|
+
failState: string;
|
|
98
|
+
tickMs: number;
|
|
99
|
+
/** Hold time of the result track before the next round. */
|
|
100
|
+
resultMs?: {
|
|
101
|
+
success: number;
|
|
102
|
+
fail: number;
|
|
103
|
+
};
|
|
104
|
+
successProbability: number;
|
|
105
|
+
success?: {
|
|
106
|
+
effects: PetGameplayEffect[];
|
|
107
|
+
};
|
|
108
|
+
fail?: {
|
|
109
|
+
effects: PetGameplayEffect[];
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
sleep?: {
|
|
113
|
+
state: string;
|
|
114
|
+
wakeState?: string;
|
|
115
|
+
restore: {
|
|
116
|
+
stat: string;
|
|
117
|
+
amount: number;
|
|
118
|
+
intervalMs: number;
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
passiveIncome?: {
|
|
122
|
+
currency: string;
|
|
123
|
+
amount: number;
|
|
124
|
+
intervalMs: number;
|
|
125
|
+
};
|
|
126
|
+
shop?: {
|
|
127
|
+
state?: string;
|
|
128
|
+
items: PetGameplayShopItem[];
|
|
129
|
+
};
|
|
130
|
+
/** Track played while the chrome reports dragging (default 'drag'). */
|
|
131
|
+
dragState?: string;
|
|
132
|
+
/** Track played once when a drag ends (miku: standup), before settling. */
|
|
133
|
+
dragEndState?: string;
|
|
134
|
+
}
|
|
135
|
+
export interface GameplayParseHooks {
|
|
136
|
+
/** State names the renderer can play (frames2d track ids). */
|
|
137
|
+
stateNames: ReadonlySet<string>;
|
|
138
|
+
error: (message: string) => void;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Validate the manifest 'gameplay' block (fail-closed). Only frames2d pets
|
|
142
|
+
* may declare gameplay today: every state reference checks against the
|
|
143
|
+
* declared track names.
|
|
144
|
+
*/
|
|
145
|
+
export declare function parseGameplayManifest(raw: unknown, hooks: GameplayParseHooks): PetGameplayManifest | undefined;
|
|
146
|
+
/** Persisted per-pet gameplay state (pet.json 'gameplay' map values). */
|
|
147
|
+
export interface PetGameplayState {
|
|
148
|
+
stats: Record<string, number>;
|
|
149
|
+
currencies: Record<string, number>;
|
|
150
|
+
mode: 'work' | 'sleep' | null;
|
|
151
|
+
/** Epoch ms of the last lazy settle. */
|
|
152
|
+
settledAt: number;
|
|
153
|
+
}
|
|
154
|
+
/** Fresh state for one pet: stats at their initial (default max), no currency. */
|
|
155
|
+
export declare function initialGameplayState(manifest: PetGameplayManifest, now: number): PetGameplayState;
|
|
156
|
+
/** Clamp one stat value into [0, max]; currencies into [0, CURRENCY_MAX]. */
|
|
157
|
+
export declare function clampGameplay(state: PetGameplayState, manifest: PetGameplayManifest): void;
|
|
158
|
+
/**
|
|
159
|
+
* Lazy settle: apply stat decay, passive income and sleep restore for the
|
|
160
|
+
* elapsed wall time since the last settle. Mirrors the treats.ts discipline
|
|
161
|
+
* (no host timers; read paths settle). Returns whether anything changed.
|
|
162
|
+
*/
|
|
163
|
+
export declare function settleGameplay(state: PetGameplayState, manifest: PetGameplayManifest, now: number, options: {
|
|
164
|
+
sessionActive: boolean;
|
|
165
|
+
}): boolean;
|
|
166
|
+
/** Apply one effect vector (touch/work/shop), clamped. */
|
|
167
|
+
export declare function applyGameplayEffects(state: PetGameplayState, manifest: PetGameplayManifest, effects: readonly PetGameplayEffect[]): void;
|
|
168
|
+
/** Roll one touch zone branch; undefined when the roll lands in no-op mass. */
|
|
169
|
+
export declare function rollTouchBranch(zone: PetGameplayTouchZone, rng: () => number): PetGameplayTouchBranch | undefined;
|
|
170
|
+
/** Roll one work tick outcome. */
|
|
171
|
+
export declare function rollWorkOutcome(work: NonNullable<PetGameplayManifest['work']>, rng: () => number): 'success' | 'fail';
|
|
172
|
+
/** Draw one lottery prize tier; uncovered mass falls through to the last tier. */
|
|
173
|
+
export declare function drawLotteryTier(lottery: NonNullable<PetGameplayShopItem['lottery']>, rng: () => number): {
|
|
174
|
+
probability: number;
|
|
175
|
+
prize: number;
|
|
176
|
+
currency?: string;
|
|
177
|
+
};
|
|
178
|
+
/** The zone one normalized hit-box point lands in, if any. */
|
|
179
|
+
export declare function touchZoneAt(touch: {
|
|
180
|
+
zones: PetGameplayTouchZone[];
|
|
181
|
+
}, yFraction: number): PetGameplayTouchZone | undefined;
|
|
182
|
+
//# sourceMappingURL=gameplay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gameplay.d.ts","sourceRoot":"","sources":["../../src/gameplay.ts"],"names":[],"mappings":"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"}
|