From 5ea7137e6f1f22114f822aced7f23519fbd9d3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=8F=E3=82=93?= <149618204+wancor1@users.noreply.github.com> Date: Sat, 13 Dec 2025 12:43:52 +0900 Subject: [PATCH] Fix infinite rebuild recursion in settings UI Fix settings menu crash caused by infinite rebuild recursion SettingsTableX was able to call rebuild() recursively from multiple paths, resulting in StackOverflowError. Added rebuild guard and removed implicit rebuild triggers. --- .../net/liplum/ui/settings/SettingsTableX.kt | 63 ++++++++++++------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/main/src/net/liplum/ui/settings/SettingsTableX.kt b/main/src/net/liplum/ui/settings/SettingsTableX.kt index ff73b42e..3ad76ab8 100644 --- a/main/src/net/liplum/ui/settings/SettingsTableX.kt +++ b/main/src/net/liplum/ui/settings/SettingsTableX.kt @@ -1,40 +1,55 @@ package net.liplum.ui.settings import arc.Core -import mindustry.ui.dialogs.SettingsMenuDialog.SettingsTable +import arc.scene.ui.layout.Cell +import mindustry.ui.dialogs.SettingsMenuDialog import net.liplum.common.delegate.Delegate import plumy.dsl.bundle +import kotlin.jvm.functions.Function0 +import kotlin.jvm.functions.Function1 -class SettingsTableX : SettingsTable() { +class SettingsTableX : SettingsMenuDialog.SettingsTable() { val onReset = Delegate() - fun onSettingsReset(handler: () -> Unit) { + var genHeader: (SettingsTableX) -> Unit = {} + private var rebuilding = false + fun onSettingsReset(handler: Function0) { onReset.add(handler) } - var genHeader: (SettingsTableX) -> Unit = {} - set(value) { - field = value - rebuild() - } - override fun rebuild() { - clearChildren() + if (rebuilding) return + rebuilding = true - genHeader(this) - for (setting in list) { - if (setting is ISettingCondition && !setting.canShow()) continue - setting.add(this) - } - button("settings.reset".bundle) { + try { + clearChildren() + genHeader(this) for (setting in list) { - if (setting.name == null || setting.title == null) continue - Core.settings.put(setting.name, Core.settings.getDefault(setting.name)) + if (setting is ISettingCondition && !setting.canShow()) continue + setting.add(this) + } + button( + bundle("settings.reset", "Reset to Defaults") + ) { + resetSettings() + }.margin(14f).width(240f).pad(6f) + for (cell: Cell<*> in cells) { + cell.pad(5f) + } + } finally { + rebuilding = false + } + } + + private fun resetSettings() { + for (setting in list) { + if (setting.name != null && setting.title != null) { + Core.settings.put( + setting.name, + Core.settings.getDefault(setting.name) + ) } - onReset() - rebuild() - }.margin(14f).width(240f).pad(6f) - for (cell in cells) { - cell.pad(5f) } + onReset.invoke() + rebuild() } -} \ No newline at end of file +}