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

feat: Add configurable maximum durability feature via config key "Item-Durability" #16

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
11 changes: 11 additions & 0 deletions src/main/java/com/cjcrafter/armormechanics/ArmorMechanics.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package com.cjcrafter.armormechanics

import com.cjcrafter.armormechanics.commands.Command
import com.cjcrafter.armormechanics.durability.registerDurabilityPlaceholders
import com.cjcrafter.armormechanics.listeners.*
import listeners.ArmorEquipListener
import me.cjcrafter.auto.UpdateChecker
import me.cjcrafter.auto.UpdateInfo
import me.deecaad.core.MechanicsCore
import me.deecaad.core.events.QueueSerializerEvent
import me.deecaad.core.file.BukkitConfig
import me.deecaad.core.file.SerializeData
import me.deecaad.core.file.SerializerException
import me.deecaad.core.file.TaskChain
import me.deecaad.core.lib.adventure.text.serializer.legacy.LegacyComponentSerializer
import me.deecaad.core.utils.Debugger
import me.deecaad.core.utils.FileUtil
import me.deecaad.core.utils.LogLevel
import me.deecaad.core.utils.ReflectionUtil
import me.deecaad.core.utils.StringUtil
import org.bstats.bukkit.Metrics
import org.bstats.charts.SimplePie
import org.bukkit.Bukkit
Expand Down Expand Up @@ -51,6 +55,7 @@ class ArmorMechanics : JavaPlugin() {
server.pluginManager.disablePlugin(this)
return
}
registerDurabilityPlaceholders()
}

