@@ -22,12 +22,13 @@ import com.lambda.config.Config
2222import com.lambda.config.Tab
2323import com.lambda.config.categories.GuiCategory
2424import com.lambda.config.entries.Setting.Companion.onValueChange
25- import com.lambda.config.settings.complex.KeybindSetting.Companion.onPress
25+ import com.lambda.config.settings.complex.KeybindSetting.Companion.onPressUnsafe
2626import com.lambda.core.Loadable
2727import com.lambda.event.events.GuiEvent
28- import com.lambda.event.listener.SafeListener .Companion.listen
28+ import com.lambda.event.listener.UnsafeListener .Companion.listenUnsafe
2929import com.lambda.gui.DearImGui
3030import com.lambda.gui.LambdaScreen
31+ import com.lambda.gui.OverlayBackgroundScreen
3132import com.lambda.gui.MenuBar
3233import com.lambda.gui.MenuBar.buildMenuBar
3334import com.lambda.gui.components.QuickSearch.renderQuickSearch
@@ -45,6 +46,7 @@ import com.lambda.imgui.flag.ImGuiHoveredFlags
4546import com.lambda.imgui.flag.ImGuiWindowFlags
4647import com.lambda.module.ModuleRegistry
4748import com.lambda.module.modules.client.Client
49+ import com.lambda.module.modules.combat.autodisconnect.AutoDisconnectScreen
4850import com.lambda.module.tag.ModuleTag
4951import com.lambda.module.tag.ModuleTag.Companion.shownTags
5052import com.lambda.sound.LambdaSound
@@ -56,9 +58,11 @@ import com.lambda.util.WindowUtils.setLambdaWindowIcon
5658import net.minecraft.SharedConstants
5759import net.minecraft.client.gui.screen.ChatScreen
5860import net.minecraft.client.gui.screen.Screen
61+ import net.minecraft.client.gui.screen.TitleScreen
5962import net.minecraft.client.gui.screen.ingame.AnvilScreen
6063import net.minecraft.client.gui.screen.ingame.CommandBlockScreen
6164import net.minecraft.client.gui.screen.ingame.SignEditScreen
65+ import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen
6266import net.minecraft.client.util.Icons
6367import java.awt.Color
6468
@@ -69,12 +73,29 @@ object ClickGuiLayout : Loadable, Config(
6973) {
7074 var open = false
7175 var developerMode = false
76+ // onPressUnsafe (not onPress) so the GUI can also be toggled from menu screens
77+ // (title, multiplayer, world-select) where there is no SafeContext, not just in-game.
7278 val keybind by setting(" Keybind" , KeyCode .Y , screenCheck = false )
73- .onPress {
74- if (! open && mc.currentScreen != null ) return @onPress
75- if (DearImGui .io.wantTextInput) return @onPress
79+ .onPressUnsafe {
80+ if (DearImGui .io.wantTextInput ) return @onPressUnsafe
81+ if (! open && ! canOpenOver(mc.currentScreen)) return @onPressUnsafe
7682 toggle()
7783 }
84+
85+ /* *
86+ * Screens (besides the in-game/null case) the GUI is allowed to open over.
87+ * Add a class here to support opening the GUI on another screen.
88+ */
89+ private val backgroundScreenTypes = mutableListOf (
90+ TitleScreen ::class .java,
91+ MultiplayerScreen ::class .java,
92+ AutoDisconnectScreen ::class .java,
93+ )
94+
95+ /* * True when the GUI may be opened over [screen]; null means in-game. */
96+ fun canOpenOver (screen : Screen ? ): Boolean =
97+ screen == null || backgroundScreenTypes.any { it.isInstance(screen) }
98+
7899 private var initialLayoutComplete = false
79100 private var frameCount = 0
80101 private var activeDragWindowName: String? = null
@@ -246,8 +267,8 @@ object ClickGuiLayout : Loadable, Config(
246267 @Tab(COLORS_TAB ) val modalWindowDimBg by setting(" Modal Window Dim Background" , Color (35 , 0 , 14 , 90 ))
247268
248269 init {
249- listen <GuiEvent .NewImguiFrame > {
250- if (! open) return @listen
270+ listenUnsafe <GuiEvent .NewImguiFrame > {
271+ if (! open) return @listenUnsafe
251272
252273 buildLayout {
253274 buildMenuBar()
@@ -361,16 +382,21 @@ object ClickGuiLayout : Loadable, Config(
361382
362383 fun toggle () {
363384 if (open) {
364- close()
385+ // LambdaScreen.close() restores the background screen and triggers
386+ // removed() -> close(), which flips `open` off and plays the sound.
365387 LambdaScreen .close()
366388 } else {
367- if (! mc.currentScreen.hasInput) {
368- if (Client .clientSounds) LambdaSound .ModuleOn .play()
369- mc.setScreen(LambdaScreen )
370- open = true
371- frameCount = 0
372- initialLayoutComplete = false
373- }
389+ val current = mc.currentScreen
390+ if (current.hasInput) return
391+ if (Client .clientSounds) LambdaSound .ModuleOn .play()
392+ LambdaScreen .parentScreen = if (current is LambdaScreen ) null else current
393+ // Let the parent retain resources past the removed() that setScreen triggers,
394+ // since we restore it when the GUI closes.
395+ (current as ? OverlayBackgroundScreen )?.onOverlaidByGui()
396+ mc.setScreen(LambdaScreen )
397+ open = true
398+ frameCount = 0
399+ initialLayoutComplete = false
374400 }
375401 }
376402
0 commit comments