Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated craft trigger to return total items crafted. #153

Merged
merged 1 commit into from
May 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ import org.bukkit.event.inventory.ClickType
import org.bukkit.event.inventory.CraftItemEvent
import org.bukkit.event.inventory.InventoryAction
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.PlayerInventory

object TriggerCraft : Trigger("craft") {

private const val CRAFTING_FAILED = 0

override val parameters = setOf(
TriggerParameter.PLAYER,
TriggerParameter.LOCATION,
Expand All @@ -26,78 +30,93 @@ object TriggerCraft : Trigger("craft") {
if (event.result == Event.Result.DENY) {
return
}

if (event.action == InventoryAction.NOTHING || event.inventory.result == null) {
return
}

val player = event.whoClicked as? Player ?: return
val item = event.recipe.result
val cursor: ItemStack? = event.cursor
var recipeRepetitions = 1
val click = event.click

if (click == ClickType.NUMBER_KEY) {
// Hotbar crafting fails if cursor contains item, or hotbar destination is not empty.
if (cursor != null && cursor.type != Material.AIR) {
recipeRepetitions = 0
} else if (player.inventory.getItem(event.hotbarButton) != null) {
recipeRepetitions = 0
}
val cursor = event.cursor
val recipeRepetitions = when (event.click) {
ClickType.NUMBER_KEY -> handleNumberKeyCompletion(cursor, player, event)
ClickType.DROP, ClickType.CONTROL_DROP -> handleDropCompletion(cursor)
ClickType.SWAP_OFFHAND -> handleSwapOffhandCompletion(player)
ClickType.SHIFT_RIGHT, ClickType.SHIFT_LEFT -> handleShiftClickCompletion(event, item)
else -> 1
}
if (recipeRepetitions == CRAFTING_FAILED) {
return
}
val totalItemsCrafted = item.amount * recipeRepetitions
this.dispatch(
player.toDispatcher(),
TriggerData(
player = player,
item = item,
value = totalItemsCrafted.toDouble()
)
)
}

} else if (click == ClickType.DROP || click == ClickType.CONTROL_DROP) {
// Drop crafting with Q fails if cursor is full
if (cursor != null && cursor.type != Material.AIR) {
recipeRepetitions = 0
}
private fun handleShiftClickCompletion(event: CraftItemEvent, result: ItemStack): Int {
val inventoryContent = event.view.topInventory.storageContents.toList().filterNot { item ->
item == null || item.type.isAir
}.drop(1)

} else if (click == ClickType.SWAP_OFFHAND) {
// Can't craft into off-hand if off-hand is full.
if (player.inventory.itemInOffHand.type != Material.AIR) {
recipeRepetitions = 0
val playerInventory = event.view.bottomInventory as PlayerInventory
val contents = playerInventory.storageContents.toList()
val totalPossibleSlotsForItems = contents.sumOf { item ->
val slotIsBlank = item == null || item.type.isAir
if (slotIsBlank) {
return@sumOf result.maxStackSize
}

} else if (click == ClickType.SHIFT_RIGHT || click == ClickType.SHIFT_LEFT) {
// This relies on the fact we can only craft as many as our smallest material stack.
recipeRepetitions = Integer.MAX_VALUE
for (istack: ItemStack? in event.inventory.matrix) {
if (istack != null && istack.amount < recipeRepetitions) {
recipeRepetitions = istack.amount
}
val itemIsResult = item!!.isSimilar(result)
if (itemIsResult) {
return@sumOf result.maxStackSize - item.amount
}
0
}

if (recipeRepetitions == Integer.MAX_VALUE) {
recipeRepetitions = 0
} else if (item.amount > 0) {
// Determine how many of this stack we can fit in our inventory...
var capacity = 0
if (totalPossibleSlotsForItems == 0) {
return CRAFTING_FAILED
}

for (istack: ItemStack? in event.view.bottomInventory.storageContents) {
if (istack == null) {
capacity += item.maxStackSize
} else if (istack.isSimilar(item)) {
capacity += (item.maxStackSize - istack.amount).coerceAtLeast(0)
}
}
val totalCraftableItems = inventoryContent.minOf { it!!.amount }
return if (totalCraftableItems <= totalPossibleSlotsForItems) {
totalCraftableItems
} else {
totalPossibleSlotsForItems / result.amount
}
}

// If we can't fit everything, round up to the next full recipe amount.
if (capacity < recipeRepetitions * item.amount) {
recipeRepetitions = ((capacity + item.amount - 1) / item.amount)
}
}
private fun handleSwapOffhandCompletion(player: Player): Int {
val playerOffhandIsNotEmpty = player.inventory.itemInOffHand.type != Material.AIR
// Can't craft into off-hand if off-hand is full.
return if (playerOffhandIsNotEmpty) {
CRAFTING_FAILED
} else {
1
}
}

if (recipeRepetitions == 0) {
return
private fun handleDropCompletion(cursor: ItemStack?): Int {
// Drop crafting with Q fails if cursor is full
val curseIsNotEmpty = cursor != null && cursor.type != Material.AIR
return if (curseIsNotEmpty) {
CRAFTING_FAILED
} else {
1
}
}

this.dispatch(
player.toDispatcher(),
TriggerData(
player = player,
item = item,
value = recipeRepetitions.toDouble()
)
)
private fun handleNumberKeyCompletion(cursor: ItemStack?, player: Player, event: CraftItemEvent): Int {
val cursorIsNotEmpty = cursor != null && cursor.type != Material.AIR
val playerHasItemInSlot = player.inventory.getItem(event.hotbarButton) != null
// Hotbar crafting fails if cursor contains item, or hotbar destination is not empty.
return if (cursorIsNotEmpty || playerHasItemInSlot) {
CRAFTING_FAILED
} else {
1
}
}
}

}