refactor: 按审查意见调整寻路模块与开发规范

This commit is contained in:
unanmed 2026-09-09 19:05:57 +08:00
parent 489e3de106
commit 622008f67c
6 changed files with 25 additions and 26 deletions

4
dev.md
View File

@ -73,7 +73,7 @@
- 公共方法、接口必须在**源头处**(多数情况下为 `interface`)添加 `jsDoc` 注释;其他常用成员、方法、类型也必须添加注释(含义极为明确或极少使用的可例外,但建议全部添加)。接口中每个方法之间必须添加空行,成员之间应根据成员功能添加换行。 - 公共方法、接口必须在**源头处**(多数情况下为 `interface`)添加 `jsDoc` 注释;其他常用成员、方法、类型也必须添加注释(含义极为明确或极少使用的可例外,但建议全部添加)。接口中每个方法之间必须添加空行,成员之间应根据成员功能添加换行。
- 继承或 `implements` 而来的 API方法、成员等若注释说明无需变更则**不应重复添加** `jsDoc` 注释。 - 继承或 `implements` 而来的 API方法、成员等若注释说明无需变更则**不应重复添加** `jsDoc` 注释。
- 不对构造器添加注释。若构造器使用了属性声明语法(`constructor(public prop: T)`)且成员需要说明,可仅对该成员添加参数注释,不写构造器描述。**在这种情况下**建议避免在构造器中使用属性声明语法,将成员单独声明并在构造器中赋值。此条建议**并非**要求不使用构造器的属性声明语法,而是仅在这一情况下不建议使用,常规情况下推荐使用此语法来缩短代码长度并提高可读性。 - 不对构造器添加注释。若构造器使用了属性声明语法(`constructor(public prop: T)`)且成员需要说明,可仅对该成员添加参数注释,不写构造器描述。**在这种情况下**建议避免在构造器中使用属性声明语法,将成员单独声明并在构造器中赋值。此条建议**并非**要求不使用构造器的属性声明语法,而是仅在这一情况下不建议使用,常规情况下推荐使用此语法来缩短代码长度并提高可读性。
- 长文件可使用 `#region` / `#endregion` 分段以支持折叠。 - 长文件可使用 `#region` / `#endregion` 分段以支持折叠,分区应以功能进行划分,即这个 region 负责某个功能,而不是按照修饰符等内容划分
- TODO 使用 `// TODO:``// todo:` 格式。 - TODO 使用 `// TODO:``// todo:` 格式。
- 单行注释的 `//` 与注释内容之间留一个空格;不允许出现非 jsDoc 的多行注释,如需多行注释,使用多个单行注释代替。 - 单行注释的 `//` 与注释内容之间留一个空格;不允许出现非 jsDoc 的多行注释,如需多行注释,使用多个单行注释代替。
- 注释合理换行:考虑中文字符较宽,建议每 4060 个字符在标点符号后换行,不要频繁换行,每行长度应差不多,不要过短也不要过长,不允许在句中换行;参数注释换行后保持对齐。 - 注释合理换行:考虑中文字符较宽,建议每 4060 个字符在标点符号后换行,不要频繁换行,每行长度应差不多,不要过短也不要过长,不允许在句中换行;参数注释换行后保持对齐。
@ -115,6 +115,8 @@
- 换行使用 `CRLF` 格式。 - 换行使用 `CRLF` 格式。
- 不得将一个对象上的函数声明为一个临时变量/常量,哪怕其没有 `this` 指向问题。 - 不得将一个对象上的函数声明为一个临时变量/常量,哪怕其没有 `this` 指向问题。
- 通常情况下,一个文件应只包含一个类,但如果一个类仅是另一个类的依赖,或一个类的长度远远小于另一个类等特殊情况时,允许将多个类放在同一个文件中。 - 通常情况下,一个文件应只包含一个类,但如果一个类仅是另一个类的依赖,或一个类的长度远远小于另一个类等特殊情况时,允许将多个类放在同一个文件中。
- 私有方法应该放到调用之的方法之前,同时保证其处在合理的 region 内。
- 对象的非空判断用 `!obj`,字面量的非空判断用 `!isNil(value)`
## 双端分离 ## 双端分离

View File

