feat(framework): platform PlayerStore(=C_Player) applyLogin

Implement PlayerStore wrapping signal<PlayerState> for player account data.
Adds applyLogin(raw) to fill state from login response A group, with:
- Mandatory fields get default 0/'' if missing (never undefined)
- Optional fields (openid/unionid/province/city) only set if present
- Immutable updates via spread operator
- Notifies subscribers on state change

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 22:06:06 +08:00
co-authored by Claude Opus 4.8
parent 7659e1fac5
commit 4b4e2261b4
2 changed files with 74 additions and 0 deletions
@@ -0,0 +1,38 @@
import { signal, type ReadonlyReactive } from '../../core/reactive.ts';
import type { PlayerState } from './types.ts';
import type { ReadonlyPlayerStore } from '../readonly.ts';
import type { LoginResponseData } from '../../core/types/login.ts';
const INITIAL: PlayerState = {
playerid: 0, nickname: '', avatar: '', sex: 0,
bean: 0, roomcard: 0, score: 0, charm: 0,
taskstate: 0, advanced: 0,
bankpower: 0, bank: 0, bankpwd: 0,
ip: '', sign: null, tel: null,
invitecode: null, initCard: 0, initBean: 0,
};
/** 玩家自身状态(= 旧 C_Player)。 */
export class PlayerStore implements ReadonlyPlayerStore {
private s = signal<PlayerState>({ ...INITIAL });
get state(): ReadonlyReactive<PlayerState> { return this.s; }
/** 从 login 响应 A 组填充。字段名对齐 protocol/04(直接取服务器下发值)。 */
applyLogin(raw: LoginResponseData): void {
const r = raw as any;
this.s.value = {
...this.s.value,
playerid: r.playerid ?? 0,
nickname: r.nickname ?? '', avatar: r.avatar ?? '', sex: r.sex ?? 0,
bean: r.bean ?? 0, roomcard: r.roomcard ?? 0, score: r.score ?? 0, charm: r.charm ?? 0,
taskstate: r.taskstate ?? 0, advanced: r.advanced ?? 0,
bankpower: r.bankpower ?? 0, bank: r.bank ?? 0, bankpwd: r.bankpwd ?? 0,
ip: r.ip ?? '', sign: r.sign ?? null, tel: r.tel ?? null,
invitecode: r.invitecode ?? null, initCard: r.initCard ?? 0, initBean: r.initBean ?? 0,
...(r.openid != null ? { openid: String(r.openid) } : {}),
...(r.unionid != null ? { unionid: r.unionid } : {}),
...(r.province != null ? { province: String(r.province) } : {}),
...(r.city != null ? { city: String(r.city) } : {}),
};
}
}