@@ -6,24 +6,24 @@ This file contains the menu system.
6
6
import { CommandError , fail } from "./commands" ;
7
7
import { FishPlayer } from "./players" ;
8
8
import { outputFail } from "./utils" ;
9
- import { crash , parseError } from './funcs' ;
9
+ import { parseError } from './funcs' ;
10
10
import { to2DArray } from './funcs' ;
11
11
import { Promise } from "./promise" ;
12
12
13
+ /** Used to change the behavior of adding another menu when being run in a menu callback. */
14
+ let isInMenuCallback = false ;
13
15
/** Stores a mapping from name to the numeric id of a listener that has been registered. */
14
16
const registeredListeners : Record < string , number > = { } ;
15
17
/** Stores all listeners in use by fish-commands. */
16
18
const listeners = {
17
19
generic ( player , option ) {
18
20
const fishSender = FishPlayer . get ( player ) ;
19
21
20
- //TODO replace with queue
21
- const prevCallback = fishSender . activeMenu . callback ;
22
- fishSender . activeMenu . callback ?.( fishSender , option ) ;
23
- //if the callback wasn't modified, then clear it
24
- if ( fishSender . activeMenu . callback === prevCallback )
25
- fishSender . activeMenu . callback = undefined ;
26
- //otherwise, the menu spawned another menu that needs to be handled
22
+ const prevCallback = fishSender . activeMenus . shift ( ) ;
23
+ if ( ! prevCallback ) return ; //No menu to process, do nothing
24
+ isInMenuCallback = true ;
25
+ prevCallback . callback ( option ) ;
26
+ isInMenuCallback = false ;
27
27
} ,
28
28
none ( player , option ) {
29
29
//do nothing
@@ -82,15 +82,17 @@ export const Menu = {
82
82
}
83
83
84
84
//The target fishPlayer has a property called activeMenu, which stores information about the last menu triggered.
85
- target . activeMenu . callback = ( fishSender , option ) => {
85
+ //If menu() is being called from a menu calback, add it to the front of the queue so it is processed before any other menus.
86
+ //Otherwise, two multi-step menus queued together would alternate, which would confuse the player.
87
+ target . activeMenus [ isInMenuCallback ? "unshift" : "push" ] ( { callback ( option ) {
86
88
//Additional permission validation could be done here, but the only way that callback() can be called is if the above statement executed,
87
89
//and on sensitive menus such as the stop menu, the only way to reach that is if menu() was called by the /stop command,
88
90
//which already checks permissions.
89
91
//Additionally, the callback is cleared by the generic menu listener after it is executed.
90
92
91
93
try {
92
94
//We do need to validate option though, as it can be any number.
93
- if ( option === - 1 || option === fishSender . activeMenu . cancelOptionId || ! ( option in options ) ) {
95
+ if ( option === - 1 || option === cancelOptionId || ! ( option in options ) ) {
94
96
//Consider any invalid option to be a cancellation
95
97
if ( onCancel == "null" ) resolve ( null as never ) ;
96
98
else if ( onCancel == "reject" ) reject ( "cancel" as never ) ;
@@ -109,7 +111,7 @@ export const Menu = {
109
111
Log . err ( err as Error ) ;
110
112
}
111
113
}
112
- } ;
114
+ } } ) ;
113
115
114
116
Call . menu ( target . con , registeredListeners . generic , title , description , arrangedOptions ) ;
115
117
return promise ;
0 commit comments