Skip to content

Commit 61af38e

Browse files
committed
allow breaking with any tool with a setting for suitable only
1 parent adc8a42 commit 61af38e

File tree

4 files changed

+89
-50
lines changed

4 files changed

+89
-50
lines changed

common/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class BreakSettings(
4545
override val breakConfirmation by c.setting("Break Confirmation", BreakConfirmationMode.BreakThenAwait, "The style of confirmation used when breaking") { vis() }
4646
override val maxPendingBreaks by c.setting("Max Pending Breaks", 15, 1..30, 1, "The maximum amount of pending breaks") { vis() }
4747
override val breaksPerTick by c.setting("Breaks Per Tick", 5, 1..30, 1, "Maximum instant block breaks per tick") { vis() }
48+
override val suitableToolsOnly by c.setting("Suitable Tools Only", false, "Places a restriction to only use tools suitable for the given block", visibility = vis)
4849
override val breakWeakBlocks by c.setting("Break Weak Blocks", false, "Break blocks that dont have structural integrity (e.g: grass)") { vis() }
4950
override val forceSilkTouch by c.setting("Force Silk Touch", false, "Force silk touch when breaking blocks") { vis() }
5051
override val forceFortunePickaxe by c.setting("Force Fortune Pickaxe", false, "Force fortune pickaxe when breaking blocks") { vis() }

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

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import com.lambda.interaction.construction.result.BuildResult
3030
import com.lambda.interaction.construction.result.PlaceResult
3131
import com.lambda.interaction.construction.verify.TargetState
3232
import com.lambda.interaction.material.ContainerSelection.Companion.selectContainer
33+
import com.lambda.interaction.material.StackSelection
3334
import com.lambda.interaction.material.StackSelection.Companion.select
3435
import com.lambda.interaction.material.StackSelection.Companion.selectStack
3536
import com.lambda.interaction.material.container.ContainerManager.containerWithMaterial
@@ -56,7 +57,6 @@ import com.lambda.util.BlockUtils.instantBreakable
5657
import com.lambda.util.BlockUtils.vecOf
5758
import com.lambda.util.Communication.warn
5859
import com.lambda.util.item.ItemStackUtils.equal
59-
import com.lambda.util.item.ItemUtils.findBestToolsForBreaking
6060
import com.lambda.util.math.distSq
6161
import com.lambda.util.player.SlotUtils.hotbar
6262
import com.lambda.util.player.copyPlayer
@@ -68,6 +68,7 @@ import net.minecraft.block.pattern.CachedBlockPosition
6868
import net.minecraft.enchantment.Enchantments
6969
import net.minecraft.item.BlockItem
7070
import net.minecraft.item.ItemPlacementContext
71+
import net.minecraft.item.ItemStack
7172
import net.minecraft.item.ItemUsageContext
7273
import net.minecraft.registry.RegistryKeys
7374
import net.minecraft.util.Hand
@@ -542,45 +543,67 @@ object BuildSimulator {
542543
return acc
543544
}
544545

545-
val bestTools = findBestToolsForBreaking(state, inventory.allowedTools)
546-
547-
/* there is no good tool for the job */
548-
if (bestTools.isEmpty()) {
549-
/* The current selected item cant mine the block */
550-
Hand.entries.forEach {
551-
val stack = player.getStackInHand(it)
552-
if (stack.isEmpty) return@forEach
553-
if (stack.item.canMine(state, world, pos, player)) return@forEach
554-
acc.add(BreakResult.ItemCantMine(pos, state, stack.item, inventory))
555-
return acc
546+
// val bestTools = findBestToolForBreaking(state, inventory.allowedTools)
547+
//
548+
// /* there is no good tool for the job */
549+
// if (bestTools.isEmpty()) {
550+
// /* The current selected item cant mine the block */
551+
// Hand.entries.forEach {
552+
// val stack = player.getStackInHand(it)
553+
// if (stack.isEmpty) return@forEach
554+
// if (stack.item.canMine(state, world, pos, player)) return@forEach
555+
// acc.add(BreakResult.ItemCantMine(pos, state, stack.item, inventory))
556+
// return acc
557+
// }
558+
// // ToDo: Switch to non destroyable item
559+
// acc.add(BreakResult.Break(pos, breakContext))
560+
// return acc
561+
// }
562+
//
563+
// val toolSelection = if (build.breaking.forceSilkTouch) {
564+
// selectStack { isOneOfItems(bestTools) and hasEnchantment(Enchantments.SILK_TOUCH) }
565+
// } else if (build.breaking.forceFortunePickaxe) {
566+
// selectStack { isOneOfItems(bestTools) and hasEnchantment(Enchantments.FORTUNE, build.breaking.minFortuneLevel) }
567+
// } else {
568+
// bestTools.select()
569+
// }
570+
// val silentSwapSelection = selectContainer {
571+
// matches(toolSelection) and ofAnyType(MaterialContainer.Rank.HOTBAR)
572+
// }
573+
// val fullSelection = selectContainer {
574+
// matches(toolSelection) and matches(inventory.containerSelection)
575+
// }
576+
577+
val stackSelection = selectStack(
578+
block = {
579+
run {
580+
if (build.breaking.suitableToolsOnly) isSuitableForBreaking(state)
581+
else StackSelection.EVERYTHING
582+
} and if (build.breaking.forceSilkTouch) {
583+
hasEnchantment(Enchantments.SILK_TOUCH)
584+
} else if (build.breaking.forceFortunePickaxe) {
585+
hasEnchantment(Enchantments.FORTUNE, build.breaking.minFortuneLevel)
586+
} else StackSelection.EVERYTHING
587+
},
588+
sorter = compareByDescending<ItemStack> {
589+
it.canDestroy(world.registryManager.get(RegistryKeys.BLOCK), CachedBlockPosition(world, pos, false))
590+
}.thenByDescending {
591+
state.calcItemBlockBreakingDelta(player, world, pos, it)
556592
}
557-
// ToDo: Switch to non destroyable item
558-
acc.add(BreakResult.Break(pos, breakContext))
559-
return acc
560-
}
593+
)
561594

562-
val toolSelection = if (build.breaking.forceSilkTouch) {
563-
selectStack { isOneOfItems(bestTools) and hasEnchantment(Enchantments.SILK_TOUCH) }
564-
} else if (build.breaking.forceFortunePickaxe) {
565-
selectStack { isOneOfItems(bestTools) and hasEnchantment(Enchantments.FORTUNE, build.breaking.minFortuneLevel) }
566-
} else {
567-
bestTools.select()
568-
}
569595
val silentSwapSelection = selectContainer {
570-
matches(toolSelection) and ofAnyType(MaterialContainer.Rank.HOTBAR)
596+
matches(stackSelection) and ofAnyType(MaterialContainer.Rank.HOTBAR)
571597
}
572-
val fullSelection = selectContainer {
573-
matches(toolSelection) and matches(inventory.containerSelection)
574-
}
575598

576-
val swapCandidates = toolSelection.containerWithMaterial(inventory, silentSwapSelection)
599+
val swapCandidates = stackSelection.containerWithMaterial(inventory, silentSwapSelection)
577600
if (swapCandidates.isEmpty()) {
578-
acc.add(BuildResult.WrongItemSelection(pos, breakContext, toolSelection, player.mainHandStack, inventory))
601+
acc.add(BuildResult.WrongItemSelection(pos, breakContext, stackSelection, player.mainHandStack, inventory))
579602
return acc
580603
}
581604

582-
val matchingStacks = swapCandidates.associateWith { it.matchingStacks(toolSelection) }
583-
val (container, toolPair) = matchingStacks.mapValues { (_, stacks) ->
605+
val matchingStacks = swapCandidates.associateWith { it.matchingStacks(stackSelection) }
606+
val (_, toolPair) = matchingStacks.mapValues { (_, stacks) ->
584607
stacks.associateWith { state.calcItemBlockBreakingDelta(player, world, pos, it) }
585608
.maxByOrNull { it.value }
586609
?.toPair()

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

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package com.lambda.interaction.material
2020
import com.lambda.util.BlockUtils.item
2121
import com.lambda.util.item.ItemStackUtils.shulkerBoxContents
2222
import net.minecraft.block.Block
23+
import net.minecraft.block.BlockState
2324
import net.minecraft.enchantment.Enchantment
2425
import net.minecraft.enchantment.EnchantmentHelper
2526
import net.minecraft.item.Item
@@ -32,6 +33,7 @@ import kotlin.reflect.KClass
3233
*/
3334
class StackSelection {
3435
var selector: (ItemStack) -> Boolean = { true }
36+
var comparator: Comparator<ItemStack>? = null
3537
var count: Int = DEFAULT_AMOUNT
3638
var inShulkerBox: Boolean = false
3739

@@ -45,28 +47,24 @@ class StackSelection {
4547
val optimalStack: ItemStack?
4648
get() = itemStack ?: item?.let { ItemStack(it, count) }
4749

48-
val filterStack: (ItemStack) -> Boolean
49-
get() = { stack ->
50-
if (inShulkerBox) {
51-
stack.shulkerBoxContents.any { selector(it) }
52-
} else {
53-
selector(stack)
54-
}
55-
}
50+
fun filterStack(stack: ItemStack) =
51+
if (inShulkerBox) stack.shulkerBoxContents.any { selector(it) }
52+
else selector(stack)
5653

57-
val filterSlot: (Slot) -> Boolean
58-
get() = { slot ->
59-
filterStack(slot.stack)
60-
}
54+
fun filterSlot(slot: Slot) = filterStack(slot.stack)
6155

62-
val filterStacks: (List<ItemStack>) -> List<ItemStack>
63-
get() = {
64-
it.filter(filterStack)
56+
fun filterStacks(stacks: List<ItemStack>): List<ItemStack> =
57+
stacks.filter(::filterStack).let { filteredStacks ->
58+
comparator?.run {
59+
filteredStacks.sortedWith(this)
60+
} ?: filteredStacks
6561
}
6662

67-
val filterSlots: (List<Slot>) -> List<Slot>
68-
get() = { slots ->
69-
slots.filter { filterSlot(it) }
63+
fun filterSlots(slots: List<Slot>): List<Slot> =
64+
slots.filter(::filterSlot).let { filteredSlots ->
65+
comparator?.run {
66+
filteredSlots.sortedWith { slot, slot2 -> compare(slot.stack, slot2.stack) }
67+
} ?: filteredSlots
7068
}
7169

7270
/**
@@ -127,6 +125,9 @@ class StackSelection {
127125
@StackSelectionDsl
128126
fun isOneOfStacks(stacks: Collection<ItemStack>): (ItemStack) -> Boolean = { it in stacks }
129127

128+
@StackSelectionDsl
129+
fun isSuitableForBreaking(blockState: BlockState): (ItemStack) -> Boolean = { it.isSuitableFor(blockState) }
130+
130131
/**
131132
* [isItem] returns a predicate that matches a specific [Item] instance.
132133
* @param T The instance of [Item] to be matched.
@@ -257,15 +258,28 @@ class StackSelection {
257258
* @param block The predicate to be used to select the items.
258259
* @return A [StackSelection] with the given parameters.
259260
*/
261+
@StackSelectionDsl
262+
fun selectStack(
263+
count: Int = DEFAULT_AMOUNT,
264+
inShulkerBox: Boolean = false,
265+
block: StackSelection.() -> (ItemStack) -> Boolean
266+
) = StackSelection().apply {
267+
selector = block()
268+
this.count = count
269+
this.inShulkerBox = inShulkerBox
270+
}
271+
260272
@StackSelectionDsl
261273
fun selectStack(
262274
count: Int = DEFAULT_AMOUNT,
263275
inShulkerBox: Boolean = false,
264276
block: StackSelection.() -> (ItemStack) -> Boolean,
277+
sorter: Comparator<ItemStack>? = null
265278
) = StackSelection().apply {
266279
selector = block()
280+
comparator = sorter
267281
this.count = count
268282
this.inShulkerBox = inShulkerBox
269283
}
270284
}
271-
}
285+
}

common/src/main/kotlin/com/lambda/interaction/request/breaking/BreakConfig.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ abstract class BreakConfig(
4242
abstract val breakConfirmation: BreakConfirmationMode
4343
abstract val maxPendingBreaks: Int
4444
abstract val breaksPerTick: Int
45+
abstract val suitableToolsOnly: Boolean
4546
abstract val breakWeakBlocks: Boolean
4647
abstract val forceSilkTouch: Boolean
4748
abstract val forceFortunePickaxe: Boolean

0 commit comments

Comments
 (0)