From e04d69b34197fb0cd1aae77dc35f707908422dfb Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Tue, 2 Dec 2025 21:15:24 +0000 Subject: [PATCH 1/9] initial changes --- .../com/lambda/mixin/CrashReportMixin.java | 4 +- .../lambda/command/commands/ConfigCommand.kt | 4 +- .../com/lambda/config/AbstractSetting.kt | 265 ---------------- .../com/lambda/config/AutomationConfig.kt | 2 - .../kotlin/com/lambda/config/ConfigEditor.kt | 47 ++- .../kotlin/com/lambda/config/Configurable.kt | 151 +++++----- .../kotlin/com/lambda/config/Configuration.kt | 12 +- .../kotlin/com/lambda/config/SettingCore.kt | 283 ++++++++++++++++++ .../kotlin/com/lambda/config/SettingGroup.kt | 6 +- .../com/lambda/config/UserAutomationConfig.kt | 3 +- .../{CharSetting.kt => CharSettingCore.kt} | 27 +- ...ctionSetting.kt => FunctionSettingCore.kt} | 26 +- ...umericSetting.kt => NumericSettingCore.kt} | 43 ++- ...{StringSetting.kt => StringSettingCore.kt} | 33 +- ...tting.kt => BlockCollectionSettingCore.kt} | 22 +- ...tting.kt => ClassCollectionSettingCore.kt} | 26 +- ...ionSetting.kt => CollectionSettingCore.kt} | 58 ++-- ...etting.kt => ItemCollectionSettingCore.kt} | 24 +- .../{MapSetting.kt => MapSettingCore.kt} | 24 +- ...ooleanSetting.kt => BooleanSettingCore.kt} | 29 +- .../{EnumSetting.kt => EnumSettingCore.kt} | 28 +- ...ckPosSetting.kt => BlockPosSettingCore.kt} | 25 +- .../{BlockSetting.kt => BlockSettingCore.kt} | 23 +- .../{ColorSetting.kt => ColorSettingCore.kt} | 27 +- ...eybindSetting.kt => KeybindSettingCore.kt} | 30 +- .../{Vec3dSetting.kt => Vec3DSettingCore.kt} | 27 +- ...{DoubleSetting.kt => DoubleSettingCore.kt} | 25 +- .../{FloatSetting.kt => FloatSettingCore.kt} | 23 +- ...ntegerSetting.kt => IntegerSettingCore.kt} | 25 +- .../{LongSetting.kt => LongSettingCore.kt} | 25 +- .../com/lambda/gui/components/QuickSearch.kt | 6 +- .../lambda/gui/components/SettingsWidget.kt | 16 +- .../request/rotating/RotationConfig.kt | 4 +- src/main/kotlin/com/lambda/module/Module.kt | 4 +- src/main/kotlin/com/lambda/util/Formatting.kt | 4 +- 35 files changed, 651 insertions(+), 730 deletions(-) delete mode 100644 src/main/kotlin/com/lambda/config/AbstractSetting.kt create mode 100644 src/main/kotlin/com/lambda/config/SettingCore.kt rename src/main/kotlin/com/lambda/config/settings/{CharSetting.kt => CharSettingCore.kt} (78%) rename src/main/kotlin/com/lambda/config/settings/{FunctionSetting.kt => FunctionSettingCore.kt} (68%) rename src/main/kotlin/com/lambda/config/settings/{NumericSetting.kt => NumericSettingCore.kt} (77%) rename src/main/kotlin/com/lambda/config/settings/{StringSetting.kt => StringSettingCore.kt} (73%) rename src/main/kotlin/com/lambda/config/settings/collections/{BlockCollectionSetting.kt => BlockCollectionSettingCore.kt} (83%) rename src/main/kotlin/com/lambda/config/settings/collections/{ClassCollectionSetting.kt => ClassCollectionSettingCore.kt} (85%) rename src/main/kotlin/com/lambda/config/settings/collections/{CollectionSetting.kt => CollectionSettingCore.kt} (73%) rename src/main/kotlin/com/lambda/config/settings/collections/{ItemCollectionSetting.kt => ItemCollectionSettingCore.kt} (82%) rename src/main/kotlin/com/lambda/config/settings/collections/{MapSetting.kt => MapSettingCore.kt} (70%) rename src/main/kotlin/com/lambda/config/settings/comparable/{BooleanSetting.kt => BooleanSettingCore.kt} (70%) rename src/main/kotlin/com/lambda/config/settings/comparable/{EnumSetting.kt => EnumSettingCore.kt} (84%) rename src/main/kotlin/com/lambda/config/settings/complex/{BlockPosSetting.kt => BlockPosSettingCore.kt} (76%) rename src/main/kotlin/com/lambda/config/settings/complex/{BlockSetting.kt => BlockSettingCore.kt} (75%) rename src/main/kotlin/com/lambda/config/settings/complex/{ColorSetting.kt => ColorSettingCore.kt} (76%) rename src/main/kotlin/com/lambda/config/settings/complex/{KeybindSetting.kt => KeybindSettingCore.kt} (90%) rename src/main/kotlin/com/lambda/config/settings/complex/{Vec3dSetting.kt => Vec3DSettingCore.kt} (73%) rename src/main/kotlin/com/lambda/config/settings/numeric/{DoubleSetting.kt => DoubleSettingCore.kt} (79%) rename src/main/kotlin/com/lambda/config/settings/numeric/{FloatSetting.kt => FloatSettingCore.kt} (79%) rename src/main/kotlin/com/lambda/config/settings/numeric/{IntegerSetting.kt => IntegerSettingCore.kt} (75%) rename src/main/kotlin/com/lambda/config/settings/numeric/{LongSetting.kt => LongSettingCore.kt} (79%) diff --git a/src/main/java/com/lambda/mixin/CrashReportMixin.java b/src/main/java/com/lambda/mixin/CrashReportMixin.java index ec4521c81..d0d144c8f 100644 --- a/src/main/java/com/lambda/mixin/CrashReportMixin.java +++ b/src/main/java/com/lambda/mixin/CrashReportMixin.java @@ -18,7 +18,7 @@ package com.lambda.mixin; import com.lambda.Lambda; -import com.lambda.config.AbstractSetting; +import com.lambda.config.Setting; import com.lambda.module.Module; import com.lambda.module.ModuleRegistry; import com.lambda.util.DynamicExceptionKt; @@ -67,7 +67,7 @@ String injectString(ReportType type, List extraInfo, Operation o module.getSettings() .stream() - .filter(AbstractSetting::isModified) + .filter(Setting::isModified) .forEach(setting -> list.add(String.format("\t\t%s -> %s", setting.getName(), setting.getValue()))); }); } diff --git a/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt b/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt index 0c500f8b6..9147800f0 100644 --- a/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt +++ b/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt @@ -79,10 +79,10 @@ object ConfigCommand : LambdaCommand( val conf = Configuration.configurableByCommandName(confName) ?: run { return@executeWithResult failure("$confName is not a valid configurable.") } - val set = Configuration.settingByCommandName(conf, settingName) ?: run { + val setDel = Configuration.settingDelegateByCommandName(conf, settingName) ?: run { return@executeWithResult failure("$settingName is not a valid setting for $confName.") } - set.reset() + setDel.reset() return@executeWithResult success() } } diff --git a/src/main/kotlin/com/lambda/config/AbstractSetting.kt b/src/main/kotlin/com/lambda/config/AbstractSetting.kt deleted file mode 100644 index 0e08bdc37..000000000 --- a/src/main/kotlin/com/lambda/config/AbstractSetting.kt +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2025 Lambda - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lambda.config - -import com.google.gson.JsonElement -import com.google.gson.JsonParser -import com.lambda.Lambda.LOG -import com.lambda.Lambda.gson -import com.lambda.brigadier.CommandResult.Companion.failure -import com.lambda.brigadier.CommandResult.Companion.success -import com.lambda.brigadier.argument.string -import com.lambda.brigadier.argument.value -import com.lambda.brigadier.executeWithResult -import com.lambda.brigadier.required -import com.lambda.command.CommandRegistry -import com.lambda.command.commands.ConfigCommand -import com.lambda.context.SafeContext -import com.lambda.gui.Layout -import com.lambda.threading.runSafe -import com.lambda.util.Communication.info -import com.lambda.util.Describable -import com.lambda.util.Nameable -import com.lambda.util.NamedEnum -import com.lambda.util.extension.CommandBuilder -import com.lambda.util.text.ClickEvents -import com.lambda.util.text.HoverEvents -import com.lambda.util.text.TextBuilder -import com.lambda.util.text.buildText -import com.lambda.util.text.clickEvent -import com.lambda.util.text.highlighted -import com.lambda.util.text.hoverEvent -import com.lambda.util.text.literal -import net.minecraft.command.CommandRegistryAccess -import java.lang.reflect.Type -import kotlin.properties.Delegates -import kotlin.reflect.KProperty - -/** - * Represents a setting with a [defaultValue], [visibility] condition, and [description]. - * This setting is serializable ([Jsonable]) and has a [name]. - * - * When the [value] is modified, all registered [listeners] are notified. - * The [visibility] of the setting can be checked with the [isVisible] property. - * The setting can be [reset] to its [defaultValue]. - * - * Simple Usage: - * ```kotlin - * // this uses the delegate (by) association to access the setting value in the code directly. - * val mode by setting("Mode", Modes.FREEZE, { page == Page.CUSTOM }, "The mode of the module.") - * - * init { - * listener { - * LOG.info("Mode: $mode") // direct access of the value - * } - * } - * ``` - * - * Advanced usage with listeners: - * ```kotlin - * // notice how this does not use the delegate (by) association, to access the setting object to register listeners. - * val mode = setting("Mode", Modes.FREEZE, { page == Page.CUSTOM }, "The mode of the module.") - * - * init { - * mode.listener { from, to -> - * // Do something when the mode changes in a safe context - * } - * mode.unsafeListener { from, to -> - * // Do something when the mode changes in an unsafe context - * } - * - * listener { - * LOG.info("Mode: ${mode.value}") // indirect access of the value - * } - * } - * ``` - * - * @property defaultValue The default value of the setting. - * @property description A description of the setting. - * @property type The type reflection of the setting. - * @property visibility A function that determines whether the setting is visible. - */ -abstract class AbstractSetting( - override var name: String, - internal var defaultValue: T, - val type: Type, - override var description: String, - var visibility: () -> Boolean, -) : Jsonable, Nameable, Describable, Layout { - private val listeners = mutableListOf>() - var disabled = { false } - var groups: MutableList> = mutableListOf() - - var value by Delegates.observable(defaultValue) { _, from, to -> - listeners.forEach { - if (it.requiresValueChange && from == to) return@forEach - it.execute(from, to) - } - } - - val isModified get() = value != defaultValue - - operator fun getValue(thisRef: Any?, property: KProperty<*>) = value - open operator fun setValue(thisRef: Any?, property: KProperty<*>, valueIn: T) { - value = valueIn - } - - override fun toJson(): JsonElement = - gson.toJsonTree(value, type) - - override fun loadFromJson(serialized: JsonElement) { - runCatching { - value = gson.fromJson(serialized, type) - }.onFailure { - LOG.warn("Failed to load setting ${this.name} with value $serialized. Resetting to default value $defaultValue") - value = defaultValue - } - } - - class ValueListener(val requiresValueChange: Boolean, val execute: (from: T, to: T) -> Unit) - - /** - * Will only register changes of the variable, not the content of the variable! - * E.g., if the variable is a list, it will only register if the list reference changes, not if the content of the list changes. - */ - fun onValueChange(block: SafeContext.(from: T, to: T) -> Unit) = apply { - listeners.add(ValueListener(true) { from, to -> - runSafe { - block(from, to) - } - }) - } - - fun onValueChangeUnsafe(block: (from: T, to: T) -> Unit) = apply { - listeners.add(ValueListener(true, block)) - } - - fun onValueSet(block: (from: T, to: T) -> Unit) = apply { - listeners.add(ValueListener(false, block)) - } - - fun disabled(predicate: () -> Boolean) = apply { - disabled = predicate - } - - fun group(path: List, vararg continuation: NamedEnum) = apply { - groups.add(path + continuation) - } - - fun group(vararg path: NamedEnum) = apply { - groups.add(path.toList()) - } - - fun group(path: NamedEnum?) = apply { - path?.let { groups.add(listOf(it)) } - } - - fun reset(silent: Boolean = false) { - if (!silent && value == defaultValue) { - ConfigCommand.info(notChangedMessage()) - return - } - if (!silent) ConfigCommand.info(resetMessage(value, defaultValue)) - value = defaultValue - } - - open fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(string("value as JSON")) { value -> - executeWithResult { - val valueString = value().value() - val parsed = try { - JsonParser.parseString("\"$valueString\"") - } catch (_: Exception) { - return@executeWithResult failure("$valueString is not a valid JSON string.") - } - val config = Configuration.configurableBySetting(this@AbstractSetting) - ?: return@executeWithResult failure("No config found for $name.") - val previous = this@AbstractSetting.value - try { - loadFromJson(parsed) - } catch (_: Exception) { - return@executeWithResult failure("Failed to load $valueString as a ${type::class.simpleName} for $name in ${config.name}.") - } - ConfigCommand.info(setMessage(previous, this@AbstractSetting.value)) - return@executeWithResult success() - } - } - } - - fun trySetValue(newValue: T) { - if (newValue == value) { - ConfigCommand.info(notChangedMessage()) - } else { - val previous = value - value = newValue - ConfigCommand.info(setMessage(previous, newValue)) - } - } - - private fun setMessage(previousValue: T, newValue: T) = buildText { - literal("Set ") - changedMessage(previousValue, newValue) - val config = Configuration.configurableBySetting(this@AbstractSetting) ?: return@buildText - clickEvent(ClickEvents.suggestCommand("${CommandRegistry.prefix}${ConfigCommand.name} reset ${config.commandName} $commandName")) { - hoverEvent(HoverEvents.showText(buildText { - literal("Click to reset to default value ") - highlighted(defaultValue.toString()) - })) { - highlighted(" [Reset]") - } - } - } - - private fun resetMessage(previousValue: T, newValue: T) = buildText { - literal("Reset ") - changedMessage(previousValue, newValue) - } - - private fun notChangedMessage() = buildText { - literal("No changes made to ") - highlighted(name) - literal(" as it is already set to ") - highlighted(value.toString()) - literal(".") - } - - private fun TextBuilder.changedMessage(previousValue: T, newValue: T) { - val config = Configuration.configurableBySetting(this@AbstractSetting) ?: return - highlighted(config.name) - literal(" > ") - highlighted(name) - literal(" from ") - highlighted(previousValue.toString()) - literal(" to ") - highlighted(newValue.toString()) - literal(".") - clickEvent(ClickEvents.suggestCommand("${CommandRegistry.prefix}${ConfigCommand.name} set ${config.commandName} $commandName $previousValue")) { - hoverEvent(HoverEvents.showText(buildText { - literal("Click to undo to previous value ") - highlighted(previousValue.toString()) - })) { - highlighted(" [Undo]") - } - } - } - - override fun toString() = "Setting $name: $value of type ${type.typeName}" - - override fun equals(other: Any?) = other is AbstractSetting<*> && name == other.name - override fun hashCode() = name.hashCode() -} diff --git a/src/main/kotlin/com/lambda/config/AutomationConfig.kt b/src/main/kotlin/com/lambda/config/AutomationConfig.kt index bd67681ed..4e1039ad5 100644 --- a/src/main/kotlin/com/lambda/config/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/AutomationConfig.kt @@ -59,8 +59,6 @@ open class AutomationConfig( override val hotbarConfig = HotbarSettings(this, Group.Hotbar) override val eatConfig = EatSettings(this, Group.Eat) - val hiddenSettings = mutableSetOf>() - companion object { context(module: Module) fun MutableAutomationConfig.setDefaultAutomationConfig( diff --git a/src/main/kotlin/com/lambda/config/ConfigEditor.kt b/src/main/kotlin/com/lambda/config/ConfigEditor.kt index 856021a7b..eee9a8671 100644 --- a/src/main/kotlin/com/lambda/config/ConfigEditor.kt +++ b/src/main/kotlin/com/lambda/config/ConfigEditor.kt @@ -17,7 +17,6 @@ package com.lambda.config -import com.lambda.config.AutomationConfig.Companion.DEFAULT.hiddenSettings import com.lambda.util.NamedEnum import kotlin.reflect.KProperty0 import kotlin.reflect.jvm.isAccessible @@ -39,62 +38,60 @@ open class SettingGroupEditor(open val c: T) { throw IllegalStateException("Could not access delegate for property $name", e) } - fun KProperty0<*>.settingDelegate() = - this.delegate as? AbstractSetting - ?: throw IllegalStateException("Setting (${(delegate as AbstractSetting<*>).name}) delegate did not match current value's type") + fun KProperty0.setting() = + this.delegate as? Setting, T> + ?: throw IllegalStateException("Setting delegate did not match current value's type") + + fun KProperty0.settingCore() = setting().core @SettingEditorDsl - inline fun KProperty0.edit(edits: TypedEditBuilder.(AbstractSetting) -> Unit) { - val setting = settingDelegate() - TypedEditBuilder(this@SettingGroupEditor, listOf(setting)).edits(setting) + inline fun KProperty0.edit(edits: TypedEditBuilder.(SettingCore) -> Unit) { + val delegate = setting() + TypedEditBuilder(this@SettingGroupEditor, listOf(delegate)).edits(delegate.core) } @SettingEditorDsl inline fun KProperty0.editWith( other: KProperty0, - edits: TypedEditBuilder.(AbstractSetting) -> Unit - ) { - val setting = settingDelegate() - TypedEditBuilder(this@SettingGroupEditor, listOf(setting)).edits(other.settingDelegate()) - } + edits: TypedEditBuilder.(SettingCore) -> Unit + ) = TypedEditBuilder(this@SettingGroupEditor, listOf(setting())).edits(other.settingCore()) @SettingEditorDsl fun edit( vararg settings: KProperty0<*>, edits: BasicEditBuilder.() -> Unit - ) { BasicEditBuilder(this, settings.map { it.delegate } as List>).apply(edits) } + ) = BasicEditBuilder(this, settings.map { it.setting() }).apply(edits) @SettingEditorDsl inline fun editWith( vararg settings: KProperty0<*>, other: KProperty0, - edits: BasicEditBuilder.(AbstractSetting) -> Unit - ) = BasicEditBuilder(this, settings.map { it.delegate } as List>).edits(other.settingDelegate()) + edits: BasicEditBuilder.(SettingCore) -> Unit + ) = BasicEditBuilder(this, settings.map { it.setting() }).edits(other.settingCore()) @SettingEditorDsl inline fun editTyped( vararg settings: KProperty0, edits: TypedEditBuilder.() -> Unit - ) { TypedEditBuilder(this, settings.map { it.delegate } as List>).apply(edits) } + ) = TypedEditBuilder(this, settings.map { it.setting() }).apply(edits) @SettingEditorDsl inline fun editTypedWith( vararg settings: KProperty0, other: KProperty0, - edits: TypedEditBuilder.(AbstractSetting) -> Unit - ) = TypedEditBuilder(this, settings.map { it.delegate } as List>).edits(other.delegate as AbstractSetting) + edits: TypedEditBuilder.(SettingCore) -> Unit + ) = TypedEditBuilder(this, settings.map { it.setting() }).edits(other.settingCore()) @SettingEditorDsl - fun hide(settings: Collection>) { + fun hide(settings: Collection>) { c.settings.removeAll(settings) - hiddenSettings.addAll(settings) } @SettingEditorDsl fun hide(vararg settings: KProperty0<*>) = - hide((settings.map { it.delegate } as List>)) + hide(settings.map { it.setting() }) - open class BasicEditBuilder(val c: SettingGroupEditor<*>, open val settings: Collection>) { + open class BasicEditBuilder(val c: SettingGroupEditor<*>, open val settings: Collection>) { @SettingEditorDsl fun visibility(vis: () -> Boolean) = settings.forEach { it.visibility = vis } @@ -113,13 +110,13 @@ open class SettingGroupEditor(open val c: T) { class TypedEditBuilder( c: SettingGroupEditor<*>, - override val settings: Collection> + override val settings: Collection, T>> ) : BasicEditBuilder(c, settings) { @SettingEditorDsl fun defaultValue(value: T) = settings.forEach { - it.defaultValue = value - it.value = value + it.core.defaultValue = value + it.core.value = value } } } diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index ac1cd1389..1927d6247 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -21,54 +21,49 @@ import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.reflect.TypeToken import com.lambda.Lambda.LOG -import com.lambda.config.settings.CharSetting -import com.lambda.config.settings.FunctionSetting -import com.lambda.config.settings.StringSetting -import com.lambda.config.settings.collections.BlockCollectionSetting -import com.lambda.config.settings.collections.ClassCollectionSetting -import com.lambda.config.settings.collections.CollectionSetting -import com.lambda.config.settings.collections.ItemCollectionSetting -import com.lambda.config.settings.collections.MapSetting -import com.lambda.config.settings.comparable.BooleanSetting -import com.lambda.config.settings.comparable.EnumSetting +import com.lambda.config.settings.CharSettingCore +import com.lambda.config.settings.FunctionSettingCore +import com.lambda.config.settings.StringSettingCore +import com.lambda.config.settings.collections.BlockCollectionSettingCore +import com.lambda.config.settings.collections.ClassCollectionSettingCore +import com.lambda.config.settings.collections.CollectionSettingCore +import com.lambda.config.settings.collections.ItemCollectionSettingCore +import com.lambda.config.settings.collections.MapSettingCore +import com.lambda.config.settings.comparable.BooleanSettingCore +import com.lambda.config.settings.comparable.EnumSettingCore import com.lambda.config.settings.complex.Bind -import com.lambda.config.settings.complex.BlockPosSetting -import com.lambda.config.settings.complex.BlockSetting -import com.lambda.config.settings.complex.ColorSetting -import com.lambda.config.settings.complex.KeybindSetting -import com.lambda.config.settings.complex.Vec3dSetting -import com.lambda.config.settings.numeric.DoubleSetting -import com.lambda.config.settings.numeric.FloatSetting -import com.lambda.config.settings.numeric.IntegerSetting -import com.lambda.config.settings.numeric.LongSetting +import com.lambda.config.settings.complex.BlockPosSettingCore +import com.lambda.config.settings.complex.BlockSettingCore +import com.lambda.config.settings.complex.ColorSettingCore +import com.lambda.config.settings.complex.KeybindSettingCore +import com.lambda.config.settings.complex.Vec3DSettingCore +import com.lambda.config.settings.numeric.DoubleSettingCore +import com.lambda.config.settings.numeric.FloatSettingCore +import com.lambda.config.settings.numeric.IntegerSettingCore +import com.lambda.config.settings.numeric.LongSettingCore import com.lambda.util.Communication.logError import com.lambda.util.KeyCode import com.lambda.util.Nameable -import com.lambda.util.reflections.getInstancesImplementingWithParameters import imgui.flag.ImGuiInputTextFlags -import io.github.classgraph.ClassInfoList import net.minecraft.block.Block import net.minecraft.item.Item -import net.minecraft.network.listener.ClientPlayPacketListener -import net.minecraft.network.packet.Packet import net.minecraft.registry.Registries import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Vec3d import java.awt.Color -import kotlin.reflect.KClass /** - * Represents a set of [AbstractSetting]s that are associated with the [name] of the [Configurable]. + * Represents a set of [SettingCore]s that are associated with the [name] of the [Configurable]. * The settings are managed by this [Configurable] and are saved and loaded as part of the [Configuration]. * * This class also provides a series of helper methods ([setting]) for creating different types of settings. * - * @property settings A set of [AbstractSetting]s that this configurable manages. + * @property settings A set of [SettingCore]s that this configurable manages. */ abstract class Configurable( private val configuration: Configuration, ) : Jsonable, Nameable { - val settings = mutableListOf>() + val settings = mutableListOf>() val settingGroups = mutableListOf() init { @@ -77,11 +72,10 @@ abstract class Configurable( private fun registerConfigurable() = configuration.configurables.add(this) - inline fun > T.register(): T { + fun , R : Any> Setting.register() = apply { if (settings.any { it.name == name }) throw IllegalStateException("Setting with name $name already exists for configurable: ${this@Configurable.name}") - settings.add(this) - return this + settings.add(this) } override fun toJson() = @@ -107,7 +101,7 @@ abstract class Configurable( defaultValue: Boolean, description: String = "", visibility: () -> Boolean = { true }, - ) = BooleanSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, BooleanSettingCore(defaultValue), visibility).register() inline fun > setting( name: String, @@ -115,14 +109,14 @@ abstract class Configurable( description: String = "", noinline visibility: () -> Boolean = { true }, - ) = EnumSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description,EnumSettingCore(defaultValue), visibility).register() fun setting( name: String, defaultValue: Char, description: String = "", visibility: () -> Boolean = { true }, - ) = CharSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, CharSettingCore(defaultValue), visibility).register() fun setting( name: String, @@ -131,65 +125,52 @@ abstract class Configurable( flags: Int = ImGuiInputTextFlags.None, description: String = "", visibility: () -> Boolean = { true }, - ) = StringSetting(name, defaultValue, multiline, flags, description, visibility).register() - + ) = Setting(name, description, StringSettingCore(defaultValue, multiline, flags), visibility).register() + @JvmName("collectionSetting1") fun setting( name: String, defaultValue: Collection, immutableCollection: Collection = Registries.BLOCK.toList(), description: String = "", visibility: () -> Boolean = { true }, - ) = BlockCollectionSetting( - name, - immutableCollection, - defaultValue.toMutableList(), - description, - visibility, - ).register() + ) = Setting(name, description, BlockCollectionSettingCore(immutableCollection, defaultValue.toMutableList()), visibility).register() + @JvmName("collectionSetting2") fun setting( name: String, defaultValue: Collection, immutableCollection: Collection = Registries.ITEM.toList(), description: String = "", visibility: () -> Boolean = { true }, - ) = ItemCollectionSetting( - name, - immutableCollection, - defaultValue.toMutableList(), - description, - visibility, - ).register() + ) = Setting(name, description, ItemCollectionSettingCore(immutableCollection, defaultValue.toMutableList()), visibility).register() + @JvmName("collectionSetting3") inline fun > setting( name: String, defaultValue: Collection, immutableList: Collection = defaultValue, description: String = "", noinline visibility: () -> Boolean = { true }, - ) = CollectionSetting( - name, - defaultValue.toMutableList(), - immutableList, - TypeToken.getParameterized(Collection::class.java, T::class.java).type, - description, - visibility, - ).register() + ) = Setting( + name, + description, + CollectionSettingCore( + defaultValue.toMutableList(), + immutableList, + TypeToken.getParameterized(Collection::class.java, T::class.java).type + ), + visibility + ).register() + @JvmName("collectionSetting4") inline fun setting( name: String, defaultValue: Collection, immutableList: Collection = defaultValue, description: String = "", noinline visibility: () -> Boolean = { true }, - ) = ClassCollectionSetting( - name, - immutableList, - defaultValue.toMutableList(), - description, - visibility, - ).register() + ) = Setting(name, description, ClassCollectionSettingCore(immutableList, defaultValue.toMutableList()), visibility).register() // ToDo: Actually implement maps inline fun setting( @@ -197,13 +178,15 @@ abstract class Configurable( defaultValue: Map, description: String = "", noinline visibility: () -> Boolean = { true }, - ) = MapSetting( - name, - defaultValue.toMutableMap(), - TypeToken.getParameterized(MutableMap::class.java, K::class.java, V::class.java).type, - description, - visibility - ).register() + ) = Setting( + name, + description, + MapSettingCore( + defaultValue.toMutableMap(), + TypeToken.getParameterized(MutableMap::class.java, K::class.java, V::class.java).type + ), + visibility + ).register() fun setting( name: String, @@ -213,7 +196,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = DoubleSetting(name, defaultValue, range, step, description, unit, visibility).register() + ) = Setting(name, description, DoubleSettingCore(defaultValue, range, step, unit), visibility).register() fun setting( name: String, @@ -223,7 +206,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = FloatSetting(name, defaultValue, range, step, description, unit, visibility).register() + ) = Setting(name, description, FloatSettingCore(defaultValue, range, step, unit), visibility).register() fun setting( name: String, @@ -233,7 +216,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = IntegerSetting(name, defaultValue, range, step, description, unit, visibility).register() + ) = Setting(name, description, IntegerSettingCore(defaultValue, range, step, unit), visibility).register() fun setting( name: String, @@ -243,61 +226,61 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = LongSetting(name, defaultValue, range, step, description, unit, visibility).register() + ) = Setting(name, description, LongSettingCore(defaultValue, range, step, unit), visibility).register() fun setting( name: String, defaultValue: Bind, description: String = "", visibility: () -> Boolean = { true }, - ) = KeybindSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, KeybindSettingCore(defaultValue), visibility).register() fun setting( name: String, defaultValue: KeyCode, description: String = "", visibility: () -> Boolean = { true }, - ) = KeybindSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, KeybindSettingCore(defaultValue), visibility).register() fun setting( name: String, defaultValue: Color, description: String = "", visibility: () -> Boolean = { true }, - ) = ColorSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, ColorSettingCore(defaultValue), visibility).register() fun setting( name: String, defaultValue: Vec3d, description: String = "", visibility: () -> Boolean = { true }, - ) = Vec3dSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, Vec3DSettingCore(defaultValue), visibility).register() fun setting( name: String, defaultValue: BlockPos.Mutable, description: String = "", visibility: () -> Boolean = { true }, - ) = BlockPosSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, BlockPosSettingCore(defaultValue), visibility).register() fun setting( name: String, defaultValue: BlockPos, description: String = "", visibility: () -> Boolean = { true }, - ) = BlockPosSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, BlockPosSettingCore(defaultValue), visibility).register() fun setting( name: String, defaultValue: Block, description: String = "", visibility: () -> Boolean = { true }, - ) = BlockSetting(name, defaultValue, description, visibility).register() + ) = Setting(name, description, BlockSettingCore(defaultValue), visibility).register() fun setting( name: String, defaultValue: () -> Unit, description: String = "", visibility: () -> Boolean = { true } - ) = FunctionSetting(name, defaultValue, description, visibility).register() -} + ) = Setting(name, description, FunctionSettingCore(defaultValue), visibility).register() +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/Configuration.kt b/src/main/kotlin/com/lambda/config/Configuration.kt index 102924ace..b727518d7 100644 --- a/src/main/kotlin/com/lambda/config/Configuration.kt +++ b/src/main/kotlin/com/lambda/config/Configuration.kt @@ -42,7 +42,7 @@ import kotlin.time.Duration.Companion.minutes /** - * Represents a compound of [Configurable] objects whose [AbstractSetting]s + * Represents a compound of [Configurable] objects whose [SettingCore]s * are saved into a single [Configuration] file ([Configuration.primary]). * * This class also handles the concurrent loading and saving of persisted data on the `Dispatchers.IO` thread. @@ -159,12 +159,12 @@ abstract class Configuration : Jsonable, Loadable { val configurations = mutableSetOf() val configurables: Set get() = configurations.flatMapTo(mutableSetOf()) { it.configurables } - val settings: Set> + val settings: Set, *>> get() = configurables.flatMapTo(mutableSetOf()) { it.settings } //ToDo: Store owner in setting - fun configurableBySetting(setting: AbstractSetting<*>) = - configurables.find { it.settings.contains(setting) } + fun configurableBySetting(setting: Setting<*, *>) = + configurables.find { it.settings.any { del -> del.name == setting.name } } fun configurableByName(name: String) = configurables.find { it.name == name } @@ -172,10 +172,10 @@ abstract class Configuration : Jsonable, Loadable { fun configurableByCommandName(name: String) = configurables.find { it.commandName == name } - fun settingByName(configurable: Configurable, name: String) = + fun settingDelegateByName(configurable: Configurable, name: String) = configurable.settings.find { it.name == name } - fun settingByCommandName(configurable: Configurable, name: String) = + fun settingDelegateByCommandName(configurable: Configurable, name: String) = configurable.settings.find { it.commandName == name } } } diff --git a/src/main/kotlin/com/lambda/config/SettingCore.kt b/src/main/kotlin/com/lambda/config/SettingCore.kt new file mode 100644 index 000000000..a7e821f05 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/SettingCore.kt @@ -0,0 +1,283 @@ +/* + * Copyright 2025 Lambda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lambda.config + +import com.google.gson.JsonElement +import com.google.gson.JsonParser +import com.lambda.Lambda.LOG +import com.lambda.Lambda.gson +import com.lambda.brigadier.CommandResult.Companion.failure +import com.lambda.brigadier.CommandResult.Companion.success +import com.lambda.brigadier.argument.string +import com.lambda.brigadier.argument.value +import com.lambda.brigadier.executeWithResult +import com.lambda.brigadier.required +import com.lambda.command.CommandRegistry +import com.lambda.command.commands.ConfigCommand +import com.lambda.context.SafeContext +import com.lambda.gui.Layout +import com.lambda.gui.dsl.ImGuiBuilder +import com.lambda.threading.runSafe +import com.lambda.util.Communication.info +import com.lambda.util.Describable +import com.lambda.util.Nameable +import com.lambda.util.NamedEnum +import com.lambda.util.extension.CommandBuilder +import com.lambda.util.text.ClickEvents +import com.lambda.util.text.HoverEvents +import com.lambda.util.text.TextBuilder +import com.lambda.util.text.buildText +import com.lambda.util.text.clickEvent +import com.lambda.util.text.highlighted +import com.lambda.util.text.hoverEvent +import com.lambda.util.text.literal +import net.minecraft.command.CommandRegistryAccess +import java.lang.reflect.Type +import kotlin.reflect.KProperty + +/** + * Represents a setting with a [defaultValue], [visibility] condition, and [description]. + * This setting is serializable ([Jsonable]) and has a [name]. + * + * When the [value] is modified, all registered [listeners] are notified. + * The [visibility] of the setting can be checked with the [isVisible] property. + * The setting can be [reset] to its [defaultValue]. + * + * Simple Usage: + * ```kotlin + * // this uses the delegate (by) association to access the setting value in the code directly. + * val mode by setting("Mode", Modes.FREEZE, { page == Page.CUSTOM }, "The mode of the module.") + * + * init { + * listener { + * LOG.info("Mode: $mode") // direct access of the value + * } + * } + * ``` + * + * Advanced usage with listeners: + * ```kotlin + * // notice how this does not use the delegate (by) association, to access the setting object to register listeners. + * val mode = setting("Mode", Modes.FREEZE, { page == Page.CUSTOM }, "The mode of the module.") + * + * init { + * mode.listener { from, to -> + * // Do something when the mode changes in a safe context + * } + * mode.unsafeListener { from, to -> + * // Do something when the mode changes in an unsafe context + * } + * + * listener { + * LOG.info("Mode: ${mode.value}") // indirect access of the value + * } + * } + * ``` + * + * @property defaultValue The default value of the setting. + * @property description A description of the setting. + * @property type The type reflection of the setting. + * @property visibility A function that determines whether the setting is visible. + */ +abstract class SettingCore( + var defaultValue: T, + val type: Type +) { + var value = defaultValue + + context(setting: Setting<*, T>) + abstract fun ImGuiBuilder.buildLayout() + + context(setting: Setting<*, T>) + open fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { + required(string("value as JSON")) { value -> + executeWithResult { + val valueString = value().value() + val parsed = try { + JsonParser.parseString("\"$valueString\"") + } catch (_: Exception) { + return@executeWithResult failure("$valueString is not a valid JSON string.") + } + val config = Configuration.configurableBySetting(setting) + ?: return@executeWithResult failure("No config found for $name.") + val previous = this@SettingCore.value + try { + loadFromJson(parsed) + } catch (_: Exception) { + return@executeWithResult failure("Failed to load $valueString as a ${type::class.simpleName} for $name in ${config.name}.") + } + ConfigCommand.info(setting.setMessage(previous, this@SettingCore.value)) + return@executeWithResult success() + } + } + } + + context(setting: Setting<*, T>) + open fun toJson(): JsonElement = + gson.toJsonTree(value, type) + + context(setting: Setting<*, T>) + open fun loadFromJson(serialized: JsonElement) { + runCatching { + value = gson.fromJson(serialized, type) + }.onFailure { + LOG.warn("Failed to load setting ${setting.name} with value $serialized. Resetting to default value $defaultValue") + value = defaultValue + } + } +} + +class Setting, R : Any>( + override val name: String, + override val description: String, + var core: T, + var visibility: () -> Boolean, +) : Nameable, Describable { + val listeners = mutableListOf>() + var disabled = { false } + var groups: MutableList> = mutableListOf() + + var value by this + + val isModified get() = value != core.defaultValue + + operator fun getValue(thisRef: Any?, property: KProperty<*>) = core.value + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: R) { + val oldValue = core.value + core.value = value + listeners.forEach { + if (it.requiresValueChange && oldValue == value) return@forEach + it.execute(oldValue, value) + } + } + + fun reset(silent: Boolean = false) { + if (!silent && value == core.defaultValue) { + ConfigCommand.info(notChangedMessage()) + return + } + if (!silent) ConfigCommand.info(resetMessage(value, core.defaultValue)) + value = core.defaultValue + } + + fun ImGuiBuilder.buildLayout() = with(core) { buildLayout() } + fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) = with(core) { buildCommand(registry) } + + fun toJson() = core.toJson() + fun loadFromJson(serialized: JsonElement) = core.loadFromJson(serialized) + + class ValueListener(val requiresValueChange: Boolean, val execute: (from: T, to: T) -> Unit) + + /** + * Will only register changes of the variable, not the content of the variable! + * E.g., if the variable is a list, it will only register if the list reference changes, not if the content of the list changes. + */ + fun onValueChange(block: SafeContext.(from: R, to: R) -> Unit) = apply { + listeners.add(ValueListener(true) { from, to -> + runSafe { + block(from, to) + } + }) + } + + fun onValueChangeUnsafe(block: (from: R, to: R) -> Unit) = apply { + listeners.add(ValueListener(true, block)) + } + + fun onValueSet(block: (from: R, to: R) -> Unit) = apply { + listeners.add(ValueListener(false, block)) + } + + fun disabled(predicate: () -> Boolean) = apply { + disabled = predicate + } + + fun group(path: List, vararg continuation: NamedEnum) = apply { + groups.add(path + continuation) + } + + fun group(vararg path: NamedEnum) = apply { + groups.add(path.toList()) + } + + fun group(path: NamedEnum?) = apply { + path?.let { groups.add(listOf(it)) } + } + + fun trySetValue(newValue: R) { + if (newValue == value) { + ConfigCommand.info(notChangedMessage()) + } else { + val previous = value + value = newValue + ConfigCommand.info(setMessage(previous, newValue)) + } + } + + fun setMessage(previousValue: R, newValue: R) = buildText { + literal("Set ") + changedMessage(previousValue, newValue) + val config = Configuration.configurableBySetting(this@Setting) ?: return@buildText + clickEvent(ClickEvents.suggestCommand("${CommandRegistry.prefix}${ConfigCommand.name} reset ${config.commandName} $commandName")) { + hoverEvent(HoverEvents.showText(buildText { + literal("Click to reset to default value ") + highlighted(core.defaultValue.toString()) + })) { + highlighted(" [Reset]") + } + } + } + + private fun resetMessage(previousValue: R, newValue: R) = buildText { + literal("Reset ") + changedMessage(previousValue, newValue) + } + + private fun notChangedMessage() = buildText { + literal("No changes made to ") + highlighted(name) + literal(" as it is already set to ") + highlighted(value.toString()) + literal(".") + } + + private fun TextBuilder.changedMessage(previousValue: R, newValue: R) { + val config = Configuration.configurableBySetting(this@Setting) ?: return + highlighted(config.name) + literal(" > ") + highlighted(name) + literal(" from ") + highlighted(previousValue.toString()) + literal(" to ") + highlighted(newValue.toString()) + literal(".") + clickEvent(ClickEvents.suggestCommand("${CommandRegistry.prefix}${ConfigCommand.name} set ${config.commandName} $commandName $previousValue")) { + hoverEvent(HoverEvents.showText(buildText { + literal("Click to undo to previous value ") + highlighted(previousValue.toString()) + })) { + highlighted(" [Undo]") + } + } + } + + override fun toString() = core.toString() + + override fun equals(other: Any?) = core == other + override fun hashCode() = core.hashCode() +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/SettingGroup.kt b/src/main/kotlin/com/lambda/config/SettingGroup.kt index 6f45278b7..6ee65aae3 100644 --- a/src/main/kotlin/com/lambda/config/SettingGroup.kt +++ b/src/main/kotlin/com/lambda/config/SettingGroup.kt @@ -18,17 +18,17 @@ package com.lambda.config interface ISettingGroup { - val settings: MutableList> + val settings: MutableList> } abstract class SettingGroup(c: Configurable) : ISettingGroup { - override val settings = mutableListOf>() + override val settings = mutableListOf>() init { c.settingGroups.add(this) } - fun AbstractSetting.index(): AbstractSetting { + fun , R : Any> Setting.index(): Setting { settings.add(this) return this } diff --git a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt index e629012e8..df6972152 100644 --- a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt @@ -18,6 +18,8 @@ package com.lambda.config import com.lambda.config.configurations.UserAutomationConfigs +import com.lambda.config.settings.collections.CollectionSettingCore.Companion.onDeselect +import com.lambda.config.settings.collections.CollectionSettingCore.Companion.onSelect import com.lambda.module.Module import com.lambda.module.ModuleRegistry.moduleNameMap @@ -29,7 +31,6 @@ class UserAutomationConfig(override val name: String) : AutomationConfig(name, U it.automationConfig = this@UserAutomationConfig } } - .onDeselect { name -> moduleNameMap[name]?.let { module -> module.automationConfig = module.defaultAutomationConfig diff --git a/src/main/kotlin/com/lambda/config/settings/CharSetting.kt b/src/main/kotlin/com/lambda/config/settings/CharSettingCore.kt similarity index 78% rename from src/main/kotlin/com/lambda/config/settings/CharSetting.kt rename to src/main/kotlin/com/lambda/config/settings/CharSettingCore.kt index 2e2abaea3..a0ffff322 100644 --- a/src/main/kotlin/com/lambda/config/settings/CharSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/CharSettingCore.kt @@ -24,7 +24,8 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.argument.word import com.lambda.brigadier.executeWithResult import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -32,27 +33,19 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class CharSetting( - override var name: String, - defaultValue: Char, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(Char::class.java).type, - description, - visibility +class CharSettingCore(defaultValue: Char) : SettingCore( + defaultValue, + TypeToken.get(Char::class.java).type ) { - override fun ImGuiBuilder.buildLayout() { - - } + context(setting: Setting<*, Char>) + override fun ImGuiBuilder.buildLayout() {} + context(setting: Setting<*, Char>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(word(name)) { parameter -> + required(word(setting.name)) { parameter -> executeWithResult { val char = parameter().value().firstOrNull() ?: return@executeWithResult failure("Cant parse char type") - trySetValue(char) + setting.trySetValue(char) return@executeWithResult success() } } diff --git a/src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt b/src/main/kotlin/com/lambda/config/settings/FunctionSettingCore.kt similarity index 68% rename from src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt rename to src/main/kotlin/com/lambda/config/settings/FunctionSettingCore.kt index 00f04629b..448661ec2 100644 --- a/src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/FunctionSettingCore.kt @@ -20,26 +20,22 @@ package com.lambda.config.settings import com.google.gson.JsonElement import com.google.gson.JsonNull import com.google.gson.reflect.TypeToken -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder -open class FunctionSetting( - override var name: String, - defaultValue: () -> T, - description: String, - visibility: () -> Boolean, -) : AbstractSetting<() -> T>( - name, - defaultValue, - TypeToken.get(defaultValue::class.java).type, - description, - visibility +open class FunctionSettingCore(defaultValue: () -> T) : SettingCore<() -> T>( + defaultValue, + TypeToken.get(defaultValue::class.java).type ) { - override fun ImGuiBuilder.buildLayout() { - button(name) { value() } - lambdaTooltip(description) + context(setting: Setting<*, () -> T>) + override fun ImGuiBuilder.buildLayout() { + button(setting.name) { value() } + lambdaTooltip(setting.description) } + context(setting: Setting<*, () -> T>) override fun toJson(): JsonElement = JsonNull.INSTANCE + context(setting: Setting<*, () -> T>) override fun loadFromJson(serialized: JsonElement) { value = defaultValue } } diff --git a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt b/src/main/kotlin/com/lambda/config/settings/NumericSettingCore.kt similarity index 77% rename from src/main/kotlin/com/lambda/config/settings/NumericSetting.kt rename to src/main/kotlin/com/lambda/config/settings/NumericSettingCore.kt index 162d7fbf1..65adc8b34 100644 --- a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/NumericSettingCore.kt @@ -18,7 +18,8 @@ package com.lambda.config.settings import com.google.gson.reflect.TypeToken -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.config.SettingEditorDsl import com.lambda.config.SettingGroupEditor import com.lambda.gui.dsl.ImGuiBuilder @@ -33,61 +34,57 @@ import kotlin.reflect.KProperty /** * @see [com.lambda.config.Configurable] */ -abstract class NumericSetting( - override var name: String, +abstract class NumericSettingCore( value: T, open var range: ClosedRange, open var step: T, - description: String, - var unit: String, - visibility: () -> Boolean -) : AbstractSetting( - name, - value, - TypeToken.get(value::class.java).type, - description, - visibility + var unit: String +) : SettingCore( + value, + TypeToken.get(value::class.java).type ) where T : Number, T : Comparable { private val formatter = NumberFormat.getNumberInstance(Locale.getDefault()) override fun toString() = "${formatter.format(value)}$unit" - override operator fun setValue(thisRef: Any?, property: KProperty<*>, valueIn: T) { + operator fun setValue(thisRef: Any?, property: KProperty<*>, valueIn: T) { value = valueIn.coerceIn(range) } /** * Subclasses must implement this to provide their specific slider widget. */ + context(setting: Setting<*, T>) protected abstract fun ImGuiBuilder.buildSlider() + context(setting: Setting<*, T>) override fun ImGuiBuilder.buildLayout() { - val showReset = isModified + val showReset = setting.isModified val resetButtonText = "R" - val valueString = this@NumericSetting.toString() + val valueString = this@NumericSettingCore.toString() buildSlider() - lambdaTooltip(description) + lambdaTooltip(setting.description) val itemRectMin = ImGui.getItemRectMin() val itemRectMax = ImGui.getItemRectMax() val textHeight = ImGui.getTextLineHeight() val textY = itemRectMin.y + (itemRectMax.y - itemRectMin.y - textHeight) / 2.0f - val labelWidth = calcTextSize(name).x + val labelWidth = calcTextSize(setting.name).x val valueWidth = calcTextSize(valueString).x val labelEndPosX = itemRectMin.x + style.framePadding.x * 2 + labelWidth val valueStartPosX = itemRectMax.x - style.framePadding.x * 2 - valueWidth - windowDrawList.addText(itemRectMin.x + style.framePadding.x * 2, textY, ImGui.getColorU32(ImGuiCol.Text), name) + windowDrawList.addText(itemRectMin.x + style.framePadding.x * 2, textY, ImGui.getColorU32(ImGuiCol.Text), setting.name) if (labelEndPosX < valueStartPosX) { windowDrawList.addText(valueStartPosX, textY, ImGui.getColorU32(ImGuiCol.Text), valueString) } sameLine(0.0f, style.itemSpacing.x) if (showReset) { - button("$resetButtonText##$name") { - reset() + button("$resetButtonText##${setting.name}") { + setting.reset() } onItemHover { tooltip { text("Reset to default") } @@ -101,19 +98,19 @@ abstract class NumericSetting( @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.range(range: ClosedRange) where T : Number, T : Comparable { - (settings as Collection>).forEach { it.range = range } + (settings as Collection>).forEach { it.range = range } } @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.step(step: T) where T : Number, T : Comparable { - (settings as Collection>).forEach { it.step = step } + (settings as Collection>).forEach { it.step = step } } @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.unit(unit: String) where T : Number, T : Comparable { - (settings as Collection>).forEach { it.unit = unit} + (settings as Collection>).forEach { it.unit = unit} } } } diff --git a/src/main/kotlin/com/lambda/config/settings/StringSetting.kt b/src/main/kotlin/com/lambda/config/settings/StringSettingCore.kt similarity index 73% rename from src/main/kotlin/com/lambda/config/settings/StringSetting.kt rename to src/main/kotlin/com/lambda/config/settings/StringSettingCore.kt index f6caa6c12..62a7a497e 100644 --- a/src/main/kotlin/com/lambda/config/settings/StringSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/StringSettingCore.kt @@ -22,7 +22,8 @@ import com.lambda.brigadier.argument.greedyString import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.config.SettingEditorDsl import com.lambda.config.SettingGroupEditor import com.lambda.gui.dsl.ImGuiBuilder @@ -33,33 +34,29 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class StringSetting( - override var name: String, +class StringSettingCore( defaultValue: String, var multiline: Boolean = false, var flags: Int = ImGuiInputTextFlags.None, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(String::class.java).type, - description, - visibility +) : SettingCore( + defaultValue, + TypeToken.get(String::class.java).type ) { + context(setting: Setting<*, String>) override fun ImGuiBuilder.buildLayout() { if (multiline) { - inputTextMultiline(name, ::value, flags = flags) + inputTextMultiline(setting.name, ::value, flags = flags) } else { - inputText(name, ::value, flags) + inputText(setting.name, ::value, flags) } - lambdaTooltip(description) + lambdaTooltip(setting.description) } + context(setting: Setting<*, String>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(greedyString(name)) { parameter -> + required(greedyString(setting.name)) { parameter -> execute { - trySetValue(parameter().value()) + setting.trySetValue(parameter().value()) } } } @@ -68,13 +65,13 @@ class StringSetting( @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.multiline(multiline: Boolean) { - (settings as Collection).forEach { it.multiline = multiline } + (settings as Collection).forEach { it.multiline = multiline } } @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.flags(flags: Int) { - (settings as Collection).forEach { it.flags = flags } + (settings as Collection).forEach { it.flags = flags } } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSettingCore.kt similarity index 83% rename from src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt rename to src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSettingCore.kt index da9ad7543..5d6a39df9 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSettingCore.kt @@ -20,6 +20,7 @@ package com.lambda.config.settings.collections import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson +import com.lambda.config.Setting import com.lambda.config.serializer.BlockCodec import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.StringUtils.levenshteinDistance @@ -28,30 +29,25 @@ import imgui.flag.ImGuiChildFlags import imgui.flag.ImGuiSelectableFlags.DontClosePopups import net.minecraft.block.Block -class BlockCollectionSetting( - override var name: String, +class BlockCollectionSettingCore( private val immutableCollection: Collection, defaultValue: MutableCollection, - description: String, - visibility: () -> Boolean, -) : CollectionSetting( - name, +) : CollectionSettingCore( defaultValue, immutableCollection, - TypeToken.getParameterized(Collection::class.java, Block::class.java).type, - description, - visibility, + TypeToken.getParameterized(Collection::class.java, Block::class.java).type ) { private var searchFilter = "" + context(setting: Setting<*, MutableCollection>) override fun ImGuiBuilder.buildLayout() { val text = if (value.size == 1) "block" else "blocks" - combo("##$name", "$name: ${value.size} $text") { - inputText("##$name-SearchBox", ::searchFilter) + combo("##${setting.name}", "${setting.name}: ${value.size} $text") { + inputText("##${setting.name}-SearchBox", ::searchFilter) child( - strId = "##$name-ComboOptionsChild", + strId = "##${setting.name}-ComboOptionsChild", childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, ) { val list = immutableCollection @@ -80,8 +76,10 @@ class BlockCollectionSetting( } } + context(setting: Setting<*, MutableCollection>) override fun toJson(): JsonElement = gson.toJsonTree(value, type) + context(setting: Setting<*, MutableCollection>) override fun loadFromJson(serialized: JsonElement) { value = gson.fromJson>(serialized, type) .toMutableList() diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSettingCore.kt similarity index 85% rename from src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt rename to src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSettingCore.kt index badc04fd5..027fb8f0c 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSettingCore.kt @@ -20,6 +20,7 @@ package com.lambda.config.settings.collections import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson +import com.lambda.config.Setting import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.StringUtils.levenshteinDistance import com.lambda.util.reflections.className @@ -28,33 +29,28 @@ import imgui.flag.ImGuiChildFlags import imgui.flag.ImGuiSelectableFlags.DontClosePopups /** - * @see [com.lambda.config.settings.collections.CollectionSetting] + * @see [com.lambda.config.settings.collections.CollectionSettingCore] * @see [com.lambda.config.Configurable] */ -class ClassCollectionSetting( - override var name: String, +class ClassCollectionSettingCore( private val immutableCollection: Collection, - defaultValue: MutableCollection, - description: String, - visibility: () -> Boolean, -) : CollectionSetting( - name, + defaultValue: MutableCollection +) : CollectionSettingCore( defaultValue, immutableCollection, - TypeToken.getParameterized(Collection::class.java, Any::class.java).type, - description, - visibility, + TypeToken.getParameterized(Collection::class.java, Any::class.java).type ) { private var searchFilter = "" + context(setting: Setting<*, MutableCollection>) override fun ImGuiBuilder.buildLayout() { val text = if (value.size == 1) "item" else "items" - combo("##$name", "$name: ${value.size} $text") { - inputText("##$name-SearchBox", ::searchFilter) + combo("##${setting.name}", "${setting.name}: ${value.size} $text") { + inputText("##${setting.name}-SearchBox", ::searchFilter) child( - strId = "##$name-ComboOptionsChild", + strId = "##${setting.name}-ComboOptionsChild", childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, ) { val list = immutableCollection @@ -86,8 +82,10 @@ class ClassCollectionSetting( // When serializing the list to json we do not want to serialize the elements' classes, but their stringified representation. // If we do serialize the classes we'll run into missing type adapters errors by Gson. // This is intended behaviour. If you wish your collection settings to display something else then you must extend this class. + context(setting: Setting<*, MutableCollection>) override fun toJson(): JsonElement = gson.toJsonTree(value.map { it.className }) + context(setting: Setting<*, MutableCollection>) override fun loadFromJson(serialized: JsonElement) { val strList = gson.fromJson>(serialized, type) .mapNotNull { str -> immutableCollection.find { it.className == str } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSettingCore.kt similarity index 73% rename from src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt rename to src/main/kotlin/com/lambda/config/settings/collections/CollectionSettingCore.kt index b75dbbc4e..c118537fc 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSettingCore.kt @@ -20,7 +20,8 @@ package com.lambda.config.settings.collections import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.config.SettingEditorDsl import com.lambda.config.SettingGroupEditor import com.lambda.context.SafeContext @@ -34,50 +35,37 @@ import java.lang.reflect.Type /** * This generic collection settings handles all [Comparable] values (i.e not classes) and serialize * their values by calling [Any.toString] and loads them by comparing what's in the [immutableCollection]. - * This behaviour is by design. If you wish to store collections of non-comparable values you must use [ClassCollectionSetting]. + * This behaviour is by design. If you wish to store collections of non-comparable values you must use [ClassCollectionSettingCore]. * * If you wish to use a different codec or simply display values differently you must create your own * collection setting. * * @see [com.lambda.config.Configurable] */ -open class CollectionSetting( - override var name: String, - defaultValue: MutableCollection, - private var immutableCollection: Collection, - type: Type, - description: String, - visibility: () -> Boolean, -) : AbstractSetting>( - name, - defaultValue, - type, - description, - visibility +open class CollectionSettingCore( + defaultValue: MutableCollection, + private var immutableCollection: Collection, + type: Type +) : SettingCore>( + defaultValue, + type ) { private var searchFilter = "" private val strListType = TypeToken.getParameterized(Collection::class.java, String::class.java).type - private val selectListeners = mutableListOf Unit>() - private val deselectListeners = mutableListOf Unit>() - - fun onSelect(block: SafeContext.(T) -> Unit) = apply { - selectListeners.add(block) - } - - fun onDeselect(block: SafeContext.(T) -> Unit) = apply { - deselectListeners.add(block) - } + val selectListeners = mutableListOf Unit>() + val deselectListeners = mutableListOf Unit>() + context(setting: Setting<*, MutableCollection>) override fun ImGuiBuilder.buildLayout() { val text = if (value.size == 1) "item" else "items" - combo("##$name", "$name: ${value.size} $text") { - inputText("##$name-SearchBox", ::searchFilter) + combo("##${setting.name}", "${setting.name}: ${value.size} $text") { + inputText("##${setting.name}-SearchBox", ::searchFilter) child( - strId = "##$name-ComboOptionsChild", + strId = "##${setting.name}-ComboOptionsChild", childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, ) { val list = immutableCollection @@ -106,9 +94,11 @@ open class CollectionSetting( } } + context(setting: Setting<*, MutableCollection>) override fun toJson(): JsonElement = gson.toJsonTree(value.map { it.toString() }) + context(setting: Setting<*, MutableCollection>) override fun loadFromJson(serialized: JsonElement) { val strList = gson.fromJson>(serialized, strListType) .mapNotNull { str -> immutableCollection.find { it.toString() == str } } @@ -117,11 +107,19 @@ open class CollectionSetting( value = strList } - companion object { + companion object { + fun Setting, MutableCollection>.onSelect(block: SafeContext.(T) -> Unit) = apply { + core.selectListeners.add(block) + } + + fun Setting, MutableCollection>.onDeselect(block: SafeContext.(T) -> Unit) = apply { + core.deselectListeners.add(block) + } + @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder>.immutableCollection(collection: Collection) { - (settings as Collection>).forEach { it.immutableCollection = collection } + (settings as Collection>).forEach { it.immutableCollection = collection } } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSettingCore.kt similarity index 82% rename from src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt rename to src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSettingCore.kt index e6f424b3b..4347f2e3d 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSettingCore.kt @@ -20,6 +20,7 @@ package com.lambda.config.settings.collections import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson +import com.lambda.config.Setting import com.lambda.config.serializer.ItemCodec import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.StringUtils.levenshteinDistance @@ -28,30 +29,25 @@ import imgui.flag.ImGuiChildFlags import imgui.flag.ImGuiSelectableFlags.DontClosePopups import net.minecraft.item.Item -class ItemCollectionSetting( - override var name: String, +class ItemCollectionSettingCore( private val immutableCollection: Collection, - defaultValue: MutableCollection, - description: String, - visibility: () -> Boolean, -) : CollectionSetting( - name, + defaultValue: MutableCollection +) : CollectionSettingCore( defaultValue, immutableCollection, - TypeToken.getParameterized(Collection::class.java, Item::class.java).type, - description, - visibility, + TypeToken.getParameterized(Collection::class.java, Item::class.java).type ) { private var searchFilter = "" + context(setting: Setting<*, MutableCollection>) override fun ImGuiBuilder.buildLayout() { val text = if (value.size == 1) "item" else "items" - combo("##$name", "$name: ${value.size} $text") { - inputText("##$name-SearchBox", ::searchFilter) + combo("##${setting.name}", "${setting.name}: ${value.size} $text") { + inputText("##${setting.name}-SearchBox", ::searchFilter) child( - strId = "##$name-ComboOptionsChild", + strId = "##${setting.name}-ComboOptionsChild", childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, ) { val list = immutableCollection @@ -80,8 +76,10 @@ class ItemCollectionSetting( } } + context(setting: Setting<*, MutableCollection>) override fun toJson(): JsonElement = gson.toJsonTree(value, type) + context(setting: Setting<*, MutableCollection>) override fun loadFromJson(serialized: JsonElement) { value = gson.fromJson>(serialized, type) .toMutableList() diff --git a/src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/MapSettingCore.kt similarity index 70% rename from src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt rename to src/main/kotlin/com/lambda/config/settings/collections/MapSettingCore.kt index cdf49cb6e..e83c202da 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/MapSettingCore.kt @@ -17,25 +17,21 @@ package com.lambda.config.settings.collections -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import java.lang.reflect.Type /** * @see [com.lambda.config.Configurable] */ -class MapSetting( - override var name: String, - defaultValue: MutableMap, - type: Type, - description: String, - visibility: () -> Boolean, -) : AbstractSetting>( - name, - defaultValue, - type, - description, - visibility +class MapSettingCore( + defaultValue: MutableMap, + type: Type +) : SettingCore>( + defaultValue, + type ) { - override fun ImGuiBuilder.buildLayout() {} + context(setting: Setting<*, MutableMap>) + override fun ImGuiBuilder.buildLayout() {} } diff --git a/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt b/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSettingCore.kt similarity index 70% rename from src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt rename to src/main/kotlin/com/lambda/config/settings/comparable/BooleanSettingCore.kt index 44845c99f..fd035f693 100644 --- a/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSettingCore.kt @@ -22,7 +22,8 @@ import com.lambda.brigadier.argument.boolean import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -30,27 +31,21 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class BooleanSetting( - override var name: String, - defaultValue: Boolean, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(Boolean::class.java).type, - description, - visibility +class BooleanSettingCore(defaultValue: Boolean) : SettingCore( + defaultValue, + TypeToken.get(Boolean::class.java).type ) { - override fun ImGuiBuilder.buildLayout() { - checkbox(name, ::value) - lambdaTooltip(description) + context(setting: Setting<*, Boolean>) + override fun ImGuiBuilder.buildLayout() { + checkbox(setting.name, ::value) + lambdaTooltip(setting.description) } + context(setting: Setting<*, Boolean>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(boolean(name)) { parameter -> + required(boolean(setting.name)) { parameter -> execute { - trySetValue(parameter().value()) + setting.trySetValue(parameter().value()) } } } diff --git a/src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt b/src/main/kotlin/com/lambda/config/settings/comparable/EnumSettingCore.kt similarity index 84% rename from src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt rename to src/main/kotlin/com/lambda/config/settings/comparable/EnumSettingCore.kt index e54080ae1..14b997e13 100644 --- a/src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/comparable/EnumSettingCore.kt @@ -25,7 +25,8 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.argument.word import com.lambda.brigadier.executeWithResult import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.Describable import com.lambda.util.StringUtils.capitalize @@ -37,32 +38,26 @@ import kotlin.properties.Delegates /** * @see [com.lambda.config.Configurable] */ -class EnumSetting>( - override var name: String, - defaultValue: T, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(defaultValue.declaringJavaClass).type, - description, - visibility, +class EnumSettingCore>(defaultValue: T) : SettingCore( + defaultValue, + TypeToken.get(defaultValue.declaringJavaClass).type ) { var index by Delegates.observable(value.ordinal) { _, _, to -> value = value.enumValues[to % value.enumValues.size] } + context(setting: Setting<*, T>) override fun loadFromJson(serialized: JsonElement) { super.loadFromJson(serialized) index = value.ordinal // super bug fix for imgui } + context(setting: Setting<*, T>) override fun ImGuiBuilder.buildLayout() { val values = value.enumValues val currentDisplay = value.displayValue - combo("##$name", preview = "$name: $currentDisplay") { + combo("##${setting.name}", preview = "${setting.name}: $currentDisplay") { values.forEachIndexed { idx, v -> val isSelected = idx == index @@ -74,11 +69,12 @@ class EnumSetting>( } } - lambdaTooltip(description) + lambdaTooltip(setting.description) } + context(setting: Setting<*, T>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(word(name)) { parameter -> + required(word(setting.name)) { parameter -> suggests { _, builder -> value.enumValues.forEach { builder.suggest(it.name.capitalize()) } builder.buildFuture() @@ -86,7 +82,7 @@ class EnumSetting>( executeWithResult { val newValue = value.enumValues.find { it.name.equals(parameter().value(), true) } ?: return@executeWithResult failure("Invalid value") - trySetValue(newValue) + setting.trySetValue(newValue) return@executeWithResult success() } } diff --git a/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSettingCore.kt similarity index 76% rename from src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt rename to src/main/kotlin/com/lambda/config/settings/complex/BlockPosSettingCore.kt index 35c7b1e6c..89026c45a 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSettingCore.kt @@ -22,7 +22,8 @@ import com.lambda.brigadier.argument.integer import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.BlockUtils.blockPos import com.lambda.util.extension.CommandBuilder @@ -32,29 +33,23 @@ import net.minecraft.util.math.BlockPos /** * @see [com.lambda.config.Configurable] */ -class BlockPosSetting( - override var name: String, - defaultValue: BlockPos, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(BlockPos::class.java).type, - description, - visibility +class BlockPosSettingCore(defaultValue: BlockPos) : SettingCore( + defaultValue, + TypeToken.get(BlockPos::class.java).type ) { + context(setting: Setting<*, BlockPos>) override fun ImGuiBuilder.buildLayout() { - inputVec3i(name, value) { value = it.blockPos } - lambdaTooltip(description) + inputVec3i(setting.name, value) { value = it.blockPos } + lambdaTooltip(setting.description) } + context(setting: Setting<*, BlockPos>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { required(integer("X", -30000000, 30000000)) { x -> required(integer("Y", -64, 255)) { y -> required(integer("Z", -30000000, 30000000)) { z -> execute { - trySetValue(BlockPos(x().value(), y().value(), z().value())) + setting.trySetValue(BlockPos(x().value(), y().value(), z().value())) } } } diff --git a/src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/BlockSettingCore.kt similarity index 75% rename from src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt rename to src/main/kotlin/com/lambda/config/settings/complex/BlockSettingCore.kt index 7833fe4cd..6b17e8926 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/BlockSettingCore.kt @@ -22,7 +22,8 @@ import com.lambda.brigadier.argument.blockState import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.block.Block @@ -31,24 +32,18 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class BlockSetting( - override var name: String, - defaultValue: Block, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(Block::class.java).type, - description, - visibility +class BlockSettingCore(defaultValue: Block) : SettingCore( + defaultValue, + TypeToken.get(Block::class.java).type ) { + context(setting: Setting<*, Block>) override fun ImGuiBuilder.buildLayout() {} + context(setting: Setting<*, Block>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(blockState(name, registry)) { argument -> + required(blockState(setting.name, registry)) { argument -> execute { - trySetValue(argument().value().blockState.block) + setting.trySetValue(argument().value().blockState.block) } } } diff --git a/src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/ColorSettingCore.kt similarity index 76% rename from src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt rename to src/main/kotlin/com/lambda/config/settings/complex/ColorSettingCore.kt index 553b5eb72..0f333baaa 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/ColorSettingCore.kt @@ -23,7 +23,8 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.optional import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -32,23 +33,17 @@ import java.awt.Color /** * @see [com.lambda.config.Configurable] */ -class ColorSetting( - override var name: String, - defaultValue: Color, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(Color::class.java).type, - description, - visibility +class ColorSettingCore(defaultValue: Color) : SettingCore( + defaultValue, + TypeToken.get(Color::class.java).type ) { - override fun ImGuiBuilder.buildLayout() { - colorEdit(name, ::value) - lambdaTooltip(description) + context(setting: Setting<*, Color>) + override fun ImGuiBuilder.buildLayout() { + colorEdit(setting.name, ::value) + lambdaTooltip(setting.description) } + context(setting: Setting<*, Color>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { required(integer("Red", 0, 255)) { red -> required(integer("Green", 0, 255)) { green -> @@ -56,7 +51,7 @@ class ColorSetting( optional(integer("Alpha", 0, 255)) { alpha -> execute { val alphaValue = alpha?.let { it().value() } ?: 255 - trySetValue(Color(red().value(), green().value(), blue().value(), alphaValue)) + setting.trySetValue(Color(red().value(), green().value(), blue().value(), alphaValue)) } } } diff --git a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSettingCore.kt similarity index 90% rename from src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt rename to src/main/kotlin/com/lambda/config/settings/complex/KeybindSettingCore.kt index e4639ae2a..eee1f5546 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSettingCore.kt @@ -26,7 +26,8 @@ import com.lambda.brigadier.argument.word import com.lambda.brigadier.executeWithResult import com.lambda.brigadier.optional import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.InputUtils import com.lambda.util.KeyCode @@ -47,25 +48,17 @@ import org.lwjgl.glfw.GLFW.GLFW_MOD_NUM_LOCK import org.lwjgl.glfw.GLFW.GLFW_MOD_SHIFT import org.lwjgl.glfw.GLFW.GLFW_MOD_SUPER -class KeybindSetting( - override var name: String, - defaultValue: Bind, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(Bind::class.java).type, - description, - visibility +class KeybindSettingCore(defaultValue: Bind) : SettingCore( + defaultValue, + TypeToken.get(Bind::class.java).type ) { - constructor(name: String, defaultValue: KeyCode, description: String, visibility: () -> Boolean) - : this(name, Bind(defaultValue.code, 0, -1), description, visibility) + constructor(defaultValue: KeyCode) : this(Bind(defaultValue.code, 0, -1)) private var listening = false + context(setting: Setting<*, Bind>) override fun ImGuiBuilder.buildLayout() { - text(name) + text(setting.name) sameLine() val bind = value @@ -86,7 +79,7 @@ class KeybindSetting( } lambdaTooltip { - if (!listening) description.ifBlank { "Click to set. Esc cancels. Backspace/Delete unbinds." } + if (!listening) setting.description.ifBlank { "Click to set. Esc cancels. Backspace/Delete unbinds." } else "Listening… Press a key to bind. Esc to cancel. Backspace/Delete to unbind." } @@ -131,8 +124,9 @@ class KeybindSetting( } } + context(setting: Setting<*, Bind>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(word(name)) { name -> + required(word(setting.name)) { name -> suggests { _, builder -> KeyCode.entries.forEach { builder.suggest(it.name.capitalize()) } (1..10).forEach { builder.suggest(it) } @@ -157,7 +151,7 @@ class KeybindSetting( } } - trySetValue(bind) + setting.trySetValue(bind) return@executeWithResult success() } } diff --git a/src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/Vec3DSettingCore.kt similarity index 73% rename from src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt rename to src/main/kotlin/com/lambda/config/settings/complex/Vec3DSettingCore.kt index fd33a860a..901b6fdba 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/Vec3DSettingCore.kt @@ -22,35 +22,30 @@ import com.lambda.brigadier.argument.double import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting +import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess import net.minecraft.util.math.Vec3d -class Vec3dSetting( - override var name: String, - defaultValue: Vec3d, - description: String, - visibility: () -> Boolean, -) : AbstractSetting( - name, - defaultValue, - TypeToken.get(Vec3d::class.java).type, - description, - visibility +class Vec3DSettingCore(defaultValue: Vec3d, ) : SettingCore( + defaultValue, + TypeToken.get(Vec3d::class.java).type ) { - override fun ImGuiBuilder.buildLayout() { - inputVec3d(name, ::value as Vec3d) // FixMe: what the fuck - lambdaTooltip(description) + context(setting: Setting<*, Vec3d>) + override fun ImGuiBuilder.buildLayout() { + inputVec3d(setting.name, ::value as Vec3d) // FixMe: what the fuck + lambdaTooltip(setting.description) } + context(setting: Setting<*, Vec3d>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { required(double("X", -30000000.0, 30000000.0)) { x -> required(double("Y", -64.0, 255.0)) { y -> required(double("Z", -30000000.0, 30000000.0)) { z -> execute { - trySetValue(Vec3d(x().value(), y().value(), z().value())) + setting.trySetValue(Vec3d(x().value(), y().value(), z().value())) } } } diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt b/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSettingCore.kt similarity index 79% rename from src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt rename to src/main/kotlin/com/lambda/config/settings/numeric/DoubleSettingCore.kt index 0856ee2f1..285188381 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSettingCore.kt @@ -22,7 +22,8 @@ import com.lambda.brigadier.argument.double import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.settings.NumericSetting +import com.lambda.config.Setting +import com.lambda.config.settings.NumericSettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -31,22 +32,16 @@ import kotlin.math.roundToInt /** * @see [com.lambda.config.Configurable] */ -class DoubleSetting( - override var name: String, +class DoubleSettingCore( defaultValue: Double, override var range: ClosedRange, override var step: Double, - description: String, - unit: String, - visibility: () -> Boolean -) : NumericSetting( - name, + unit: String +) : NumericSettingCore( defaultValue, range, step, - description, - unit, - visibility + unit ) { private var valueIndex: Int get() = ((value - range.start) / step).roundToInt() @@ -54,15 +49,17 @@ class DoubleSetting( value = (range.start + index * step).coerceIn(range) } + context(setting: Setting<*, Double>) override fun ImGuiBuilder.buildSlider() { val maxIndex = ((range.endInclusive - range.start) / step).toInt() - slider("##$name", ::valueIndex, 0, maxIndex, "") + slider("##${setting.name}", ::valueIndex, 0, maxIndex, "") } + context(setting: Setting<*, Double>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(double(name, range.start, range.endInclusive)) { parameter -> + required(double(setting.name, range.start, range.endInclusive)) { parameter -> execute { - trySetValue(parameter().value()) + setting.trySetValue(parameter().value()) } } } diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt b/src/main/kotlin/com/lambda/config/settings/numeric/FloatSettingCore.kt similarity index 79% rename from src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt rename to src/main/kotlin/com/lambda/config/settings/numeric/FloatSettingCore.kt index ad3e5a830..7bae3f291 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/FloatSettingCore.kt @@ -21,7 +21,8 @@ import com.lambda.brigadier.argument.float import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.settings.NumericSetting +import com.lambda.config.Setting +import com.lambda.config.settings.NumericSettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -30,22 +31,16 @@ import kotlin.math.roundToInt /** * @see [com.lambda.config.Configurable] */ -class FloatSetting( - override var name: String, +class FloatSettingCore( defaultValue: Float, override var range: ClosedRange, override var step: Float = 1f, - description: String, unit: String, - visibility: () -> Boolean -) : NumericSetting( - name, +) : NumericSettingCore( defaultValue, range, step, - description, - unit, - visibility + unit ) { private var valueIndex: Int get() = ((value - range.start) / step).roundToInt() @@ -53,15 +48,17 @@ class FloatSetting( value = (range.start + index * step).coerceIn(range) } + context(setting: Setting<*, Float>) override fun ImGuiBuilder.buildSlider() { val maxIndex = ((range.endInclusive - range.start) / step).toInt() - slider("##$name", ::valueIndex, 0, maxIndex, "") + slider("##${setting.name}", ::valueIndex, 0, maxIndex, "") } + context(setting: Setting<*, Float>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(float(name, range.start, range.endInclusive)) { parameter -> + required(float(setting.name, range.start, range.endInclusive)) { parameter -> execute { - trySetValue(parameter().value()) + setting.trySetValue(parameter().value()) } } } diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt b/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSettingCore.kt similarity index 75% rename from src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt rename to src/main/kotlin/com/lambda/config/settings/numeric/IntegerSettingCore.kt index 7eb0eb056..06f1a8aa5 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSettingCore.kt @@ -21,7 +21,8 @@ import com.lambda.brigadier.argument.integer import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.settings.NumericSetting +import com.lambda.config.Setting +import com.lambda.config.settings.NumericSettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -29,31 +30,27 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class IntegerSetting( - override var name: String, +class IntegerSettingCore( defaultValue: Int, override var range: ClosedRange, override var step: Int = 1, - description: String, - unit: String, - visibility: () -> Boolean -) : NumericSetting( - name, + unit: String +) : NumericSettingCore( defaultValue, range, step, - description, - unit, - visibility + unit ) { + context(setting: Setting<*, Int>) override fun ImGuiBuilder.buildSlider() { - slider("##$name", ::value, range.start, range.endInclusive, "") + slider("##${setting.name}", ::value, range.start, range.endInclusive, "") } + context(setting: Setting<*, Int>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(integer(name, range.start, range.endInclusive)) { parameter -> + required(integer(setting.name, range.start, range.endInclusive)) { parameter -> execute { - trySetValue(parameter().value()) + setting.trySetValue(parameter().value()) } } } diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt b/src/main/kotlin/com/lambda/config/settings/numeric/LongSettingCore.kt similarity index 79% rename from src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt rename to src/main/kotlin/com/lambda/config/settings/numeric/LongSettingCore.kt index 00a2d8d61..fcb4423ef 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/LongSettingCore.kt @@ -21,7 +21,8 @@ import com.lambda.brigadier.argument.long import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required -import com.lambda.config.settings.NumericSetting +import com.lambda.config.Setting +import com.lambda.config.settings.NumericSettingCore import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -29,22 +30,16 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class LongSetting( - override var name: String, +class LongSettingCore( defaultValue: Long, override var range: ClosedRange, override var step: Long = 1, - description: String, - unit: String, - visibility: () -> Boolean -) : NumericSetting( - name, + unit: String +) : NumericSettingCore( defaultValue, range, step, - description, - unit, - visibility + unit ) { // ToDo: No worky for super large numbers private var valueIndex: Int @@ -53,15 +48,17 @@ class LongSetting( value = (range.start + index * step).coerceIn(range) } + context(setting: Setting<*, Long>) override fun ImGuiBuilder.buildSlider() { val maxIndex = ((range.endInclusive - range.start) / step).toInt() - slider("##$name", ::valueIndex, 0, maxIndex, "") + slider("##${setting.name}", ::valueIndex, 0, maxIndex, "") } + context(setting: Setting<*, Long>) override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(long(name, range.start, range.endInclusive)) { parameter -> + required(long(setting.name, range.start, range.endInclusive)) { parameter -> execute { - trySetValue(parameter().value()) + setting.trySetValue(parameter().value()) } } } diff --git a/src/main/kotlin/com/lambda/gui/components/QuickSearch.kt b/src/main/kotlin/com/lambda/gui/components/QuickSearch.kt index f5544aa56..0868117cc 100644 --- a/src/main/kotlin/com/lambda/gui/components/QuickSearch.kt +++ b/src/main/kotlin/com/lambda/gui/components/QuickSearch.kt @@ -20,9 +20,9 @@ package com.lambda.gui.components import com.lambda.Lambda.mc import com.lambda.command.CommandRegistry import com.lambda.command.LambdaCommand -import com.lambda.config.AbstractSetting import com.lambda.config.Configurable import com.lambda.config.Configuration +import com.lambda.config.Setting import com.lambda.event.events.KeyboardEvent import com.lambda.event.listener.UnsafeListener.Companion.listenUnsafe import com.lambda.gui.LambdaScreen @@ -100,7 +100,7 @@ object QuickSearch { } } - private class SettingResult(val setting: AbstractSetting<*>, val configurable: Configurable) : SearchResult { + private class SettingResult(val setting: Setting<*, *>, val configurable: Configurable) : SearchResult { override val breadcrumb: String by lazy { buildSettingBreadcrumb(configurable.name, setting) } override fun ImGuiBuilder.buildLayout() { @@ -295,7 +295,7 @@ object QuickSearch { } } - private fun buildSettingBreadcrumb(configurableName: String, setting: AbstractSetting<*>): String { + private fun buildSettingBreadcrumb(configurableName: String, setting: Setting<*, *>): String { val group = setting.groups .minByOrNull { it.size } ?.joinToString(" » ") { it.displayName } diff --git a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt index bc016631c..eb302cddd 100644 --- a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt +++ b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt @@ -17,10 +17,10 @@ package com.lambda.gui.components -import com.lambda.config.AbstractSetting import com.lambda.config.AutomationConfig import com.lambda.config.Configurable import com.lambda.config.MutableAutomationConfig +import com.lambda.config.Setting import com.lambda.config.UserAutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.module.Module @@ -33,7 +33,7 @@ object SettingsWidget { /** * Builds the settings context popup content for a given configurable. */ - fun ImGuiBuilder.buildConfigSettingsContext(config: Configurable, hiddenSettings: Set> = emptySet()) { + fun ImGuiBuilder.buildConfigSettingsContext(config: Configurable) { group { if (config is Module) { with(config.keybindSetting) { buildLayout() } @@ -49,7 +49,7 @@ object SettingsWidget { } ImGui.setNextWindowSizeConstraints(0f, 0f, Float.MAX_VALUE, io.displaySize.y * 0.5f) popupContextItem("##automation-config-popup-${config.name}", ImGuiPopupFlags.None) { - buildConfigSettingsContext(config.automationConfig, config.defaultAutomationConfig.hiddenSettings) + buildConfigSettingsContext(config.automationConfig) } if (config.automationConfig !== config.defaultAutomationConfig) { sameLine() @@ -64,7 +64,7 @@ object SettingsWidget { is UserAutomationConfig -> setOf(config.linkedModules) else -> emptySet() } - val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings - hiddenSettings + val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() } ungrouped.forEach { it.withDisabled { buildLayout() } @@ -72,16 +72,16 @@ object SettingsWidget { renderGroup(grouped, emptyList(), config) } - private fun AbstractSetting<*>.withDisabled(block: AbstractSetting<*>.() -> Unit) { + private fun Setting<*, *>.withDisabled(block: Setting<*, *>.() -> Unit) { if (disabled()) ImGui.beginDisabled() block() if (disabled()) ImGui.endDisabled() } private fun ImGuiBuilder.renderGroup( - settings: List>, - parentPath: List, - config: Configurable + settings: List>, + parentPath: List, + config: Configurable ) { settings.filter { it.groups.contains(parentPath) }.forEach { it.withDisabled { buildLayout() } diff --git a/src/main/kotlin/com/lambda/interaction/request/rotating/RotationConfig.kt b/src/main/kotlin/com/lambda/interaction/request/rotating/RotationConfig.kt index 75cca282f..9e48d60ad 100644 --- a/src/main/kotlin/com/lambda/interaction/request/rotating/RotationConfig.kt +++ b/src/main/kotlin/com/lambda/interaction/request/rotating/RotationConfig.kt @@ -17,8 +17,8 @@ package com.lambda.interaction.request.rotating -import com.lambda.config.AbstractSetting import com.lambda.config.ISettingGroup +import com.lambda.config.Setting import com.lambda.event.events.TickEvent interface RotationConfig : ISettingGroup { @@ -50,7 +50,7 @@ interface RotationConfig : ISettingGroup { val rotate: Boolean get() = rotationMode != RotationMode.None open class Instant(mode: RotationMode) : RotationConfig { - override val settings = mutableListOf>() + override val settings = mutableListOf>() override val rotationMode = mode override val keepTicks = 1 override val decayTicks = 1 diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index 2c6dd6625..0d2d29887 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -19,7 +19,7 @@ package com.lambda.module import com.lambda.Lambda import com.lambda.command.LambdaCommand -import com.lambda.config.AbstractSetting +import com.lambda.config.SettingCore import com.lambda.config.AutomationConfig import com.lambda.config.Configurable import com.lambda.config.Configuration @@ -59,7 +59,7 @@ import com.lambda.util.Nameable * If a module does not need to be activated by a key (like [ClickGui]), * the default [keybind] should not be set (using [KeyCode.Unbound]). * - * [Module]s are [Configurable]s with [settings] (see [AbstractSetting] for all setting types). + * [Module]s are [Configurable]s with [settings] (see [SettingCore] for all setting types). * Example: * ``` * private val foo by setting("Foo", true) diff --git a/src/main/kotlin/com/lambda/util/Formatting.kt b/src/main/kotlin/com/lambda/util/Formatting.kt index 4217f551d..bd37d3e3e 100644 --- a/src/main/kotlin/com/lambda/util/Formatting.kt +++ b/src/main/kotlin/com/lambda/util/Formatting.kt @@ -17,7 +17,7 @@ package com.lambda.util -import com.lambda.config.AbstractSetting +import com.lambda.config.Setting import com.lambda.config.groups.FormatterConfig import com.lambda.util.math.Vec2d import net.minecraft.util.math.Vec2f @@ -124,7 +124,7 @@ object Formatting { } object Default : FormatterConfig { - override val settings = mutableListOf>() + override val settings = mutableListOf>() override val locale: Locale = Locale.US override val separator: String = "," override val prefix: String = "(" From 5ec50b392e360021ff34e66adb3cc8e872f2cdbe Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Tue, 2 Dec 2025 21:23:27 +0000 Subject: [PATCH 2/9] cleanup --- .../kotlin/com/lambda/config/Configurable.kt | 74 +++++++++---------- .../config/{SettingCore.kt => Setting.kt} | 1 - .../com/lambda/config/UserAutomationConfig.kt | 4 +- .../{CharSettingCore.kt => CharSetting.kt} | 2 +- ...ctionSettingCore.kt => FunctionSetting.kt} | 2 +- ...umericSettingCore.kt => NumericSetting.kt} | 10 +-- ...{StringSettingCore.kt => StringSetting.kt} | 6 +- ...ttingCore.kt => BlockCollectionSetting.kt} | 4 +- ...ttingCore.kt => ClassCollectionSetting.kt} | 6 +- ...ionSettingCore.kt => CollectionSetting.kt} | 10 +-- ...ettingCore.kt => ItemCollectionSetting.kt} | 4 +- .../{MapSettingCore.kt => MapSetting.kt} | 2 +- ...ooleanSettingCore.kt => BooleanSetting.kt} | 2 +- .../{EnumSettingCore.kt => EnumSetting.kt} | 2 +- ...ckPosSettingCore.kt => BlockPosSetting.kt} | 2 +- .../{BlockSettingCore.kt => BlockSetting.kt} | 2 +- .../{ColorSettingCore.kt => ColorSetting.kt} | 2 +- ...eybindSettingCore.kt => KeybindSetting.kt} | 0 .../{Vec3DSettingCore.kt => Vec3DSetting.kt} | 2 +- ...{DoubleSettingCore.kt => DoubleSetting.kt} | 6 +- .../{FloatSettingCore.kt => FloatSetting.kt} | 6 +- ...ntegerSettingCore.kt => IntegerSetting.kt} | 6 +- .../{LongSettingCore.kt => LongSetting.kt} | 6 +- 23 files changed, 80 insertions(+), 81 deletions(-) rename src/main/kotlin/com/lambda/config/{SettingCore.kt => Setting.kt} (99%) rename src/main/kotlin/com/lambda/config/settings/{CharSettingCore.kt => CharSetting.kt} (96%) rename src/main/kotlin/com/lambda/config/settings/{FunctionSettingCore.kt => FunctionSetting.kt} (94%) rename src/main/kotlin/com/lambda/config/settings/{NumericSettingCore.kt => NumericSetting.kt} (91%) rename src/main/kotlin/com/lambda/config/settings/{StringSettingCore.kt => StringSetting.kt} (92%) rename src/main/kotlin/com/lambda/config/settings/collections/{BlockCollectionSettingCore.kt => BlockCollectionSetting.kt} (97%) rename src/main/kotlin/com/lambda/config/settings/collections/{ClassCollectionSettingCore.kt => ClassCollectionSetting.kt} (97%) rename src/main/kotlin/com/lambda/config/settings/collections/{CollectionSettingCore.kt => CollectionSetting.kt} (90%) rename src/main/kotlin/com/lambda/config/settings/collections/{ItemCollectionSettingCore.kt => ItemCollectionSetting.kt} (97%) rename src/main/kotlin/com/lambda/config/settings/collections/{MapSettingCore.kt => MapSetting.kt} (97%) rename src/main/kotlin/com/lambda/config/settings/comparable/{BooleanSettingCore.kt => BooleanSetting.kt} (95%) rename src/main/kotlin/com/lambda/config/settings/comparable/{EnumSettingCore.kt => EnumSetting.kt} (97%) rename src/main/kotlin/com/lambda/config/settings/complex/{BlockPosSettingCore.kt => BlockPosSetting.kt} (96%) rename src/main/kotlin/com/lambda/config/settings/complex/{BlockSettingCore.kt => BlockSetting.kt} (96%) rename src/main/kotlin/com/lambda/config/settings/complex/{ColorSettingCore.kt => ColorSetting.kt} (97%) rename src/main/kotlin/com/lambda/config/settings/complex/{KeybindSettingCore.kt => KeybindSetting.kt} (100%) rename src/main/kotlin/com/lambda/config/settings/complex/{Vec3DSettingCore.kt => Vec3DSetting.kt} (96%) rename src/main/kotlin/com/lambda/config/settings/numeric/{DoubleSettingCore.kt => DoubleSetting.kt} (94%) rename src/main/kotlin/com/lambda/config/settings/numeric/{FloatSettingCore.kt => FloatSetting.kt} (94%) rename src/main/kotlin/com/lambda/config/settings/numeric/{IntegerSettingCore.kt => IntegerSetting.kt} (94%) rename src/main/kotlin/com/lambda/config/settings/numeric/{LongSettingCore.kt => LongSetting.kt} (95%) diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index 1927d6247..208ef8627 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -21,26 +21,26 @@ import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.reflect.TypeToken import com.lambda.Lambda.LOG -import com.lambda.config.settings.CharSettingCore -import com.lambda.config.settings.FunctionSettingCore -import com.lambda.config.settings.StringSettingCore -import com.lambda.config.settings.collections.BlockCollectionSettingCore -import com.lambda.config.settings.collections.ClassCollectionSettingCore -import com.lambda.config.settings.collections.CollectionSettingCore -import com.lambda.config.settings.collections.ItemCollectionSettingCore -import com.lambda.config.settings.collections.MapSettingCore -import com.lambda.config.settings.comparable.BooleanSettingCore -import com.lambda.config.settings.comparable.EnumSettingCore +import com.lambda.config.settings.CharSetting +import com.lambda.config.settings.FunctionSetting +import com.lambda.config.settings.StringSetting +import com.lambda.config.settings.collections.BlockCollectionSetting +import com.lambda.config.settings.collections.ClassCollectionSetting +import com.lambda.config.settings.collections.CollectionSetting +import com.lambda.config.settings.collections.ItemCollectionSetting +import com.lambda.config.settings.collections.MapSetting +import com.lambda.config.settings.comparable.BooleanSetting +import com.lambda.config.settings.comparable.EnumSetting import com.lambda.config.settings.complex.Bind -import com.lambda.config.settings.complex.BlockPosSettingCore -import com.lambda.config.settings.complex.BlockSettingCore -import com.lambda.config.settings.complex.ColorSettingCore +import com.lambda.config.settings.complex.BlockPosSetting +import com.lambda.config.settings.complex.BlockSetting +import com.lambda.config.settings.complex.ColorSetting import com.lambda.config.settings.complex.KeybindSettingCore -import com.lambda.config.settings.complex.Vec3DSettingCore -import com.lambda.config.settings.numeric.DoubleSettingCore -import com.lambda.config.settings.numeric.FloatSettingCore -import com.lambda.config.settings.numeric.IntegerSettingCore -import com.lambda.config.settings.numeric.LongSettingCore +import com.lambda.config.settings.complex.Vec3DSetting +import com.lambda.config.settings.numeric.DoubleSetting +import com.lambda.config.settings.numeric.FloatSetting +import com.lambda.config.settings.numeric.IntegerSetting +import com.lambda.config.settings.numeric.LongSetting import com.lambda.util.Communication.logError import com.lambda.util.KeyCode import com.lambda.util.Nameable @@ -101,7 +101,7 @@ abstract class Configurable( defaultValue: Boolean, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BooleanSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, BooleanSetting(defaultValue), visibility).register() inline fun > setting( name: String, @@ -109,14 +109,14 @@ abstract class Configurable( description: String = "", noinline visibility: () -> Boolean = { true }, - ) = Setting(name, description,EnumSettingCore(defaultValue), visibility).register() + ) = Setting(name, description,EnumSetting(defaultValue), visibility).register() fun setting( name: String, defaultValue: Char, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, CharSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, CharSetting(defaultValue), visibility).register() fun setting( name: String, @@ -125,7 +125,7 @@ abstract class Configurable( flags: Int = ImGuiInputTextFlags.None, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, StringSettingCore(defaultValue, multiline, flags), visibility).register() + ) = Setting(name, description, StringSetting(defaultValue, multiline, flags), visibility).register() @JvmName("collectionSetting1") fun setting( @@ -134,7 +134,7 @@ abstract class Configurable( immutableCollection: Collection = Registries.BLOCK.toList(), description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BlockCollectionSettingCore(immutableCollection, defaultValue.toMutableList()), visibility).register() + ) = Setting(name, description, BlockCollectionSetting(immutableCollection, defaultValue.toMutableList()), visibility).register() @JvmName("collectionSetting2") fun setting( @@ -143,7 +143,7 @@ abstract class Configurable( immutableCollection: Collection = Registries.ITEM.toList(), description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, ItemCollectionSettingCore(immutableCollection, defaultValue.toMutableList()), visibility).register() + ) = Setting(name, description, ItemCollectionSetting(immutableCollection, defaultValue.toMutableList()), visibility).register() @JvmName("collectionSetting3") inline fun > setting( @@ -155,7 +155,7 @@ abstract class Configurable( ) = Setting( name, description, - CollectionSettingCore( + CollectionSetting( defaultValue.toMutableList(), immutableList, TypeToken.getParameterized(Collection::class.java, T::class.java).type @@ -170,7 +170,7 @@ abstract class Configurable( immutableList: Collection = defaultValue, description: String = "", noinline visibility: () -> Boolean = { true }, - ) = Setting(name, description, ClassCollectionSettingCore(immutableList, defaultValue.toMutableList()), visibility).register() + ) = Setting(name, description, ClassCollectionSetting(immutableList, defaultValue.toMutableList()), visibility).register() // ToDo: Actually implement maps inline fun setting( @@ -181,7 +181,7 @@ abstract class Configurable( ) = Setting( name, description, - MapSettingCore( + MapSetting( defaultValue.toMutableMap(), TypeToken.getParameterized(MutableMap::class.java, K::class.java, V::class.java).type ), @@ -196,7 +196,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, DoubleSettingCore(defaultValue, range, step, unit), visibility).register() + ) = Setting(name, description, DoubleSetting(defaultValue, range, step, unit), visibility).register() fun setting( name: String, @@ -206,7 +206,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, FloatSettingCore(defaultValue, range, step, unit), visibility).register() + ) = Setting(name, description, FloatSetting(defaultValue, range, step, unit), visibility).register() fun setting( name: String, @@ -216,7 +216,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, IntegerSettingCore(defaultValue, range, step, unit), visibility).register() + ) = Setting(name, description, IntegerSetting(defaultValue, range, step, unit), visibility).register() fun setting( name: String, @@ -226,7 +226,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, LongSettingCore(defaultValue, range, step, unit), visibility).register() + ) = Setting(name, description, LongSetting(defaultValue, range, step, unit), visibility).register() fun setting( name: String, @@ -247,40 +247,40 @@ abstract class Configurable( defaultValue: Color, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, ColorSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, ColorSetting(defaultValue), visibility).register() fun setting( name: String, defaultValue: Vec3d, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, Vec3DSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, Vec3DSetting(defaultValue), visibility).register() fun setting( name: String, defaultValue: BlockPos.Mutable, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BlockPosSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, BlockPosSetting(defaultValue), visibility).register() fun setting( name: String, defaultValue: BlockPos, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BlockPosSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, BlockPosSetting(defaultValue), visibility).register() fun setting( name: String, defaultValue: Block, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BlockSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, BlockSetting(defaultValue), visibility).register() fun setting( name: String, defaultValue: () -> Unit, description: String = "", visibility: () -> Boolean = { true } - ) = Setting(name, description, FunctionSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, FunctionSetting(defaultValue), visibility).register() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/SettingCore.kt b/src/main/kotlin/com/lambda/config/Setting.kt similarity index 99% rename from src/main/kotlin/com/lambda/config/SettingCore.kt rename to src/main/kotlin/com/lambda/config/Setting.kt index a7e821f05..dd9217fed 100644 --- a/src/main/kotlin/com/lambda/config/SettingCore.kt +++ b/src/main/kotlin/com/lambda/config/Setting.kt @@ -30,7 +30,6 @@ import com.lambda.brigadier.required import com.lambda.command.CommandRegistry import com.lambda.command.commands.ConfigCommand import com.lambda.context.SafeContext -import com.lambda.gui.Layout import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.threading.runSafe import com.lambda.util.Communication.info diff --git a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt index df6972152..522678ed4 100644 --- a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt @@ -18,8 +18,8 @@ package com.lambda.config import com.lambda.config.configurations.UserAutomationConfigs -import com.lambda.config.settings.collections.CollectionSettingCore.Companion.onDeselect -import com.lambda.config.settings.collections.CollectionSettingCore.Companion.onSelect +import com.lambda.config.settings.collections.CollectionSetting.Companion.onDeselect +import com.lambda.config.settings.collections.CollectionSetting.Companion.onSelect import com.lambda.module.Module import com.lambda.module.ModuleRegistry.moduleNameMap diff --git a/src/main/kotlin/com/lambda/config/settings/CharSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/CharSetting.kt similarity index 96% rename from src/main/kotlin/com/lambda/config/settings/CharSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/CharSetting.kt index a0ffff322..d32c394be 100644 --- a/src/main/kotlin/com/lambda/config/settings/CharSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/CharSetting.kt @@ -33,7 +33,7 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class CharSettingCore(defaultValue: Char) : SettingCore( +class CharSetting(defaultValue: Char) : SettingCore( defaultValue, TypeToken.get(Char::class.java).type ) { diff --git a/src/main/kotlin/com/lambda/config/settings/FunctionSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt similarity index 94% rename from src/main/kotlin/com/lambda/config/settings/FunctionSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt index 448661ec2..eb3cef115 100644 --- a/src/main/kotlin/com/lambda/config/settings/FunctionSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt @@ -24,7 +24,7 @@ import com.lambda.config.Setting import com.lambda.config.SettingCore import com.lambda.gui.dsl.ImGuiBuilder -open class FunctionSettingCore(defaultValue: () -> T) : SettingCore<() -> T>( +open class FunctionSetting(defaultValue: () -> T) : SettingCore<() -> T>( defaultValue, TypeToken.get(defaultValue::class.java).type ) { diff --git a/src/main/kotlin/com/lambda/config/settings/NumericSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt similarity index 91% rename from src/main/kotlin/com/lambda/config/settings/NumericSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/NumericSetting.kt index 65adc8b34..cdc003227 100644 --- a/src/main/kotlin/com/lambda/config/settings/NumericSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt @@ -34,7 +34,7 @@ import kotlin.reflect.KProperty /** * @see [com.lambda.config.Configurable] */ -abstract class NumericSettingCore( +abstract class NumericSetting( value: T, open var range: ClosedRange, open var step: T, @@ -61,7 +61,7 @@ abstract class NumericSettingCore( override fun ImGuiBuilder.buildLayout() { val showReset = setting.isModified val resetButtonText = "R" - val valueString = this@NumericSettingCore.toString() + val valueString = this@NumericSetting.toString() buildSlider() lambdaTooltip(setting.description) @@ -98,19 +98,19 @@ abstract class NumericSettingCore( @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.range(range: ClosedRange) where T : Number, T : Comparable { - (settings as Collection>).forEach { it.range = range } + (settings as Collection>).forEach { it.range = range } } @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.step(step: T) where T : Number, T : Comparable { - (settings as Collection>).forEach { it.step = step } + (settings as Collection>).forEach { it.step = step } } @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.unit(unit: String) where T : Number, T : Comparable { - (settings as Collection>).forEach { it.unit = unit} + (settings as Collection>).forEach { it.unit = unit} } } } diff --git a/src/main/kotlin/com/lambda/config/settings/StringSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/StringSetting.kt similarity index 92% rename from src/main/kotlin/com/lambda/config/settings/StringSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/StringSetting.kt index 62a7a497e..fdf569979 100644 --- a/src/main/kotlin/com/lambda/config/settings/StringSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/StringSetting.kt @@ -34,7 +34,7 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class StringSettingCore( +class StringSetting( defaultValue: String, var multiline: Boolean = false, var flags: Int = ImGuiInputTextFlags.None, @@ -65,13 +65,13 @@ class StringSettingCore( @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.multiline(multiline: Boolean) { - (settings as Collection).forEach { it.multiline = multiline } + (settings as Collection).forEach { it.multiline = multiline } } @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder.flags(flags: Int) { - (settings as Collection).forEach { it.flags = flags } + (settings as Collection).forEach { it.flags = flags } } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt similarity index 97% rename from src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt index 5d6a39df9..2ed52d2cb 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt @@ -29,10 +29,10 @@ import imgui.flag.ImGuiChildFlags import imgui.flag.ImGuiSelectableFlags.DontClosePopups import net.minecraft.block.Block -class BlockCollectionSettingCore( +class BlockCollectionSetting( private val immutableCollection: Collection, defaultValue: MutableCollection, -) : CollectionSettingCore( +) : CollectionSetting( defaultValue, immutableCollection, TypeToken.getParameterized(Collection::class.java, Block::class.java).type diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt similarity index 97% rename from src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt index 027fb8f0c..51f845f22 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt @@ -29,13 +29,13 @@ import imgui.flag.ImGuiChildFlags import imgui.flag.ImGuiSelectableFlags.DontClosePopups /** - * @see [com.lambda.config.settings.collections.CollectionSettingCore] + * @see [com.lambda.config.settings.collections.CollectionSetting] * @see [com.lambda.config.Configurable] */ -class ClassCollectionSettingCore( +class ClassCollectionSetting( private val immutableCollection: Collection, defaultValue: MutableCollection -) : CollectionSettingCore( +) : CollectionSetting( defaultValue, immutableCollection, TypeToken.getParameterized(Collection::class.java, Any::class.java).type diff --git a/src/main/kotlin/com/lambda/config/settings/collections/CollectionSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt similarity index 90% rename from src/main/kotlin/com/lambda/config/settings/collections/CollectionSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt index c118537fc..8628586b9 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/CollectionSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt @@ -35,14 +35,14 @@ import java.lang.reflect.Type /** * This generic collection settings handles all [Comparable] values (i.e not classes) and serialize * their values by calling [Any.toString] and loads them by comparing what's in the [immutableCollection]. - * This behaviour is by design. If you wish to store collections of non-comparable values you must use [ClassCollectionSettingCore]. + * This behaviour is by design. If you wish to store collections of non-comparable values you must use [ClassCollectionSetting]. * * If you wish to use a different codec or simply display values differently you must create your own * collection setting. * * @see [com.lambda.config.Configurable] */ -open class CollectionSettingCore( +open class CollectionSetting( defaultValue: MutableCollection, private var immutableCollection: Collection, type: Type @@ -108,18 +108,18 @@ open class CollectionSettingCore( } companion object { - fun Setting, MutableCollection>.onSelect(block: SafeContext.(T) -> Unit) = apply { + fun Setting, MutableCollection>.onSelect(block: SafeContext.(T) -> Unit) = apply { core.selectListeners.add(block) } - fun Setting, MutableCollection>.onDeselect(block: SafeContext.(T) -> Unit) = apply { + fun Setting, MutableCollection>.onDeselect(block: SafeContext.(T) -> Unit) = apply { core.deselectListeners.add(block) } @SettingEditorDsl @Suppress("unchecked_cast") fun SettingGroupEditor.TypedEditBuilder>.immutableCollection(collection: Collection) { - (settings as Collection>).forEach { it.immutableCollection = collection } + (settings as Collection>).forEach { it.immutableCollection = collection } } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt similarity index 97% rename from src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt index 4347f2e3d..ee12981c6 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt @@ -29,10 +29,10 @@ import imgui.flag.ImGuiChildFlags import imgui.flag.ImGuiSelectableFlags.DontClosePopups import net.minecraft.item.Item -class ItemCollectionSettingCore( +class ItemCollectionSetting( private val immutableCollection: Collection, defaultValue: MutableCollection -) : CollectionSettingCore( +) : CollectionSetting( defaultValue, immutableCollection, TypeToken.getParameterized(Collection::class.java, Item::class.java).type diff --git a/src/main/kotlin/com/lambda/config/settings/collections/MapSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt similarity index 97% rename from src/main/kotlin/com/lambda/config/settings/collections/MapSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt index e83c202da..3e0fba2ac 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/MapSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt @@ -25,7 +25,7 @@ import java.lang.reflect.Type /** * @see [com.lambda.config.Configurable] */ -class MapSettingCore( +class MapSetting( defaultValue: MutableMap, type: Type ) : SettingCore>( diff --git a/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt similarity index 95% rename from src/main/kotlin/com/lambda/config/settings/comparable/BooleanSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt index fd035f693..bf08e9c49 100644 --- a/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt @@ -31,7 +31,7 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class BooleanSettingCore(defaultValue: Boolean) : SettingCore( +class BooleanSetting(defaultValue: Boolean) : SettingCore( defaultValue, TypeToken.get(Boolean::class.java).type ) { diff --git a/src/main/kotlin/com/lambda/config/settings/comparable/EnumSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt similarity index 97% rename from src/main/kotlin/com/lambda/config/settings/comparable/EnumSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt index 14b997e13..182f145c4 100644 --- a/src/main/kotlin/com/lambda/config/settings/comparable/EnumSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt @@ -38,7 +38,7 @@ import kotlin.properties.Delegates /** * @see [com.lambda.config.Configurable] */ -class EnumSettingCore>(defaultValue: T) : SettingCore( +class EnumSetting>(defaultValue: T) : SettingCore( defaultValue, TypeToken.get(defaultValue.declaringJavaClass).type ) { diff --git a/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt similarity index 96% rename from src/main/kotlin/com/lambda/config/settings/complex/BlockPosSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt index 89026c45a..907b74d96 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt @@ -33,7 +33,7 @@ import net.minecraft.util.math.BlockPos /** * @see [com.lambda.config.Configurable] */ -class BlockPosSettingCore(defaultValue: BlockPos) : SettingCore( +class BlockPosSetting(defaultValue: BlockPos) : SettingCore( defaultValue, TypeToken.get(BlockPos::class.java).type ) { diff --git a/src/main/kotlin/com/lambda/config/settings/complex/BlockSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt similarity index 96% rename from src/main/kotlin/com/lambda/config/settings/complex/BlockSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt index 6b17e8926..87ca679f2 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/BlockSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt @@ -32,7 +32,7 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class BlockSettingCore(defaultValue: Block) : SettingCore( +class BlockSetting(defaultValue: Block) : SettingCore( defaultValue, TypeToken.get(Block::class.java).type ) { diff --git a/src/main/kotlin/com/lambda/config/settings/complex/ColorSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt similarity index 97% rename from src/main/kotlin/com/lambda/config/settings/complex/ColorSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt index 0f333baaa..1621da90e 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/ColorSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt @@ -33,7 +33,7 @@ import java.awt.Color /** * @see [com.lambda.config.Configurable] */ -class ColorSettingCore(defaultValue: Color) : SettingCore( +class ColorSetting(defaultValue: Color) : SettingCore( defaultValue, TypeToken.get(Color::class.java).type ) { diff --git a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt similarity index 100% rename from src/main/kotlin/com/lambda/config/settings/complex/KeybindSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt diff --git a/src/main/kotlin/com/lambda/config/settings/complex/Vec3DSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/complex/Vec3DSetting.kt similarity index 96% rename from src/main/kotlin/com/lambda/config/settings/complex/Vec3DSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/complex/Vec3DSetting.kt index 901b6fdba..a63b03b6e 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/Vec3DSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/Vec3DSetting.kt @@ -29,7 +29,7 @@ import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess import net.minecraft.util.math.Vec3d -class Vec3DSettingCore(defaultValue: Vec3d, ) : SettingCore( +class Vec3DSetting(defaultValue: Vec3d) : SettingCore( defaultValue, TypeToken.get(Vec3d::class.java).type ) { diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt similarity index 94% rename from src/main/kotlin/com/lambda/config/settings/numeric/DoubleSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt index 285188381..e6577b751 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt @@ -23,7 +23,7 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required import com.lambda.config.Setting -import com.lambda.config.settings.NumericSettingCore +import com.lambda.config.settings.NumericSetting import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -32,12 +32,12 @@ import kotlin.math.roundToInt /** * @see [com.lambda.config.Configurable] */ -class DoubleSettingCore( +class DoubleSetting( defaultValue: Double, override var range: ClosedRange, override var step: Double, unit: String -) : NumericSettingCore( +) : NumericSetting( defaultValue, range, step, diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/FloatSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt similarity index 94% rename from src/main/kotlin/com/lambda/config/settings/numeric/FloatSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt index 7bae3f291..469655a71 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/FloatSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt @@ -22,7 +22,7 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required import com.lambda.config.Setting -import com.lambda.config.settings.NumericSettingCore +import com.lambda.config.settings.NumericSetting import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -31,12 +31,12 @@ import kotlin.math.roundToInt /** * @see [com.lambda.config.Configurable] */ -class FloatSettingCore( +class FloatSetting( defaultValue: Float, override var range: ClosedRange, override var step: Float = 1f, unit: String, -) : NumericSettingCore( +) : NumericSetting( defaultValue, range, step, diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt similarity index 94% rename from src/main/kotlin/com/lambda/config/settings/numeric/IntegerSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt index 06f1a8aa5..2df3b50ad 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt @@ -22,7 +22,7 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required import com.lambda.config.Setting -import com.lambda.config.settings.NumericSettingCore +import com.lambda.config.settings.NumericSetting import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -30,12 +30,12 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class IntegerSettingCore( +class IntegerSetting( defaultValue: Int, override var range: ClosedRange, override var step: Int = 1, unit: String -) : NumericSettingCore( +) : NumericSetting( defaultValue, range, step, diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/LongSettingCore.kt b/src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt similarity index 95% rename from src/main/kotlin/com/lambda/config/settings/numeric/LongSettingCore.kt rename to src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt index fcb4423ef..2198a0f23 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/LongSettingCore.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt @@ -22,7 +22,7 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.required import com.lambda.config.Setting -import com.lambda.config.settings.NumericSettingCore +import com.lambda.config.settings.NumericSetting import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess @@ -30,12 +30,12 @@ import net.minecraft.command.CommandRegistryAccess /** * @see [com.lambda.config.Configurable] */ -class LongSettingCore( +class LongSetting( defaultValue: Long, override var range: ClosedRange, override var step: Long = 1, unit: String -) : NumericSettingCore( +) : NumericSetting( defaultValue, range, step, From af9b1c86a1c6274f6200926a7503e3f6e81aa0f9 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Wed, 3 Dec 2025 02:36:18 +0000 Subject: [PATCH 3/9] it works! Cleanup --- .../lambda/config/MutableAutomationConfig.kt | 47 +++++++++++++++---- src/main/kotlin/com/lambda/config/Setting.kt | 11 +++-- src/main/kotlin/com/lambda/gui/MenuBar.kt | 4 +- .../lambda/gui/components/SettingsWidget.kt | 9 ++-- src/main/kotlin/com/lambda/module/Module.kt | 12 ++--- .../module/modules/player/PacketMine.kt | 2 +- 6 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt b/src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt index 58a90eea8..ee9bf5aca 100644 --- a/src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt @@ -29,14 +29,43 @@ import com.lambda.interaction.request.rotating.RotationConfig interface MutableAutomationConfig : Automated { var defaultAutomationConfig: AutomationConfig - var automationConfig: AutomationConfig + var backingAutomationConfig: AutomationConfig + var automationConfig: AutomationConfig - override val buildConfig: BuildConfig get() = automationConfig.buildConfig - override val breakConfig: BreakConfig get() = automationConfig.breakConfig - override val placeConfig: PlaceConfig get() = automationConfig.placeConfig - override val interactConfig: InteractConfig get() = automationConfig.interactConfig - override val rotationConfig: RotationConfig get() = automationConfig.rotationConfig - override val inventoryConfig: InventoryConfig get() = automationConfig.inventoryConfig - override val hotbarConfig: HotbarConfig get() = automationConfig.hotbarConfig - override val eatConfig: EatConfig get() = automationConfig.eatConfig + override val buildConfig: BuildConfig get() = automationConfig.buildConfig + override val breakConfig: BreakConfig get() = automationConfig.breakConfig + override val placeConfig: PlaceConfig get() = automationConfig.placeConfig + override val interactConfig: InteractConfig get() = automationConfig.interactConfig + override val rotationConfig: RotationConfig get() = automationConfig.rotationConfig + override val inventoryConfig: InventoryConfig get() = automationConfig.inventoryConfig + override val hotbarConfig: HotbarConfig get() = automationConfig.hotbarConfig + override val eatConfig: EatConfig get() = automationConfig.eatConfig +} + +class MutableAutomationConfigImpl : MutableAutomationConfig { + override var defaultAutomationConfig: AutomationConfig = AutomationConfig.Companion.DEFAULT + set(value) { + field = value + automationConfig = value + } + override var backingAutomationConfig: AutomationConfig = defaultAutomationConfig + override var automationConfig: AutomationConfig = defaultAutomationConfig + set(value) { + if (value === defaultAutomationConfig) { + if (backingAutomationConfig !== defaultAutomationConfig) { + field.settings.forEach(Setting<*, *>::restoreOriginalCore) + } + field = value + } else field.settings.forEach { setting -> + value.settings.forEach { newSetting -> + if (setting.name == newSetting.name) { + if (setting.core.type != newSetting.core.type) + throw IllegalStateException("Settings with the same name do not have the same type.") + @Suppress("UNCHECKED_CAST") + (setting as Setting, Any>).core = newSetting.core as SettingCore + } + } + } + backingAutomationConfig = value + } } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/Setting.kt b/src/main/kotlin/com/lambda/config/Setting.kt index dd9217fed..05e1ab436 100644 --- a/src/main/kotlin/com/lambda/config/Setting.kt +++ b/src/main/kotlin/com/lambda/config/Setting.kt @@ -147,6 +147,7 @@ class Setting, R : Any>( var core: T, var visibility: () -> Boolean, ) : Nameable, Describable { + val originalCore = core val listeners = mutableListOf>() var disabled = { false } var groups: MutableList> = mutableListOf() @@ -174,6 +175,10 @@ class Setting, R : Any>( value = core.defaultValue } + fun restoreOriginalCore() { + core = originalCore + } + fun ImGuiBuilder.buildLayout() = with(core) { buildLayout() } fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) = with(core) { buildCommand(registry) } @@ -275,8 +280,8 @@ class Setting, R : Any>( } } - override fun toString() = core.toString() + override fun toString() = "Setting $name: $value of type ${core.type.typeName}" - override fun equals(other: Any?) = core == other - override fun hashCode() = core.hashCode() + override fun equals(other: Any?) = other is Setting<*, *> && name == other.name + override fun hashCode() = name.hashCode() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/gui/MenuBar.kt b/src/main/kotlin/com/lambda/gui/MenuBar.kt index d636bae70..4cf3ef7f9 100644 --- a/src/main/kotlin/com/lambda/gui/MenuBar.kt +++ b/src/main/kotlin/com/lambda/gui/MenuBar.kt @@ -75,7 +75,7 @@ object MenuBar { menu("HUD") { buildHudMenu() } menu("GUI") { buildGuiMenu() } menu("Modules") { buildModulesMenu() } - menu("Automation Configs") { buildConfigPresetsMenu() } + menu("Automation Configs") { buildAutomationConfigsMenu() } menu("Minecraft") { buildMinecraftMenu() } menu("Help") { buildHelpMenu() } buildGitHubReference() @@ -284,7 +284,7 @@ object MenuBar { } } - private fun ImGuiBuilder.buildConfigPresetsMenu() { + private fun ImGuiBuilder.buildAutomationConfigsMenu() { button("New Config") { ImGui.openPopup("##new-config") } popupContextWindow("##new-config") { diff --git a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt index eb302cddd..103b8baa4 100644 --- a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt +++ b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt @@ -51,13 +51,12 @@ object SettingsWidget { popupContextItem("##automation-config-popup-${config.name}", ImGuiPopupFlags.None) { buildConfigSettingsContext(config.automationConfig) } - if (config.automationConfig !== config.defaultAutomationConfig) { + if (config.backingAutomationConfig !== config.defaultAutomationConfig) { sameLine() - text("(${config.automationConfig.name})") + text("(${config.backingAutomationConfig.name})") } } } - separator() val toIgnoreSettings = when (config) { is Module -> setOf(config.keybindSetting, config.disableOnReleaseSetting) @@ -65,8 +64,10 @@ object SettingsWidget { else -> emptySet() } val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings + if (visibleSettings.isEmpty()) return + else separator() val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() } - ungrouped.forEach { + ungrouped.forEach { it.withDisabled { buildLayout() } } renderGroup(grouped, emptyList(), config) diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index 0d2d29887..5b6721d66 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -19,11 +19,11 @@ package com.lambda.module import com.lambda.Lambda import com.lambda.command.LambdaCommand -import com.lambda.config.SettingCore -import com.lambda.config.AutomationConfig import com.lambda.config.Configurable import com.lambda.config.Configuration import com.lambda.config.MutableAutomationConfig +import com.lambda.config.MutableAutomationConfigImpl +import com.lambda.config.SettingCore import com.lambda.config.configurations.ModuleConfigs import com.lambda.config.settings.complex.Bind import com.lambda.context.SafeContext @@ -120,13 +120,7 @@ abstract class Module( enabledByDefault: Boolean = false, defaultKeybind: Bind = Bind.EMPTY, autoDisable: Boolean = false -) : Nameable, Muteable, Configurable(ModuleConfigs), MutableAutomationConfig { - final override var defaultAutomationConfig: AutomationConfig = AutomationConfig.Companion.DEFAULT - set(value) { - field = value - automationConfig = value - } - final override var automationConfig = defaultAutomationConfig +) : Nameable, Muteable, Configurable(ModuleConfigs), MutableAutomationConfig by MutableAutomationConfigImpl() { private val isEnabledSetting = setting("Enabled", enabledByDefault) { false } val keybindSetting = setting("Keybind", defaultKeybind) { false } val disableOnReleaseSetting = setting("Disable On Release", false) { false } diff --git a/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt b/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt index 677bd3443..b63f5871f 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt @@ -99,6 +99,7 @@ object PacketMine : Module( init { setDefaultAutomationConfig { applyEdits { + hideAllGroupsExcept(breakConfig, rotationConfig, hotbarConfig) breakConfig.apply { editTyped( ::avoidLiquids, @@ -111,7 +112,6 @@ object PacketMine : Module( hotbarConfig.apply { ::keepTicks.edit { defaultValue(0) } } - hideGroups(buildConfig, placeConfig, interactConfig, inventoryConfig, eatConfig) } } From 1fb073887ee344aaa053a250ca8cda10b677d104 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Wed, 3 Dec 2025 03:31:01 +0000 Subject: [PATCH 4/9] fix collection setting imgui logic --- .../com/lambda/config/UserAutomationConfig.kt | 2 +- .../collections/BlockCollectionSetting.kt | 45 +--------- .../collections/ClassCollectionSetting.kt | 42 +--------- .../settings/collections/CollectionSetting.kt | 82 +++++++++++-------- .../collections/ItemCollectionSetting.kt | 45 +--------- 5 files changed, 52 insertions(+), 164 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt index 522678ed4..d2398c16b 100644 --- a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt @@ -38,6 +38,6 @@ class UserAutomationConfig(override val name: String) : AutomationConfig(name, U } private fun Module.removeLink() { - (automationConfig as UserAutomationConfig).linkedModules.value -= name + (automationConfig as? UserAutomationConfig)?.linkedModules?.value -= name } } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt index 2ed52d2cb..268650544 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt @@ -21,60 +21,19 @@ import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson import com.lambda.config.Setting -import com.lambda.config.serializer.BlockCodec import com.lambda.gui.dsl.ImGuiBuilder -import com.lambda.util.StringUtils.levenshteinDistance -import imgui.ImGuiListClipper -import imgui.flag.ImGuiChildFlags -import imgui.flag.ImGuiSelectableFlags.DontClosePopups import net.minecraft.block.Block class BlockCollectionSetting( - private val immutableCollection: Collection, + immutableCollection: Collection, defaultValue: MutableCollection, ) : CollectionSetting( defaultValue, immutableCollection, TypeToken.getParameterized(Collection::class.java, Block::class.java).type ) { - private var searchFilter = "" - context(setting: Setting<*, MutableCollection>) - override fun ImGuiBuilder.buildLayout() { - val text = if (value.size == 1) "block" else "blocks" - - combo("##${setting.name}", "${setting.name}: ${value.size} $text") { - inputText("##${setting.name}-SearchBox", ::searchFilter) - - child( - strId = "##${setting.name}-ComboOptionsChild", - childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, - ) { - val list = immutableCollection - .filter { searchFilter == "" || searchFilter.levenshteinDistance(BlockCodec.stringify(it)) < 3 } - - ImGuiListClipper.forEach { // not actually iterating - it.begin(list.size) - - while (it.step()) { - for (i in it.displayStart..it.displayEnd) { - val v = list.getOrNull(i) ?: continue - val selected = value.contains(v) - - selectable( - label = BlockCodec.stringify(v), - selected = selected, - flags = DontClosePopups - ) { - if (selected) value.remove(v) - else value.add(v) - } - } - } - } - } - } - } + override fun ImGuiBuilder.buildLayout() = buildComboBox("block") context(setting: Setting<*, MutableCollection>) override fun toJson(): JsonElement = gson.toJsonTree(value, type) diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt index 51f845f22..2047f6169 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt @@ -22,11 +22,7 @@ import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson import com.lambda.config.Setting import com.lambda.gui.dsl.ImGuiBuilder -import com.lambda.util.StringUtils.levenshteinDistance import com.lambda.util.reflections.className -import imgui.ImGuiListClipper -import imgui.flag.ImGuiChildFlags -import imgui.flag.ImGuiSelectableFlags.DontClosePopups /** * @see [com.lambda.config.settings.collections.CollectionSetting] @@ -40,44 +36,8 @@ class ClassCollectionSetting( immutableCollection, TypeToken.getParameterized(Collection::class.java, Any::class.java).type ) { - private var searchFilter = "" - context(setting: Setting<*, MutableCollection>) - override fun ImGuiBuilder.buildLayout() { - val text = if (value.size == 1) "item" else "items" - - combo("##${setting.name}", "${setting.name}: ${value.size} $text") { - inputText("##${setting.name}-SearchBox", ::searchFilter) - - child( - strId = "##${setting.name}-ComboOptionsChild", - childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, - ) { - val list = immutableCollection - .filter { searchFilter == "" || searchFilter.levenshteinDistance(it.className) < 3 } - - ImGuiListClipper.forEach { // not actually iterating - it.begin(list.size) - - while (it.step()) { - for (i in it.displayStart..it.displayEnd) { - val v = list.getOrNull(i) ?: continue - val selected = value.contains(v) - - selectable( - label = v.className, - selected = selected, - flags = DontClosePopups - ) { - if (selected) value.remove(v) - else value.add(v) - } - } - } - } - } - } - } + override fun ImGuiBuilder.buildLayout() = buildComboBox("item") // When serializing the list to json we do not want to serialize the elements' classes, but their stringified representation. // If we do serialize the classes we'll run into missing type adapters errors by Gson. diff --git a/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt index 8628586b9..5c22a5d3d 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt @@ -26,8 +26,9 @@ import com.lambda.config.SettingEditorDsl import com.lambda.config.SettingGroupEditor import com.lambda.context.SafeContext import com.lambda.gui.dsl.ImGuiBuilder -import com.lambda.util.StringUtils.levenshteinDistance +import com.lambda.threading.runSafe import imgui.ImGuiListClipper +import imgui.callback.ImListClipperCallback import imgui.flag.ImGuiChildFlags import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -58,41 +59,50 @@ open class CollectionSetting( val deselectListeners = mutableListOf Unit>() context(setting: Setting<*, MutableCollection>) - override fun ImGuiBuilder.buildLayout() { - val text = if (value.size == 1) "item" else "items" - - combo("##${setting.name}", "${setting.name}: ${value.size} $text") { - inputText("##${setting.name}-SearchBox", ::searchFilter) - - child( - strId = "##${setting.name}-ComboOptionsChild", - childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, - ) { - val list = immutableCollection - .filter { searchFilter == "" || searchFilter.levenshteinDistance(it.toString()) < 3 } - - ImGuiListClipper.forEach { // not actually iterating - it.begin(list.size) - - while (it.step()) { - for (i in it.displayStart..it.displayEnd) { - val v = list.getOrNull(i) ?: continue - val selected = value.contains(v) - - selectable( - label = v.toString(), - selected = selected, - flags = DontClosePopups - ) { - if (selected) value.remove(v) - else value.add(v) - } - } - } - } - } - } - } + override fun ImGuiBuilder.buildLayout() = buildComboBox("item") + + context(setting: Setting<*, MutableCollection>) + fun ImGuiBuilder.buildComboBox(itemName: String) { + val text = if (value.size == 1) itemName else "${itemName}s" + + combo("##${setting.name}", "${setting.name}: ${value.size} $text") { + inputText("##${setting.name}-SearchBox", ::searchFilter) + + child( + strId = "##${setting.name}-ComboOptionsChild", + childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, + ) { + val list = immutableCollection + .filter { item -> + val q = searchFilter.trim() + if (q.isEmpty()) true + else item.toString().startsWith(q, ignoreCase = true) + } + + val listClipperCallback = object : ImListClipperCallback() { + override fun accept(index: Int) { + val v = list.getOrNull(index) ?: return + val selected = value.contains(v) + + selectable( + label = v.toString(), + selected = selected, + flags = DontClosePopups + ) { + if (selected) { + value.remove(v) + runSafe { deselectListeners.forEach { listener -> listener(v) } } + } else { + value.add(v) + runSafe { selectListeners.forEach { listener -> listener(v) } } + } + } + } + } + ImGuiListClipper.forEach(list.size, listClipperCallback) + } + } + } context(setting: Setting<*, MutableCollection>) override fun toJson(): JsonElement = diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt index ee12981c6..8432a8568 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt @@ -21,60 +21,19 @@ import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson import com.lambda.config.Setting -import com.lambda.config.serializer.ItemCodec import com.lambda.gui.dsl.ImGuiBuilder -import com.lambda.util.StringUtils.levenshteinDistance -import imgui.ImGuiListClipper -import imgui.flag.ImGuiChildFlags -import imgui.flag.ImGuiSelectableFlags.DontClosePopups import net.minecraft.item.Item class ItemCollectionSetting( - private val immutableCollection: Collection, + immutableCollection: Collection, defaultValue: MutableCollection ) : CollectionSetting( defaultValue, immutableCollection, TypeToken.getParameterized(Collection::class.java, Item::class.java).type ) { - private var searchFilter = "" - context(setting: Setting<*, MutableCollection>) - override fun ImGuiBuilder.buildLayout() { - val text = if (value.size == 1) "item" else "items" - - combo("##${setting.name}", "${setting.name}: ${value.size} $text") { - inputText("##${setting.name}-SearchBox", ::searchFilter) - - child( - strId = "##${setting.name}-ComboOptionsChild", - childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize, - ) { - val list = immutableCollection - .filter { searchFilter == "" || searchFilter.levenshteinDistance(ItemCodec.stringify(it)) < 3 } - - ImGuiListClipper.forEach { // not actually iterating - it.begin(list.size) - - while (it.step()) { - for (i in it.displayStart..it.displayEnd) { - val v = list.getOrNull(i) ?: continue - val selected = value.contains(v) - - selectable( - label = ItemCodec.stringify(v), - selected = selected, - flags = DontClosePopups - ) { - if (selected) value.remove(v) - else value.add(v) - } - } - } - } - } - } - } + override fun ImGuiBuilder.buildLayout() = buildComboBox("item") context(setting: Setting<*, MutableCollection>) override fun toJson(): JsonElement = gson.toJsonTree(value, type) From 48a79ad9ad5cf8afe07610a467a40c81fe0f2b61 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Wed, 3 Dec 2025 03:34:19 +0000 Subject: [PATCH 5/9] save and load settings from original setting core --- src/main/kotlin/com/lambda/config/Setting.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/Setting.kt b/src/main/kotlin/com/lambda/config/Setting.kt index 05e1ab436..ccb2721a8 100644 --- a/src/main/kotlin/com/lambda/config/Setting.kt +++ b/src/main/kotlin/com/lambda/config/Setting.kt @@ -182,8 +182,8 @@ class Setting, R : Any>( fun ImGuiBuilder.buildLayout() = with(core) { buildLayout() } fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) = with(core) { buildCommand(registry) } - fun toJson() = core.toJson() - fun loadFromJson(serialized: JsonElement) = core.loadFromJson(serialized) + fun toJson() = originalCore.toJson() + fun loadFromJson(serialized: JsonElement) = originalCore.loadFromJson(serialized) class ValueListener(val requiresValueChange: Boolean, val execute: (from: T, to: T) -> Unit) From c83fcbc2d348a431590acd93248fde4c30a3b380 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Wed, 3 Dec 2025 04:15:37 +0000 Subject: [PATCH 6/9] store configurable in setting, check and throw if duplicate configuration / configurable, and remove visibility edit (which we can add back at a later date to setting core if it's needed) --- .../lambda/command/commands/ConfigCommand.kt | 6 +-- .../kotlin/com/lambda/config/ConfigEditor.kt | 4 -- .../kotlin/com/lambda/config/Configurable.kt | 49 +++++++++++-------- .../kotlin/com/lambda/config/Configuration.kt | 16 +++--- src/main/kotlin/com/lambda/config/Setting.kt | 14 +++--- 5 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt b/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt index 9147800f0..f0b50d65e 100644 --- a/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt +++ b/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt @@ -76,13 +76,13 @@ object ConfigCommand : LambdaCommand( executeWithResult { val confName = config().value() val settingName = setting().value() - val conf = Configuration.configurableByCommandName(confName) ?: run { + val configurable = Configuration.configurableByCommandName(confName) ?: run { return@executeWithResult failure("$confName is not a valid configurable.") } - val setDel = Configuration.settingDelegateByCommandName(conf, settingName) ?: run { + val setting = Configuration.settingByCommandName(configurable, settingName) ?: run { return@executeWithResult failure("$settingName is not a valid setting for $confName.") } - setDel.reset() + setting.reset() return@executeWithResult success() } } diff --git a/src/main/kotlin/com/lambda/config/ConfigEditor.kt b/src/main/kotlin/com/lambda/config/ConfigEditor.kt index eee9a8671..4a9e168b9 100644 --- a/src/main/kotlin/com/lambda/config/ConfigEditor.kt +++ b/src/main/kotlin/com/lambda/config/ConfigEditor.kt @@ -92,10 +92,6 @@ open class SettingGroupEditor(open val c: T) { hide(settings.map { it.setting() }) open class BasicEditBuilder(val c: SettingGroupEditor<*>, open val settings: Collection>) { - @SettingEditorDsl - fun visibility(vis: () -> Boolean) = - settings.forEach { it.visibility = vis } - @SettingEditorDsl fun hide() = c.hide(settings) diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index 208ef8627..4662c3d05 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -21,6 +21,7 @@ import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.reflect.TypeToken import com.lambda.Lambda.LOG +import com.lambda.config.Configuration.Companion.configurables import com.lambda.config.settings.CharSetting import com.lambda.config.settings.FunctionSetting import com.lambda.config.settings.StringSetting @@ -61,7 +62,7 @@ import java.awt.Color * @property settings A set of [SettingCore]s that this configurable manages. */ abstract class Configurable( - private val configuration: Configuration, + val configuration: Configuration, ) : Jsonable, Nameable { val settings = mutableListOf>() val settingGroups = mutableListOf() @@ -70,7 +71,11 @@ abstract class Configurable( registerConfigurable() } - private fun registerConfigurable() = configuration.configurables.add(this) + private fun registerConfigurable() { + if (configurables.any { it.name == name }) + throw IllegalStateException("Configurable with name $name already exists") + configuration.configurables.add(this) + } fun , R : Any> Setting.register() = apply { if (settings.any { it.name == name }) @@ -101,7 +106,7 @@ abstract class Configurable( defaultValue: Boolean, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BooleanSetting(defaultValue), visibility).register() + ) = Setting(name, description, BooleanSetting(defaultValue), this, visibility).register() inline fun > setting( name: String, @@ -109,14 +114,14 @@ abstract class Configurable( description: String = "", noinline visibility: () -> Boolean = { true }, - ) = Setting(name, description,EnumSetting(defaultValue), visibility).register() + ) = Setting(name, description,EnumSetting(defaultValue), this, visibility).register() fun setting( name: String, defaultValue: Char, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, CharSetting(defaultValue), visibility).register() + ) = Setting(name, description, CharSetting(defaultValue), this, visibility).register() fun setting( name: String, @@ -125,7 +130,7 @@ abstract class Configurable( flags: Int = ImGuiInputTextFlags.None, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, StringSetting(defaultValue, multiline, flags), visibility).register() + ) = Setting(name, description, StringSetting(defaultValue, multiline, flags), this, visibility).register() @JvmName("collectionSetting1") fun setting( @@ -134,7 +139,7 @@ abstract class Configurable( immutableCollection: Collection = Registries.BLOCK.toList(), description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BlockCollectionSetting(immutableCollection, defaultValue.toMutableList()), visibility).register() + ) = Setting(name, description, BlockCollectionSetting(immutableCollection, defaultValue.toMutableList()), this, visibility).register() @JvmName("collectionSetting2") fun setting( @@ -143,7 +148,7 @@ abstract class Configurable( immutableCollection: Collection = Registries.ITEM.toList(), description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, ItemCollectionSetting(immutableCollection, defaultValue.toMutableList()), visibility).register() + ) = Setting(name, description, ItemCollectionSetting(immutableCollection, defaultValue.toMutableList()), this, visibility).register() @JvmName("collectionSetting3") inline fun > setting( @@ -160,6 +165,7 @@ abstract class Configurable( immutableList, TypeToken.getParameterized(Collection::class.java, T::class.java).type ), + this, visibility ).register() @@ -170,7 +176,7 @@ abstract class Configurable( immutableList: Collection = defaultValue, description: String = "", noinline visibility: () -> Boolean = { true }, - ) = Setting(name, description, ClassCollectionSetting(immutableList, defaultValue.toMutableList()), visibility).register() + ) = Setting(name, description, ClassCollectionSetting(immutableList, defaultValue.toMutableList()), this, visibility).register() // ToDo: Actually implement maps inline fun setting( @@ -185,6 +191,7 @@ abstract class Configurable( defaultValue.toMutableMap(), TypeToken.getParameterized(MutableMap::class.java, K::class.java, V::class.java).type ), + this, visibility ).register() @@ -196,7 +203,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, DoubleSetting(defaultValue, range, step, unit), visibility).register() + ) = Setting(name, description, DoubleSetting(defaultValue, range, step, unit), this, visibility).register() fun setting( name: String, @@ -206,7 +213,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, FloatSetting(defaultValue, range, step, unit), visibility).register() + ) = Setting(name, description, FloatSetting(defaultValue, range, step, unit), this, visibility).register() fun setting( name: String, @@ -216,7 +223,7 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, IntegerSetting(defaultValue, range, step, unit), visibility).register() + ) = Setting(name, description, IntegerSetting(defaultValue, range, step, unit), this, visibility).register() fun setting( name: String, @@ -226,61 +233,61 @@ abstract class Configurable( description: String = "", unit: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, LongSetting(defaultValue, range, step, unit), visibility).register() + ) = Setting(name, description, LongSetting(defaultValue, range, step, unit), this, visibility).register() fun setting( name: String, defaultValue: Bind, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, KeybindSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, KeybindSettingCore(defaultValue), this, visibility).register() fun setting( name: String, defaultValue: KeyCode, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, KeybindSettingCore(defaultValue), visibility).register() + ) = Setting(name, description, KeybindSettingCore(defaultValue), this, visibility).register() fun setting( name: String, defaultValue: Color, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, ColorSetting(defaultValue), visibility).register() + ) = Setting(name, description, ColorSetting(defaultValue), this, visibility).register() fun setting( name: String, defaultValue: Vec3d, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, Vec3DSetting(defaultValue), visibility).register() + ) = Setting(name, description, Vec3DSetting(defaultValue), this, visibility).register() fun setting( name: String, defaultValue: BlockPos.Mutable, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BlockPosSetting(defaultValue), visibility).register() + ) = Setting(name, description, BlockPosSetting(defaultValue), this, visibility).register() fun setting( name: String, defaultValue: BlockPos, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BlockPosSetting(defaultValue), visibility).register() + ) = Setting(name, description, BlockPosSetting(defaultValue), this, visibility).register() fun setting( name: String, defaultValue: Block, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, BlockSetting(defaultValue), visibility).register() + ) = Setting(name, description, BlockSetting(defaultValue), this, visibility).register() fun setting( name: String, defaultValue: () -> Unit, description: String = "", visibility: () -> Boolean = { true } - ) = Setting(name, description, FunctionSetting(defaultValue), visibility).register() + ) = Setting(name, description, FunctionSetting(defaultValue), this, visibility).register() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/Configuration.kt b/src/main/kotlin/com/lambda/config/Configuration.kt index b727518d7..c00385c7f 100644 --- a/src/main/kotlin/com/lambda/config/Configuration.kt +++ b/src/main/kotlin/com/lambda/config/Configuration.kt @@ -72,6 +72,9 @@ abstract class Configuration : Jsonable, Loadable { // Avoid context-leaking warning private fun register() { + if (configurations.any { it.configName == configName }) + throw IllegalStateException("Configuration with name $configName already exists") + fixedRateTimer( daemon = true, name = "Scheduler-config-${configName}", @@ -159,12 +162,8 @@ abstract class Configuration : Jsonable, Loadable { val configurations = mutableSetOf() val configurables: Set get() = configurations.flatMapTo(mutableSetOf()) { it.configurables } - val settings: Set, *>> - get() = configurables.flatMapTo(mutableSetOf()) { it.settings } - - //ToDo: Store owner in setting - fun configurableBySetting(setting: Setting<*, *>) = - configurables.find { it.settings.any { del -> del.name == setting.name } } + val settings: List> + get() = configurables.flatMapTo(mutableListOf()) { it.settings } fun configurableByName(name: String) = configurables.find { it.name == name } @@ -172,10 +171,7 @@ abstract class Configuration : Jsonable, Loadable { fun configurableByCommandName(name: String) = configurables.find { it.commandName == name } - fun settingDelegateByName(configurable: Configurable, name: String) = - configurable.settings.find { it.name == name } - - fun settingDelegateByCommandName(configurable: Configurable, name: String) = + fun settingByCommandName(configurable: Configurable, name: String) = configurable.settings.find { it.commandName == name } } } diff --git a/src/main/kotlin/com/lambda/config/Setting.kt b/src/main/kotlin/com/lambda/config/Setting.kt index ccb2721a8..457b74817 100644 --- a/src/main/kotlin/com/lambda/config/Setting.kt +++ b/src/main/kotlin/com/lambda/config/Setting.kt @@ -112,13 +112,12 @@ abstract class SettingCore( } catch (_: Exception) { return@executeWithResult failure("$valueString is not a valid JSON string.") } - val config = Configuration.configurableBySetting(setting) ?: return@executeWithResult failure("No config found for $name.") val previous = this@SettingCore.value try { loadFromJson(parsed) } catch (_: Exception) { - return@executeWithResult failure("Failed to load $valueString as a ${type::class.simpleName} for $name in ${config.name}.") + return@executeWithResult failure("Failed to load $valueString as a ${type::class.simpleName} for $name in ${setting.configurable.name}.") } ConfigCommand.info(setting.setMessage(previous, this@SettingCore.value)) return@executeWithResult success() @@ -145,7 +144,8 @@ class Setting, R : Any>( override val name: String, override val description: String, var core: T, - var visibility: () -> Boolean, + val configurable: Configurable, + val visibility: () -> Boolean, ) : Nameable, Describable { val originalCore = core val listeners = mutableListOf>() @@ -236,8 +236,7 @@ class Setting, R : Any>( fun setMessage(previousValue: R, newValue: R) = buildText { literal("Set ") changedMessage(previousValue, newValue) - val config = Configuration.configurableBySetting(this@Setting) ?: return@buildText - clickEvent(ClickEvents.suggestCommand("${CommandRegistry.prefix}${ConfigCommand.name} reset ${config.commandName} $commandName")) { + clickEvent(ClickEvents.suggestCommand("${CommandRegistry.prefix}${ConfigCommand.name} reset ${configurable.commandName} $commandName")) { hoverEvent(HoverEvents.showText(buildText { literal("Click to reset to default value ") highlighted(core.defaultValue.toString()) @@ -261,8 +260,7 @@ class Setting, R : Any>( } private fun TextBuilder.changedMessage(previousValue: R, newValue: R) { - val config = Configuration.configurableBySetting(this@Setting) ?: return - highlighted(config.name) + highlighted(configurable.name) literal(" > ") highlighted(name) literal(" from ") @@ -270,7 +268,7 @@ class Setting, R : Any>( literal(" to ") highlighted(newValue.toString()) literal(".") - clickEvent(ClickEvents.suggestCommand("${CommandRegistry.prefix}${ConfigCommand.name} set ${config.commandName} $commandName $previousValue")) { + clickEvent(ClickEvents.suggestCommand("${CommandRegistry.prefix}${ConfigCommand.name} set ${configurable.commandName} $commandName $previousValue")) { hoverEvent(HoverEvents.showText(buildText { literal("Click to undo to previous value ") highlighted(previousValue.toString()) From 2305f9f9e7bef5072233577a25f09b60a2907d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emy=20=F0=9F=92=9C?= Date: Wed, 3 Dec 2025 10:06:00 -0500 Subject: [PATCH 7/9] renamed the vec3d setting class --- .../settings/complex/{Vec3DSetting.kt => Vec3dSetting.kt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/kotlin/com/lambda/config/settings/complex/{Vec3DSetting.kt => Vec3dSetting.kt} (96%) diff --git a/src/main/kotlin/com/lambda/config/settings/complex/Vec3DSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt similarity index 96% rename from src/main/kotlin/com/lambda/config/settings/complex/Vec3DSetting.kt rename to src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt index a63b03b6e..bc7224b4a 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/Vec3DSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt @@ -29,7 +29,7 @@ import com.lambda.util.extension.CommandBuilder import net.minecraft.command.CommandRegistryAccess import net.minecraft.util.math.Vec3d -class Vec3DSetting(defaultValue: Vec3d) : SettingCore( +class Vec3dSetting(defaultValue: Vec3d) : SettingCore( defaultValue, TypeToken.get(Vec3d::class.java).type ) { From 675da83c6aaff263c1823934510cc603fa9c35d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emy=20=F0=9F=92=9C?= Date: Wed, 3 Dec 2025 10:07:03 -0500 Subject: [PATCH 8/9] Update Configurable.kt --- src/main/kotlin/com/lambda/config/Configurable.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index 4662c3d05..ba1cb14f7 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -37,7 +37,7 @@ import com.lambda.config.settings.complex.BlockPosSetting import com.lambda.config.settings.complex.BlockSetting import com.lambda.config.settings.complex.ColorSetting import com.lambda.config.settings.complex.KeybindSettingCore -import com.lambda.config.settings.complex.Vec3DSetting +import com.lambda.config.settings.complex.Vec3dSetting import com.lambda.config.settings.numeric.DoubleSetting import com.lambda.config.settings.numeric.FloatSetting import com.lambda.config.settings.numeric.IntegerSetting @@ -261,7 +261,7 @@ abstract class Configurable( defaultValue: Vec3d, description: String = "", visibility: () -> Boolean = { true }, - ) = Setting(name, description, Vec3DSetting(defaultValue), this, visibility).register() + ) = Setting(name, description, Vec3dSetting(defaultValue), this, visibility).register() fun setting( name: String, From 4fd21ce563c8bc1ca91615db268cc030315d57f1 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Wed, 3 Dec 2025 15:59:18 +0000 Subject: [PATCH 9/9] fix onSelect and onDeselect not recognising child classes of collection settings --- .../lambda/config/settings/collections/CollectionSetting.kt | 4 ++-- src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt index 5c22a5d3d..9242f38b6 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt @@ -118,11 +118,11 @@ open class CollectionSetting( } companion object { - fun Setting, MutableCollection>.onSelect(block: SafeContext.(T) -> Unit) = apply { + fun , R : Any> Setting>.onSelect(block: SafeContext.(R) -> Unit) = apply { core.selectListeners.add(block) } - fun Setting, MutableCollection>.onDeselect(block: SafeContext.(T) -> Unit) = apply { + fun , R : Any> Setting>.onDeselect(block: SafeContext.(R) -> Unit) = apply { core.deselectListeners.add(block) } diff --git a/src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt b/src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt index c6cb41e19..282c6fcd1 100644 --- a/src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt +++ b/src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt @@ -18,7 +18,8 @@ package com.lambda.module.modules.render import com.lambda.Lambda.mc -import com.lambda.config.serializer.BlockCodec +import com.lambda.config.settings.collections.CollectionSetting.Companion.onDeselect +import com.lambda.config.settings.collections.CollectionSetting.Companion.onSelect import com.lambda.context.SafeContext import com.lambda.graphics.renderer.esp.ChunkedESP.Companion.newChunkedESP import com.lambda.graphics.renderer.esp.DirectionMask