Skip to content

Commit cc8408a

Browse files
committed
Refactor inventory handling and transaction structure.
Replaced `InventoryTransfer` with `TransactionExecutor` for improved naming and functionality. Renamed `InventoryTransferTask` to `SlotTransfer` and updated method calls accordingly. Introduced `QuickCraftTransaction` and `TransferSelection` for expanded transaction capabilities and added error handling in `InventoryChanges`.
1 parent 3442d57 commit cc8408a

File tree

12 files changed

+126
-49
lines changed

12 files changed

+126
-49
lines changed

common/src/main/java/com/lambda/mixin/entity/ClientPlayInteractionManagerMixin.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ public void interactItemHead(PlayerEntity player, Hand hand, CallbackInfoReturna
6666
}
6767
}
6868

69-
@Inject(method = "attackBlock", at = @At("HEAD"))
69+
@Inject(method = "attackBlock", at = @At("HEAD"), cancellable = true)
7070
public void onAttackBlock(BlockPos pos, Direction side, CallbackInfoReturnable<Boolean> cir) {
71-
if (EventFlow.post(new PlayerEvent.Attack.Block(pos, side)).isCanceled()) cir.cancel();
71+
if (EventFlow.post(new PlayerEvent.Attack.Block(pos, side)).isCanceled()) {
72+
cir.setReturnValue(false);
73+
}
7274
}
7375

7476
@Inject(method = "attackEntity", at = @At("HEAD"), cancellable = true)

