From 010383a914a8d8aebd6bcd1e07a7a99ff4226341 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Wed, 25 Jun 2025 16:22:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BD=95=E5=83=8F=E5=9B=9E=E6=94=BE?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=20&=20fix:=20=E5=BF=AB=E6=8D=B7=E5=95=86?= =?UTF-8?q?=E5=BA=97=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client-modules/src/action/hotkey.ts | 3 - .../client-modules/src/render/action.ts | 8 ++- .../client-modules/src/render/ui/save.tsx | 18 ++++++ .../client-modules/src/render/ui/settings.tsx | 57 +++++++++++++++++-- public/libs/control.js | 26 +++------ public/libs/events.js | 2 +- src/types/declaration/control.d.ts | 3 +- 7 files changed, 88 insertions(+), 29 deletions(-) diff --git a/packages-user/client-modules/src/action/hotkey.ts b/packages-user/client-modules/src/action/hotkey.ts index 0931247..37c919e 100644 --- a/packages-user/client-modules/src/action/hotkey.ts +++ b/packages-user/client-modules/src/action/hotkey.ts @@ -489,9 +489,6 @@ gameKey .realize('fly', () => { core.useFly(true); }) - .realize('replay', () => { - core.ui._drawReplay(); - }) .realize('shop', () => { core.openQuickShop(true); }) diff --git a/packages-user/client-modules/src/render/action.ts b/packages-user/client-modules/src/render/action.ts index 0a70389..7e022f2 100644 --- a/packages-user/client-modules/src/render/action.ts +++ b/packages-user/client-modules/src/render/action.ts @@ -5,7 +5,8 @@ import { mainUIController, openStatistics, saveLoad, - openSettings + openSettings, + ReplaySettingsUI } from './ui'; export function createAction() { @@ -21,5 +22,10 @@ export function createAction() { }) .realize('menu', () => { openSettings(mainUIController, [420, 240, 240, 400, 0.5, 0.5]); + }) + .realize('replay', () => { + mainUIController.open(ReplaySettingsUI, { + loc: [420, 240, void 0, void 0, 0.5, 0.5] + }); }); } diff --git a/packages-user/client-modules/src/render/ui/save.tsx b/packages-user/client-modules/src/render/ui/save.tsx index 04011fa..f3af6e2 100644 --- a/packages-user/client-modules/src/render/ui/save.tsx +++ b/packages-user/client-modules/src/render/ui/save.tsx @@ -566,3 +566,21 @@ export async function saveLoad( } return true; } + +export async function saveWithExist( + controller: IUIMountable, + loc: ElementLocator, + props?: SaveProps +) { + const validate = (_: number, exist: boolean): SaveValidation => { + return { message: '无效的存档!', valid: exist }; + }; + const index = await selectSave( + controller, + loc, + SaveMode.Load, + validate, + props + ); + return index; +} diff --git a/packages-user/client-modules/src/render/ui/settings.tsx b/packages-user/client-modules/src/render/ui/settings.tsx index 0ac172f..c8fd8b6 100644 --- a/packages-user/client-modules/src/render/ui/settings.tsx +++ b/packages-user/client-modules/src/render/ui/settings.tsx @@ -21,6 +21,8 @@ import { getVitualKeyOnce } from '@motajs/legacy-ui'; import { getAllSavesData, getSaveData, syncFromServer } from '../utils'; import { getInput } from '../components/input'; import { openStatistics } from './statistics'; +import { saveWithExist } from './save'; +import { compressToBase64 } from 'lz-string'; export interface MainSettingsProps extends Partial, @@ -144,7 +146,7 @@ export const ReplaySettings = defineComponent(props => { [ReplayChoice.Back, '返回游戏'] ]; - const choose = (key: ChoiceKey) => { + const choose = async (key: ChoiceKey) => { switch (key) { case ReplayChoice.Start: { props.controller.closeAll(); @@ -155,15 +157,59 @@ export const ReplaySettings = defineComponent(props => { break; } case ReplayChoice.StartFromSave: { - // todo + const index = await saveWithExist( + props.controller, + [0, 0, 840, 480] + ); + if (index === -2) break; + if (index === -1) { + core.doSL('autoSave', 'replayLoad'); + } else { + core.doSL(index + 1, 'replayLoad'); + } + props.controller.closeAll(); break; } case ReplayChoice.ResumeReplay: { - // todo + const index = await saveWithExist( + props.controller, + [0, 0, 840, 480] + ); + if (index === -2) break; + const name = index === -1 ? 'autoSave' : index + 1; + const success = core.doSL(name, 'replayRemain'); + if (!success) { + props.controller.closeAll(); + break; + } + await getConfirm( + props.controller, + '[步骤2]请选择第二个存档。\n\r[yellow]该存档必须是前一个存档的后续。\r\n将尝试播放到此存档。', + [420, 240, void 0, void 0, 0.5, 0.5], + 240 + ); + const index2 = await saveWithExist( + props.controller, + [0, 0, 840, 480] + ); + if (index2 === -2) break; + const name2 = index2 === -1 ? 'autoSave' : index2 + 1; + core.doSL(name2, 'replayRemain'); + props.controller.closeAll(); break; } case ReplayChoice.ReplayRest: { - // todo + const index = await saveWithExist( + props.controller, + [0, 0, 840, 480] + ); + if (index === -2) break; + if (index === -1) { + core.doSL('autoSave', 'replaySince'); + } else { + core.doSL(index + 1, 'replaySince'); + } + props.controller.closeAll(); break; } case ReplayChoice.ChooseReplay: { @@ -174,8 +220,7 @@ export const ReplaySettings = defineComponent(props => { case ReplayChoice.Download: { core.download( core.firstData.name + '_' + core.formatDate2() + '.h5route', - // @ts-expect-error 暂时无法推导 - LZString.compressToBase64( + compressToBase64( JSON.stringify({ name: core.firstData.name, hard: core.status.hard, diff --git a/public/libs/control.js b/public/libs/control.js index 8156f54..12f01f5 100644 --- a/public/libs/control.js +++ b/public/libs/control.js @@ -2019,7 +2019,7 @@ control.prototype.doSL = function (id, type) { this._doSL_load(id, this._doSL_replayLoad_afterGet); break; case 'replayRemain': - this._doSL_load(id, this._doSL_replayRemain_afterGet); + return this._doSL_load(id, this._doSL_replayRemain_afterGet); break; case 'replaySince': this._doSL_load(id, this._doSL_replaySince_afterGet); @@ -2186,7 +2186,8 @@ control.prototype._doSL_replayLoad_afterGet = function (id, data) { control.prototype._doSL_replayRemain_afterGet = function (id, data) { if (!data) { core.playSound('操作失败'); - return core.drawTip('无效的存档'); + core.drawTip('无效的存档'); + return false; } var route = core.decodeRoute(data.route); if (core.status.tempRoute) { @@ -2199,27 +2200,18 @@ control.prototype._doSL_replayRemain_afterGet = function (id, data) { core.ui.closePanel(); core.startReplay(remainRoute); core.drawTip('接续播放录像'); - return; + return true; } else if ( data.floorId != core.status.floorId || data.hero.loc.x != core.getHeroLoc('x') || data.hero.loc.y != core.getHeroLoc('y') - ) - return alert('楼层或坐标不一致!'); + ) { + alert('楼层或坐标不一致!'); + return false; + } core.status.tempRoute = route; - core.ui.closePanel(); - core.drawText( - '\t[步骤2]请选择第二个存档。\n\r[yellow]该存档必须是前一个存档的后续。\r\n将尝试播放到此存档。', - function () { - core.status.event.id = 'replayRemain'; - core.lockControl(); - var saveIndex = core.saves.saveIndex; - var page = Math.floor((saveIndex - 1) / 5), - offset = saveIndex - 5 * page; - core.ui._drawSLPanel(10 * page + offset); - } - ); + return true; }; control.prototype._doSL_replaySince_afterGet = function (id, data) { diff --git a/public/libs/events.js b/public/libs/events.js index da4e30e..1fddc39 100644 --- a/public/libs/events.js +++ b/public/libs/events.js @@ -3408,7 +3408,7 @@ events.prototype.openToolbox = function (fromUserAction) { ////// 点击快捷商店按钮时的打开操作 ////// events.prototype.openQuickShop = function (fromUserAction) { if (core.isReplaying()) return; - const shop = Mota.require('@user/data-state'); + const shop = Mota.require('@user/legacy-plugin-data'); if (Object.keys(core.status.shops).length == 0) { core.playSound('操作失败'); diff --git a/src/types/declaration/control.d.ts b/src/types/declaration/control.d.ts index ef110b4..e1b1d84 100644 --- a/src/types/declaration/control.d.ts +++ b/src/types/declaration/control.d.ts @@ -610,7 +610,8 @@ interface Control { /** * 实际进行存读档事件 */ - doSL(id: string | number, type: SLType): void; + doSL(id: string | number, type: Exclude): void; + doSL(id: string | number, type: 'replayRemain'): boolean; /** * 同步存档到服务器