Skip to content

Commit 6ebfb10

Browse files
committed
Improve prototype
1 parent 23a2a91 commit 6ebfb10

File tree

8 files changed

+153
-82
lines changed

8 files changed

+153
-82
lines changed

src/main/kotlin/com/lambda/config/groups/EatConfig.kt

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,92 @@
1717

1818
package com.lambda.config.groups
1919

20+
import com.lambda.context.SafeContext
21+
import com.lambda.interaction.material.StackSelection
22+
import com.lambda.interaction.material.StackSelection.Companion.selectStack
23+
import com.lambda.threading.runSafe
24+
import com.lambda.util.Describable
2025
import com.lambda.util.NamedEnum
26+
import com.lambda.util.item.ItemUtils.nutrition
27+
import net.minecraft.entity.effect.StatusEffects
2128
import net.minecraft.item.Item
29+
import net.minecraft.item.ItemStack
2230

2331
interface EatConfig {
24-
val eatFood: Boolean
32+
val eatOnHunger: Boolean
2533
val minFoodLevel: Int
26-
val eatUntilFull: Boolean
34+
val nutritiousFood: List<Item>
35+
val selectionPriority: SelectionPriority
36+
val saturated: Saturation
2737
val eatOnFire: Boolean
28-
val eatHeal: Boolean
38+
val resistanceFood: List<Item>
39+
val eatOnDamage: Boolean
40+
val minDamage: Int
41+
val regenerationFood: List<Item>
42+
val ignoreBadFood: Boolean
43+
val badFood: List<Item>
2944

30-
val selectionMode: SelectionMode
31-
val whitelist: List<Item>
32-
val blacklist: List<Item>
45+
enum class Saturation(
46+
override val displayName: String,
47+
override val description: String
48+
): NamedEnum, Describable {
49+
EatSmart("Eat Smart", "Eats until the next food would exceed the hunger limit."),
50+
EatUntilFull("Eat Until Full", "Eats food until the hunger bar is completely full. May waste some food."),
51+
}
52+
53+
enum class SelectionPriority(
54+
val comparator: Comparator<ItemStack>,
55+
override val displayName: String,
56+
override val description: String): NamedEnum, Describable {
57+
LeastNutritious(
58+
compareBy { it.item.nutrition },
59+
"Least Nutritious",
60+
"Eats food items with the least nutritional value."
61+
),
62+
MostNutritious(
63+
compareByDescending { it.item.nutrition },
64+
"Most Nutritious",
65+
"Eats food items with the most nutritional value."
66+
)
67+
}
68+
69+
enum class Reason(val message: (ItemStack) -> String) {
70+
None({ "Waiting for food to eat..." }),
71+
Hunger({ "Eating ${it.item.name.string} due to Hunger" }),
72+
Damage({ "Eating ${it.item.name.string} due to Damage" }),
73+
Fire({ "Eating ${it.item.name.string} due to Fire" });
74+
75+
fun shouldEat() = this != None
76+
77+
fun shouldKeepEating(config: EatConfig, stack: ItemStack?) = runSafe {
78+
if (stack == null || stack.isEmpty) return@runSafe false
79+
when(this@Reason) {
80+
Hunger -> when(config.saturated) {
81+
Saturation.EatSmart -> stack.item.nutrition + player.hungerManager.foodLevel <= 20
82+
Saturation.EatUntilFull -> player.hungerManager.isNotFull
83+
}
84+
Damage -> !player.hasStatusEffect(StatusEffects.REGENERATION)
85+
Fire -> !player.hasStatusEffect(StatusEffects.FIRE_RESISTANCE)
86+
None -> false
87+
}
88+
} ?: false
89+
90+
fun selector(config: EatConfig) = selectStack(sorter = config.selectionPriority.comparator) {
91+
when(this@Reason) {
92+
None -> any()
93+
Hunger -> isOneOfItems(config.nutritiousFood)
94+
Damage -> isOneOfItems(config.regenerationFood)
95+
Fire -> isOneOfItems(config.resistanceFood)
96+
} and if (config.ignoreBadFood) isNoneOfItems(config.badFood) else any()
97+
}
98+
}
3399

34-
enum class SelectionMode(override val displayName: String): NamedEnum {
35-
Whitelist("Whitelist"),
36-
Blacklist("Blacklist")
100+
companion object {
101+
fun SafeContext.reasonEating(config: EatConfig) = when {
102+
config.eatOnHunger && player.hungerManager.foodLevel <= config.minFoodLevel -> Reason.Hunger
103+
config.eatOnDamage && player.health <= config.minDamage && !player.hasStatusEffect(StatusEffects.REGENERATION) -> Reason.Damage
104+
config.eatOnFire && player.isOnFire && !player.hasStatusEffect(StatusEffects.FIRE_RESISTANCE) -> Reason.Fire
105+
else -> Reason.None
106+
}
37107
}
38108
}

src/main/kotlin/com/lambda/config/groups/EatSettings.kt

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
package com.lambda.config.groups
1919

2020
import com.lambda.config.Configurable
21-
import com.lambda.event.events.TickEvent
22-
import com.lambda.interaction.request.hotbar.HotbarConfig
2321
import com.lambda.util.NamedEnum
2422
import net.minecraft.item.Item
2523
import net.minecraft.item.Items
@@ -29,14 +27,21 @@ class EatSettings(
2927
baseGroup: NamedEnum,
3028
vis: () -> Boolean = { true }
3129
) : EatConfig {
32-
val defaultWhitelist = listOf(Items.GOLDEN_CARROT)
30+
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)
31+
val resistanceFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE)
32+
val regenerationFoodDefaults = listOf(Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE)
33+
val negativeFoodDefaults = listOf(Items.CHICKEN, Items.POISONOUS_POTATO, Items.PUFFERFISH, Items.ROTTEN_FLESH, Items.SPIDER_EYE)
3334

34-
override val eatFood by c.setting("Eat Food", true, "Whether food should be eaten", vis).group(baseGroup)
35-
override val eatUntilFull by c.setting("Eat Until Full", false, "Eat until the food level is full") { vis() && eatFood }.group(baseGroup)
36-
override val minFoodLevel by c.setting("Minimum Food Level", 6, 0..20, 1, "The minimum food level to eat food", " food level") { vis() && eatFood }.group(baseGroup)
37-
override val eatOnFire by c.setting("Eat On Fire", false, "Eat when you are on fire") { vis() && eatFood }.group(baseGroup)
38-
override val eatHeal by c.setting("Eat Heal", false, "Eat healing food when you are below the minimum health level") { vis() && eatFood }.group(baseGroup)
39-
override val selectionMode by c.setting("Selection Mode", EatConfig.SelectionMode.Whitelist, "The selection mode for eating") { vis() && eatFood }.group(baseGroup)
40-
override val whitelist by c.setting("Whitelist", defaultWhitelist, defaultWhitelist, "The whitelist of items to eat") { vis() && eatFood }.group(baseGroup)
41-
override val blacklist by c.setting("Blacklist", listOf(), listOf<Item>(), "The blacklist of items to eat") { vis() && eatFood }.group(baseGroup)
35+
override val eatOnHunger by c.setting("Eat On Hunger", true, "Whether to eat when hungry", vis).group(baseGroup)
36+
override val minFoodLevel by c.setting("Minimum Food Level", 6, 0..20, 1, "The minimum food level to eat food", " food level") { vis() && eatOnHunger }.group(baseGroup)
37+
override val saturated by c.setting("Saturated", EatConfig.Saturation.EatSmart, "When to stop eating") { vis() && eatOnHunger }.group(baseGroup)
38+
override val nutritiousFood by c.setting("Nutritious Food", nutritiousFoodDefaults, nutritiousFoodDefaults, "Items that are be considered nutritious") { vis() && eatOnHunger }.group(baseGroup)
39+
override val selectionPriority by c.setting("Selection Priority", EatConfig.SelectionPriority.MostNutritious, "The priority for selecting food items") { vis() && eatOnHunger }.group(baseGroup)
40+
override val eatOnFire by c.setting("Eat On Fire", true, "Whether to eat when on fire", vis).group(baseGroup)
41+
override val resistanceFood by c.setting("Resistance Food", resistanceFoodDefaults, resistanceFoodDefaults, "Items that give Fire Resistance") { vis() && eatOnFire}.group(baseGroup)
42+
override val eatOnDamage by c.setting("Eat On Damage", true, "Whether to eat when damaged", vis).group(baseGroup)
43+
override val minDamage by c.setting("Minimum Damage", 10, 0..20, 1, "The minimum damage threshold to trigger eating") { vis() && eatOnDamage }.group(baseGroup)
44+
override val regenerationFood by c.setting("Regeneration Food", regenerationFoodDefaults, regenerationFoodDefaults, "Items that give Regeneration") { vis() && eatOnDamage }.group(baseGroup)
45+
override val ignoreBadFood by c.setting("Ignore Bad Food", true, "Whether to eat when the food is bad", vis).group(baseGroup)
46+
override val badFood by c.setting("Bad Food", negativeFoodDefaults, negativeFoodDefaults, "Items that are considered bad food") { vis() && ignoreBadFood }.group(baseGroup)
4247
}

