import { HeroAttribute } from './attribute'; import { IHeroAttribute, IHeroModifier, IHeroMover, IHeroState, IHeroStateSave, IModifierStateSave, IReadonlyHeroAttribute } from './types'; import { SaveCompression } from '../common'; import { logger } from '@motajs/common'; export class HeroState implements IHeroState { /** 修饰器工厂函数注册表 */ private readonly registry: Map IHeroModifier> = new Map(); constructor( public mover: IHeroMover, public attribute: IHeroAttribute ) {} attachMover(mover: IHeroMover): void { this.mover = mover; } attachAttribute(attribute: IHeroAttribute): void { this.attribute = attribute; } getHeroMover(): IHeroMover { return this.mover; } getModifiableAttribute(): IHeroAttribute { return this.attribute; } getAttribute(): IReadonlyHeroAttribute { return this.attribute; } getIsolatedAttribute(): IHeroAttribute { return this.attribute.getModifiableClone(); } registerModifier(type: string, cons: () => IHeroModifier): void { this.registry.set(type, cons); } createModifier(type: string): IHeroModifier | null { const cons = this.registry.get(type); if (!cons) { logger.warn(116, type); return null; } else { return cons() as IHeroModifier; } } createAndInsertModifier( type: string, name: K ): IHeroModifier | null { const modifier = this.createModifier(type); if (!modifier) return null; this.attribute.addModifier(name, modifier); return modifier; } saveState(compression: SaveCompression): IHeroStateSave { const modifiers: IModifierStateSave[] = []; for (const [name, modifier] of this.attribute.iterateModifiers()) { modifiers.push({ name, type: modifier.type, state: modifier.saveState(compression) }); } return { attribute: this.attribute.toStructured(), locator: { x: this.mover.x, y: this.mover.y, direction: this.mover.direction }, followers: structuredClone(this.mover.followers), modifiers }; } loadState( state: IHeroStateSave, compression: SaveCompression ): void { const newAttribute = new HeroAttribute(state.attribute); for (const save of state.modifiers) { const cons = this.registry.get(save.type); if (!cons) continue; const modifier = cons(); modifier.loadState(save.state as never, compression); newAttribute.addModifier( save.name as keyof THero, modifier as unknown as IHeroModifier ); } this.attribute = newAttribute; this.mover.setPosition(state.locator.x, state.locator.y); this.mover.turn(state.locator.direction); this.mover.removeAllFollowers(); state.followers.forEach(follower => { this.mover.addFollower(follower.num, follower.identifier); this.mover.setFollowerAlpha(follower.identifier, follower.alpha); }); } }