Skip to content

Commit

Permalink
Finishing touches
Browse files Browse the repository at this point in the history
Improved coroutine modules
* Now they only work if gamemode is survival or adventure.
* Stealer now drops garbage items that block useful items from chest from being taken, when the chest is full as well...
* Stealer now checks whether armor slot isn't occupied, when equipping while stealing.
* Removed forgotten debug message.

Improved ItemStack?.isEmpty()
* Used kotlin contract to make stack smart-cast to not null ItemStack.

Improved AutoPot, AutoSoup
* No longer closes visually open inventory when simulating inventory closing after each click.

A bit of refactoring and other minor stuff.
  • Loading branch information
CzechHek committed Oct 10, 2023
1 parent cdcb597 commit 01e9e3c
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 91 deletions.
Expand Up @@ -32,23 +32,7 @@ class GiveCommand : Command("give", "item", "i", "get") {
return
}

var emptySlot = -1

for (i in 36..44) {
if (thePlayer.inventoryContainer.getSlot(i).stack == null) {
emptySlot = i
break
}
}

if (emptySlot == -1) {
for (i in 9..44) {
if (thePlayer.inventoryContainer.getSlot(i).stack == null) {
emptySlot = i
break
}
}
}
val emptySlot = thePlayer.inventory.firstEmptyStack