src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -840,23 +840,23 @@ object BuildSimulator {
840840
) {
841841
isTool() and if (breaking.suitableToolsOnly) {
842842
isSuitableForBreaking(state)
843-
} else StackSelection.EVERYTHING and if (breaking.forceSilkTouch) {
843+
} else any() and if (breaking.forceSilkTouch) {
844844
hasEnchantment(Enchantments.SILK_TOUCH)
845-
} else StackSelection.EVERYTHING and if (breaking.forceFortunePickaxe) {
845+
} else any() and if (breaking.forceFortunePickaxe) {
846846
hasEnchantment(Enchantments.FORTUNE)
847-
} else StackSelection.EVERYTHING and if (!breaking.useWoodenTools) {
847+
} else any() and if (!breaking.useWoodenTools) {
848848
hasTag(WOODEN_TOOL_MATERIALS).not()
849-
} else StackSelection.EVERYTHING and if (!breaking.useStoneTools) {
849+
} else any() and if (!breaking.useStoneTools) {
850850
hasTag(STONE_TOOL_MATERIALS).not()
851-
} else StackSelection.EVERYTHING and if (!breaking.useIronTools) {
851+
} else any() and if (!breaking.useIronTools) {
852852
hasTag(IRON_TOOL_MATERIALS).not()
853-
} else StackSelection.EVERYTHING and if (!breaking.useDiamondTools) {
853+
} else any() and if (!breaking.useDiamondTools) {
854854
hasTag(DIAMOND_TOOL_MATERIALS).not()
855-
} else StackSelection.EVERYTHING and if (!breaking.useGoldTools) {
855+
} else any() and if (!breaking.useGoldTools) {
856856
hasTag(GOLD_TOOL_MATERIALS).not()
857-
} else StackSelection.EVERYTHING and if (!breaking.useNetheriteTools) {
857+
} else any() and if (!breaking.useNetheriteTools) {
858858
hasTag(NETHERITE_TOOL_MATERIALS).not()
859-
} else StackSelection.EVERYTHING
859+
} else any()
860860
}
861861

862862
val silentSwapSelection = selectContainer {

src/main/kotlin/com/lambda/interaction/material/StackSelection.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ class StackSelection {
128128
}
129129
}
130130

131+
fun any() = EVERYTHING
132+
fun none() = NOTHING
133+
131134
/**
132135
* [isItem] returns a predicate that matches a specific [Item].
133136
* @param item The [Item] to be matched.
@@ -146,15 +149,15 @@ class StackSelection {
146149
*/
147150
fun isOneOfItems(items: Collection<Item>): (ItemStack) -> Boolean = { it.item in items }
148151

149-
fun isNoneOfItems(items: Collection<Item>): (ItemStack) -> Boolean = { it.item !in items }
152+
fun isNoneOfItems(items: Collection<Item>): (ItemStack) -> Boolean = isOneOfItems(items).not()
150153

151154
/**
152155
* Returns a predicate that checks if a given `ItemStack` exists within the provided collection of `ItemStack`s.
153156
*
154157
* @param stacks A collection of `ItemStack` instances to be checked against.
155158
* @return A predicate that evaluates to `true` if the given `ItemStack` is within the specified collection, otherwise `false`.
156159
*/
157-
fun isOneOfStacks(stacks: Collection<ItemStack>): (ItemStack) -> Boolean = { it in stacks }
160+
fun isOneOfStacks(stacks: Collection<ItemStack>): (ItemStack) -> Boolean = stacks::contains
158161

159162
fun isSuitableForBreaking(blockState: BlockState): (ItemStack) -> Boolean = { it.isSuitableFor(blockState) }
160163

src/main/kotlin/com/lambda/module/modules/player/AutoEat.kt

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,16 @@
1717

1818
package com.lambda.module.modules.player
1919

