diff --git a/packages-user/data-base/src/hero/attribute.ts b/packages-user/data-base/src/hero/attribute.ts index 34b146e..f3691aa 100644 --- a/packages-user/data-base/src/hero/attribute.ts +++ b/packages-user/data-base/src/hero/attribute.ts @@ -43,8 +43,11 @@ export abstract class BaseHeroModifier implements IHeroModifier { export class HeroAttribute implements IHeroAttribute { /** 当前勇士属性修饰器 */ private readonly modifier: Map = new Map(); - /** 当前每个修饰器对应的属性值 */ - private readonly modifierName: Map = new Map(); + /** 当前每个修饰器对应的属性名称 */ + private readonly modifierName: Map< + IHeroModifier, + keyof THero + > = new Map(); /** 当前勇士最终属性 */ private readonly finalAttribute: THero; @@ -144,7 +147,7 @@ export class HeroAttribute implements IHeroAttribute { addModifier( name: K, - modifier: IHeroModifier + modifier: IHeroModifier ): void { if (modifier.owner) { const modiferName = modifier.constructor.name; @@ -181,7 +184,7 @@ export class HeroAttribute implements IHeroAttribute { this.recalculateAttribute(name); } - markModifierDirty(modifier: IHeroModifier): void { + markModifierDirty(modifier: IHeroModifier): void { const name = this.modifierName.get(modifier); if (name === undefined) return; this.markDirty(name); @@ -210,9 +213,16 @@ export class HeroAttribute implements IHeroAttribute { return structuredClone(this.attribute); } - *iterateModifiers(): IterableIterator<[keyof THero, IHeroModifier]> { + *iterateModifiers(): IterableIterator<[PropertyKey, IHeroModifier]> { for (const [modifier, name] of this.modifierName) { yield [name, modifier]; } } + + getModifiers( + name: K + ): Iterable> { + const arr = this.modifier.get(name) as IHeroModifier[]; + return arr ?? []; + } } diff --git a/packages-user/data-base/src/hero/follower.ts b/packages-user/data-base/src/hero/follower.ts index cf4f002..ec8716e 100644 --- a/packages-user/data-base/src/hero/follower.ts +++ b/packages-user/data-base/src/hero/follower.ts @@ -65,6 +65,7 @@ export class HeroFollower implements IHeroFollower { saveState(compression: SaveCompression): IHeroFollowerSave { return { + num: this.num, rendering: this.rendering.saveState(compression), location: this.location.saveState(compression) }; diff --git a/packages-user/data-base/src/hero/state.ts b/packages-user/data-base/src/hero/state.ts index 9e45d56..7f865b6 100644 --- a/packages-user/data-base/src/hero/state.ts +++ b/packages-user/data-base/src/hero/state.ts @@ -1,39 +1,66 @@ import { HeroAttribute } from './attribute'; +import { HeroFollowersController } from './followersController'; +import { HeroLocation } from './location'; +import { HeroRendering } from './rendering'; import { IHeroAttribute, + IHeroFollowersController, + IHeroLocation, IHeroModifier, - IHeroMoveController, + IHeroRendering, IHeroState, IHeroStateSave, IModifierStateSave, IReadonlyHeroAttribute } from './types'; -import { SaveCompression } from '@user/data-common'; +import { + FaceDirection, + IDataCommon, + IFaceHandler, + SaveCompression +} from '@user/data-common'; import { IFacedTileLocator, logger } from '@motajs/common'; export class HeroState implements IHeroState { /** 修饰器工厂函数注册表 */ - private readonly registry: Map IHeroModifier> = new Map(); + private readonly registry: Map< + string, + () => IHeroModifier + > = new Map(); + + readonly location: IHeroLocation; + readonly rendering: IHeroRendering; + readonly followers: IHeroFollowersController; constructor( - public mover: IHeroMoveController, + state: IDataCommon, + faceHandler: IFaceHandler, public attribute: IHeroAttribute - ) {} - - attachMover(mover: IHeroMoveController): void { - this.mover = mover; + ) { + this.rendering = new HeroRendering(state); + const defaultLoc: IFacedTileLocator = { + x: 0, + y: 0, + direction: FaceDirection.Down + }; + this.location = new HeroLocation(state, defaultLoc, faceHandler); + this.followers = new HeroFollowersController( + state, + this.location, + faceHandler + ); } attachAttribute(attribute: IHeroAttribute): void { this.attribute = attribute; } - getHeroMover(): IHeroMoveController { - return this.mover; - } - getLocation(): IFacedTileLocator { - return this.mover; + return { + x: this.location.x, + y: this.location.y, + direction: this.location.mover.faceDirection + }; } getModifiableAttribute(): IHeroAttribute { @@ -48,7 +75,10 @@ export class HeroState implements IHeroState { return this.attribute.getModifiableClone(); } - registerModifier(type: string, cons: () => IHeroModifier): void { + registerModifier( + type: string, + cons: () => IHeroModifier + ): void { this.registry.set(type, cons); } @@ -57,9 +87,8 @@ export class HeroState implements IHeroState { if (!cons) { logger.warn(116, type); return null; - } else { - return cons() as IHeroModifier; } + return cons() as IHeroModifier; } createAndInsertModifier( @@ -73,22 +102,23 @@ export class HeroState implements IHeroState { } saveState(compression: SaveCompression): IHeroStateSave { - const modifiers: IModifierStateSave[] = []; + const modifiers: IModifierStateSave[] = []; for (const [name, modifier] of this.attribute.iterateModifiers()) { modifiers.push({ - name, + name: name as keyof THero, type: modifier.type, state: modifier.saveState(compression) }); } + const followerSaves = this.followers + .getAllFollowers() + .map(v => v.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), + location: this.location.saveState(compression), + rendering: this.rendering.saveState(compression), + followers: followerSaves, modifiers }; } @@ -102,19 +132,16 @@ export class HeroState implements IHeroState { 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 - ); + modifier.loadState(save.state, compression); + newAttribute.addModifier(save.name, modifier); } 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); - }); + this.location.loadState(state.location, compression); + this.rendering.loadState(state.rendering, compression); + void this.followers.removeAllFollowers(); + for (const save of state.followers) { + const follower = this.followers.addFollower(save.num); + follower.loadState(save, compression); + } } } diff --git a/packages-user/data-base/src/hero/types.ts b/packages-user/data-base/src/hero/types.ts index 99f5a85..ffc87e5 100644 --- a/packages-user/data-base/src/hero/types.ts +++ b/packages-user/data-base/src/hero/types.ts @@ -9,9 +9,9 @@ import { //#region 勇士属性 export interface IHeroModifier< - K = unknown, - V = unknown, - Save = unknown + H = unknown, // 属性值类型 + V = unknown, // 修饰器参数类型 + Save = unknown // 存档类型 > extends ISaveableContent { /** 修饰器类型 */ readonly type: string; @@ -45,17 +45,17 @@ export interface IHeroModifier< * @param baseValue 该属性值的基础属性值 * @param name 属性名称 */ - modify(value: K, baseValue: K, name: PropertyKey): K; + modify(value: H, baseValue: H, name: PropertyKey): H; /** * 深拷贝此修饰器 */ - clone(): IHeroModifier; + clone(): IHeroModifier; } -export interface IModifierStateSave { +export interface IModifierStateSave { /** 属性名称 */ - readonly name: PropertyKey; + readonly name: keyof THero; /** 修饰器类型 */ readonly type: string; /** 修饰器存档数据 */ @@ -107,6 +107,14 @@ export interface IReadonlyHeroAttribute { * 遍历所有已挂载的属性修饰器 */ iterateModifiers(): Iterable<[PropertyKey, IHeroModifier]>; + + /** + * 获取指定属性名称的所有修饰器 + * @param name 属性名称 + */ + getModifiers( + name: K + ): Iterable>; } export interface IHeroAttribute extends IReadonlyHeroAttribute { @@ -263,6 +271,8 @@ export interface IHeroRendering //#region 勇士跟随者 export interface IHeroFollowerSave { + /** 跟随者图块数字 */ + readonly num: number; /** 跟随者渲染对象保存 */ readonly rendering: IHeroRenderingSave; /** 跟随者位置保存 */ @@ -369,11 +379,13 @@ export interface IHeroStateSave { /** 勇士属性状态 */ readonly attribute: THero; /** 勇士当前位置 */ - readonly locator: IHeroLocationSave; + readonly location: IHeroLocationSave; + /** 勇士渲染状态 */ + readonly rendering: IHeroRenderingSave; /** 勇士当前的跟随者 */ readonly followers: readonly IHeroFollowerSave[]; /** 勇士属性修饰器状态 */ - readonly modifiers: readonly IModifierStateSave[]; + readonly modifiers: readonly IModifierStateSave[]; } export interface IHeroState extends ISaveableContent< diff --git a/packages-user/data-system/src/combat/types.ts b/packages-user/data-system/src/combat/types.ts index ec45622..8ef1ecd 100644 --- a/packages-user/data-system/src/combat/types.ts +++ b/packages-user/data-system/src/combat/types.ts @@ -700,7 +700,7 @@ export interface IEnemyContext extends IReadonlyEnemyContext< * 绑定伤害计算系统 * @param system 伤害系统 */ - attachDamageSystem(system: IDamageSystem | null): void; + attachDamageSystem(system: IDamageSystem | null): void; /** * 重建当前上下文中的全部怪物计算结果