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:
@@ -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) } : {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { test } from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { PlayerStore } from '../../YouleNexus/assets/framework/platform/stores/player-store.ts';
|
||||||
|
|
||||||
|
const RAW = { state: 0, playerid: 430511, nickname: '测试号', avatar: 'http://a', sex: 0,
|
||||||
|
bean: 0, roomcard: 3, score: 0, taskstate: 1, advanced: 0, bankpower: 1, bank: 0, bankpwd: 0,
|
||||||
|
ip: '127.0.0.1', sign: null, tel: null, invitecode: null, initCard: '3', initBean: '0',
|
||||||
|
openid: 'o1', unionid: 'u1', province: 'p', city: 'c' };
|
||||||
|
|
||||||
|
test('applyLogin 填充 PlayerState 并通知订阅者', () => {
|
||||||
|
const store = new PlayerStore();
|
||||||
|
let notified = 0;
|
||||||
|
store.state.subscribe(() => { notified++; });
|
||||||
|
store.applyLogin(RAW as any);
|
||||||
|
const v = store.state.value;
|
||||||
|
assert.equal(v.playerid, 430511);
|
||||||
|
assert.equal(v.nickname, '测试号');
|
||||||
|
assert.equal(v.roomcard, 3);
|
||||||
|
assert.equal(v.taskstate, 1);
|
||||||
|
assert.equal(v.openid, 'o1');
|
||||||
|
assert.equal(v.initCard, '3');
|
||||||
|
assert.equal(notified, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('charm 等缺省字段补默认 0', () => {
|
||||||
|
const store = new PlayerStore();
|
||||||
|
store.applyLogin(RAW as any);
|
||||||
|
assert.equal(store.state.value.charm, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('未下发的可选字段(openid 等)缺省时不写入', () => {
|
||||||
|
const store = new PlayerStore();
|
||||||
|
store.applyLogin({ state: 0, playerid: 1 } as any);
|
||||||
|
assert.equal(store.state.value.openid, undefined);
|
||||||
|
assert.equal(store.state.value.playerid, 1);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user