20+
import com.lambda.config.groups.EatConfig.Companion.reasonEating
2021
import com.lambda.config.groups.EatSettings
21-
import com.lambda.config.groups.RotationSettings
22-
import com.lambda.context.SafeContext
2322
import com.lambda.event.events.TickEvent
24-
import com.lambda.event.events.UpdateManagerEvent
2523
import com.lambda.event.listener.SafeListener.Companion.listen
26-
import com.lambda.interaction.request.Request.Companion.submit
27-
import com.lambda.interaction.request.rotating.Rotation
28-
import com.lambda.interaction.request.rotating.Rotation.Companion.rotationTo
29-
import com.lambda.interaction.request.rotating.Rotation.Companion.wrap
30-
import com.lambda.interaction.request.rotating.RotationRequest
31-
import com.lambda.interaction.request.rotating.visibilty.lookAt
3224
import com.lambda.module.Module
3325
import com.lambda.module.tag.ModuleTag
3426
import com.lambda.task.RootTask.run
3527
import com.lambda.task.tasks.EatTask
3628
import com.lambda.task.tasks.EatTask.Companion.eat
37-
import com.lambda.task.tasks.EatTask.Companion.shouldEat
3829
import com.lambda.util.NamedEnum
39-
import com.lambda.util.math.distSq
40-
import net.minecraft.entity.Entity
41-
import net.minecraft.entity.player.PlayerEntity
42-
import net.minecraft.util.math.MathHelper.wrapDegrees
43-
import kotlin.random.Random
4430

