refactor(replay): add command base class and rewrite move/teleport

- BaseReplayCommand with name/paramTypes and assertParameter guard
- add optional IReplayCommand.notExecuted for trailing-step finalization
- sandbox invokes previous command notExecuted when the next command differs
- rewrite ReplayMoveCommand (batched step + notExecuted start/await) and ReplayTeleportCommand
- add replay logger error codes 2001-2005 and warn 175

NOTE: command tests still reference the pre-rewrite class names; updated in follow-up.
This commit is contained in:
AncTe committed 2026-09-13 15:16:51 +08:00
1 parent 8f1e973886
commit 37bfb77301
5 files changed
+186 -65

No files matched your search

@@ -31,6 +31,9 @@ export class ReplaySandbox
/** 录像的流式读取器 */
private reader: Readonly<IReplayReadStream>;
/** 上一步播放的指令 */
private last: number = -1;
constructor(
readonly route: IReplayArray,
readonly system: IReplaySystem,
@@ -126,6 +129,23 @@ export class ReplaySandbox
this.ending = true;
return false;
}
// notExecuted
if (this.last !== -1) {
const last = this.system.getCommand(this.last);
if (!last) {
logger.warn(157, this.last.toString());
return false;
}
const success = (await last.notExecuted?.()) ?? true;
if (!success) {
logger.warn(175, this.last.toString());
return false;
}
}
this.last = next.command;
// execute
const command = this.system.getCommand(next.command);
if (!command) {
logger.warn(157, next.command.toString());
@@ -140,7 +160,10 @@ export class ReplaySandbox
);
return false;
}
// hook
await Promise.all(this.forEachHook(hook => hook.onStep?.(next)));
return true;
}
}
@@ -18,6 +18,12 @@ export interface IReplayCommand {
* @returns 当此录像步执行完毕时兑现的 `Promise`,兑现值表示此录像步是否播放成功
*/
execute(step: IReplayStepHandler): Promise<boolean>;
/**
* 若上一步是当前录像指令,而下一步不是,触发此函数,一般用于连续步骤的后处理
* @returns 当此后处理执行完毕时兑现的 `Promise`,兑现值表示是否执行成功
*/
notExecuted?(): Promise<boolean>;
}
export interface IReplaySandboxHooks extends IHookBase {