Compare commits

..

11 Commits

27 changed files with 362 additions and 624 deletions

View File

@ -22,7 +22,7 @@
当你**制作完游戏**后,点击构建游戏,即可自动构建游戏,构建结果在 `dist` 文件夹,会自动打包到 `dist.zip` 压缩包,发塔或更新上传此压缩包即可。 当你**制作完游戏**后,点击构建游戏,即可自动构建游戏,构建结果在 `dist` 文件夹,会自动打包到 `dist.zip` 压缩包,发塔或更新上传此压缩包即可。
此帮助文档远比 2.x 的文档易读,也更容易理解,建议多阅读此文档来解决自己的问题,如果问题很复杂,或是短时间内解决不了,再去造塔群询问 此帮助文档远比 2.x 的文档易读,也更容易理解,但是遇到问题时我们依然建议直接在造塔群询问,因为你可能不能判断文档中是否有关于你的问题的解答
```mermaid ```mermaid
graph TD graph TD

View File

@ -6,6 +6,8 @@
Unexpected error when posting danmaku. Error info: $1 Unexpected error when posting danmaku. Error info: $1
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 报错原因:发送弹幕时发生报错。 - 报错原因:发送弹幕时发生报错。
- 解决方案:查看后面的 Error info检查报错信息内容按照报错信息修复问题。 - 解决方案:查看后面的 Error info检查报错信息内容按照报错信息修复问题。
@ -24,6 +26,8 @@ Unexpected loading error in loading resource '$1/$2'. Error info: $3
Syntax error in parsing CSS: Unexpected ':'. Col: $1. CSS string: '$2 Syntax error in parsing CSS: Unexpected ':'. Col: $1. CSS string: '$2
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。 - 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
- 解决方案:检查弹幕 CSS 语法是否正确。 - 解决方案:检查弹幕 CSS 语法是否正确。
@ -33,6 +37,8 @@ Syntax error in parsing CSS: Unexpected ':'. Col: $1. CSS string: '$2
Syntax error in parsing CSS: Unexpected ';'. Col: $1. CSS string: '$2' Syntax error in parsing CSS: Unexpected ';'. Col: $1. CSS string: '$2'
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。 - 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
- 解决方案:检查弹幕 CSS 语法是否正确。 - 解决方案:检查弹幕 CSS 语法是否正确。
@ -42,6 +48,8 @@ Syntax error in parsing CSS: Unexpected ';'. Col: $1. CSS string: '$2'
Syntax error in parsing CSS: Missing property name after '-'. Col: $1. CSS string: '$2' Syntax error in parsing CSS: Missing property name after '-'. Col: $1. CSS string: '$2'
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。 - 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
- 解决方案:检查弹幕 CSS 语法是否正确。 - 解决方案:检查弹幕 CSS 语法是否正确。
@ -51,6 +59,8 @@ Syntax error in parsing CSS: Missing property name after '-'. Col: $1. CSS strin
Syntax error in parsing CSS: Unexpected end of css, expecting ':'. Col: $1. CSS string: '$2' Syntax error in parsing CSS: Unexpected end of css, expecting ':'. Col: $1. CSS string: '$2'
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。 - 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
- 解决方案:检查弹幕 CSS 语法是否正确。 - 解决方案:检查弹幕 CSS 语法是否正确。
@ -60,6 +70,8 @@ Syntax error in parsing CSS: Unexpected end of css, expecting ':'. Col: $1. CSS
Syntax error in parsing CSS: Unexpected end of css, expecting property value. Col: $1. CSS string: '$2' Syntax error in parsing CSS: Unexpected end of css, expecting property value. Col: $1. CSS string: '$2'
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。 - 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
- 解决方案:检查弹幕 CSS 语法是否正确。 - 解决方案:检查弹幕 CSS 语法是否正确。
@ -69,6 +81,8 @@ Syntax error in parsing CSS: Unexpected end of css, expecting property value. Co
Post danmaku with not allowed css. Info: $1 Post danmaku with not allowed css. Info: $1
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 报错原因:弹幕 CSS 中使用了不允许的 css 属性类型。 - 报错原因:弹幕 CSS 中使用了不允许的 css 属性类型。
- 解决方案:目前仅支持 `color` `background-color` `font-size: x%` 属性。 - 解决方案:目前仅支持 `color` `background-color` `font-size: x%` 属性。
@ -133,7 +147,7 @@ Cannot use shader program for shader element that does not belong to it.
## ERROR CODE 18 ## ERROR CODE 18
```txt ```txt
Cannot delete shader program for shader element that does not belong to Cannot delete shader program for shader element that does not belong to it.
``` ```
- 报错原因:在一个着色器上删除了不属于这个着色器的着色器程序。 - 报错原因:在一个着色器上删除了不属于这个着色器的着色器程序。

View File

