mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 16:16:17 +02:00
add shift click for unit repair
This commit is contained in:
parent
4195add655
commit
d9c7a9376b
1 changed files with 116 additions and 50 deletions
|
|
@ -9,6 +9,7 @@ import io.delilaheve.util.ItemUtil.isEnchantedBook
|
||||||
import io.delilaheve.util.ItemUtil.repairFrom
|
import io.delilaheve.util.ItemUtil.repairFrom
|
||||||
import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe
|
import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe
|
||||||
import io.delilaheve.util.ItemUtil.unitRepair
|
import io.delilaheve.util.ItemUtil.unitRepair
|
||||||
|
import org.bukkit.GameMode
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.event.Event
|
import org.bukkit.event.Event
|
||||||
|
|
@ -25,6 +26,7 @@ import xyz.alexcrea.group.ConflictType
|
||||||
import xyz.alexcrea.util.UnitRepairUtil.getRepair
|
import xyz.alexcrea.util.UnitRepairUtil.getRepair
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener for anvil events
|
* Listener for anvil events
|
||||||
*/
|
*/
|
||||||
|
|
@ -35,6 +37,9 @@ class AnvilEventListener : Listener {
|
||||||
private const val ANVIL_INPUT_LEFT = 0
|
private const val ANVIL_INPUT_LEFT = 0
|
||||||
private const val ANVIL_INPUT_RIGHT = 1
|
private const val ANVIL_INPUT_RIGHT = 1
|
||||||
private const val ANVIL_OUTPUT_SLOT = 2
|
private const val ANVIL_OUTPUT_SLOT = 2
|
||||||
|
// static slot container
|
||||||
|
private val NO_SLOT = SlotContainer(SlotType.NO_SLOT,0)
|
||||||
|
private val CURSOR_SLOT = SlotContainer(SlotType.CURSOR,0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -170,75 +175,127 @@ class AnvilEventListener : Listener {
|
||||||
if(canMerge){
|
if(canMerge){
|
||||||
event.result = Event.Result.ALLOW
|
event.result = Event.Result.ALLOW
|
||||||
}else if(unitRepairResult != null){
|
}else if(unitRepairResult != null){
|
||||||
val resultCopy = leftItem.clone()
|
onUnitRepairExtract(leftItem, rightItem, output,
|
||||||
val resultAmount = resultCopy.unitRepair(
|
unitRepairResult, event, player, inventory)
|
||||||
rightItem.amount, unitRepairResult)
|
|
||||||
|
|
||||||
// To avoid vanilla, we cancel the event for unit repair
|
|
||||||
event.result = Event.Result.DENY
|
|
||||||
event.isCancelled = true
|
|
||||||
// And we give the item manually
|
|
||||||
// But first we check if we should give the item
|
|
||||||
if(player.itemOnCursor.type != Material.AIR) return
|
|
||||||
if(inventory.repairCost > player.level) return
|
|
||||||
|
|
||||||
// Get repairCost
|
|
||||||
var repairCost = 0
|
|
||||||
leftItem.itemMeta?.let { leftMeta ->
|
|
||||||
val leftName = leftMeta.displayName
|
|
||||||
output.itemMeta?.let {
|
|
||||||
if(!leftName.contentEquals(it.displayName)){
|
|
||||||
repairCost+= ConfigOptions.itemRenameCost
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repairCost+= calculatePenalty(leftItem,null,resultCopy)
|
|
||||||
repairCost+= resultAmount*ConfigOptions.unitRepairCost
|
|
||||||
|
|
||||||
if((inventory.maximumRepairCost < repairCost)
|
|
||||||
|| (player.level < repairCost)) return
|
|
||||||
|
|
||||||
// We remove what should be removed
|
|
||||||
inventory.setItem(ANVIL_INPUT_LEFT,null)
|
|
||||||
rightItem.amount-= resultAmount
|
|
||||||
inventory.setItem(ANVIL_INPUT_RIGHT,rightItem)
|
|
||||||
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
|
||||||
|
|
||||||
UnsafeEnchants.log("repair cost: $repairCost")
|
|
||||||
player.level-= repairCost
|
|
||||||
|
|
||||||
// Finally, we add the item to the player
|
|
||||||
player.setItemOnCursor(output)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onUnitRepairExtract(leftItem: ItemStack,
|
||||||
|
rightItem: ItemStack,
|
||||||
|
output: ItemStack,
|
||||||
|
unitRepairResult: Double,
|
||||||
|
event: InventoryClickEvent,
|
||||||
|
player: Player,
|
||||||
|
inventory: AnvilInventory){
|
||||||
|
val resultCopy = leftItem.clone()
|
||||||
|
val resultAmount = resultCopy.unitRepair(
|
||||||
|
rightItem.amount, unitRepairResult)
|
||||||
|
|
||||||
|
// To avoid vanilla, we cancel the event for unit repair
|
||||||
|
event.result = Event.Result.DENY
|
||||||
|
event.isCancelled = true
|
||||||
|
// And we give the item manually
|
||||||
|
// But first we check if we should give the item
|
||||||
|
val slotDestination = getActionSlot(event,player)
|
||||||
|
if(slotDestination.type == SlotType.NO_SLOT) return
|
||||||
|
if(inventory.repairCost > player.level) return
|
||||||
|
|
||||||
|
// Get repairCost
|
||||||
|
var repairCost = 0
|
||||||
|
leftItem.itemMeta?.let { leftMeta ->
|
||||||
|
val leftName = leftMeta.displayName
|
||||||
|
output.itemMeta?.let {
|
||||||
|
if(!leftName.contentEquals(it.displayName)){
|
||||||
|
repairCost+= ConfigOptions.itemRenameCost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repairCost+= calculatePenalty(leftItem,null,resultCopy)
|
||||||
|
repairCost+= resultAmount*ConfigOptions.unitRepairCost
|
||||||
|
|
||||||
|
val ignoreXpCost = player.gameMode == GameMode.CREATIVE
|
||||||
|
if((!ignoreXpCost) && ((inventory.maximumRepairCost < repairCost)
|
||||||
|
|| (player.level < repairCost))) return
|
||||||
|
|
||||||
|
// We remove what should be removed
|
||||||
|
inventory.setItem(ANVIL_INPUT_LEFT,null)
|
||||||
|
rightItem.amount-= resultAmount
|
||||||
|
inventory.setItem(ANVIL_INPUT_RIGHT,rightItem)
|
||||||
|
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
||||||
|
|
||||||
|
if(!ignoreXpCost){
|
||||||
|
player.level-= repairCost
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we add the item to the player
|
||||||
|
if(slotDestination.type == SlotType.CURSOR){
|
||||||
|
player.setItemOnCursor(output)
|
||||||
|
}else{// We assume SlotType == SlotType.INVENTORY
|
||||||
|
player.inventory.setItem(slotDestination.slot,output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the destination slot or "NO_SLOT" slot container if there is no slot available
|
||||||
|
*/
|
||||||
|
private fun getActionSlot(event: InventoryClickEvent, player: Player): SlotContainer{
|
||||||
|
if(event.isShiftClick){
|
||||||
|
val inventory = player.inventory
|
||||||
|
val firstEmpty = inventory.firstEmpty()
|
||||||
|
if(firstEmpty == -1){
|
||||||
|
return NO_SLOT
|
||||||
|
}
|
||||||
|
//check hotbare full
|
||||||
|
var slotIndex = 8
|
||||||
|
while(slotIndex >= 0 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)){
|
||||||
|
slotIndex--
|
||||||
|
}
|
||||||
|
if(slotIndex >= 0){
|
||||||
|
return SlotContainer(SlotType.INVENTORY,slotIndex)
|
||||||
|
}
|
||||||
|
slotIndex = 35 //4*9 - 1 (max of player inventory)
|
||||||
|
while(slotIndex >= 9 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)){
|
||||||
|
slotIndex--
|
||||||
|
}
|
||||||
|
if(slotIndex < 9){
|
||||||
|
return NO_SLOT
|
||||||
|
}
|
||||||
|
return SlotContainer(SlotType.INVENTORY,slotIndex)
|
||||||
|
}else{
|
||||||
|
if(player.itemOnCursor.type != Material.AIR){
|
||||||
|
return NO_SLOT
|
||||||
|
}
|
||||||
|
return CURSOR_SLOT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to calculate work penalty of anvil work
|
* Function to calculate work penalty of anvil work
|
||||||
* Also change result work penalty
|
* Also change result work penalty
|
||||||
*/
|
*/
|
||||||
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int{
|
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int{
|
||||||
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
|
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
|
||||||
// Calculate work penality
|
// Calculate work penalty
|
||||||
val leftPenality = (left.itemMeta as? Repairable)?.repairCost ?: 0
|
val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0
|
||||||
val rightPenality =
|
val rightPenalty =
|
||||||
if(right == null){ 0 }
|
if(right == null){ 0 }
|
||||||
else{ (right.itemMeta as? Repairable)?.repairCost ?: 0 }
|
else{ (right.itemMeta as? Repairable)?.repairCost ?: 0 }
|
||||||
|
|
||||||
// Try to set work penality for the result item
|
// Try to set work penalty for the result item
|
||||||
result.itemMeta?.let {
|
result.itemMeta?.let {
|
||||||
(it as? Repairable)?.repairCost = leftPenality*2+1
|
(it as? Repairable)?.repairCost = leftPenalty*2+1
|
||||||
result.itemMeta = it
|
result.itemMeta = it
|
||||||
}
|
}
|
||||||
|
|
||||||
UnsafeEnchants.log("Calculated penality: " +
|
UnsafeEnchants.log("Calculated penalty: " +
|
||||||
"leftPenality: $leftPenality, " +
|
"leftPenalty: $leftPenalty, " +
|
||||||
"rightPenality: $rightPenality, " +
|
"rightPenalty: $rightPenalty, " +
|
||||||
"result penality: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}")
|
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}")
|
||||||
|
|
||||||
return leftPenality + rightPenality
|
return leftPenalty + rightPenalty
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -307,3 +364,12 @@ class AnvilEventListener : Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class SlotContainer(val type: SlotType, val slot: Int)
|
||||||
|
private enum class SlotType{
|
||||||
|
CURSOR,
|
||||||
|
INVENTORY,
|
||||||
|
NO_SLOT
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue