diff --git a/src/main/kotlin/com/lambda/config/AbstractSetting.kt b/src/main/kotlin/com/lambda/config/AbstractSetting.kt index c7c8fb577..2cb0dc346 100644 --- a/src/main/kotlin/com/lambda/config/AbstractSetting.kt +++ b/src/main/kotlin/com/lambda/config/AbstractSetting.kt @@ -33,6 +33,7 @@ import com.lambda.context.SafeContext import com.lambda.gui.Layout import com.lambda.threading.runSafe import com.lambda.util.Communication.info +import com.lambda.util.Describable import com.lambda.util.Nameable import com.lambda.util.NamedEnum import com.lambda.util.extension.CommandBuilder @@ -94,13 +95,14 @@ import kotlin.reflect.KProperty * @property visibility A function that determines whether the setting is visible. */ abstract class AbstractSetting( - internal val defaultValue: T, + override var name: String, + internal var defaultValue: T, val type: Type, - val description: String, - val visibility: () -> Boolean, -) : Jsonable, Nameable, Layout { + override var description: String, + var visibility: () -> Boolean, +) : Jsonable, Nameable, Describable, Layout { private val listeners = mutableListOf>() - val groups: MutableList> = mutableListOf() + var groups: MutableList> = mutableListOf() var value by Delegates.observable(defaultValue) { _, from, to -> listeners.forEach { @@ -185,7 +187,7 @@ abstract class AbstractSetting( val previous = this@AbstractSetting.value try { loadFromJson(parsed) - } catch (e: Exception) { + } catch (_: Exception) { return@executeWithResult failure("Failed to load $valueString as a ${type::class.simpleName} for $name in ${config.name}.") } ConfigCommand.info(setMessage(previous, this@AbstractSetting.value)) diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index 8f63a7183..51dac7ec8 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -59,7 +59,7 @@ import java.awt.Color abstract class Configurable( private val configuration: Configuration, ) : Jsonable, Nameable { - val settings = mutableSetOf>() + val settings = mutableListOf>() init { registerConfigurable() diff --git a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt index c5edd44de..704ca6fea 100644 --- a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt @@ -31,84 +31,84 @@ import java.awt.Color class BreakSettings( c: Configurable, - groupPath: List = emptyList(), + baseGroup: NamedEnum, vis: () -> Boolean = { true }, -) : BreakConfig { +) : BreakConfig, SettingGroup(c) { 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(groupPath, Group.General) - override val sorter by c.setting("Sorter", SortMode.Closest, "The order in which breaks are performed", visibility = vis).group(groupPath, Group.General) - override val rebreak by c.setting("Rebreak", true, "Re-breaks blocks after they've been broken once", visibility = vis).group(groupPath, Group.General) + override val breakMode by c.setting("Break Mode", BreakMode.Packet, visibility = vis).group(baseGroup, Group.General) + override val sorter by c.setting("Sorter", 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) // Double break - override val doubleBreak by c.setting("Double Break", true, "Allows breaking two blocks at once", visibility = vis).group(groupPath, 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(groupPath, Group.General) + 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) // 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(groupPath, 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(groupPath, 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(groupPath, 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", 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(groupPath, Group.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) // Timing - override val breakStageMask 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(groupPath, Group.General) + override val breakStageMask 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) // 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(groupPath, 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", visibility = vis).group(baseGroup, Group.General) // Swing - override val swing by c.setting("Swing Mode", SwingMode.Constant, "The times at which to swing the players hand", visibility = vis).group(groupPath, Group.General) - override val swingType by c.setting("Break Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { vis() && swing != SwingMode.None }.group(groupPath, Group.General) + 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) // Rotate - override val rotateForBreak by c.setting("Rotate For Break", false, "Rotate towards block while breaking", visibility = vis).group(groupPath, Group.General) + override val rotateForBreak by c.setting("Rotate For Break", false, "Rotate towards block while breaking", visibility = vis).group(baseGroup, Group.General) // Pending / Post - override val breakConfirmation by c.setting("Break Confirmation", BreakConfirmationMode.BreakThenAwait, "The style of confirmation used when breaking", visibility = vis).group(groupPath, Group.General) - override val breaksPerTick by c.setting("Breaks Per Tick", 5, 1..30, 1, "Maximum instant block breaks per tick", visibility = vis).group(groupPath, Group.General) - override val maxPendingBreaks by c.setting("Max Pending Breaks", 15, 1..30, 1, "The maximum amount of pending breaks", visibility = vis).group(groupPath, Group.General) + 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) // Block - override val avoidLiquids by c.setting("Avoid Liquids", true, "Avoids breaking blocks that would cause liquid to spill", visibility = vis).group(groupPath, Group.General) - override val avoidSupporting by c.setting("Avoid Supporting", true, "Avoids breaking the block supporting the player", visibility = vis).group(groupPath, Group.General) - override val breakWeakBlocks by c.setting("Break Weak Blocks", false, "Break blocks that dont have structural integrity (e.g: grass)", visibility = vis).group(groupPath, Group.General) - override val ignoredBlocks by c.setting("Ignored Blocks", allSigns, description = "Blocks that wont be broken", visibility = vis).group(groupPath, Group.General) + 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 breakWeakBlocks by c.setting("Break Weak Blocks", false, "Break blocks that dont have structural integrity (e.g: grass)", 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) // Tool - override val suitableToolsOnly by c.setting("Suitable Tools Only", true, "Only use tools suitable for the given block (will get the item drop)", visibility = vis).group(groupPath, Group.General) - override val forceSilkTouch by c.setting("Force Silk Touch", false, "Force silk touch when breaking blocks", visibility = vis).group(groupPath, Group.General) - override val forceFortunePickaxe by c.setting("Force Fortune Pickaxe", false, "Force fortune pickaxe when breaking blocks", visibility = vis).group(groupPath, Group.General) - override val minFortuneLevel by c.setting("Min Fortune Level", 1, 1..3, 1, "The minimum fortune level to use") { vis() && forceFortunePickaxe }.group(groupPath, Group.General) - override val useWoodenTools by c.setting("Use Wooden Tools", true, "Use wooden tools when breaking blocks", visibility = vis).group(groupPath, Group.General) - override val useStoneTools by c.setting("Use Stone Tools", true, "Use stone tools when breaking blocks", visibility = vis).group(groupPath, Group.General) - override val useIronTools by c.setting("Use Iron Tools", true, "Use iron tools when breaking blocks", visibility = vis).group(groupPath, Group.General) - override val useDiamondTools by c.setting("Use Diamond Tools", true, "Use diamond tools when breaking blocks", visibility = vis).group(groupPath, Group.General) - override val useGoldTools by c.setting("Use Gold Tools", true, "Use gold tools when breaking blocks", visibility = vis).group(groupPath, Group.General) - override val useNetheriteTools by c.setting("Use Netherite Tools", true, "Use netherite tools when breaking blocks", visibility = vis).group(groupPath, 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) // Cosmetics - override val sounds by c.setting("Break Sounds", true, "Plays the breaking sounds", visibility = vis).group(groupPath, Group.Cosmetic) - override val particles by c.setting("Particles", true, "Renders the breaking particles", visibility = vis).group(groupPath, Group.Cosmetic) - override val breakingTexture by c.setting("Breaking Overlay", true, "Overlays the breaking texture at its different stages", visibility = vis).group(groupPath, Group.Cosmetic) + 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) // Modes - override val renders by c.setting("Renders", true, "Enables the render settings for breaking progress", visibility = vis).group(groupPath, Group.Cosmetic) - override val animation by c.setting("Animation", AnimationMode.Out, "The style of animation used for the box") { vis() && renders }.group(groupPath, Group.Cosmetic) + 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) // Fill - override val fill by c.setting("Fill", true, "Renders the sides of the box to display break progress") { vis() && renders }.group(groupPath, 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(groupPath, 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(groupPath, 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(groupPath, 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(groupPath, Group.Cosmetic) + 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) // Outline - override val outline by c.setting("Outline", true, "Renders the lines of the box to display break progress") { vis() && renders }.group(groupPath, Group.Cosmetic) - override val outlineWidth by c.setting("Outline Width", 2, 0..5, 1, "The width of the outline") { vis() && renders && outline }.group(groupPath, 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(groupPath, 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(groupPath, 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(groupPath, 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(groupPath, Group.Cosmetic) + 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) } diff --git a/src/main/kotlin/com/lambda/config/groups/BuildConfig.kt b/src/main/kotlin/com/lambda/config/groups/BuildConfig.kt index 4e8c70271..5ff39bbdb 100644 --- a/src/main/kotlin/com/lambda/config/groups/BuildConfig.kt +++ b/src/main/kotlin/com/lambda/config/groups/BuildConfig.kt @@ -17,6 +17,7 @@ package com.lambda.config.groups +import com.lambda.interaction.request.rotating.visibilty.PointSelection import com.lambda.util.Describable import com.lambda.util.NamedEnum @@ -29,14 +30,15 @@ interface BuildConfig { val maxPendingInteractions: Int val interactionTimeout: Int - // Breaking - val breakConfig: BreakSettings + val useDefaultReach: Boolean + val attackReach: Double + val interactReach: Double + val scanReach: Double - // Placing - val placeConfig: PlaceSettings - - // Interacting - val interactConfig: InteractSettings + val strictRayCast: Boolean + val checkSideVisibility: Boolean + val resolution: Int + val pointSelection: PointSelection enum class SwingType( override val displayName: String, diff --git a/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt b/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt index c7d537870..4205fe605 100644 --- a/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt @@ -18,41 +18,42 @@ package com.lambda.config.groups import com.lambda.config.Configurable -import com.lambda.interaction.request.breaking.BreakConfig.BreakConfirmationMode -import com.lambda.interaction.request.placing.PlaceConfig +import com.lambda.interaction.request.rotating.visibilty.PointSelection import com.lambda.util.NamedEnum +import kotlin.math.max class BuildSettings( c: Configurable, - vararg groupPath: NamedEnum, + vararg baseGroup: NamedEnum, vis: () -> Boolean = { true }, -) : BuildConfig { +) : BuildConfig, SettingGroup(c) { enum class Group(override val displayName: String) : NamedEnum { General("General"), - Break("Break"), - Place("Place"), - Interact("Interact") + Reach("Reach"), + Scan("Scan") } // General - override val pathing by c.setting("Pathing", true, "Path to blocks", vis).group(*groupPath, Group.General) - override val stayInRange by c.setting("Stay In Range", true, "Stay in range of blocks", vis).group(*groupPath, Group.General) - override val collectDrops by c.setting("Collect All Drops", false, "Collect all drops when breaking blocks", vis).group(*groupPath, 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(*groupPath, 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(*groupPath, Group.General) - - // Breaking - override val breakConfig = BreakSettings(c, groupPath.toList() + Group.Break, vis) - - // Placing - override val placeConfig = PlaceSettings(c, groupPath.toList() + Group.Place, vis) - - //Interacting - override val interactConfig = InteractSettings(c, groupPath.toList() + Group.Interact, vis) - - override val interactionTimeout by c.setting("Interaction Timeout", 10, 1..30, 1, "Timeout for block breaks in ticks", unit = " ticks") { - vis() && (placeConfig.placeConfirmationMode != PlaceConfig.PlaceConfirmationMode.None - || breakConfig.breakConfirmation != BreakConfirmationMode.None - || interactConfig.interactConfirmationMode != InteractionConfig.InteractConfirmationMode.None) - }.group(*groupPath, Group.Break, BreakSettings.Group.General).group(*groupPath, Group.Place).group(*groupPath, Group.Interact) + 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 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 scanReach: Double get() = max(attackReach, interactReach) + + 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 checkSideVisibility by c.setting("Visibility Check", true, "Whether to check if an AABB side is visible", 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) + + companion object { + const val DEFAULT_ATTACK_REACH = 3.0 + const val DEFAULT_INTERACT_REACH = 4.5 + } } diff --git a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt index f4981a86a..f5cec297d 100644 --- a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt @@ -19,14 +19,13 @@ package com.lambda.config.groups import com.lambda.config.Configurable import com.lambda.util.NamedEnum -import net.minecraft.item.Item import net.minecraft.item.Items class EatSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : EatConfig { +) : EatConfig, SettingGroup(c) { val nutritiousFoodDefaults = listOf(Items.APPLE, Items.BAKED_POTATO, Items.BEEF, Items.BEETROOT, Items.BEETROOT_SOUP, Items.BREAD, Items.CARROT, Items.CHICKEN, Items.CHORUS_FRUIT, Items.COD, Items.COOKED_BEEF, Items.COOKED_CHICKEN, Items.COOKED_COD, Items.COOKED_MUTTON, Items.COOKED_PORKCHOP, Items.COOKED_RABBIT, Items.COOKED_SALMON, Items.COOKIE, Items.DRIED_KELP, Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE, Items.GOLDEN_CARROT, Items.HONEY_BOTTLE, Items.MELON_SLICE, Items.MUSHROOM_STEW, Items.MUTTON, Items.POISONOUS_POTATO, Items.PORKCHOP, Items.POTATO, Items.PUFFERFISH, Items.PUMPKIN_PIE, Items.RABBIT, Items.RABBIT_STEW, Items.ROTTEN_FLESH, Items.SALMON, Items.SPIDER_EYE, Items.SUSPICIOUS_STEW, Items.SWEET_BERRIES, Items.GLOW_BERRIES, Items.TROPICAL_FISH) val resistanceFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE) val regenerationFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE) diff --git a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt index 3deba31f3..11c9bd66c 100644 --- a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt @@ -26,8 +26,8 @@ class HotbarSettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : HotbarConfig { - override val keepTicks by c.setting("Keep Ticks", 3, 0..20, 1, "The number of ticks to keep the current hotbar selection active", " ticks", visibility = vis).group(baseGroup) +) : 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) diff --git a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt index 24c497d59..4c4b885c2 100644 --- a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt @@ -24,12 +24,12 @@ import com.lambda.util.NamedEnum class InteractSettings( c: Configurable, - groupPath: List = emptyList(), + baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : InteractConfig { - override val rotate by c.setting("Rotate For Interact", true, "Rotates the player to look at the block when interacting", visibility = vis).group(groupPath) - override val swingHand by c.setting("Swing On Interact", true, "Swings the players hand after interacting", visibility = vis).group(groupPath) - override val interactStageMask by c.setting("Interact Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which interact actions are performed", visibility = vis).group(groupPath) - override val interactSwingType by c.setting("Interact Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { vis() && swingHand }.group(groupPath) - override val interactConfirmationMode by c.setting("Interact Confirmation Mode", InteractionConfig.InteractConfirmationMode.InteractThenAwait, "The style of confirmation for interactions", visibility = vis).group(groupPath) +) : 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 swingHand by c.setting("Swing On Interact", true, "Swings the players hand after interacting", visibility = vis).group(baseGroup) + override val interactStageMask 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) } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/InteractionConfig.kt b/src/main/kotlin/com/lambda/config/groups/InteractionConfig.kt deleted file mode 100644 index e8bca2ca2..000000000 --- a/src/main/kotlin/com/lambda/config/groups/InteractionConfig.kt +++ /dev/null @@ -1,72 +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.interaction.request.rotating.visibilty.PointSelection -import com.lambda.util.Describable -import com.lambda.util.NamedEnum - -interface InteractionConfig { - /** - * Maximum entity interaction distance - */ - val attackReach: Double - - /** - * Maximum block interaction distance - */ - val interactReach: Double - - /** - * Maximum possible interaction distance - * - * Equals to `max(attackReach, placeReach)` if both are present. Equals to one of them otherwise - */ - val scanReach: Double - - /** - * Whether to include the environment to the ray cast context. - * - * if false: skips walls for entities, skips entities for blocks. - */ - val strictRayCast: Boolean - - /** - * Whether to check if an AABB side is visible. - */ - val checkSideVisibility: Boolean - - /** - * Grid divisions count per surface of the hit box. - */ - val resolution: Int - - /** - * The way to select the best point. - */ - val pointSelection: PointSelection - - enum class InteractConfirmationMode( - override val displayName: String, - override val description: String - ): NamedEnum, Describable { - None("No confirmation", "Send the interaction and don’t wait for the server. Lowest latency, but effects may briefly appear if the server rejects it."), - InteractThenAwait("Interact now, confirm later", "Show interaction effects immediately, then wait for the server to confirm. Feels instant while still verifying the result."), - AwaitThenInteract("Confirm first, then interact", "Wait for the server response before showing any effects. Most accurate and safe, but adds a short delay.") - } -} diff --git a/src/main/kotlin/com/lambda/config/groups/InteractionSettings.kt b/src/main/kotlin/com/lambda/config/groups/InteractionSettings.kt deleted file mode 100644 index 82da26d15..000000000 --- a/src/main/kotlin/com/lambda/config/groups/InteractionSettings.kt +++ /dev/null @@ -1,69 +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.Configurable -import com.lambda.interaction.request.rotating.visibilty.PointSelection -import com.lambda.util.NamedEnum -import com.lambda.util.world.raycast.InteractionMask -import kotlin.math.max - -class InteractionSettings( - c: Configurable, - baseGroup: NamedEnum, - private val usage: InteractionMask, - vis: () -> Boolean = { true }, -) : InteractionConfig { - // Reach - private val useDefaultReach by c.setting("Default Reach", true, "Whether to use vanilla interaction ranges", vis).group(baseGroup) - private val attackReachSetting = if (usage.entity) c.setting("Attack Reach", DEFAULT_ATTACK_REACH, 1.0..10.0, 0.01, "Maximum entity interaction distance") { vis() && !useDefaultReach }.group(baseGroup) else null - private val interactReachSetting = if (usage.block) c.setting("Interact Reach", DEFAULT_INTERACT_REACH, 1.0..10.0, 0.01, "Maximum block interaction distance") { vis() && !useDefaultReach }.group(baseGroup) else null - - override val attackReach: Double get() { - check(usage.entity) { - "Given interaction config has no attack reach implementation" - } - - return if (useDefaultReach) DEFAULT_ATTACK_REACH else attackReachSetting!!.value - } - - override val interactReach: Double get() { - check(usage.block) { - "Given interaction config has no place reach implementation" - } - - return if (useDefaultReach) DEFAULT_INTERACT_REACH else interactReachSetting!!.value - } - - override val scanReach: Double get() = when (usage) { - InteractionMask.Entity -> attackReach - InteractionMask.Block -> interactReach - InteractionMask.Both -> max(attackReach, interactReach) - } - - // Point scan - override val strictRayCast by c.setting("Strict Raycast", false, "Whether to include the environment to the ray cast context", vis).group(baseGroup) - override val checkSideVisibility by c.setting("Visibility Check", true, "Whether to check if an AABB side is visible", vis).group(baseGroup) - 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) - override val pointSelection by c.setting("Point Selection", PointSelection.Optimum, "The strategy to select the best hit point", vis).group(baseGroup) - - companion object { - const val DEFAULT_ATTACK_REACH = 3.0 - const val DEFAULT_INTERACT_REACH = 4.5 - } -} diff --git a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt index 68b6f1f2a..f2a38e41f 100644 --- a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt @@ -26,7 +26,7 @@ class InventorySettings( c: Configurable, baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : InventoryConfig { +) : InventoryConfig, SettingGroup(c) { enum class Group(override val displayName: String) : NamedEnum { Container("Container"), Access("Access") diff --git a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt index e4578ca5a..9c44e5a27 100644 --- a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt @@ -26,17 +26,17 @@ import com.lambda.util.NamedEnum class PlaceSettings( c: Configurable, - groupPath: List = emptyList(), + baseGroup: NamedEnum, vis: () -> Boolean = { true } -) : PlaceConfig { - override val rotateForPlace by c.setting("Rotate For Place", true, "Rotate towards block while placing", visibility = vis).group(groupPath) - override val airPlace by c.setting("Air Place", AirPlaceMode.None, "Allows for placing blocks without adjacent faces", visibility = vis).group(groupPath) - 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(groupPath) - override val placeStageMask by c.setting("Place Stage mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which place actions are performed", visibility = vis).group(groupPath) - override val placeConfirmationMode by c.setting("Place Confirmation", PlaceConfirmationMode.PlaceThenAwait, "Wait for block placement confirmation", visibility = vis).group(groupPath) - override val maxPendingPlacements by c.setting("Max Pending Placements", 5, 0..30, 1, "The maximum amount of pending placements", visibility = vis).group(groupPath) - override val placementsPerTick by c.setting("Places Per Tick", 1, 1..30, 1, "Maximum instant block places per tick", visibility = vis).group(groupPath) - override val swing by c.setting("Swing On Place", true, "Swings the players hand when placing", visibility = vis).group(groupPath) - override val swingType by c.setting("Place Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { vis() && swing }.group(groupPath) - override val sounds by c.setting("Place Sounds", true, "Plays the placing sounds", visibility = vis).group(groupPath) +) : 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 placeStageMask 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) } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt index 505d9cfdb..d84e1dd6c 100644 --- a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt @@ -32,7 +32,7 @@ class RotationSettings( c: Configurable, baseGroup: NamedEnum? = null, vis: () -> Boolean = { true } -) : RotationConfig { +) : RotationConfig, SettingGroup(c) { override var rotationMode by c.setting("Mode", RotationMode.Sync, "How the player is being rotated on interaction", vis).group(baseGroup) /** How many ticks to keep the rotation before resetting */ diff --git a/src/main/kotlin/com/lambda/config/groups/SettingGroup.kt b/src/main/kotlin/com/lambda/config/groups/SettingGroup.kt new file mode 100644 index 000000000..71eb1469a --- /dev/null +++ b/src/main/kotlin/com/lambda/config/groups/SettingGroup.kt @@ -0,0 +1,151 @@ +/* + * 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 130164626..0fa2ee273 100644 --- a/src/main/kotlin/com/lambda/config/groups/Targeting.kt +++ b/src/main/kotlin/com/lambda/config/groups/Targeting.kt @@ -50,11 +50,11 @@ import java.util.* */ abstract class Targeting( private val owner: Configurable, - private val baseGroup: NamedEnum, + baseGroup: NamedEnum, private val predicate: () -> Boolean = { true }, private val defaultRange: Double, private val maxRange: Double, -) : TargetingConfig { +) : TargetingConfig, SettingGroup(owner) { /** * The range within which entities can be targeted. This value is configurable and constrained diff --git a/src/main/kotlin/com/lambda/config/settings/CharSetting.kt b/src/main/kotlin/com/lambda/config/settings/CharSetting.kt index 97530dfb7..2e2abaea3 100644 --- a/src/main/kotlin/com/lambda/config/settings/CharSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/CharSetting.kt @@ -33,11 +33,12 @@ import net.minecraft.command.CommandRegistryAccess * @see [com.lambda.config.Configurable] */ class CharSetting( - override val name: String, + override var name: String, defaultValue: Char, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(Char::class.java).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt b/src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt index 0fff87d72..00f04629b 100644 --- a/src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt @@ -24,11 +24,12 @@ import com.lambda.config.AbstractSetting import com.lambda.gui.dsl.ImGuiBuilder open class FunctionSetting( - override val name: String, + override var name: String, defaultValue: () -> T, description: String, visibility: () -> Boolean, ) : AbstractSetting<() -> T>( + name, defaultValue, TypeToken.get(defaultValue::class.java).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt index efa7d555c..d553e6587 100644 --- a/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt @@ -19,6 +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.gui.dsl.ImGuiBuilder import imgui.ImGui import imgui.ImGui.calcTextSize @@ -32,13 +33,15 @@ import kotlin.reflect.KProperty * @see [com.lambda.config.Configurable] */ abstract class NumericSetting( + override var name: String, value: T, - open val range: ClosedRange, - open val step: T, + open var range: ClosedRange, + open var step: T, description: String, - val unit: String, + var unit: String, visibility: () -> Boolean ) : AbstractSetting( + name, value, TypeToken.get(value::class.java).type, description, @@ -92,4 +95,22 @@ abstract class NumericSetting( dummy(calcTextSize(resetButtonText).x + style.framePadding.x * 2.0f, ImGui.getFrameHeight()) } } + + @SettingGroup.SettingEditorDsl + @Suppress("unchecked_cast") + fun SettingGroup.TypedEditBuilder.range(range: ClosedRange) { + (settings as Collection>).forEach { it.range = range } + } + + @SettingGroup.SettingEditorDsl + @Suppress("unchecked_cast") + fun SettingGroup.TypedEditBuilder.step(step: T) { + (settings as Collection>).forEach { it.step = step } + } + + @SettingGroup.SettingEditorDsl + @Suppress("unchecked_cast") + fun SettingGroup.TypedEditBuilder<*>.unit(unit: String) { + (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 41fe12402..17d68c740 100644 --- a/src/main/kotlin/com/lambda/config/settings/StringSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/StringSetting.kt @@ -23,6 +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.gui.dsl.ImGuiBuilder import com.lambda.util.extension.CommandBuilder import imgui.flag.ImGuiInputTextFlags @@ -32,13 +33,14 @@ import net.minecraft.command.CommandRegistryAccess * @see [com.lambda.config.Configurable] */ class StringSetting( - override val name: String, + override var name: String, defaultValue: String, - val multiline: Boolean = false, - val flags: Int = ImGuiInputTextFlags.None, + var multiline: Boolean = false, + var flags: Int = ImGuiInputTextFlags.None, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(String::class.java).type, description, @@ -60,4 +62,16 @@ class StringSetting( } } } + + @SettingGroup.SettingEditorDsl + @Suppress("unchecked_cast") + fun SettingGroup.TypedEditBuilder.multiline(multiline: Boolean) { + (settings as Collection).forEach { it.multiline = multiline } + } + + @SettingGroup.SettingEditorDsl + @Suppress("unchecked_cast") + fun SettingGroup.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 afa6fee6b..51091713c 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt @@ -21,6 +21,7 @@ import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson import com.lambda.config.AbstractSetting +import com.lambda.config.groups.SettingGroup import com.lambda.gui.dsl.ImGuiBuilder import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -29,13 +30,14 @@ import java.lang.reflect.Type * @see [com.lambda.config.Configurable] */ class ListSetting( - override val name: String, - private val immutableList: List, + override var name: String, + private var immutableList: List, defaultValue: MutableList, type: Type, description: String, visibility: () -> Boolean, ) : AbstractSetting>( + name, defaultValue, type, description, @@ -71,4 +73,10 @@ class ListSetting( value = strList } + + @SettingGroup.SettingEditorDsl + @Suppress("unchecked_cast") + fun SettingGroup.TypedEditBuilder>.immutableList(immutableList: List) { + (settings as Collection>).forEach { it.immutableList = immutableList } + } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt index 9d90e18f2..cdf49cb6e 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/MapSetting.kt @@ -25,12 +25,13 @@ import java.lang.reflect.Type * @see [com.lambda.config.Configurable] */ class MapSetting( - override val name: String, + override var name: String, defaultValue: MutableMap, type: Type, description: String, visibility: () -> Boolean, ) : AbstractSetting>( + name, defaultValue, type, description, 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 15eea6a07..ab6b2b73d 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt @@ -21,6 +21,7 @@ import com.google.gson.JsonElement import com.google.gson.reflect.TypeToken import com.lambda.Lambda.gson import com.lambda.config.AbstractSetting +import com.lambda.config.groups.SettingGroup import com.lambda.gui.dsl.ImGuiBuilder import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type @@ -29,13 +30,14 @@ import java.lang.reflect.Type * @see [com.lambda.config.Configurable] */ class SetSetting( - override val name: String, - private val immutableSet: Set, + override var name: String, + private var immutableSet: Set, defaultValue: MutableSet, type: Type, description: String, visibility: () -> Boolean, ) : AbstractSetting>( + name, defaultValue, type, description, @@ -72,4 +74,10 @@ class SetSetting( value = strSet } + + @SettingGroup.SettingEditorDsl + @Suppress("unchecked_cast") + fun SettingGroup.TypedEditBuilder>.immutableSet(immutableSet: Set) { + (settings as Collection>).forEach { it.immutableSet = immutableSet } + } } diff --git a/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt b/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt index 25b679a52..44845c99f 100644 --- a/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/comparable/BooleanSetting.kt @@ -31,11 +31,12 @@ import net.minecraft.command.CommandRegistryAccess * @see [com.lambda.config.Configurable] */ class BooleanSetting( - override val name: String, + override var name: String, defaultValue: Boolean, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(Boolean::class.java).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt b/src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt index 0f9936909..47739ff5f 100644 --- a/src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/comparable/EnumSetting.kt @@ -37,11 +37,12 @@ import kotlin.properties.Delegates * @see [com.lambda.config.Configurable] */ class EnumSetting>( - override val name: String, + override var name: String, defaultValue: T, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(defaultValue.declaringJavaClass).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt index dc81b46c4..35c7b1e6c 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/BlockPosSetting.kt @@ -33,11 +33,12 @@ import net.minecraft.util.math.BlockPos * @see [com.lambda.config.Configurable] */ class BlockPosSetting( - override val name: String, + override var name: String, defaultValue: BlockPos, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(BlockPos::class.java).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt index ccd10b615..7833fe4cd 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/BlockSetting.kt @@ -32,11 +32,12 @@ import net.minecraft.command.CommandRegistryAccess * @see [com.lambda.config.Configurable] */ class BlockSetting( - override val name: String, + override var name: String, defaultValue: Block, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(Block::class.java).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt index 0c56e5bb2..553b5eb72 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/ColorSetting.kt @@ -33,11 +33,12 @@ import java.awt.Color * @see [com.lambda.config.Configurable] */ class ColorSetting( - override val name: String, + override var name: String, defaultValue: Color, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(Color::class.java).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt index 4dddcc01a..e071399f5 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt @@ -36,11 +36,12 @@ import net.minecraft.command.CommandRegistryAccess import org.lwjgl.glfw.GLFW class KeybindSetting( - override val name: String, + override var name: String, defaultValue: KeyCode, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(KeyCode::class.java).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt index bf4f3c8d5..afd243170 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/Vec3dSetting.kt @@ -29,11 +29,12 @@ import net.minecraft.command.CommandRegistryAccess import net.minecraft.util.math.Vec3d class Vec3dSetting( - override val name: String, + override var name: String, defaultValue: Vec3d, description: String, visibility: () -> Boolean, ) : AbstractSetting( + name, defaultValue, TypeToken.get(Vec3d::class.java).type, description, diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt b/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt index 0364ccaaa..0856ee2f1 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt @@ -32,14 +32,15 @@ import kotlin.math.roundToInt * @see [com.lambda.config.Configurable] */ class DoubleSetting( - override val name: String, + override var name: String, defaultValue: Double, - override val range: ClosedRange, - override val step: Double, + override var range: ClosedRange, + override var step: Double, description: String, unit: String, visibility: () -> Boolean ) : NumericSetting( + name, defaultValue, range, step, diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt b/src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt index e0aeb5ce3..ad3e5a830 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt @@ -31,14 +31,15 @@ import kotlin.math.roundToInt * @see [com.lambda.config.Configurable] */ class FloatSetting( - override val name: String, + override var name: String, defaultValue: Float, - override val range: ClosedRange, - override val step: Float = 1f, + override var range: ClosedRange, + override var step: Float = 1f, description: String, unit: String, visibility: () -> Boolean ) : NumericSetting( + name, defaultValue, range, step, diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt b/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt index e92ac05ea..7eb0eb056 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt @@ -30,14 +30,15 @@ import net.minecraft.command.CommandRegistryAccess * @see [com.lambda.config.Configurable] */ class IntegerSetting( - override val name: String, + override var name: String, defaultValue: Int, - override val range: ClosedRange, - override val step: Int = 1, + override var range: ClosedRange, + override var step: Int = 1, description: String, unit: String, visibility: () -> Boolean ) : NumericSetting( + name, defaultValue, range, step, diff --git a/src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt b/src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt index 7b253d331..00a2d8d61 100644 --- a/src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt @@ -30,14 +30,15 @@ import net.minecraft.command.CommandRegistryAccess * @see [com.lambda.config.Configurable] */ class LongSetting( - override val name: String, + override var name: String, defaultValue: Long, - override val range: ClosedRange, - override val step: Long = 1, + override var range: ClosedRange, + override var step: Long = 1, description: String, unit: String, visibility: () -> Boolean ) : NumericSetting( + name, defaultValue, range, step, diff --git a/src/main/kotlin/com/lambda/context/Automated.kt b/src/main/kotlin/com/lambda/context/Automated.kt index 0cbbeea57..e5e6bbea5 100644 --- a/src/main/kotlin/com/lambda/context/Automated.kt +++ b/src/main/kotlin/com/lambda/context/Automated.kt @@ -19,20 +19,20 @@ package com.lambda.context import com.lambda.config.groups.BuildConfig import com.lambda.config.groups.EatConfig -import com.lambda.config.groups.InteractionConfig +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 Automated { val buildConfig: BuildConfig + val breakConfig: BreakConfig + val placeConfig: PlaceConfig + val interactConfig: InteractConfig val rotationConfig: RotationConfig - val interactionConfig: InteractionConfig val inventoryConfig: InventoryConfig val hotbarConfig: HotbarConfig val eatConfig: EatConfig -} - -val Automated.breakConfig get() = buildConfig.breakConfig -val Automated.placeConfig get() = buildConfig.placeConfig -val Automated.interactConfig get() = buildConfig.interactConfig \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/context/AutomationConfig.kt b/src/main/kotlin/com/lambda/context/AutomationConfig.kt index d6d78cd51..03f4f20b2 100644 --- a/src/main/kotlin/com/lambda/context/AutomationConfig.kt +++ b/src/main/kotlin/com/lambda/context/AutomationConfig.kt @@ -19,22 +19,26 @@ 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.InteractionSettings +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 -import com.lambda.util.world.raycast.InteractionMask 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"), Interaction("Interaction"), Inventory("Inventory"), @@ -47,8 +51,10 @@ object AutomationConfig : Configurable(LambdaConfig), Automated { 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 interactionConfig = InteractionSettings(this, Group.Interaction, InteractionMask.Both) override val inventoryConfig = InventorySettings(this, Group.Inventory) override val hotbarConfig = HotbarSettings(this, Group.Hotbar) override val eatConfig = EatSettings(this, Group.Eat) diff --git a/src/main/kotlin/com/lambda/interaction/construction/context/BreakContext.kt b/src/main/kotlin/com/lambda/interaction/construction/context/BreakContext.kt index f044a7f5b..e6df5e6b9 100644 --- a/src/main/kotlin/com/lambda/interaction/construction/context/BreakContext.kt +++ b/src/main/kotlin/com/lambda/interaction/construction/context/BreakContext.kt @@ -84,7 +84,7 @@ data class BreakContext( private fun Vec3d.distance(vec: Vec3d, block: Block): Double { val d = vec.x - x val e = (vec.y - y).let { - if (block is FallingBlock) it - (interactionConfig.attackReach / 2) + if (block is FallingBlock) it - (buildConfig.attackReach / 2) else it } val f = vec.z - z diff --git a/src/main/kotlin/com/lambda/interaction/construction/context/InteractionContext.kt b/src/main/kotlin/com/lambda/interaction/construction/context/InteractionContext.kt index 37d392695..8e2bd04e2 100644 --- a/src/main/kotlin/com/lambda/interaction/construction/context/InteractionContext.kt +++ b/src/main/kotlin/com/lambda/interaction/construction/context/InteractionContext.kt @@ -18,7 +18,6 @@ package com.lambda.interaction.construction.context import com.lambda.context.Automated -import com.lambda.context.interactConfig import com.lambda.graphics.renderer.esp.DirectionMask.mask import com.lambda.graphics.renderer.esp.ShapeBuilder import com.lambda.interaction.request.LogContext diff --git a/src/main/kotlin/com/lambda/interaction/construction/context/PlaceContext.kt b/src/main/kotlin/com/lambda/interaction/construction/context/PlaceContext.kt index b81db31e6..752bce524 100644 --- a/src/main/kotlin/com/lambda/interaction/construction/context/PlaceContext.kt +++ b/src/main/kotlin/com/lambda/interaction/construction/context/PlaceContext.kt @@ -19,7 +19,6 @@ package com.lambda.interaction.construction.context import com.lambda.Lambda.mc import com.lambda.context.Automated -import com.lambda.context.placeConfig import com.lambda.graphics.renderer.esp.DirectionMask.mask import com.lambda.graphics.renderer.esp.ShapeBuilder import com.lambda.interaction.request.LogContext diff --git a/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt b/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt index 7c819c45c..53a607ffb 100644 --- a/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt +++ b/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt @@ -18,8 +18,6 @@ package com.lambda.interaction.construction.simulation import com.lambda.context.AutomatedSafeContext -import com.lambda.context.breakConfig -import com.lambda.context.placeConfig import com.lambda.interaction.construction.blueprint.Blueprint import com.lambda.interaction.construction.context.BreakContext import com.lambda.interaction.construction.context.InteractionContext @@ -203,7 +201,7 @@ object BuildSimulator { val airPlace = placing && placeConfig.airPlace.isEnabled boxes.forEach { box -> - val refinedSides = if (interactionConfig.checkSideVisibility) { + val refinedSides = if (buildConfig.checkSideVisibility) { box.getVisibleSurfaces(eye).let { visibleSides -> sides?.let { specific -> visibleSides.intersect(specific) @@ -214,36 +212,36 @@ object BuildSimulator { scanSurfaces( box, refinedSides, - interactionConfig.resolution, + buildConfig.resolution, preProcessing.surfaceScan ) { hitSide, vec -> val distSquared = eye distSq vec - if (distSquared > interactionConfig.interactReach.pow(2)) { + if (distSquared > buildConfig.interactReach.pow(2)) { misses.add(vec) return@scanSurfaces } val newRotation = eye.rotationTo(vec) - val hit = if (interactionConfig.strictRayCast) { - val rayCast = newRotation.rayCast(interactionConfig.interactReach, eye) + val hit = if (buildConfig.strictRayCast) { + val rayCast = newRotation.rayCast(buildConfig.interactReach, eye) when { rayCast != null && (!airPlace || eye distSq rayCast.pos <= distSquared) -> rayCast.blockResult airPlace -> { - val hitVec = newRotation.castBox(box, interactionConfig.interactReach, eye) + val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye) BlockHitResult(hitVec, hitSide, pos, false) } else -> null } } else { - val hitVec = newRotation.castBox(box, interactionConfig.interactReach, eye) + val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye) BlockHitResult(hitVec, hitSide, pos, false) } ?: return@scanSurfaces - val checked = CheckedHit(hit, newRotation, interactionConfig.interactReach) + val checked = CheckedHit(hit, newRotation, buildConfig.interactReach) if (hit.blockResult?.blockPos != pos) { blockedHits.add(vec) return@scanSurfaces @@ -270,7 +268,7 @@ object BuildSimulator { return@interactBlock } - interactionConfig.pointSelection.select(validHits)?.let { checkedHit -> + buildConfig.pointSelection.select(validHits)?.let { checkedHit -> val checkedResult = checkedHit.hit val rotationTarget = lookAt(checkedHit.targetRotation, 0.001) val context = InteractionContext( @@ -403,14 +401,14 @@ object BuildSimulator { val validHits = mutableListOf() val misses = mutableSetOf() - val reachSq = interactionConfig.interactReach.pow(2) + val reachSq = buildConfig.interactReach.pow(2) boxes.forEach { box -> - val sides = if (interactionConfig.checkSideVisibility) { + val sides = if (buildConfig.checkSideVisibility) { box.getVisibleSurfaces(eye).intersect(setOf(hitSide)) } else setOf(hitSide) - scanSurfaces(box, sides, interactionConfig.resolution, preProcessing.surfaceScan) { _, vec -> + scanSurfaces(box, sides, buildConfig.resolution, preProcessing.surfaceScan) { _, vec -> val distSquared = eye distSq vec if (distSquared > reachSq) { misses.add(vec) @@ -419,25 +417,25 @@ object BuildSimulator { val newRotation = eye.rotationTo(vec) - val hit = if (interactionConfig.strictRayCast) { - val rayCast = newRotation.rayCast(interactionConfig.interactReach, eye) + val hit = if (buildConfig.strictRayCast) { + val rayCast = newRotation.rayCast(buildConfig.interactReach, eye) when { rayCast != null && (!placeConfig.airPlace.isEnabled || eye distSq rayCast.pos <= distSquared) -> rayCast.blockResult placeConfig.airPlace.isEnabled -> { - val hitVec = newRotation.castBox(box, interactionConfig.interactReach, eye) + val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye) BlockHitResult(hitVec, hitSide, hitPos, false) } else -> null } } else { - val hitVec = newRotation.castBox(box, interactionConfig.interactReach, eye) + val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye) BlockHitResult(hitVec, hitSide, hitPos, false) } ?: return@scanSurfaces - val checked = CheckedHit(hit, newRotation, interactionConfig.interactReach) + val checked = CheckedHit(hit, newRotation, buildConfig.interactReach) if (!checked.verify()) return@scanSurfaces validHits.add(checked) @@ -454,7 +452,7 @@ object BuildSimulator { return@forEach } - interactionConfig.pointSelection.select(validHits)?.let { checkedHit -> + buildConfig.pointSelection.select(validHits)?.let { checkedHit -> val optimalStack = nextTargetState.getStack(world, pos, this) // ToDo: For each hand and sneak or not? @@ -723,7 +721,7 @@ object BuildSimulator { } val currentRotation = RotationManager.activeRotation - val currentCast = currentRotation.rayCast(interactionConfig.interactReach, eye) + val currentCast = currentRotation.rayCast(buildConfig.interactReach, eye) val voxelShape = state.getOutlineShape(world, pos) voxelShape.getClosestPointTo(eye).ifPresent { @@ -759,14 +757,14 @@ object BuildSimulator { val validHits = mutableListOf() val misses = mutableSetOf() - val reachSq = interactionConfig.interactReach.pow(2) + val reachSq = buildConfig.interactReach.pow(2) boxes.forEach { box -> - val sides = if (interactionConfig.checkSideVisibility) { + val sides = if (buildConfig.checkSideVisibility) { box.getVisibleSurfaces(eye).intersect(Direction.entries) } else Direction.entries.toSet() // ToDo: Rewrite Rotation request system to allow support for all sim features and use the rotation finder - scanSurfaces(box, sides, interactionConfig.resolution) { side, vec -> + scanSurfaces(box, sides, buildConfig.resolution) { side, vec -> if (eye distSq vec > reachSq) { misses.add(vec) return@scanSurfaces @@ -774,14 +772,14 @@ object BuildSimulator { val newRotation = eye.rotationTo(vec) - val hit = if (interactionConfig.strictRayCast) { - newRotation.rayCast(interactionConfig.interactReach, eye)?.blockResult + val hit = if (buildConfig.strictRayCast) { + newRotation.rayCast(buildConfig.interactReach, eye)?.blockResult } else { - val hitVec = newRotation.castBox(box, interactionConfig.interactReach, eye) + val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye) BlockHitResult(hitVec, side, pos, false) } ?: return@scanSurfaces - val checked = CheckedHit(hit, newRotation, interactionConfig.interactReach) + val checked = CheckedHit(hit, newRotation, buildConfig.interactReach) if (!checked.verify()) return@scanSurfaces validHits.add(checked) @@ -794,7 +792,7 @@ object BuildSimulator { return acc } - val bestHit = interactionConfig.pointSelection.select(validHits) ?: return acc + val bestHit = buildConfig.pointSelection.select(validHits) ?: return acc val blockHit = bestHit.hit.blockResult ?: return acc val target = lookAt(bestHit.targetRotation, 0.001) val rotationRequest = RotationRequest(target, this) diff --git a/src/main/kotlin/com/lambda/interaction/request/PostActionHandler.kt b/src/main/kotlin/com/lambda/interaction/request/PostActionHandler.kt index 3af3f47bb..e8afb77fe 100644 --- a/src/main/kotlin/com/lambda/interaction/request/PostActionHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/PostActionHandler.kt @@ -49,7 +49,7 @@ abstract class PostActionHandler { } fun Automated.setPendingConfigs() { - BrokenBlockHandler.pendingActions.setSizeLimit(buildConfig.breakConfig.maxPendingBreaks) + BrokenBlockHandler.pendingActions.setSizeLimit(breakConfig.maxPendingBreaks) BrokenBlockHandler.pendingActions.setDecayTime(buildConfig.interactionTimeout * 50L) } } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/BreakInfo.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/BreakInfo.kt index 8a56c104e..98d9379cd 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/BreakInfo.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/BreakInfo.kt @@ -43,7 +43,7 @@ data class BreakInfo( var request: BreakRequest ) : ActionInfo, LogContext { // Delegates - val breakConfig get() = request.buildConfig.breakConfig + val breakConfig get() = request.breakConfig override val pendingInteractionsList get() = request.pendingInteractions // Pre Processing diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt index 36017825e..c9b7b449c 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt @@ -19,7 +19,6 @@ package com.lambda.interaction.request.breaking import com.lambda.context.AutomatedSafeContext import com.lambda.context.SafeContext -import com.lambda.context.breakConfig import com.lambda.event.Event import com.lambda.event.EventFlow.post import com.lambda.event.events.ConnectionEvent diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/RebreakHandler.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/RebreakHandler.kt index 7034579a3..b35b88836 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/RebreakHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/RebreakHandler.kt @@ -18,7 +18,6 @@ package com.lambda.interaction.request.breaking import com.lambda.context.SafeContext -import com.lambda.context.breakConfig import com.lambda.event.events.ConnectionEvent import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen 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 226308c25..9ffd890be 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/SwapInfo.kt @@ -20,7 +20,6 @@ package com.lambda.interaction.request.breaking import com.lambda.context.Automated import com.lambda.context.AutomationConfig import com.lambda.context.SafeContext -import com.lambda.context.breakConfig import com.lambda.interaction.request.LogContext import com.lambda.interaction.request.LogContext.Companion.LogContextBuilder import com.lambda.interaction.request.breaking.BreakInfo.BreakType.Primary diff --git a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractConfig.kt b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractConfig.kt index 4db1f6057..429867c8e 100644 --- a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractConfig.kt +++ b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractConfig.kt @@ -18,14 +18,24 @@ package com.lambda.interaction.request.interacting import com.lambda.config.groups.BuildConfig -import com.lambda.config.groups.InteractionConfig import com.lambda.event.Event import com.lambda.interaction.request.RequestConfig +import com.lambda.util.Describable +import com.lambda.util.NamedEnum interface InteractConfig : RequestConfig { val rotate: Boolean val swingHand: Boolean val interactStageMask: Set val interactSwingType: BuildConfig.SwingType - val interactConfirmationMode: InteractionConfig.InteractConfirmationMode + val interactConfirmationMode: InteractConfirmationMode + + enum class InteractConfirmationMode( + override val displayName: String, + override val description: String + ): NamedEnum, Describable { + None("No confirmation", "Send the interaction and don’t wait for the server. Lowest latency, but effects may briefly appear if the server rejects it."), + InteractThenAwait("Interact now, confirm later", "Show interaction effects immediately, then wait for the server to confirm. Feels instant while still verifying the result."), + AwaitThenInteract("Confirm first, then interact", "Wait for the server response before showing any effects. Most accurate and safe, but adds a short delay.") + } } \ No newline at end of file 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 09cb5200e..8d7d9f1cc 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,6 @@ package com.lambda.interaction.request.interacting import com.lambda.Lambda.mc -import com.lambda.config.groups.InteractionConfig import com.lambda.context.AutomationConfig import com.lambda.event.events.WorldEvent import com.lambda.event.listener.SafeListener.Companion.listen @@ -35,7 +34,7 @@ object InteractedBlockHandler : PostActionHandler() { AutomationConfig.buildConfig.interactionTimeout * 50L ) { info("${it::class.simpleName} at ${it.context.blockPos.toShortString()} timed out") - if (it.interactConfirmationMode != InteractionConfig.InteractConfirmationMode.AwaitThenInteract) { + if (it.interactConfirmationMode != InteractConfig.InteractConfirmationMode.AwaitThenInteract) { mc.world?.setBlockState(it.context.blockPos, it.context.cachedState) } it.pendingInteractionsList.remove(it.context) diff --git a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionInfo.kt b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionInfo.kt index 5c46aa5bc..85c78297d 100644 --- a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionInfo.kt +++ b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionInfo.kt @@ -18,7 +18,6 @@ package com.lambda.interaction.request.interacting import com.lambda.context.Automated -import com.lambda.context.interactConfig import com.lambda.interaction.construction.context.BuildContext import com.lambda.interaction.construction.context.InteractionContext import com.lambda.interaction.request.ActionInfo diff --git a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionManager.kt b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionManager.kt index c7f9048bd..927827f7a 100644 --- a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionManager.kt @@ -17,10 +17,8 @@ package com.lambda.interaction.request.interacting -import com.lambda.config.groups.InteractionConfig import com.lambda.context.Automated import com.lambda.context.AutomatedSafeContext -import com.lambda.context.interactConfig import com.lambda.event.EventFlow.post import com.lambda.event.events.MovementEvent import com.lambda.event.events.TickEvent @@ -120,10 +118,10 @@ object InteractionManager : RequestHandler( } if (tickStage !in interactConfig.interactStageMask) return - if (interactConfig.interactConfirmationMode != InteractionConfig.InteractConfirmationMode.None) { + if (interactConfig.interactConfirmationMode != InteractConfig.InteractConfirmationMode.None) { InteractionInfo(ctx, request.pendingInteractionsList, request).startPending() } - if (interactConfig.interactConfirmationMode != InteractionConfig.InteractConfirmationMode.AwaitThenInteract) { + if (interactConfig.interactConfirmationMode != InteractConfig.InteractConfirmationMode.AwaitThenInteract) { interaction.interactBlock(player, Hand.MAIN_HAND, ctx.result) } else { interaction.sendSequencedPacket(world) { sequence -> diff --git a/src/main/kotlin/com/lambda/interaction/request/placing/PlaceManager.kt b/src/main/kotlin/com/lambda/interaction/request/placing/PlaceManager.kt index 5c31bb56c..9bfc7ded4 100644 --- a/src/main/kotlin/com/lambda/interaction/request/placing/PlaceManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/placing/PlaceManager.kt @@ -20,7 +20,6 @@ package com.lambda.interaction.request.placing import com.lambda.context.Automated import com.lambda.context.AutomatedSafeContext import com.lambda.context.SafeContext -import com.lambda.context.placeConfig import com.lambda.event.Event import com.lambda.event.EventFlow.post import com.lambda.event.events.MovementEvent diff --git a/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/RotationTargets.kt b/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/RotationTargets.kt index 85d23063a..1661dd772 100644 --- a/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/RotationTargets.kt +++ b/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/RotationTargets.kt @@ -98,13 +98,13 @@ fun Automated.lookAtHit(hit: HitResult): RotationTarget? { */ @RotationDsl fun Automated.lookAtEntity(entity: LivingEntity): RotationTarget { - val requestedHit = entityHit(entity, interactionConfig.attackReach) + val requestedHit = entityHit(entity, buildConfig.attackReach) return RotationTarget(requestedHit) { runSafeAutomated { findRotation( requestedHit.getBoundingBoxes(), - interactionConfig.attackReach, + buildConfig.attackReach, player.eyePos, ALL_SIDES, SurfaceScan.DEFAULT, @@ -128,13 +128,13 @@ fun Automated.lookAtBlock( sides: Set = ALL_SIDES, surfaceScan: SurfaceScan = SurfaceScan.DEFAULT ): RotationTarget { - val requestedHit = blockHit(pos, sides, interactionConfig.interactReach) + val requestedHit = blockHit(pos, sides, buildConfig.interactReach) return RotationTarget(requestedHit) { runSafeAutomated { findRotation( requestedHit.getBoundingBoxes(), - interactionConfig.interactReach, + buildConfig.interactReach, player.eyePos, sides, surfaceScan, 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 7aa527061..31aad1e65 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 @@ -17,10 +17,8 @@ package com.lambda.interaction.request.rotating.visibilty -import com.lambda.config.groups.InteractionConfig import com.lambda.context.AutomatedSafeContext import com.lambda.context.AutomationConfig -import com.lambda.context.SafeContext import com.lambda.interaction.construction.verify.ScanMode import com.lambda.interaction.construction.verify.SurfaceScan import com.lambda.interaction.request.rotating.Rotation @@ -73,7 +71,7 @@ object VisibilityChecker { } } - return interactionConfig.pointSelection.select( + return buildConfig.pointSelection.select( collectHitsFor(boxes, reach, eye, sides, scan, targetType, verify) ) } @@ -100,17 +98,17 @@ object VisibilityChecker { targetType: InteractionMask, verify: CheckedHit.() -> Boolean, ) = mutableListOf().apply { - val reachSq = interactionConfig.scanReach.pow(2) + val reachSq = buildConfig.scanReach.pow(2) boxes.forEach { box -> - val visible = visibleSides(box, eye, interactionConfig.checkSideVisibility) + val visible = visibleSides(box, eye, buildConfig.checkSideVisibility) - scanSurfaces(box, visible.intersect(sides), interactionConfig.resolution, scan) { _, vec -> + scanSurfaces(box, visible.intersect(sides), buildConfig.resolution, scan) { _, vec -> if (eye distSq vec > reachSq) return@scanSurfaces val newRotation = eye.rotationTo(vec) - val mask = if (interactionConfig.strictRayCast) InteractionMask.Both else targetType + val mask = if (buildConfig.strictRayCast) InteractionMask.Both else targetType val hit = newRotation.rayCast(reach, eye, mask = mask) ?: return@scanSurfaces val checked = CheckedHit(hit, newRotation, reach) @@ -121,7 +119,7 @@ object VisibilityChecker { } } - private fun SafeContext.collectHitsInternal( + private fun AutomatedSafeContext.collectHitsInternal( boxes: List, reach: Double, eye: Vec3d, @@ -129,20 +127,19 @@ object VisibilityChecker { scan: SurfaceScan, targetType: InteractionMask, entity: LivingEntity?, - interaction: InteractionConfig, verify: CheckedHit.() -> Boolean, ) = mutableListOf().apply { - val reachSq = interaction.scanReach.pow(2) + val reachSq = buildConfig.scanReach.pow(2) boxes.forEach { box -> - val visible = visibleSides(box, eye, interaction.checkSideVisibility) + val visible = visibleSides(box, eye, buildConfig.checkSideVisibility) - scanSurfaces(box, visible.intersect(sides), interaction.resolution, scan) { _, vec -> + scanSurfaces(box, visible.intersect(sides), buildConfig.resolution, scan) { _, vec -> if (eye distSq vec > reachSq) return@scanSurfaces val newRotation = eye.rotationTo(vec) - val mask = if (interaction.strictRayCast || entity == null) InteractionMask.Both else targetType + val mask = if (buildConfig.strictRayCast || entity == null) InteractionMask.Both else targetType val hit = newRotation.rayCast(reach, eye, mask = mask) ?: return@scanSurfaces val checked = CheckedHit(hit, newRotation, reach) 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 6cd95c95f..309fa3fd7 100644 --- a/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt +++ b/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt @@ -18,7 +18,6 @@ package com.lambda.module.modules.combat import com.lambda.config.groups.BuildSettings -import com.lambda.config.groups.InteractionSettings import com.lambda.config.groups.RotationSettings import com.lambda.config.groups.Targeting import com.lambda.context.SafeContext @@ -39,7 +38,6 @@ import com.lambda.util.item.ItemStackUtils.attackSpeed import com.lambda.util.item.ItemStackUtils.equal import com.lambda.util.math.random import com.lambda.util.player.SlotUtils.hotbarAndStorage -import com.lambda.util.world.raycast.InteractionMask import com.lambda.util.world.raycast.RayCastUtils.entityResult import net.minecraft.entity.LivingEntity import net.minecraft.util.Hand @@ -51,7 +49,6 @@ object KillAura : Module( tag = ModuleTag.COMBAT, ) { // Interact - override val interactionConfig = InteractionSettings(this, Group.Interaction, InteractionMask.Entity) override val buildConfig = BuildSettings(this, Group.Build) private val swap by setting("Swap", true, "Swap to the item with the highest damage").group(Group.Build) private val attackMode by setting("Attack Mode", AttackMode.Cooldown).group(Group.Build) @@ -128,18 +125,18 @@ object KillAura : Module( if (rotate) { val angle = RotationManager.activeRotation - if (interactionConfig.strictRayCast) { - val cast = angle.rayCast(interactionConfig.attackReach) + if (buildConfig.strictRayCast) { + val cast = angle.rayCast(buildConfig.attackReach) if (cast?.entityResult?.entity != target) return } // Perform a raycast without checking the environment - angle.castBox(target.boundingBox, interactionConfig.attackReach) ?: return + angle.castBox(target.boundingBox, buildConfig.attackReach) ?: return } // Attack interaction.attackEntity(player, target) - if (buildConfig.interactConfig.swingHand) player.swingHand(Hand.MAIN_HAND) + if (interactConfig.swingHand) player.swingHand(Hand.MAIN_HAND) lastAttackTime = System.currentTimeMillis() hitDelay = (hitDelay1..hitDelay2).random() * 50 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 43f2ca324..2b1cd3998 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/FastBreak.kt @@ -17,12 +17,17 @@ package com.lambda.module.modules.player -import com.lambda.config.groups.BuildSettings +import com.lambda.config.groups.BreakSettings +import com.lambda.config.groups.HotbarSettings +import com.lambda.config.groups.InventorySettings import com.lambda.event.events.PlayerEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.construction.context.BreakContext import com.lambda.interaction.construction.context.BuildContext -import com.lambda.interaction.material.StackSelection.Companion.select +import com.lambda.interaction.material.ContainerSelection.Companion.selectContainer +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.BreakRequest import com.lambda.interaction.request.rotating.Rotation.Companion.rotation import com.lambda.interaction.request.rotating.RotationRequest @@ -30,8 +35,19 @@ import com.lambda.interaction.request.rotating.visibilty.lookAt import com.lambda.module.Module 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 net.minecraft.util.Hand +import com.lambda.util.player.SlotUtils.hotbar +import net.minecraft.block.pattern.CachedBlockPosition +import net.minecraft.enchantment.Enchantments +import net.minecraft.item.ItemStack +import net.minecraft.registry.tag.ItemTags.DIAMOND_TOOL_MATERIALS +import net.minecraft.registry.tag.ItemTags.GOLD_TOOL_MATERIALS +import net.minecraft.registry.tag.ItemTags.IRON_TOOL_MATERIALS +import net.minecraft.registry.tag.ItemTags.NETHERITE_TOOL_MATERIALS +import net.minecraft.registry.tag.ItemTags.STONE_TOOL_MATERIALS +import net.minecraft.registry.tag.ItemTags.WOODEN_TOOL_MATERIALS import net.minecraft.util.hit.BlockHitResult import java.util.concurrent.ConcurrentLinkedQueue @@ -41,10 +57,42 @@ object FastBreak : Module( tag = ModuleTag.PLAYER, ) { private enum class Group(override val displayName: String) : NamedEnum { - Build("Build") + Break("Break"), + Inventory("Inventory"), + Hotbar("Hotbar") } - override val buildConfig = BuildSettings(this, Group.Build) + override val breakConfig = BreakSettings(this, Group.Break).apply { + editTyped( + ::avoidLiquids, + ::avoidSupporting, + ::suitableToolsOnly, + ::rotateForBreak, + ::doubleBreak + ) { defaultValue(false) } + ::breaksPerTick.edit { defaultValue(1) } + ::breakWeakBlocks.edit { defaultValue(true) } + hide( + ::sorter, + ::doubleBreak, + ::unsafeCancels, + ::rotateForBreak, + ::breaksPerTick, + ::breakWeakBlocks + ) + } + override val inventoryConfig = InventorySettings(this, Group.Inventory).apply { + editTyped( + ::accessShulkerBoxes, + ::accessEnderChest, + ::accessChests, + ::accessStashes + ) { + defaultValue(false) + hide() + } + } + override val hotbarConfig = HotbarSettings(this, Group.Hotbar) private val pendingInteractions = ConcurrentLinkedQueue() @@ -52,20 +100,81 @@ object FastBreak : Module( listen { it.cancel() } listen { event -> event.cancel() - player.swingHand(Hand.MAIN_HAND) val hitResult = mc.crosshairTarget as? BlockHitResult ?: return@listen val pos = event.pos val state = blockState(pos) + //ToDo: Copied this swap logic from the build sim. Needs reworking when we rework the build sim. Probably need to + // adjust the build sim to accept partial simulations. For example, ignoring hit scanning in this situation + val silentSwapSelection = selectContainer { + ofAnyType(MaterialContainer.Rank.HOTBAR) + } + + val stackSelection = selectStack( + sorter = compareByDescending { + it.canBreak(CachedBlockPosition(world, pos, false)) + }.thenByDescending { + state.calcItemBlockBreakingDelta(pos, it) + } + ) { + isTool() and if (breakConfig.suitableToolsOnly) { + isSuitableForBreaking(state) + } else any() and if (breakConfig.forceSilkTouch) { + hasEnchantment(Enchantments.SILK_TOUCH) + } else any() and if (breakConfig.forceFortunePickaxe) { + hasEnchantment(Enchantments.FORTUNE) + } else any() and if (!breakConfig.useWoodenTools) { + hasTag(WOODEN_TOOL_MATERIALS).not() + } else any() and if (!breakConfig.useStoneTools) { + hasTag(STONE_TOOL_MATERIALS).not() + } else any() and if (!breakConfig.useIronTools) { + hasTag(IRON_TOOL_MATERIALS).not() + } else any() and if (!breakConfig.useDiamondTools) { + hasTag(DIAMOND_TOOL_MATERIALS).not() + } else any() and if (!breakConfig.useGoldTools) { + hasTag(GOLD_TOOL_MATERIALS).not() + } else any() and if (!breakConfig.useNetheriteTools) { + hasTag(NETHERITE_TOOL_MATERIALS).not() + } else any() + } + + val swapCandidates = stackSelection.containerWithMaterial(silentSwapSelection) + if (swapCandidates.isEmpty()) return@listen + + val swapStack = swapCandidates + .map { it.matchingStacks(stackSelection) } + .asSequence() + .flatten() + .let { containerStacks -> + var bestStack = ItemStack.EMPTY + var bestBreakDelta = -1f + containerStacks.forEach { stack -> + val breakDelta = state.calcItemBlockBreakingDelta(pos, stack) + if (breakDelta > bestBreakDelta || + (stack == player.mainHandStack && breakDelta >= bestBreakDelta) + ) { + bestBreakDelta = breakDelta + bestStack = stack + } + } + bestStack + } + val breakContext = BreakContext( hitResult, RotationRequest(lookAt(player.rotation), this@FastBreak), - player.inventory.selectedSlot, - player.mainHandStack.select(), - state.calcBlockBreakingDelta(player, world, pos) >= buildConfig.breakConfig.breakThreshold, + player.hotbar.indexOf(swapStack), + stackSelection, + instantBreakable( + state, + pos, + if (breakConfig.swapMode.isEnabled()) swapStack + else player.mainHandStack, + breakConfig.breakThreshold + ), state, - buildConfig.breakConfig.sorter, + breakConfig.sorter, this@FastBreak ) 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 2c746fccc..63fb744af 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt @@ -17,16 +17,19 @@ 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.InteractionSettings +import com.lambda.config.groups.InteractSettings import com.lambda.config.groups.InventorySettings +import com.lambda.config.groups.PlaceSettings import com.lambda.config.groups.RotationSettings import com.lambda.interaction.BaritoneManager import com.lambda.interaction.construction.blueprint.Blueprint.Companion.emptyStructure import com.lambda.interaction.construction.blueprint.PropagatingBlueprint.Companion.propagatingBlueprint import com.lambda.interaction.construction.verify.TargetState +import com.lambda.interaction.request.breaking.BreakConfig import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.task.RootTask.run @@ -41,7 +44,6 @@ import com.lambda.util.math.MathUtils.floorToInt import com.lambda.util.math.rotateClockwise import com.lambda.util.player.MovementUtils.octant import com.lambda.util.world.StructureUtils.generateDirectionalTube -import com.lambda.util.world.raycast.InteractionMask import net.minecraft.block.Blocks import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Direction @@ -53,6 +55,19 @@ 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) @@ -70,8 +85,12 @@ object HighwayTools : Module( 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 interactionConfig = InteractionSettings(this, Group.Interaction, InteractionMask.Block) override val inventoryConfig = InventorySettings(this, Group.Inventory) override val hotbarConfig = HotbarSettings(this, Group.Hotbar) override val eatConfig = EatSettings(this, Group.Eat) @@ -99,16 +118,6 @@ object HighwayTools : Module( Solid("Solid", "Fills the corner block of the highway pavement below the rims with solid blocks."), } - enum class Group(override val displayName: String): NamedEnum { - Structure("Structure"), - Build("Build"), - Rotation("Rotation"), - Interaction("Interaction"), - Inventory("Inventory"), - Hotbar("Hotbar"), - Eat("Eat") - } - init { onEnable { octant = player.octant 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 7823377d8..df042db97 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Nuker.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Nuker.kt @@ -18,7 +18,6 @@ package com.lambda.module.modules.player import com.lambda.context.AutomationConfig -import com.lambda.context.breakConfig import com.lambda.interaction.BaritoneManager import com.lambda.interaction.construction.blueprint.TickingBlueprint.Companion.tickingBlueprint import com.lambda.interaction.construction.verify.TargetState 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 776f03eb8..dca765b20 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt @@ -17,13 +17,13 @@ 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.InteractionSettings import com.lambda.config.groups.InventorySettings import com.lambda.config.groups.RotationSettings +import com.lambda.config.groups.SettingGroup import com.lambda.context.SafeContext -import com.lambda.context.breakConfig import com.lambda.event.events.PlayerEvent import com.lambda.event.events.TickEvent import com.lambda.event.events.onStaticRender @@ -34,6 +34,7 @@ import com.lambda.interaction.construction.context.BuildContext import com.lambda.interaction.construction.result.BreakResult 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.module.Module import com.lambda.module.tag.ModuleTag @@ -44,7 +45,6 @@ import com.lambda.util.NamedEnum import com.lambda.util.math.distSq import com.lambda.util.math.lerp import com.lambda.util.math.setAlpha -import com.lambda.util.world.raycast.InteractionMask import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Box import java.awt.Color @@ -56,35 +56,68 @@ object PacketMine : Module( tag = ModuleTag.PLAYER ) { private enum class Group(override val displayName: String) : NamedEnum { - General("General"), + Break("Break"), Build("Build"), Rotation("Rotation"), - Interaction("Interaction"), Inventory("Inventory"), Hotbar("Hotbar"), - Render("Render") } - private val rebreakMode by setting("Rebreak Mode", RebreakMode.Manual, "The method used to re-break blocks after they've been broken once") { 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) + 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) .onValueChange { _, to -> if (!to) queuePositions.clear() } - private val queueOrder by setting("Queue Order", QueueOrder.Standard, "Which end of the queue to break blocks from") { queue }.group(Group.General) + private val queueOrder by setting("Queue Order", QueueOrder.Standard, "Which end of the queue to break blocks from") { queue }.group(Group.Break, BreakSettings.Group.General) - override val buildConfig = BuildSettings(this, Group.Build) - override val rotationConfig = RotationSettings(this, Group.Rotation) - override val interactionConfig = InteractionSettings(this, Group.Interaction, InteractionMask.Block) - override val inventoryConfig = InventorySettings(this, Group.Inventory) - override val hotbarConfig = HotbarSettings(this, Group.Hotbar) + 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, ::suitableToolsOnly) { defaultValue(false) } + ::breakWeakBlocks.edit { defaultValue(true) } + ::swing.edit { defaultValue(BreakConfig.SwingMode.Start) } + + ::rebreak.insert(::rebreakMode, SettingGroup.InsertMode.Below) + ::rebreakMode.edit { visibility { rebreak } } - private val renderQueue by setting("Render Queue", true, "Adds renders to signify what block positions are queued").group(Group.Render) - private val renderSize by setting("Render Size", 0.3f, 0.01f..1f, 0.01f, "The scale of the queue renders") { renderQueue }.group(Group.Render) - private val renderMode by setting("Render Mode", RenderMode.State, "The style of the queue renders") { renderQueue }.group(Group.Render) - private val dynamicColor by setting("Dynamic Color", true, "Interpolates the color between start and end") { renderQueue }.group(Group.Render) - private val staticColor by setting("Color", Color(255, 0, 0, 60).brighter()) { renderQueue && !dynamicColor }.group(Group.Render) - 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.Render) - 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.Render) + ::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 pendingInteractions = ConcurrentLinkedQueue() diff --git a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt index f026caa7d..fec4193d3 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt @@ -19,7 +19,6 @@ package com.lambda.module.modules.player import com.lambda.config.groups.BuildSettings import com.lambda.config.groups.HotbarSettings -import com.lambda.config.groups.InteractionSettings import com.lambda.config.groups.InventorySettings import com.lambda.config.groups.RotationSettings import com.lambda.context.SafeContext @@ -42,7 +41,6 @@ import com.lambda.util.KeyCode import com.lambda.util.KeyboardUtils.isKeyPressed import com.lambda.util.NamedEnum import com.lambda.util.math.distSq -import com.lambda.util.world.raycast.InteractionMask import net.minecraft.util.math.BlockPos import java.util.concurrent.ConcurrentLinkedQueue @@ -55,7 +53,6 @@ object Scaffold : Module( General("General"), Build("Build"), Rotation("Rotation"), - Interaction("Interaction"), Hotbar("Hotbar"), Inventory("Inventory") } @@ -64,11 +61,25 @@ object Scaffold : Module( 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 != KeyCode.UNBOUND }.group(Group.General) - override val buildConfig = BuildSettings(this, Group.Build) + override val buildConfig = BuildSettings(this, Group.Build).apply { + editTyped(::pathing, ::stayInRange, ::collectDrops) { + defaultValue(false) + hide() + } + } override val rotationConfig = RotationSettings(this, Group.Rotation) - override val interactionConfig = InteractionSettings(this, Group.Interaction, InteractionMask.Block) override val hotbarConfig = HotbarSettings(this, Group.Hotbar) - override val inventoryConfig = InventorySettings(this, Group.Inventory) + 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() + } + } private val pendingActions = ConcurrentLinkedQueue() @@ -104,7 +115,7 @@ object Scaffold : Module( private fun SafeContext.scaffoldPositions(beneath: BlockPos): List { if (!blockState(beneath).isReplaceable) return emptyList() - if (buildConfig.placeConfig.airPlace.isEnabled) return listOf(beneath) + if (placeConfig.airPlace.isEnabled) return listOf(beneath) return BlockPos.iterateOutwards(beneath, bridgeRange, bridgeRange, bridgeRange) .asSequence() diff --git a/src/main/kotlin/com/lambda/task/tasks/OpenContainer.kt b/src/main/kotlin/com/lambda/task/tasks/OpenContainer.kt index 8428a05c6..e3ada19a2 100644 --- a/src/main/kotlin/com/lambda/task/tasks/OpenContainer.kt +++ b/src/main/kotlin/com/lambda/task/tasks/OpenContainer.kt @@ -18,7 +18,6 @@ package com.lambda.task.tasks import com.lambda.context.Automated -import com.lambda.context.interactConfig import com.lambda.event.events.InventoryEvent import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen