diff --git a/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt b/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt index 1591a801d..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 @@ -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/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 267c735ee..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 @@ -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/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/AutomationConfig.kt b/src/main/kotlin/com/lambda/config/AutomationConfig.kt new file mode 100644 index 000000000..df32d84c8 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/AutomationConfig.kt @@ -0,0 +1,209 @@ +/* + * 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.AutomationConfigs +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.context.Automated +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 + +@Suppress("unchecked_cast", "unused") +open class AutomationConfig( + override val name: String, + configuration: Configuration = AutomationConfigs +) : Configurable(configuration), Automated { + enum class Group(override val displayName: String) : NamedEnum { + Build("Build"), + Break("Break"), + Place("Place"), + Interact("Interact"), + Rotation("Rotation"), + Interaction("Interaction"), + Inventory("Inventory"), + Hotbar("Hotbar"), + Eat("Eat"), + Render("Render"), + Debug("Debug") + } + + override val buildConfig = BuildSettings(this, Group.Build) + override val breakConfig = BreakSettings(this, Group.Break) + 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) + + val hiddenSettings = mutableSetOf>() + + companion object { + context(module: Module) + fun automationConfig(name: String = module.name, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = + AutomationConfig("Default $name Automation Config").apply { edits?.invoke(this) } + + fun automationConfig(name: String, edits: (AutomationConfig.() -> Unit)? = null): AutomationConfig = + AutomationConfig("Default $name Automation Config").apply { edits?.invoke(this) } + + 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) + 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) + + @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: TypedEditBuilder.(AbstractSetting) -> Unit) { + val setting = delegate as? AbstractSetting ?: throw IllegalStateException("Setting delegate did not match current value's type") + TypedEditBuilder(this@AutomationConfig, listOf(setting)).edits(setting) + } + + @SettingEditorDsl + 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") + TypedEditBuilder(this@AutomationConfig, listOf(setting)).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 + 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) } + + @SettingEditorDsl + internal inline fun editTyped( + vararg settings: KProperty0, + edits: TypedEditBuilder.() -> Unit + ) { 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(this@AutomationConfig, settings.map { it.delegate } as List>).edits(other.delegate as AbstractSetting) + + @SettingEditorDsl + fun hide(vararg settings: KProperty0<*>) { + hideAll((settings.map { it.delegate } as List>)) + } + + @SettingEditorDsl + fun hideAll(settingGroup: SettingGroup) = hideAll(settingGroup.settings) + + @SettingEditorDsl + fun hideAll(settings: Collection>) { + this@AutomationConfig.settings.removeAll(settings) + hiddenSettings.addAll(settings) + } + + @SettingEditorDsl + fun hideAll(vararg settingGroups: SettingGroup) { + settingGroups.forEach { hideAll(it.settings) } + } + + @SettingEditorDsl + fun hideAllExcept(settingGroup: SettingGroup, vararg settings: KProperty0<*>) { + 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: AutomationConfig, open val settings: Collection>) { + @SettingEditorDsl + fun visibility(vis: () -> Boolean) = + settings.forEach { it.visibility = vis } + + @SettingEditorDsl + fun hide() = c.hideAll(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( + c: AutomationConfig, + override val settings: Collection> + ) : BasicEditBuilder(c, settings) { + @SettingEditorDsl + fun defaultValue(value: T) = + settings.forEach { + it.defaultValue = value + it.value = value + } + } + + enum class InsertMode { + Above, + Below + } +} \ No newline at end of file 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..a668e4580 100644 --- a/src/main/kotlin/com/lambda/config/Configuration.kt +++ b/src/main/kotlin/com/lambda/config/Configuration.kt @@ -25,7 +25,8 @@ 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.core.Loadable import com.lambda.event.events.ClientEvent import com.lambda.event.listener.UnsafeListener.Companion.listenUnsafe import com.lambda.threading.runIO @@ -48,13 +49,14 @@ 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. * @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())) @@ -103,16 +105,30 @@ abstract class Configuration : Jsonable { } } + 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 */ - 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 { + protected open fun internalTryLoad() { load(primary) .onSuccess { val message = "${configName.capitalize()} config loaded." @@ -135,19 +151,8 @@ abstract class Configuration : Jsonable { } } - 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/MutableAutomationConfig.kt b/src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt new file mode 100644 index 000000000..58a90eea8 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/MutableAutomationConfig.kt @@ -0,0 +1,42 @@ +/* + * 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.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 +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/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/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/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/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/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/configurations/UserAutomationConfigs.kt b/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt new file mode 100644 index 000000000..05289e2cc --- /dev/null +++ b/src/main/kotlin/com/lambda/config/configurations/UserAutomationConfigs.kt @@ -0,0 +1,47 @@ +/* + * 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.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 : Configuration() { + override val configName = "custom-automation" + override val primary: File = FolderRegister.config.resolve("${configName}.json").toFile() + + override fun internalTryLoad() { + primary.ifExists { + JsonParser.parseReader(it.reader()).asJsonObject.entrySet().forEach { (name, _) -> + if (configurables.any { config -> config.name == name }) return@forEach + UserAutomationConfig(name) + } + } + super.internalTryLoad() + configurables.forEach { + val config = it as? UserAutomationConfig ?: throw IllegalStateException("UserAutomationConfigs contains non-UserAutomationConfig") + config.linkedModules.value.forEach { moduleName -> + moduleNameMap[moduleName]?.automationConfig = config + } + } + } +} \ 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 548f7f35f..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 @@ -28,86 +29,89 @@ 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) { - enum class Group(override val displayName: String) : NamedEnum { +) : 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 b8f4397aa..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, SettingGroup(c) { + 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 f5cec297d..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, SettingGroup(c) { + 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 11c9bd66c..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, SettingGroup(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) - 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 aaad972e9..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, SettingGroup(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) - 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 4e105532f..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, SettingGroup(c) { + 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 13e1f6468..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, SettingGroup(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) - 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 d84e1dd6c..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, SettingGroup(c) { - 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/SettingGroup.kt b/src/main/kotlin/com/lambda/config/groups/SettingGroup.kt deleted file mode 100644 index 71eb1469a..000000000 --- a/src/main/kotlin/com/lambda/config/groups/SettingGroup.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 SettingGroup(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/Targeting.kt b/src/main/kotlin/com/lambda/config/groups/Targeting.kt index 5590d23b9..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(owner) { +) : 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/config/settings/NumericSetting.kt b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt index 31a9f53b1..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.config.groups.SettingGroup +import com.lambda.config.AutomationConfig import com.lambda.gui.dsl.ImGuiBuilder import imgui.ImGui import imgui.ImGui.calcTextSize @@ -97,21 +97,21 @@ abstract class NumericSetting( } companion object { - @SettingGroup.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.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 } } - @SettingGroup.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.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 } } - @SettingGroup.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.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 602f3f2d9..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.config.groups.SettingGroup +import com.lambda.config.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 { - @SettingGroup.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.TypedEditBuilder.multiline(multiline: Boolean) { + fun AutomationConfig.TypedEditBuilder.multiline(multiline: Boolean) { (settings as Collection).forEach { it.multiline = multiline } } - @SettingGroup.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.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 69665a380..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.config.groups.SettingGroup +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,10 +86,18 @@ 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 { - @SettingGroup.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.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 afb5c0ad6..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.config.groups.SettingGroup +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,10 +86,18 @@ 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 { - @SettingGroup.SettingEditorDsl + @AutomationConfig.SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroup.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/AutomationConfig.kt b/src/main/kotlin/com/lambda/context/AutomationConfig.kt index a1c7db55a..e69de29bb 100644 --- a/src/main/kotlin/com/lambda/context/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/context/AutomationConfig.kt @@ -1,77 +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 - -import com.lambda.config.Configurable -import com.lambda.config.configurations.LambdaConfig -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.event.events.onStaticRender -import com.lambda.interaction.construction.result.Drawable -import com.lambda.util.NamedEnum - -object AutomationConfig : Configurable(LambdaConfig), Automated { - override val name = "automation" - - enum class Group(override val displayName: String) : NamedEnum { - Build("Build"), - Break("Break"), - Place("Place"), - Interact("Interact"), - Rotation("Rotation"), - Inventory("Inventory"), - Hotbar("Hotbar"), - Eat("Eat"), - Render("Render"), - 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) - 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) - - 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) - - @Volatile - var drawables = listOf() - - init { - onStaticRender { - if (renders) - with(it) { drawables.forEach { with(it) { buildRenderer() } } } - } - } -} \ 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..1c454f93e 100644 --- a/src/main/kotlin/com/lambda/gui/MenuBar.kt +++ b/src/main/kotlin/com/lambda/gui/MenuBar.kt @@ -22,7 +22,9 @@ 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.config.Configuration.Companion.configurables +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 @@ -34,6 +36,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 @@ -47,6 +50,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 @@ -54,6 +58,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") @@ -68,6 +73,7 @@ object MenuBar { menu("HUD") { buildHudMenu() } menu("GUI") { buildGuiMenu() } menu("Modules") { buildModulesMenu() } + menu("Automation Presets") { buildConfigPresetsMenu() } menu("Minecraft") { buildMinecraftMenu() } menu("Help") { buildHelpMenu() } buildGitHubReference() @@ -145,9 +151,6 @@ object MenuBar { menu("Baritone Settings") { buildConfigSettingsContext(BaritoneManager) } - menu("Automation Settings") { - buildConfigSettingsContext(AutomationConfig) - } } separator() menu("Open Folder") { @@ -279,6 +282,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 && configurables.none { it.name == newConfigName.get() }) 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 16f257832..993b46555 100644 --- a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt +++ b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt @@ -18,17 +18,21 @@ package com.lambda.gui.components import com.lambda.config.AbstractSetting +import com.lambda.config.AutomationConfig import com.lambda.config.Configurable +import com.lambda.config.MutableAutomationConfig +import com.lambda.config.UserAutomationConfig 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 { /** * 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() } @@ -38,21 +42,46 @@ object SettingsWidget { config.settings.forEach { it.reset(silent = true) } } lambdaTooltip("Resets all settings for this module to their default values") + 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})") + } + } } separator() - val toIgnoreSettings = if (config is Module) setOf(config.keybindSetting, config.disableOnReleaseSetting) else emptySet() - val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings + 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 - hiddenSettings 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/interaction/BaritoneManager.kt b/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt index 917453404..16275ef85 100644 --- a/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt +++ b/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt @@ -25,11 +25,11 @@ 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 -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 ed7338ffa..ac681d0e8 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.config.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..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 +import com.lambda.config.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..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 +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 @@ -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..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 +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 @@ -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..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,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.config.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..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 +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 @@ -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..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 +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 @@ -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..2c6dd6625 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -20,11 +20,11 @@ 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.configurations.ModuleConfig -import com.lambda.context.Automated -import com.lambda.context.AutomationConfig +import com.lambda.config.MutableAutomationConfig +import com.lambda.config.configurations.ModuleConfigs import com.lambda.config.settings.complex.Bind import com.lambda.context.SafeContext import com.lambda.event.Muteable @@ -67,7 +67,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 +120,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), MutableAutomationConfig { + final override var defaultAutomationConfig: AutomationConfig = AutomationConfig.Companion.DEFAULT + set(value) { + field = value + automationConfig = value + } + 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/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/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 4470717e5..b9b9a04ea 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.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 @@ -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,38 @@ 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") - } + private val pendingInteractions = ConcurrentLinkedQueue() - 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 breakConfig = object : BreakConfig by super.breakConfig { + override val rotateForBreak = false + override val doubleBreak = false + override val breaksPerTick = 1 } - 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 { + defaultAutomationConfig = automationConfig { + breakConfig.apply { + editTyped( + ::avoidLiquids, + ::avoidSupporting, + ::efficientOnly, + ::suitableToolsOnly + ) { defaultValue(false) } + hide( + ::rotateForBreak, + ::doubleBreak, + ::breaksPerTick + ) + } + hideAll(buildConfig, placeConfig, interactConfig, inventoryConfig, eatConfig) + } + listen { it.cancel() } listen { event -> event.cancel() 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..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,19 +17,11 @@ 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.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 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 +47,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 @@ -120,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) 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..0139228c7 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,8 @@ 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.SettingGroup +import com.lambda.config.AutomationConfig.Companion.automationConfig +import com.lambda.config.groups.BuildConfig import com.lambda.context.SafeContext import com.lambda.event.events.PlayerEvent import com.lambda.event.events.TickEvent @@ -36,6 +32,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 @@ -56,72 +53,24 @@ object PacketMine : Module( tag = ModuleTag.PLAYER ) { private enum class Group(override val displayName: String) : NamedEnum { - Break("Break"), - Build("Build"), - Rotation("Rotation"), - Inventory("Inventory"), - Hotbar("Hotbar"), + 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").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 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").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) - - override val breakConfig = BreakSettings(this, Group.Break).apply { - editTyped( - ::avoidLiquids, - ::avoidSupporting, - ::efficientOnly, - ::suitableToolsOnly - ) { defaultValue(false) } - ::swing.edit { defaultValue(BreakConfig.SwingMode.Start) } - - ::rebreak.insert(::rebreakMode, SettingGroup.InsertMode.Below) - ::rebreakMode.edit { visibility { rebreak } } - - ::sounds.insert( - ::renderQueue, - ::renderSize, - ::renderMode, - ::dynamicColor, - ::staticColor, - ::startColor, - ::endColor, - insertMode = SettingGroup.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.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() @@ -146,7 +95,35 @@ 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 { + breakConfig.apply { + editTyped( + ::avoidLiquids, + ::avoidSupporting, + ::efficientOnly, + ::suitableToolsOnly + ) { defaultValue(false) } + ::swing.edit { defaultValue(BreakConfig.SwingMode.Start) } + } + hotbarConfig.apply { + ::keepTicks.edit { defaultValue(0) } + } + hideAll(buildConfig, placeConfig, interactConfig, inventoryConfig, eatConfig) + } + listen { attackedThisTick = false } 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!") 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..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,10 +17,8 @@ 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.AutomationConfig.Companion.automationConfig +import com.lambda.config.groups.BuildConfig import com.lambda.config.settings.complex.Bind import com.lambda.context.SafeContext import com.lambda.event.events.MovementEvent @@ -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,42 @@ 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() + } + } + hideAll(buildConfig, breakConfig, interactConfig, inventoryConfig, eatConfig) + } + listen { val playerSupport = player.blockPos.down() val alreadySupported = blockState(playerSupport).hasSolidTopSurface(world, playerSupport, player) diff --git a/src/main/kotlin/com/lambda/task/Task.kt b/src/main/kotlin/com/lambda/task/Task.kt index 502337293..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 +import com.lambda.config.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..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 +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 @@ -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(),