mirror of
https://github.com/motajs/template.git
synced 2026-07-17 09:21:09 +08:00
refactor: 合并 follower 和 followersController
This commit is contained in:
parent
867a3c480f
commit
3e150c4a1d
@ -1,4 +1,10 @@
|
||||
import { IFacedTileLocator, logger } from '@motajs/common';
|
||||
import {
|
||||
Hookable,
|
||||
HookController,
|
||||
IFacedTileLocator,
|
||||
IHookController,
|
||||
logger
|
||||
} from '@motajs/common';
|
||||
import {
|
||||
FaceDirection,
|
||||
IDataCommon,
|
||||
@ -11,6 +17,7 @@ import {
|
||||
IHeroFollower,
|
||||
IHeroFollowerSave,
|
||||
IHeroFollowersController,
|
||||
IHeroFollowersControllerHooks,
|
||||
IHeroLocation,
|
||||
IHeroRendering
|
||||
} from './types';
|
||||
@ -76,3 +83,135 @@ export class HeroFollower implements IHeroFollower {
|
||||
this.location.loadState(state.location, compression);
|
||||
}
|
||||
}
|
||||
|
||||
export class HeroFollowersController
|
||||
extends Hookable<IHeroFollowersControllerHooks>
|
||||
implements IHeroFollowersController
|
||||
{
|
||||
readonly state: IDataCommon;
|
||||
/** 跟随者列表 */
|
||||
private readonly followers: HeroFollower[] = [];
|
||||
/** 勇士位置对象,用于获取聚集目标位置 */
|
||||
private readonly heroLocation: IHeroLocation;
|
||||
/** 朝向处理器,传递给新创建的跟随者 */
|
||||
private readonly faceHandler: IFaceHandler<FaceDirection>;
|
||||
|
||||
constructor(
|
||||
state: IDataCommon,
|
||||
heroLocation: IHeroLocation,
|
||||
faceHandler: IFaceHandler<FaceDirection>
|
||||
) {
|
||||
super();
|
||||
this.state = state;
|
||||
this.heroLocation = heroLocation;
|
||||
this.faceHandler = faceHandler;
|
||||
}
|
||||
|
||||
protected createController(
|
||||
hook: Partial<IHeroFollowersControllerHooks>
|
||||
): IHookController<IHeroFollowersControllerHooks> {
|
||||
return new HookController(this, hook);
|
||||
}
|
||||
|
||||
addFollower(num: number | string): IHeroFollower {
|
||||
const loc: IFacedTileLocator = {
|
||||
x: this.heroLocation.x,
|
||||
y: this.heroLocation.y,
|
||||
direction: this.heroLocation.mover.faceDirection
|
||||
};
|
||||
const follower = new HeroFollower(num, loc, this.faceHandler, this);
|
||||
this.followers.push(follower);
|
||||
const index = this.followers.length - 1;
|
||||
this.forEachHook(hook => {
|
||||
hook.onAddFollower?.(follower, index);
|
||||
});
|
||||
return follower;
|
||||
}
|
||||
|
||||
getFollower(index: number): IHeroFollower | null {
|
||||
return this.followers[index] ?? null;
|
||||
}
|
||||
|
||||
*getFollowersById(
|
||||
num: number | string
|
||||
): IterableIterator<[number, IHeroFollower]> {
|
||||
const store = this.state.tileStore;
|
||||
const target = typeof num === 'string' ? store.idToNumber(num)! : num;
|
||||
for (let i = 0; i < this.followers.length; i++) {
|
||||
if (this.followers[i].num === target) {
|
||||
yield [i, this.followers[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getAllFollowers(): IHeroFollower[] {
|
||||
return this.followers.slice();
|
||||
}
|
||||
|
||||
async removeFollower(index: number): Promise<void> {
|
||||
const removed = this.followers.splice(index, 1);
|
||||
if (removed.length > 0) {
|
||||
this.forEachHook(hook => {
|
||||
hook.onRemoveFollower?.(removed[0], index);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async removeAllFollowers(): Promise<void> {
|
||||
const snapshot = this.followers.slice();
|
||||
this.followers.length = 0;
|
||||
this.forEachHook(hook => {
|
||||
snapshot.forEach((v, i) => {
|
||||
hook.onRemoveFollower?.(v, i);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async gatherFollowers(): Promise<void> {
|
||||
const { x, y, mover } = this.heroLocation;
|
||||
|
||||
for (let i = 0; i < this.followers.length; i++) {
|
||||
const follower = this.followers[i];
|
||||
follower.location.mover.clear();
|
||||
|
||||
let skip = false;
|
||||
for (let j = i - 1; j >= 0; j--) {
|
||||
const dir = this.followers[j].location.mover.moveDirection;
|
||||
if (dir === FaceDirection.Unknown) {
|
||||
follower.location.mover.clear();
|
||||
follower.location.mover.tp(x, y);
|
||||
follower.location.mover.face(mover.faceDirection);
|
||||
skip = true;
|
||||
break;
|
||||
} else {
|
||||
follower.location.mover.step(dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
follower.location.mover.step(mover.moveDirection);
|
||||
}
|
||||
}
|
||||
|
||||
const controllers = this.followers.map(
|
||||
v => v.location.mover.start()?.onEnd
|
||||
);
|
||||
await Promise.all(controllers);
|
||||
this.forEachHook(hook => {
|
||||
hook.onGatherFollowers?.(false);
|
||||
});
|
||||
}
|
||||
|
||||
gatherFollowersSync(): void {
|
||||
const { x, y } = this.heroLocation;
|
||||
const dir = this.heroLocation.mover.faceDirection;
|
||||
for (const follower of this.followers) {
|
||||
const mover = follower.location.mover;
|
||||
mover.setPos(x, y);
|
||||
mover.setFaceDir(dir);
|
||||
}
|
||||
this.forEachHook(hook => {
|
||||
hook.onGatherFollowers?.(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,146 +0,0 @@
|
||||
import {
|
||||
Hookable,
|
||||
HookController,
|
||||
IFacedTileLocator,
|
||||
IHookController
|
||||
} from '@motajs/common';
|
||||
import { FaceDirection, IDataCommon, IFaceHandler } from '@user/data-common';
|
||||
import { HeroFollower } from './follower';
|
||||
import {
|
||||
IHeroFollowersController,
|
||||
IHeroFollowersControllerHooks,
|
||||
IHeroFollower,
|
||||
IHeroLocation
|
||||
} from './types';
|
||||
|
||||
export class HeroFollowersController
|
||||
extends Hookable<IHeroFollowersControllerHooks>
|
||||
implements IHeroFollowersController
|
||||
{
|
||||
readonly state: IDataCommon;
|
||||
/** 跟随者列表 */
|
||||
private readonly followers: HeroFollower[] = [];
|
||||
/** 勇士位置对象,用于获取聚集目标位置 */
|
||||
private readonly heroLocation: IHeroLocation;
|
||||
/** 朝向处理器,传递给新创建的跟随者 */
|
||||
private readonly faceHandler: IFaceHandler<FaceDirection>;
|
||||
|
||||
constructor(
|
||||
state: IDataCommon,
|
||||
heroLocation: IHeroLocation,
|
||||
faceHandler: IFaceHandler<FaceDirection>
|
||||
) {
|
||||
super();
|
||||
this.state = state;
|
||||
this.heroLocation = heroLocation;
|
||||
this.faceHandler = faceHandler;
|
||||
}
|
||||
|
||||
protected createController(
|
||||
hook: Partial<IHeroFollowersControllerHooks>
|
||||
): IHookController<IHeroFollowersControllerHooks> {
|
||||
return new HookController(this, hook);
|
||||
}
|
||||
|
||||
addFollower(num: number | string): IHeroFollower {
|
||||
const loc: IFacedTileLocator = {
|
||||
x: this.heroLocation.x,
|
||||
y: this.heroLocation.y,
|
||||
direction: this.heroLocation.mover.faceDirection
|
||||
};
|
||||
const follower = new HeroFollower(num, loc, this.faceHandler, this);
|
||||
this.followers.push(follower);
|
||||
const index = this.followers.length - 1;
|
||||
this.forEachHook(hook => {
|
||||
hook.onAddFollower?.(follower, index);
|
||||
});
|
||||
return follower;
|
||||
}
|
||||
|
||||
getFollower(index: number): IHeroFollower | null {
|
||||
return this.followers[index] ?? null;
|
||||
}
|
||||
|
||||
*getFollowersById(
|
||||
num: number | string
|
||||
): IterableIterator<[number, IHeroFollower]> {
|
||||
const store = this.state.tileStore;
|
||||
const target = typeof num === 'string' ? store.idToNumber(num)! : num;
|
||||
for (let i = 0; i < this.followers.length; i++) {
|
||||
if (this.followers[i].num === target) {
|
||||
yield [i, this.followers[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getAllFollowers(): IHeroFollower[] {
|
||||
return this.followers.slice();
|
||||
}
|
||||
|
||||
async removeFollower(index: number): Promise<void> {
|
||||
const removed = this.followers.splice(index, 1);
|
||||
if (removed.length > 0) {
|
||||
this.forEachHook(hook => {
|
||||
hook.onRemoveFollower?.(removed[0], index);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async removeAllFollowers(): Promise<void> {
|
||||
const snapshot = this.followers.slice();
|
||||
this.followers.length = 0;
|
||||
this.forEachHook(hook => {
|
||||
snapshot.forEach((v, i) => {
|
||||
hook.onRemoveFollower?.(v, i);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async gatherFollowers(): Promise<void> {
|
||||
const { x, y, mover } = this.heroLocation;
|
||||
|
||||
for (let i = 0; i < this.followers.length; i++) {
|
||||
const follower = this.followers[i];
|
||||
follower.location.mover.clear();
|
||||
|
||||
let skip = false;
|
||||
for (let j = i - 1; j >= 0; j--) {
|
||||
const dir = this.followers[j].location.mover.moveDirection;
|
||||
if (dir === FaceDirection.Unknown) {
|
||||
follower.location.mover.clear();
|
||||
follower.location.mover.tp(x, y);
|
||||
follower.location.mover.face(mover.faceDirection);
|
||||
skip = true;
|
||||
break;
|
||||
} else {
|
||||
follower.location.mover.step(dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
follower.location.mover.step(mover.moveDirection);
|
||||
}
|
||||
}
|
||||
|
||||
const controllers = this.followers.map(
|
||||
v => v.location.mover.start()?.onEnd
|
||||
);
|
||||
await Promise.all(controllers);
|
||||
this.forEachHook(hook => {
|
||||
hook.onGatherFollowers?.(false);
|
||||
});
|
||||
}
|
||||
|
||||
gatherFollowersSync(): void {
|
||||
const { x, y } = this.heroLocation;
|
||||
const dir = this.heroLocation.mover.faceDirection;
|
||||
for (const follower of this.followers) {
|
||||
const mover = follower.location.mover;
|
||||
mover.setPos(x, y);
|
||||
mover.setFaceDir(dir);
|
||||
}
|
||||
this.forEachHook(hook => {
|
||||
hook.onGatherFollowers?.(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
export * from './attribute';
|
||||
export * from './follower';
|
||||
export * from './followersController';
|
||||
export * from './location';
|
||||
export * from './rendering';
|
||||
export * from './mover';
|
||||
|
||||
@ -57,17 +57,12 @@ export class HeroMover<T extends IHeroLocation>
|
||||
protected async onMoveStart(
|
||||
_tile: IHeroLocation,
|
||||
_controller: Readonly<IMoverController>
|
||||
): Promise<void> {
|
||||
// TODO: 通知渲染端开始移动,同步平滑视角
|
||||
}
|
||||
): Promise<void> {}
|
||||
|
||||
protected async onMoveEnd(
|
||||
_tile: IHeroLocation,
|
||||
_controller: Readonly<IMoverController>
|
||||
): Promise<void> {
|
||||
// TODO: 通知渲染端移动结束
|
||||
// TODO: 清除自动寻路状态
|
||||
}
|
||||
): Promise<void> {}
|
||||
|
||||
protected async onStepStart(
|
||||
step: ObjectMoveStep,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { HeroAttribute } from './attribute';
|
||||
import { HeroFollowersController } from './followersController';
|
||||
import { HeroFollowersController } from './follower';
|
||||
import { HeroLocation } from './location';
|
||||
import { HeroRendering } from './rendering';
|
||||
import {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user