override fun onEnable() {
Expand All @@ -62,6 +67,7 @@ class ArmorMechanics : JavaPlugin() {
pm.registerEvents(ArmorUpdateListener(), this)
pm.registerEvents(BlockPlaceListener(), this)
pm.registerEvents(DamageMechanicListener(), this)
pm.registerEvents(DurabilityListener(), this)
pm.registerEvents(ImmunePotionCanceller(), this)
pm.registerEvents(PreventRemoveListener(), this)

Expand Down Expand Up @@ -100,6 +106,9 @@ class ArmorMechanics : JavaPlugin() {
})
.thenRunSync(Runnable {
reloadConfig()
// Reload durability prefix and format
CJCrafter marked this conversation as resolved.
Show resolved Hide resolved
DURABILITY_PREFIX = LegacyComponentSerializer.legacySection().serialize(MechanicsCore.getPlugin().message.deserialize(StringUtil.colorAdventure(config.getString("Durability_Prefix"))!!))
DURABILITY_FORMAT = StringUtil.colorAdventure(config.getString("Durability_Format"))!!

// Clear old data
effects.clear()
Expand Down Expand Up @@ -202,5 +211,7 @@ class ArmorMechanics : JavaPlugin() {

companion object {
lateinit var INSTANCE: ArmorMechanics
lateinit var DURABILITY_PREFIX: String
lateinit var DURABILITY_FORMAT: String
}
}
30 changes: 28 additions & 2 deletions src/main/java/com/cjcrafter/armormechanics/ArmorSerializer.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.cjcrafter.armormechanics

import me.deecaad.core.compatibility.CompatibilityAPI
import com.cjcrafter.armormechanics.durability.DurabilityManager.setDurability
import com.cjcrafter.armormechanics.durability.DurabilityManager.setMaxDurability
import me.deecaad.core.file.SerializeData
import me.deecaad.core.file.SerializerException
import me.deecaad.core.file.serializers.ItemSerializer
import me.deecaad.core.utils.AdventureUtil
import me.deecaad.core.lib.adventure.text.serializer.legacy.LegacyComponentSerializer
import me.deecaad.core.placeholder.PlaceholderData
import me.deecaad.core.placeholder.PlaceholderMessage
import me.deecaad.weaponmechanics.utils.CustomTag
import org.bukkit.inventory.ItemStack
import javax.annotation.Nonnull
Expand All @@ -20,6 +23,29 @@ class ArmorSerializer : ItemSerializer() {
"Material was not a valid armor type",
SerializerException.forValue(item.type)
)


if (data.has("Item_Durability")) {
val durability = data.of("Item_Durability").getInt(0)
if (durability > 0) {
setDurability(item, durability)
setMaxDurability(item, durability)
val meta = item.itemMeta
val lore = ArrayList<String>()
if (meta!!.hasLore()) {
lore.addAll(meta.lore!!)
}
val placeholderMessage = PlaceholderMessage(ArmorMechanics.DURABILITY_FORMAT)
val component = placeholderMessage.replaceAndDeserialize(PlaceholderData.of(null, item, null, null))
val legacy = LegacyComponentSerializer.legacySection().serialize(component)
lore.add(ArmorMechanics.DURABILITY_PREFIX + legacy)
meta.lore = lore
item.itemMeta = meta
}
}



val title = data.key
val effect = data.of("Bonus_Effects").serialize(BonusEffect::class.java)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.cjcrafter.armormechanics.durability

import com.cjcrafter.armormechanics.ArmorMechanics
import me.deecaad.core.compatibility.CompatibilityAPI
import me.deecaad.core.lib.adventure.text.serializer.legacy.LegacyComponentSerializer
import me.deecaad.core.placeholder.PlaceholderData
import me.deecaad.core.placeholder.PlaceholderMessage
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.Damageable
import org.bukkit.inventory.meta.ItemMeta

object DurabilityManager {
fun changeDurability(item: ItemStack, change: Int) {
if (getDurability(item) == -1) {
return
}
var durability = getDurability(item)
val maxDurability = getMaxDurability(item)
durability = Math.min(durability + change, maxDurability)
setDurability(item, durability)
val damageable = item.itemMeta
if (damageable !is Damageable) {
return
}

if (durability > 0) {
damageable.damage = item.type.maxDurability - (durability * item.type.maxDurability) / maxDurability
if ((damageable as ItemMeta).hasLore()) {
val lore: ArrayList<String> = ArrayList((damageable as ItemMeta).lore!!)
val loreClone = lore.toMutableList()
val index = loreClone.indexOfFirst { it.startsWith(ArmorMechanics.DURABILITY_PREFIX) }
val placeholderMessage = PlaceholderMessage(ArmorMechanics.DURABILITY_FORMAT)
val component = placeholderMessage.replaceAndDeserialize(PlaceholderData.of(null, item, null, null))
val legacy = LegacyComponentSerializer.legacySection().serialize(component)
loreClone[index] = ArmorMechanics.DURABILITY_PREFIX + legacy
(damageable as ItemMeta).lore = loreClone
} else {
(damageable as ItemMeta).lore = listOf(
ArmorMechanics.DURABILITY_PREFIX + LegacyComponentSerializer.legacySection().serialize(
PlaceholderMessage(
ArmorMechanics.DURABILITY_FORMAT
).replaceAndDeserialize(PlaceholderData.of(null, item, null, null))
)
)
}
} else {
damageable.damage = item.type.maxDurability.toInt()
item.amount = 0
}
item.itemMeta = damageable
}

fun getMaxDurability(item: ItemStack): Int {
return if (CompatibilityAPI.getNBTCompatibility().hasInt(item, "ArmorMechanics", "armor-durability-max")) {
CompatibilityAPI.getNBTCompatibility().getInt(item, "ArmorMechanics", "armor-durability-max")
} else -1
}

fun getDurability(item: ItemStack): Int {
return if (CompatibilityAPI.getNBTCompatibility().hasInt(item, "ArmorMechanics", "armor-durability")) {
CompatibilityAPI.getNBTCompatibility().getInt(item, "ArmorMechanics", "armor-durability")
} else -1
}

fun setMaxDurability(item: ItemStack, value: Int) {
CompatibilityAPI.getNBTCompatibility().setInt(item, "ArmorMechanics", "armor-durability-max", value)
}

fun setDurability(item: ItemStack, value: Int) {
CompatibilityAPI.getNBTCompatibility().setInt(item, "ArmorMechanics", "armor-durability", value)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.cjcrafter.armormechanics.durability

import me.deecaad.core.placeholder.NumericPlaceholderHandler
import me.deecaad.core.placeholder.PlaceholderData
import me.deecaad.core.placeholder.PlaceholderHandler

fun registerDurabilityPlaceholders() {
PlaceholderHandler.REGISTRY.add(DurabilityPlaceholderHandler())
PlaceholderHandler.REGISTRY.add(MaxDurabilityPlaceholderHandler())
}
class DurabilityPlaceholderHandler : NumericPlaceholderHandler("durability_current") {
override fun requestValue(p0: PlaceholderData): Number? {
return DurabilityManager.getDurability(p0.item()!!)
}
}

class MaxDurabilityPlaceholderHandler : NumericPlaceholderHandler("durability_max") {
override fun requestValue(p0: PlaceholderData): Number? {
return DurabilityManager.getMaxDurability(p0.item()!!)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.cjcrafter.armormechanics.listeners

import com.cjcrafter.armormechanics.durability.DurabilityManager.changeDurability
import com.cjcrafter.armormechanics.durability.DurabilityManager.getDurability
import me.deecaad.core.compatibility.CompatibilityAPI
import org.bukkit.Material
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.event.inventory.PrepareItemCraftEvent
import org.bukkit.event.player.PlayerItemDamageEvent
import org.bukkit.event.player.PlayerItemMendEvent
import org.bukkit.inventory.ItemStack

class DurabilityListener : Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
fun onItemDamaged(event: PlayerItemDamageEvent) {
changeDurability(event.item, -event.damage)
}

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
fun onItemMend(event: PlayerItemMendEvent) {
changeDurability(event.item, event.repairAmount)
}

@EventHandler
fun onRepairAnvil(event: PrepareAnvilEvent) {
val (names, totalDurability, result) = namesTotalDurabilityAndResult(event.inventory.contents) ?: return // Returns if ArmorMechanics is not involved
if (names.size != 1) {
event.result = null // We can set result to null because we are sure about ArmorMechanics is involved
return
}
changeDurability(result, totalDurability - getDurability(result))
event.result = result
}

@EventHandler
fun onRepairCraft(event: PrepareItemCraftEvent) {
if (!event.isRepair) return
val (names, totalDurability, result) = namesTotalDurabilityAndResult(event.inventory.matrix) ?: return // Returns if ArmorMechanics is not involved
if (names.size != 1) {
event.inventory.result = null // We can set result to null because we are sure about ArmorMechanics is involved
return
}
changeDurability(result, totalDurability - getDurability(result))
event.inventory.result = result
}

private fun namesTotalDurabilityAndResult(items: Array<ItemStack?>): Triple<Set<String>, Int, ItemStack>? {
var totalDurability = 0
val names = mutableSetOf<String>()
var resultItem: ItemStack? = null
for (item in items) {
if (item == null || item.type == Material.AIR) continue
val durability = getDurability(item)
if (durability == -1) return null // An unknown item is involved
if (resultItem == null) resultItem = item.clone()
totalDurability += durability
val name = CompatibilityAPI.getNBTCompatibility().getString(item, "ArmorMechanics", "armor-title") ?: return null // Returns if ArmorMechanics is not involved
names += name
}
if (resultItem == null) return null // None of the items have custom durability
return Triple(names, totalDurability, resultItem)
}
}
7 changes: 6 additions & 1 deletion src/main/resources/ArmorMechanics/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ Delete_Old_Armor: false
# Whenever you update your armor, I *HIGHLY SUGGEST* you run a /restart on your
# server instead of just a /am reload. This will force all players to relog and
# their armor will be updated.
Update_Armor: true
Update_Armor: true

# These settings are for setting maximum durability for armor.
# You can use Item_Durability attribute on armors to use this feature.
Durability_Prefix: '<gray>Durability: '
Durability_Format: "<green><durability_current><white>/<green><durability_max>"