if (emptySlot != -1) {
sendPacket(C10PacketCreativeInventoryAction(emptySlot, itemStack))
Expand Down
Expand Up @@ -156,7 +156,7 @@ open class Module @JvmOverloads constructor(
TickedActions.schedule(id, instance, allowDuplicates, action)

internal fun scheduleClick(slot: Int, button: Int, mode: Int, allowDuplicates: Boolean = false, windowId: Int = mc.thePlayer.openContainer.windowId, action: ((ItemStack?) -> Unit)? = null) =
TickedActions.schedule(slot, instance, allowDuplicates) {
schedule(slot, allowDuplicates) {
val newStack = mc.playerController.windowClick(windowId, slot, button, mode, mc.thePlayer)
action?.invoke(newStack)
}
Expand All @@ -170,9 +170,14 @@ open class Module @JvmOverloads constructor(
internal fun scheduleAndSuspend(vararg actions: () -> Unit) =
actions.forEach {
this += it
waitUntil { isEmpty() }
waitUntil(::isEmpty)
}

internal fun scheduleAndSuspend(id: Int = -1, allowDuplicates: Boolean = true, action: () -> Unit) {
schedule(id, allowDuplicates, action)
waitUntil(::isEmpty)
}

internal fun isScheduled(id: Int) = TickedActions.isScheduled(id, instance)

// Checks if id click is scheduled: if (id in TickScheduler)
Expand Down
Expand Up @@ -19,7 +19,7 @@ import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay
import net.ccbluex.liquidbounce.value.BoolValue
import net.ccbluex.liquidbounce.value.IntegerValue
import net.minecraft.client.gui.inventory.GuiInventory
import net.minecraft.item.ItemArmor
import net.minecraft.entity.EntityLiving.getArmorPosition
import net.minecraft.item.ItemStack
import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement
import net.minecraft.network.play.client.C09PacketHeldItemChange
Expand Down Expand Up @@ -59,15 +59,15 @@ object CoroutineArmorer: Module("CoroutineArmorer", ModuleCategory.BETA) {
val onlyWhenNoScreen by BoolValue("OnlyWhenNoScreen", false) { hotbar }

suspend fun equipFromHotbar() {
if (!shouldExecute(onlyHotbar = true))
if (!shouldOperate(onlyHotbar = true))
return

val thePlayer = mc.thePlayer ?: return

var hasClickedHotbar = false

for (hotbarIndex in 0..8) {
if (!shouldExecute(onlyHotbar = true))
if (!shouldOperate(onlyHotbar = true))
return

// Don't right-click to equip items while inventory is open when value onlyWhenNoScreen is enabled
Expand All @@ -76,17 +76,17 @@ object CoroutineArmorer: Module("CoroutineArmorer", ModuleCategory.BETA) {

val stacks = thePlayer.openContainer.inventory

val bestArmorSet = getBestArmorSet(stacks) ?: return

val stack = stacks.getOrNull(hotbarIndex + 36) ?: continue

val bestArmorSet = getBestArmorSet(stacks) ?: return

if (stack !in bestArmorSet)
continue

val equippedStack = stacks[(stack.item as ItemArmor).armorType + 5]
val armorPosition = getArmorPosition(stack) - 1

// If armor slot isn't occupied, right click to equip
if (equippedStack == null) {
if (thePlayer.getCurrentArmor(armorPosition) == null) {
hasClickedHotbar = true

val equippingAction = {
Expand All @@ -96,12 +96,9 @@ object CoroutineArmorer: Module("CoroutineArmorer", ModuleCategory.BETA) {
C08PacketPlayerBlockPlacement(stack)
)

// TODO: Still clicks repetitively, probably because openContainer gets updated after some ticks?
// Instantly update inventory on client-side to prevent repetitive clicking because of ping
/*
thePlayer.inventory.armorInventory[abs((stack.item as ItemArmor).armorType - 3)] = stack
thePlayer.inventory.armorInventory[armorPosition] = stack
thePlayer.inventory.mainInventory[hotbarIndex] = null
*/
}

if (delayedSlotSwitch)
Expand All @@ -113,21 +110,24 @@ object CoroutineArmorer: Module("CoroutineArmorer", ModuleCategory.BETA) {
}
}

waitUntil { TickScheduler.isEmpty() }
// Not really needed to bypass
delay(randomDelay(minDelay, maxDelay).toLong())

waitUntil(TickScheduler::isEmpty)

// Sync selected slot
// Sync selected slot next tick
if (hasClickedHotbar)
TickScheduler += { serverSlot = thePlayer.inventory.currentItem }
}

suspend fun equipFromInventory() {
if (!shouldExecute())
if (!shouldOperate())
return

val thePlayer = mc.thePlayer ?: return

for (armorType in 0..3) {
if (!shouldExecute())
if (!shouldOperate())
return

val stacks = thePlayer.openContainer.inventory
Expand Down Expand Up @@ -183,7 +183,7 @@ object CoroutineArmorer: Module("CoroutineArmorer", ModuleCategory.BETA) {
}

// Wait till all scheduled clicks were sent
waitUntil { TickScheduler.isEmpty() }
waitUntil(TickScheduler::isEmpty)
}

fun equipFromHotbarInChest(hotbarIndex: Int?, stack: ItemStack) {
Expand All @@ -197,11 +197,14 @@ object CoroutineArmorer: Module("CoroutineArmorer", ModuleCategory.BETA) {
)
}

private suspend fun shouldExecute(onlyHotbar: Boolean = false): Boolean {
private suspend fun shouldOperate(onlyHotbar: Boolean = false): Boolean {
while (true) {
if (!state)
return false

if (mc.playerController?.currentGameType?.isSurvivalOrAdventure != true)
return false

// It is impossible to equip armor when a container is open; only try to equip by right-clicking from hotbar (if onlyWhenNoScreen is disabled)
if (mc.thePlayer?.openContainer?.windowId != 0 && (!onlyHotbar || onlyWhenNoScreen))
return false
Expand Down
Expand Up @@ -81,14 +81,14 @@ object CoroutineCleaner: Module("CoroutineCleaner", ModuleCategory.BETA) {

// Compact multiple small stacks into one to free up inventory space
suspend fun compactStacks() {
if (!mergeStacks || !shouldExecute())
if (!mergeStacks || !shouldOperate())
return

val thePlayer = mc.thePlayer ?: return

// Loop multiple times until no clicks were scheduled
while (true) {
if (!shouldExecute()) return
if (!shouldOperate()) return

val stacks = thePlayer.openContainer.inventory

Expand Down Expand Up @@ -118,7 +118,7 @@ object CoroutineCleaner: Module("CoroutineCleaner", ModuleCategory.BETA) {
var hasMerged = false

for (index in indicesToDoubleClick) {
if (!shouldExecute()) return
if (!shouldOperate()) return

if (index in TickScheduler) continue

Expand All @@ -138,13 +138,13 @@ object CoroutineCleaner: Module("CoroutineCleaner", ModuleCategory.BETA) {

// This part isn't fully instant because of the complex vanilla merging behaviour, stack size changes and so on
// Waits a tick to see how the stacks got merged
waitUntil { TickScheduler.isEmpty() }
waitUntil(TickScheduler::isEmpty)
}
}

// Sort hotbar (with useful items without even dropping bad items first)
suspend fun sortHotbar() {
if (!sort || !shouldExecute()) return
if (!sort || !shouldOperate()) return

val thePlayer = mc.thePlayer ?: return

Expand All @@ -153,7 +153,7 @@ object CoroutineCleaner: Module("CoroutineCleaner", ModuleCategory.BETA) {
val isRightType = SORTING_TARGETS[value.get()] ?: continue

// Stop if player violates invopen or nomove checks
if (!shouldExecute()) return
if (!shouldOperate()) return

val stacks = thePlayer.openContainer.inventory

Expand Down Expand Up @@ -184,18 +184,18 @@ object CoroutineCleaner: Module("CoroutineCleaner", ModuleCategory.BETA) {
}
}

waitUntil { TickScheduler.isEmpty() }
waitUntil(TickScheduler::isEmpty)
}

// Drop bad items to free up inventory space
suspend fun dropGarbage() {
if (!drop || !shouldExecute()) return
if (!drop || !shouldOperate()) return

val thePlayer = mc.thePlayer ?: return

for (index in thePlayer.openContainer.inventorySlots.indices.shuffled(randomSlot)) {
// Stop if player violates invopen or nomove checks
if (!shouldExecute()) return
if (!shouldOperate()) return

if (index in TickScheduler)
continue
Expand All @@ -211,14 +211,17 @@ object CoroutineCleaner: Module("CoroutineCleaner", ModuleCategory.BETA) {
click(index, 1, 4)
}

waitUntil { TickScheduler.isEmpty() }
waitUntil(TickScheduler::isEmpty)
}

private suspend fun shouldExecute(): Boolean {
private suspend fun shouldOperate(): Boolean {
while (true) {
if (!state)
return false

if (mc.playerController?.currentGameType?.isSurvivalOrAdventure != true)
return false

if (mc.thePlayer?.openContainer?.windowId != 0)
return false

Expand Down

0 comments on commit 01e9e3c

Please sign in to comment.