Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/kotlin/com/lambda/command/commands/BuildCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
5 changes: 2 additions & 3 deletions src/main/kotlin/com/lambda/command/commands/ModuleCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
}
Expand All @@ -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))
}
Expand All @@ -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.")
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/com/lambda/config/AbstractSetting.kt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ abstract class AbstractSetting<T : Any>(
var visibility: () -> Boolean,
) : Jsonable, Nameable, Describable, Layout {
private val listeners = mutableListOf<ValueListener<T>>()
var disabled = { false }
var groups: MutableList<List<NamedEnum>> = mutableListOf()

var value by Delegates.observable(defaultValue) { _, from, to ->
Expand Down Expand Up @@ -152,6 +153,10 @@ abstract class AbstractSetting<T : Any>(
listeners.add(ValueListener(false, block))
}

fun disabled(predicate: () -> Boolean) = apply {
disabled = predicate
}

fun group(path: List<NamedEnum>, vararg continuation: NamedEnum) = apply {
groups.add(path + continuation)
}
Expand Down
209 changes: 209 additions & 0 deletions src/main/kotlin/com/lambda/config/AutomationConfig.kt
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

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<AbstractSetting<*>>()

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<Drawable>()

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 <T : Any> KProperty0<T>.edit(edits: TypedEditBuilder<T>.(AbstractSetting<T>) -> Unit) {
val setting = delegate as? AbstractSetting<T> ?: throw IllegalStateException("Setting delegate did not match current value's type")
TypedEditBuilder(this@AutomationConfig, listOf(setting)).edits(setting)
}

@SettingEditorDsl
internal inline fun <T : Any, R : Any> KProperty0<T>.editWith(
other: KProperty0<R>,
edits: TypedEditBuilder<T>.(AbstractSetting<R>) -> Unit
) {
val setting = delegate as? AbstractSetting<T> ?: throw IllegalStateException("Setting delegate did not match current value's type")
TypedEditBuilder(this@AutomationConfig, listOf(setting)).edits(other.delegate as AbstractSetting<R>)
}

@SettingEditorDsl
fun edit(
vararg settings: KProperty0<*>,
edits: BasicEditBuilder.() -> Unit
) { BasicEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List<AbstractSetting<*>>).apply(edits) }

@SettingEditorDsl
internal inline fun <T : Any> editWith(
vararg settings: KProperty0<*>,
other: KProperty0<T>,
edits: BasicEditBuilder.(AbstractSetting<T>) -> Unit
) { BasicEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List<AbstractSetting<*>>).edits(other.delegate as AbstractSetting<T>) }

@SettingEditorDsl
internal inline fun <T : Any> editTyped(
vararg settings: KProperty0<T>,
edits: TypedEditBuilder<T>.() -> Unit
) { TypedEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List<AbstractSetting<T>>).apply(edits) }

@SettingEditorDsl
internal inline fun <T : Any, R : Any> editTypedWith(
vararg settings: KProperty0<T>,
other: KProperty0<R>,
edits: TypedEditBuilder<T>.(AbstractSetting<R>) -> Unit
) = TypedEditBuilder(this@AutomationConfig, settings.map { it.delegate } as List<AbstractSetting<T>>).edits(other.delegate as AbstractSetting<R>)

@SettingEditorDsl
fun hide(vararg settings: KProperty0<*>) {
hideAll((settings.map { it.delegate } as List<AbstractSetting<*>>))
}

@SettingEditorDsl
fun hideAll(settingGroup: SettingGroup) = hideAll(settingGroup.settings)

@SettingEditorDsl
fun hideAll(settings: Collection<AbstractSetting<*>>) {
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<AbstractSetting<*>>)) {
hiddenSettings.add(it)
true
} else false
}
}

open class BasicEditBuilder(val c: AutomationConfig, open val settings: Collection<AbstractSetting<*>>) {
@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<List<NamedEnum>>) =
settings.forEach { it.groups = groups }
}

open class TypedEditBuilder<T : Any>(
c: AutomationConfig,
override val settings: Collection<AbstractSetting<T>>
) : BasicEditBuilder(c, settings) {
@SettingEditorDsl
fun defaultValue(value: T) =
settings.forEach {
it.defaultValue = value
it.value = value
}
}

enum class InsertMode {
Above,
Below
}
}
5 changes: 3 additions & 2 deletions src/main/kotlin/com/lambda/config/Configurable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -69,7 +68,9 @@ abstract class Configurable(
private fun registerConfigurable() = configuration.configurables.add(this)

inline fun <reified T : AbstractSetting<*>> 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
}

Expand Down
Loading
Loading