template/packages-user/data-state/src/event/map.ts
unanmed 3134537d30 feat(03-02): implement approved event built-ins
- Add map, hero, touch, and temporary event controls
- Register exactly eight built-ins through top-level event assembly
- Cover awaited behavior and safe failure with explicit fixtures
2026-09-10 16:25:02 +08:00

93 lines
2.5 KiB
TypeScript

import { IBlockEventEnv } from '@user/data-system';
import {
IDeleteBlockEventParam,
IMoveBlockEventParam,
ISetBlockEventParam
} from './types';
import { isNil } from 'lodash-es';
import { logger } from '@motajs/common';
import { IGameMap, IMapLayer } from '@user/data-base';
import { appendMoveSteps } from './hero';
/**
* 通过环境参量获取可能的地图对象
* @param env 事件环境变量
*/
export function getPossibleMap(env: IBlockEventEnv): IGameMap | null {
if (env.map) return env.map;
if (env.layer) return env.layer.map;
const map = env.state.maps.getMap(env.heroFloor);
if (map) return map;
return null;
}
/** 通过环境参量获取可能的事件图层 */
export function getPossibleLayer(env: IBlockEventEnv): IMapLayer | null {
if (env.layer) return env.layer;
const map = getPossibleMap(env);
if (map?.eventLayer) return map.eventLayer;
return null;
}
export function eventSetBlock(
param: ISetBlockEventParam,
env: IBlockEventEnv
): void {
const layer = getPossibleLayer(env);
if (!layer) return;
if (!layer.inMap(param.x, param.y)) return;
const num = env.state.tileStore.num(param.tile);
if (isNil(num)) {
logger.warn(1001);
return;
}
layer.setBlock(num, param.x, param.y);
}
/** 将动态图块移动完成后还原为静态图块 */
export async function eventMoveBlock(
param: IMoveBlockEventParam,
env: IBlockEventEnv
): Promise<void> {
const layer = getPossibleLayer(env);
if (!layer || !layer.inMap(param.x, param.y)) return;
if (!layer.getTile(param.x, param.y)) return;
const dynamic = layer.transferToDynamic(param.x, param.y);
if (!dynamic) return;
if (dynamic.mover.moving) return;
appendMoveSteps(dynamic.mover, param.steps);
const controller = dynamic.mover.start();
if (!controller) return;
await controller.onEnd;
if (param.safe) {
layer.transferToStaticIfSafe(dynamic);
} else {
layer.transferToStatic(dynamic);
}
}
/** 删除目标坐标的静态图块和动态图块 */
export async function eventDeleteBlock(
param: IDeleteBlockEventParam,
env: IBlockEventEnv
): Promise<void> {
const layer = getPossibleLayer(env);
if (!layer || !layer.inMap(param.x, param.y)) return;
const dynamics = [...layer.getDynamicTilesAt(param.x, param.y)];
await Promise.all(dynamics.map(tile => layer.deleteDynamic(tile)));
if (layer.getTile(param.x, param.y)) {
layer.setBlock(0, param.x, param.y);
}
}