From ca4b17ec24bbe962f8bdde1c546ed982bdc509d6 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Thu, 20 Nov 2025 04:42:18 +0000 Subject: [PATCH 01/12] mostly structurally complete, need to add a gui to create and link presets, set presets on modules from config load, add a way to view the configs in modules, then cleanup whatever mess is left behind from incomplete refactors --- .../lambda/command/commands/BuildCommand.kt | 2 +- .../command/commands/TransferCommand.kt | 6 +- .../kotlin/com/lambda/config/Configurable.kt | 5 +- .../kotlin/com/lambda/config/Configuration.kt | 4 +- .../configurations/AutomationConfigs.kt | 27 +++ .../{ModuleConfig.kt => ModuleConfigs.kt} | 8 +- .../com/lambda/config/groups/BreakSettings.kt | 4 +- .../com/lambda/config/groups/BuildSettings.kt | 2 +- .../com/lambda/config/groups/EatSettings.kt | 2 +- .../lambda/config/groups/HotbarSettings.kt | 2 +- .../lambda/config/groups/InteractSettings.kt | 2 +- .../lambda/config/groups/InventorySettings.kt | 2 +- .../{SettingGroup.kt => MutableSettings.kt} | 2 +- .../com/lambda/config/groups/PlaceSettings.kt | 2 +- .../lambda/config/groups/RotationSettings.kt | 2 +- .../com/lambda/config/groups/Targeting.kt | 2 +- .../lambda/config/settings/NumericSetting.kt | 14 +- .../lambda/config/settings/StringSetting.kt | 10 +- .../settings/collections/ListSetting.kt | 6 +- .../config/settings/collections/SetSetting.kt | 6 +- .../com/lambda/context/AutomatedDelegate.kt | 31 ++++ .../com/lambda/context/AutomationConfig.kt | 175 ++++++++++++++++-- src/main/kotlin/com/lambda/gui/MenuBar.kt | 4 - .../com/lambda/interaction/BaritoneManager.kt | 2 +- .../construction/simulation/Sim.kt | 4 +- .../request/breaking/BrokenBlockHandler.kt | 6 +- .../interaction/request/breaking/SwapInfo.kt | 6 +- .../interacting/InteractedBlockHandler.kt | 6 +- .../request/inventory/InventoryManager.kt | 15 +- .../request/placing/PlacedBlockHandler.kt | 6 +- .../rotating/visibilty/VisibilityChecker.kt | 6 +- src/main/kotlin/com/lambda/module/Module.kt | 15 +- .../lambda/module/modules/player/FastBreak.kt | 74 ++++---- .../module/modules/player/PacketMine.kt | 6 +- src/main/kotlin/com/lambda/task/Task.kt | 4 +- .../kotlin/com/lambda/task/tasks/BuildTask.kt | 12 +- 36 files changed, 340 insertions(+), 142 deletions(-) create mode 100644 src/main/kotlin/com/lambda/config/configurations/AutomationConfigs.kt rename src/main/kotlin/com/lambda/config/configurations/{ModuleConfig.kt => ModuleConfigs.kt} (82%) rename src/main/kotlin/com/lambda/config/groups/{SettingGroup.kt => MutableSettings.kt} (99%) create mode 100644 src/main/kotlin/com/lambda/context/AutomatedDelegate.kt diff --git a/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt b/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt index 1591a801d..1da4f889f 100644 --- a/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt +++ b/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt @@ -62,7 +62,7 @@ object BuildCommand : LambdaCommand( .loadStructureByRelativePath(Path.of(pathString)) .let { template -> info("Building structure $pathString with dimensions ${template.size.toShortString()} created by ${template.author}") - lastBuildTask = with(AutomationConfig) { + lastBuildTask = with(AutomationConfig.Companion.DEFAULT) { template.toStructure() .move(player.blockPos) .toBlueprint() diff --git a/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt b/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt index 267c735ee..7ab91dc05 100644 --- a/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt +++ b/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt @@ -53,7 +53,7 @@ object TransferCommand : LambdaCommand( val selection = selectStack(count) { isItem(stack(ctx).value().item) } - with(AutomationConfig) { + with(AutomationConfig.Companion.DEFAULT) { selection.containerWithMaterial().forEachIndexed { i, container -> builder.suggest("\"${i + 1}. ${container.name}\"", container.description(selection)) } @@ -65,7 +65,7 @@ object TransferCommand : LambdaCommand( val selection = selectStack(amount(ctx).value()) { isItem(stack(ctx).value().item) } - with(AutomationConfig) { + with(AutomationConfig.Companion.DEFAULT) { containerWithSpace(selection).forEachIndexed { i, container -> builder.suggest("\"${i + 1}. ${container.name}\"", container.description(selection)) } @@ -84,7 +84,7 @@ object TransferCommand : LambdaCommand( it.name == to().value().split(".").last().trim() } ?: return@executeWithResult failure("To container not found") - with(AutomationConfig) { + with(AutomationConfig.Companion.DEFAULT) { when (val transaction = fromContainer.transfer(selection, toContainer)) { is TransferResult.ContainerTransfer -> { info("${transaction.name} started.") diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index 53b55e7ea..3a1ee030f 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -20,7 +20,6 @@ package com.lambda.config import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.reflect.TypeToken -import com.lambda.Lambda import com.lambda.Lambda.LOG import com.lambda.config.settings.CharSetting import com.lambda.config.settings.FunctionSetting @@ -69,7 +68,9 @@ abstract class Configurable( private fun registerConfigurable() = configuration.configurables.add(this) inline fun > T.register(): T { - check(settings.add(this)) { "Setting with name $name already exists for configurable: ${this@Configurable.name}" } + if (settings.any { it.name == name }) + throw IllegalStateException("Setting with name $name already exists for configurable: ${this@Configurable.name}") + settings.add(this) return this } diff --git a/src/main/kotlin/com/lambda/config/Configuration.kt b/src/main/kotlin/com/lambda/config/Configuration.kt index 2c68b2470..a4d4aef09 100644 --- a/src/main/kotlin/com/lambda/config/Configuration.kt +++ b/src/main/kotlin/com/lambda/config/Configuration.kt @@ -25,7 +25,7 @@ import com.google.gson.JsonSyntaxException import com.lambda.Lambda.LOG import com.lambda.Lambda.gson import com.lambda.config.Configuration.Companion.configurables -import com.lambda.config.configurations.ModuleConfig +import com.lambda.config.configurations.ModuleConfigs import com.lambda.event.events.ClientEvent import com.lambda.event.listener.UnsafeListener.Companion.listenUnsafe import com.lambda.threading.runIO @@ -48,7 +48,7 @@ import kotlin.time.Duration.Companion.minutes * Each configuration will be loaded concurrently, * while the underlying configurables are populated with the settings in sequence. * - * See also [ModuleConfig]. + * See also [ModuleConfigs]. * * @property configName The name of the configuration. * @property primary The primary file where the configuration is saved. diff --git a/src/main/kotlin/com/lambda/config/configurations/AutomationConfigs.kt b/src/main/kotlin/com/lambda/config/configurations/AutomationConfigs.kt new file mode 100644 index 000000000..311ec0b96 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/configurations/AutomationConfigs.kt @@ -0,0 +1,27 @@ +/* + * 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.configurations + +import com.lambda.config.Configuration +import com.lambda.util.FolderRegister +import java.io.File + +object AutomationConfigs : Configuration() { + override val configName = "automation" + override val primary: File = FolderRegister.config.resolve("${configName}.json").toFile() +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/configurations/ModuleConfig.kt b/src/main/kotlin/com/lambda/config/configurations/ModuleConfigs.kt similarity index 82% rename from src/main/kotlin/com/lambda/config/configurations/ModuleConfig.kt rename to src/main/kotlin/com/lambda/config/configurations/ModuleConfigs.kt index 0d78023ca..43516f554 100644 --- a/src/main/kotlin/com/lambda/config/configurations/ModuleConfig.kt +++ b/src/main/kotlin/com/lambda/config/configurations/ModuleConfigs.kt @@ -18,21 +18,21 @@ package com.lambda.config.configurations import com.lambda.config.Configuration -import com.lambda.config.configurations.ModuleConfig.configName -import com.lambda.config.configurations.ModuleConfig.primary +import com.lambda.config.configurations.ModuleConfigs.configName +import com.lambda.config.configurations.ModuleConfigs.primary import com.lambda.util.FolderRegister import java.io.File /** - * The [ModuleConfig] object represents the configuration file for the [Module]s. + * The [ModuleConfigs] object represents the configuration file for the [Module]s. * * This object is used to save and load the settings of all [Module]s in the system. * * @property configName The name of the configuration. * @property primary The primary file where the configuration is saved. */ -object ModuleConfig : Configuration() { +object ModuleConfigs : Configuration() { override val configName get() = "modules" override val primary: File = FolderRegister.config.resolve("$configName.json").toFile() } diff --git a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt index 548f7f35f..911073393 100644 --- a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt @@ -28,11 +28,11 @@ import com.lambda.util.BlockUtils.allSigns import com.lambda.util.NamedEnum import java.awt.Color -class BreakSettings( +open class BreakSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true }, -) : BreakConfig, SettingGroup(c) { +) : BreakConfig, MutableSettings(c) { enum class Group(override val displayName: String) : NamedEnum { General("General"), Cosmetic("Cosmetic") diff --git a/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt b/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt index b8f4397aa..9556b0e43 100644 --- a/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt @@ -26,7 +26,7 @@ class BuildSettings( c: Configurable, vararg baseGroup: NamedEnum, vis: () -> Boolean = { true }, -) : BuildConfig, SettingGroup(c) { +) : BuildConfig, MutableSettings(c) { enum class Group(override val displayName: String) : NamedEnum { General("General"), Reach("Reach"), diff --git a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt index f5cec297d..50cdd9e18 100644 --- a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt @@ -25,7 +25,7 @@ class EatSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : EatConfig, SettingGroup(c) { +) : EatConfig, MutableSettings(c) { val nutritiousFoodDefaults = listOf(Items.APPLE, Items.BAKED_POTATO, Items.BEEF, Items.BEETROOT, Items.BEETROOT_SOUP, Items.BREAD, Items.CARROT, Items.CHICKEN, Items.CHORUS_FRUIT, Items.COD, Items.COOKED_BEEF, Items.COOKED_CHICKEN, Items.COOKED_COD, Items.COOKED_MUTTON, Items.COOKED_PORKCHOP, Items.COOKED_RABBIT, Items.COOKED_SALMON, Items.COOKIE, Items.DRIED_KELP, Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE, Items.GOLDEN_CARROT, Items.HONEY_BOTTLE, Items.MELON_SLICE, Items.MUSHROOM_STEW, Items.MUTTON, Items.POISONOUS_POTATO, Items.PORKCHOP, Items.POTATO, Items.PUFFERFISH, Items.PUMPKIN_PIE, Items.RABBIT, Items.RABBIT_STEW, Items.ROTTEN_FLESH, Items.SALMON, Items.SPIDER_EYE, Items.SUSPICIOUS_STEW, Items.SWEET_BERRIES, Items.GLOW_BERRIES, Items.TROPICAL_FISH) val resistanceFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE) val regenerationFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE) diff --git a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt index 11c9bd66c..21efc3347 100644 --- a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt @@ -26,7 +26,7 @@ class HotbarSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : HotbarConfig, SettingGroup(c) { +) : HotbarConfig, MutableSettings(c) { override val keepTicks by c.setting("Keep Ticks", 1, 0..20, 1, "The number of ticks to keep the current hotbar selection active", " ticks", visibility = vis).group(baseGroup) override val swapDelay by c.setting("Swap Delay", 0, 0..3, 1, "The number of ticks delay before allowing another hotbar selection swap", " ticks", visibility = vis).group(baseGroup) override val swapsPerTick by c.setting("Swaps Per Tick", 3, 1..10, 1, "The number of hotbar selection swaps that can take place each tick") { swapDelay <= 0 && vis() }.group(baseGroup) diff --git a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt index aaad972e9..ddbb41513 100644 --- a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt @@ -26,7 +26,7 @@ class InteractSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : InteractConfig, SettingGroup(c) { +) : InteractConfig, MutableSettings(c) { override val rotate by c.setting("Rotate For Interact", true, "Rotates the player to look at the block when interacting", visibility = vis).group(baseGroup) override val sorter by c.setting("Interact Sorter", ActionConfig.SortMode.Tool, "The order in which interactions are performed", visibility = vis).group(baseGroup) override val swingHand by c.setting("Swing On Interact", true, "Swings the players hand after interacting", visibility = vis).group(baseGroup) diff --git a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt index 4e105532f..689211456 100644 --- a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt @@ -27,7 +27,7 @@ class InventorySettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : InventoryConfig, SettingGroup(c) { +) : InventoryConfig, MutableSettings(c) { enum class Group(override val displayName: String) : NamedEnum { General("General"), Container("Container"), diff --git a/src/main/kotlin/com/lambda/config/groups/SettingGroup.kt b/src/main/kotlin/com/lambda/config/groups/MutableSettings.kt similarity index 99% rename from src/main/kotlin/com/lambda/config/groups/SettingGroup.kt rename to src/main/kotlin/com/lambda/config/groups/MutableSettings.kt index 71eb1469a..12fb93ede 100644 --- a/src/main/kotlin/com/lambda/config/groups/SettingGroup.kt +++ b/src/main/kotlin/com/lambda/config/groups/MutableSettings.kt @@ -31,7 +31,7 @@ private val KProperty0<*>.delegate } @Suppress("unchecked_cast") -abstract class SettingGroup(val c: Configurable) { +abstract class MutableSettings(val c: Configurable) { @DslMarker annotation class SettingEditorDsl diff --git a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt index 13e1f6468..ff410115d 100644 --- a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt @@ -28,7 +28,7 @@ class PlaceSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : PlaceConfig, SettingGroup(c) { +) : PlaceConfig, MutableSettings(c) { override val rotateForPlace by c.setting("Rotate For Place", true, "Rotate towards block while placing", visibility = vis).group(baseGroup) override val airPlace by c.setting("Air Place", AirPlaceMode.None, "Allows for placing blocks without adjacent faces", visibility = vis).group(baseGroup) override val axisRotateSetting by c.setting("Axis Rotate", true, "Overrides the Rotate For Place setting and rotates the player on each axis to air place rotational blocks") { vis() && airPlace.isEnabled }.group(baseGroup) diff --git a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt index d84e1dd6c..de06e622b 100644 --- a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt @@ -32,7 +32,7 @@ class RotationSettings( c: Configurable, baseGroup: NamedEnum? = null, vis: () -> Boolean = { true } -) : RotationConfig, SettingGroup(c) { +) : RotationConfig, MutableSettings(c) { override var rotationMode by c.setting("Mode", RotationMode.Sync, "How the player is being rotated on interaction", vis).group(baseGroup) /** How many ticks to keep the rotation before resetting */ diff --git a/src/main/kotlin/com/lambda/config/groups/Targeting.kt b/src/main/kotlin/com/lambda/config/groups/Targeting.kt index 5590d23b9..f6e08177c 100644 --- a/src/main/kotlin/com/lambda/config/groups/Targeting.kt +++ b/src/main/kotlin/com/lambda/config/groups/Targeting.kt @@ -54,7 +54,7 @@ abstract class Targeting( private val predicate: () -> Boolean = { true }, private val defaultRange: Double, private val maxRange: Double, -) : TargetingConfig, SettingGroup(owner) { +) : TargetingConfig, MutableSettings(owner) { /** * The range within which entities can be targeted. This value is configurable and constrained diff --git a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt index 31a9f53b1..dd8ca0c7f 100644 --- a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt @@ -19,7 +19,7 @@ package com.lambda.config.settings import com.google.gson.reflect.TypeToken import com.lambda.config.AbstractSetting -import com.lambda.config.groups.SettingGroup +import com.lambda.config.groups.MutableSettings import com.lambda.gui.dsl.ImGuiBuilder import imgui.ImGui import imgui.ImGui.calcTextSize @@ -97,21 +97,21 @@ abstract class NumericSetting( } companion object { - @SettingGroup.SettingEditorDsl + @MutableSettings.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.TypedEditBuilder.range(range: ClosedRange) where T : Number, T : Comparable { + fun MutableSettings.TypedEditBuilder.range(range: ClosedRange) where T : Number, T : Comparable { (settings as Collection>).forEach { it.range = range } } - @SettingGroup.SettingEditorDsl + @MutableSettings.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.TypedEditBuilder.step(step: T) where T : Number, T : Comparable { + fun MutableSettings.TypedEditBuilder.step(step: T) where T : Number, T : Comparable { (settings as Collection>).forEach { it.step = step } } - @SettingGroup.SettingEditorDsl + @MutableSettings.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.TypedEditBuilder.unit(unit: String) where T : Number, T : Comparable { + fun MutableSettings.TypedEditBuilder.unit(unit: String) where T : Number, T : Comparable { (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/StringSetting.kt index 602f3f2d9..5ae35dc24 100644 --- a/src/main/kotlin/com/lambda/config/settings/StringSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/StringSetting.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.AbstractSetting -import com.lambda.config.groups.SettingGroup +import com.lambda.config.groups.MutableSettings import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import imgui.flag.ImGuiInputTextFlags @@ -64,15 +64,15 @@ class StringSetting( } companion object { - @SettingGroup.SettingEditorDsl + @MutableSettings.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.TypedEditBuilder.multiline(multiline: Boolean) { + fun MutableSettings.TypedEditBuilder.multiline(multiline: Boolean) { (settings as Collection).forEach { it.multiline = multiline } } - @SettingGroup.SettingEditorDsl + @MutableSettings.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.TypedEditBuilder.flags(flags: Int) { + fun MutableSettings.TypedEditBuilder.flags(flags: Int) { (settings as Collection).forEach { it.flags = flags } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt index 69665a380..26f3ed559 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt @@ -21,7 +21,7 @@ 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.groups.SettingGroup +import com.lambda.config.groups.MutableSettings import com.lambda.gui.dsl.ImGuiBuilder import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -75,9 +75,9 @@ class ListSetting( } companion object { - @SettingGroup.SettingEditorDsl + @MutableSettings.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.TypedEditBuilder>.immutableList(immutableList: List) { + fun MutableSettings.TypedEditBuilder>.immutableList(immutableList: List) { (settings as Collection>).forEach { it.immutableList = immutableList } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt index afb5c0ad6..acd0e661d 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt @@ -21,7 +21,7 @@ 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.groups.SettingGroup +import com.lambda.config.groups.MutableSettings import com.lambda.gui.dsl.ImGuiBuilder import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -76,9 +76,9 @@ class SetSetting( } companion object { - @SettingGroup.SettingEditorDsl + @MutableSettings.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.TypedEditBuilder>.immutableSet(immutableSet: Set) { + fun MutableSettings.TypedEditBuilder>.immutableSet(immutableSet: Set) { (settings as Collection>).forEach { it.immutableSet = immutableSet } } } diff --git a/src/main/kotlin/com/lambda/context/AutomatedDelegate.kt b/src/main/kotlin/com/lambda/context/AutomatedDelegate.kt new file mode 100644 index 000000000..5b9c9d594 --- /dev/null +++ b/src/main/kotlin/com/lambda/context/AutomatedDelegate.kt @@ -0,0 +1,31 @@ +/* + * 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.context + +interface AutomatedDelegate : Automated { + var automated: Automated + + override val buildConfig get() = automated.buildConfig + override val breakConfig get() = automated.breakConfig + override val placeConfig get() = automated.placeConfig + override val interactConfig get() = automated.interactConfig + override val rotationConfig get() = automated.rotationConfig + override val inventoryConfig get() = automated.inventoryConfig + override val hotbarConfig get() = automated.hotbarConfig + override val eatConfig get() = automated.eatConfig +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/context/AutomationConfig.kt b/src/main/kotlin/com/lambda/context/AutomationConfig.kt index aebb64f1f..bcd5eef68 100644 --- a/src/main/kotlin/com/lambda/context/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/context/AutomationConfig.kt @@ -17,8 +17,9 @@ package com.lambda.context +import com.lambda.config.AbstractSetting import com.lambda.config.Configurable -import com.lambda.config.configurations.LambdaConfig +import com.lambda.config.configurations.AutomationConfigs import com.lambda.config.groups.BreakSettings import com.lambda.config.groups.BuildSettings import com.lambda.config.groups.EatSettings @@ -29,11 +30,15 @@ import com.lambda.config.groups.PlaceSettings import com.lambda.config.groups.RotationSettings import com.lambda.event.events.onStaticRender import com.lambda.interaction.construction.result.Drawable +import com.lambda.module.Module import com.lambda.util.NamedEnum +import kotlin.reflect.KProperty0 +import kotlin.reflect.jvm.isAccessible -object AutomationConfig : Configurable(LambdaConfig), Automated { - override val name = "automation" - +@Suppress("unchecked_cast", "unused") +open class AutomationConfig( + override val name: String +) : Configurable(AutomationConfigs), Automated { enum class Group(override val displayName: String) : NamedEnum { Build("Build"), Break("Break"), @@ -48,8 +53,6 @@ object AutomationConfig : Configurable(LambdaConfig), Automated { Debug("Debug") } - val renders by setting("Render", false).group(Group.Render) - override val buildConfig = BuildSettings(this, Group.Build) override val breakConfig = BreakSettings(this, Group.Break) override val placeConfig = PlaceSettings(this, Group.Place) @@ -59,20 +62,156 @@ object AutomationConfig : Configurable(LambdaConfig), Automated { override val hotbarConfig = HotbarSettings(this, Group.Hotbar) override val eatConfig = EatSettings(this, Group.Eat) - val avoidDesync by setting("Avoid Desync", true, "Cancels incoming inventory update packets if they match previous actions").group(Group.Debug) - val desyncTimeout by setting("Desync Timeout", 30, 1..30, 1, unit = " ticks", description = "Time to store previous inventory actions before dropping the cache") { avoidDesync }.group(Group.Debug) - val showAllEntries by setting("Show All Entries", false, "Show all entries in the task tree").group(Group.Debug) - val shrinkFactor by setting("Shrink Factor", 0.001, 0.0..1.0, 0.001).group(Group.Debug) - val ignoreItemDropWarnings by setting("Ignore Drop Warnings", false, "Hides the item drop warnings from the break manager").group(Group.Debug) - val maxSimDependencies by setting("Max Sim Dependencies", 3, 0..10, 1, "Maximum dependency build results").group(Group.Debug) + companion object { + context(module: Module) + fun automationConfig(name: String = module.name, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = + AutomationConfig(name).apply { edits?.invoke(this) } + + fun automationConfig(name: String, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = + AutomationConfig(name).apply { edits?.invoke(this) } - @Volatile - var drawables = listOf() + object DEFAULT : AutomationConfig("Default") { + val renders by setting("Render", false).group(Group.Render) + val avoidDesync by setting("Avoid Desync", true, "Cancels incoming inventory update packets if they match previous actions").group(Group.Debug) + val desyncTimeout by setting("Desync Timeout", 30, 1..30, 1, unit = " ticks", description = "Time to store previous inventory actions before dropping the cache") { avoidDesync }.group(Group.Debug) + val showAllEntries by setting("Show All Entries", false, "Show all entries in the task tree").group(Group.Debug) + val shrinkFactor by setting("Shrink Factor", 0.001, 0.0..1.0, 0.001).group(Group.Debug) + val ignoreItemDropWarnings by setting("Ignore Drop Warnings", false, "Hides the item drop warnings from the break manager").group(Group.Debug) + val maxSimDependencies by setting("Max Sim Dependencies", 3, 0..10, 1, "Maximum dependency build results").group(Group.Debug) - init { - onStaticRender { - if (renders) - with(it) { drawables.forEach { with(it) { buildRenderer() } } } + @Volatile + var drawables = listOf() + + init { + onStaticRender { + if (renders) + with(it) { drawables.forEach { with(it) { buildRenderer() } } } + } + } } } + + @DslMarker + annotation class SettingEditorDsl + + private val KProperty0<*>.delegate + get() = try { + apply { isAccessible = true }.getDelegate() + } catch (e: Exception) { + throw IllegalStateException("Could not access delegate for property $name", e) + } + + @SettingEditorDsl + internal inline fun KProperty0.edit(edits: FullEditBuilder.(AbstractSetting) -> Unit) { + val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") + FullEditBuilder(setting, this@AutomationConfig).edits(setting) + } + + @SettingEditorDsl + internal inline fun KProperty0.editWith( + other: KProperty0<*>, + edits: FullEditBuilder.(AbstractSetting<*>) -> Unit + ) { + val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") + FullEditBuilder(setting, this@AutomationConfig).edits(other.delegate as AbstractSetting<*>) + } + + @SettingEditorDsl + fun edit( + vararg settings: KProperty0<*>, + edits: BasicEditBuilder.() -> Unit + ) { BasicEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List>).apply(edits) } + + @SettingEditorDsl + fun editWith( + vararg settings: KProperty0<*>, + other: KProperty0<*>, + edits: BasicEditBuilder.(AbstractSetting<*>) -> Unit + ) { BasicEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List>).edits(other.delegate as AbstractSetting<*>) } + + @SettingEditorDsl + internal inline fun editTyped( + vararg settings: KProperty0, + edits: TypedEditBuilder.() -> Unit + ) { TypedEditBuilder(settings.map { it.delegate } as List>, this@AutomationConfig).apply(edits) } + + @SettingEditorDsl + internal inline fun editTypedWith( + vararg settings: KProperty0, + other: KProperty0, + edits: TypedEditBuilder.(AbstractSetting) -> Unit + ) = TypedEditBuilder(settings.map { it.delegate } as List>, this@AutomationConfig).edits(other.delegate as AbstractSetting) + + @SettingEditorDsl + fun hide(vararg settings: KProperty0<*>) = + this@AutomationConfig.settings.removeAll(settings.map { it.delegate } as List>) + + @SettingEditorDsl + fun KProperty0<*>.insert(insert: KProperty0<*>, insertMode: InsertMode) { + val delegate = insert.delegate as AbstractSetting<*> + this@AutomationConfig.settings.remove(delegate) + val index = this@AutomationConfig.settings.indexOf(this.delegate as AbstractSetting<*>) + this@AutomationConfig.settings.add(if (insertMode == InsertMode.Below) index + 1 else index, delegate) + } + + @SettingEditorDsl + fun KProperty0<*>.insert(vararg inserts: KProperty0<*>, insertMode: InsertMode) { + inserts.forEach { this@AutomationConfig.settings.remove(it.delegate as AbstractSetting<*>) } + val index = this@AutomationConfig.settings.indexOf(delegate as AbstractSetting<*>) + this@AutomationConfig.settings.addAll( + if (insertMode == InsertMode.Below) index + 1 else index, + inserts.map { it.delegate } as List> + ) + } + + open class BasicEditBuilder(val c: Configurable, open val settings: Collection>) { + @SettingEditorDsl + fun visibility(vis: () -> Boolean) = + settings.forEach { it.visibility = vis } + + @SettingEditorDsl + fun hide() { + c.settings.removeAll(settings) + } + + @SettingEditorDsl + fun groups(vararg groups: NamedEnum) = + settings.forEach { it.groups = mutableListOf(groups.toList()) } + + @SettingEditorDsl + fun groups(groups: MutableList>) = + settings.forEach { it.groups = groups } + } + + open class TypedEditBuilder( + override val settings: Collection>, + c: Configurable + ) : BasicEditBuilder(c, settings) { + @SettingEditorDsl + fun defaultValue(value: T) = + settings.forEach { + it.defaultValue = value + it.value = value + } + } + + class FullEditBuilder( + private val setting: AbstractSetting, + c: Configurable + ) : TypedEditBuilder(setOf(setting), c) { + @SettingEditorDsl + fun name(name: String) { + setting.name = name + } + + @SettingEditorDsl + fun description(description: String) { + setting.description = description + } + } + + enum class InsertMode { + Above, + Below + } } \ 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 d4b5bcba8..d4b86e217 100644 --- a/src/main/kotlin/com/lambda/gui/MenuBar.kt +++ b/src/main/kotlin/com/lambda/gui/MenuBar.kt @@ -22,7 +22,6 @@ import com.lambda.Lambda.REPO_URL import com.lambda.Lambda.mc import com.lambda.command.CommandRegistry import com.lambda.config.Configuration -import com.lambda.context.AutomationConfig import com.lambda.core.Loader import com.lambda.event.EventFlow import com.lambda.graphics.texture.TextureOwner.upload @@ -145,9 +144,6 @@ object MenuBar { menu("Baritone Settings") { buildConfigSettingsContext(BaritoneManager) } - menu("Automation Settings") { - buildConfigSettingsContext(AutomationConfig) - } } separator() menu("Open Folder") { diff --git a/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt b/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt index 917453404..b9e352a1e 100644 --- a/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt +++ b/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt @@ -29,7 +29,7 @@ import com.lambda.context.AutomationConfig import com.lambda.util.BlockUtils.blockPos import com.lambda.util.NamedEnum -object BaritoneManager : Configurable(LambdaConfig), Automated by AutomationConfig { +object BaritoneManager : Configurable(LambdaConfig), Automated by AutomationConfig.Companion.DEFAULT { override val name = "baritone" private val baritone = BaritoneAPI.getProvider() diff --git a/src/main/kotlin/com/lambda/interaction/construction/simulation/Sim.kt b/src/main/kotlin/com/lambda/interaction/construction/simulation/Sim.kt index 8436871b0..e41d62ad4 100644 --- a/src/main/kotlin/com/lambda/interaction/construction/simulation/Sim.kt +++ b/src/main/kotlin/com/lambda/interaction/construction/simulation/Sim.kt @@ -17,7 +17,7 @@ package com.lambda.interaction.construction.simulation -import com.lambda.context.AutomationConfig.maxSimDependencies +import com.lambda.context.AutomationConfig import com.lambda.interaction.construction.processing.PreProcessingInfo import com.lambda.interaction.construction.result.BuildResult import com.lambda.interaction.construction.result.results.GenericResult @@ -77,7 +77,7 @@ abstract class Sim : Results { */ protected suspend fun ISimInfo.withDependent(dependent: Sim<*>, block: suspend () -> Unit) { // +1 because the build sim counts as a dependent - if (dependencyStack.size >= maxSimDependencies + 1) return + if (dependencyStack.size >= AutomationConfig.Companion.DEFAULT.maxSimDependencies + 1) return dependencyStack.push(dependent) block() dependencyStack.pop() diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/BrokenBlockHandler.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/BrokenBlockHandler.kt index 65b14b745..1213e8c04 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/BrokenBlockHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/BrokenBlockHandler.kt @@ -17,7 +17,7 @@ package com.lambda.interaction.request.breaking -import com.lambda.context.AutomationConfig +import com.lambda.context.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.event.events.EntityEvent import com.lambda.event.events.WorldEvent @@ -49,7 +49,7 @@ import net.minecraft.util.math.ChunkSectionPos */ object BrokenBlockHandler : PostActionHandler() { override val pendingActions = LimitedDecayQueue( - AutomationConfig.buildConfig.maxPendingInteractions, AutomationConfig.buildConfig.interactionTimeout * 50L + DEFAULT.buildConfig.maxPendingInteractions, DEFAULT.buildConfig.interactionTimeout * 50L ) { info -> runSafe { val pos = info.context.blockPos @@ -61,7 +61,7 @@ object BrokenBlockHandler : PostActionHandler() { val message = "${info.type} ${info::class.simpleName} at ${info.context.blockPos.toShortString()} timed out with cached state ${info.context.cachedState}" BreakManager.logger.error(message) warn(message) - } else if (!AutomationConfig.ignoreItemDropWarnings) { + } else if (!DEFAULT.ignoreItemDropWarnings) { val message = "${info.type} ${info::class.simpleName}'s item drop at ${info.context.blockPos.toShortString()} timed out" BreakManager.logger.warn(message) warn(message) diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt index 52b3df455..f77f72a8e 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt @@ -18,7 +18,7 @@ package com.lambda.interaction.request.breaking import com.lambda.context.Automated -import com.lambda.context.AutomationConfig +import com.lambda.context.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.interaction.request.LogContext import com.lambda.interaction.request.LogContext.Companion.LogContextBuilder @@ -32,7 +32,7 @@ import com.lambda.threading.runSafeAutomated */ data class SwapInfo( private val type: BreakInfo.BreakType, - private val automated: Automated, + private val automated: Automated = DEFAULT, val swap: Boolean = false, val longSwap: Boolean = false ) : LogContext, Automated by automated { @@ -44,7 +44,7 @@ data class SwapInfo( } companion object { - val EMPTY = SwapInfo(Primary, AutomationConfig) + val EMPTY = SwapInfo(Primary) /** * Calculates the contents and returns a [SwapInfo]. diff --git a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractedBlockHandler.kt b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractedBlockHandler.kt index da93007a0..fecf0f0a4 100644 --- a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractedBlockHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractedBlockHandler.kt @@ -18,7 +18,7 @@ package com.lambda.interaction.request.interacting import com.lambda.Lambda.mc -import com.lambda.context.AutomationConfig +import com.lambda.context.AutomationConfig.Companion.DEFAULT import com.lambda.event.events.WorldEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.construction.processing.ProcessorRegistry @@ -35,8 +35,8 @@ import com.lambda.util.collections.LimitedDecayQueue */ object InteractedBlockHandler : PostActionHandler() { override val pendingActions = LimitedDecayQueue( - AutomationConfig.buildConfig.maxPendingInteractions, - AutomationConfig.buildConfig.interactionTimeout * 50L + DEFAULT.buildConfig.maxPendingInteractions, + DEFAULT.buildConfig.interactionTimeout * 50L ) { info("${it::class.simpleName} at ${it.context.blockPos.toShortString()} timed out") if (it.interactConfig.interactConfirmationMode != InteractConfig.InteractConfirmationMode.AwaitThenInteract) { diff --git a/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt b/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt index a9069ecb4..0397d9bbf 100644 --- a/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt @@ -18,8 +18,7 @@ package com.lambda.interaction.request.inventory import com.lambda.context.AutomatedSafeContext -import com.lambda.context.AutomationConfig -import com.lambda.context.AutomationConfig.avoidDesync +import com.lambda.context.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.event.EventFlow.post import com.lambda.event.events.TickEvent @@ -62,7 +61,7 @@ object InventoryManager : RequestHandler( private var slots = listOf() private var alteredSlots = LimitedDecayQueue>>( - Int.MAX_VALUE, AutomationConfig.desyncTimeout * 50L + Int.MAX_VALUE, DEFAULT.desyncTimeout * 50L ) private var screenHandler: ScreenHandler? = null @@ -83,7 +82,7 @@ object InventoryManager : RequestHandler( super.load() listen(priority = Int.MIN_VALUE) { - if (avoidDesync) indexInventoryChanges() + if (DEFAULT.avoidDesync) indexInventoryChanges() if (++secondCounter >= 20) { secondCounter = 0 actionsThisSecond = 0 @@ -125,7 +124,7 @@ object InventoryManager : RequestHandler( activeRequest = request actions = request.actions.toMutableList() maxActionsThisSecond = request.inventoryConfig.actionsPerSecond - alteredSlots.setDecayTime(AutomationConfig.desyncTimeout * 50L) + alteredSlots.setDecayTime(DEFAULT.desyncTimeout * 50L) } /** @@ -144,7 +143,7 @@ object InventoryManager : RequestHandler( if (action is InventoryAction.Inventory && actionsThisSecond + 1 > maxActionsThisSecond && !active.mustPerform) break action.action(this) - if (avoidDesync) indexInventoryChanges() + if (DEFAULT.avoidDesync) indexInventoryChanges() actionsThisTick++ actionsThisSecond++ iterator.remove() @@ -186,7 +185,7 @@ object InventoryManager : RequestHandler( @JvmStatic fun onInventoryUpdate(packet: InventoryS2CPacket, original: Operation){ runSafe { - if (!mc.isOnThread || !avoidDesync) { + if (!mc.isOnThread || !DEFAULT.avoidDesync) { original.call(packet) return } @@ -220,7 +219,7 @@ object InventoryManager : RequestHandler( fun onSlotUpdate(packet: ScreenHandlerSlotUpdateS2CPacket, original: Operation) { runSafe { screenHandler = player.currentScreenHandler - if (!mc.isOnThread || !avoidDesync) { + if (!mc.isOnThread || !DEFAULT.avoidDesync) { original.call(packet) return } diff --git a/src/main/kotlin/com/lambda/interaction/request/placing/PlacedBlockHandler.kt b/src/main/kotlin/com/lambda/interaction/request/placing/PlacedBlockHandler.kt index 8e3a7ca1d..60628d051 100644 --- a/src/main/kotlin/com/lambda/interaction/request/placing/PlacedBlockHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/placing/PlacedBlockHandler.kt @@ -17,7 +17,7 @@ package com.lambda.interaction.request.placing -import com.lambda.context.AutomationConfig +import com.lambda.context.AutomationConfig.Companion.DEFAULT import com.lambda.event.events.WorldEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.construction.processing.ProcessorRegistry @@ -31,8 +31,8 @@ import com.lambda.util.collections.LimitedDecayQueue object PlacedBlockHandler : PostActionHandler() { override val pendingActions = LimitedDecayQueue( - AutomationConfig.buildConfig.maxPendingInteractions, - AutomationConfig.buildConfig.interactionTimeout * 50L + DEFAULT.buildConfig.maxPendingInteractions, + DEFAULT.buildConfig.interactionTimeout * 50L ) { info("${it::class.simpleName} at ${it.context.blockPos.toShortString()} timed out") if (it.placeConfig.placeConfirmationMode != PlaceConfig.PlaceConfirmationMode.AwaitThenPlace) { diff --git a/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/VisibilityChecker.kt b/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/VisibilityChecker.kt index 000af3d3f..03a8c093b 100644 --- a/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/VisibilityChecker.kt +++ b/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/VisibilityChecker.kt @@ -18,7 +18,7 @@ package com.lambda.interaction.request.rotating.visibilty import com.lambda.context.AutomatedSafeContext -import com.lambda.context.AutomationConfig +import com.lambda.context.AutomationConfig.Companion.DEFAULT import com.lambda.interaction.construction.verify.ScanMode import com.lambda.interaction.construction.verify.SurfaceScan import com.lambda.interaction.request.rotating.Rotation @@ -169,8 +169,8 @@ object VisibilityChecker { ) { sides.forEach { side -> val (minX, minY, minZ, maxX, maxY, maxZ) = box - .contract(AutomationConfig.shrinkFactor) - .offset(side.doubleVector.multiply(AutomationConfig.shrinkFactor)) + .contract(DEFAULT.shrinkFactor) + .offset(side.doubleVector.multiply(DEFAULT.shrinkFactor)) .bounds(side) // Determine the bounds to scan based on the axis and mode. Skip if no part of the face is in the desired bounds diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index ffc5b0bb2..a6f0dd5ba 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -22,10 +22,11 @@ import com.lambda.command.LambdaCommand import com.lambda.config.AbstractSetting import com.lambda.config.Configurable import com.lambda.config.Configuration -import com.lambda.config.configurations.ModuleConfig +import com.lambda.config.configurations.ModuleConfigs +import com.lambda.config.settings.complex.Bind import com.lambda.context.Automated +import com.lambda.context.AutomatedDelegate import com.lambda.context.AutomationConfig -import com.lambda.config.settings.complex.Bind import com.lambda.context.SafeContext import com.lambda.event.Muteable import com.lambda.event.events.ClientEvent @@ -67,7 +68,7 @@ import com.lambda.util.Nameable * ``` * * These settings are persisted in the `lambda/config/modules.json` config file. - * See [ModuleConfig.primary] and [Configuration] for more details. + * See [ModuleConfigs.primary] and [Configuration] for more details. * * In the `init` block, you can add hooks like [onEnable], [onDisable], [onToggle] and add listeners. * @@ -120,7 +121,13 @@ abstract class Module( enabledByDefault: Boolean = false, defaultKeybind: Bind = Bind.EMPTY, autoDisable: Boolean = false -) : Nameable, Muteable, Configurable(ModuleConfig), Automated by AutomationConfig { +) : Nameable, Muteable, Configurable(ModuleConfigs), AutomatedDelegate { + protected var defaultConfig: Automated = AutomationConfig.Companion.DEFAULT + set(value) { + field = value + automated = value + } + override var automated = defaultConfig 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/FastBreak.kt b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt index 4470717e5..13ceacf5d 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt @@ -17,9 +17,7 @@ package com.lambda.module.modules.player -import com.lambda.config.groups.BreakSettings -import com.lambda.config.groups.HotbarSettings -import com.lambda.config.groups.InventorySettings +import com.lambda.context.AutomationConfig.Companion.automationConfig import com.lambda.event.events.PlayerEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.construction.context.BreakContext @@ -28,7 +26,9 @@ import com.lambda.interaction.material.ContainerSelection.Companion.selectContai import com.lambda.interaction.material.StackSelection.Companion.selectStack import com.lambda.interaction.material.container.ContainerManager.containerWithMaterial import com.lambda.interaction.material.container.MaterialContainer +import com.lambda.interaction.request.breaking.BreakConfig import com.lambda.interaction.request.breaking.BreakRequest.Companion.breakRequest +import com.lambda.interaction.request.inventory.InventoryConfig import com.lambda.interaction.request.rotating.Rotation.Companion.rotation import com.lambda.interaction.request.rotating.RotationRequest import com.lambda.interaction.request.rotating.visibilty.lookAt @@ -37,7 +37,6 @@ import com.lambda.module.tag.ModuleTag import com.lambda.util.BlockUtils.blockState import com.lambda.util.BlockUtils.calcItemBlockBreakingDelta import com.lambda.util.BlockUtils.instantBreakable -import com.lambda.util.NamedEnum import com.lambda.util.player.SlotUtils.hotbar import net.minecraft.block.pattern.CachedBlockPosition import net.minecraft.enchantment.Enchantments @@ -56,46 +55,45 @@ object FastBreak : Module( description = "Break blocks faster.", tag = ModuleTag.PLAYER, ) { - private enum class Group(override val displayName: String) : NamedEnum { - Break("Break"), - Inventory("Inventory"), - Hotbar("Hotbar") + override val breakConfig = object : BreakConfig by super.breakConfig { + override val rotateForBreak = false + override val doubleBreak = false + override val breaksPerTick = 1 } - - override val breakConfig = BreakSettings(this, Group.Break).apply { - editTyped( - ::avoidLiquids, - ::avoidSupporting, - ::efficientOnly, - ::suitableToolsOnly, - ::rotateForBreak, - ::doubleBreak - ) { defaultValue(false) } - ::breaksPerTick.edit { defaultValue(1) } - hide( - ::sorter, - ::doubleBreak, - ::unsafeCancels, - ::rotateForBreak, - ::breaksPerTick, - ) - } - override val inventoryConfig = InventorySettings(this, Group.Inventory).apply { - editTyped( - ::accessShulkerBoxes, - ::accessEnderChest, - ::accessChests, - ::accessStashes - ) { - defaultValue(false) - hide() - } + override val inventoryConfig = object : InventoryConfig by super.inventoryConfig { + override val accessShulkerBoxes = false + override val accessEnderChest = false + override val accessChests = false + override val accessStashes = false } - override val hotbarConfig = HotbarSettings(this, Group.Hotbar) private val pendingInteractions = ConcurrentLinkedQueue() init { + defaultConfig = automationConfig { + breakConfig.apply { + editTyped( + ::avoidLiquids, + ::avoidSupporting, + ::efficientOnly, + ::suitableToolsOnly + ) { defaultValue(false) } + hide( + ::rotateForBreak, + ::doubleBreak, + ::breaksPerTick + ) + } + inventoryConfig.apply { + hide( + ::accessShulkerBoxes, + ::accessEnderChest, + ::accessChests, + ::accessStashes + ) + } + } + listen { it.cancel() } listen { event -> event.cancel() 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 494a62339..276898804 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt @@ -22,7 +22,7 @@ import com.lambda.config.groups.BuildSettings import com.lambda.config.groups.HotbarSettings import com.lambda.config.groups.InventorySettings import com.lambda.config.groups.RotationSettings -import com.lambda.config.groups.SettingGroup +import com.lambda.config.groups.MutableSettings import com.lambda.context.SafeContext import com.lambda.event.events.PlayerEvent import com.lambda.event.events.TickEvent @@ -87,7 +87,7 @@ object PacketMine : Module( ) { defaultValue(false) } ::swing.edit { defaultValue(BreakConfig.SwingMode.Start) } - ::rebreak.insert(::rebreakMode, SettingGroup.InsertMode.Below) + ::rebreak.insert(::rebreakMode, MutableSettings.InsertMode.Below) ::rebreakMode.edit { visibility { rebreak } } ::sounds.insert( @@ -98,7 +98,7 @@ object PacketMine : Module( ::staticColor, ::startColor, ::endColor, - insertMode = SettingGroup.InsertMode.Above + insertMode = MutableSettings.InsertMode.Above ) } override val buildConfig = BuildSettings(this, Group.Build).apply { diff --git a/src/main/kotlin/com/lambda/task/Task.kt b/src/main/kotlin/com/lambda/task/Task.kt index 502337293..70078999b 100644 --- a/src/main/kotlin/com/lambda/task/Task.kt +++ b/src/main/kotlin/com/lambda/task/Task.kt @@ -18,7 +18,7 @@ package com.lambda.task import com.lambda.Lambda.LOG -import com.lambda.context.AutomationConfig +import com.lambda.context.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.event.EventFlow.unsubscribe import com.lambda.event.Muteable @@ -127,7 +127,7 @@ abstract class Task : Nameable, Muteable { fun success(result: Result) { unsubscribe() state = State.Completed - if (!AutomationConfig.showAllEntries) parent?.subTasks?.remove(this) + if (!DEFAULT.showAllEntries) parent?.subTasks?.remove(this) runSafe { executeNextTask(result) } } diff --git a/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt b/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt index 11c66b24a..50c499bd9 100644 --- a/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt +++ b/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt @@ -21,7 +21,7 @@ import baritone.api.pathing.goals.GoalBlock import com.lambda.Lambda.LOG import com.lambda.config.groups.EatConfig.Companion.reasonEating import com.lambda.context.Automated -import com.lambda.context.AutomationConfig +import com.lambda.context.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen @@ -123,7 +123,7 @@ class BuildTask private constructor( private fun SafeContext.simulateAndProcess() { val results = runSafeAutomated { blueprint.simulate() } - AutomationConfig.drawables = results + DEFAULT.drawables = results .filterIsInstance() .plus(pendingInteractions.toList()) @@ -258,7 +258,7 @@ class BuildTask private constructor( @Ta5kBuilder fun Automated.build( finishOnDone: Boolean = true, - collectDrops: Boolean = AutomationConfig.buildConfig.collectDrops, + collectDrops: Boolean = DEFAULT.buildConfig.collectDrops, lifeMaintenance: Boolean = false, blueprint: () -> Blueprint ) = BuildTask(blueprint(), finishOnDone, collectDrops, lifeMaintenance, this) @@ -267,7 +267,7 @@ class BuildTask private constructor( context(automated: Automated) fun Structure.build( finishOnDone: Boolean = true, - collectDrops: Boolean = AutomationConfig.buildConfig.collectDrops, + collectDrops: Boolean = DEFAULT.buildConfig.collectDrops, lifeMaintenance: Boolean = false ) = BuildTask(toBlueprint(), finishOnDone, collectDrops, lifeMaintenance, automated) @@ -275,7 +275,7 @@ class BuildTask private constructor( context(automated: Automated) fun Blueprint.build( finishOnDone: Boolean = true, - collectDrops: Boolean = AutomationConfig.buildConfig.collectDrops, + collectDrops: Boolean = DEFAULT.buildConfig.collectDrops, lifeMaintenance: Boolean = false ) = BuildTask(this, finishOnDone, collectDrops, lifeMaintenance, automated) @@ -294,7 +294,7 @@ class BuildTask private constructor( fun Automated.breakBlock( blockPos: BlockPos, finishOnDone: Boolean = true, - collectDrops: Boolean = AutomationConfig.buildConfig.collectDrops, + collectDrops: Boolean = DEFAULT.buildConfig.collectDrops, lifeMaintenance: Boolean = false ) = BuildTask( blockPos.toStructure(TargetState.Air).toBlueprint(), From 3b43ed3d4103bd6b087754ced2a9a3e711973efc Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Thu, 20 Nov 2025 20:13:55 +0000 Subject: [PATCH 02/12] a button to access the automation configs within modules --- .../com/lambda/config/AbstractSetting.kt | 5 + .../com/lambda/config/groups/BreakSettings.kt | 2 +- .../com/lambda/config/groups/BuildSettings.kt | 2 +- .../com/lambda/config/groups/EatSettings.kt | 2 +- .../lambda/config/groups/HotbarSettings.kt | 2 +- .../lambda/config/groups/InteractSettings.kt | 2 +- .../lambda/config/groups/InventorySettings.kt | 2 +- .../lambda/config/groups/MutableSettings.kt | 151 ------------------ .../com/lambda/config/groups/PlaceSettings.kt | 2 +- .../lambda/config/groups/RotationSettings.kt | 2 +- .../com/lambda/config/groups/Targeting.kt | 2 +- .../lambda/config/settings/NumericSetting.kt | 14 +- .../lambda/config/settings/StringSetting.kt | 10 +- .../settings/collections/ListSetting.kt | 6 +- .../config/settings/collections/SetSetting.kt | 6 +- .../com/lambda/context/AutomatedDelegate.kt | 31 ---- .../com/lambda/context/AutomationConfig.kt | 18 --- .../lambda/context/MutableAutomationConfig.kt | 41 +++++ .../lambda/gui/components/SettingsWidget.kt | 25 ++- src/main/kotlin/com/lambda/module/Module.kt | 11 +- .../lambda/module/modules/player/FastBreak.kt | 6 +- .../module/modules/player/HighwayTools.kt | 65 ++------ .../module/modules/player/PacketMine.kt | 131 +++++++-------- .../lambda/module/modules/player/Scaffold.kt | 70 ++++---- 24 files changed, 214 insertions(+), 394 deletions(-) delete mode 100644 src/main/kotlin/com/lambda/config/groups/MutableSettings.kt delete mode 100644 src/main/kotlin/com/lambda/context/AutomatedDelegate.kt create mode 100644 src/main/kotlin/com/lambda/context/MutableAutomationConfig.kt diff --git a/src/main/kotlin/com/lambda/config/AbstractSetting.kt b/src/main/kotlin/com/lambda/config/AbstractSetting.kt index 2cb0dc346..0e08bdc37 100644 --- a/src/main/kotlin/com/lambda/config/AbstractSetting.kt +++ b/src/main/kotlin/com/lambda/config/AbstractSetting.kt @@ -102,6 +102,7 @@ abstract class AbstractSetting( 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 -> @@ -152,6 +153,10 @@ abstract class AbstractSetting( listeners.add(ValueListener(false, block)) } + fun disabled(predicate: () -> Boolean) = apply { + disabled = predicate + } + fun group(path: List, vararg continuation: NamedEnum) = apply { groups.add(path + continuation) } diff --git a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt index 911073393..15c40fa22 100644 --- a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt @@ -32,7 +32,7 @@ open class BreakSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true }, -) : BreakConfig, MutableSettings(c) { +) : BreakConfig { enum class Group(override val displayName: String) : NamedEnum { General("General"), Cosmetic("Cosmetic") diff --git a/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt b/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt index 9556b0e43..c116b205c 100644 --- a/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt @@ -26,7 +26,7 @@ class BuildSettings( c: Configurable, vararg baseGroup: NamedEnum, vis: () -> Boolean = { true }, -) : BuildConfig, MutableSettings(c) { +) : BuildConfig { enum class Group(override val displayName: String) : NamedEnum { General("General"), Reach("Reach"), diff --git a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt index 50cdd9e18..fddcbe9c2 100644 --- a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt @@ -25,7 +25,7 @@ class EatSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : EatConfig, MutableSettings(c) { +) : EatConfig { val nutritiousFoodDefaults = listOf(Items.APPLE, Items.BAKED_POTATO, Items.BEEF, Items.BEETROOT, Items.BEETROOT_SOUP, Items.BREAD, Items.CARROT, Items.CHICKEN, Items.CHORUS_FRUIT, Items.COD, Items.COOKED_BEEF, Items.COOKED_CHICKEN, Items.COOKED_COD, Items.COOKED_MUTTON, Items.COOKED_PORKCHOP, Items.COOKED_RABBIT, Items.COOKED_SALMON, Items.COOKIE, Items.DRIED_KELP, Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE, Items.GOLDEN_CARROT, Items.HONEY_BOTTLE, Items.MELON_SLICE, Items.MUSHROOM_STEW, Items.MUTTON, Items.POISONOUS_POTATO, Items.PORKCHOP, Items.POTATO, Items.PUFFERFISH, Items.PUMPKIN_PIE, Items.RABBIT, Items.RABBIT_STEW, Items.ROTTEN_FLESH, Items.SALMON, Items.SPIDER_EYE, Items.SUSPICIOUS_STEW, Items.SWEET_BERRIES, Items.GLOW_BERRIES, Items.TROPICAL_FISH) val resistanceFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE) val regenerationFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE) diff --git a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt index 21efc3347..acf1c950b 100644 --- a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt @@ -26,7 +26,7 @@ class HotbarSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : HotbarConfig, MutableSettings(c) { +) : HotbarConfig { override val keepTicks by c.setting("Keep Ticks", 1, 0..20, 1, "The number of ticks to keep the current hotbar selection active", " ticks", visibility = vis).group(baseGroup) override val swapDelay by c.setting("Swap Delay", 0, 0..3, 1, "The number of ticks delay before allowing another hotbar selection swap", " ticks", visibility = vis).group(baseGroup) override val swapsPerTick by c.setting("Swaps Per Tick", 3, 1..10, 1, "The number of hotbar selection swaps that can take place each tick") { swapDelay <= 0 && vis() }.group(baseGroup) diff --git a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt index ddbb41513..5ad6428de 100644 --- a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt @@ -26,7 +26,7 @@ class InteractSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : InteractConfig, MutableSettings(c) { +) : InteractConfig { override val rotate by c.setting("Rotate For Interact", true, "Rotates the player to look at the block when interacting", visibility = vis).group(baseGroup) override val sorter by c.setting("Interact Sorter", ActionConfig.SortMode.Tool, "The order in which interactions are performed", visibility = vis).group(baseGroup) override val swingHand by c.setting("Swing On Interact", true, "Swings the players hand after interacting", visibility = vis).group(baseGroup) diff --git a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt index 689211456..11ddfcc00 100644 --- a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt @@ -27,7 +27,7 @@ class InventorySettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : InventoryConfig, MutableSettings(c) { +) : InventoryConfig { enum class Group(override val displayName: String) : NamedEnum { General("General"), Container("Container"), diff --git a/src/main/kotlin/com/lambda/config/groups/MutableSettings.kt b/src/main/kotlin/com/lambda/config/groups/MutableSettings.kt deleted file mode 100644 index 12fb93ede..000000000 --- a/src/main/kotlin/com/lambda/config/groups/MutableSettings.kt +++ /dev/null @@ -1,151 +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.groups - -import com.lambda.config.AbstractSetting -import com.lambda.config.Configurable -import com.lambda.util.NamedEnum -import kotlin.reflect.KProperty0 -import kotlin.reflect.jvm.isAccessible - -private val KProperty0<*>.delegate - get() = try { - apply { isAccessible = true }.getDelegate() - } catch (e: Exception) { - throw IllegalStateException("Could not access delegate for property $name", e) - } - -@Suppress("unchecked_cast") -abstract class MutableSettings(val c: Configurable) { - @DslMarker - annotation class SettingEditorDsl - - @SettingEditorDsl - internal inline fun KProperty0.edit(edits: FullEditBuilder.(AbstractSetting) -> Unit) { - val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") - FullEditBuilder(setting, c).edits(setting) - } - - @SettingEditorDsl - internal inline fun KProperty0.editWith( - other: KProperty0<*>, - edits: FullEditBuilder.(AbstractSetting<*>) -> Unit - ) { - val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") - FullEditBuilder(setting, c).edits(other.delegate as AbstractSetting<*>) - } - - @SettingEditorDsl - fun edit( - vararg settings: KProperty0<*>, - edits: BasicEditBuilder.() -> Unit - ) { BasicEditBuilder(c, settings.map { it.delegate } as List>).apply(edits) } - - @SettingEditorDsl - fun editWith( - vararg settings: KProperty0<*>, - other: KProperty0<*>, - edits: BasicEditBuilder.(AbstractSetting<*>) -> Unit - ) { BasicEditBuilder(c, settings.map { it.delegate } as List>).edits(other.delegate as AbstractSetting<*>) } - - @SettingEditorDsl - internal inline fun editTyped( - vararg settings: KProperty0, - edits: TypedEditBuilder.() -> Unit - ) { TypedEditBuilder(settings.map { it.delegate } as List>, c).apply(edits) } - - @SettingEditorDsl - internal inline fun editTypedWith( - vararg settings: KProperty0, - other: KProperty0, - edits: TypedEditBuilder.(AbstractSetting) -> Unit - ) = TypedEditBuilder(settings.map { it.delegate } as List>, c).edits(other.delegate as AbstractSetting) - - @SettingEditorDsl - fun hide(vararg settings: KProperty0<*>) = - c.settings.removeAll(settings.map { it.delegate } as List>) - - @SettingEditorDsl - fun KProperty0<*>.insert(insert: KProperty0<*>, insertMode: InsertMode) { - val delegate = insert.delegate as AbstractSetting<*> - c.settings.remove(delegate) - val index = c.settings.indexOf(this.delegate as AbstractSetting<*>) - c.settings.add(if (insertMode == InsertMode.Below) index + 1 else index, delegate) - } - - @SettingEditorDsl - fun KProperty0<*>.insert(vararg inserts: KProperty0<*>, insertMode: InsertMode) { - inserts.forEach { c.settings.remove(it.delegate as AbstractSetting<*>) } - val index = c.settings.indexOf(delegate as AbstractSetting<*>) - c.settings.addAll( - if (insertMode == InsertMode.Below) index + 1 else index, - inserts.map { it.delegate } as List> - ) - } - - open class BasicEditBuilder(val c: Configurable, open val settings: Collection>) { - @SettingEditorDsl - fun visibility(vis: () -> Boolean) = - settings.forEach { it.visibility = vis } - - @SettingEditorDsl - fun hide() { - c.settings.removeAll(settings) - } - - @SettingEditorDsl - fun groups(vararg groups: NamedEnum) = - settings.forEach { it.groups = mutableListOf(groups.toList()) } - - @SettingEditorDsl - fun groups(groups: MutableList>) = - settings.forEach { it.groups = groups } - } - - open class TypedEditBuilder( - override val settings: Collection>, - c: Configurable - ) : BasicEditBuilder(c, settings) { - @SettingEditorDsl - fun defaultValue(value: T) = - settings.forEach { - it.defaultValue = value - it.value = value - } - } - - class FullEditBuilder( - private val setting: AbstractSetting, - c: Configurable - ) : TypedEditBuilder(setOf(setting), c) { - @SettingEditorDsl - fun name(name: String) { - setting.name = name - } - - @SettingEditorDsl - fun description(description: String) { - setting.description = description - } - } - - enum class InsertMode { - Above, - Below - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt index ff410115d..da897e574 100644 --- a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt @@ -28,7 +28,7 @@ class PlaceSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : PlaceConfig, MutableSettings(c) { +) : PlaceConfig { override val rotateForPlace by c.setting("Rotate For Place", true, "Rotate towards block while placing", visibility = vis).group(baseGroup) override val airPlace by c.setting("Air Place", AirPlaceMode.None, "Allows for placing blocks without adjacent faces", visibility = vis).group(baseGroup) override val axisRotateSetting by c.setting("Axis Rotate", true, "Overrides the Rotate For Place setting and rotates the player on each axis to air place rotational blocks") { vis() && airPlace.isEnabled }.group(baseGroup) diff --git a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt index de06e622b..505d9cfdb 100644 --- a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt @@ -32,7 +32,7 @@ class RotationSettings( c: Configurable, baseGroup: NamedEnum? = null, vis: () -> Boolean = { true } -) : RotationConfig, MutableSettings(c) { +) : RotationConfig { override var rotationMode by c.setting("Mode", RotationMode.Sync, "How the player is being rotated on interaction", vis).group(baseGroup) /** How many ticks to keep the rotation before resetting */ diff --git a/src/main/kotlin/com/lambda/config/groups/Targeting.kt b/src/main/kotlin/com/lambda/config/groups/Targeting.kt index f6e08177c..51cfdf391 100644 --- a/src/main/kotlin/com/lambda/config/groups/Targeting.kt +++ b/src/main/kotlin/com/lambda/config/groups/Targeting.kt @@ -54,7 +54,7 @@ abstract class Targeting( private val predicate: () -> Boolean = { true }, private val defaultRange: Double, private val maxRange: Double, -) : TargetingConfig, MutableSettings(owner) { +) : TargetingConfig { /** * The range within which entities can be targeted. This value is configurable and constrained diff --git a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt index dd8ca0c7f..00ccc6c43 100644 --- a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt @@ -19,7 +19,7 @@ package com.lambda.config.settings import com.google.gson.reflect.TypeToken import com.lambda.config.AbstractSetting -import com.lambda.config.groups.MutableSettings +import com.lambda.context.AutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import imgui.ImGui import imgui.ImGui.calcTextSize @@ -97,21 +97,21 @@ abstract class NumericSetting( } companion object { - @MutableSettings.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun MutableSettings.TypedEditBuilder.range(range: ClosedRange) where T : Number, T : Comparable { + fun AutomationConfig.TypedEditBuilder.range(range: ClosedRange) where T : Number, T : Comparable { (settings as Collection>).forEach { it.range = range } } - @MutableSettings.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun MutableSettings.TypedEditBuilder.step(step: T) where T : Number, T : Comparable { + fun AutomationConfig.TypedEditBuilder.step(step: T) where T : Number, T : Comparable { (settings as Collection>).forEach { it.step = step } } - @MutableSettings.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun MutableSettings.TypedEditBuilder.unit(unit: String) where T : Number, T : Comparable { + fun AutomationConfig.TypedEditBuilder.unit(unit: String) where T : Number, T : Comparable { (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/StringSetting.kt index 5ae35dc24..cabf6ac68 100644 --- a/src/main/kotlin/com/lambda/config/settings/StringSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/StringSetting.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.AbstractSetting -import com.lambda.config.groups.MutableSettings +import com.lambda.context.AutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import imgui.flag.ImGuiInputTextFlags @@ -64,15 +64,15 @@ class StringSetting( } companion object { - @MutableSettings.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun MutableSettings.TypedEditBuilder.multiline(multiline: Boolean) { + fun AutomationConfig.TypedEditBuilder.multiline(multiline: Boolean) { (settings as Collection).forEach { it.multiline = multiline } } - @MutableSettings.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun MutableSettings.TypedEditBuilder.flags(flags: Int) { + fun AutomationConfig.TypedEditBuilder.flags(flags: Int) { (settings as Collection).forEach { it.flags = flags } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt index 26f3ed559..d38326dd8 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt @@ -21,7 +21,7 @@ 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.groups.MutableSettings +import com.lambda.context.AutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -75,9 +75,9 @@ class ListSetting( } companion object { - @MutableSettings.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun MutableSettings.TypedEditBuilder>.immutableList(immutableList: List) { + fun AutomationConfig.TypedEditBuilder>.immutableList(immutableList: List) { (settings as Collection>).forEach { it.immutableList = immutableList } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt index acd0e661d..74e202b12 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt @@ -21,7 +21,7 @@ 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.groups.MutableSettings +import com.lambda.context.AutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -76,9 +76,9 @@ class SetSetting( } companion object { - @MutableSettings.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun MutableSettings.TypedEditBuilder>.immutableSet(immutableSet: Set) { + fun AutomationConfig.TypedEditBuilder>.immutableSet(immutableSet: Set) { (settings as Collection>).forEach { it.immutableSet = immutableSet } } } diff --git a/src/main/kotlin/com/lambda/context/AutomatedDelegate.kt b/src/main/kotlin/com/lambda/context/AutomatedDelegate.kt deleted file mode 100644 index 5b9c9d594..000000000 --- a/src/main/kotlin/com/lambda/context/AutomatedDelegate.kt +++ /dev/null @@ -1,31 +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.context - -interface AutomatedDelegate : Automated { - var automated: Automated - - override val buildConfig get() = automated.buildConfig - override val breakConfig get() = automated.breakConfig - override val placeConfig get() = automated.placeConfig - override val interactConfig get() = automated.interactConfig - override val rotationConfig get() = automated.rotationConfig - override val inventoryConfig get() = automated.inventoryConfig - override val hotbarConfig get() = automated.hotbarConfig - override val eatConfig get() = automated.eatConfig -} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/context/AutomationConfig.kt b/src/main/kotlin/com/lambda/context/AutomationConfig.kt index bcd5eef68..8ac4f3740 100644 --- a/src/main/kotlin/com/lambda/context/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/context/AutomationConfig.kt @@ -146,24 +146,6 @@ open class AutomationConfig( fun hide(vararg settings: KProperty0<*>) = this@AutomationConfig.settings.removeAll(settings.map { it.delegate } as List>) - @SettingEditorDsl - fun KProperty0<*>.insert(insert: KProperty0<*>, insertMode: InsertMode) { - val delegate = insert.delegate as AbstractSetting<*> - this@AutomationConfig.settings.remove(delegate) - val index = this@AutomationConfig.settings.indexOf(this.delegate as AbstractSetting<*>) - this@AutomationConfig.settings.add(if (insertMode == InsertMode.Below) index + 1 else index, delegate) - } - - @SettingEditorDsl - fun KProperty0<*>.insert(vararg inserts: KProperty0<*>, insertMode: InsertMode) { - inserts.forEach { this@AutomationConfig.settings.remove(it.delegate as AbstractSetting<*>) } - val index = this@AutomationConfig.settings.indexOf(delegate as AbstractSetting<*>) - this@AutomationConfig.settings.addAll( - if (insertMode == InsertMode.Below) index + 1 else index, - inserts.map { it.delegate } as List> - ) - } - open class BasicEditBuilder(val c: Configurable, open val settings: Collection>) { @SettingEditorDsl fun visibility(vis: () -> Boolean) = diff --git a/src/main/kotlin/com/lambda/context/MutableAutomationConfig.kt b/src/main/kotlin/com/lambda/context/MutableAutomationConfig.kt new file mode 100644 index 000000000..150327fcf --- /dev/null +++ b/src/main/kotlin/com/lambda/context/MutableAutomationConfig.kt @@ -0,0 +1,41 @@ +/* + * 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.context + +import com.lambda.config.groups.BuildConfig +import com.lambda.config.groups.EatConfig +import com.lambda.interaction.request.breaking.BreakConfig +import com.lambda.interaction.request.hotbar.HotbarConfig +import com.lambda.interaction.request.interacting.InteractConfig +import com.lambda.interaction.request.inventory.InventoryConfig +import com.lambda.interaction.request.placing.PlaceConfig +import com.lambda.interaction.request.rotating.RotationConfig + +interface MutableAutomationConfig : Automated { + var defaultAutomationConfig: 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 +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt index 16f257832..5214cb864 100644 --- a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt +++ b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt @@ -19,9 +19,11 @@ package com.lambda.gui.components import com.lambda.config.AbstractSetting import com.lambda.config.Configurable +import com.lambda.context.MutableAutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.module.Module import com.lambda.util.NamedEnum +import imgui.ImGui import imgui.flag.ImGuiTabBarFlags object SettingsWidget { @@ -38,21 +40,40 @@ object SettingsWidget { config.settings.forEach { it.reset(silent = true) } } lambdaTooltip("Resets all settings for this module to their default values") + if (config is MutableAutomationConfig) { + button("Automation Config") + popupContextItem("##automation-config-popup-${config.name}") { + if (config.automationConfig !== config.defaultAutomationConfig) { + text("Linked to the ${config.automationConfig.name} configuration") + } + buildConfigSettingsContext(config.automationConfig) + } + } } separator() val toIgnoreSettings = if (config is Module) setOf(config.keybindSetting, config.disableOnReleaseSetting) else emptySet() val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() } - ungrouped.forEach { with(it) { buildLayout() } } + ungrouped.forEach { + it.withDisabled { buildLayout() } + } renderGroup(grouped, emptyList(), config) } + private fun AbstractSetting<*>.withDisabled(block: AbstractSetting<*>.() -> Unit) { + if (disabled()) ImGui.beginDisabled() + block() + if (disabled()) ImGui.endDisabled() + } + private fun ImGuiBuilder.renderGroup( settings: List>, parentPath: List, config: Configurable ) { - settings.filter { it.groups.contains(parentPath) }.forEach { with(it) { buildLayout() } } + settings.filter { it.groups.contains(parentPath) }.forEach { + it.withDisabled { buildLayout() } + } val subGroupSettings = settings.filter { s -> s.groups.any { it.size > parentPath.size && it.subList(0, parentPath.size) == parentPath } diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index a6f0dd5ba..45a70f5ed 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -24,9 +24,8 @@ import com.lambda.config.Configurable import com.lambda.config.Configuration import com.lambda.config.configurations.ModuleConfigs import com.lambda.config.settings.complex.Bind -import com.lambda.context.Automated -import com.lambda.context.AutomatedDelegate import com.lambda.context.AutomationConfig +import com.lambda.context.MutableAutomationConfig import com.lambda.context.SafeContext import com.lambda.event.Muteable import com.lambda.event.events.ClientEvent @@ -121,13 +120,13 @@ abstract class Module( enabledByDefault: Boolean = false, defaultKeybind: Bind = Bind.EMPTY, autoDisable: Boolean = false -) : Nameable, Muteable, Configurable(ModuleConfigs), AutomatedDelegate { - protected var defaultConfig: Automated = AutomationConfig.Companion.DEFAULT +) : Nameable, Muteable, Configurable(ModuleConfigs), MutableAutomationConfig { + override var defaultAutomationConfig: AutomationConfig = AutomationConfig.Companion.DEFAULT set(value) { field = value - automated = value + automationConfig = value } - override var automated = defaultConfig + override var automationConfig = defaultAutomationConfig 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/FastBreak.kt b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt index 13ceacf5d..171de3245 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt @@ -55,6 +55,8 @@ object FastBreak : Module( description = "Break blocks faster.", tag = ModuleTag.PLAYER, ) { + private val pendingInteractions = ConcurrentLinkedQueue() + override val breakConfig = object : BreakConfig by super.breakConfig { override val rotateForBreak = false override val doubleBreak = false @@ -67,10 +69,8 @@ object FastBreak : Module( override val accessStashes = false } - private val pendingInteractions = ConcurrentLinkedQueue() - init { - defaultConfig = automationConfig { + defaultAutomationConfig = automationConfig { breakConfig.apply { editTyped( ::avoidLiquids, diff --git a/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt b/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt index 46327ce69..e0689df36 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt @@ -17,19 +17,10 @@ package com.lambda.module.modules.player -import com.lambda.config.groups.BreakSettings -import com.lambda.config.groups.BuildSettings -import com.lambda.config.groups.EatSettings -import com.lambda.config.groups.HotbarSettings -import com.lambda.config.groups.InteractSettings -import com.lambda.config.groups.InventorySettings -import com.lambda.config.groups.PlaceSettings -import com.lambda.config.groups.RotationSettings import com.lambda.interaction.BaritoneManager import com.lambda.interaction.construction.blueprint.Blueprint.Companion.emptyStructure import com.lambda.interaction.construction.blueprint.PropagatingBlueprint.Companion.propagatingBlueprint import com.lambda.interaction.construction.verify.TargetState -import com.lambda.interaction.request.breaking.BreakConfig import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.task.RootTask.run @@ -55,46 +46,22 @@ object HighwayTools : Module( description = "Auto highway builder", tag = ModuleTag.PLAYER, ) { - enum class Group(override val displayName: String): NamedEnum { - Structure("Structure"), - Build("Build"), - Break("Break"), - Place("Place"), - Interact("Interact"), - Rotation("Rotation"), - Interaction("Interaction"), - Inventory("Inventory"), - Hotbar("Hotbar"), - Eat("Eat") - } - - private val height by setting("Height", 4, 2..10, 1).group(Group.Structure) - private val width by setting("Width", 6, 1..30, 1).group(Group.Structure) - private val pavement by setting("Pavement", Material.Block, "Material for the pavement").group(Group.Structure) - private val rimHeight by setting("Pavement Rim Height", 1, 0..6, 1) { pavement != Material.None }.group(Group.Structure) - private val cornerBlock by setting("Corner", Corner.None, "Include corner blocks in the highway") { pavement != Material.None }.group(Group.Structure) - private val pavementMaterial by setting("Pavement Material", Blocks.OBSIDIAN, "Material to build the highway with") { pavement == Material.Block }.group(Group.Structure) - private val floor by setting("Floor", Material.None, "Material for the floor").group(Group.Structure) - private val floorMaterial by setting("Floor Material", Blocks.NETHERRACK, "Material to build the floor with") { floor == Material.Block }.group(Group.Structure) - private val rightWall by setting("Right Wall", Material.None, "Build the right wall").group(Group.Structure) - private val leftWall by setting("Left Wall", Material.None, "Build the left wall").group(Group.Structure) - private val wallMaterial by setting("Wall Material", Blocks.NETHERRACK, "Material to build the walls with") { rightWall == Material.Block || leftWall == Material.Block }.group(Group.Structure) - private val ceiling by setting("Ceiling", Material.None, "Material for the ceiling").group(Group.Structure) - private val ceilingMaterial by setting("Ceiling Material", Blocks.OBSIDIAN, "Material to build the ceiling with") { ceiling == Material.Block }.group(Group.Structure) - private val replaceableSolids by setting("Replaceable Solids", setOf(Blocks.MAGMA_BLOCK, Blocks.SOUL_SAND)).group(Group.Structure) - private val distance by setting("Distance", -1, -1..1000000, 1, "Distance to build the highway/tunnel (negative for infinite)").group(Group.Structure) - private val sliceSize by setting("Slice Size", 3, 1..5, 1, "Number of slices to build at once").group(Group.Structure) - - override val buildConfig = BuildSettings(this, Group.Build) - override val breakConfig = BreakSettings(this, Group.Break).apply { - ::swapMode.edit { defaultValue(BreakConfig.SwapMode.Constant) } - } - override val placeConfig = PlaceSettings(this, Group.Place) - override val interactConfig = InteractSettings(this, Group.Interact) - override val rotationConfig = RotationSettings(this, Group.Rotation) - override val inventoryConfig = InventorySettings(this, Group.Inventory) - override val hotbarConfig = HotbarSettings(this, Group.Hotbar) - override val eatConfig = EatSettings(this, Group.Eat) + private val height by setting("Height", 4, 2..10, 1) + private val width by setting("Width", 6, 1..30, 1) + private val pavement by setting("Pavement", Material.Block, "Material for the pavement") + private val rimHeight by setting("Pavement Rim Height", 1, 0..6, 1) { pavement != Material.None } + private val cornerBlock by setting("Corner", Corner.None, "Include corner blocks in the highway") { pavement != Material.None } + private val pavementMaterial by setting("Pavement Material", Blocks.OBSIDIAN, "Material to build the highway with") { pavement == Material.Block } + private val floor by setting("Floor", Material.None, "Material for the floor") + private val floorMaterial by setting("Floor Material", Blocks.NETHERRACK, "Material to build the floor with") { floor == Material.Block } + private val rightWall by setting("Right Wall", Material.None, "Build the right wall") + private val leftWall by setting("Left Wall", Material.None, "Build the left wall") + private val wallMaterial by setting("Wall Material", Blocks.NETHERRACK, "Material to build the walls with") { rightWall == Material.Block || leftWall == Material.Block } + private val ceiling by setting("Ceiling", Material.None, "Material for the ceiling") + private val ceilingMaterial by setting("Ceiling Material", Blocks.OBSIDIAN, "Material to build the ceiling with") { ceiling == Material.Block } + private val replaceableSolids by setting("Replaceable Solids", setOf(Blocks.MAGMA_BLOCK, Blocks.SOUL_SAND)) + private val distance by setting("Distance", -1, -1..1000000, 1, "Distance to build the highway/tunnel (negative for infinite)") + private val sliceSize by setting("Slice Size", 3, 1..5, 1, "Number of slices to build at once") private var octant = EightWayDirection.NORTH private var distanceMoved = 0 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 276898804..91346eacb 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt @@ -17,12 +17,9 @@ package com.lambda.module.modules.player -import com.lambda.config.groups.BreakSettings -import com.lambda.config.groups.BuildSettings -import com.lambda.config.groups.HotbarSettings -import com.lambda.config.groups.InventorySettings -import com.lambda.config.groups.RotationSettings -import com.lambda.config.groups.MutableSettings +import com.lambda.config.groups.BreakSettings.Group +import com.lambda.config.groups.BuildConfig +import com.lambda.context.AutomationConfig.Companion.automationConfig import com.lambda.context.SafeContext import com.lambda.event.events.PlayerEvent import com.lambda.event.events.TickEvent @@ -36,6 +33,7 @@ import com.lambda.interaction.construction.simulation.BuildSimulator.simulate import com.lambda.interaction.construction.verify.TargetState import com.lambda.interaction.request.breaking.BreakConfig import com.lambda.interaction.request.breaking.BreakRequest.Companion.breakRequest +import com.lambda.interaction.request.inventory.InventoryConfig import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.threading.runSafeAutomated @@ -55,73 +53,20 @@ object PacketMine : Module( description = "automatically breaks blocks, and does it faster", tag = ModuleTag.PLAYER ) { - private enum class Group(override val displayName: String) : NamedEnum { - Break("Break"), - Build("Build"), - Rotation("Rotation"), - Inventory("Inventory"), - Hotbar("Hotbar"), - } - - private val rebreakMode by setting("Rebreak Mode", RebreakMode.Manual, "The method used to re-break blocks after they've been broken once").group(Group.Break, BreakSettings.Group.General) - private val breakRadius by setting("Break Radius", 0, 0..5, 1, "Selects and breaks all blocks within the break radius of the selected block").group(Group.Break, BreakSettings.Group.General) - private val flatten by setting("Flatten", true, "Wont allow breaking extra blocks under your players position") { breakRadius > 0 }.group(Group.Break, BreakSettings.Group.General) - private val queue by setting("Queue", false, "Queues blocks to break so you can select multiple at once").group(Group.Break, BreakSettings.Group.General) + private val rebreakMode by setting("Rebreak Mode", RebreakMode.Manual, "The method used to re-break blocks after they've been broken once").disabled { !breakConfig.rebreak }.group(Group.General) + private val breakRadius by setting("Break Radius", 0, 0..5, 1, "Selects and breaks all blocks within the break radius of the selected block").group(Group.General) + private val flatten by setting("Flatten", true, "Wont allow breaking extra blocks under your players position") { breakRadius > 0 }.group(Group.General) + private val queue by setting("Queue", false, "Queues blocks to break so you can select multiple at once").group(Group.General) .onValueChange { _, to -> if (!to) queuePositions.clear() } - private val queueOrder by setting("Queue Order", QueueOrder.Standard, "Which end of the queue to break blocks from") { queue }.group(Group.Break, BreakSettings.Group.General) - - private val renderQueue by setting("Render Queue", true, "Adds renders to signify what block positions are queued").group(Group.Break, BreakSettings.Group.Cosmetic) - private val renderSize by setting("Render Size", 0.3f, 0.01f..1f, 0.01f, "The scale of the queue renders") { renderQueue }.group(Group.Break, BreakSettings.Group.Cosmetic) - private val renderMode by setting("Render Mode", RenderMode.State, "The style of the queue renders") { renderQueue }.group(Group.Break, BreakSettings.Group.Cosmetic) - private val dynamicColor by setting("Dynamic Color", true, "Interpolates the color between start and end") { renderQueue }.group(Group.Break, BreakSettings.Group.Cosmetic) - private val staticColor by setting("Color", Color(255, 0, 0, 60).brighter()) { renderQueue && !dynamicColor }.group(Group.Break, BreakSettings.Group.Cosmetic) - private val startColor by setting("Start Color", Color(255, 255, 0, 60).brighter(), "The color of the start (closest to breaking) of the queue") { renderQueue && dynamicColor }.group(Group.Break, BreakSettings.Group.Cosmetic) - private val endColor by setting("End Color", Color(255, 0, 0, 60).brighter(), "The color of the end (farthest from breaking) of the queue") { renderQueue && dynamicColor }.group(Group.Break, BreakSettings.Group.Cosmetic) + private val queueOrder by setting("Queue Order", QueueOrder.Standard, "Which end of the queue to break blocks from") { queue }.group(Group.General) - override val breakConfig = BreakSettings(this, Group.Break).apply { - editTyped( - ::avoidLiquids, - ::avoidSupporting, - ::efficientOnly, - ::suitableToolsOnly - ) { defaultValue(false) } - ::swing.edit { defaultValue(BreakConfig.SwingMode.Start) } - - ::rebreak.insert(::rebreakMode, MutableSettings.InsertMode.Below) - ::rebreakMode.edit { visibility { rebreak } } - - ::sounds.insert( - ::renderQueue, - ::renderSize, - ::renderMode, - ::dynamicColor, - ::staticColor, - ::startColor, - ::endColor, - insertMode = MutableSettings.InsertMode.Above - ) - } - override val buildConfig = BuildSettings(this, Group.Build).apply { - editTyped(::pathing, ::stayInRange, ::collectDrops) { - defaultValue(false) - hide() - } - } - override val rotationConfig = RotationSettings(this, Group.Rotation) - override val inventoryConfig = InventorySettings(this, Group.Inventory).apply { - editTyped( - ::accessShulkerBoxes, - ::accessEnderChest, - ::accessChests, - ::accessStashes - ) { - defaultValue(false) - hide() - } - } - override val hotbarConfig = HotbarSettings(this, Group.Hotbar).apply { - ::keepTicks.edit { defaultValue(0) } - } + private val renderQueue by setting("Render Queue", true, "Adds renders to signify what block positions are queued").disabled { !breakConfig.renders }.group(Group.Cosmetic) + private val renderSize by setting("Render Size", 0.3f, 0.01f..1f, 0.01f, "The scale of the queue renders") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Cosmetic) + private val renderMode by setting("Render Mode", RenderMode.State, "The style of the queue renders") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Cosmetic) + private val dynamicColor by setting("Dynamic Color", true, "Interpolates the color between start and end") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Cosmetic) + private val staticColor by setting("Color", Color(255, 0, 0, 60).brighter()) { renderQueue && !dynamicColor }.disabled { !breakConfig.renders }.group(Group.Cosmetic) + private val startColor by setting("Start Color", Color(255, 255, 0, 60).brighter(), "The color of the start (closest to breaking) of the queue") { renderQueue && dynamicColor }.disabled { !breakConfig.renders }.group(Group.Cosmetic) + private val endColor by setting("End Color", Color(255, 0, 0, 60).brighter(), "The color of the end (farthest from breaking) of the queue") { renderQueue && dynamicColor }.disabled { !breakConfig.renders }.group(Group.Cosmetic) private val pendingInteractions = ConcurrentLinkedQueue() @@ -146,7 +91,51 @@ object PacketMine : Module( private var reBreakPos: BlockPos? = null private var attackedThisTick = false + override val buildConfig = object : BuildConfig by super.buildConfig { + override val pathing = false + override val stayInRange = false + override val collectDrops = false + } + override val inventoryConfig = object : InventoryConfig by super.inventoryConfig { + override val accessShulkerBoxes = false + override val accessEnderChest = false + override val accessChests = false + override val accessStashes = false + } + init { + defaultAutomationConfig = automationConfig { + buildConfig.apply { + editTyped(::pathing, ::stayInRange, ::collectDrops) { + defaultValue(false) + hide() + } + } + breakConfig.apply { + editTyped( + ::avoidLiquids, + ::avoidSupporting, + ::efficientOnly, + ::suitableToolsOnly + ) { defaultValue(false) } + ::swing.edit { defaultValue(BreakConfig.SwingMode.Start) } + } + inventoryConfig.apply { + editTyped( + ::accessShulkerBoxes, + ::accessEnderChest, + ::accessChests, + ::accessStashes + ) { + defaultValue(false) + hide() + } + } + hotbarConfig.apply { + ::keepTicks.edit { defaultValue(0) } + } + } + listen { attackedThisTick = false } diff --git a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt index 4080c2aaf..c7297454b 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt @@ -17,11 +17,9 @@ package com.lambda.module.modules.player -import com.lambda.config.groups.BuildSettings -import com.lambda.config.groups.HotbarSettings -import com.lambda.config.groups.InventorySettings -import com.lambda.config.groups.RotationSettings +import com.lambda.config.groups.BuildConfig import com.lambda.config.settings.complex.Bind +import com.lambda.context.AutomationConfig.Companion.automationConfig import com.lambda.context.SafeContext import com.lambda.event.events.MovementEvent import com.lambda.event.events.TickEvent @@ -32,15 +30,15 @@ import com.lambda.interaction.construction.result.results.PlaceResult import com.lambda.interaction.construction.simulation.BuildSimulator.simulate import com.lambda.interaction.construction.verify.TargetState import com.lambda.interaction.request.Request.Companion.submit +import com.lambda.interaction.request.inventory.InventoryConfig import com.lambda.interaction.request.placing.PlaceRequest import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.threading.runSafeAutomated import com.lambda.util.BlockUtils.blockPos import com.lambda.util.BlockUtils.blockState -import com.lambda.util.KeyCode import com.lambda.util.InputUtils.isKeyPressed -import com.lambda.util.NamedEnum +import com.lambda.util.KeyCode import com.lambda.util.math.distSq import net.minecraft.util.math.BlockPos import java.util.concurrent.ConcurrentLinkedQueue @@ -50,41 +48,41 @@ object Scaffold : Module( description = "Places blocks under the player", tag = ModuleTag.PLAYER, ) { - private enum class Group(override val displayName: String) : NamedEnum { - General("General"), - Build("Build"), - Rotation("Rotation"), - Hotbar("Hotbar"), - Inventory("Inventory") - } + private val bridgeRange by setting("Bridge Range", 5, 0..5, 1, "The range at which blocks can be placed to help build support for the player", unit = " blocks") + private val onlyBelow by setting("Only Below", true, "Restricts bridging to only below the player to avoid place spam if it's impossible to reach the supporting position") { bridgeRange > 0 } + private val descend by setting("Descend", KeyCode.Unbound, "Lower the place position by one to allow the player to lower y level") + private val descendAmount by setting("Descend Amount", 1, 1..5, 1, "The amount to lower the place position by when descending", unit = " blocks") { descend != Bind.EMPTY } - private val bridgeRange by setting("Bridge Range", 5, 0..5, 1, "The range at which blocks can be placed to help build support for the player", unit = " blocks").group(Group.General) - private val onlyBelow by setting("Only Below", true, "Restricts bridging to only below the player to avoid place spam if it's impossible to reach the supporting position") { bridgeRange > 0 }.group(Group.General) - private val descend by setting("Descend", KeyCode.Unbound, "Lower the place position by one to allow the player to lower y level").group(Group.General) - private val descendAmount by setting("Descend Amount", 1, 1..5, 1, "The amount to lower the place position by when descending", unit = " blocks") { descend != Bind.EMPTY }.group(Group.General) - override val buildConfig = BuildSettings(this, Group.Build).apply { - editTyped(::pathing, ::stayInRange, ::collectDrops) { - defaultValue(false) - hide() - } + private val pendingActions = ConcurrentLinkedQueue() + + override val buildConfig = object : BuildConfig by super.buildConfig { + override val pathing = false + override val stayInRange = false + override val collectDrops = false } - override val rotationConfig = RotationSettings(this, Group.Rotation) - override val hotbarConfig = HotbarSettings(this, Group.Hotbar) - override val inventoryConfig = InventorySettings(this, Group.Inventory).apply { - ::disposables.edit { - name("Blocks") - description("Blocks to use as scaffolding") - groups(Group.General) - } - editTyped(::accessShulkerBoxes, ::accessEnderChest, ::accessChests, ::accessStashes) { - defaultValue(false) - hide() - } + override val inventoryConfig = object : InventoryConfig by super.inventoryConfig { + override val accessShulkerBoxes = false + override val accessEnderChest = false + override val accessChests = false + override val accessStashes = false } - private val pendingActions = ConcurrentLinkedQueue() - init { + defaultAutomationConfig = automationConfig { + buildConfig.apply { + editTyped(::pathing, ::stayInRange, ::collectDrops) { + defaultValue(false) + hide() + } + } + inventoryConfig.apply { + editTyped(::accessShulkerBoxes, ::accessEnderChest, ::accessChests, ::accessStashes) { + defaultValue(false) + hide() + } + } + } + listen { val playerSupport = player.blockPos.down() val alreadySupported = blockState(playerSupport).hasSolidTopSurface(world, playerSupport, player) From c56b3dec82ac4ea4126aaaceecfc2fad6c0e5a03 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sat, 22 Nov 2025 21:45:57 +0000 Subject: [PATCH 03/12] working :3 --- .../lambda/command/commands/BuildCommand.kt | 2 +- .../lambda/command/commands/ModuleCommand.kt | 5 +- .../command/commands/TransferCommand.kt | 2 +- .../{context => config}/AutomationConfig.kt | 16 +++--- .../kotlin/com/lambda/config/Configuration.kt | 16 +++--- .../com/lambda/config/DynamicConfiguration.kt | 57 +++++++++++++++++++ .../MutableAutomationConfig.kt | 3 +- .../com/lambda/config/UserAutomationConfig.kt | 31 ++++++++++ .../config/configurations/ConfigLoader.kt | 1 + .../configurations/UserAutomationConfigs.kt | 53 +++++++++++++++++ .../com/lambda/config/groups/BreakSettings.kt | 2 +- .../lambda/config/settings/NumericSetting.kt | 2 +- .../lambda/config/settings/StringSetting.kt | 2 +- .../settings/collections/ListSetting.kt | 24 +++++++- .../config/settings/collections/SetSetting.kt | 25 +++++++- src/main/kotlin/com/lambda/gui/MenuBar.kt | 45 +++++++++++++++ .../lambda/gui/components/SettingsWidget.kt | 20 +++++-- .../com/lambda/interaction/BaritoneManager.kt | 2 +- .../construction/simulation/Sim.kt | 2 +- .../request/breaking/BrokenBlockHandler.kt | 2 +- .../interaction/request/breaking/SwapInfo.kt | 2 +- .../interacting/InteractedBlockHandler.kt | 2 +- .../request/inventory/InventoryManager.kt | 2 +- .../request/placing/PlacedBlockHandler.kt | 2 +- .../rotating/visibilty/VisibilityChecker.kt | 2 +- src/main/kotlin/com/lambda/module/Module.kt | 8 +-- .../com/lambda/module/ModuleRegistry.kt | 2 +- .../lambda/module/modules/player/FastBreak.kt | 2 +- .../module/modules/player/PacketMine.kt | 22 ++++--- .../lambda/module/modules/player/Scaffold.kt | 2 +- src/main/kotlin/com/lambda/task/Task.kt | 2 +- .../kotlin/com/lambda/task/tasks/BuildTask.kt | 2 +- 32 files changed, 301 insertions(+), 61 deletions(-) rename src/main/kotlin/com/lambda/{context => config}/AutomationConfig.kt (94%) create mode 100644 src/main/kotlin/com/lambda/config/DynamicConfiguration.kt rename src/main/kotlin/com/lambda/{context => config}/MutableAutomationConfig.kt (96%) create mode 100644 src/main/kotlin/com/lambda/config/UserAutomationConfig.kt create mode 100644 src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt diff --git a/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt b/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt index 1da4f889f..b047cf686 100644 --- a/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt +++ b/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt @@ -25,7 +25,7 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.executeWithResult import com.lambda.brigadier.required import com.lambda.command.LambdaCommand -import com.lambda.context.AutomationConfig +import com.lambda.config.AutomationConfig import com.lambda.interaction.construction.StructureRegistry import com.lambda.interaction.construction.blueprint.Blueprint.Companion.toStructure import com.lambda.interaction.construction.blueprint.StaticBlueprint.Companion.toBlueprint diff --git a/src/main/kotlin/com/lambda/command/commands/ModuleCommand.kt b/src/main/kotlin/com/lambda/command/commands/ModuleCommand.kt index f1794394d..316821efb 100644 --- a/src/main/kotlin/com/lambda/command/commands/ModuleCommand.kt +++ b/src/main/kotlin/com/lambda/command/commands/ModuleCommand.kt @@ -32,7 +32,6 @@ import com.lambda.threading.runSafe import com.lambda.util.Communication.info import com.lambda.util.Communication.joinToText import com.lambda.util.Communication.warn -import com.lambda.util.StringUtils import com.lambda.util.StringUtils.findSimilarStrings import com.lambda.util.extension.CommandBuilder import com.lambda.util.text.ClickEvents.suggestCommand @@ -76,7 +75,7 @@ object ModuleCommand : LambdaCommand( required(string("module name")) { moduleName -> suggests { _, builder -> - ModuleRegistry.moduleNames.forEach { + ModuleRegistry.moduleNameMap.keys.forEach { builder.suggest(it) } builder.buildFuture() @@ -95,7 +94,7 @@ object ModuleCommand : LambdaCommand( literal("not found!") } val similarModules = name.findSimilarStrings( - ModuleRegistry.moduleNames, + ModuleRegistry.moduleNameMap.keys, 3 ) if (similarModules.isEmpty()) return@buildText diff --git a/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt b/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt index 7ab91dc05..c8b267b10 100644 --- a/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt +++ b/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt @@ -27,7 +27,7 @@ import com.lambda.brigadier.argument.value import com.lambda.brigadier.executeWithResult import com.lambda.brigadier.required import com.lambda.command.LambdaCommand -import com.lambda.context.AutomationConfig +import com.lambda.config.AutomationConfig import com.lambda.interaction.material.StackSelection.Companion.selectStack import com.lambda.interaction.material.container.ContainerManager import com.lambda.interaction.material.container.ContainerManager.containerWithMaterial diff --git a/src/main/kotlin/com/lambda/context/AutomationConfig.kt b/src/main/kotlin/com/lambda/config/AutomationConfig.kt similarity index 94% rename from src/main/kotlin/com/lambda/context/AutomationConfig.kt rename to src/main/kotlin/com/lambda/config/AutomationConfig.kt index 8ac4f3740..f09e6d2f7 100644 --- a/src/main/kotlin/com/lambda/context/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/AutomationConfig.kt @@ -15,10 +15,8 @@ * along with this program. If not, see . */ -package com.lambda.context +package com.lambda.config -import com.lambda.config.AbstractSetting -import com.lambda.config.Configurable import com.lambda.config.configurations.AutomationConfigs import com.lambda.config.groups.BreakSettings import com.lambda.config.groups.BuildSettings @@ -28,6 +26,7 @@ import com.lambda.config.groups.InteractSettings import com.lambda.config.groups.InventorySettings import com.lambda.config.groups.PlaceSettings import com.lambda.config.groups.RotationSettings +import com.lambda.context.Automated import com.lambda.event.events.onStaticRender import com.lambda.interaction.construction.result.Drawable import com.lambda.module.Module @@ -37,8 +36,9 @@ import kotlin.reflect.jvm.isAccessible @Suppress("unchecked_cast", "unused") open class AutomationConfig( - override val name: String -) : Configurable(AutomationConfigs), Automated { + override val name: String, + configuration: Configuration = AutomationConfigs +) : Configurable(configuration), Automated { enum class Group(override val displayName: String) : NamedEnum { Build("Build"), Break("Break"), @@ -65,12 +65,12 @@ open class AutomationConfig( companion object { context(module: Module) fun automationConfig(name: String = module.name, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = - AutomationConfig(name).apply { edits?.invoke(this) } + AutomationConfig("$name Automation Config").apply { edits?.invoke(this) } fun automationConfig(name: String, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = - AutomationConfig(name).apply { edits?.invoke(this) } + AutomationConfig("$name Automation Config").apply { edits?.invoke(this) } - object DEFAULT : AutomationConfig("Default") { + object DEFAULT : AutomationConfig("Default Automation Config") { val renders by setting("Render", false).group(Group.Render) val avoidDesync by setting("Avoid Desync", true, "Cancels incoming inventory update packets if they match previous actions").group(Group.Debug) val desyncTimeout by setting("Desync Timeout", 30, 1..30, 1, unit = " ticks", description = "Time to store previous inventory actions before dropping the cache") { avoidDesync }.group(Group.Debug) diff --git a/src/main/kotlin/com/lambda/config/Configuration.kt b/src/main/kotlin/com/lambda/config/Configuration.kt index a4d4aef09..e091e2d07 100644 --- a/src/main/kotlin/com/lambda/config/Configuration.kt +++ b/src/main/kotlin/com/lambda/config/Configuration.kt @@ -26,6 +26,7 @@ import com.lambda.Lambda.LOG import com.lambda.Lambda.gson import com.lambda.config.Configuration.Companion.configurables import com.lambda.config.configurations.ModuleConfigs +import com.lambda.core.Loadable import com.lambda.event.events.ClientEvent import com.lambda.event.listener.UnsafeListener.Companion.listenUnsafe import com.lambda.threading.runIO @@ -54,7 +55,8 @@ import kotlin.time.Duration.Companion.minutes * @property primary The primary file where the configuration is saved. * @property configurables A set of [Configurable] objects that this configuration manages. */ -abstract class Configuration : Jsonable { +abstract class Configuration : Jsonable, Loadable { + override val priority = 1 abstract val configName: String abstract val primary: File @@ -62,10 +64,10 @@ abstract class Configuration : Jsonable { private val backup: File get() = File("${primary.parent}/${primary.nameWithoutExtension}-backup.${primary.extension}") - init { + override fun load(): String { listenUnsafe(Int.MIN_VALUE) { trySave() } - register() + return super.load() } // Avoid context-leaking warning @@ -95,7 +97,7 @@ abstract class Configuration : Jsonable { } } - fun save() = runCatching { + private fun save() = runCatching { primary.createIfNotExists() .let { it.writeText(gson.toJson(toJson())) @@ -107,12 +109,12 @@ abstract class Configuration : Jsonable { * Loads the config from the [file] * Encapsulates [JsonIOException] and [JsonSyntaxException] in a runCatching block */ - fun load(file: File) = runCatching { + private fun load(file: File) = runCatching { file.ifNotExists { LOG.warn("No configuration file found for ${configName.capitalize()}. Creating new file when saving.") } .ifExists { loadFromJson(JsonParser.parseReader(it.reader()).asJsonObject) } } - fun tryLoad() = runIO { + open fun tryLoad() = runIO { load(primary) .onSuccess { val message = "${configName.capitalize()} config loaded." @@ -135,7 +137,7 @@ abstract class Configuration : Jsonable { } } - fun trySave(logToChat: Boolean = false) = runIO { + open fun trySave(logToChat: Boolean = false) = runIO { save() .onSuccess { val message = "Saved ${configName.capitalize()} config." diff --git a/src/main/kotlin/com/lambda/config/DynamicConfiguration.kt b/src/main/kotlin/com/lambda/config/DynamicConfiguration.kt new file mode 100644 index 000000000..42f6b4fc7 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/DynamicConfiguration.kt @@ -0,0 +1,57 @@ +/* + * 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 kotlinx.coroutines.Job + +abstract class DynamicConfiguration : Configuration() { + private val preLoadListeners = mutableListOf<() -> Unit>() + private val postLoadListeners = mutableListOf<() -> Unit>() + private val preSaveListeners = mutableListOf<() -> Unit>() + private val postSaveListeners = mutableListOf<() -> Unit>() + + override fun tryLoad(): Job { + preLoadListeners.forEach { it() } + return super.tryLoad().also { job -> + job.invokeOnCompletion { postLoadListeners.forEach { it() } } + } + } + + override fun trySave(logToChat: Boolean): Job { + preSaveListeners.forEach { it() } + return super.trySave(logToChat).also { job -> + job.invokeOnCompletion { postSaveListeners.forEach { it() } } + } + } + + fun onPreLoad(block: () -> Unit) { + preLoadListeners.add(block) + } + + fun onPostLoad(block: () -> Unit) { + postLoadListeners.add(block) + } + + fun onPreSave(block: () -> Unit) { + preSaveListeners.add(block) + } + + fun onPostSave(block: () -> Unit) { + postSaveListeners.add(block) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/context/MutableAutomationConfig.kt b/src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt similarity index 96% rename from src/main/kotlin/com/lambda/context/MutableAutomationConfig.kt rename to src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt index 150327fcf..58a90eea8 100644 --- a/src/main/kotlin/com/lambda/context/MutableAutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt @@ -15,10 +15,11 @@ * along with this program. If not, see . */ -package com.lambda.context +package com.lambda.config import com.lambda.config.groups.BuildConfig import com.lambda.config.groups.EatConfig +import com.lambda.context.Automated import com.lambda.interaction.request.breaking.BreakConfig import com.lambda.interaction.request.hotbar.HotbarConfig import com.lambda.interaction.request.interacting.InteractConfig diff --git a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt new file mode 100644 index 000000000..cdf19707e --- /dev/null +++ b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt @@ -0,0 +1,31 @@ +/* + * 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.lambda.config.configurations.UserAutomationConfigs +import com.lambda.module.ModuleRegistry.moduleNameMap + +class UserAutomationConfig(override val name: String) : AutomationConfig(name, UserAutomationConfigs) { + val linkedModules = setting("Linked Modules", moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys, emptySet()) + .onSelect { module -> moduleNameMap[module]?.automationConfig = this@UserAutomationConfig } + .onDeselect { module -> + moduleNameMap[module]?.let { module -> + module.automationConfig = module.defaultAutomationConfig + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/configurations/ConfigLoader.kt b/src/main/kotlin/com/lambda/config/configurations/ConfigLoader.kt index 4b7e36e27..dcab2af48 100644 --- a/src/main/kotlin/com/lambda/config/configurations/ConfigLoader.kt +++ b/src/main/kotlin/com/lambda/config/configurations/ConfigLoader.kt @@ -21,6 +21,7 @@ import com.lambda.config.Configuration import com.lambda.core.Loadable object ConfigLoader: Loadable { + override val priority = 0 override fun load(): String { Configuration.configurations.forEach { it.tryLoad() diff --git a/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt b/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt new file mode 100644 index 000000000..fd4d6b9ba --- /dev/null +++ b/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt @@ -0,0 +1,53 @@ +/* + * 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.configurations + +import com.google.gson.JsonParser +import com.lambda.config.DynamicConfiguration +import com.lambda.config.UserAutomationConfig +import com.lambda.module.ModuleRegistry.moduleNameMap +import com.lambda.util.FileUtils.ifExists +import com.lambda.util.FolderRegister +import java.io.File + +object UserAutomationConfigs : DynamicConfiguration() { + override val configName = "custom-automation" + override val primary: File = FolderRegister.config.resolve("${configName}.json").toFile() + + override fun load(): String { + onPreLoad { + primary.ifExists { + JsonParser.parseReader(it.reader()).asJsonObject.entrySet().forEach { (name, _) -> + if (configurables.any { config -> config.name == name }) return@forEach + UserAutomationConfig(name) + } + } + } + + onPostLoad { + configurables.forEach { + val config = it as? UserAutomationConfig ?: throw IllegalStateException("UserAutomationConfigs contains non-AutomationConfig") + config.linkedModules.value.forEach { moduleName -> + moduleNameMap[moduleName]?.automationConfig = config + } + } + } + + return super.load() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt index 15c40fa22..65c58f7e4 100644 --- a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt @@ -33,7 +33,7 @@ open class BreakSettings( baseGroup: NamedEnum, vis: () -> Boolean = { true }, ) : BreakConfig { - enum class Group(override val displayName: String) : NamedEnum { + private enum class Group(override val displayName: String) : NamedEnum { General("General"), Cosmetic("Cosmetic") } diff --git a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt index 00ccc6c43..cbab36202 100644 --- a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt @@ -19,7 +19,7 @@ package com.lambda.config.settings import com.google.gson.reflect.TypeToken import com.lambda.config.AbstractSetting -import com.lambda.context.AutomationConfig +import com.lambda.config.AutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import imgui.ImGui import imgui.ImGui.calcTextSize diff --git a/src/main/kotlin/com/lambda/config/settings/StringSetting.kt b/src/main/kotlin/com/lambda/config/settings/StringSetting.kt index cabf6ac68..90022880e 100644 --- a/src/main/kotlin/com/lambda/config/settings/StringSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/StringSetting.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.AbstractSetting -import com.lambda.context.AutomationConfig +import com.lambda.config.AutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import imgui.flag.ImGuiInputTextFlags diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt index d38326dd8..9bde358c3 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt @@ -21,8 +21,10 @@ import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson import com.lambda.config.AbstractSetting -import com.lambda.context.AutomationConfig +import com.lambda.config.AutomationConfig +import com.lambda.context.SafeContext import com.lambda.gui.dsl.ImGuiBuilder +import com.lambda.threading.runSafe import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -43,6 +45,8 @@ class ListSetting( description, visibility ) { + private val selectListeners = mutableListOf Unit>() + private val deselectListeners = mutableListOf Unit>() private val strListType = TypeToken.getParameterized(MutableList::class.java, String::class.java).type @@ -55,7 +59,15 @@ class ListSetting( selectable( it.toString(), isSelected, flags = DontClosePopups - ) { if (isSelected) value.remove(it) else value.add(it) } + ) { + if (isSelected) { + value.remove(it) + runSafe { deselectListeners.forEach { listener -> listener(it) } } + } else { + value.add(it) + runSafe { selectListeners.forEach { listener -> listener(it) } } + } + } } } } @@ -74,6 +86,14 @@ class ListSetting( value = strList } + fun onSelect(block: SafeContext.(T) -> Unit) = apply { + selectListeners.add(block) + } + + fun onDeselect(block: SafeContext.(T) -> Unit) = apply { + deselectListeners.add(block) + } + companion object { @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") diff --git a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt index 74e202b12..de93b5958 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt @@ -21,8 +21,10 @@ import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson import com.lambda.config.AbstractSetting -import com.lambda.context.AutomationConfig +import com.lambda.config.AutomationConfig +import com.lambda.context.SafeContext import com.lambda.gui.dsl.ImGuiBuilder +import com.lambda.threading.runSafe import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -43,6 +45,8 @@ class SetSetting( description, visibility ) { + private val selectListeners = mutableListOf Unit>() + private val deselectListeners = mutableListOf Unit>() private val strSetType = TypeToken.getParameterized(Set::class.java, String::class.java).type @@ -55,8 +59,15 @@ class SetSetting( selectable( it.toString(), isSelected, flags = DontClosePopups - ) - { if (isSelected) value.remove(it) else value.add(it) } + ) { + if (isSelected) { + value.remove(it) + runSafe { deselectListeners.forEach { listener -> listener(it) } } + } else { + value.add(it) + runSafe { selectListeners.forEach { listener -> listener(it) } } + } + } } } } @@ -75,6 +86,14 @@ class SetSetting( value = strSet } + fun onSelect(block: SafeContext.(T) -> Unit) = apply { + selectListeners.add(block) + } + + fun onDeselect(block: SafeContext.(T) -> Unit) = apply { + deselectListeners.add(block) + } + companion object { @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") diff --git a/src/main/kotlin/com/lambda/gui/MenuBar.kt b/src/main/kotlin/com/lambda/gui/MenuBar.kt index d4b86e217..a3470e36c 100644 --- a/src/main/kotlin/com/lambda/gui/MenuBar.kt +++ b/src/main/kotlin/com/lambda/gui/MenuBar.kt @@ -22,6 +22,8 @@ import com.lambda.Lambda.REPO_URL import com.lambda.Lambda.mc import com.lambda.command.CommandRegistry import com.lambda.config.Configuration +import com.lambda.config.UserAutomationConfig +import com.lambda.config.configurations.UserAutomationConfigs import com.lambda.core.Loader import com.lambda.event.EventFlow import com.lambda.graphics.texture.TextureOwner.upload @@ -33,6 +35,7 @@ import com.lambda.gui.components.SettingsWidget.buildConfigSettingsContext import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.interaction.BaritoneManager import com.lambda.module.ModuleRegistry +import com.lambda.module.ModuleRegistry.moduleNameMap import com.lambda.module.tag.ModuleTag import com.lambda.network.LambdaAPI import com.lambda.threading.runSafe @@ -46,6 +49,7 @@ import imgui.ImGui.closeCurrentPopup import imgui.flag.ImGuiCol import imgui.flag.ImGuiStyleVar import imgui.flag.ImGuiWindowFlags +import imgui.type.ImString import net.fabricmc.loader.api.FabricLoader import net.minecraft.util.Util import net.minecraft.world.GameMode @@ -53,6 +57,7 @@ import java.util.* object MenuBar { private var aboutRequested = false + val newConfigName = ImString() val headerLogo = upload("textures/lambda_text_color.png") val lambdaLogo = upload("textures/lambda.png") val githubLogo = upload("textures/github_logo.png") @@ -67,6 +72,7 @@ object MenuBar { menu("HUD") { buildHudMenu() } menu("GUI") { buildGuiMenu() } menu("Modules") { buildModulesMenu() } + menu("Automation Presets") { buildConfigPresetsMenu() } menu("Minecraft") { buildMinecraftMenu() } menu("Help") { buildHelpMenu() } buildGitHubReference() @@ -275,6 +281,45 @@ object MenuBar { } } + private fun ImGuiBuilder.buildConfigPresetsMenu() { + button("New Config") { ImGui.openPopup("##new-config") } + + popupContextWindow("##new-config") { + inputText("Name", newConfigName) + button("Create") { + if (newConfigName.isEmpty) return@button + UserAutomationConfig(newConfigName.get()) + newConfigName.clear() + closeCurrentPopup() + return@button + } + sameLine() + button("Cancel") { + newConfigName.clear() + closeCurrentPopup() + } + } + + UserAutomationConfigs.configurables.forEach { config -> + if (config !is UserAutomationConfig) throw java.lang.IllegalStateException("All configurables within UserAutomationConfigs must be UserAutomationConfigs!") + selectable(config.name) + + popupContextItem("##automation-config-popup-${config.name}") { + with(config.linkedModules) { buildLayout() } + button("Delete") { + config.linkedModules.value.forEach { + moduleNameMap[it]?.let { module -> + module.automationConfig = module.defaultAutomationConfig + } + } + UserAutomationConfigs.configurables.remove(config) + } + separator() + buildConfigSettingsContext(config) + } + } + } + private fun ImGuiBuilder.buildMinecraftMenu() { menu("Open Folder") { menuItem("Open Minecraft Folder") { diff --git a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt index 5214cb864..52bea1aa3 100644 --- a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt +++ b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt @@ -18,8 +18,10 @@ package com.lambda.gui.components import com.lambda.config.AbstractSetting +import com.lambda.config.AutomationConfig import com.lambda.config.Configurable -import com.lambda.context.MutableAutomationConfig +import com.lambda.config.MutableAutomationConfig +import com.lambda.config.UserAutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.module.Module import com.lambda.util.NamedEnum @@ -40,18 +42,24 @@ object SettingsWidget { config.settings.forEach { it.reset(silent = true) } } lambdaTooltip("Resets all settings for this module to their default values") - if (config is MutableAutomationConfig) { + if (config is MutableAutomationConfig && config.automationConfig !== AutomationConfig.Companion.DEFAULT) { button("Automation Config") + sameLine() + if (config.automationConfig !== config.defaultAutomationConfig) { + text("(${config.automationConfig.name})") + } popupContextItem("##automation-config-popup-${config.name}") { - if (config.automationConfig !== config.defaultAutomationConfig) { - text("Linked to the ${config.automationConfig.name} configuration") - } buildConfigSettingsContext(config.automationConfig) } } } separator() - val toIgnoreSettings = if (config is Module) setOf(config.keybindSetting, config.disableOnReleaseSetting) else emptySet() + val toIgnoreSettings = + when (config) { + is Module -> setOf(config.keybindSetting, config.disableOnReleaseSetting) + is UserAutomationConfig -> setOf(config.linkedModules) + else -> emptySet() + } val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() } ungrouped.forEach { diff --git a/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt b/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt index b9e352a1e..16275ef85 100644 --- a/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt +++ b/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt @@ -25,7 +25,7 @@ import com.lambda.config.Configurable import com.lambda.config.configurations.LambdaConfig import com.lambda.config.groups.RotationSettings import com.lambda.context.Automated -import com.lambda.context.AutomationConfig +import com.lambda.config.AutomationConfig import com.lambda.util.BlockUtils.blockPos import com.lambda.util.NamedEnum diff --git a/src/main/kotlin/com/lambda/interaction/construction/simulation/Sim.kt b/src/main/kotlin/com/lambda/interaction/construction/simulation/Sim.kt index e41d62ad4..3f8e4a0f7 100644 --- a/src/main/kotlin/com/lambda/interaction/construction/simulation/Sim.kt +++ b/src/main/kotlin/com/lambda/interaction/construction/simulation/Sim.kt @@ -17,7 +17,7 @@ package com.lambda.interaction.construction.simulation -import com.lambda.context.AutomationConfig +import com.lambda.config.AutomationConfig import com.lambda.interaction.construction.processing.PreProcessingInfo import com.lambda.interaction.construction.result.BuildResult import com.lambda.interaction.construction.result.results.GenericResult diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/BrokenBlockHandler.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/BrokenBlockHandler.kt index 1213e8c04..da3716135 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/BrokenBlockHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/BrokenBlockHandler.kt @@ -17,7 +17,7 @@ package com.lambda.interaction.request.breaking -import com.lambda.context.AutomationConfig.Companion.DEFAULT +import com.lambda.config.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.event.events.EntityEvent import com.lambda.event.events.WorldEvent diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt index f77f72a8e..5e76c303e 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt @@ -18,7 +18,7 @@ package com.lambda.interaction.request.breaking import com.lambda.context.Automated -import com.lambda.context.AutomationConfig.Companion.DEFAULT +import com.lambda.config.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.interaction.request.LogContext import com.lambda.interaction.request.LogContext.Companion.LogContextBuilder diff --git a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractedBlockHandler.kt b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractedBlockHandler.kt index fecf0f0a4..6c5d7a253 100644 --- a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractedBlockHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractedBlockHandler.kt @@ -18,7 +18,7 @@ package com.lambda.interaction.request.interacting import com.lambda.Lambda.mc -import com.lambda.context.AutomationConfig.Companion.DEFAULT +import com.lambda.config.AutomationConfig.Companion.DEFAULT import com.lambda.event.events.WorldEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.construction.processing.ProcessorRegistry diff --git a/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt b/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt index 0397d9bbf..f600b3c26 100644 --- a/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt @@ -18,7 +18,7 @@ package com.lambda.interaction.request.inventory import com.lambda.context.AutomatedSafeContext -import com.lambda.context.AutomationConfig.Companion.DEFAULT +import com.lambda.config.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.event.EventFlow.post import com.lambda.event.events.TickEvent diff --git a/src/main/kotlin/com/lambda/interaction/request/placing/PlacedBlockHandler.kt b/src/main/kotlin/com/lambda/interaction/request/placing/PlacedBlockHandler.kt index 60628d051..3b029f327 100644 --- a/src/main/kotlin/com/lambda/interaction/request/placing/PlacedBlockHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/placing/PlacedBlockHandler.kt @@ -17,7 +17,7 @@ package com.lambda.interaction.request.placing -import com.lambda.context.AutomationConfig.Companion.DEFAULT +import com.lambda.config.AutomationConfig.Companion.DEFAULT import com.lambda.event.events.WorldEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.construction.processing.ProcessorRegistry diff --git a/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/VisibilityChecker.kt b/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/VisibilityChecker.kt index 03a8c093b..add56d6f7 100644 --- a/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/VisibilityChecker.kt +++ b/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/VisibilityChecker.kt @@ -18,7 +18,7 @@ package com.lambda.interaction.request.rotating.visibilty import com.lambda.context.AutomatedSafeContext -import com.lambda.context.AutomationConfig.Companion.DEFAULT +import com.lambda.config.AutomationConfig.Companion.DEFAULT import com.lambda.interaction.construction.verify.ScanMode import com.lambda.interaction.construction.verify.SurfaceScan import com.lambda.interaction.request.rotating.Rotation diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index 45a70f5ed..2c6dd6625 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -20,12 +20,12 @@ package com.lambda.module import com.lambda.Lambda import com.lambda.command.LambdaCommand import com.lambda.config.AbstractSetting +import com.lambda.config.AutomationConfig import com.lambda.config.Configurable import com.lambda.config.Configuration +import com.lambda.config.MutableAutomationConfig import com.lambda.config.configurations.ModuleConfigs import com.lambda.config.settings.complex.Bind -import com.lambda.context.AutomationConfig -import com.lambda.context.MutableAutomationConfig import com.lambda.context.SafeContext import com.lambda.event.Muteable import com.lambda.event.events.ClientEvent @@ -121,12 +121,12 @@ abstract class Module( defaultKeybind: Bind = Bind.EMPTY, autoDisable: Boolean = false ) : Nameable, Muteable, Configurable(ModuleConfigs), MutableAutomationConfig { - override var defaultAutomationConfig: AutomationConfig = AutomationConfig.Companion.DEFAULT + final override var defaultAutomationConfig: AutomationConfig = AutomationConfig.Companion.DEFAULT set(value) { field = value automationConfig = value } - override var automationConfig = defaultAutomationConfig + final override var automationConfig = defaultAutomationConfig 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/ModuleRegistry.kt b/src/main/kotlin/com/lambda/module/ModuleRegistry.kt index d0d0dd3d4..47095da76 100644 --- a/src/main/kotlin/com/lambda/module/ModuleRegistry.kt +++ b/src/main/kotlin/com/lambda/module/ModuleRegistry.kt @@ -26,7 +26,7 @@ object ModuleRegistry : Loadable { val modules = getInstances() .sortedBy { it.name } - val moduleNames = modules.map { it.name }.toSet() + val moduleNameMap = modules.associateBy { it.name } override fun load() = "Loaded ${modules.size} modules with ${modules.sumOf { it.settings.size }} settings" diff --git a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt index 171de3245..c5c788d2a 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt @@ -17,7 +17,7 @@ package com.lambda.module.modules.player -import com.lambda.context.AutomationConfig.Companion.automationConfig +import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.event.events.PlayerEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.construction.context.BreakContext 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 91346eacb..43c5e8242 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt @@ -17,9 +17,8 @@ package com.lambda.module.modules.player -import com.lambda.config.groups.BreakSettings.Group +import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.config.groups.BuildConfig -import com.lambda.context.AutomationConfig.Companion.automationConfig import com.lambda.context.SafeContext import com.lambda.event.events.PlayerEvent import com.lambda.event.events.TickEvent @@ -53,6 +52,11 @@ object PacketMine : Module( description = "automatically breaks blocks, and does it faster", tag = ModuleTag.PLAYER ) { + private enum class Group(override val displayName: String) : NamedEnum { + General("General"), + Renders("Renders") + } + private val rebreakMode by setting("Rebreak Mode", RebreakMode.Manual, "The method used to re-break blocks after they've been broken once").disabled { !breakConfig.rebreak }.group(Group.General) private val breakRadius by setting("Break Radius", 0, 0..5, 1, "Selects and breaks all blocks within the break radius of the selected block").group(Group.General) private val flatten by setting("Flatten", true, "Wont allow breaking extra blocks under your players position") { breakRadius > 0 }.group(Group.General) @@ -60,13 +64,13 @@ object PacketMine : Module( .onValueChange { _, to -> if (!to) queuePositions.clear() } private val queueOrder by setting("Queue Order", QueueOrder.Standard, "Which end of the queue to break blocks from") { queue }.group(Group.General) - private val renderQueue by setting("Render Queue", true, "Adds renders to signify what block positions are queued").disabled { !breakConfig.renders }.group(Group.Cosmetic) - private val renderSize by setting("Render Size", 0.3f, 0.01f..1f, 0.01f, "The scale of the queue renders") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Cosmetic) - private val renderMode by setting("Render Mode", RenderMode.State, "The style of the queue renders") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Cosmetic) - private val dynamicColor by setting("Dynamic Color", true, "Interpolates the color between start and end") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Cosmetic) - private val staticColor by setting("Color", Color(255, 0, 0, 60).brighter()) { renderQueue && !dynamicColor }.disabled { !breakConfig.renders }.group(Group.Cosmetic) - private val startColor by setting("Start Color", Color(255, 255, 0, 60).brighter(), "The color of the start (closest to breaking) of the queue") { renderQueue && dynamicColor }.disabled { !breakConfig.renders }.group(Group.Cosmetic) - private val endColor by setting("End Color", Color(255, 0, 0, 60).brighter(), "The color of the end (farthest from breaking) of the queue") { renderQueue && dynamicColor }.disabled { !breakConfig.renders }.group(Group.Cosmetic) + private val renderQueue by setting("Render Queue", true, "Adds renders to signify what block positions are queued").disabled { !breakConfig.renders }.group(Group.Renders) + private val renderSize by setting("Render Size", 0.3f, 0.01f..1f, 0.01f, "The scale of the queue renders") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Renders) + private val renderMode by setting("Render Mode", RenderMode.State, "The style of the queue renders") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Renders) + private val dynamicColor by setting("Dynamic Color", true, "Interpolates the color between start and end") { renderQueue }.disabled { !breakConfig.renders }.group(Group.Renders) + private val staticColor by setting("Color", Color(255, 0, 0, 60).brighter()) { renderQueue && !dynamicColor }.disabled { !breakConfig.renders }.group(Group.Renders) + private val startColor by setting("Start Color", Color(255, 255, 0, 60).brighter(), "The color of the start (closest to breaking) of the queue") { renderQueue && dynamicColor }.disabled { !breakConfig.renders }.group(Group.Renders) + private val endColor by setting("End Color", Color(255, 0, 0, 60).brighter(), "The color of the end (farthest from breaking) of the queue") { renderQueue && dynamicColor }.disabled { !breakConfig.renders }.group(Group.Renders) private val pendingInteractions = ConcurrentLinkedQueue() diff --git a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt index c7297454b..af1ce67dc 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt @@ -19,7 +19,7 @@ package com.lambda.module.modules.player import com.lambda.config.groups.BuildConfig import com.lambda.config.settings.complex.Bind -import com.lambda.context.AutomationConfig.Companion.automationConfig +import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.context.SafeContext import com.lambda.event.events.MovementEvent import com.lambda.event.events.TickEvent diff --git a/src/main/kotlin/com/lambda/task/Task.kt b/src/main/kotlin/com/lambda/task/Task.kt index 70078999b..1f07279f1 100644 --- a/src/main/kotlin/com/lambda/task/Task.kt +++ b/src/main/kotlin/com/lambda/task/Task.kt @@ -18,7 +18,7 @@ package com.lambda.task import com.lambda.Lambda.LOG -import com.lambda.context.AutomationConfig.Companion.DEFAULT +import com.lambda.config.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.event.EventFlow.unsubscribe import com.lambda.event.Muteable diff --git a/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt b/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt index 50c499bd9..5aafe9615 100644 --- a/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt +++ b/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt @@ -21,7 +21,7 @@ import baritone.api.pathing.goals.GoalBlock import com.lambda.Lambda.LOG import com.lambda.config.groups.EatConfig.Companion.reasonEating import com.lambda.context.Automated -import com.lambda.context.AutomationConfig.Companion.DEFAULT +import com.lambda.config.AutomationConfig.Companion.DEFAULT import com.lambda.context.SafeContext import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen From 90d041baf0ce641806c1ee1c1a6dc7013463d55a Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sat, 22 Nov 2025 21:49:14 +0000 Subject: [PATCH 04/12] check that no configurables already have the entered name --- src/main/kotlin/com/lambda/gui/MenuBar.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/lambda/gui/MenuBar.kt b/src/main/kotlin/com/lambda/gui/MenuBar.kt index a3470e36c..1c454f93e 100644 --- a/src/main/kotlin/com/lambda/gui/MenuBar.kt +++ b/src/main/kotlin/com/lambda/gui/MenuBar.kt @@ -22,6 +22,7 @@ import com.lambda.Lambda.REPO_URL import com.lambda.Lambda.mc import com.lambda.command.CommandRegistry import com.lambda.config.Configuration +import com.lambda.config.Configuration.Companion.configurables import com.lambda.config.UserAutomationConfig import com.lambda.config.configurations.UserAutomationConfigs import com.lambda.core.Loader @@ -287,7 +288,7 @@ object MenuBar { popupContextWindow("##new-config") { inputText("Name", newConfigName) button("Create") { - if (newConfigName.isEmpty) return@button + if (newConfigName.isEmpty && configurables.none { it.name == newConfigName.get() }) return@button UserAutomationConfig(newConfigName.get()) newConfigName.clear() closeCurrentPopup() From 1c9626e39ac6494b4b74bf9c9690f01f5740f59b Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sat, 22 Nov 2025 23:17:43 +0000 Subject: [PATCH 05/12] setting group hiding --- .../com/lambda/config/AutomationConfig.kt | 50 ++++----- .../kotlin/com/lambda/config/SettingGroup.kt | 27 +++++ .../com/lambda/config/groups/BreakSettings.kt | 104 +++++++++--------- .../com/lambda/config/groups/BuildSettings.kt | 32 +++--- .../com/lambda/config/groups/EatSettings.kt | 30 ++--- .../lambda/config/groups/HotbarSettings.kt | 16 +-- .../lambda/config/groups/InteractSettings.kt | 18 +-- .../lambda/config/groups/InventorySettings.kt | 26 ++--- .../com/lambda/config/groups/PlaceSettings.kt | 28 ++--- .../lambda/config/groups/RotationSettings.kt | 18 +-- .../com/lambda/config/groups/Targeting.kt | 40 ++++--- .../lambda/module/modules/combat/KillAura.kt | 5 +- .../module/modules/debug/RotationTest.kt | 3 +- .../lambda/module/modules/player/FastBreak.kt | 1 + .../module/modules/player/PacketMine.kt | 18 +-- .../lambda/module/modules/player/Scaffold.kt | 3 +- 16 files changed, 217 insertions(+), 202 deletions(-) create mode 100644 src/main/kotlin/com/lambda/config/SettingGroup.kt diff --git a/src/main/kotlin/com/lambda/config/AutomationConfig.kt b/src/main/kotlin/com/lambda/config/AutomationConfig.kt index f09e6d2f7..395badfea 100644 --- a/src/main/kotlin/com/lambda/config/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/AutomationConfig.kt @@ -102,18 +102,18 @@ open class AutomationConfig( } @SettingEditorDsl - internal inline fun KProperty0.edit(edits: FullEditBuilder.(AbstractSetting) -> Unit) { + internal inline fun KProperty0.edit(edits: TypedEditBuilder.(AbstractSetting) -> Unit) { val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") - FullEditBuilder(setting, this@AutomationConfig).edits(setting) + TypedEditBuilder(listOf(setting), this@AutomationConfig).edits(setting) } @SettingEditorDsl - internal inline fun KProperty0.editWith( - other: KProperty0<*>, - edits: FullEditBuilder.(AbstractSetting<*>) -> Unit + internal inline fun KProperty0.editWith( + other: KProperty0, + edits: TypedEditBuilder.(AbstractSetting) -> Unit ) { val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") - FullEditBuilder(setting, this@AutomationConfig).edits(other.delegate as AbstractSetting<*>) + TypedEditBuilder(listOf(setting), this@AutomationConfig).edits(other.delegate as AbstractSetting) } @SettingEditorDsl @@ -123,11 +123,11 @@ open class AutomationConfig( ) { BasicEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List>).apply(edits) } @SettingEditorDsl - fun editWith( + internal inline fun editWith( vararg settings: KProperty0<*>, - other: KProperty0<*>, - edits: BasicEditBuilder.(AbstractSetting<*>) -> Unit - ) { BasicEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List>).edits(other.delegate as AbstractSetting<*>) } + other: KProperty0, + edits: BasicEditBuilder.(AbstractSetting) -> Unit + ) { BasicEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List>).edits(other.delegate as AbstractSetting) } @SettingEditorDsl internal inline fun editTyped( @@ -146,6 +146,21 @@ open class AutomationConfig( fun hide(vararg settings: KProperty0<*>) = this@AutomationConfig.settings.removeAll(settings.map { it.delegate } as List>) + @SettingEditorDsl + fun hideAll(settingGroup: SettingGroup) { + settings.removeAll(settingGroup.settings) + } + + @SettingEditorDsl + fun hideAll(vararg settingGroups: SettingGroup) { + settings.removeAll(settingGroups.flatMap { it.settings }) + } + + @SettingEditorDsl + fun hideAllExcept(settingGroup: SettingGroup, vararg settings: KProperty0<*>) { + this@AutomationConfig.settings.removeIf { it in settingGroup.settings && it !in (settings.toList() as List>) } + } + open class BasicEditBuilder(val c: Configurable, open val settings: Collection>) { @SettingEditorDsl fun visibility(vis: () -> Boolean) = @@ -177,21 +192,6 @@ open class AutomationConfig( } } - class FullEditBuilder( - private val setting: AbstractSetting, - c: Configurable - ) : TypedEditBuilder(setOf(setting), c) { - @SettingEditorDsl - fun name(name: String) { - setting.name = name - } - - @SettingEditorDsl - fun description(description: String) { - setting.description = description - } - } - enum class InsertMode { Above, Below diff --git a/src/main/kotlin/com/lambda/config/SettingGroup.kt b/src/main/kotlin/com/lambda/config/SettingGroup.kt new file mode 100644 index 000000000..4ea5b79f7 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/SettingGroup.kt @@ -0,0 +1,27 @@ +/* + * 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 + +abstract class SettingGroup() { + val settings = mutableListOf>() + + fun AbstractSetting.index(): AbstractSetting { + settings.add(this) + return this + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt index 65c58f7e4..8560066b8 100644 --- a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt @@ -18,6 +18,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent import com.lambda.interaction.request.breaking.BreakConfig import com.lambda.interaction.request.breaking.BreakConfig.AnimationMode @@ -31,83 +32,86 @@ import java.awt.Color open class BreakSettings( c: Configurable, baseGroup: NamedEnum, - vis: () -> Boolean = { true }, -) : BreakConfig { +) : SettingGroup(), BreakConfig { private enum class Group(override val displayName: String) : NamedEnum { General("General"), Cosmetic("Cosmetic") } // General - override val breakMode by c.setting("Break Mode", BreakMode.Packet, visibility = vis).group(baseGroup, Group.General) - override val sorter by c.setting("Break Sorter", ActionConfig.SortMode.Tool, "The order in which breaks are performed", visibility = vis).group(baseGroup, Group.General) - override val rebreak by c.setting("Rebreak", true, "Re-breaks blocks after they've been broken once", visibility = vis).group(baseGroup, Group.General) + override val breakMode by c.setting("Break Mode", BreakMode.Packet).group(baseGroup, Group.General).index() + override val sorter by c.setting("Break Sorter", ActionConfig.SortMode.Tool, "The order in which breaks are performed").group(baseGroup, Group.General).index() + override val rebreak by c.setting("Rebreak", true, "Re-breaks blocks after they've been broken once").group(baseGroup, Group.General).index() // Double break - override val doubleBreak by c.setting("Double Break", true, "Allows breaking two blocks at once", visibility = vis).group(baseGroup, Group.General) - override val unsafeCancels by c.setting("Unsafe Cancels", true, "Allows cancelling block breaking even if the server might continue breaking sever side, potentially causing unexpected state changes", visibility = vis).group(baseGroup, Group.General) + override val doubleBreak by c.setting("Double Break", true, "Allows breaking two blocks at once").group(baseGroup, Group.General).index() + override val unsafeCancels by c.setting("Unsafe Cancels", true, "Allows cancelling block breaking even if the server might continue breaking sever side, potentially causing unexpected state changes").group(baseGroup, Group.General).index() // Fixes / Delays - override val breakThreshold by c.setting("Break Threshold", 0.70f, 0.1f..1.0f, 0.01f, "The break amount at which the block is considered broken", visibility = vis).group(baseGroup, Group.General) - override val fudgeFactor by c.setting("Fudge Factor", 1, 0..5, 1, "The number of ticks to add to the break time, usually to account for server lag", visibility = vis).group(baseGroup, Group.General) - override val serverSwapTicks by c.setting("Server Swap", 0, 0..5, 1, "The number of ticks to give the server time to recognize the player attributes on the swapped item", " tick(s)", visibility = vis).group(baseGroup, Group.General) -// override val desyncFix by c.setting("Desync Fix", false, "Predicts if the players breaking will be slowed next tick as block break packets are processed using the players next position") { vis() && page == Page.General } - override val breakDelay by c.setting("Break Delay", 0, 0..6, 1, "The delay between breaking blocks", " tick(s)", visibility = vis).group(baseGroup, Group.General) + override val breakThreshold by c.setting("Break Threshold", 0.70f, 0.1f..1.0f, 0.01f, "The break amount at which the block is considered broken").group(baseGroup, Group.General).index() + override val fudgeFactor by c.setting("Fudge Factor", 1, 0..5, 1, "The number of ticks to add to the break time, usually to account for server lag").group(baseGroup, Group.General).index() + override val serverSwapTicks by c.setting("Server Swap", 0, 0..5, 1, "The number of ticks to give the server time to recognize the player attributes on the swapped item", " tick(s)").group(baseGroup, Group.General).index() + + // override val desyncFix by c.setting("Desync Fix", false, "Predicts if the players breaking will be slowed next tick as block break packets are processed using the players next position") { vis() && page == Page.General } + override val breakDelay by c.setting("Break Delay", 0, 0..6, 1, "The delay between breaking blocks", " tick(s)").group(baseGroup, Group.General).index() // Timing - override val tickStageMask by c.setting("Break Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which break actions can be performed", visibility = vis).group(baseGroup, Group.General) + override val tickStageMask by c.setting("Break Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which break actions can be performed").group(baseGroup, Group.General).index() // Swap - override val swapMode by c.setting("Swap Mode", BreakConfig.SwapMode.End, "Decides when to swap to the best suited tool when breaking a block", visibility = vis).group(baseGroup, Group.General) + override val swapMode by c.setting("Swap Mode", BreakConfig.SwapMode.End, "Decides when to swap to the best suited tool when breaking a block").group(baseGroup, Group.General).index() // Swing - override val swing by c.setting("Swing Mode", SwingMode.Constant, "The times at which to swing the players hand", visibility = vis).group(baseGroup, Group.General) - override val swingType by c.setting("Break Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { vis() && swing != SwingMode.None }.group(baseGroup, Group.General) + override val swing by c.setting("Swing Mode", SwingMode.Constant, "The times at which to swing the players hand").group(baseGroup, Group.General).index() + override val swingType by c.setting("Break Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { swing != SwingMode.None }.group(baseGroup, Group.General).index() // Rotate - override val rotateForBreak by c.setting("Rotate For Break", false, "Rotate towards block while breaking", visibility = vis).group(baseGroup, Group.General) + override val rotateForBreak by c.setting("Rotate For Break", false, "Rotate towards block while breaking").group(baseGroup, Group.General).index() // Pending / Post - override val breakConfirmation by c.setting("Break Confirmation", BreakConfirmationMode.BreakThenAwait, "The style of confirmation used when breaking", visibility = vis).group(baseGroup, Group.General) - override val breaksPerTick by c.setting("Breaks Per Tick", 5, 1..30, 1, "Maximum instant block breaks per tick", visibility = vis).group(baseGroup, Group.General) - override val maxPendingBreaks by c.setting("Max Pending Breaks", 15, 1..30, 1, "The maximum amount of pending breaks", visibility = vis).group(baseGroup, Group.General) + override val breakConfirmation by c.setting("Break Confirmation", BreakConfirmationMode.BreakThenAwait, "The style of confirmation used when breaking").group(baseGroup, Group.General).index() + override val breaksPerTick by c.setting("Breaks Per Tick", 5, 1..30, 1, "Maximum instant block breaks per tick").group(baseGroup, Group.General).index() + override val maxPendingBreaks by c.setting("Max Pending Breaks", 15, 1..30, 1, "The maximum amount of pending breaks").group(baseGroup, Group.General).index() // Block - override val avoidLiquids by c.setting("Avoid Liquids", true, "Avoids breaking blocks that would cause liquid to spill", visibility = vis).group(baseGroup, Group.General) - override val avoidSupporting by c.setting("Avoid Supporting", true, "Avoids breaking the block supporting the player", visibility = vis).group(baseGroup, Group.General) - override val ignoredBlocks by c.setting("Ignored Blocks", allSigns, description = "Blocks that wont be broken", visibility = vis).group(baseGroup, Group.General) + override val avoidLiquids by c.setting("Avoid Liquids", true, "Avoids breaking blocks that would cause liquid to spill").group(baseGroup, Group.General).index() + override val avoidSupporting by c.setting("Avoid Supporting", true, "Avoids breaking the block supporting the player").group(baseGroup, Group.General).index() + override val ignoredBlocks by c.setting("Ignored Blocks", allSigns, description = "Blocks that wont be broken").group(baseGroup, Group.General).index() // Tool - override val efficientOnly by c.setting("Efficient Tools Only", true, "Only use tools suitable for the given block (will get the item drop)") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val suitableToolsOnly by c.setting("Suitable Tools Only", true, "Only use tools suitable for the given block (will get the item drop)") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val forceSilkTouch by c.setting("Force Silk Touch", false, "Force silk touch when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val forceFortunePickaxe by c.setting("Force Fortune Pickaxe", false, "Force fortune pickaxe when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val minFortuneLevel by c.setting("Min Fortune Level", 1, 1..3, 1, "The minimum fortune level to use") { vis() && swapMode.isEnabled() && forceFortunePickaxe }.group(baseGroup, Group.General) - override val useWoodenTools by c.setting("Use Wooden Tools", true, "Use wooden tools when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val useStoneTools by c.setting("Use Stone Tools", true, "Use stone tools when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val useIronTools by c.setting("Use Iron Tools", true, "Use iron tools when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val useDiamondTools by c.setting("Use Diamond Tools", true, "Use diamond tools when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val useGoldTools by c.setting("Use Gold Tools", true, "Use gold tools when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) - override val useNetheriteTools by c.setting("Use Netherite Tools", true, "Use netherite tools when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General) + override val efficientOnly by c.setting("Efficient Tools Only", true, "Only use tools suitable for the given block (will get the item drop)") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val suitableToolsOnly by c.setting("Suitable Tools Only", true, "Only use tools suitable for the given block (will get the item drop)") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val forceSilkTouch by c.setting("Force Silk Touch", false, "Force silk touch when breaking blocks") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val forceFortunePickaxe by c.setting("Force Fortune Pickaxe", false, "Force fortune pickaxe when breaking blocks") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val minFortuneLevel by c.setting("Min Fortune Level", 1, 1..3, 1, "The minimum fortune level to use") { swapMode.isEnabled() && forceFortunePickaxe }.group(baseGroup, Group.General).index() + override val useWoodenTools by c.setting("Use Wooden Tools", true, "Use wooden tools when breaking blocks") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val useStoneTools by c.setting("Use Stone Tools", true, "Use stone tools when breaking blocks") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val useIronTools by c.setting("Use Iron Tools", true, "Use iron tools when breaking blocks") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val useDiamondTools by c.setting("Use Diamond Tools", true, "Use diamond tools when breaking blocks") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val useGoldTools by c.setting("Use Gold Tools", true, "Use gold tools when breaking blocks") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() + override val useNetheriteTools by c.setting("Use Netherite Tools", true, "Use netherite tools when breaking blocks") { swapMode.isEnabled() }.group(baseGroup, Group.General).index() // Cosmetics - override val sounds by c.setting("Break Sounds", true, "Plays the breaking sounds", visibility = vis).group(baseGroup, Group.Cosmetic) - override val particles by c.setting("Particles", true, "Renders the breaking particles", visibility = vis).group(baseGroup, Group.Cosmetic) - override val breakingTexture by c.setting("Breaking Overlay", true, "Overlays the breaking texture at its different stages", visibility = vis).group(baseGroup, Group.Cosmetic) + override val sounds by c.setting("Break Sounds", true, "Plays the breaking sounds").group(baseGroup, Group.Cosmetic).index() + override val particles by c.setting("Particles", true, "Renders the breaking particles").group(baseGroup, Group.Cosmetic).index() + override val breakingTexture by c.setting("Breaking Overlay", true, "Overlays the breaking texture at its different stages").group(baseGroup, Group.Cosmetic).index() + // Modes - override val renders by c.setting("Renders", true, "Enables the render settings for breaking progress", visibility = vis).group(baseGroup, Group.Cosmetic) - override val animation by c.setting("Animation", AnimationMode.Out, "The style of animation used for the box") { vis() && renders }.group(baseGroup, Group.Cosmetic) + override val renders by c.setting("Renders", true, "Enables the render settings for breaking progress").group(baseGroup, Group.Cosmetic).index() + override val animation by c.setting("Animation", AnimationMode.Out, "The style of animation used for the box") { renders }.group(baseGroup, Group.Cosmetic).index() + // Fill - override val fill by c.setting("Fill", true, "Renders the sides of the box to display break progress") { vis() && renders }.group(baseGroup, Group.Cosmetic) - override val dynamicFillColor by c.setting("Dynamic Colour", true, "Enables fill color interpolation from start to finish for fill when breaking a block") { vis() && renders && fill }.group(baseGroup, Group.Cosmetic) - override val staticFillColor by c.setting("Fill Color", Color(255, 0, 0, 60).brighter(), "The color of the fill") { vis() && renders && !dynamicFillColor && fill }.group(baseGroup, Group.Cosmetic) - override val startFillColor by c.setting("Start Fill Color", Color(255, 0, 0, 60).brighter(), "The color of the fill at the start of breaking") { vis() && renders && dynamicFillColor && fill }.group(baseGroup, Group.Cosmetic) - override val endFillColor by c.setting("End Fill Color", Color(0, 255, 0, 60).brighter(), "The color of the fill at the end of breaking") { vis() && renders && dynamicFillColor && fill }.group(baseGroup, Group.Cosmetic) + override val fill by c.setting("Fill", true, "Renders the sides of the box to display break progress") { renders }.group(baseGroup, Group.Cosmetic).index() + override val dynamicFillColor by c.setting("Dynamic Colour", true, "Enables fill color interpolation from start to finish for fill when breaking a block") { renders && fill }.group(baseGroup, Group.Cosmetic).index() + override val staticFillColor by c.setting("Fill Color", Color(255, 0, 0, 60).brighter(), "The color of the fill") { renders && !dynamicFillColor && fill }.group(baseGroup, Group.Cosmetic).index() + override val startFillColor by c.setting("Start Fill Color", Color(255, 0, 0, 60).brighter(), "The color of the fill at the start of breaking") { renders && dynamicFillColor && fill }.group(baseGroup, Group.Cosmetic).index() + override val endFillColor by c.setting("End Fill Color", Color(0, 255, 0, 60).brighter(), "The color of the fill at the end of breaking") { renders && dynamicFillColor && fill }.group(baseGroup, Group.Cosmetic).index() + // Outline - override val outline by c.setting("Outline", true, "Renders the lines of the box to display break progress") { vis() && renders }.group(baseGroup, Group.Cosmetic) - override val outlineWidth by c.setting("Outline Width", 2, 0..5, 1, "The width of the outline") { vis() && renders && outline }.group(baseGroup, Group.Cosmetic) - override val dynamicOutlineColor by c.setting("Dynamic Outline Color", true, "Enables color interpolation from start to finish for the outline when breaking a block") { vis() && renders && outline }.group(baseGroup, Group.Cosmetic) - override val staticOutlineColor by c.setting("Outline Color", Color.RED.brighter(), "The Color of the outline at the start of breaking") { vis() && renders && !dynamicOutlineColor && outline }.group(baseGroup, Group.Cosmetic) - override val startOutlineColor by c.setting("Start Outline Color", Color.RED.brighter(), "The color of the outline at the start of breaking") { vis() && renders && dynamicOutlineColor && outline }.group(baseGroup, Group.Cosmetic) - override val endOutlineColor by c.setting("End Outline Color", Color.GREEN.brighter(), "The color of the outline at the end of breaking") { vis() && renders && dynamicOutlineColor && outline }.group(baseGroup, Group.Cosmetic) + override val outline by c.setting("Outline", true, "Renders the lines of the box to display break progress") { renders }.group(baseGroup, Group.Cosmetic).index() + override val outlineWidth by c.setting("Outline Width", 2, 0..5, 1, "The width of the outline") { renders && outline }.group(baseGroup, Group.Cosmetic).index() + override val dynamicOutlineColor by c.setting("Dynamic Outline Color", true, "Enables color interpolation from start to finish for the outline when breaking a block") { renders && outline }.group(baseGroup, Group.Cosmetic).index() + override val staticOutlineColor by c.setting("Outline Color", Color.RED.brighter(), "The Color of the outline at the start of breaking") { renders && !dynamicOutlineColor && outline }.group(baseGroup, Group.Cosmetic).index() + override val startOutlineColor by c.setting("Start Outline Color", Color.RED.brighter(), "The color of the outline at the start of breaking") { renders && dynamicOutlineColor && outline }.group(baseGroup, Group.Cosmetic).index() + override val endOutlineColor by c.setting("End Outline Color", Color.GREEN.brighter(), "The color of the outline at the end of breaking") { renders && dynamicOutlineColor && outline }.group(baseGroup, Group.Cosmetic).index() } diff --git a/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt b/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt index c116b205c..89c3011e9 100644 --- a/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt @@ -18,15 +18,15 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.interaction.request.rotating.visibilty.PointSelection import com.lambda.util.NamedEnum import kotlin.math.max class BuildSettings( c: Configurable, - vararg baseGroup: NamedEnum, - vis: () -> Boolean = { true }, -) : BuildConfig { + baseGroup: NamedEnum, +) : SettingGroup(), BuildConfig { enum class Group(override val displayName: String) : NamedEnum { General("General"), Reach("Reach"), @@ -34,23 +34,23 @@ class BuildSettings( } // General - override val pathing by c.setting("Pathing", true, "Path to blocks", vis).group(*baseGroup, Group.General) - override val stayInRange by c.setting("Stay In Range", true, "Stay in range of blocks", vis).group(*baseGroup, Group.General) - override val collectDrops by c.setting("Collect All Drops", false, "Collect all drops when breaking blocks", vis).group(*baseGroup, Group.General) - override val interactionsPerTick by c.setting("Interactions Per Tick", 5, 1..30, 1, "The amount of interactions that can happen per tick", visibility = vis).group(*baseGroup, Group.General) - override val maxPendingInteractions by c.setting("Max Pending Interactions", 15, 1..30, 1, "The maximum count of pending interactions to allow before pausing future interactions", visibility = vis).group(*baseGroup, Group.General) - override val interactionTimeout by c.setting("Interaction Timeout", 10, 1..30, 1, "Timeout for block breaks in ticks", unit = " ticks", visibility = vis).group(*baseGroup, Group.General) + override val pathing by c.setting("Pathing", true, "Path to blocks").group(baseGroup, Group.General).index() + override val stayInRange by c.setting("Stay In Range", true, "Stay in range of blocks").group(baseGroup, Group.General).index() + override val collectDrops by c.setting("Collect All Drops", false, "Collect all drops when breaking blocks").group(baseGroup, Group.General).index() + override val interactionsPerTick by c.setting("Interactions Per Tick", 5, 1..30, 1, "The amount of interactions that can happen per tick").group(baseGroup, Group.General).index() + override val maxPendingInteractions by c.setting("Max Pending Interactions", 15, 1..30, 1, "The maximum count of pending interactions to allow before pausing future interactions").group(baseGroup, Group.General).index() + override val interactionTimeout by c.setting("Interaction Timeout", 10, 1..30, 1, "Timeout for block breaks in ticks", unit = " ticks").group(baseGroup, Group.General).index() - override val useDefaultReach by c.setting("Default Reach", true, "Whether to use vanilla interaction ranges", vis).group(*baseGroup, Group.Reach) - override val attackReach by c.setting("Attack Reach", DEFAULT_ATTACK_REACH, 1.0..10.0, 0.01, "Maximum entity interaction distance") { vis() && !useDefaultReach }.group(*baseGroup, Group.Reach) - override val interactReach by c.setting("Interact Reach", DEFAULT_INTERACT_REACH, 1.0..10.0, 0.01, "Maximum block interaction distance") { vis() && !useDefaultReach }.group(*baseGroup, Group.Reach) + override val useDefaultReach by c.setting("Default Reach", true, "Whether to use vanilla interaction ranges").group(baseGroup, Group.Reach).index() + override val attackReach by c.setting("Attack Reach", DEFAULT_ATTACK_REACH, 1.0..10.0, 0.01, "Maximum entity interaction distance") { !useDefaultReach }.group(baseGroup, Group.Reach).index() + override val interactReach by c.setting("Interact Reach", DEFAULT_INTERACT_REACH, 1.0..10.0, 0.01, "Maximum block interaction distance") { !useDefaultReach }.group(baseGroup, Group.Reach).index() override val scanReach: Double get() = max(attackReach, interactReach) - override val checkSideVisibility by c.setting("Visibility Check", true, "Whether to check if an AABB side is visible", vis).group(*baseGroup, Group.Scan) - override val strictRayCast by c.setting("Strict Raycast", false, "Whether to include the environment to the ray cast context", vis).group(*baseGroup, Group.Scan) - override val resolution by c.setting("Resolution", 5, 1..20, 1, "The amount of grid divisions per surface of the hit box", "", vis).group(*baseGroup, Group.Scan) - override val pointSelection by c.setting("Point Selection", PointSelection.Optimum, "The strategy to select the best hit point", vis).group(*baseGroup, Group.Scan) + override val checkSideVisibility by c.setting("Visibility Check", true, "Whether to check if an AABB side is visible").group(baseGroup, Group.Scan).index() + override val strictRayCast by c.setting("Strict Raycast", false, "Whether to include the environment to the ray cast context").group(baseGroup, Group.Scan).index() + override val resolution by c.setting("Resolution", 5, 1..20, 1, "The amount of grid divisions per surface of the hit box", "").group(baseGroup, Group.Scan).index() + override val pointSelection by c.setting("Point Selection", PointSelection.Optimum, "The strategy to select the best hit point").group(baseGroup, Group.Scan).index() companion object { const val DEFAULT_ATTACK_REACH = 3.0 diff --git a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt index fddcbe9c2..a59ac07c4 100644 --- a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt @@ -18,29 +18,29 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.util.NamedEnum import net.minecraft.item.Items class EatSettings( c: Configurable, - baseGroup: NamedEnum, - vis: () -> Boolean = { true } -) : EatConfig { + baseGroup: NamedEnum +) : SettingGroup(), EatConfig { val nutritiousFoodDefaults = listOf(Items.APPLE, Items.BAKED_POTATO, Items.BEEF, Items.BEETROOT, Items.BEETROOT_SOUP, Items.BREAD, Items.CARROT, Items.CHICKEN, Items.CHORUS_FRUIT, Items.COD, Items.COOKED_BEEF, Items.COOKED_CHICKEN, Items.COOKED_COD, Items.COOKED_MUTTON, Items.COOKED_PORKCHOP, Items.COOKED_RABBIT, Items.COOKED_SALMON, Items.COOKIE, Items.DRIED_KELP, Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE, Items.GOLDEN_CARROT, Items.HONEY_BOTTLE, Items.MELON_SLICE, Items.MUSHROOM_STEW, Items.MUTTON, Items.POISONOUS_POTATO, Items.PORKCHOP, Items.POTATO, Items.PUFFERFISH, Items.PUMPKIN_PIE, Items.RABBIT, Items.RABBIT_STEW, Items.ROTTEN_FLESH, Items.SALMON, Items.SPIDER_EYE, Items.SUSPICIOUS_STEW, Items.SWEET_BERRIES, Items.GLOW_BERRIES, Items.TROPICAL_FISH) val resistanceFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE) val regenerationFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE) val negativeFoodDefaults = listOf(Items.CHICKEN, Items.POISONOUS_POTATO, Items.PUFFERFISH, Items.ROTTEN_FLESH, Items.SPIDER_EYE) - override val eatOnHunger by c.setting("Eat On Hunger", true, "Whether to eat when hungry", vis).group(baseGroup) - override val minFoodLevel by c.setting("Minimum Food Level", 6, 0..20, 1, "The minimum food level to eat food", " food level") { vis() && eatOnHunger }.group(baseGroup) - override val saturated by c.setting("Saturated", EatConfig.Saturation.EatSmart, "When to stop eating") { vis() && eatOnHunger }.group(baseGroup) - override val nutritiousFood by c.setting("Nutritious Food", nutritiousFoodDefaults, nutritiousFoodDefaults, "Items that are be considered nutritious") { vis() && eatOnHunger }.group(baseGroup) - override val selectionPriority by c.setting("Selection Priority", EatConfig.SelectionPriority.MostNutritious, "The priority for selecting food items") { vis() && eatOnHunger }.group(baseGroup) - override val eatOnFire by c.setting("Eat On Fire", true, "Whether to eat when on fire", vis).group(baseGroup) - override val resistanceFood by c.setting("Resistance Food", resistanceFoodDefaults, resistanceFoodDefaults, "Items that give Fire Resistance") { vis() && eatOnFire}.group(baseGroup) - override val eatOnDamage by c.setting("Eat On Damage", true, "Whether to eat when damaged", vis).group(baseGroup) - override val minDamage by c.setting("Minimum Damage", 10, 0..20, 1, "The minimum damage threshold to trigger eating") { vis() && eatOnDamage }.group(baseGroup) - override val regenerationFood by c.setting("Regeneration Food", regenerationFoodDefaults, regenerationFoodDefaults, "Items that give Regeneration") { vis() && eatOnDamage }.group(baseGroup) - override val ignoreBadFood by c.setting("Ignore Bad Food", true, "Whether to eat when the food is bad", vis).group(baseGroup) - override val badFood by c.setting("Bad Food", negativeFoodDefaults, negativeFoodDefaults, "Items that are considered bad food") { vis() && ignoreBadFood }.group(baseGroup) + override val eatOnHunger by c.setting("Eat On Hunger", true, "Whether to eat when hungry").group(baseGroup).index() + override val minFoodLevel by c.setting("Minimum Food Level", 6, 0..20, 1, "The minimum food level to eat food", " food level") { eatOnHunger }.group(baseGroup).index() + override val saturated by c.setting("Saturated", EatConfig.Saturation.EatSmart, "When to stop eating") { eatOnHunger }.group(baseGroup).index() + override val nutritiousFood by c.setting("Nutritious Food", nutritiousFoodDefaults, nutritiousFoodDefaults, "Items that are be considered nutritious") { eatOnHunger }.group(baseGroup).index() + override val selectionPriority by c.setting("Selection Priority", EatConfig.SelectionPriority.MostNutritious, "The priority for selecting food items") { eatOnHunger }.group(baseGroup).index() + override val eatOnFire by c.setting("Eat On Fire", true, "Whether to eat when on fire").group(baseGroup).index() + override val resistanceFood by c.setting("Resistance Food", resistanceFoodDefaults, resistanceFoodDefaults, "Items that give Fire Resistance") { eatOnFire }.group(baseGroup).index() + override val eatOnDamage by c.setting("Eat On Damage", true, "Whether to eat when damaged").group(baseGroup).index() + override val minDamage by c.setting("Minimum Damage", 10, 0..20, 1, "The minimum damage threshold to trigger eating") { eatOnDamage }.group(baseGroup).index() + override val regenerationFood by c.setting("Regeneration Food", regenerationFoodDefaults, regenerationFoodDefaults, "Items that give Regeneration") { eatOnDamage }.group(baseGroup).index() + override val ignoreBadFood by c.setting("Ignore Bad Food", true, "Whether to eat when the food is bad").group(baseGroup).index() + override val badFood by c.setting("Bad Food", negativeFoodDefaults, negativeFoodDefaults, "Items that are considered bad food") { ignoreBadFood }.group(baseGroup).index() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt index acf1c950b..a80097dd5 100644 --- a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt @@ -18,18 +18,18 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent import com.lambda.interaction.request.hotbar.HotbarConfig import com.lambda.util.NamedEnum class HotbarSettings( c: Configurable, - baseGroup: NamedEnum, - vis: () -> Boolean = { true } -) : HotbarConfig { - override val keepTicks by c.setting("Keep Ticks", 1, 0..20, 1, "The number of ticks to keep the current hotbar selection active", " ticks", visibility = vis).group(baseGroup) - override val swapDelay by c.setting("Swap Delay", 0, 0..3, 1, "The number of ticks delay before allowing another hotbar selection swap", " ticks", visibility = vis).group(baseGroup) - override val swapsPerTick by c.setting("Swaps Per Tick", 3, 1..10, 1, "The number of hotbar selection swaps that can take place each tick") { swapDelay <= 0 && vis() }.group(baseGroup) - override val swapPause by c.setting("Swap Pause", 0, 0..20, 1, "The delay in ticks to pause actions after switching to the slot", " ticks", visibility = vis).group(baseGroup) - override val sequenceStageMask by c.setting("Hotbar Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which hotbar actions are performed", visibility = vis).group(baseGroup) + baseGroup: NamedEnum +) : SettingGroup(), HotbarConfig { + override val keepTicks by c.setting("Keep Ticks", 1, 0..20, 1, "The number of ticks to keep the current hotbar selection active", " ticks").group(baseGroup).index() + override val swapDelay by c.setting("Swap Delay", 0, 0..3, 1, "The number of ticks delay before allowing another hotbar selection swap", " ticks").group(baseGroup).index() + override val swapsPerTick by c.setting("Swaps Per Tick", 3, 1..10, 1, "The number of hotbar selection swaps that can take place each tick") { swapDelay <= 0 }.group(baseGroup).index() + override val swapPause by c.setting("Swap Pause", 0, 0..20, 1, "The delay in ticks to pause actions after switching to the slot", " ticks").group(baseGroup).index() + override val sequenceStageMask by c.setting("Hotbar Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which hotbar actions are performed").group(baseGroup).index() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt index 5ad6428de..f85214b2c 100644 --- a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt @@ -18,19 +18,19 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent import com.lambda.interaction.request.interacting.InteractConfig import com.lambda.util.NamedEnum class InteractSettings( c: Configurable, - baseGroup: NamedEnum, - vis: () -> Boolean = { true } -) : InteractConfig { - override val rotate by c.setting("Rotate For Interact", true, "Rotates the player to look at the block when interacting", visibility = vis).group(baseGroup) - override val sorter by c.setting("Interact Sorter", ActionConfig.SortMode.Tool, "The order in which interactions are performed", visibility = vis).group(baseGroup) - override val swingHand by c.setting("Swing On Interact", true, "Swings the players hand after interacting", visibility = vis).group(baseGroup) - override val tickStageMask by c.setting("Interact Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which interact actions are performed", visibility = vis).group(baseGroup) - override val interactSwingType by c.setting("Interact Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { vis() && swingHand }.group(baseGroup) - override val interactConfirmationMode by c.setting("Interact Confirmation Mode", InteractConfig.InteractConfirmationMode.InteractThenAwait, "The style of confirmation for interactions", visibility = vis).group(baseGroup) + baseGroup: NamedEnum +) : SettingGroup(), InteractConfig { + override val rotate by c.setting("Rotate For Interact", true, "Rotates the player to look at the block when interacting").group(baseGroup).index() + override val sorter by c.setting("Interact Sorter", ActionConfig.SortMode.Tool, "The order in which interactions are performed").group(baseGroup).index() + override val swingHand by c.setting("Swing On Interact", true, "Swings the players hand after interacting").group(baseGroup).index() + override val tickStageMask by c.setting("Interact Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which interact actions are performed").group(baseGroup).index() + override val interactSwingType by c.setting("Interact Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { swingHand }.group(baseGroup).index() + override val interactConfirmationMode by c.setting("Interact Confirmation Mode", InteractConfig.InteractConfirmationMode.InteractThenAwait, "The style of confirmation for interactions").group(baseGroup).index() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt index 11ddfcc00..2b6f30753 100644 --- a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt @@ -18,6 +18,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent import com.lambda.interaction.request.inventory.InventoryConfig import com.lambda.util.NamedEnum @@ -25,24 +26,23 @@ import com.lambda.util.item.ItemUtils class InventorySettings( c: Configurable, - baseGroup: NamedEnum, - vis: () -> Boolean = { true } -) : InventoryConfig { + baseGroup: NamedEnum +) : SettingGroup(), InventoryConfig { enum class Group(override val displayName: String) : NamedEnum { General("General"), Container("Container"), Access("Access") } - override val actionsPerSecond by c.setting("Actions Per Second", 100, 0..100, 1, "How many inventory actions can be performed per tick", visibility = vis).group(baseGroup, Group.General) - override val tickStageMask by c.setting("Inventory Stage Mask", setOf(TickEvent.Pre, TickEvent.Input.Pre, TickEvent.Input.Post, TickEvent.Player.Post), description = "The sub-tick timing at which inventory actions are performed", visibility = vis).group(baseGroup, Group.General) - override val disposables by c.setting("Disposables", ItemUtils.defaultDisposables, ItemUtils.defaultDisposables, "Items that will be ignored when checking for a free slot", vis).group(baseGroup, Group.Container) - override val swapWithDisposables by c.setting("Swap With Disposables", true, "Swap items with disposable ones", vis).group(baseGroup, Group.Container) - override val providerPriority by c.setting("Provider Priority", InventoryConfig.Priority.WithMinItems, "What container to prefer when retrieving the item from", vis).group(baseGroup, Group.Container) - override val storePriority by c.setting("Store Priority", InventoryConfig.Priority.WithMinItems, "What container to prefer when storing the item to", vis).group(baseGroup, Group.Container) + override val actionsPerSecond by c.setting("Actions Per Second", 100, 0..100, 1, "How many inventory actions can be performed per tick").group(baseGroup, Group.General).index() + override val tickStageMask by c.setting("Inventory Stage Mask", setOf(TickEvent.Pre, TickEvent.Input.Pre, TickEvent.Input.Post, TickEvent.Player.Post), description = "The sub-tick timing at which inventory actions are performed").group(baseGroup, Group.General).index() + override val disposables by c.setting("Disposables", ItemUtils.defaultDisposables, ItemUtils.defaultDisposables, "Items that will be ignored when checking for a free slot").group(baseGroup, Group.Container).index() + override val swapWithDisposables by c.setting("Swap With Disposables", true, "Swap items with disposable ones").group(baseGroup, Group.Container).index() + override val providerPriority by c.setting("Provider Priority", InventoryConfig.Priority.WithMinItems, "What container to prefer when retrieving the item from").group(baseGroup, Group.Container).index() + override val storePriority by c.setting("Store Priority", InventoryConfig.Priority.WithMinItems, "What container to prefer when storing the item to").group(baseGroup, Group.Container).index() - override val accessShulkerBoxes by c.setting("Access Shulker Boxes", true, "Allow access to the player's shulker boxes", vis).group(baseGroup, Group.Access) - override val accessEnderChest by c.setting("Access Ender Chest", false, "Allow access to the player's ender chest", vis).group(baseGroup, Group.Access) - override val accessChests by c.setting("Access Chests", false, "Allow access to the player's normal chests", vis).group(baseGroup, Group.Access) - override val accessStashes by c.setting("Access Stashes", false, "Allow access to the player's stashes", vis).group(baseGroup, Group.Access) + override val accessShulkerBoxes by c.setting("Access Shulker Boxes", true, "Allow access to the player's shulker boxes").group(baseGroup, Group.Access).index() + override val accessEnderChest by c.setting("Access Ender Chest", false, "Allow access to the player's ender chest").group(baseGroup, Group.Access).index() + override val accessChests by c.setting("Access Chests", false, "Allow access to the player's normal chests").group(baseGroup, Group.Access).index() + override val accessStashes by c.setting("Access Stashes", false, "Allow access to the player's stashes").group(baseGroup, Group.Access).index() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt index da897e574..35e1f295d 100644 --- a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt @@ -18,6 +18,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent import com.lambda.interaction.request.placing.PlaceConfig import com.lambda.interaction.request.placing.PlaceConfig.AirPlaceMode @@ -26,18 +27,17 @@ import com.lambda.util.NamedEnum class PlaceSettings( c: Configurable, - baseGroup: NamedEnum, - vis: () -> Boolean = { true } -) : PlaceConfig { - override val rotateForPlace by c.setting("Rotate For Place", true, "Rotate towards block while placing", visibility = vis).group(baseGroup) - override val airPlace by c.setting("Air Place", AirPlaceMode.None, "Allows for placing blocks without adjacent faces", visibility = vis).group(baseGroup) - override val axisRotateSetting by c.setting("Axis Rotate", true, "Overrides the Rotate For Place setting and rotates the player on each axis to air place rotational blocks") { vis() && airPlace.isEnabled }.group(baseGroup) - override val sorter by c.setting("Place Sorter", ActionConfig.SortMode.Tool, "The order in which placements are performed", visibility = vis).group(baseGroup) - override val tickStageMask by c.setting("Place Stage mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which place actions are performed", visibility = vis).group(baseGroup) - override val placeConfirmationMode by c.setting("Place Confirmation", PlaceConfirmationMode.PlaceThenAwait, "Wait for block placement confirmation", visibility = vis).group(baseGroup) - override val maxPendingPlacements by c.setting("Max Pending Placements", 5, 0..30, 1, "The maximum amount of pending placements", visibility = vis).group(baseGroup) - override val placementsPerTick by c.setting("Places Per Tick", 1, 1..30, 1, "Maximum instant block places per tick", visibility = vis).group(baseGroup) - override val swing by c.setting("Swing On Place", true, "Swings the players hand when placing", visibility = vis).group(baseGroup) - override val swingType by c.setting("Place Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { vis() && swing }.group(baseGroup) - override val sounds by c.setting("Place Sounds", true, "Plays the placing sounds", visibility = vis).group(baseGroup) + baseGroup: NamedEnum +) : SettingGroup(), PlaceConfig { + override val rotateForPlace by c.setting("Rotate For Place", true, "Rotate towards block while placing").group(baseGroup).index() + override val airPlace by c.setting("Air Place", AirPlaceMode.None, "Allows for placing blocks without adjacent faces").group(baseGroup).index() + override val axisRotateSetting by c.setting("Axis Rotate", true, "Overrides the Rotate For Place setting and rotates the player on each axis to air place rotational blocks") { airPlace.isEnabled }.group(baseGroup).index() + override val sorter by c.setting("Place Sorter", ActionConfig.SortMode.Tool, "The order in which placements are performed").group(baseGroup).index() + override val tickStageMask by c.setting("Place Stage mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which place actions are performed").group(baseGroup).index() + override val placeConfirmationMode by c.setting("Place Confirmation", PlaceConfirmationMode.PlaceThenAwait, "Wait for block placement confirmation").group(baseGroup).index() + override val maxPendingPlacements by c.setting("Max Pending Placements", 5, 0..30, 1, "The maximum amount of pending placements").group(baseGroup).index() + override val placementsPerTick by c.setting("Places Per Tick", 1, 1..30, 1, "Maximum instant block places per tick").group(baseGroup).index() + override val swing by c.setting("Swing On Place", true, "Swings the players hand when placing").group(baseGroup).index() + override val swingType by c.setting("Place Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { swing }.group(baseGroup).index() + override val sounds by c.setting("Place Sounds", true, "Plays the placing sounds").group(baseGroup).index() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt index 505d9cfdb..9ba8fe956 100644 --- a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt @@ -18,6 +18,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.interaction.request.rotating.RotationConfig import com.lambda.interaction.request.rotating.RotationMode import com.lambda.util.NamedEnum @@ -30,31 +31,30 @@ import kotlin.random.Random class RotationSettings( c: Configurable, - baseGroup: NamedEnum? = null, - vis: () -> Boolean = { true } -) : RotationConfig { - override var rotationMode by c.setting("Mode", RotationMode.Sync, "How the player is being rotated on interaction", vis).group(baseGroup) + baseGroup: NamedEnum, +) : SettingGroup(), RotationConfig { + override var rotationMode by c.setting("Mode", RotationMode.Sync, "How the player is being rotated on interaction").group(baseGroup).index() /** How many ticks to keep the rotation before resetting */ - override val keepTicks by c.setting("Keep Rotation", 1, 1..10, 1, "Ticks to keep rotation", " ticks") { rotate && vis() }.group(baseGroup) + override val keepTicks by c.setting("Keep Rotation", 1, 1..10, 1, "Ticks to keep rotation", " ticks") { rotate }.group(baseGroup).index() /** How many ticks to wait before resetting the rotation */ - override val decayTicks by c.setting("Reset Rotation", 1, 1..10, 1, "Ticks before rotation is reset", " ticks") { rotate && vis() }.group(baseGroup) + override val decayTicks by c.setting("Reset Rotation", 1, 1..10, 1, "Ticks before rotation is reset", " ticks") { rotate }.group(baseGroup).index() /** Whether the rotation is instant */ - var instant by c.setting("Instant Rotation", true, "Instantly rotate") { rotate && vis() }.group(baseGroup) + var instant by c.setting("Instant Rotation", true, "Instantly rotate") { rotate }.group(baseGroup).index() /** * The mean (average/base) value used to calculate rotation speed. * This value represents the center of the distribution. */ - var mean by c.setting("Mean", 40.0, 1.0..120.0, 0.1, "Average rotation speed", unit = "°") { rotate && vis() && !instant }.group(baseGroup) + var mean by c.setting("Mean", 40.0, 1.0..120.0, 0.1, "Average rotation speed", unit = "°") { rotate && !instant }.group(baseGroup).index() /** * The standard deviation for the Gaussian distribution used to calculate rotation speed. * This value represents the spread of rotation speed. */ - var spread by c.setting("Spread", 10.0, 0.0..60.0, 0.1, "Spread of rotation speeds", unit = "°") { rotate && vis() && !instant }.group(baseGroup) + var spread by c.setting("Spread", 10.0, 0.0..60.0, 0.1, "Spread of rotation speeds", unit = "°") { rotate && !instant }.group(baseGroup).index() /** * We must always provide turn speed to the interpolator because the player's yaw might exceed the -180 to 180 range. diff --git a/src/main/kotlin/com/lambda/config/groups/Targeting.kt b/src/main/kotlin/com/lambda/config/groups/Targeting.kt index 51cfdf391..c505f4c8c 100644 --- a/src/main/kotlin/com/lambda/config/groups/Targeting.kt +++ b/src/main/kotlin/com/lambda/config/groups/Targeting.kt @@ -18,6 +18,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable +import com.lambda.config.SettingGroup import com.lambda.context.SafeContext import com.lambda.friend.FriendManager.isFriend import com.lambda.interaction.request.rotating.Rotation.Companion.dist @@ -43,50 +44,49 @@ import java.util.* * based on player settings and entity characteristics. It allows for specifying which types of entities * are targetable, the range of targeting, and various other conditions for targeting. * - * @param owner The [Configurable] instance used to get and set configuration options for targeting. - * @param predicate The predicate used to determine whether the targeting settings are visible and active. + * @param c The [Configurable] instance used to get and set configuration options for targeting. + * @param vis The predicate used to determine whether the targeting settings are visible and active. * @param defaultRange The default range within which entities can be targeted. * @param maxRange The maximum range within which entities can be targeted. */ abstract class Targeting( - private val owner: Configurable, + private val c: Configurable, baseGroup: NamedEnum, - private val predicate: () -> Boolean = { true }, private val defaultRange: Double, private val maxRange: Double, -) : TargetingConfig { +) : SettingGroup(), TargetingConfig { /** * The range within which entities can be targeted. This value is configurable and constrained * between 1.0 and [maxRange]. */ - override val targetingRange by owner.setting("Targeting Range", defaultRange, 1.0..maxRange, 0.05) { predicate() }.group(baseGroup) + override val targetingRange by c.setting("Targeting Range", defaultRange, 1.0..maxRange, 0.05).group(baseGroup) /** * Whether players are included in the targeting scope. */ - override val players by owner.setting("Players", true) { predicate() }.group(baseGroup) + override val players by c.setting("Players", true).group(baseGroup) /** * Whether friends are included in the targeting scope. * Requires [players] to be true. */ - override val friends by owner.setting("Friends", false) { predicate() && players }.group(baseGroup) + override val friends by c.setting("Friends", false) { players }.group(baseGroup) /** * Whether mobs are included in the targeting scope. */ - private val mobs by owner.setting("Mobs", true) { predicate() }.group(baseGroup) + private val mobs by c.setting("Mobs", true).group(baseGroup) /** * Whether hostile mobs are included in the targeting scope */ - private val hostilesSetting by owner.setting("Hostiles", true) { predicate() && mobs }.group(baseGroup) + private val hostilesSetting by c.setting("Hostiles", true) { mobs }.group(baseGroup) /** * Whether passive animals are included in the targeting scope */ - private val animalsSetting by owner.setting("Animals", true) { predicate() && mobs }.group(baseGroup) + private val animalsSetting by c.setting("Animals", true) { mobs }.group(baseGroup) /** * Indicates whether hostile entities are included in the targeting scope. @@ -101,12 +101,12 @@ abstract class Targeting( /** * Whether invisible entities are included in the targeting scope. */ - override val invisible by owner.setting("Invisible", true) { predicate() }.group(baseGroup) + override val invisible by c.setting("Invisible", true).group(baseGroup) /** * Whether dead entities are included in the targeting scope. */ - override val dead by owner.setting("Dead", false) { predicate() }.group(baseGroup) + override val dead by c.setting("Dead", false).group(baseGroup) /** * Validates whether a given entity is targetable by the player based on current settings. @@ -134,22 +134,21 @@ abstract class Targeting( * @property priority The priority used to determine which entity is targeted when multiple candidates are available. */ class Combat( - owner: Configurable, + c: Configurable, baseGroup: NamedEnum, defaultRange: Double = 5.0, maxRange: Double = 16.0, - predicate: () -> Boolean = { true }, - ) : Targeting(owner, baseGroup, predicate, defaultRange, maxRange) { + ) : Targeting(c, baseGroup, defaultRange, maxRange) { /** * The field of view limit for targeting entities. Configurable between 5 and 180 degrees. */ - val fov by owner.setting("FOV Limit", 180, 5..180, 1) { predicate() && priority == Priority.Fov }.group(baseGroup) + val fov by c.setting("FOV Limit", 180, 5..180, 1) { priority == Priority.Fov }.group(baseGroup) /** * The priority used to determine which entity is targeted. Configurable with default set to [Priority.Distance]. */ - val priority by owner.setting("Priority", Priority.Distance) { predicate() }.group(baseGroup) + val priority by c.setting("Priority", Priority.Distance).group(baseGroup) /** * Validates whether a given entity is targetable for combat based on the field of view limit and other settings. @@ -186,10 +185,9 @@ abstract class Targeting( * Subclass for targeting entities for ESP (Extrasensory Perception) purposes. */ class ESP( - owner: Configurable, + c: Configurable, baseGroup: NamedEnum, - predicate: () -> Boolean = { true }, - ) : Targeting(owner, baseGroup, predicate, 128.0, 1024.0) + ) : Targeting(c, baseGroup, 128.0, 1024.0) /** * Enum representing the different priority factors used for determining the best target. diff --git a/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt b/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt index 309fa3fd7..1b822cb30 100644 --- a/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt +++ b/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt @@ -60,8 +60,7 @@ object KillAura : Module( private val targeting = Targeting.Combat(this, Group.Targeting) // Aiming - private val rotate by setting("Rotate", true).group(Group.Aiming) - override val rotationConfig = RotationSettings(this, Group.Aiming) { rotate } + override val rotationConfig = RotationSettings(this, Group.Aiming) val target: LivingEntity? get() = targeting.target() @@ -122,7 +121,7 @@ object KillAura : Module( } // Rotation check - if (rotate) { + if (rotationConfig.rotate) { val angle = RotationManager.activeRotation if (buildConfig.strictRayCast) { diff --git a/src/main/kotlin/com/lambda/module/modules/debug/RotationTest.kt b/src/main/kotlin/com/lambda/module/modules/debug/RotationTest.kt index 79c479932..bac9cd061 100644 --- a/src/main/kotlin/com/lambda/module/modules/debug/RotationTest.kt +++ b/src/main/kotlin/com/lambda/module/modules/debug/RotationTest.kt @@ -17,6 +17,7 @@ package com.lambda.module.modules.debug +import com.lambda.config.AutomationConfig import com.lambda.config.groups.RotationSettings import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen @@ -29,7 +30,7 @@ object RotationTest : Module( name = "RotationTest", tag = ModuleTag.DEBUG, ) { - override val rotationConfig = RotationSettings(this) + override val rotationConfig = RotationSettings(this, AutomationConfig.Group.Rotation) var hitPos: HitResult? = null init { diff --git a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt index c5c788d2a..bef3bfd2c 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt @@ -92,6 +92,7 @@ object FastBreak : Module( ::accessStashes ) } + hideAll(buildConfig, placeConfig, interactConfig, inventoryConfig, eatConfig) } listen { it.cancel() } 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 43c5e8242..0139228c7 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt @@ -109,12 +109,6 @@ object PacketMine : Module( init { defaultAutomationConfig = automationConfig { - buildConfig.apply { - editTyped(::pathing, ::stayInRange, ::collectDrops) { - defaultValue(false) - hide() - } - } breakConfig.apply { editTyped( ::avoidLiquids, @@ -124,20 +118,10 @@ object PacketMine : Module( ) { defaultValue(false) } ::swing.edit { defaultValue(BreakConfig.SwingMode.Start) } } - inventoryConfig.apply { - editTyped( - ::accessShulkerBoxes, - ::accessEnderChest, - ::accessChests, - ::accessStashes - ) { - defaultValue(false) - hide() - } - } hotbarConfig.apply { ::keepTicks.edit { defaultValue(0) } } + hideAll(buildConfig, placeConfig, interactConfig, inventoryConfig, eatConfig) } listen { diff --git a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt index af1ce67dc..c5bed8a30 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt @@ -17,9 +17,9 @@ package com.lambda.module.modules.player +import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.config.groups.BuildConfig import com.lambda.config.settings.complex.Bind -import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.context.SafeContext import com.lambda.event.events.MovementEvent import com.lambda.event.events.TickEvent @@ -81,6 +81,7 @@ object Scaffold : Module( hide() } } + hideAll(buildConfig, breakConfig, interactConfig, inventoryConfig, eatConfig) } listen { From 8970805c6f2c072a130f3a31d4a30fe3b3aa55e5 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sun, 23 Nov 2025 01:03:43 +0000 Subject: [PATCH 06/12] correct hidden settings for linked configs --- .../com/lambda/config/AutomationConfig.kt | 48 ++++++++++++------- .../lambda/gui/components/SettingsWidget.kt | 10 ++-- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/AutomationConfig.kt b/src/main/kotlin/com/lambda/config/AutomationConfig.kt index 395badfea..804a61383 100644 --- a/src/main/kotlin/com/lambda/config/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/AutomationConfig.kt @@ -62,6 +62,8 @@ 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 automationConfig(name: String = module.name, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = @@ -104,7 +106,7 @@ open class AutomationConfig( @SettingEditorDsl internal inline fun KProperty0.edit(edits: TypedEditBuilder.(AbstractSetting) -> Unit) { val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") - TypedEditBuilder(listOf(setting), this@AutomationConfig).edits(setting) + TypedEditBuilder(this@AutomationConfig, listOf(setting)).edits(setting) } @SettingEditorDsl @@ -113,7 +115,7 @@ open class AutomationConfig( edits: TypedEditBuilder.(AbstractSetting) -> Unit ) { val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") - TypedEditBuilder(listOf(setting), this@AutomationConfig).edits(other.delegate as AbstractSetting) + TypedEditBuilder(this@AutomationConfig, listOf(setting)).edits(other.delegate as AbstractSetting) } @SettingEditorDsl @@ -133,43 +135,57 @@ open class AutomationConfig( internal inline fun editTyped( vararg settings: KProperty0, edits: TypedEditBuilder.() -> Unit - ) { TypedEditBuilder(settings.map { it.delegate } as List>, this@AutomationConfig).apply(edits) } + ) { TypedEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List>).apply(edits) } @SettingEditorDsl internal inline fun editTypedWith( vararg settings: KProperty0, other: KProperty0, edits: TypedEditBuilder.(AbstractSetting) -> Unit - ) = TypedEditBuilder(settings.map { it.delegate } as List>, this@AutomationConfig).edits(other.delegate as AbstractSetting) + ) = TypedEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List>).edits(other.delegate as AbstractSetting) + + @SettingEditorDsl + fun hide(vararg settings: KProperty0<*>) = { + (settings.map { it.delegate } as List>).let { removed -> + this@AutomationConfig.settings.removeAll(removed) + hiddenSettings.addAll(removed) + } + } @SettingEditorDsl - fun hide(vararg settings: KProperty0<*>) = - this@AutomationConfig.settings.removeAll(settings.map { it.delegate } as List>) + fun hideAll(settingGroup: SettingGroup) = hideAll(settingGroup.settings) @SettingEditorDsl - fun hideAll(settingGroup: SettingGroup) { - settings.removeAll(settingGroup.settings) + fun hideAll(settings: Collection>) { + this@AutomationConfig.settings.removeAll(settings) + hiddenSettings.addAll(settings) } @SettingEditorDsl fun hideAll(vararg settingGroups: SettingGroup) { - settings.removeAll(settingGroups.flatMap { it.settings }) + settingGroups.flatMap { it.settings }.let { removed -> + settings.removeAll(removed) + hiddenSettings.addAll(removed) + } } @SettingEditorDsl fun hideAllExcept(settingGroup: SettingGroup, vararg settings: KProperty0<*>) { - this@AutomationConfig.settings.removeIf { it in settingGroup.settings && it !in (settings.toList() as List>) } + this@AutomationConfig.settings.removeIf { + return@removeIf if (it in settingGroup.settings && it !in (settings.toList() as List>)) { + hiddenSettings.add(it) + true + } else false + } } - open class BasicEditBuilder(val c: Configurable, open val settings: Collection>) { + open class BasicEditBuilder(val c: AutomationConfig, open val settings: Collection>) { @SettingEditorDsl fun visibility(vis: () -> Boolean) = settings.forEach { it.visibility = vis } @SettingEditorDsl - fun hide() { - c.settings.removeAll(settings) - } + fun hide() = c.hideAll(settings) @SettingEditorDsl fun groups(vararg groups: NamedEnum) = @@ -181,8 +197,8 @@ open class AutomationConfig( } open class TypedEditBuilder( - override val settings: Collection>, - c: Configurable + c: AutomationConfig, + override val settings: Collection> ) : BasicEditBuilder(c, settings) { @SettingEditorDsl fun defaultValue(value: T) = diff --git a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt index 52bea1aa3..993b46555 100644 --- a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt +++ b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt @@ -32,7 +32,7 @@ object SettingsWidget { /** * Builds the settings context popup content for a given configurable. */ - fun ImGuiBuilder.buildConfigSettingsContext(config: Configurable) { + fun ImGuiBuilder.buildConfigSettingsContext(config: Configurable, hiddenSettings: Set> = emptySet()) { group { if (config is Module) { with(config.keybindSetting) { buildLayout() } @@ -45,12 +45,12 @@ object SettingsWidget { if (config is MutableAutomationConfig && config.automationConfig !== AutomationConfig.Companion.DEFAULT) { button("Automation Config") sameLine() + popupContextItem("##automation-config-popup-${config.name}") { + buildConfigSettingsContext(config.automationConfig, config.defaultAutomationConfig.hiddenSettings) + } if (config.automationConfig !== config.defaultAutomationConfig) { text("(${config.automationConfig.name})") } - popupContextItem("##automation-config-popup-${config.name}") { - buildConfigSettingsContext(config.automationConfig) - } } } separator() @@ -60,7 +60,7 @@ object SettingsWidget { is UserAutomationConfig -> setOf(config.linkedModules) else -> emptySet() } - val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings + val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings - hiddenSettings val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() } ungrouped.forEach { it.withDisabled { buildLayout() } From 4bddc30d03eeb80a518633bea30e24d92f681891 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sun, 23 Nov 2025 01:21:19 +0000 Subject: [PATCH 07/12] less duplicate code in hide functions --- .../kotlin/com/lambda/config/AutomationConfig.kt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/AutomationConfig.kt b/src/main/kotlin/com/lambda/config/AutomationConfig.kt index 804a61383..245cd9442 100644 --- a/src/main/kotlin/com/lambda/config/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/AutomationConfig.kt @@ -145,11 +145,8 @@ open class AutomationConfig( ) = TypedEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List>).edits(other.delegate as AbstractSetting) @SettingEditorDsl - fun hide(vararg settings: KProperty0<*>) = { - (settings.map { it.delegate } as List>).let { removed -> - this@AutomationConfig.settings.removeAll(removed) - hiddenSettings.addAll(removed) - } + fun hide(vararg settings: KProperty0<*>) { + hideAll((settings.map { it.delegate } as List>)) } @SettingEditorDsl @@ -163,10 +160,7 @@ open class AutomationConfig( @SettingEditorDsl fun hideAll(vararg settingGroups: SettingGroup) { - settingGroups.flatMap { it.settings }.let { removed -> - settings.removeAll(removed) - hiddenSettings.addAll(removed) - } + settingGroups.forEach { hideAll(it.settings) } } @SettingEditorDsl From b3cf49c68926aa314b088a8291497ff39231ae7f Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sun, 23 Nov 2025 02:46:27 +0000 Subject: [PATCH 08/12] use new automation config thingy in modules --- .../com/lambda/module/modules/player/AutoEat.kt | 13 +++++++++++++ .../com/lambda/module/modules/player/FastBreak.kt | 8 -------- .../lambda/module/modules/player/HighwayTools.kt | 4 ++++ .../com/lambda/module/modules/player/Nuker.kt | 4 ++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/lambda/module/modules/player/AutoEat.kt b/src/main/kotlin/com/lambda/module/modules/player/AutoEat.kt index 7114de5ec..01fc502b6 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/AutoEat.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/AutoEat.kt @@ -17,6 +17,7 @@ package com.lambda.module.modules.player +import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.config.groups.EatConfig.Companion.reasonEating import com.lambda.config.groups.EatSettings import com.lambda.config.groups.InventorySettings @@ -45,6 +46,18 @@ object AutoEat : Module( private var eatTask: EatTask? = null init { + defaultAutomationConfig = automationConfig { + hideAll( + buildConfig, + breakConfig, + placeConfig, + interactConfig, + rotationConfig, + inventoryConfig, + hotbarConfig, + ) + } + listen { val reason = runSafeAutomated { reasonEating() } if (eatTask != null || !reason.shouldEat()) return@listen diff --git a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt index bef3bfd2c..b9b9a04ea 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt @@ -84,14 +84,6 @@ object FastBreak : Module( ::breaksPerTick ) } - inventoryConfig.apply { - hide( - ::accessShulkerBoxes, - ::accessEnderChest, - ::accessChests, - ::accessStashes - ) - } hideAll(buildConfig, placeConfig, interactConfig, inventoryConfig, eatConfig) } diff --git a/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt b/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt index e0689df36..a1cc943bd 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt @@ -17,6 +17,7 @@ package com.lambda.module.modules.player +import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.interaction.BaritoneManager import com.lambda.interaction.construction.blueprint.Blueprint.Companion.emptyStructure import com.lambda.interaction.construction.blueprint.PropagatingBlueprint.Companion.propagatingBlueprint @@ -87,6 +88,9 @@ object HighwayTools : Module( } init { + defaultAutomationConfig = automationConfig { + hideAll(interactConfig) + } onEnable { octant = player.octant startPos = player.blockPos diff --git a/src/main/kotlin/com/lambda/module/modules/player/Nuker.kt b/src/main/kotlin/com/lambda/module/modules/player/Nuker.kt index a967db0b4..c51b89254 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Nuker.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Nuker.kt @@ -17,6 +17,7 @@ package com.lambda.module.modules.player +import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.interaction.BaritoneManager import com.lambda.interaction.construction.blueprint.TickingBlueprint.Companion.tickingBlueprint import com.lambda.interaction.construction.verify.TargetState @@ -44,6 +45,9 @@ object Nuker : Module( private var task: Task<*>? = null init { + defaultAutomationConfig = automationConfig { + hideAll(interactConfig) + } onEnable { task = tickingBlueprint { val selection = BlockPos.iterateOutwards(player.blockPos, width, height, width) From 3a7cca7e58e86c0fcf61b39a6374714ea5d895ca Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sun, 23 Nov 2025 04:58:18 +0000 Subject: [PATCH 09/12] add "Default" to default module automation config configurables --- src/main/kotlin/com/lambda/config/AutomationConfig.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/AutomationConfig.kt b/src/main/kotlin/com/lambda/config/AutomationConfig.kt index 245cd9442..df32d84c8 100644 --- a/src/main/kotlin/com/lambda/config/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/AutomationConfig.kt @@ -67,10 +67,10 @@ open class AutomationConfig( companion object { context(module: Module) fun automationConfig(name: String = module.name, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = - AutomationConfig("$name Automation Config").apply { edits?.invoke(this) } + AutomationConfig("Default $name Automation Config").apply { edits?.invoke(this) } fun automationConfig(name: String, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = - AutomationConfig("$name Automation Config").apply { edits?.invoke(this) } + AutomationConfig("Default $name Automation Config").apply { edits?.invoke(this) } object DEFAULT : AutomationConfig("Default Automation Config") { val renders by setting("Render", false).group(Group.Render) From 4ceee4ecf9e8536be94e4fe913b2bd397b27dade Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sun, 23 Nov 2025 17:05:29 +0000 Subject: [PATCH 10/12] merge printer module --- .../lambda/module/modules/player/Printer.kt | 49 ++++++------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/src/main/kotlin/com/lambda/module/modules/player/Printer.kt b/src/main/kotlin/com/lambda/module/modules/player/Printer.kt index efc6cc8c4..3ad9431b1 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Printer.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Printer.kt @@ -17,13 +17,7 @@ package com.lambda.module.modules.player -import com.lambda.config.groups.BreakSettings -import com.lambda.config.groups.BuildSettings -import com.lambda.config.groups.HotbarSettings -import com.lambda.config.groups.InteractSettings -import com.lambda.config.groups.InventorySettings -import com.lambda.config.groups.PlaceSettings -import com.lambda.config.groups.RotationSettings +import com.lambda.config.AutomationConfig.Companion.automationConfig import com.lambda.interaction.construction.blueprint.TickingBlueprint import com.lambda.interaction.construction.verify.TargetState import com.lambda.interaction.request.placing.PlaceConfig @@ -33,7 +27,6 @@ import com.lambda.task.RootTask.run import com.lambda.task.Task import com.lambda.task.tasks.BuildTask.Companion.build import com.lambda.util.BlockUtils.blockPos -import com.lambda.util.NamedEnum import fi.dy.masa.litematica.world.SchematicWorldHandler import net.minecraft.util.math.BlockPos @@ -47,37 +40,23 @@ object Printer : Module( true }.getOrDefault(false) - private val range by setting("Range", 5, 1..7, 1).group(Group.General) - private val air by setting("Air", false).group(Group.General) - - override val buildConfig = BuildSettings(this, Group.Build).apply { - editTyped(::pathing, ::stayInRange) { defaultValue(false) } - } - override val breakConfig = BreakSettings(this, Group.Break).apply { - editTyped(::efficientOnly, ::suitableToolsOnly) { defaultValue(false) } - } - override val placeConfig = PlaceSettings(this, Group.Place).apply { - ::airPlace.edit { defaultValue(PlaceConfig.AirPlaceMode.Grim) } - } - override val interactConfig = InteractSettings(this, Group.Interact) - override val rotationConfig = RotationSettings(this, Group.Rotation) - override val inventoryConfig = InventorySettings(this, Group.Inventory) - override val hotbarConfig = HotbarSettings(this, Group.Hotbar) + private val range by setting("Range", 5, 1..7, 1) + private val air by setting("Air", false) private var buildTask: Task<*>? = null - private enum class Group(override val displayName: String) : NamedEnum { - General("General"), - Build("Build"), - Break("Break"), - Place("Place"), - Interact("Interact"), - Rotation("Rotation"), - Inventory("Inventory"), - Hotbar("Hotbar") - } - init { + defaultAutomationConfig = automationConfig { + buildConfig.apply { + editTyped(::pathing, ::stayInRange) { defaultValue(false) } + } + breakConfig.apply { + editTyped(::efficientOnly, ::suitableToolsOnly) { defaultValue(false) } + } + placeConfig.apply { + ::airPlace.edit { defaultValue(PlaceConfig.AirPlaceMode.Grim) } + } + } onEnable { if (!isSchematicHandlerAvailable()) { error("Litematica is not installed!") From 53d23c597bf8274b33fe51c343ba54e6a7c09ba2 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Mon, 24 Nov 2025 01:21:42 +0000 Subject: [PATCH 11/12] internal functions with public api to allow overriding instead of goofy onPreLoad onPostLoad functions --- .../kotlin/com/lambda/config/Configuration.kt | 31 +++++----- .../com/lambda/config/DynamicConfiguration.kt | 57 ------------------- .../configurations/UserAutomationConfigs.kt | 30 ++++------ 3 files changed, 29 insertions(+), 89 deletions(-) delete mode 100644 src/main/kotlin/com/lambda/config/DynamicConfiguration.kt diff --git a/src/main/kotlin/com/lambda/config/Configuration.kt b/src/main/kotlin/com/lambda/config/Configuration.kt index e091e2d07..a668e4580 100644 --- a/src/main/kotlin/com/lambda/config/Configuration.kt +++ b/src/main/kotlin/com/lambda/config/Configuration.kt @@ -105,6 +105,20 @@ abstract class Configuration : Jsonable, Loadable { } } + protected open fun internalTrySave(logToChat: Boolean) { + save() + .onSuccess { + val message = "Saved ${configName.capitalize()} config." + LOG.info(message) + if (logToChat) info(message) + } + .onFailure { + val message = "Failed to save ${configName.capitalize()} config" + LOG.error(message, it) + logError(message) + } + } + /** * Loads the config from the [file] * Encapsulates [JsonIOException] and [JsonSyntaxException] in a runCatching block @@ -114,7 +128,7 @@ abstract class Configuration : Jsonable, Loadable { .ifExists { loadFromJson(JsonParser.parseReader(it.reader()).asJsonObject) } } - open fun tryLoad() = runIO { + protected open fun internalTryLoad() { load(primary) .onSuccess { val message = "${configName.capitalize()} config loaded." @@ -137,19 +151,8 @@ abstract class Configuration : Jsonable, Loadable { } } - open fun trySave(logToChat: Boolean = false) = runIO { - save() - .onSuccess { - val message = "Saved ${configName.capitalize()} config." - LOG.info(message) - if (logToChat) info(message) - } - .onFailure { - val message = "Failed to save ${configName.capitalize()} config" - LOG.error(message, it) - logError(message) - } - } + fun tryLoad() = runIO { internalTryLoad() } + fun trySave(logToChat: Boolean = false) = runIO { internalTrySave(logToChat) } companion object { val configurations = mutableSetOf() diff --git a/src/main/kotlin/com/lambda/config/DynamicConfiguration.kt b/src/main/kotlin/com/lambda/config/DynamicConfiguration.kt deleted file mode 100644 index 42f6b4fc7..000000000 --- a/src/main/kotlin/com/lambda/config/DynamicConfiguration.kt +++ /dev/null @@ -1,57 +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 kotlinx.coroutines.Job - -abstract class DynamicConfiguration : Configuration() { - private val preLoadListeners = mutableListOf<() -> Unit>() - private val postLoadListeners = mutableListOf<() -> Unit>() - private val preSaveListeners = mutableListOf<() -> Unit>() - private val postSaveListeners = mutableListOf<() -> Unit>() - - override fun tryLoad(): Job { - preLoadListeners.forEach { it() } - return super.tryLoad().also { job -> - job.invokeOnCompletion { postLoadListeners.forEach { it() } } - } - } - - override fun trySave(logToChat: Boolean): Job { - preSaveListeners.forEach { it() } - return super.trySave(logToChat).also { job -> - job.invokeOnCompletion { postSaveListeners.forEach { it() } } - } - } - - fun onPreLoad(block: () -> Unit) { - preLoadListeners.add(block) - } - - fun onPostLoad(block: () -> Unit) { - postLoadListeners.add(block) - } - - fun onPreSave(block: () -> Unit) { - preSaveListeners.add(block) - } - - fun onPostSave(block: () -> Unit) { - postSaveListeners.add(block) - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt b/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt index fd4d6b9ba..746d97f8c 100644 --- a/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt +++ b/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt @@ -18,36 +18,30 @@ package com.lambda.config.configurations import com.google.gson.JsonParser -import com.lambda.config.DynamicConfiguration +import com.lambda.config.Configuration import com.lambda.config.UserAutomationConfig import com.lambda.module.ModuleRegistry.moduleNameMap import com.lambda.util.FileUtils.ifExists import com.lambda.util.FolderRegister import java.io.File -object UserAutomationConfigs : DynamicConfiguration() { +object UserAutomationConfigs : Configuration() { override val configName = "custom-automation" override val primary: File = FolderRegister.config.resolve("${configName}.json").toFile() - override fun load(): String { - onPreLoad { - primary.ifExists { - JsonParser.parseReader(it.reader()).asJsonObject.entrySet().forEach { (name, _) -> - if (configurables.any { config -> config.name == name }) return@forEach - UserAutomationConfig(name) - } + override fun internalTryLoad() { + primary.ifExists { + JsonParser.parseReader(it.reader()).asJsonObject.entrySet().forEach { (name, _) -> + if (configurables.any { config -> config.name == name }) return@forEach + UserAutomationConfig(name) } } - - onPostLoad { - configurables.forEach { - val config = it as? UserAutomationConfig ?: throw IllegalStateException("UserAutomationConfigs contains non-AutomationConfig") - config.linkedModules.value.forEach { moduleName -> - moduleNameMap[moduleName]?.automationConfig = config - } + super.internalTryLoad() + configurables.forEach { + val config = it as? UserAutomationConfig ?: throw IllegalStateException("UserAutomationConfigs contains non-AutomationConfig") + config.linkedModules.value.forEach { moduleName -> + moduleNameMap[moduleName]?.automationConfig = config } } - - return super.load() } } \ No newline at end of file From 7c3976a7627d5153a96061d3a3137af3ef7e9cae Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Mon, 24 Nov 2025 01:24:29 +0000 Subject: [PATCH 12/12] non-UserAutomationConfig --- .../com/lambda/config/configurations/UserAutomationConfigs.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt b/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt index 746d97f8c..05289e2cc 100644 --- a/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt +++ b/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt @@ -38,7 +38,7 @@ object UserAutomationConfigs : Configuration() { } super.internalTryLoad() configurables.forEach { - val config = it as? UserAutomationConfig ?: throw IllegalStateException("UserAutomationConfigs contains non-AutomationConfig") + val config = it as? UserAutomationConfig ?: throw IllegalStateException("UserAutomationConfigs contains non-UserAutomationConfig") config.linkedModules.value.forEach { moduleName -> moduleNameMap[moduleName]?.automationConfig = config }