@ -24,6 +24,8 @@ Repeat load of resource '$1/$2'.
Unknown danmaku tag: $1 Unknown danmaku tag: $1
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 警告原因:出现了未知的弹幕标签(指 `[xxx:xxx]` - 警告原因:出现了未知的弹幕标签(指 `[xxx:xxx]`
- 解决方案:目前仅支持 `[i:xxx]` 标签,如果需要显示方括号,请使用 `\[\]` - 解决方案:目前仅支持 `[i:xxx]` 标签,如果需要显示方括号,请使用 `\[\]`
@ -33,6 +35,8 @@ Unknown danmaku tag: $1
Ignored a mismatched ']' in danmaku. Ignored a mismatched ']' in danmaku.
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 警告原因:出现了不能匹配的右方括号。 - 警告原因:出现了不能匹配的右方括号。
- 解决方案:如果需要显示方括号,请使用 `\[\]` - 解决方案:如果需要显示方括号,请使用 `\[\]`
@ -42,6 +46,8 @@ Ignored a mismatched ']' in danmaku.
Repeat post danmaku. Repeat post danmaku.
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 警告原因:同一个弹幕被发送了两次。 - 警告原因:同一个弹幕被发送了两次。
- 解决方案:确保一个弹幕实例只调用了一次 `post` 方法。 - 解决方案:确保一个弹幕实例只调用了一次 `post` 方法。
@ -51,6 +57,8 @@ Repeat post danmaku.
Registered special danmaku element: $1. Registered special danmaku element: $1.
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 警告原因:要注册的弹幕标签已经存在。 - 警告原因:要注册的弹幕标签已经存在。
- 解决方案:避免使用同一个标签名,如果内容不一样请换一个标签名。 - 解决方案:避免使用同一个标签名,如果内容不一样请换一个标签名。
@ -150,6 +158,8 @@ Floor-damage extension needs 'floor-binder' extension as dependency.
Uncaught error in posting like info for danmaku. Danmaku id: $1. Uncaught error in posting like info for danmaku. Danmaku id: $1.
``` ```
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
- 警告原因:为弹幕点赞时出现报错。 - 警告原因:为弹幕点赞时出现报错。
- 解决方案:可能是网络问题,检查网络。 - 解决方案:可能是网络问题,检查网络。
@ -159,6 +169,8 @@ Uncaught error in posting like info for danmaku. Danmaku id: $1.
Repeat light id: '$1' Repeat light id: '$1'
``` ```
> 应该不会遇到这个报错,因为样板并不内置点光源。
- 警告原因:重复的光源 id。 - 警告原因:重复的光源 id。
- 解决方案:避免光源 id 出现重复。 - 解决方案:避免光源 id 出现重复。
@ -284,8 +296,7 @@ Sub-image exceeds texture dimensions, auto adjusting size.
Cannot modify MotaOffscreenCanvas2D that is freezed. Cannot modify MotaOffscreenCanvas2D that is freezed.
``` ```
- 警告原因:不能修改已冻结的画布属性。 - 遇不到这个报错。
- 解决方案:如果这个画布后续还需要修改属性,那么就不要冻结它。
## WARN CODE 34 ## WARN CODE 34

View File

@ -116,3 +116,21 @@ Uncaught promise error in waiting box component. Error reason: $1
- 警告原因:在等待 box 组件(选择框、确认框等)时,出现了异步报错。 - 警告原因:在等待 box 组件(选择框、确认框等)时,出现了异步报错。
- 解决方案:根据报错内容解决问题。 - 解决方案:根据报错内容解决问题。
## WARN CODE 64
```txt
Text node type and block type mismatch: '$1' vs '$2'
```
- 警告原因多行文本TextContent解析时节点类型和分块类型不一致。
- 解决方案:理应不会遇到这个问题,如果遇到了,请到造塔群寻求帮助。
## WARN CODE 65
```txt
Cannot bind a weather controller twice.
```
- 警告原因:一个天气控制器不能绑定到两个元素上。
- 解决方案:如果两个元素需要天气,那么请创建两个天气控制器,一个天气控制器只能绑定一个,且不能解绑。

View File

@ -715,6 +715,7 @@ export async function routedConfirm(
const confirm = getChoiceRoute(1) === 0; const confirm = getChoiceRoute(1) === 0;
const timeout = core.control.__replay_getTimeout(); const timeout = core.control.__replay_getTimeout();
core.status.route.push(`choices:${confirm ? 0 : 1}`); core.status.route.push(`choices:${confirm ? 0 : 1}`);
core.status.replay.toReplay.shift();
if (timeout === 0) return confirm; if (timeout === 0) return confirm;
const instance = controller.open(ConfirmBoxUI, { const instance = controller.open(ConfirmBoxUI, {
...(props ?? {}), ...(props ?? {}),
@ -769,6 +770,7 @@ export async function routedChoices<T extends ChoiceKey>(
const selected = getChoiceRoute(0); const selected = getChoiceRoute(0);
const timeout = core.control.__replay_getTimeout(); const timeout = core.control.__replay_getTimeout();
core.status.route.push(`choices:${selected}`); core.status.route.push(`choices:${selected}`);
core.status.replay.toReplay.shift();
if (timeout === 0) return choices[selected][0]; if (timeout === 0) return choices[selected][0];
const instance = controller.open(ChoicesUI, { const instance = controller.open(ChoicesUI, {
...(props ?? {}), ...(props ?? {}),
@ -782,7 +784,7 @@ export async function routedChoices<T extends ChoiceKey>(
return choices[selected][0]; return choices[selected][0];
} else { } else {
const choice = await getChoice(controller, choices, loc, width, props); const choice = await getChoice(controller, choices, loc, width, props);
const index = choices.findIndex(v => v[1] === choice); const index = choices.findIndex(v => v[0] === choice);
core.status.route.push(`choices:${index}`); core.status.route.push(`choices:${index}`);
return choice; return choice;
} }

View File

@ -389,6 +389,10 @@ export class Damage extends RenderItem<EDamageEvent> {
const font = '300 9px Verdana'; const font = '300 9px Verdana';
if (dam.damage > 0) { if (dam.damage > 0) {
text = core.formatBigNumber(dam.damage, true); text = core.formatBigNumber(dam.damage, true);
} else if (dam.ambush) {
text = `!`;
} else if (dam.repulse) {
text = '阻';
} }
const mapDam: DamageRenderable = { const mapDam: DamageRenderable = {

View File

@ -241,10 +241,10 @@ export const Save = defineComponent<SaveProps, SaveEmits, keyof SaveEmits>(
}; };
onMounted(() => { onMounted(() => {
const startIndex = getPosIndex(core.saves.saveIndex); const startIndex = getPosIndex(core.saves.saveIndex - 1);
selected.value = startIndex - 1; selected.value = startIndex;
pageRef.value?.changePage( pageRef.value?.changePage(
Math.floor(core.saves.saveIndex / (grid.value.count - 1)) Math.floor((core.saves.saveIndex - 1) / (grid.value.count - 1))
); );
updateDataList(now.value); updateDataList(now.value);
}); });
@ -380,10 +380,10 @@ export const Save = defineComponent<SaveProps, SaveEmits, keyof SaveEmits>(
'@save_right', '@save_right',
() => { () => {
const count = grid.value.count; const count = grid.value.count;
if (selected.value < count) { if (selected.value < count - 1) {
selected.value++; selected.value++;
} else { } else {
selected.value = 0; selected.value = 1;
pageRef.value?.movePage(1); pageRef.value?.movePage(1);
} }
}, },

View File

@ -48,6 +48,7 @@ export function patchDamage() {
} }
function renderThumbnailDamage(col: EnemyCollection) { function renderThumbnailDamage(col: EnemyCollection) {
if (main.replayChecking) return;
core.status.damage.data = []; core.status.damage.data = [];
core.status.damage.extraData = []; core.status.damage.extraData = [];

View File

@ -590,6 +590,10 @@ export class HeroMover extends ObjectMoverBase {
// 中毒处理 // 中毒处理
if (core.hasFlag('poison')) { if (core.hasFlag('poison')) {
core.status.hero.hp -= core.values.poisonDamage; core.status.hero.hp -= core.values.poisonDamage;
if (core.status.hero.hp <= 0) {
core.status.hero.hp = 0;
core.events.lose();
}
core.updateStatusBar(); core.updateStatusBar();
} }

View File

@ -63,7 +63,6 @@ interface PortResponse {
core.status.maps[data].enemy?.calRealAttribute(); core.status.maps[data].enemy?.calRealAttribute();
core.updateStatusBar(true, true); core.updateStatusBar(true, true);
} }
Mota.require('@user/client-modules').Shadow.update(true);
const Binder = Mota.require( const Binder = Mota.require(
'@user/client-modules' '@user/client-modules'
).LayerGroupFloorBinder; ).LayerGroupFloorBinder;

View File

@ -357,6 +357,7 @@ export function initFallback() {
y y
); );
callback?.(); callback?.();
delete core.animateFrame.asyncId[animate];
}; };
adapters['door-animate']?.all('openDoor', block).then(cb); adapters['door-animate']?.all('openDoor', block).then(cb);

View File

@ -2,7 +2,9 @@
export function initUI() { export function initUI() {
if (main.mode === 'editor') return; if (main.mode === 'editor') return;
const { mainUi, fixedUi, mainSetting } = Mota.require('@motajs/legacy-ui'); if (!main.replayChecking) {
const { mainUi, fixedUi, mainSetting } =
Mota.require('@motajs/legacy-ui');
ui.prototype.drawBook = function () { ui.prototype.drawBook = function () {
if (!core.isReplaying()) return mainUi.open('book'); if (!core.isReplaying()) return mainUi.open('book');
@ -20,16 +22,6 @@ export function initUI() {
if (!core.isReplaying()) return mainUi.open('fly'); if (!core.isReplaying()) return mainUi.open('fly');
}; };
control.prototype.updateStatusBar_update = function () {
core.control.updateNextFrame = false;
if (!core.isPlaying() || core.hasFlag('__statistics__')) return;
core.control.controldata.updateStatusBar();
if (!core.control.noAutoEvents) core.checkAutoEvents();
core.control._updateStatusBar_setToolboxIcon();
core.control.noAutoEvents = true;
Mota.require('@user/data-base').hook.emit('statusBarUpdate');
};
control.prototype.showStatusBar = function () { control.prototype.showStatusBar = function () {
if (main.mode === 'editor') return; if (main.mode === 'editor') return;
core.removeFlag('hideStatusBar'); core.removeFlag('hideStatusBar');
@ -54,3 +46,14 @@ export function initUI() {
core.updateStatusBar(); core.updateStatusBar();
}; };
} }
control.prototype.updateStatusBar_update = function () {
core.control.updateNextFrame = false;
if (!core.isPlaying() || core.hasFlag('__statistics__')) return;
core.control.controldata.updateStatusBar();
if (!core.control.noAutoEvents) core.checkAutoEvents();
core.control._updateStatusBar_setToolboxIcon();
core.control.noAutoEvents = true;
Mota.require('@user/data-base').hook.emit('statusBarUpdate');
};
}

View File

@ -26,10 +26,7 @@
"24": "Cannot decode source type of '$1', since there is no registered decoder for that type.", "24": "Cannot decode source type of '$1', since there is no registered decoder for that type.",
"25": "Unknown audio type. Header: '$1'", "25": "Unknown audio type. Header: '$1'",
"26": "Uncaught error when fetching stream data from '$1'. Error info: $2.", "26": "Uncaught error when fetching stream data from '$1'. Error info: $2.",
"1101": "Shadow extension needs 'floor-hero' extension as dependency.", "1201": "Floor-damage extension needs 'floor-binder' extension as dependency."
"1201": "Floor-damage extension needs 'floor-binder' extension as dependency.",
"1301": "Portal extension need 'floor-binder' extension as dependency.",
"1401": "Halo extension needs 'floor-binder' extension as dependency."
}, },
"warn": { "warn": {
"1": "Resource with type of 'none' is loaded.", "1": "Resource with type of 'none' is loaded.",
@ -97,7 +94,6 @@
"63": "Uncaught promise error in waiting box component. Error reason: $1", "63": "Uncaught promise error in waiting box component. Error reason: $1",
"64": "Text node type and block type mismatch: '$1' vs '$2'", "64": "Text node type and block type mismatch: '$1' vs '$2'",
"65": "Cannot bind a weather controller twice.", "65": "Cannot bind a weather controller twice.",
"1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency.", "1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency."
"1101": "Cannot add new effect to point effect instance, for there's no more reserve space for it. Please increase the max count of the instance."
} }
} }

View File

@ -66,7 +66,7 @@ editor_uievent_wrapper = function (editor) {
} }
core.saveCanvas('uievent'); core.saveCanvas('uievent');
core.status.event.selection = data.selected || 0; core.status.event.selection = data.selected || 0;
core.drawChoices(core.replaceText(data.text), data.choices, data.width, 'uievent'); core.drawChoices2(core.replaceText(data.text), data.choices, data.width, 'uievent');
core.status.event.selection = null; core.status.event.selection = null;
core.loadCanvas('uievent'); core.loadCanvas('uievent');
return; return;

View File

@ -388,12 +388,6 @@ actions.prototype._sys_keyUp_lockControl = function (keyCode, altKey) {
core.status.holdingKeys = []; core.status.holdingKeys = [];
switch (core.status.event.id) { switch (core.status.event.id) {
case 'text':
ok() && core.drawText();
break;
case 'confirmBox':
this._keyUpConfirmBox(keyCode);
break;
case 'action': case 'action':
this._keyUpAction(keyCode); this._keyUpAction(keyCode);
break; break;
@ -530,9 +524,6 @@ actions.prototype._sys_ondown_lockControl = function (x, y, px, py) {
case 'action': case 'action':
this._clickAction(x, y, px, py); this._clickAction(x, y, px, py);
break; break;
case 'text':
core.drawText();
break;
case 'notes': case 'notes':
this._clickNotes(x, y, px, py); this._clickNotes(x, y, px, py);
break; break;
@ -822,10 +813,6 @@ actions.prototype.keyDownCtrl = function () {
}; };
actions.prototype._sys_keyDownCtrl = function () { actions.prototype._sys_keyDownCtrl = function () {
if (core.status.event.id == 'text') {
core.drawText();
return true;
}
if ( if (
core.status.event.id == 'action' && core.status.event.id == 'action' &&
core.status.event.data.type == 'text' core.status.event.data.type == 'text'
@ -855,10 +842,6 @@ actions.prototype.longClick = function (x, y, px, py) {
actions.prototype._sys_longClick_lockControl = function (x, y, px, py) { actions.prototype._sys_longClick_lockControl = function (x, y, px, py) {
if (!core.status.lockControl) return false; if (!core.status.lockControl) return false;
if (core.status.event.id == 'text') {
core.drawText();
return true;
}
if ( if (
core.status.event.id == 'action' && core.status.event.id == 'action' &&
core.status.event.data.type == 'text' core.status.event.data.type == 'text'
@ -976,70 +959,10 @@ actions.prototype._clickConfirmBox = function (x, y, px, py) {
}; };
////// 键盘操作确认框时 ////// ////// 键盘操作确认框时 //////
actions.prototype._keyUpConfirmBox = function (keycode) { actions.prototype._keyUpConfirmBox = function (keycode) {};
if (keycode == 37 || keycode == 39) {
core.status.event.selection = 1 - core.status.event.selection;
core.playSound('光标移动');
core.ui.drawConfirmBox(
core.status.event.ui,
core.status.event.data.yes,
core.status.event.data.no
);
return;
}
if (keycode == 13 || keycode == 32 || keycode == 67) {
if (core.status.event.selection == 0 && core.status.event.data.yes) {
// core.playSound('确定');
core.status.event.selection = null;
core.status.event.data.yes();
return;
}
if (core.status.event.selection == 1 && core.status.event.data.no) {
// core.playSound('确定');
core.status.event.selection = null;
core.status.event.data.no();
return;
}
}
};
////// 鼠标在确认框上移动时 ////// ////// 鼠标在确认框上移动时 //////
actions.prototype._onMoveConfirmBox = function (x, y, px, py) { actions.prototype._onMoveConfirmBox = function (x, y, px, py) {};
if (py >= core._PY_ / 2 && py <= core._PY_ / 2 + 64) {
if (px >= core._PX_ / 2 - 70 && px <= core._PX_ / 2 - 10) {
if (core.status.event.selection != 0) {
core.status.event.selection = 0;
core.playSound('光标移动');
if (core.status.event.id == 'action') {
core.ui.drawConfirmBox(core.status.event.ui.text);
} else {
core.ui.drawConfirmBox(
core.status.event.ui,
core.status.event.data.yes,
core.status.event.data.no
);
}
}
return;
}
if (px >= core._PX_ / 2 + 10 && px <= core._PX_ / 2 + 70) {
if (core.status.event.selection != 1) {
core.status.event.selection = 1;
core.playSound('光标移动');
if (core.status.event.id == 'action') {
core.ui.drawConfirmBox(core.status.event.ui.text);
} else {
core.ui.drawConfirmBox(
core.status.event.ui,
core.status.event.data.yes,
core.status.event.data.no
);
}
}
return;
}
}
};
actions.prototype._clickAction_text = function () { actions.prototype._clickAction_text = function () {
// 正在淡入淡出的话不执行 // 正在淡入淡出的话不执行

View File

@ -1584,7 +1584,8 @@ control.prototype._replay_finished = function () {
core.status.replay.replaying = true; core.status.replay.replaying = true;
core.ui.closePanel(); core.ui.closePanel();
core.pauseReplay(); core.pauseReplay();
} },
true
); );
}; };
@ -1639,7 +1640,8 @@ control.prototype._replay_error = function (action, callback) {
core.ui.closePanel(); core.ui.closePanel();
core.stopReplay(true); core.stopReplay(true);
if (callback) callback(); if (callback) callback();
} },
true
); );
}; };
@ -2212,139 +2214,20 @@ control.prototype.syncSave = function (type) {
}; };
control.prototype._syncSave_http = function (type, saves) { control.prototype._syncSave_http = function (type, saves) {
if (!saves) return core.drawText('没有要同步的存档'); // Deprecated.
var formData = new FormData();
formData.append('type', 'save');
formData.append('name', core.firstData.name);
formData.append('data', LZString.compressToBase64(JSON.stringify(saves)));
formData.append('shorten', '1');
core.http(
'POST',
'/games/sync.php',
formData,
function (data) {
var response = JSON.parse(data);
if (response.code < 0) {
core.drawText(
'出错啦!\n无法同步存档到服务器。\n错误原因' +
response.msg
);
} else {
core.drawText(
(type == 'all'
? '所有存档'
: '存档' + core.saves.saveIndex) +
'同步成功!\n\n您的存档编号+密码: \r[yellow]' +
response.code +
response.msg +
'\r\n\n请牢记以上信息如截图等在从服务器\n同步存档时使用。\n\r[yellow]另外请注意,存档同步只会保存一个月的时间。\r'
);
}
},
function (e) {
core.drawText('出错啦!\n无法同步存档到服务器。\n错误原因' + e);
}
);
}; };
////// 从服务器加载存档 ////// ////// 从服务器加载存档 //////
control.prototype.syncLoad = function () { control.prototype.syncLoad = function () {
core.myprompt('请输入存档编号+密码', null, function (idpassword) { // Deprecated.
if (!idpassword) return core.ui._drawSyncSave();
if (
!/^\d{6}\w{4}$/.test(idpassword) &&
!/^\d{4}\w{3}$/.test(idpassword)
) {
core.drawText('不合法的存档编号+密码!');
return;
}
core.ui.drawWaiting('正在同步,请稍候...');
if (idpassword.length == 7) {
core.control._syncLoad_http(
idpassword.substring(0, 4),
idpassword.substring(4)
);
} else {
core.control._syncLoad_http(
idpassword.substring(0, 6),
idpassword.substring(6)
);
}
});
}; };
control.prototype._syncLoad_http = function (id, password) { control.prototype._syncLoad_http = function (id, password) {
var formData = new FormData(); // Deprecated.
formData.append('type', 'load');
formData.append('name', core.firstData.name);
formData.append('id', id);
formData.append('password', password);
core.http(
'POST',
'/games/sync.php',
formData,
function (data) {
var response = JSON.parse(data);
if (response.code == 0) {
var msg = null;
try {
msg = JSON.parse(
LZString.decompressFromBase64(response.msg)
);
} catch (e) {}
if (!msg) {
try {
msg = JSON.parse(response.msg);
} catch (e) {}
}
if (msg) {
core.control._syncLoad_write(msg);
} else {
core.drawText('出错啦!\n存档解析失败');
}
} else {
core.drawText(
'出错啦!\n无法从服务器同步存档。\n错误原因' +
response.msg
);
}
},
function (e) {
core.drawText('出错啦!\n无法从服务器同步存档。\n错误原因' + e);
}
);
}; };
control.prototype._syncLoad_write = function (data) { control.prototype._syncLoad_write = function (data) {
if (data instanceof Array) { // Deprecated.
core.status.event.selection = 1;
core.ui.drawConfirmBox(
'所有本地存档都将被覆盖,确认?',
function () {
for (var i = 1; i <= 5 * (main.savePages || 30); i++) {
if (i <= data.length)
core.setLocalForage('save' + i, data[i - 1]);
else if (core.saves.ids[i])
core.removeLocalForage('save' + i);
}
core.ui.closePanel();
core.drawText('同步成功!\n你的本地所有存档均已被覆盖。');
},
function () {
core.status.event.selection = 0;
core.ui._drawSyncSave();
}
);
} else {
// 只覆盖单存档
core.setLocalForage('save' + core.saves.saveIndex, data, function () {
core.drawText(
'同步成功!\n单存档已覆盖至存档' + core.saves.saveIndex
);
});
}
}; };
////// 存档到本地 ////// ////// 存档到本地 //////
@ -2741,9 +2624,7 @@ control.prototype.unlockControl = function () {
////// 开启debug模式 ////// ////// 开启debug模式 //////
control.prototype.debug = function () { control.prototype.debug = function () {
core.setFlag('debug', true); core.setFlag('debug', true);
core.drawText( core.drawTip('[调试模式开启]此模式下按住Ctrl键可以穿墙并忽略一切事件');
'\t[调试模式开启]此模式下按住Ctrl键或Ctrl+Shift键可以穿墙并忽略一切事件。\n此模式下将无法上传成绩。'
);
}; };
control.prototype._bindRoutePush = function () { control.prototype._bindRoutePush = function () {

View File

@ -320,6 +320,8 @@ core.prototype.initSync = function (coreData, callback) {
this._init_platform(); this._init_platform();
this._init_others(); this._init_others();
core.initStatus.maps = core.maps._initMaps();
core.loader._load(function () { core.loader._load(function () {
core._afterLoadResources(callback); core._afterLoadResources(callback);
}); });

View File

@ -42,7 +42,7 @@ events.prototype._startGame_start = function (hard, seed, route, callback) {
core.firstData.hero, core.firstData.hero,
hard, hard,
null, null,
core.cloneArray(core.initStatus.maps) core.clone(core.initStatus.maps)
); );
core.setHeroLoc('x', -1); core.setHeroLoc('x', -1);
core.setHeroLoc('y', -1); core.setHeroLoc('y', -1);
@ -120,7 +120,6 @@ events.prototype._startGame_upload = function () {
////// 游戏获胜事件 ////// ////// 游戏获胜事件 //////
events.prototype.win = function (reason, norank, noexit) { events.prototype.win = function (reason, norank, noexit) {
if (!noexit) core.status.gameOver = true;
return this.eventdata.win(reason, norank, noexit); return this.eventdata.win(reason, norank, noexit);
}; };
@ -130,7 +129,6 @@ events.prototype.lose = function (reason) {
return core.control._replay_error(reason, function () { return core.control._replay_error(reason, function () {
core.lose(reason); core.lose(reason);
}); });
core.status.gameOver = true;
return this.eventdata.lose(reason); return this.eventdata.lose(reason);
}; };
@ -187,7 +185,8 @@ events.prototype._gameOver_confirmUpload = function (ending, norank) {
if (main.isCompetition) if (main.isCompetition)
core.events._gameOver_confirmDownload(ending); core.events._gameOver_confirmDownload(ending);
else core.events._gameOver_doUpload(null, ending, norank); else core.events._gameOver_doUpload(null, ending, norank);
} },
true
); );
}; };
@ -251,7 +250,8 @@ events.prototype._gameOver_confirmDownload = function (ending) {
}, },
function () { function () {
core.events._gameOver_askRate(ending); core.events._gameOver_askRate(ending);
} },
true
); );
}; };
@ -284,7 +284,8 @@ events.prototype._gameOver_askRate = function (ending) {
function () { function () {
core.ui.closePanel(); core.ui.closePanel();
core.restart(); core.restart();
} },
true
); );
return; return;
} }
@ -301,7 +302,8 @@ events.prototype._gameOver_askRate = function (ending) {
}, },
function () { function () {
core.restart(); core.restart();
} },
true
); );
}; };
@ -327,7 +329,8 @@ events.prototype.confirmRestart = function () {
function () { function () {
core.playSound('取消'); core.playSound('取消');
core.ui.closePanel(); core.ui.closePanel();
} },
true
); );
}; };
@ -1563,6 +1566,10 @@ events.prototype.__action_doAsyncFunc = function (isAsync, func) {
}; };
events.prototype._action_text = function (data) { events.prototype._action_text = function (data) {
if (main.replayChecking) {
core.doAction();
return;
}
if (this.__action_checkReplaying()) return; if (this.__action_checkReplaying()) return;
const Store = Mota.require('@user/client-modules').TextboxStore; const Store = Mota.require('@user/client-modules').TextboxStore;
const { textbox = 'main-textbox', text, icon = 'none', title = '' } = data; const { textbox = 'main-textbox', text, icon = 'none', title = '' } = data;
@ -1592,6 +1599,10 @@ events.prototype._action_text = function (data) {
}; };
events.prototype._action_autoText = function (data) { events.prototype._action_autoText = function (data) {
if (main.replayChecking) {
core.doAction();
return;
}
if (this.__action_checkReplaying()) return; if (this.__action_checkReplaying()) return;
const Store = Mota.require('@user/client-modules').TextboxStore; const Store = Mota.require('@user/client-modules').TextboxStore;
const { textbox = 'main-textbox', text, icon = 'none', title = '' } = data; const { textbox = 'main-textbox', text, icon = 'none', title = '' } = data;
@ -1638,6 +1649,10 @@ events.prototype._action__label = function (data, x, y, prefix) {
}; };
events.prototype._action_setText = function (data) { events.prototype._action_setText = function (data) {
if (main.replayChecking) {
core.doAction();
return;
}
const isNil = value => value === null || value === void 0; const isNil = value => value === null || value === void 0;
const { textbox = 'main-textbox' } = data; const { textbox = 'main-textbox' } = data;
const Store = Mota.require('@user/client-modules').TextboxStore; const Store = Mota.require('@user/client-modules').TextboxStore;
@ -1740,7 +1755,7 @@ events.prototype._action_confirm = function (data, x, y, prefix) {
}; };
events.prototype._action_choices = function (data, x, y, prefix) { events.prototype._action_choices = function (data, x, y, prefix) {
core.ui.drawChoices( core.ui.drawChoices2(
core.replaceText(data.text, prefix), core.replaceText(data.text, prefix),
data.choices, data.choices,
data.width data.width

View File

@ -3682,112 +3682,12 @@ maps.prototype._moveDetachedBlock = function (
opacity, opacity,
canvases canvases
) { ) {
var height = blockInfo.height, // Deprecated.
posX = blockInfo.posX,
posY = blockInfo.posY,
image = blockInfo.image;
var headCanvas = canvases.headCanvas,
bodyCanvas = canvases.bodyCanvas,
damageCanvas = canvases.damageCanvas;
if (headCanvas) {
core.dymCanvas[headCanvas].clearRect(0, 0, 32, height);
core.dymCanvas[headCanvas].drawImage(
image,
posX * 32,
posY * height,
32,
height - 32,
0,
0,
32,
height - 32
);
core.relocateCanvas(
headCanvas,
nowX - core.bigmap.offsetX,
nowY + 32 - height - core.bigmap.offsetY
);
core.setOpacity(headCanvas, opacity);
}
if (bodyCanvas) {
if (blockInfo.bigImage) {
var face = blockInfo.face;
if (!blockInfo.faceIds) face = 'down';
else if (!blockInfo.faceIds[face]) {
// 维持此时朝向
face = 'down';
for (var f in blockInfo.faceIds) {
if (blockInfo.faceIds[f] == blockInfo.id) {
face = f;
}
}
}
var bigImageInfo = this._getBigImageInfo(
blockInfo.bigImage,
face,
blockInfo.posX
);
var per_width = bigImageInfo.per_width,
per_height = bigImageInfo.per_height;
core.dymCanvas[bodyCanvas].clearRect(
0,
0,
bigImageInfo.per_width,
bigImageInfo.per_height
);
core.dymCanvas[bodyCanvas].drawImage(
blockInfo.bigImage,
bigImageInfo.sx,
bigImageInfo.sy,
per_width,
per_height,
0,
0,
per_width,
per_height
);
core.relocateCanvas(
bodyCanvas,
nowX - core.bigmap.offsetX + bigImageInfo.dx,
nowY - core.bigmap.offsetY + bigImageInfo.dy
);
core.setOpacity(bodyCanvas, opacity);
} else {
core.dymCanvas[bodyCanvas].clearRect(0, 0, 32, 32);
core.dymCanvas[bodyCanvas].drawImage(
image,
posX * 32,
posY * height + height - 32,
32,
32,
0,
0,
32,
32
);
core.relocateCanvas(
bodyCanvas,
nowX - core.bigmap.offsetX,
nowY - core.bigmap.offsetY
);
core.setOpacity(bodyCanvas, opacity);
}
}
if (damageCanvas) {
core.relocateCanvas(
damageCanvas,
nowX - core.bigmap.offsetX,
nowY - core.bigmap.offsetY
);
core.setOpacity(damageCanvas, opacity);
}
}; };
////// 删除独立的block canvas ////// ////// 删除独立的block canvas //////
maps.prototype._deleteDetachedBlock = function (canvases) { maps.prototype._deleteDetachedBlock = function (canvases) {
core.deleteCanvas(canvases.headCanvas); // Deprecated.
core.deleteCanvas(canvases.bodyCanvas);
core.deleteCanvas(canvases.damageCanvas);
}; };
maps.prototype._getAndRemoveBlock = function (x, y) { maps.prototype._getAndRemoveBlock = function (x, y) {

View File

@ -2228,7 +2228,7 @@ ui.prototype.textImage = function (content, lineHeight) {
}; };
////// 绘制一个选项界面 ////// ////// 绘制一个选项界面 //////
ui.prototype.drawChoices = async function (content, choices, width) { ui.prototype.drawChoices2 = async function (content, choices, width, noRoute) {
if (main.replayChecking) { if (main.replayChecking) {
const selected = (() => { const selected = (() => {
const route = core.status.replay.toReplay[0]; const route = core.status.replay.toReplay[0];
@ -2238,18 +2238,21 @@ ui.prototype.drawChoices = async function (content, choices, width) {
return Number(route.slice(8)); return Number(route.slice(8));
} }
})(); })();
core.status.replay.toReplay.shift();
core.insertAction(choices[selected].action); core.insertAction(choices[selected].action);
core.doAction(); core.doAction();
} else { } else {
const { const {
routedChoices, routedChoices,
getChoices,
mainUIController, mainUIController,
HALF_WIDTH, HALF_WIDTH,
HALF_HEIGHT, HALF_HEIGHT,
POP_BOX_WIDTH POP_BOX_WIDTH
} = Mota.require('@user/client-modules'); } = Mota.require('@user/client-modules');
const choice = choices.map((v, i) => [i, v.text]); const choice = choices.map((v, i) => [i, v.text]);
const selected = await routedChoices( const fn = noRoute ? getChoices : routedChoices;
const selected = await fn(
mainUIController, mainUIController,
choice, choice,
[HALF_WIDTH, HALF_HEIGHT, void 0, void 0, 0.5, 0.5], [HALF_WIDTH, HALF_HEIGHT, void 0, void 0, 0.5, 0.5],
@ -2282,7 +2285,7 @@ ui.prototype.drawConfirmBox = async function (
text, text,
yesCallback, yesCallback,
noCallback, noCallback,
ctx noRoute
) { ) {
if (main.replayChecking) { if (main.replayChecking) {
const confirm = (() => { const confirm = (() => {
@ -2293,6 +2296,7 @@ ui.prototype.drawConfirmBox = async function (
return Number(route.slice(8)) === 1; return Number(route.slice(8)) === 1;
} }
})(); })();
core.status.replay.toReplay.shift();
if (confirm) { if (confirm) {
yesCallback?.(); yesCallback?.();
} else { } else {
@ -2301,12 +2305,14 @@ ui.prototype.drawConfirmBox = async function (
} else { } else {
const { const {
routedConfirm, routedConfirm,
getConfirm,
mainUIController, mainUIController,
HALF_WIDTH, HALF_WIDTH,
HALF_HEIGHT, HALF_HEIGHT,
POP_BOX_WIDTH POP_BOX_WIDTH
} = Mota.require('@user/client-modules'); } = Mota.require('@user/client-modules');
const confirm = await routedConfirm( const fn = noRoute ? getConfirm : routedConfirm;
const confirm = await fn(
mainUIController, mainUIController,
text, text,
[HALF_WIDTH, HALF_HEIGHT, void 0, void 0, 0.5, 0.5], [HALF_WIDTH, HALF_HEIGHT, void 0, void 0, 0.5, 0.5],
@ -2369,7 +2375,7 @@ ui.prototype._drawQuickShop = function () {
}; };
}); });
choices.push('返回游戏'); choices.push('返回游戏');
this.drawChoices(null, choices); this.drawChoices(null, choices, void 0, true);
}; };
ui.prototype._drawSyncSave = function () { ui.prototype._drawSyncSave = function () {

View File

@ -109,7 +109,7 @@ function main() {
this.canvas = {}; this.canvas = {};
this.__VERSION__ = '2.10.0'; this.__VERSION__ = '2.10.0';
this.__VERSION_CODE__ = 510; this.__VERSION_CODE__ = 610;
} }
// >>>> body end // >>>> body end
@ -183,15 +183,12 @@ main.prototype.loadSync = function (mode, callback) {
coreData[t] = main[t]; coreData[t] = main[t];
}); });
core.initSync(coreData, callback); core.initSync(coreData, () => {});
main.loading.emit('coreInit'); main.loading.emit('coreInit');
core.initStatus.maps = core.maps._initMaps();
core.resize(); core.resize();
main.core = core; main.core = core;
core.completeAchievement = () => 0; callback?.();
core.plugin = { drawLight: 0 };
}; };
main.prototype.loadAsync = async function (mode, callback) { main.prototype.loadAsync = async function (mode, callback) {

View File

@ -185,9 +185,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
}, },
"flags": {}, "flags": {},
"followers": [], "followers": [],
"steps": 0, "steps": 0
"magicDef": 0,
"magicRed": 0
}, },
"startCanvas": [ "startCanvas": [
{ {

View File

@ -295,6 +295,7 @@ main.floors.sample1=
}, },
{ {
"type": "hide", "type": "hide",
"remove": true,
"time": 500 "time": 500
} }
], ],

View File

@ -17,6 +17,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
core.status.played = true; core.status.played = true;
// 初始化人物,图标,统计信息 // 初始化人物,图标,统计信息
core.status.hero = core.clone(hero); core.status.hero = core.clone(hero);
core.status.hero.buff ??= {};
window.hero = core.status.hero; window.hero = core.status.hero;
window.flags = core.status.hero.flags; window.flags = core.status.hero.flags;
core.events.setHeroIcon(core.status.hero.image, true); core.events.setHeroIcon(core.status.hero.image, true);
@ -56,27 +57,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
} else { } else {
flags.autoSkill ??= true; flags.autoSkill ??= true;
} }
// 兼容性调整
const h = core.status.hero;
if (h.magicDef === void 0 || h.magicDef === null) {
h.magicDef = 0;
}
if (!core.status.hero.buff) {
const buff = {};
core.status.hero.buff = buff;
const toDelete = [];
for (const [key, value] of Object.entries(flags)) {
if (/__\w+_buff__/.test(key)) {
const name = key.slice(2, -7);
buff[name] = value;
toDelete.push(key);
}
}
toDelete.forEach(v => {
delete flags[v];
});
}
}, },
win: function (reason, norank, noexit) { win: function (reason, norank, noexit) {
// 游戏获胜事件 // 游戏获胜事件
@ -88,30 +68,23 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
core.status.extraEvent = core.clone(core.status.event); core.status.extraEvent = core.clone(core.status.event);
} }
if (reason === '智慧之始') {
core.status.hero.hp +=
core.itemCount('yellowKey') * 5000 +
core.itemCount('blueKey') * 15000;
}
// 游戏获胜事件 // 游戏获胜事件
core.ui.closePanel(); core.ui.closePanel();
var replaying = core.isReplaying(); var replaying = core.isReplaying();
if (replaying) core.stopReplay(); if (replaying) core.stopReplay();
core.waitHeroToStop(function () { core.waitHeroToStop(function () {
if (!noexit) {
core.clearMap('all'); // 清空全地图
core.deleteAllCanvas(); // 删除所有创建的画布
}
reason = core.replaceText(reason); reason = core.replaceText(reason);
core.drawText( core.insertAction(
[ {
'\t[' + type: 'text',
(reason || '恭喜通关') + text: '你的分数是' + core.status.hero.hp,
']你的分数是${status:hp}。' title: reason ?? '恭喜通关'
], },
function () { void 0,
core.events.gameOver(reason || '', replaying, norank); void 0,
() => {
core.events.gameOver(reason ?? '', replaying, norank);
if (!noexit) core.status.gameOver = true;
} }
); );
}); });
@ -122,10 +95,17 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
var replaying = core.isReplaying(); var replaying = core.isReplaying();
core.stopReplay(); core.stopReplay();
core.waitHeroToStop(function () { core.waitHeroToStop(function () {
core.drawText( core.insertAction(
['\t[' + (reason || '结局1') + ']你死了。\n如题。'], {
function () { type: 'text',
text: '你死了。\n如题。',
title: reason ?? '结局1'
},
void 0,
void 0,
() => {
core.events.gameOver(null, replaying); core.events.gameOver(null, replaying);
core.status.gameOver = true;
} }
); );
}); });
@ -165,21 +145,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
if (bgm instanceof Array) bgm = bgm[0]; if (bgm instanceof Array) bgm = bgm[0];
if (!core.hasFlag('__bgm__')) core.playBgm(bgm); if (!core.hasFlag('__bgm__')) core.playBgm(bgm);
} }
// 更改画面色调
var color = core.getFlag('__color__', null);
if (!color && core.status.maps[floorId].color)
color = core.status.maps[floorId].color;
core.clearMap('curtain');
core.status.curtainColor = color;
if (color)
core.fillRect(
'curtain',
0,
0,
core._PX_,
core._PY_,
core.arrayToRGBA(color)
);
// 更改天气 // 更改天气
var weather = core.getFlag('__weather__', null); var weather = core.getFlag('__weather__', null);
if (!weather && core.status.maps[floorId].weather) if (!weather && core.status.maps[floorId].weather)
@ -228,8 +193,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
core.visitFloor(floorId); core.visitFloor(floorId);
} }
} }
// if (!flags.debug && !main.replayChecking)
// Mota.require('completion_r').checkVisitedFloor();
Mota.require('@user/data-base').hook.emit( Mota.require('@user/data-base').hook.emit(
'afterChangeFloor', 'afterChangeFloor',
floorId floorId
@ -342,16 +305,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
core.removeFlag('__fromLoad__'); core.removeFlag('__fromLoad__');
if (callback) callback(); if (callback) callback();
Mota.r(() => {
if (flags.onChase) {
const chase = Mota.require(
'@user/legacy-plugin-client'
);
const controller = chase.initChase(0);
controller.start(true);
}
});
}); });
Mota.require('@user/data-base').hook.emit('loadData'); Mota.require('@user/data-base').hook.emit('loadData');

