@linxin666/dsh-pet 0.3.24 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +4 -3
- package/README.zh.md +4 -3
- package/icon.svg +3 -0
- package/lib/client.js +522 -194
- package/lib/client.js.map +1 -1
- package/lib/index.js +706 -422
- package/lib/live2d-vendor.js +96 -96
- package/lib/live2d-vendor.js.map +1 -1
- package/lib/types/client/PetDockEntry.d.ts.map +1 -1
- package/lib/types/client/PetDockEntry.js +1 -1
- package/lib/types/client/PetSettingsCard.d.ts +20 -9
- package/lib/types/client/PetSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PetSettingsCard.js +116 -5
- package/lib/types/client/PetSprite.d.ts +6 -0
- package/lib/types/client/PetSprite.d.ts.map +1 -1
- package/lib/types/client/PetSprite.js +95 -0
- package/lib/types/client/PluginSettingsCard.d.ts +4 -0
- package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PluginSettingsCard.js +3 -2
- package/lib/types/client/gameplay-hud.d.ts +10 -1
- package/lib/types/client/gameplay-hud.d.ts.map +1 -1
- package/lib/types/client/gameplay-hud.js +137 -23
- package/lib/types/client/index.d.ts +8 -5
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +61 -27
- package/lib/types/client/main-session.d.ts +33 -0
- package/lib/types/client/main-session.d.ts.map +1 -0
- package/lib/types/client/main-session.js +34 -0
- package/lib/types/client/settings-form.d.ts +17 -17
- package/lib/types/client/settings-form.d.ts.map +1 -1
- package/lib/types/client/settings-form.js +30 -27
- package/lib/types/event-projection.d.ts.map +1 -1
- package/lib/types/event-projection.js +5 -3
- package/lib/types/gameplay.d.ts +79 -5
- package/lib/types/gameplay.d.ts.map +1 -1
- package/lib/types/gameplay.js +212 -17
- package/lib/types/http.d.ts +18 -1
- package/lib/types/http.d.ts.map +1 -1
- package/lib/types/http.js +22 -1
- package/lib/types/index.d.ts +100 -29
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +113 -64
- package/lib/types/persist.d.ts.map +1 -1
- package/lib/types/persist.js +3 -1
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +3 -1
- package/lib/types/service.d.ts +8 -3
- package/lib/types/service.d.ts.map +1 -1
- package/lib/types/service.js +26 -4
- package/package.json +46 -26
- package/src/client/PetDockEntry.tsx +1 -0
- package/src/client/PetSettingsCard.test.tsx +103 -0
- package/src/client/PetSettingsCard.tsx +129 -26
- package/src/client/PetSprite.tsx +96 -0
- package/src/client/PluginSettingsCard.tsx +7 -2
- package/src/client/gameplay-hud.test.tsx +106 -8
- package/src/client/gameplay-hud.tsx +143 -28
- package/src/client/index.test.tsx +37 -4
- package/src/client/index.ts +74 -34
- package/src/client/main-session.ts +43 -0
- package/src/client/settings-form.ts +34 -31
- package/src/event-projection.ts +5 -3
- package/src/gameplay.test.ts +138 -1
- package/src/gameplay.ts +253 -16
- package/src/http.ts +23 -1
- package/src/index.test.ts +107 -11
- package/src/index.ts +162 -73
- package/src/persist.ts +3 -1
- package/src/registry.test.ts +3 -2
- package/src/routes.ts +3 -1
- package/src/service.ts +27 -5
package/lib/types/http.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Shared JSON body/response helpers for the host route families: one strict
|
|
4
4
|
* bounded body reader, one lenient bounded body reader, one JSON object
|
|
5
|
-
* narrow,
|
|
5
|
+
* narrow, one JSON writer, and the outbound request-init helper that keeps a
|
|
6
|
+
* host fetch body decodable (withIdentityEncoding). Previously the readers
|
|
7
|
+
* were copy-pasted across the
|
|
6
8
|
* package route files (routes.ts, update-routes.ts, mobile-api.ts, and each
|
|
7
9
|
* family's route module) with drifting contracts: body caps ranging 4 KiB to
|
|
8
10
|
* 1 MiB and four distinct overflow behaviors (reject, undefined, null, throw).
|
|
@@ -80,6 +82,25 @@ function isJsonObject(value) {
|
|
|
80
82
|
export function asJsonObject(value) {
|
|
81
83
|
return isJsonObject(value) ? value : undefined;
|
|
82
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Request init that asks a remote origin for an uncompressed body.
|
|
87
|
+
*
|
|
88
|
+
* The DSH host boots `@deepseek-ai/dsh-http-proxy`, whose top-level import of
|
|
89
|
+
* the npm `undici` copy replaces the legacy `undici.globalDispatcher.1` slot
|
|
90
|
+
* Node's built-in `fetch()` reads. That cross-major wrapper drops the
|
|
91
|
+
* `content-encoding` header and automatic decompression, so a plain fetch
|
|
92
|
+
* resolves to raw gzip/brotli/zstd bytes — compressed noise no JSON or text
|
|
93
|
+
* consumer can read. Every host fetch that parses a remote body must request
|
|
94
|
+
* identity encoding. Caller headers survive; `accept-encoding` is forced to
|
|
95
|
+
* `identity` because a caller value has no decoder behind it in this host.
|
|
96
|
+
* @param init - the caller's request init (signal, headers, method, ...).
|
|
97
|
+
* @returns a copy with `accept-encoding: identity` merged in.
|
|
98
|
+
*/
|
|
99
|
+
export function withIdentityEncoding(init = {}) {
|
|
100
|
+
const headers = new Headers(init.headers);
|
|
101
|
+
headers.set('accept-encoding', 'identity');
|
|
102
|
+
return { ...init, headers };
|
|
103
|
+
}
|
|
83
104
|
/**
|
|
84
105
|
* Write one JSON response. Default headers are the family defaults
|
|
85
106
|
* (content-type and referrer-policy); caller headers are appended or
|
package/lib/types/index.d.ts
CHANGED
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
* cordis.patch.yml inserts this plugin row.
|
|
11
11
|
* @module @linxin666/dsh-pet
|
|
12
12
|
*/
|
|
13
|
-
import { Context } from '@deepseek-ai/cordis';
|
|
14
|
-
import z from 'schemastery';
|
|
15
|
-
import { type PetConfig } from './service.ts';
|
|
13
|
+
import { Context, type Volatile } from '@deepseek-ai/cordis';
|
|
14
|
+
import z from '@deepseek-ai/schemastery';
|
|
15
|
+
import { type PetConfig, type PetSettingsSection } from './service.ts';
|
|
16
16
|
export { PetService, MAX_SESSION_BUBBLES } from './service.ts';
|
|
17
17
|
export type { PetConfig, PetInteractResult, PetSettingsSection, PetSessionView, PetStateView, } from './service.ts';
|
|
18
18
|
export { AFFINITY_MAX, AFFINITY_RANKS, applyInteraction, applyTurnReward, emptyAffinity, rankOf, } from './affinity.ts';
|
|
@@ -33,33 +33,104 @@ export declare const name = "pet";
|
|
|
33
33
|
/** Services required before the pet can mount its surfaces. */
|
|
34
34
|
export declare const inject: string[];
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* a removed pet cannot invalidate the section (a strict union would refuse
|
|
40
|
-
* the whole registration). The settings card renders the actual registry
|
|
41
|
-
* choices itself from '/api/pet/pets'.
|
|
36
|
+
* Defaults of the fields the pet's settings page edits. They are the schema
|
|
37
|
+
* defaults of the pet row's own config, i.e. what a field the profile entry
|
|
38
|
+
* never set resolves to.
|
|
42
39
|
*/
|
|
43
|
-
export declare
|
|
44
|
-
visible:
|
|
45
|
-
size:
|
|
46
|
-
right:
|
|
47
|
-
bottom:
|
|
48
|
-
bubbleScale:
|
|
49
|
-
petId:
|
|
50
|
-
enabled:
|
|
51
|
-
decorationEnabled:
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
40
|
+
export declare const PET_FORM_DEFAULTS: {
|
|
41
|
+
readonly visible: true;
|
|
42
|
+
readonly size: 160;
|
|
43
|
+
readonly right: 24;
|
|
44
|
+
readonly bottom: 20;
|
|
45
|
+
readonly bubbleScale: 1;
|
|
46
|
+
readonly petId: "whale-girl";
|
|
47
|
+
readonly enabled: true;
|
|
48
|
+
readonly decorationEnabled: true;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* One settings field as the config carries it. The Host commits an edit into
|
|
52
|
+
* the running config through a live reference rather than remounting the row,
|
|
53
|
+
* so a field usually arrives as that reference; a plain value appears when the
|
|
54
|
+
* plugin runs outside a Loader (tests, direct mounts).
|
|
55
|
+
*/
|
|
56
|
+
export type LiveField<T> = Volatile<T> | T;
|
|
57
|
+
/** The pet's settings fields, as a profile entry's config declares them. */
|
|
58
|
+
export interface PetFormConfig {
|
|
59
|
+
/** Master switch for the plugin (browser half + host routes). */
|
|
60
|
+
enabled?: LiveField<boolean>;
|
|
61
|
+
/** Status-decoration master switch (pet-center M5, #567); defaults to on. */
|
|
62
|
+
decorationEnabled?: LiveField<boolean>;
|
|
63
|
+
/** Master switch for the pet surface. */
|
|
64
|
+
visible?: LiveField<boolean>;
|
|
65
|
+
/** Scale of the rendered pet in px (sprite cell height). */
|
|
66
|
+
size?: LiveField<number>;
|
|
67
|
+
/** Horizontal inset from the viewport right edge, px. */
|
|
68
|
+
right?: LiveField<number>;
|
|
69
|
+
/** Vertical inset from the viewport bottom edge, px. */
|
|
70
|
+
bottom?: LiveField<number>;
|
|
71
|
+
/** Bubble typography multiplier on the automatic size following (#1549). */
|
|
72
|
+
bubbleScale?: LiveField<number>;
|
|
73
|
+
/** Selected pet id (a registry entry; the service clamps stale values). */
|
|
74
|
+
petId?: LiveField<string | undefined>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Plugin configuration. Under the 0.1.7 settings model a plugin's own Cordis
|
|
78
|
+
* Config IS its settings page: the Host derives one form per profile entry
|
|
79
|
+
* from this schema, so the fields the pet card edits live here with the
|
|
80
|
+
* defaults the card inherits, next to the tuning block a profile may still
|
|
81
|
+
* declare.
|
|
82
|
+
*
|
|
83
|
+
* Every page field is `volatile()` on purpose. The Host serves exactly the
|
|
84
|
+
* volatile fields of a Config and refuses writes to any other path, and a
|
|
85
|
+
* volatile field is the one it can commit into the RUNNING config: the pet
|
|
86
|
+
* reads the edited value from the live reference instead of being remounted
|
|
87
|
+
* for each edit (see `syncSettings` in `apply`). petId stays a plain string
|
|
88
|
+
* because the service clamps the value against the registry, so a stored
|
|
89
|
+
* selection naming a removed pet cannot invalidate the entry.
|
|
90
|
+
*/
|
|
91
|
+
export declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
92
|
+
visible: z<boolean, boolean, "volatile-defined">;
|
|
93
|
+
size: z<number, number, "volatile-defined">;
|
|
94
|
+
right: z<number, number, "volatile-defined">;
|
|
95
|
+
bottom: z<number, number, "volatile-defined">;
|
|
96
|
+
bubbleScale: z<number, number, "volatile-defined">;
|
|
97
|
+
petId: z<string, string, "volatile">;
|
|
98
|
+
enabled: z<boolean, boolean, "volatile-defined">;
|
|
99
|
+
decorationEnabled: z<boolean, boolean, "volatile-defined">;
|
|
100
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
101
|
+
visible: z<boolean, boolean, "volatile-defined">;
|
|
102
|
+
size: z<number, number, "volatile-defined">;
|
|
103
|
+
right: z<number, number, "volatile-defined">;
|
|
104
|
+
bottom: z<number, number, "volatile-defined">;
|
|
105
|
+
bubbleScale: z<number, number, "volatile-defined">;
|
|
106
|
+
petId: z<string, string, "volatile">;
|
|
107
|
+
enabled: z<boolean, boolean, "volatile-defined">;
|
|
108
|
+
decorationEnabled: z<boolean, boolean, "volatile-defined">;
|
|
109
|
+
}>>, "plain">;
|
|
110
|
+
/**
|
|
111
|
+
* The settings section the pet runs with: the effective values of the row's
|
|
112
|
+
* own config. `fallbackPetId` covers a mount whose config names no pet at all
|
|
113
|
+
* (a direct mount outside a Loader) — under a Loader the schema default is
|
|
114
|
+
* always present, so the persisted selection stands whenever the config
|
|
115
|
+
* carries it.
|
|
116
|
+
* @param config - the effective config of the pet row.
|
|
117
|
+
* @param fallbackPetId - pet id to use when the config names none.
|
|
118
|
+
* @returns the resolved settings section.
|
|
119
|
+
*/
|
|
120
|
+
export declare function petSettingsSection(config: PetFormConfig, fallbackPetId: string): PetSettingsSection;
|
|
62
121
|
/** Register the pet service and its API + asset routes on the context. */
|
|
63
122
|
export declare const apply: typeof applyImpl;
|
|
64
|
-
|
|
123
|
+
/** Plugin config: the tuning block a profile may declare plus the pet's settings fields. */
|
|
124
|
+
export type PetPluginConfig = Omit<PetConfig, 'enabled' | 'decorationEnabled'> & PetFormConfig;
|
|
125
|
+
declare function applyImpl(ctx: Context, config?: PetPluginConfig): void;
|
|
126
|
+
declare module '@deepseek-ai/cordis' {
|
|
127
|
+
interface Events {
|
|
128
|
+
/**
|
|
129
|
+
* Volatile config values were committed into the running fiber without a
|
|
130
|
+
* remount; dispatched to the owning fiber only. Declared by the Loader and
|
|
131
|
+
* restated here because this package carries no dependency on its types.
|
|
132
|
+
*/
|
|
133
|
+
'loader/volatile-update'(paths: readonly (readonly string[])[]): void;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
65
136
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/types/index.js
CHANGED
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
* cordis.patch.yml inserts this plugin row.
|
|
11
11
|
* @module @linxin666/dsh-pet
|
|
12
12
|
*/
|
|
13
|
-
import z from 'schemastery';
|
|
14
|
-
import { PetService
|
|
13
|
+
import z from '@deepseek-ai/schemastery';
|
|
14
|
+
import { PetService } from "./service.js";
|
|
15
15
|
import { makePetRoutes } from "./routes.js";
|
|
16
16
|
import { loadPetRegistry, petPackageRoot } from "./registry.js";
|
|
17
|
-
import { BUBBLE_SCALE_MAX, BUBBLE_SCALE_MIN, DISPLAY_INSET_MAX, DISPLAY_SIZE_MAX, DISPLAY_SIZE_MIN } from "./persist.js";
|
|
17
|
+
import { BUBBLE_SCALE_MAX, BUBBLE_SCALE_MIN, DEFAULT_PET_ID, DISPLAY_INSET_MAX, DISPLAY_SIZE_MAX, DISPLAY_SIZE_MIN } from "./persist.js";
|
|
18
18
|
import { mountOnce } from "./mount-once.js";
|
|
19
19
|
export { PetService, MAX_SESSION_BUBBLES } from "./service.js";
|
|
20
20
|
export { AFFINITY_MAX, AFFINITY_RANKS, applyInteraction, applyTurnReward, emptyAffinity, rankOf, } from "./affinity.js";
|
|
@@ -29,24 +29,80 @@ export const name = 'pet';
|
|
|
29
29
|
/** Services required before the pet can mount its surfaces. */
|
|
30
30
|
export const inject = ['webServer'];
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* a removed pet cannot invalidate the section (a strict union would refuse
|
|
36
|
-
* the whole registration). The settings card renders the actual registry
|
|
37
|
-
* choices itself from '/api/pet/pets'.
|
|
32
|
+
* Defaults of the fields the pet's settings page edits. They are the schema
|
|
33
|
+
* defaults of the pet row's own config, i.e. what a field the profile entry
|
|
34
|
+
* never set resolves to.
|
|
38
35
|
*/
|
|
39
|
-
export
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
export const PET_FORM_DEFAULTS = {
|
|
37
|
+
visible: true,
|
|
38
|
+
size: 160,
|
|
39
|
+
right: 24,
|
|
40
|
+
bottom: 20,
|
|
41
|
+
bubbleScale: 1,
|
|
42
|
+
petId: DEFAULT_PET_ID,
|
|
43
|
+
enabled: true,
|
|
44
|
+
decorationEnabled: true,
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Plugin configuration. Under the 0.1.7 settings model a plugin's own Cordis
|
|
48
|
+
* Config IS its settings page: the Host derives one form per profile entry
|
|
49
|
+
* from this schema, so the fields the pet card edits live here with the
|
|
50
|
+
* defaults the card inherits, next to the tuning block a profile may still
|
|
51
|
+
* declare.
|
|
52
|
+
*
|
|
53
|
+
* Every page field is `volatile()` on purpose. The Host serves exactly the
|
|
54
|
+
* volatile fields of a Config and refuses writes to any other path, and a
|
|
55
|
+
* volatile field is the one it can commit into the RUNNING config: the pet
|
|
56
|
+
* reads the edited value from the live reference instead of being remounted
|
|
57
|
+
* for each edit (see `syncSettings` in `apply`). petId stays a plain string
|
|
58
|
+
* because the service clamps the value against the registry, so a stored
|
|
59
|
+
* selection naming a removed pet cannot invalidate the entry.
|
|
60
|
+
*/
|
|
61
|
+
export const Config = z.object({
|
|
62
|
+
visible: z.boolean().default(PET_FORM_DEFAULTS.visible).volatile(),
|
|
63
|
+
size: z.number().step(1).min(DISPLAY_SIZE_MIN).max(DISPLAY_SIZE_MAX).default(PET_FORM_DEFAULTS.size).volatile(),
|
|
64
|
+
right: z.number().step(1).min(0).max(DISPLAY_INSET_MAX).default(PET_FORM_DEFAULTS.right).volatile(),
|
|
65
|
+
bottom: z.number().step(1).min(0).max(DISPLAY_INSET_MAX).default(PET_FORM_DEFAULTS.bottom).volatile(),
|
|
66
|
+
bubbleScale: z.number().step(0.05).min(BUBBLE_SCALE_MIN).max(BUBBLE_SCALE_MAX).default(PET_FORM_DEFAULTS.bubbleScale).volatile(),
|
|
67
|
+
// An absent profile choice must leave the selection persisted in pet.json
|
|
68
|
+
// intact across restarts (aggregate rows have no served Host pet form).
|
|
69
|
+
petId: z.string().volatile(),
|
|
70
|
+
enabled: z.boolean().default(PET_FORM_DEFAULTS.enabled).volatile(),
|
|
71
|
+
decorationEnabled: z.boolean().default(PET_FORM_DEFAULTS.decorationEnabled).volatile(),
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* Read one live config field.
|
|
75
|
+
* @param field - the field's live reference, plain value, or nothing at all.
|
|
76
|
+
* @param fallback - value used when the field is absent.
|
|
77
|
+
* @returns the current field value.
|
|
78
|
+
*/
|
|
79
|
+
function readLive(field, fallback) {
|
|
80
|
+
if (field === undefined)
|
|
81
|
+
return fallback;
|
|
82
|
+
const ref = field;
|
|
83
|
+
return typeof ref.get === 'function' ? ref.get() ?? fallback : field;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The settings section the pet runs with: the effective values of the row's
|
|
87
|
+
* own config. `fallbackPetId` covers a mount whose config names no pet at all
|
|
88
|
+
* (a direct mount outside a Loader) — under a Loader the schema default is
|
|
89
|
+
* always present, so the persisted selection stands whenever the config
|
|
90
|
+
* carries it.
|
|
91
|
+
* @param config - the effective config of the pet row.
|
|
92
|
+
* @param fallbackPetId - pet id to use when the config names none.
|
|
93
|
+
* @returns the resolved settings section.
|
|
94
|
+
*/
|
|
95
|
+
export function petSettingsSection(config, fallbackPetId) {
|
|
96
|
+
return {
|
|
97
|
+
visible: readLive(config.visible, PET_FORM_DEFAULTS.visible),
|
|
98
|
+
size: readLive(config.size, PET_FORM_DEFAULTS.size),
|
|
99
|
+
right: readLive(config.right, PET_FORM_DEFAULTS.right),
|
|
100
|
+
bottom: readLive(config.bottom, PET_FORM_DEFAULTS.bottom),
|
|
101
|
+
bubbleScale: readLive(config.bubbleScale, PET_FORM_DEFAULTS.bubbleScale),
|
|
102
|
+
petId: readLive(config.petId, fallbackPetId),
|
|
103
|
+
enabled: readLive(config.enabled, PET_FORM_DEFAULTS.enabled),
|
|
104
|
+
decorationEnabled: readLive(config.decorationEnabled, PET_FORM_DEFAULTS.decorationEnabled),
|
|
105
|
+
};
|
|
50
106
|
}
|
|
51
107
|
/** Register the pet service and its API + asset routes on the context. */
|
|
52
108
|
export const apply = mountOnce('@linxin666/dsh-pet', applyImpl);
|
|
@@ -56,24 +112,18 @@ function applyImpl(ctx, config = {}) {
|
|
|
56
112
|
packageRoot: petPackageRoot(import.meta.url),
|
|
57
113
|
...(config.pets === undefined ? {} : { extra: config.pets }),
|
|
58
114
|
});
|
|
59
|
-
const service = new PetService(ctx, {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
right: service.display().right,
|
|
72
|
-
bottom: service.display().bottom,
|
|
73
|
-
petId: service.selectedPetId(),
|
|
74
|
-
enabled: config.enabled ?? true,
|
|
75
|
-
decorationEnabled: config.decorationEnabled ?? true,
|
|
76
|
-
};
|
|
115
|
+
const service = new PetService(ctx, {
|
|
116
|
+
...config,
|
|
117
|
+
enabled: readLive(config.enabled, PET_FORM_DEFAULTS.enabled),
|
|
118
|
+
decorationEnabled: readLive(config.decorationEnabled, PET_FORM_DEFAULTS.decorationEnabled),
|
|
119
|
+
registry,
|
|
120
|
+
});
|
|
121
|
+
// The effective settings ARE this row's own config: the Host serves one form
|
|
122
|
+
// per profile entry from `Config` above, and every edit is committed into the
|
|
123
|
+
// running config, so the plugin re-reads the section here instead of holding
|
|
124
|
+
// a separate settings document (0.1.6 registered one through
|
|
125
|
+
// settings.installSection/register and re-resolved it on every change).
|
|
126
|
+
const current = () => petSettingsSection(config, service.selectedPetId());
|
|
77
127
|
// The browser half talks to the pet through same-origin JSON endpoints and
|
|
78
128
|
// loads each pet's atlas from the registry's own media route (RPC domains
|
|
79
129
|
// are platform-registered, so the pet serves its own API — the same
|
|
@@ -96,34 +146,33 @@ function applyImpl(ctx, config = {}) {
|
|
|
96
146
|
disposeRoutes = undefined;
|
|
97
147
|
}
|
|
98
148
|
};
|
|
149
|
+
// Apply the row's config to the running service: pet.json mirrors the live
|
|
150
|
+
// display the drag / hide / summon interactions write (see
|
|
151
|
+
// syncSettingsFromPet), so a section the settings surface never touched
|
|
152
|
+
// resolves back to exactly what the pet already shows (the composition
|
|
153
|
+
// 'base' of the pre-0.1.7 section).
|
|
154
|
+
const syncSettings = () => {
|
|
155
|
+
const section = current();
|
|
156
|
+
service.applySettingsSection(section);
|
|
157
|
+
service.setEnabled(section.enabled ?? true);
|
|
158
|
+
syncRoutes();
|
|
159
|
+
};
|
|
160
|
+
// A settings edit lands in this row's live config reference and is announced
|
|
161
|
+
// here; the entry is NOT remounted for it, so the pet applies the new section
|
|
162
|
+
// itself (the pre-0.1.7 host ran the section's onChange hook for this).
|
|
163
|
+
ctx.on('loader/volatile-update', () => { syncSettings(); });
|
|
99
164
|
ctx.inject(['settings'], (settingsCtx) => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const section = current();
|
|
107
|
-
service.applySettingsSection(section);
|
|
108
|
-
service.setEnabled(section.enabled ?? true);
|
|
109
|
-
syncRoutes();
|
|
110
|
-
},
|
|
111
|
-
});
|
|
165
|
+
// The pet ships its own settings card (the browser half's
|
|
166
|
+
// 'settings.section' page), so the Host must not also generate a page for
|
|
167
|
+
// this entry from Config.
|
|
168
|
+
settingsCtx.effect(() => {
|
|
169
|
+
try {
|
|
170
|
+
return settingsCtx.settings.configure({ auto: false }, ctx.fiber);
|
|
112
171
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
current = () => scope?.get?.() ?? base;
|
|
116
|
-
scope?.watch?.(() => {
|
|
117
|
-
const section = current();
|
|
118
|
-
service.applySettingsSection(section);
|
|
119
|
-
service.setEnabled(section.enabled ?? true);
|
|
120
|
-
syncRoutes();
|
|
121
|
-
});
|
|
172
|
+
catch {
|
|
173
|
+
return () => { };
|
|
122
174
|
}
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
// Defensive fallback against settings registration differences
|
|
126
|
-
}
|
|
175
|
+
}, 'pet: settings page policy');
|
|
127
176
|
});
|
|
128
|
-
|
|
177
|
+
syncSettings();
|
|
129
178
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/persist.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAEpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhE,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,oBAAoB,EAAE,gBAMlC,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAClC,eAAO,MAAM,gBAAgB,OAAO,CAAA;AACpC,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAEvC,8CAA8C;AAC9C,eAAO,MAAM,gBAAgB,MAAM,CAAA;AACnC,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,MAAM,CAAA;AACtC,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,KAAK,CAAA;AACpC,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAWzG;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,aAAa,CAAA;IACvB,gCAAgC;IAChC,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,gBAAgB,CAAA;IACzB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAC3C;AAED,wBAAwB;AACxB,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,YAAY,IAAI,UAAU,CAUzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;
|
|
1
|
+
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/persist.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAEpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhE,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,oBAAoB,EAAE,gBAMlC,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAClC,eAAO,MAAM,gBAAgB,OAAO,CAAA;AACpC,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAEvC,8CAA8C;AAC9C,eAAO,MAAM,gBAAgB,MAAM,CAAA;AACnC,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,MAAM,CAAA;AACtC,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,KAAK,CAAA;AACpC,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAWzG;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,aAAa,CAAA;IACvB,gCAAgC;IAChC,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,gBAAgB,CAAA;IACzB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAC3C;AAED,wBAAwB;AACxB,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,YAAY,IAAI,UAAU,CAUzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAqFD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAqB,GAAG,UAAU,CAuDrE;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,GAAE,MAAqB,GAAG,IAAI,CAMjF"}
|
package/lib/types/persist.js
CHANGED
|
@@ -146,7 +146,9 @@ function loadGameplay(parsed) {
|
|
|
146
146
|
const item = {
|
|
147
147
|
stats,
|
|
148
148
|
currencies,
|
|
149
|
-
|
|
149
|
+
// Any non-empty id survives the round trip; whether it is still declared
|
|
150
|
+
// is settled against the manifest when the mode is read back.
|
|
151
|
+
mode: typeof record.mode === 'string' && record.mode.length > 0 && record.mode.length <= 24 ? record.mode : null,
|
|
150
152
|
settledAt: clamp(finiteNum(record.settledAt, 0), Number.MAX_SAFE_INTEGER),
|
|
151
153
|
};
|
|
152
154
|
if (typeof record.incomeCarryMs === 'number' && Number.isFinite(record.incomeCarryMs)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAO9C,+CAA+C;AAC/C,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,SAAS,CAAA;AAMtC;;;;GAIG;AACH,eAAO,MAAM,cAAc;IACzB,yBAAyB;;IAEzB,iDAAiD;;IAEjD,8EAA8E;;CAEtE,CAAA;AAEV,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAsBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAcrF;AAqPD,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,QAA8B,CAAA;AAe7D,4EAA4E;AAC5E,eAAO,MAAM,eAAe,QAAmB,CAAA;AAE/C,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA4MD,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,YAAY,CAAA;CAAE,GAAG,eAAe,GAAG,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAO9C,+CAA+C;AAC/C,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,SAAS,CAAA;AAMtC;;;;GAIG;AACH,eAAO,MAAM,cAAc;IACzB,yBAAyB;;IAEzB,iDAAiD;;IAEjD,8EAA8E;;CAEtE,CAAA;AAEV,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAsBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAcrF;AAqPD,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,QAA8B,CAAA;AAe7D,4EAA4E;AAC5E,eAAO,MAAM,eAAe,QAAmB,CAAA;AAE/C,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA4MD,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,YAAY,CAAA;CAAE,GAAG,eAAe,GAAG,QAAQ,EAAE,CAuFjI;AAGD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
|
package/lib/types/routes.js
CHANGED
|
@@ -609,7 +609,9 @@ export function makePetRoutes(deps) {
|
|
|
609
609
|
}),
|
|
610
610
|
postRoute(ctx, PET_API_PREFIX + '/gameplay/mode', (body) => {
|
|
611
611
|
const mode = body.mode;
|
|
612
|
-
|
|
612
|
+
// The id is checked against the pet's own mode set in the service (work,
|
|
613
|
+
// sleep, or any declared 'modes' entry).
|
|
614
|
+
if (mode !== null && typeof mode !== 'string')
|
|
613
615
|
return Promise.reject(new Error('invalid-mode'));
|
|
614
616
|
return service.gameplaySetMode(mode);
|
|
615
617
|
}),
|
package/lib/types/service.d.ts
CHANGED
|
@@ -157,7 +157,8 @@ export type PetInteractResult = LedgerInteractionResult;
|
|
|
157
157
|
export interface PetGameplayStateView {
|
|
158
158
|
/** Stat values rounded for display. */
|
|
159
159
|
stats: Record<string, number>;
|
|
160
|
-
mode
|
|
160
|
+
/** Active mode id ('work' | 'sleep' | a declared extra mode) or null. */
|
|
161
|
+
mode: string | null;
|
|
161
162
|
}
|
|
162
163
|
/** Result of the gameplay verbs (touch / setMode / workTick / buy). */
|
|
163
164
|
export interface PetGameplayVerbResult {
|
|
@@ -305,8 +306,12 @@ export declare class PetService extends Service {
|
|
|
305
306
|
* omitted means a plain click while a touch animation holds (clickBoost).
|
|
306
307
|
*/
|
|
307
308
|
gameplayTouch(zone?: string): Promise<PetGameplayVerbResult>;
|
|
308
|
-
/**
|
|
309
|
-
|
|
309
|
+
/**
|
|
310
|
+
* RPC: enter or leave a gameplay mode (null clears it). Every mode the
|
|
311
|
+
* manifest declares is accepted: 'work', 'sleep', or one of the extra
|
|
312
|
+
* 'modes' entries (a bath, a play session…).
|
|
313
|
+
*/
|
|
314
|
+
gameplaySetMode(mode: string | null): Promise<PetGameplayVerbResult>;
|
|
310
315
|
/** RPC: one work-round adjudication (only while the work mode holds). */
|
|
311
316
|
gameplayWorkTick(): Promise<PetGameplayVerbResult>;
|
|
312
317
|
/** RPC: buy one shop item (effects, currency swap, or a lottery draw). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGtD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACpF,OAAO,EAAwC,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAC1F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAS9C,OAAO,EAAgC,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACxF,OAAO,EAWL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAA;AAGtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAA;AACtE,OAAO,EAGL,KAAK,cAAc,EAEnB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"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"}
|
package/lib/types/service.js
CHANGED
|
@@ -20,7 +20,7 @@ import { DEFAULT_DECORATION_ID, decorationView, loadPetRegistry, petEntryView, p
|
|
|
20
20
|
import { WHISPER_TTL_MS } from "./chatter.js";
|
|
21
21
|
import { mergeVoicePacks } from "./voice-pack.js";
|
|
22
22
|
import { defaultPetStateConfig, PetStateMachine, } from "./state.js";
|
|
23
|
-
import { applyGameplayEffects, drawLotteryTier, initialGameplayState, rollTouchBranch, rollWorkOutcome, settleGameplay, } from "./gameplay.js";
|
|
23
|
+
import { applyGameplayEffects, drawLotteryTier, initialGameplayState, isDeclaredMode, rollTouchBranch, rollWorkOutcome, settleGameplay, } from "./gameplay.js";
|
|
24
24
|
/** The unified gameplay currency: the shared treat (小鱼干) ledger. */
|
|
25
25
|
const GAMEPLAY_TREATS_CURRENCY = 'treats';
|
|
26
26
|
/** Settings namespace of the pet capability. Spelled here rather than imported: the browser half spells the same value. */
|
|
@@ -344,7 +344,12 @@ export class PetService extends Service {
|
|
|
344
344
|
petId,
|
|
345
345
|
state: stored === undefined
|
|
346
346
|
? initialGameplayState(def, now)
|
|
347
|
-
|
|
347
|
+
// Spread first so the settle remainders (restoreCarryMs / incomeCarryMs)
|
|
348
|
+
// survive a verb. Enumerating the fields dropped them, so every verb
|
|
349
|
+
// floored the elapsed time and threw the remainder away -- which starves
|
|
350
|
+
// any interval longer than the gap between verbs (30 s sleep restore,
|
|
351
|
+
// 30 min passive income).
|
|
352
|
+
: { ...stored, stats: { ...stored.stats }, currencies: { ...stored.currencies } },
|
|
348
353
|
};
|
|
349
354
|
}
|
|
350
355
|
/** Display view of one gameplay state (rounded stats; treats ride the shared treat ledger). */
|
|
@@ -352,7 +357,14 @@ export class PetService extends Service {
|
|
|
352
357
|
const stats = {};
|
|
353
358
|
for (const [name, value] of Object.entries(state.stats))
|
|
354
359
|
stats[name] = Math.round(value);
|
|
355
|
-
|
|
360
|
+
// A persisted mode the manifest no longer declares (a pet.json edit after
|
|
361
|
+
// the pet was parked in it) reads as "no mode". Otherwise the client would
|
|
362
|
+
// latch a mode it cannot resolve: the mode chip prints a raw i18n key, and
|
|
363
|
+
// the client's roam roll — suppressed while any mode is active — would
|
|
364
|
+
// never fire again.
|
|
365
|
+
const def = this.gameplayDef();
|
|
366
|
+
const mode = state.mode !== null && def !== undefined && !isDeclaredMode(def, state.mode) ? null : state.mode;
|
|
367
|
+
return { stats, mode };
|
|
356
368
|
}
|
|
357
369
|
/**
|
|
358
370
|
* Move gameplay 'treats' currency (the unified post-wallet currency) from
|
|
@@ -419,7 +431,11 @@ export class PetService extends Service {
|
|
|
419
431
|
view: this.gameplayViewOf(state),
|
|
420
432
|
};
|
|
421
433
|
}
|
|
422
|
-
/**
|
|
434
|
+
/**
|
|
435
|
+
* RPC: enter or leave a gameplay mode (null clears it). Every mode the
|
|
436
|
+
* manifest declares is accepted: 'work', 'sleep', or one of the extra
|
|
437
|
+
* 'modes' entries (a bath, a play session…).
|
|
438
|
+
*/
|
|
423
439
|
async gameplaySetMode(mode) {
|
|
424
440
|
const def = this.gameplayDef();
|
|
425
441
|
if (def === undefined)
|
|
@@ -428,9 +444,15 @@ export class PetService extends Service {
|
|
|
428
444
|
return { ok: false, error: 'no-work' };
|
|
429
445
|
if (mode === 'sleep' && def.sleep === undefined)
|
|
430
446
|
return { ok: false, error: 'no-sleep' };
|
|
447
|
+
if (mode !== null && !isDeclaredMode(def, mode))
|
|
448
|
+
return { ok: false, error: 'unknown-mode' };
|
|
431
449
|
const now = Date.now();
|
|
432
450
|
const { petId, state } = this.gameplayState(def, now);
|
|
433
451
|
settleGameplay(state, def, now, { sessionActive: this.machine.render().sessionActive });
|
|
452
|
+
// Switching modes restarts the restore cadence: a leftover carry from the
|
|
453
|
+
// previous mode must not advance the new mode's first tick.
|
|
454
|
+
if (state.mode !== mode)
|
|
455
|
+
state.restoreCarryMs = 0;
|
|
434
456
|
state.mode = mode;
|
|
435
457
|
this.drainGameplayTreats(state);
|
|
436
458
|
this.commitGameplay(petId, state);
|