4531
object AutoEat : Module(
4632
name = "AutoEat",
@@ -49,17 +35,15 @@ object AutoEat : Module(
4935
) {
5036
private enum class Group(override val displayName: String) : NamedEnum {
5137
FOOD("Food"),
52-
FIRE("Fire"),
53-
HEAL("Heal"),
5438
}
5539

5640
private val eat = EatSettings(this, Group.FOOD)
57-
5841
private var eatTask: EatTask? = null
5942

6043
init {
6144
listen<TickEvent.Pre> {
62-
if (eatTask != null || !shouldEat(eat)) return@listen
45+
val reason = reasonEating(eat)
46+
if (eatTask != null || !reason.shouldEat()) return@listen
6347

6448
val task = eat(eat)
6549
task.finally { eatTask = null }

src/main/kotlin/com/lambda/task/tasks/BuildTask.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import baritone.api.pathing.goals.GoalBlock
2121
import com.lambda.Lambda.LOG
2222
import com.lambda.config.groups.BuildConfig
2323
import com.lambda.config.groups.EatConfig
24+
import com.lambda.config.groups.EatConfig.Companion.reasonEating
2425
import com.lambda.config.groups.InteractionConfig
2526
import com.lambda.context.SafeContext
2627
import com.lambda.event.events.TickEvent
@@ -53,9 +54,6 @@ import com.lambda.interaction.request.rotating.RotationConfig
5354
import com.lambda.module.modules.client.TaskFlowModule
5455
import com.lambda.task.Task
5556
import com.lambda.task.tasks.EatTask.Companion.eat
56-
import com.lambda.task.tasks.EatTask.Companion.hasFood
57-
import com.lambda.task.tasks.EatTask.Companion.shouldEat
58-
import com.lambda.util.Communication.info
5957
import com.lambda.util.Formatting.string
6058
import com.lambda.util.extension.Structure
6159
import com.lambda.util.extension.inventorySlots
@@ -100,9 +98,9 @@ class BuildTask @Ta5kBuilder constructor(
10098

10199
init {
102100
listen<TickEvent.Pre> {
103-
val parentEating = (parent as? BuildTask)?.eatTask != null
101+
// val parentEating = (parent as? BuildTask)?.eatTask != null
104102
when {
105-
!parentEating && eatTask == null && shouldEat(eat) && hasFood(eat, inventory) -> {
103+
eatTask == null && reasonEating(eat).shouldEat() -> {
106104
eatTask = eat(eat)
107105
eatTask?.finally {
108106
eatTask = null

src/main/kotlin/com/lambda/task/tasks/EatTask.kt

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
package com.lambda.task.tasks
1919

2020
import com.lambda.config.groups.EatConfig
21+
import com.lambda.config.groups.EatConfig.Companion.reasonEating
2122
import com.lambda.context.SafeContext
22-
import com.lambda.event.Event
2323
import com.lambda.event.events.TickEvent
2424
import com.lambda.event.listener.SafeListener.Companion.listen
2525
import com.lambda.interaction.material.StackSelection.Companion.selectStack
@@ -28,35 +28,51 @@ import com.lambda.interaction.material.container.containers.MainHandContainer
2828
import com.lambda.interaction.request.inventory.InventoryConfig
2929
import com.lambda.module.modules.client.TaskFlowModule
3030
import com.lambda.task.Task
31-
import net.minecraft.component.DataComponentTypes
32-
import net.minecraft.component.type.FoodComponent
31+
import com.lambda.util.item.ItemUtils.nutrition
3332
import net.minecraft.item.ItemStack
3433
import net.minecraft.util.ActionResult
3534
import net.minecraft.util.Hand
36-
import java.awt.event.InputEvent
3735

3836
class EatTask @Ta5kBuilder constructor(
39-
val config: EatConfig = TaskFlowModule.eat,
40-
val inventory: InventoryConfig = TaskFlowModule.inventory,
37+
val config: EatConfig,
38+
val inventory: InventoryConfig
4139
) : Task<Unit>() {
4240
override val name: String
43-
get() = "Eating ${eatStack ?: "nothing"}"
41+
get() = reason.message(eatStack ?: ItemStack.EMPTY)
4442

4543
private var eatStack: ItemStack? = null
46-
private val selection get() = foodSelector(config)
44+
private var reason = EatConfig.Reason.None
45+
private var holdingUse = false
46+
47+
override fun SafeContext.onStart() {
48+
reason = reasonEating(config)
49+
}
4750

4851
init {
4952
listen<TickEvent.Input.Pre> {
50-
val nutrition = eatStack?.item?.components?.get(DataComponentTypes.FOOD)?.nutrition ?: 0
51-
val wouldBeFull = nutrition + player.hungerManager.foodLevel > 20
52-
if (!config.eatUntilFull && !shouldEat(config) || wouldBeFull) {
53+
if (holdingUse && !reason.shouldKeepEating(config, eatStack)) {
54+
mc.options.useKey.isPressed = false
55+
holdingUse = false
5356
interaction.stopUsingItem(player)
5457
success()
5558
return@listen
5659
}
5760

58-
if (!selection.matches(player.mainHandStack)) {
59-
selection.transfer(MainHandContainer, inventory)
61+
if (player.isUsingItem) {
62+
if (!holdingUse) {
63+
mc.options.useKey.isPressed = true
64+
holdingUse = true
65+
}
66+
return@listen
67+
}
68+
69+
val foodFinder = reason.selector(config)
70+
if (!foodFinder.matches(player.mainHandStack)) {
71+
if (holdingUse) {
72+
mc.options.useKey.isPressed = false
73+
holdingUse = false
74+
}
75+
foodFinder.transfer(MainHandContainer, inventory)
6076
?.execute(this@EatTask) ?: failure("No food found")
6177
return@listen
6278
}
@@ -65,25 +81,17 @@ class EatTask @Ta5kBuilder constructor(
6581
(interaction.interactItem(player, Hand.MAIN_HAND) as? ActionResult.Success)?.let {
6682
if (it.swingSource == ActionResult.SwingSource.CLIENT) player.swingHand(Hand.MAIN_HAND)
6783
mc.gameRenderer.firstPersonRenderer.resetEquipProgress(Hand.MAIN_HAND)
84+
mc.options.useKey.isPressed = true
85+
holdingUse = true
6886
}
6987
}
7088
}
7189

7290
companion object {
73-
fun foodSelector(config: EatConfig) = selectStack {
74-
when {
75-
config.selectionMode == EatConfig.SelectionMode.Whitelist -> isOneOfItems(config.whitelist)
76-
else -> isNoneOfItems(config.blacklist)
77-
} and isFood()
78-
}
79-
8091
@Ta5kBuilder
81-
fun eat(config: EatConfig) = EatTask(config)
82-
83-
fun SafeContext.shouldEat(config: EatConfig) =
84-
player.hungerManager.foodLevel <= config.minFoodLevel
85-
86-
fun hasFood(config: EatConfig, inventory: InventoryConfig) =
87-
foodSelector(config).transfer(MainHandContainer, inventory) != null
92+
fun eat(
93+
config: EatConfig = TaskFlowModule.eat,
94+
inventory: InventoryConfig = TaskFlowModule.inventory,
95+
) = EatTask(config, inventory)
8896
}
8997
}

0 commit comments

Comments
 (0)