Skip to content

Commit 747d6b8

Browse files
committed
Fix: inventory manager loop state and chest stealer container sync
1 parent f8a17f5 commit 747d6b8

6 files changed

Lines changed: 116 additions & 28 deletions

File tree

src/main/java/net/ccbluex/liquidbounce/features/module/modules/other/ChestStealer.kt

Lines changed: 81 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,51 @@ object ChestStealer : Module("ChestStealer", Category.OTHER, Category.SubCategor
168168
return p
169169
}
170170

171+
private fun resetStealState(clearProgress: Boolean = false) {
172+
chestStealerCurrentSlot = -1
173+
chestStealerLastSlot = -1
174+
175+
if (clearProgress) {
176+
progress = null
177+
}
178+
}
179+
180+
private fun syncOpenChestState(): Boolean {
181+
val player = mc.thePlayer ?: return false
182+
183+
if (mc.currentScreen !is GuiChest) {
184+
return false
185+
}
186+
187+
val container = player.openContainer ?: return false
188+
if (container.windowId == 0) {
189+
return false
190+
}
191+
192+
if (receivedId != container.windowId || stacks.isEmpty() || stacks.size != container.inventorySlots.size) {
193+
receivedId = container.windowId
194+
stacks = container.inventorySlots.map { it.stack }
195+
}
196+
197+
return true
198+
}
199+
200+
private fun canTakeStack(stack: ItemStack): Boolean {
201+
if (hasSpaceInInventory()) {
202+
return true
203+
}
204+
205+
val mergeableCount = mc.thePlayer?.inventory?.mainInventory?.sumOf { otherStack ->
206+
otherStack?.takeIf {
207+
it.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(stack, otherStack)
208+
}?.let { mergeableStack ->
209+
mergeableStack.maxStackSize - mergeableStack.stackSize
210+
} ?: 0
211+
} ?: 0
212+
213+
return mergeableCount > 0
214+
}
215+
171216
private suspend fun shouldOperate(): Boolean {
172217
while (true) {
173218
if (!handleEvents())
@@ -179,6 +224,8 @@ object ChestStealer : Module("ChestStealer", Category.OTHER, Category.SubCategor
179224
if (mc.currentScreen !is GuiChest)
180225
return false
181226

227+
syncOpenChestState()
228+
182229
if (mc.thePlayer?.openContainer?.windowId != receivedId)
183230
return false
184231

@@ -223,6 +270,8 @@ object ChestStealer : Module("ChestStealer", Category.OTHER, Category.SubCategor
223270
if (screen !is GuiChest || !shouldOperate())
224271
return
225272

273+
syncOpenChestState()
274+
226275
// Check if chest isn't a custom gui
227276
if (chestTitle && Blocks.chest.localizedName !in (screen.lowerChestInventory ?: return).name)
228277
return
@@ -238,26 +287,29 @@ object ChestStealer : Module("ChestStealer", Category.OTHER, Category.SubCategor
238287
if (!shouldOperate())
239288
return
240289

241-
if (!hasSpaceInInventory())
242-
return
290+
val itemsToSteal = getItemsToSteal()
243291

244-
var hasTaken = false
292+
if (itemsToSteal.isEmpty()) {
293+
progress = 1f
294+
delay(closeDelay.random().toLong())
245295

246-
val itemsToSteal = getItemsToSteal()
296+
nextTick { SilentHotbar.resetSlot() }
297+
break
298+
}
299+
300+
var hasTaken = false
247301

248302
run scheduler@{
249303
itemsToSteal.forEachIndexed { index, (slot, stack, sortableTo) ->
250304
// Wait for NoMove or cancel click
251305
if (!shouldOperate()) {
252306
nextTick { SilentHotbar.resetSlot() }
253-
chestStealerCurrentSlot = -1
254-
chestStealerLastSlot = -1
307+
resetStealState()
255308
return
256309
}
257310

258-
if (!hasSpaceInInventory()) {
259-
chestStealerCurrentSlot = -1
260-
chestStealerLastSlot = -1
311+
if (!canTakeStack(stack)) {
312+
resetStealState()
261313
return@scheduler
262314
}
263315

@@ -326,13 +378,12 @@ object ChestStealer : Module("ChestStealer", Category.OTHER, Category.SubCategor
326378
awaitTicked()
327379

328380
// Before closing the chest, check all items once more, whether server hadn't cancelled some of the actions.
329-
stacks = thePlayer.openContainer.inventory
381+
stacks = thePlayer.openContainer.inventorySlots.map { it.stack }
330382
}
331383

332384
// Wait before the chest gets closed (if it gets closed out of tick loop it could throw npe)
333385
nextTick {
334-
chestStealerCurrentSlot = -1
335-
chestStealerLastSlot = -1
386+
resetStealState()
336387
thePlayer.closeScreen()
337388
progress = null
338389

@@ -443,6 +494,14 @@ object ChestStealer : Module("ChestStealer", Category.OTHER, Category.SubCategor
443494
return itemsToSteal
444495
}
445496

497+
override fun onDisable() {
498+
receivedId = null
499+
stacks = emptyList()
500+
currentContainerPos = null
501+
SilentHotbar.resetSlot(this)
502+
resetStealState(clearProgress = true)
503+
}
504+
446505
private fun sortBasedOnOptimumPath(itemsToSteal: MutableList<ItemTakeRecord>) {
447506
for (i in itemsToSteal.indices) {
448507
var nextIndex = i
@@ -493,19 +552,22 @@ object ChestStealer : Module("ChestStealer", Category.OTHER, Category.SubCategor
493552
val onPacket = handler<PacketEvent> { event ->
494553
when (val packet = event.packet) {
495554
is S2DPacketOpenWindow -> {
496-
receivedId = null
497-
progress = null
555+
resetStealState(clearProgress = true)
556+
currentContainerPos = null
498557

499-
if (furnace && packet.windowTitle.unformattedText.lowercase().contains("furnace")) {
500-
receivedId = packet.windowId
501-
stacks = emptyList()
558+
receivedId = when {
559+
packet.guiId == "minecraft:chest" || packet.guiId == "minecraft:container" -> packet.windowId
560+
furnace && packet.windowTitle.unformattedText.lowercase().contains("furnace") -> packet.windowId
561+
else -> null
502562
}
563+
stacks = emptyList()
503564
}
504565

505566
is C0DPacketCloseWindow, is S2EPacketCloseWindow -> {
506567
receivedId = null
507-
progress = null
568+
stacks = emptyList()
508569
currentContainerPos = null
570+
resetStealState(clearProgress = true)
509571
}
510572

511573
is S30PacketWindowItems -> {
@@ -516,7 +578,7 @@ object ChestStealer : Module("ChestStealer", Category.OTHER, Category.SubCategor
516578
return@handler
517579

518580
if (receivedId != packetWindowId) {
519-
debug("Chest opened with ${stacks.size} items")
581+
debug("Chest opened with ${packet.itemStacks.size} items")
520582
}
521583

522584
receivedId = packetWindowId

src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/item/MixinItemRenderer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private void renderFireInFirstPerson(float p_color_0_, float p_color_1_, float p
232232
private ItemStack hookSilentHotbar(InventoryPlayer instance) {
233233
SilentHotbarModule module = SilentHotbarModule.INSTANCE;
234234

235-
int slot = SilentHotbar.INSTANCE.renderSlot(module.handleEvents() && module.getKeepItemInHandInFirstPerson());
235+
int slot = SilentHotbar.INSTANCE.renderFirstPersonSlot(module.handleEvents() && module.getKeepItemInHandInFirstPerson());
236236

237237
return instance.getStackInSlot(slot);
238238
}

src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/render/MixinLayerHeldItem.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public class MixinLayerHeldItem {
4949
public void doRenderLayer(EntityLivingBase entity, float p_177141_2_, float p_177141_3_, float partialTicks, float p_177141_5_, float p_177141_6_, float p_177141_7_, float scale) {
5050
SilentHotbarModule module = SilentHotbarModule.INSTANCE;
5151

52-
int slot = SilentHotbar.INSTANCE.renderSlot(module.handleEvents() && module.getKeepItemInHandInThirdPerson());
52+
int slot = SilentHotbar.INSTANCE.renderThirdPersonSlot(module.handleEvents() && module.getKeepItemInHandInThirdPerson());
5353

5454
ItemStack itemstack = entity instanceof EntityPlayerSP ? ((EntityPlayerSP) entity).inventory.getStackInSlot(slot) : entity.getHeldItem();
5555

@@ -104,4 +104,4 @@ public void doRenderLayer(EntityLivingBase entity, float p_177141_2_, float p_17
104104
popMatrix();
105105
}
106106
}
107-
}
107+
}

src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/render/MixinRenderPlayer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ private void setModelVisibilities(AbstractClientPlayer entity) {
4747
} else {
4848
SilentHotbarModule module = SilentHotbarModule.INSTANCE;
4949

50-
int slot = SilentHotbar.INSTANCE.renderSlot(module.handleEvents() && module.getKeepItemInHandInThirdPerson());
50+
int slot = SilentHotbar.INSTANCE.renderThirdPersonSlot(module.handleEvents() && module.getKeepItemInHandInThirdPerson());
5151

5252
ItemStack itemstack = entity instanceof EntityPlayerSP ? entity.inventory.getStackInSlot(slot) : entity.getHeldItem();
5353

src/main/java/net/ccbluex/liquidbounce/utils/inventory/InventoryManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ object InventoryManager : Configurable("InventoryManager"), MinecraftInstance, L
7878
get() = System.currentTimeMillis() - timeSinceClosedInventory >= postInventoryCloseDelayValue.get()
7979

8080
private val managerLoop = loopSequence(dispatcher = Dispatchers.Default, priority = 100) {
81+
hasScheduledInLastLoop = false
82+
8183
/**
8284
* ChestStealer actions
8385
*/

src/main/java/net/ccbluex/liquidbounce/utils/inventory/SilentHotbar.kt

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,22 @@ object SilentHotbar : Listenable, MinecraftInstance {
3838
*/
3939
fun selectSlotSilently(
4040
requester: Any?, slot: Int, ticksUntilReset: Int? = null, immediate: Boolean = false,
41-
render: Boolean = true, resetManually: Boolean = false,
41+
render: Boolean = true, resetManually: Boolean = false, renderHotbar: Boolean = render,
42+
renderFirstPerson: Boolean = render, renderThirdPerson: Boolean = render,
4243
) {
4344
if (originalSlot == null) {
4445
originalSlot = mc.thePlayer?.inventory?.currentItem ?: 0
4546
}
4647

47-
hotbarState = SilentHotbarState(slot, requester, ticksUntilReset, render, resetManually)
48+
hotbarState = SilentHotbarState(
49+
slot,
50+
requester,
51+
ticksUntilReset,
52+
renderHotbar,
53+
renderFirstPerson,
54+
renderThirdPerson,
55+
resetManually
56+
)
4857
ticksSinceLastUpdate = 0
4958

5059
if (immediate) {
@@ -85,14 +94,28 @@ object SilentHotbar : Listenable, MinecraftInstance {
8594
ticksSinceLastUpdate++
8695
}
8796

88-
fun renderSlot(option: Boolean): Int {
97+
fun renderSlot(option: Boolean) = renderHotbarSlot(option)
98+
99+
fun renderHotbarSlot(option: Boolean): Int {
100+
return resolveRenderedSlot(option) { it.renderHotbar }
101+
}
102+
103+
fun renderFirstPersonSlot(option: Boolean): Int {
104+
return resolveRenderedSlot(option) { it.renderFirstPerson }
105+
}
106+
107+
fun renderThirdPersonSlot(option: Boolean): Int {
108+
return resolveRenderedSlot(option) { it.renderThirdPerson }
109+
}
110+
111+
private inline fun resolveRenderedSlot(option: Boolean, shouldRender: (SilentHotbarState) -> Boolean): Int {
89112
val player = mc.thePlayer ?: return 0
90113

91114
val original = player.inventory.currentItem
92115

93116
val state = hotbarState ?: return original
94117

95-
return if (option || state.render) currentSlot else original
118+
return if (option || shouldRender(state)) currentSlot else original
96119
}
97120

98121
private fun shouldReset(slot: Int, other: Int? = originalSlot, keyPressCheck: Boolean = false): Boolean {
@@ -142,5 +165,6 @@ object SilentHotbar : Listenable, MinecraftInstance {
142165

143166
class SilentHotbarState(
144167
val enforcedSlot: Int, var requester: Any?, var resetTicks: Int?,
145-
val render: Boolean, val resetManually: Boolean,
168+
val renderHotbar: Boolean, val renderFirstPerson: Boolean, val renderThirdPerson: Boolean,
169+
val resetManually: Boolean,
146170
)

0 commit comments

Comments
 (0)