common/src/main/kotlin/com/lambda/interaction/construction/result/BreakResult.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ sealed class BreakResult : BuildResult() {
110110
?: selectStack {
111111
isItem(badItem).not()
112112
}.transfer(MainHandContainer)
113-
?: MaterialContainer.Nothing()
113+
?: MaterialContainer.Nothing("Couldn't find a tool for ${blockState.block.name.string} with $badItem in main hand.")
114114

115115
override fun SafeContext.buildRenderer() {
116116
withPos(blockPos, color)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
package com.lambda.interaction.material.container.containers
1919

2020
import com.lambda.interaction.material.StackSelection
21-
import com.lambda.interaction.material.transfer.InventoryTransferTask.Companion.deposit
22-
import com.lambda.interaction.material.transfer.InventoryTransferTask.Companion.withdraw
21+
import com.lambda.interaction.material.transfer.SlotTransfer.Companion.deposit
22+
import com.lambda.interaction.material.transfer.SlotTransfer.Companion.withdraw
2323
import com.lambda.interaction.material.container.MaterialContainer
2424
import com.lambda.task.tasks.OpenContainer
2525
import com.lambda.util.Communication.info

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import com.lambda.Lambda.mc
2121
import com.lambda.context.SafeContext
2222
import com.lambda.interaction.material.ContainerTask
2323
import com.lambda.interaction.material.StackSelection
24-
import com.lambda.interaction.material.transfer.InventoryTransferTask.Companion.deposit
24+
import com.lambda.interaction.material.transfer.SlotTransfer.Companion.deposit
2525
import com.lambda.interaction.material.container.MaterialContainer
2626
import com.lambda.util.player.SlotUtils.hotbar
2727
import com.lambda.util.text.buildText

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ 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.ContainerTask
23-
import com.lambda.interaction.material.transfer.InventoryTransfer.Companion.transfer
23+
import com.lambda.interaction.material.transfer.TransactionExecutor.Companion.transfer
2424
import com.lambda.interaction.material.StackSelection
2525
import com.lambda.interaction.material.container.MaterialContainer
2626
import com.lambda.util.item.ItemStackUtils.equal

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import com.lambda.context.SafeContext
2121
import com.lambda.interaction.material.StackSelection
2222
import com.lambda.task.Task
2323
import com.lambda.task.tasks.BuildTask.Companion.breakAndCollectBlock
24-
import com.lambda.interaction.material.transfer.InventoryTransferTask.Companion.deposit
25-
import com.lambda.interaction.material.transfer.InventoryTransferTask.Companion.withdraw
24+
import com.lambda.interaction.material.transfer.SlotTransfer.Companion.deposit
25+
import com.lambda.interaction.material.transfer.SlotTransfer.Companion.withdraw
2626
import com.lambda.interaction.material.container.MaterialContainer
2727
import com.lambda.task.tasks.OpenContainer
2828
import com.lambda.task.tasks.PlaceContainer

common/src/main/kotlin/com/lambda/interaction/material/transfer/InventoryChanges.kt

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,41 @@
11
package com.lambda.interaction.material.transfer
22

3-
import com.lambda.context.SafeContext
43
import com.lambda.interaction.material.StackSelection
4+
import com.lambda.util.item.ItemStackUtils.equal
55
import net.minecraft.item.ItemStack
66
import net.minecraft.screen.slot.Slot
77

8+
/**
9+
* A class representing changes in an inventory's state over time. It acts as a tracker for
10+
* detecting, storing, and merging differences between the original and updated states of
11+
* inventory slots. This class extends a map-like structure, where the key is the slot index
12+
* and the value is a list of pairs representing the original and updated states of an inventory slot.
13+
*
14+
* Example:
15+
* ```
16+
* #0: 64 obsidian -> 0 air, 0 air -> 64 obsidian
17+
* #36: 12 observer -> 11 observer
18+
* ```
19+
* - Where `#0` is the slot id, first it was emptied and then got `64 obsidian` again
20+
* - Where `#36` is the slot id, that was reduced by `1 observer`
21+
*
22+
* @property slots A list of `Slot` objects representing the current inventory slots being tracked.
23+
* Defaults to an empty list.
24+
*/
825
class InventoryChanges(
9-
ctx: SafeContext
26+
private var slots: List<Slot>,
1027
) : MutableMap<Int, MutableList<Pair<ItemStack, ItemStack>>> by HashMap() {
11-
12-
private var slots = ctx.player.currentScreenHandler.slots
13-
private val originalStacks = slots.map { it.stack.copy() } // Snapshot of the initial state
28+
private val originalStacks = slots.map { it.stack.copy() }
1429

1530
/**
1631
* Detect and store changes directly in the map.
1732
*/
1833
fun detectChanges() {
34+
require(slots.isNotEmpty()) { "Cannot detect changes on an empty slots list" }
1935
slots.forEachIndexed { index, slot ->
2036
val originalStack = originalStacks[index]
2137
val updatedStack = slot.stack
22-
if (!ItemStack.areEqual(originalStack, updatedStack)) {
38+
if (!originalStack.equal(updatedStack)) {
2339
getOrPut(index) { mutableListOf() }.add(originalStack to updatedStack.copy())
2440
}
2541
}
@@ -32,12 +48,23 @@ class InventoryChanges(
3248
* @return A new `InventoryChanges` instance containing merged entries.
3349
*/
3450
infix fun merge(other: InventoryChanges) {
51+
require(slots.isNotEmpty()) { "Cannot merge changes to an empty slots list" }
3552
other.forEach { (key, value) ->
3653
getOrPut(key) { mutableListOf() }.addAll(value)
3754
}
3855
}
3956

57+
/**
58+
* Evaluates if the current inventory changes fulfill the given selection requirement.
59+
*
60+
* @param to A list of `Slot` objects to evaluate for the selection criteria.
61+
* @param selection A `StackSelection` object that specifies the selection criteria, including the
62+
* target items and their required count.
63+
* @return `true` if the total count of matching items across the filtered slots meets or exceeds
64+
* the required count specified in the `StackSelection`; `false` otherwise.
65+
*/
4066
fun fulfillsSelection(to: List<Slot>, selection: StackSelection): Boolean {
67+
require(slots.isNotEmpty()) { "Cannot evaluate selection on an empty slots list" }
4168
val targetSlots = selection.filterSlots(to).map { it.id }
4269
return filter { it.key in targetSlots }.entries.sumOf { (_, changes) ->
4370
changes.lastOrNull()?.second?.count ?: 0

common/src/main/kotlin/com/lambda/interaction/material/transfer/InventoryTransaction.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,16 @@ import com.lambda.task.Task
2222
import com.lambda.threading.runSafe
2323

2424
abstract class InventoryTransaction : Task<InventoryChanges>() {
25-
private var changes: InventoryChanges? = null
25+
private lateinit var changes: InventoryChanges
2626

2727
override fun SafeContext.onStart() {
28-
changes = InventoryChanges(this)
28+
changes = InventoryChanges(player.currentScreenHandler.slots)
2929
}
3030

3131
fun finish() {
3232
runSafe {
33-
changes?.let {
34-
it.detectChanges()
35-
success(it)
36-
}
33+
changes.detectChanges()
34+
success(changes)
3735
} ?: failure("Failed to finish transaction")
3836
}
39-
4037
}

common/src/main/kotlin/com/lambda/interaction/material/transfer/InventoryTransferTask.kt renamed to common/src/main/kotlin/com/lambda/interaction/material/transfer/SlotTransfer.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ import com.lambda.context.SafeContext
2323
import com.lambda.event.events.TickEvent
2424
import com.lambda.event.listener.SafeListener.Companion.listen
2525
import com.lambda.interaction.material.StackSelection
26-
import com.lambda.interaction.material.transfer.InventoryTransfer.Companion.transfer
26+
import com.lambda.interaction.material.transfer.TransactionExecutor.Companion.transfer
2727
import com.lambda.module.modules.client.TaskFlowModule
2828
import com.lambda.task.Task
2929
import com.lambda.util.extension.containerSlots
3030
import com.lambda.util.extension.inventorySlots
3131
import net.minecraft.screen.ScreenHandler
3232
import net.minecraft.screen.slot.Slot
3333

34-
class InventoryTransferTask @Ta5kBuilder constructor(
34+
class SlotTransfer @Ta5kBuilder constructor(
3535
val screen: ScreenHandler,
3636
private val selection: StackSelection,
3737
val from: List<Slot>,
@@ -41,25 +41,25 @@ class InventoryTransferTask @Ta5kBuilder constructor(
4141
) : Task<Unit>() {
4242
private var selectedFrom = selection.filterSlots(from)
4343
private var selectedTo = to.filter { it.stack.isEmpty } // + to.filter { it.stack.item.block in TaskFlowModule.disposables }
44-
private val screenName = runCatching { screen.type::class.simpleName }.getOrNull() ?: screen::class.simpleName
4544
override val name: String
46-
get() = "Moving $selection from [${selectedFrom.joinToString { "${it.id}" }}] to [${selectedTo.joinToString { "${it.id}" }}] in $screenName"
45+
get() = "Moving $selection from slots [${selectedFrom.joinToString { "${it.id}" }}] to slots [${selectedTo.joinToString { "${it.id}" }}] in ${screen::class.simpleName}"
4746

4847
private var delay = 0
49-
private var changes: InventoryChanges? = null
48+
private lateinit var changes: InventoryChanges
5049

5150
override fun SafeContext.onStart() {
52-
changes = InventoryChanges(this)
51+
changes = InventoryChanges(player.currentScreenHandler.slots)
5352
}
5453

5554
init {
5655
listen<TickEvent.Pre> {
57-
if (player.currentScreenHandler != screen) {
58-
failure("Screen has changed")
56+
val current = player.currentScreenHandler
57+
if (current != screen) {
58+
failure("Screen has changed. Expected ${screen::class.simpleName} (revision ${screen.revision}, got ${current::class.simpleName} (revision ${current.revision})")
5959
return@listen
6060
}
6161

62-
if (changes?.fulfillsSelection(to, selection) == true) {
62+
if (changes.fulfillsSelection(to, selection)) {
6363
if (closeScreen) player.closeHandledScreen()
6464
success()
6565
return@listen
@@ -79,8 +79,8 @@ class InventoryTransferTask @Ta5kBuilder constructor(
7979
transfer {
8080
moveSlot(nextFrom.id, nextTo.id)
8181
}.finally { change ->
82-
changes?.merge(change)
83-
}.execute(this@InventoryTransferTask)
82+
changes merge change
83+
}.execute(this@SlotTransfer)
8484

8585
// if (transfer.fulfillsSelection(selection)) {
8686
// info("Transfer complete")
@@ -99,7 +99,7 @@ class InventoryTransferTask @Ta5kBuilder constructor(
9999
from: List<Slot>,
100100
to: List<Slot>,
101101
closeScreen: Boolean = true
102-
) = InventoryTransferTask(screen, selection, from, to, closeScreen)
102+
) = SlotTransfer(screen, selection, from, to, closeScreen)
103103

104104
@Ta5kBuilder
105105
fun withdraw(screen: ScreenHandler, selection: StackSelection, closeScreen: Boolean = true) =

common/src/main/kotlin/com/lambda/interaction/material/transfer/InventoryTransfer.kt renamed to common/src/main/kotlin/com/lambda/interaction/material/transfer/TransactionExecutor.kt

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,33 @@ import com.lambda.interaction.material.transfer.transaction.*
2424
import com.lambda.task.Task
2525
import net.minecraft.screen.slot.SlotActionType
2626

27-
class InventoryTransfer @Ta5kBuilder constructor() : Task<InventoryChanges>() {
28-
override val name: String get() = "Inventory Transfer"
27+
class TransactionExecutor @Ta5kBuilder constructor(
28+
private val transactions: MutableList<InventoryTransaction> = mutableListOf()
29+
) : Task<InventoryChanges>() {
30+
override val name: String get() = "Execution of ${transactions.size} transactions left"
2931

30-
@DslMarker
31-
annotation class InvTransfer
32-
33-
private var transactions = mutableListOf<InventoryTransaction>()
34-
private var changes: InventoryChanges? = null
32+
private lateinit var changes: InventoryChanges
3533

3634
override fun SafeContext.onStart() {
37-
changes = InventoryChanges(this)
35+
changes = InventoryChanges(player.currentScreenHandler.slots)
3836
}
3937

4038
init {
4139
listen<TickEvent.Pre> {
4240
if (transactions.isEmpty()) {
43-
changes?.let {
44-
success(it)
45-
}
41+
success(changes)
4642
return@listen
4743
}
4844

4945
transactions.removeFirstOrNull()?.finally { change ->
50-
changes?.merge(change)
51-
}?.execute(this@InventoryTransfer)
46+
changes merge change
47+
}?.execute(this@TransactionExecutor)
5248
}
5349
}
5450

51+
@DslMarker
52+
annotation class InvTransfer
53+
5554
@InvTransfer
5655
fun click(slotId: Int, button: Int, actionType: SlotActionType) {
5756
transactions.add(ClickSlotTransaction(slotId, button, actionType))
@@ -132,8 +131,8 @@ class InventoryTransfer @Ta5kBuilder constructor() : Task<InventoryChanges>() {
132131

133132
companion object {
134133
@InvTransfer
135-
fun transfer(block: InventoryTransfer.() -> Unit) =
136-
InventoryTransfer().apply {
134+
fun transfer(block: TransactionExecutor.() -> Unit) =
135+
TransactionExecutor().apply {
137136
block(this)
138137
}
139138
}

0 commit comments

Comments
 (0)