Skip to content

Commit eca598c

Browse files
committed
base auto armor module
1 parent ae68bff commit eca598c

File tree

14 files changed

+198
-39
lines changed

14 files changed

+198
-39
lines changed

src/main/kotlin/com/lambda/interaction/material/container/containers/HotbarContainer.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ import com.lambda.interaction.material.ContainerTask
2424
import com.lambda.interaction.material.StackSelection
2525
import com.lambda.interaction.material.container.MaterialContainer
2626
import com.lambda.interaction.material.transfer.SlotTransfer.Companion.deposit
27-
import com.lambda.util.player.SlotUtils.hotbar
27+
import com.lambda.util.player.SlotUtils.hotbarStacks
2828
import com.lambda.util.text.buildText
2929
import com.lambda.util.text.literal
3030
import net.minecraft.item.ItemStack
3131

3232
object HotbarContainer : MaterialContainer(Rank.Hotbar) {
3333
override var stacks: List<ItemStack>
34-
get() = mc.player?.hotbar ?: emptyList()
34+
get() = mc.player?.hotbarStacks ?: emptyList()
3535
set(_) {}
3636

3737
override val description = buildText { literal("Hotbar") }

src/main/kotlin/com/lambda/interaction/material/container/containers/InventoryContainer.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ package com.lambda.interaction.material.container.containers
2020
import com.lambda.Lambda.mc
2121
import com.lambda.context.SafeContext
2222
import com.lambda.interaction.material.container.MaterialContainer
23-
import com.lambda.util.player.SlotUtils.combined
23+
import com.lambda.util.player.SlotUtils.allStacks
2424
import com.lambda.util.text.buildText
2525
import com.lambda.util.text.literal
2626
import net.minecraft.item.ItemStack
2727

2828
object InventoryContainer : MaterialContainer(Rank.Inventory) {
2929
override var stacks: List<ItemStack>
30-
get() = mc.player?.combined ?: emptyList()
30+
get() = mc.player?.allStacks ?: emptyList()
3131
set(_) {}
3232

3333
override val description = buildText { literal("Inventory") }

src/main/kotlin/com/lambda/module/modules/combat/AutoDisconnect.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import com.lambda.util.combat.CombatUtils.hasDeadlyCrystal
3232
import com.lambda.util.combat.DamageUtils.isFallDeadly
3333
import com.lambda.util.extension.fullHealth
3434
import com.lambda.util.extension.tickDelta
35-
import com.lambda.util.player.SlotUtils.combined
35+
import com.lambda.util.player.SlotUtils.allStacks
3636
import com.lambda.util.text.buildText
3737
import com.lambda.util.text.color
3838
import com.lambda.util.text.highlighted
@@ -41,12 +41,10 @@ import com.lambda.util.text.text
4141
import com.lambda.util.world.fastEntitySearch
4242
import net.minecraft.entity.damage.DamageSource
4343
import net.minecraft.entity.damage.DamageTypes
44-
import net.minecraft.entity.effect.StatusEffect
4544
import net.minecraft.entity.effect.StatusEffects
4645
import net.minecraft.entity.mob.CreeperEntity
4746
import net.minecraft.entity.player.PlayerEntity
4847
import net.minecraft.item.Items
49-
import net.minecraft.registry.Registries
5048
import net.minecraft.sound.SoundEvents
5149
import net.minecraft.text.Text
5250
import net.minecraft.world.GameMode
@@ -208,7 +206,7 @@ object AutoDisconnect : Module(
208206
} else null
209207
}),
210208
Totem({ totem }, {
211-
val totemCount = player.combined.count { it.item == Items.TOTEM_OF_UNDYING }
209+
val totemCount = player.allStacks.count { it.item == Items.TOTEM_OF_UNDYING }
212210
if (totemCount < minTotems) {
213211
buildText {
214212
literal("Only ")

src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import com.lambda.util.NamedEnum
3535
import com.lambda.util.item.ItemStackUtils.attackDamage
3636
import com.lambda.util.item.ItemStackUtils.attackSpeed
3737
import com.lambda.util.math.random
38-
import com.lambda.util.player.SlotUtils.hotbar
38+
import com.lambda.util.player.SlotUtils.hotbarStacks
3939
import net.minecraft.entity.LivingEntity
4040
import net.minecraft.item.ItemStack
4141
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket
@@ -120,8 +120,8 @@ object KillAura : Module(
120120
damageMode.block(this, it)
121121
}
122122

123-
selection.bestItemMatch(player.hotbar)?.let { bestStack ->
124-
val slotId = player.hotbar.indexOf(bestStack)
123+
selection.bestItemMatch(player.hotbarStacks)?.let { bestStack ->
124+
val slotId = player.hotbarStacks.indexOf(bestStack)
125125
if (!HotbarRequest(slotId, this@KillAura, nowOrNothing = false).submit().done) return@listen
126126
}
127127
}

src/main/kotlin/com/lambda/module/modules/combat/PlayerTrap.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import com.lambda.util.BlockUtils.blockState
3333
import com.lambda.util.extension.shrinkByEpsilon
3434
import com.lambda.util.item.ItemUtils.block
3535
import com.lambda.util.math.flooredBlockPos
36-
import com.lambda.util.player.SlotUtils.hotbarAndStorage
36+
import com.lambda.util.player.SlotUtils.hotbarAndInventoryStacks
3737
import com.lambda.util.world.entitySearch
3838
import net.minecraft.block.Blocks
3939
import net.minecraft.client.network.OtherClientPlayerEntity
@@ -74,7 +74,7 @@ object PlayerTrap : Module(
7474

7575
onEnable {
7676
task = tickingBlueprint {
77-
val block = player.hotbarAndStorage.firstOrNull {
77+
val block = player.hotbarAndInventoryStacks.firstOrNull {
7878
it.item is BlockItem && blocks.contains(it.item.block)
7979
}?.item?.block ?: return@tickingBlueprint emptyMap()
8080
val targetPlayer = if (self) player

src/main/kotlin/com/lambda/module/modules/combat/Surround.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import com.lambda.task.RootTask.run
2929
import com.lambda.task.Task
3030
import com.lambda.task.tasks.BuildTask.Companion.build
3131
import com.lambda.util.item.ItemUtils.block
32-
import com.lambda.util.player.SlotUtils.hotbarAndStorage
32+
import com.lambda.util.player.SlotUtils.hotbarAndInventoryStacks
3333
import net.minecraft.block.Blocks
3434
import net.minecraft.item.BlockItem
3535

@@ -63,7 +63,7 @@ object Surround : Module(
6363

6464
onEnable {
6565
task = tickingBlueprint {
66-
val block = player.hotbarAndStorage.firstOrNull {
66+
val block = player.hotbarAndInventoryStacks.firstOrNull {
6767
it.item is BlockItem && blocks.contains(it.item.block)
6868
}?.item?.block ?: return@tickingBlueprint emptyMap()
6969
getTrapPositions(player)

src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ import com.lambda.module.tag.ModuleTag
3333
import com.lambda.threading.runSafe
3434
import com.lambda.util.KeyCode
3535
import com.lambda.util.Mouse
36-
import com.lambda.util.player.SlotUtils.hotbar
37-
import com.lambda.util.player.SlotUtils.hotbarAndStorage
36+
import com.lambda.util.player.SlotUtils.hotbarAndInventoryStacks
37+
import com.lambda.util.player.SlotUtils.hotbarStacks
3838
import net.minecraft.client.network.ClientPlayerEntity
3939
import net.minecraft.entity.effect.StatusEffects
4040
import net.minecraft.item.Items
@@ -209,9 +209,9 @@ object BetterFirework : Module(
209209
fun SafeContext.startFirework(silent: Boolean) {
210210
val stack = selectStack(count = 1) { isItem(Items.FIREWORK_ROCKET) }
211211

212-
stack.bestItemMatch(player.hotbar)
212+
stack.bestItemMatch(player.hotbarStacks)
213213
?.let {
214-
val request = HotbarRequest(player.hotbar.indexOf(it), this@BetterFirework, keepTicks = 0)
214+
val request = HotbarRequest(player.hotbarStacks.indexOf(it), this@BetterFirework, keepTicks = 0)
215215
.submit(queueIfMismatchedStage = false)
216216
if (request.done) {
217217
interaction.interactItem(player, Hand.MAIN_HAND)
@@ -222,10 +222,10 @@ object BetterFirework : Module(
222222

223223
if (!silent) return
224224

225-
stack.bestItemMatch(player.hotbarAndStorage)
225+
stack.bestItemMatch(player.hotbarAndInventoryStacks)
226226
?.let {
227-
val swapSlotId = player.hotbarAndStorage.indexOf(it)
228-
val hotbarSlotToSwapWith = player.hotbar.find { slot -> slot.isEmpty }?.let { slot -> player.hotbar.indexOf(slot) } ?: 8
227+
val swapSlotId = player.hotbarAndInventoryStacks.indexOf(it)
228+
val hotbarSlotToSwapWith = player.hotbarStacks.find { slot -> slot.isEmpty }?.let { slot -> player.hotbarStacks.indexOf(slot) } ?: 8
229229

230230
inventoryRequest {
231231
swap(swapSlotId, hotbarSlotToSwapWith)
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.module.modules.player
19+
20+
import com.lambda.config.AutomationConfig.Companion.setDefaultAutomationConfig
21+
import com.lambda.config.applyEdits
22+
import com.lambda.config.settings.complex.Bind
23+
import com.lambda.context.SafeContext
24+
import com.lambda.event.events.KeyboardEvent
25+
import com.lambda.event.events.MouseEvent
26+
import com.lambda.event.events.TickEvent
27+
import com.lambda.event.listener.SafeListener.Companion.listen
28+
import com.lambda.interaction.managers.inventory.InventoryRequest.Companion.inventoryRequest
29+
import com.lambda.module.Module
30+
import com.lambda.module.tag.ModuleTag
31+
import com.lambda.util.EnchantmentUtils.getEnchantment
32+
import com.lambda.util.InputUtils.isSatisfied
33+
import com.lambda.util.player.SlotUtils.armorSlots
34+
import com.lambda.util.player.SlotUtils.hotbarAndInventorySlots
35+
import net.minecraft.component.DataComponentTypes
36+
import net.minecraft.enchantment.Enchantment
37+
import net.minecraft.enchantment.Enchantments
38+
import net.minecraft.entity.attribute.EntityAttributes
39+
import net.minecraft.item.ItemStack
40+
import net.minecraft.item.Items
41+
import net.minecraft.registry.RegistryKey
42+
import net.minecraft.registry.tag.ItemTags
43+
import net.minecraft.screen.slot.Slot
44+
45+
object AutoArmor : Module(
46+
name = "AutoArmor",
47+
description = "Automatically equips armor",
48+
tag = ModuleTag.PLAYER
49+
) {
50+
private var elytraPriority by setting("Elytra Priority", true, "Prioritizes elytra's over other armor pieces in the chest slot")
51+
private val toggleElytraPriority by setting("Toggle Elytra Priority", Bind.EMPTY)
52+
private val headProtection by setting("Preferred Head Protection", Protection.Protection)
53+
private val chestProtection by setting("Preferred Chest Protection", Protection.Protection)
54+
private val legProtection by setting("Preferred Leg Protection", Protection.BlastProtection)
55+
private val feetProtection by setting("Preferred Feet Protection", Protection.Protection)
56+
private val ignoreBinding by setting("Ignore Binding", true, "Ignores curse of binding armor pieces")
57+
58+
init {
59+
setDefaultAutomationConfig {
60+
applyEdits {
61+
hideAllGroupsExcept(inventoryConfig)
62+
}
63+
}
64+
65+
listen<TickEvent.Pre> {
66+
val armorSlots = player.armorSlots
67+
68+
val sorter = compareByDescending<Slot> {
69+
if (elytraPriority) {
70+
if (it.stack.item == Items.ELYTRA) 1.0
71+
else 0.0
72+
} else it.stack.getOrDefault(DataComponentTypes.ATTRIBUTE_MODIFIERS, null)
73+
?.modifiers
74+
?.find { modifier -> modifier.attribute == EntityAttributes.ARMOR }
75+
?.modifier?.value
76+
?: 0.0
77+
}.thenByDescending {
78+
it.stack.getOrDefault(DataComponentTypes.ATTRIBUTE_MODIFIERS, null)
79+
?.modifiers
80+
?.find { modifier -> modifier.attribute == EntityAttributes.ARMOR_TOUGHNESS }
81+
?.modifier?.value
82+
?: 0.0
83+
}.thenByDescending {
84+
val stack = it.stack
85+
when {
86+
stack.isIn(ItemTags.FOOT_ARMOR) -> stack.getEnchantment(feetProtection.enchant)
87+
stack.isIn(ItemTags.LEG_ARMOR) -> stack.getEnchantment(legProtection.enchant)
88+
stack.isIn(ItemTags.CHEST_ARMOR) -> stack.getEnchantment(chestProtection.enchant)
89+
else -> stack.getEnchantment(headProtection.enchant)
90+
}
91+
}.thenByDescending { slot ->
92+
Protection.entries.fold(0) { acc, protection ->
93+
acc + slot.stack.getEnchantment(protection.enchant)
94+
}
95+
}.thenByDescending { slot ->
96+
slot.stack.getEnchantment(Enchantments.UNBREAKING) +
97+
slot.stack.getEnchantment(Enchantments.MENDING)
98+
}
99+
100+
val swappable = player.hotbarAndInventorySlots
101+
.filter { it.stack.isEquipable && (!ignoreBinding || it.stack.getEnchantment(Enchantments.BINDING_CURSE) <= 0) }
102+
.sortedWith(sorter)
103+
.distinctBy { it.stack.item }
104+
105+
val swaps = mutableListOf<Pair<Slot, Slot>>()
106+
armorSlots.forEach { equipped ->
107+
val new = swappable.find { new ->
108+
equipped.canInsert(new.stack) && sorter.compare(equipped, new) > 0
109+
} ?: return@forEach
110+
111+
swaps.add(Pair(new, equipped))
112+
}
113+
114+
if (swaps.isEmpty()) return@listen
115+
inventoryRequest {
116+
swaps.forEach {
117+
pickup(it.first.id)
118+
pickup(it.second.id)
119+
if (it.second.stack !== ItemStack.EMPTY)
120+
pickup(it.first.id)
121+
}
122+
}.submit()
123+
}
124+
125+
listen<KeyboardEvent.Press> { if (toggleElytraPriority.isSatisfied()) elytraPriority = !elytraPriority }
126+
listen<MouseEvent.Click> { if (toggleElytraPriority.isSatisfied()) elytraPriority = !elytraPriority }
127+
}
128+
129+
context(safeContext: SafeContext)
130+
private val ItemStack.isEquipable get() =
131+
safeContext.player.armorSlots.any { it.canInsert(this) }
132+
133+
private enum class Protection(val enchant: RegistryKey<Enchantment>) {
134+
Protection(Enchantments.PROTECTION),
135+
BlastProtection(Enchantments.BLAST_PROTECTION),
136+
ProjectileProtection(Enchantments.PROJECTILE_PROTECTION),
137+
FireProtection(Enchantments.FIRE_PROTECTION);
138+
}
139+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import com.lambda.module.tag.ModuleTag
2424
import com.lambda.util.FileUtils.locationBoundDirectory
2525
import com.lambda.util.FolderRegister
2626
import com.lambda.util.StringUtils.hashString
27-
import com.lambda.util.player.SlotUtils.combined
27+
import com.lambda.util.player.SlotUtils.allStacks
2828
import com.lambda.util.world.entitySearch
2929
import net.minecraft.block.MapColor
3030
import net.minecraft.entity.decoration.ItemFrameEntity
@@ -42,7 +42,7 @@ object MapDownloader : Module(
4242
listen<TickEvent.Pre> {
4343
val mapStates = entitySearch<ItemFrameEntity>(128.0)
4444
.mapNotNull { FilledMapItem.getMapState(it.heldItemStack, world) } +
45-
player.combined.mapNotNull { FilledMapItem.getMapState(it, world) }
45+
player.allStacks.mapNotNull { FilledMapItem.getMapState(it, world) }
4646

4747
mapStates.forEach { map ->
4848
val name = map.hash

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import com.lambda.interaction.managers.inventory.InventoryRequest.Companion.inve
2626
import com.lambda.module.Module
2727
import com.lambda.module.tag.ModuleTag
2828
import com.lambda.util.item.ItemStackUtils.slotId
29-
import com.lambda.util.player.SlotUtils.hotbar
30-
import com.lambda.util.player.SlotUtils.storage
29+
import com.lambda.util.player.SlotUtils.hotbarStacks
30+
import com.lambda.util.player.SlotUtils.inventoryStacks
3131
import net.minecraft.item.ItemStack
3232
import net.minecraft.item.Items
3333

@@ -52,7 +52,7 @@ object StackReplenish : Module(
5252

5353
listen<TickEvent.Pre> {
5454
if (player.currentScreenHandler.cursorStack.item !== Items.AIR) return@listen
55-
player.hotbar.forEach { stack -> checkReplenish(stack) }
55+
player.hotbarStacks.forEach { stack -> checkReplenish(stack) }
5656
if (offhand) checkReplenish(player.offHandStack)
5757
}
5858
}
@@ -61,7 +61,7 @@ object StackReplenish : Module(
6161
if (stack.count.toFloat() / stack.maxCount >= (minStackPercent.toFloat() / 100)) return
6262
if (!stack.isStackable) return
6363

64-
player.storage.forEach { invStack ->
64+
player.inventoryStacks.forEach { invStack ->
6565
if (invStack.item !== stack.item) return@forEach
6666
val invId = invStack.slotId
6767
val completing = stack.count + invStack.count >= stack.maxCount

0 commit comments

Comments
 (0)