View File

@ -13,6 +13,8 @@ import { RequiredData, RequiredIconsData, ResourceType } from './types';
import { splitResource, SplittedResource } from './build-resource'; import { splitResource, SplittedResource } from './build-resource';
import { formatSize } from './utils'; import { formatSize } from './utils';
const DEBUG_REPLAY = false;
const ansi = { const ansi = {
clear: '\x1b[2J\x1b[0f' clear: '\x1b[2J\x1b[0f'
}; };
@ -92,7 +94,8 @@ async function buildData(outDir: string, entry: string) {
name: 'ProcessData', name: 'ProcessData',
fileName: 'data', fileName: 'data',
formats: ['iife'] formats: ['iife']
} },
minify: !DEBUG_REPLAY
} }
} satisfies UserConfig); } satisfies UserConfig);

View File

@ -1,10 +1,14 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import { copy, emptyDir, ensureDir } from 'fs-extra'; import { copy, emptyDir, ensureDir } from 'fs-extra';
import { writeFile } from 'fs/promises';
import { resolve } from 'path'; import { resolve } from 'path';
const base = resolve(process.cwd()); const base = resolve(process.cwd());
const template = resolve(base, 'template'); const template = resolve(base, 'template');
const serve = `在 2.B 样板中,不再使用先前的启动服务,而使用一个单独的软件。
959329661 - `;
async function packTemplate() { async function packTemplate() {
await ensureDir(template); await ensureDir(template);
await emptyDir(template); await emptyDir(template);
@ -41,6 +45,8 @@ async function packTemplate() {
) )
); );
await writeFile(resolve(template, '启动服务呢?.txt'), serve, 'utf-8');
console.log(`样板打包完成`); console.log(`样板打包完成`);
} }

View File

@ -759,14 +759,14 @@ interface Ui {
textImage(content: string, lineHeight?: number): HTMLCanvasElement; textImage(content: string, lineHeight?: number): HTMLCanvasElement;
/** /**
* @deprecated `getChoices` \ * @deprecated 使 `getChoices` \
* * drawChoices
*/ */
drawChoices( drawChoices2(
content: string, content: string,
choices: object[], choices: object[],
width?: number, width?: number,
ctx?: CtxRefer noRoute?: CtxRefer
): void; ): void;
/** /**
@ -777,7 +777,7 @@ interface Ui {
text: string, text: string,
yesCallback?: () => void, yesCallback?: () => void,
noCallback?: () => void, noCallback?: () => void,
ctx?: CtxRefer noRoute?: boolean
): void; ): void;
/** /**