refactor: 录像系统指令

This commit is contained in:
unanmed 2026-09-13 16:38:19 +08:00
parent dd4e66a335
commit 46a38fa0c6
7 changed files with 47 additions and 57 deletions

View File

@ -118,6 +118,24 @@ export class ReplaySandbox
this.forEachHook(hook => hook.onStopReplay?.());
}
/**
* 触发上一步指令的连续步骤后处理
*/
private async finalizeLast(): Promise<boolean> {
if (this.last === -1) return true;
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;
}
return true;
}
async step(): Promise<boolean> {
if (!this.playing || this.ended) return false;
if (this.reader.expired) {
@ -127,17 +145,20 @@ export class ReplaySandbox
const next = this.reader.read();
if (!next) {
// notExecuted
if (!(await this.finalizeLast())) {
return false;
const ne = await this.finalizeLast();
if (ne) {
this.last = -1;
this.ending = true;
}
this.last = -1;
this.ending = true;
return false;
}
// notExecuted
if (!(await this.finalizeLast())) {
return false;
if (next.command !== this.last) {
const ne = await this.finalizeLast();
if (!ne) {
return false;
}
}
this.last = next.command;
@ -162,22 +183,4 @@ export class ReplaySandbox
return true;
}
/**
* 触发上一步指令的连续步骤后处理
*/
private async finalizeLast(): Promise<boolean> {
if (this.last === -1) return true;
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;
}
return true;
}
}

View File

@ -226,6 +226,9 @@ export class CoreState implements ICoreState {
);
this.eventSystem = eventSystem;
// 录像系统
this.replaySystem = new ReplaySystem();
//#endregion
//#region L3 初始化
@ -259,8 +262,8 @@ export class CoreState implements ICoreState {
pathfinding.useMover(this.hero.location.mover);
this.pathfinding = pathfinding;
this.replaySystem = new ReplaySystem();
this.registerReplayCommand();
// 录像系统初始化注册
this.registerReplayCommands();
//#endregion
}
@ -270,7 +273,7 @@ export class CoreState implements ICoreState {
/**
* 注册全部录像指令
*/
private registerReplayCommand() {
private registerReplayCommands() {
this.replaySystem.registerCommand(
ReplayCommandCode.Up,
new ReplayMoveCommand(this, FaceDirection.Up)
@ -288,7 +291,7 @@ export class CoreState implements ICoreState {
new ReplayMoveCommand(this, FaceDirection.Left)
);
this.replaySystem.registerCommand(
ReplayCommandCode.AutoPathfindToPoint,
ReplayCommandCode.Teleport,
new ReplayTeleportCommand(this)
);
this.replaySystem.registerCommand(

View File

@ -54,7 +54,7 @@ describe('replay commands', () => {
ReplayCommandCode.Right,
ReplayCommandCode.Down,
ReplayCommandCode.Left,
ReplayCommandCode.AutoPathfindToPoint,
ReplayCommandCode.Teleport,
ReplayCommandCode.UseItem,
ReplayCommandCode.Equip,
ReplayCommandCode.Unequip
@ -155,7 +155,7 @@ describe('replay commands', () => {
let result: boolean | undefined;
const pending = command
.execute(step(ReplayCommandCode.AutoPathfindToPoint, [2, 3]))
.execute(step(ReplayCommandCode.Teleport, [2, 3]))
.then(value => {
result = value;
});
@ -169,7 +169,7 @@ describe('replay commands', () => {
const error = vi.spyOn(logger, 'error');
teleport.mockReturnValueOnce(null);
await expect(
command.execute(step(ReplayCommandCode.AutoPathfindToPoint, [4, 5]))
command.execute(step(ReplayCommandCode.Teleport, [4, 5]))
).resolves.toBe(false);
expect(error).toHaveBeenCalledWith(2005, '4', '5');
error.mockRestore();
@ -327,10 +327,8 @@ describe('replay commands', () => {
const unequip = new ReplayUnequipCommand(state);
const invalid = [
move.execute(step(ReplayCommandCode.Up, [1])),
teleport.execute(
step(ReplayCommandCode.AutoPathfindToPoint, ['x', 1])
),
teleport.execute(step(ReplayCommandCode.AutoPathfindToPoint, [1])),
teleport.execute(step(ReplayCommandCode.Teleport, ['x', 1])),
teleport.execute(step(ReplayCommandCode.Teleport, [1])),
useItem.execute(step(ReplayCommandCode.UseItem, [])),
useItem.execute(step(ReplayCommandCode.UseItem, ['id'])),
equip.execute(step(ReplayCommandCode.Equip, [1, 0])),

View File

@ -4,7 +4,6 @@ import {
IReplayCommand,
ReplayParamValue
} from '@user/data-common';
import { EquipStatus } from '@user/data-base';
import { IStateSystem } from '@user/data-system';
import { logger } from '@motajs/common';
@ -178,16 +177,9 @@ export class ReplayEquipCommand
boolean
];
const equipment = this.state.hero.equip;
if (equipment.getEquipped(slot) === uid) {
return true;
}
if (equipment.canEquipTo(uid, slot) === EquipStatus.CannotEquip) {
logger.error(2007, uid.toString(), slot.toString());
return false;
}
equipment.equip(uid, slot, autoUnload);
if (equipment.getEquipped(slot) !== uid) {
logger.error(2008, uid.toString(), slot.toString());
logger.error(2007, uid.toString(), slot.toString());
return false;
}
return true;
@ -209,13 +201,9 @@ export class ReplayUnequipCommand
// Parameter: [int8 slot]
const slot = step.params[0] as number;
const equipment = this.state.hero.equip;
if (equipment.getEquipped(slot) === undefined) {
logger.error(2009, slot.toString());
return false;
}
equipment.unequip(slot);
if (equipment.getEquipped(slot) !== undefined) {
logger.error(2010, slot.toString());
if (equipment.getEquipped(slot) !== void 0) {
logger.error(2008, slot.toString());
return false;
}
return true;

View File

@ -9,7 +9,7 @@ export const enum ReplayCommandCode {
/** 向左移动一步 */
Left = 3,
/** 自动寻路至目标点 */
AutoPathfindToPoint = 4,
Teleport = 4,
/** 使用道具 */
UseItem = 5,
/** 装备物品 */
@ -24,7 +24,7 @@ export const REPLAY_COMMAND_ORDER: readonly ReplayCommandCode[] = [
ReplayCommandCode.Right,
ReplayCommandCode.Down,
ReplayCommandCode.Left,
ReplayCommandCode.AutoPathfindToPoint,
ReplayCommandCode.Teleport,
ReplayCommandCode.UseItem,
ReplayCommandCode.Equip,
ReplayCommandCode.Unequip

View File

@ -205,7 +205,7 @@ describe('DATA-01 closure', () => {
ReplayCommandCode.Right,
ReplayCommandCode.Down,
ReplayCommandCode.Left,
ReplayCommandCode.AutoPathfindToPoint,
ReplayCommandCode.Teleport,
ReplayCommandCode.UseItem,
ReplayCommandCode.Equip,
ReplayCommandCode.Unequip

View File

@ -71,10 +71,8 @@
"2004": "Replay(move): Unexpected move controller missing while executing move behavior.",
"2005": "Replay(teleport): Cannot find a way to target position: $1,$2.",
"2006": "Replay(use-item): Failed to use item number $1.",
"2007": "Replay(equip): Cannot equip uid $1 into slot $2.",
"2008": "Replay(equip): Equipping uid $1 into slot $2 did not take effect.",
"2009": "Replay(unequip): No equipment in slot $1.",
"2010": "Replay(unequip): Unequipping slot $1 did not take effect."
"2007": "Replay(equip): Equipping uid $1 into slot $2 failed.",
"2008": "Replay(unequip): Unequipping slot $1 failed."
},
"warn": {
"1": "Resource with type of 'none' is loaded.",