@ -55,14 +55,13 @@ export class PathfindingFinder implements IPathfinder {
} }
/** /**
* * 1
* 1
* @param block * @param block
*/ */
private getNodeCost(block: ILayerLocation): number { private getNodeCost(block: ILayerLocation): number {
if (!this.cost) return 1; if (!this.cost) return 1;
const value = this.cost(block); const value = this.cost(block);
if (!Number.isFinite(value) || value < 0) { if (value < 0) {
logger.warn(174); logger.warn(174);
return 1; return 1;
} }
@ -70,8 +69,7 @@ export class PathfindingFinder implements IPathfinder {
} }
/** /**
* *
*
* @param graph * @param graph
* @param start * @param start
* @param target * @param target

View File

@ -91,7 +91,7 @@ export class PathfindingGraphBuilder implements IPathfindingGraphBuilder {
const width = layer.width; const width = layer.width;
const height = layer.height; const height = layer.height;
const floorId = this.resolveFloorId(); const floorId = this.resolveFloorId();
const state: IDataCommon = layer.state; const state = layer.state;
const blocks: (ILayerLocation | null)[] = new Array( const blocks: (ILayerLocation | null)[] = new Array(
width * height width * height
).fill(null); ).fill(null);

View File

@ -34,10 +34,6 @@ export class PathfindingSystem implements IPathfindingSystem {
this.policy = policy; this.policy = policy;
} }
/**
*
* @param target
*/
getPath(target: ITileLocator): IPathfindingStep[] { getPath(target: ITileLocator): IPathfindingStep[] {
const mover = this.mover; const mover = this.mover;
if (isNil(mover)) { if (isNil(mover)) {
@ -49,8 +45,7 @@ export class PathfindingSystem implements IPathfindingSystem {
} }
/** /**
* * `null`
* `null`
* @param path * @param path
* @param teleport * @param teleport
*/ */
@ -64,7 +59,7 @@ export class PathfindingSystem implements IPathfindingSystem {
if (current && !current.controller.done) return null; if (current && !current.controller.done) return null;
if (teleport) { if (teleport) {
const last = path[path.length - 1]; const last = path.at(-1)!;
mover.tp(last.to.x, last.to.y); mover.tp(last.to.x, last.to.y);
} else { } else {
for (const step of path) { for (const step of path) {
@ -72,7 +67,6 @@ export class PathfindingSystem implements IPathfindingSystem {
} }
} }
// 移动器移动中时启动失败,对应已有移动进行中的契约
const controller = mover.start(); const controller = mover.start();
if (!controller) return null; if (!controller) return null;
const result: IPathfindingController = { controller, path }; const result: IPathfindingController = { controller, path };
@ -89,10 +83,11 @@ export class PathfindingSystem implements IPathfindingSystem {
teleportTo(target: ITileLocator): IPathfindingController | null { teleportTo(target: ITileLocator): IPathfindingController | null {
const path = this.getPath(target); const path = this.getPath(target);
if (path.length === 0) return null; if (path.length === 0) return null;
if (isNil(this.policy) || this.policy(path)) { if (!this.policy || this.policy(path)) {
return this.startMove(path, false); return this.startMove(path, false);
} else {
return this.startMove(path, true);
} }
return this.startMove(path, true);
} }
async interrupt(): Promise<void> { async interrupt(): Promise<void> {

View File

@ -13,6 +13,8 @@ import {
IObjectMover IObjectMover
} from '@user/data-common'; } from '@user/data-common';
//#region 寻路系统
export interface IPathfindingStep { export interface IPathfindingStep {
/** 移动方向 */ /** 移动方向 */
readonly dir: FaceDirection; readonly dir: FaceDirection;
@ -105,14 +107,12 @@ export interface IPathfindingSystem extends IDataBaseExtended {
/** /**
* *
* @param target * @param target
* @returns `null`
*/ */
moveTo(target: ITileLocator): IPathfindingController | null; moveTo(target: ITileLocator): IPathfindingController | null;
/** /**
* 退退退 * 退退退
* @param target * @param target
* @returns `null`
*/ */
teleportTo(target: ITileLocator): IPathfindingController | null; teleportTo(target: ITileLocator): IPathfindingController | null;
@ -122,6 +122,10 @@ export interface IPathfindingSystem extends IDataBaseExtended {
interrupt(): Promise<void>; interrupt(): Promise<void>;
} }
//#endregion
//#region 路径图
export interface IPathGraphEdge { export interface IPathGraphEdge {
/** 本条边对应的移动方向 */ /** 本条边对应的移动方向 */
readonly dir: FaceDirection; readonly dir: FaceDirection;
@ -156,19 +160,19 @@ export interface IPathGraph {
export interface IPathfindingGraphBuilder { export interface IPathfindingGraphBuilder {
/** /**
* id * id
* @param maps `null` * @param maps
*/ */
useMapState(maps: IMapState | null): void; useMapState(maps: IMapState | null): void;
/** /**
* *
* @param layer `null` * @param layer
*/ */
useMapLayer(layer: IMapLayer | null): void; useMapLayer(layer: IMapLayer | null): void;
/** /**
* *
* @param predicate `null` * @param predicate
*/ */
usePassPredicate(predicate: IPassPredicate | null): void; usePassPredicate(predicate: IPassPredicate | null): void;
@ -179,9 +183,9 @@ export interface IPathfindingGraphBuilder {
useDirGroup(group: number): void; useDirGroup(group: number): void;
/** /**
* *
*
* @returns
*/ */
build(): IPathGraph; build(): IPathGraph;
} }
//#endregion

View File

@ -239,6 +239,6 @@
"171": "Event id '$1' not found in event store, event will be skipped.", "171": "Event id '$1' not found in event store, event will be skipped.",
"172": "Event returned non-boolean value '$1' during reduction. JavaScript short-circuit semantics will be used.", "172": "Event returned non-boolean value '$1' during reduction. JavaScript short-circuit semantics will be used.",
"173": "Pathfinding input is invalid or a required binding (map state, map layer) is missing. An empty result will be returned.", "173": "Pathfinding input is invalid or a required binding (map state, map layer) is missing. An empty result will be returned.",
"174": "Pathfinding cost function returned a non-finite or negative value. Default cost 1 will be used instead." "174": "Pathfinding cost function returned a negative value. Default cost 1 will be used instead."
} }
} }