fix(chess): fire preset lifecycle hooks on game.presets sync
PredictionManager.applyPresets was calling activePresets.replaceAll directly, bypassing preset onActivate / onDeactivate hooks on the client engine. piece-hp installs Hp facts from onActivate, so in multiplayer the client knew the preset was active but had no Hp facts to render \u2014 the overlay silently drew nothing. Routed through setActivePresets. Both server and client now run the same idempotent onActivate, arriving at the same state without serializing Hp facts over the wire. applyFullState (snapshot path) still uses bare replaceAll because facts in the snapshot already include any preset-installed attributes.
This commit is contained in:
parent
f4e030b8e5
commit
2739cc2689
1 changed files with 14 additions and 1 deletions
|
|
@ -130,10 +130,23 @@ export class PredictionManager {
|
|||
* previously-legal optimistic moves, and re-validating them here would
|
||||
* duplicate server logic. Simpler to let the next user action
|
||||
* re-predict against the freshly-synced base.
|
||||
*
|
||||
* We route through `setActivePresets` (not bare `activePresets.replaceAll`)
|
||||
* so preset `onActivate` / `onDeactivate` lifecycle hooks fire on the
|
||||
* client's base engine. That's essential for rules like `piece-hp`
|
||||
* which install per-piece state (Hp facts) from onActivate — without
|
||||
* this the client would know the preset is active but have no Hp
|
||||
* facts to render, because `game.presets` carries only the
|
||||
* activation list, not the resulting facts.
|
||||
*
|
||||
* Idempotence guarantee: preset hooks are expected to be idempotent
|
||||
* (piece-hp.onActivate only inserts Hp when absent). Server and
|
||||
* client run the same hook logic, so both arrive at the same state.
|
||||
* The next `game.state` or `game.delta` reconciles any drift.
|
||||
*/
|
||||
private applyPresets(payload: GamePresetsPayload): void {
|
||||
try {
|
||||
this.baseEngine.activePresets.replaceAll(payload.activations);
|
||||
this.baseEngine.setActivePresets(payload.activations);
|
||||
} catch {
|
||||
// A bad set from the server shouldn't crash the client; the server
|
||||
// already validated, so this branch is defensive only. We clear
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue