
walkmc.extensions.Items.kt Maven / Gradle / Ivy
package walkmc.extensions
import net.minecraft.server.*
import org.bukkit.*
import org.bukkit.Material
import org.bukkit.craftbukkit.inventory.*
import org.bukkit.enchantments.Enchantment
import org.bukkit.inventory.*
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.*
import org.bukkit.material.*
import walkmc.*
import walkmc.block.*
import walkmc.extensions.collections.*
import walkmc.extensions.strings.*
import walkmc.placeholder.*
import walkmc.serializer.tag.impl.*
typealias MetaTransformer = ItemMeta.() -> Unit
/**
* Gets the minecraft item handler of this item stack.
*/
val ItemStack.handler: MinecraftItem get() = CraftItemStack.asNMSMirror(this) ?: CraftItemStack.asNMSCopy(this)
/**
* Copies and changes this item stack to the specified [block] function.
*/
inline fun ItemStack.copy(block: ItemStack.() -> Unit) = clone().apply(block)
/**
* Changes this item stack material type by the specified [material].
*/
fun ItemStack.changeToMaterial(material: Materials): ItemStack {
this.material = material
return this
}
/**
* Changes this item stack to the specified head representation of [url].
*/
fun ItemStack.changeToHead(url: String): ItemStack {
material = Materials.PLAYER_SKULL
data = SkullItem(url)
applyMetaTo {
this.url = url
}
return this
}
/**
* Changes this item stack to the specified head representation of the owner [name].
*/
fun ItemStack.changeToHeadOwner(name: String): ItemStack {
material = Materials.PLAYER_SKULL
applyMetaTo {
this.owner = name
}
return this
}
/**
* Changes this item stack to the specified head representation of the owner [player].
*/
fun ItemStack.changeToHeadOwner(player: OfflinePlayer): ItemStack {
material = Materials.PLAYER_SKULL
applyMetaTo {
this.owner = player.name
}
return this
}
/**
* Copies and changes this item stack material type by the specified [material].
*/
fun ItemStack.copyToMaterial(material: Materials) = copy {
this.material = material
}
/**
* Copies and changes this item stack to the specified head representation of [url].
*/
fun ItemStack.copyToHead(url: String) = copy {
material = Materials.PLAYER_SKULL
data = SkullItem(url)
applyMetaTo {
this.url = url
}
}
/**
* Copies and changes this item stack to the specified head representation of the owner [name].
*/
fun ItemStack.copyToHeadOwner(name: String) = copy {
material = Materials.PLAYER_SKULL
applyMetaTo {
owner = name
}
}
/**
* Copies and changes this item stack to the specified head representation of the owner [player].
*/
fun ItemStack.copyToHeadOwner(player: OfflinePlayer) = copy {
material = Materials.PLAYER_SKULL
applyMetaTo {
owner = player.name
}
}
/**
* Transforms this item stack meta by the specified transform.
*/
inline fun ItemStack.applyMeta(transform: MetaTransformer) = apply {
val meta = itemMeta
meta.apply(transform)
itemMeta = meta
}
/**
* Transforms this item stack meta by the specified transform.
*/
inline fun ItemStack.applyMetaTo(transform: T.() -> Unit) = apply {
val meta: T = itemMeta.cast()
meta.apply(transform)
itemMeta = meta
}
/**
* Returns the display name of this item stack.
*/
var ItemStack.name: String
get() = itemMeta.displayName ?: type.name
set(value) {
applyMeta {
displayName = value
}
}
/**
* Sets the specified name to this item stack.
*/
fun ItemStack.name(name: String) = applyMeta {
displayName = name
}
/**
* Returns the lore of this item stack.
*/
var ItemStack.lore: MutableList
get() = itemMeta.lore ?: newMutableList()
set(value) {
applyMeta {
lore = value
}
}
/**
* Inserts the specified lore to this item stack.
*/
fun ItemStack.lore(lines: Iterable) = applyMeta {
lore = lines.toList()
}
/**
* Inserts the specified lore to this item stack.
*/
fun ItemStack.lore(vararg lines: String) = applyMeta {
lore = lines.toList()
}
/**
* Inserts the specified multiline lore to this item stack. Like:
* ```
* lore("""
* §7First line
* §7Second line
* """)
* ```
*/
fun ItemStack.lore(lines: String) = applyMeta {
lore = lines.lines()
}
/**
* Returns the flags of this item stack.
*/
var ItemStack.flags: MutableSet
get() = itemMeta.itemFlags ?: mutableSetOf()
set(value) {
applyMeta {
addItemFlags(*value.toTypedArray())
}
}
/**
* Inserts the specified flags to this item stack.
*/
fun ItemStack.flags(vararg flags: ItemFlag) = applyMeta {
addItemFlags(*flags)
}
/**
* Inserts the specified enchantments to this item stack.
*/
fun ItemStack.enchantments(vararg enchantments: Pair) = apply {
addUnsafeEnchantments(enchantments.toMap())
}
/**
* Sets the specified amount of this item stack.
*/
fun ItemStack.amount(amount: Int) = apply {
this.amount = amount
}
/**
* Sets the specified durability of this item stack.
*/
fun ItemStack.durability(durability: Int) = apply {
this.durability = durability.toShort()
}
/**
* Sets the specified material data of this item stack.
*/
fun ItemStack.data(materialData: MaterialData) = apply {
this.data = materialData
}
/**
* Sets the specified material data of this item stack.
*/
fun ItemStack.data(type: Material, data: Number) = apply {
this.data = newData(type, data)
}
/**
* Sets the specified type of this item stack.
*/
fun ItemStack.type(type: Material) = apply {
this.type = type
}
/**
* Converts this item to a [MinecraftItem].
*/
fun ItemStack.asMinecraftItem(): MinecraftItem = CraftItemStack.asNMSCopy(this)
/**
* Returns if this item stack is similar to [other] item stack
*/
infix fun ItemStack.similar(other: ItemStack?) = isSimilar(other)
/**
* Applies the necessary data tag used to verify if a item stack
* is part from a custom block item.
*/
inline fun ItemStack.setCustomBlockPart() = applyTag {
setClass("BlockClass", T::class.java)
}
/**
* Returns if this item stack is a part from a custom block item.
*/
val ItemStack.isCustomBlockPart: Boolean
get() = tag.hasKey("BlockClass")
/**
* Gets the custom block part class of this item stack, or nulls
* if this item is not a part from a custom block.
*/
val ItemStack.customBlockPart: Class?
get() = try {
tag.getClass("BlockClass")
} catch (ex: Exception) {
null
}
/**
* Applies the given [block] to the root tag of this item stack.
*/
inline fun ItemStack.applyTag(block: NBTTagCompound.() -> Unit) = apply {
val handler = handler
handler.tag = handler.tag.apply(block)
itemMeta = CraftItemStack.getItemMeta(handler)
}
/**
* Gets the root tag of this item stack.
*
* ## NOTE:
*
* This MUST only used to configure certains aspects of persistent data or item data that's
* is not available in [storage], like [isUnbreakable] and others.
*
* For convenience, prefers using [storage] almost in all cases.
*/
var ItemStack.tag: NBTTagCompound
get() = handler.tag ?: NBTTagCompound()
set(value) {
val handler = handler
handler.tag = value
itemMeta = CraftItemStack.getItemMeta(handler)
}
/**
* Applies the given [block] to the storage tag of this item stack.
*/
inline fun ItemStack.applyStorage(block: CompoundTag.() -> Unit) = apply {
applyTag {
val tag = getTagGroup("Storage").tag
setTagGroup("Storage", tag.apply(block))
}
}
/**
* Gets the tag storage of this item stack.
*
* ## NOTE:
*
* This MUST be used in almost all cases when configuring persistent data or custom data of this item.
* Certain things like, setting this item to [isUnbreakable] must be configured with [tag].
*
* For convenience, prefers using this almost in all cases.
*/
var ItemStack.storage: CompoundTag
get() = tag.getTagGroup("Storage").tag
set(value) {
applyTag {
this.setTagGroup("Storage", value)
}
}
/**
* Returns if this item stack is unbreakable or not.
*/
var ItemStack.isUnbreakable: Boolean
get() = tag.getBoolean("Unbreakable")
set(value) {
applyTag {
setBoolean("Unbreakable", value)
}
}
/**
* Process this item stack with the specified placeholder and value
* by the model name and lore.
*/
fun ItemStack.process(model: ItemStack, placeholder: Placeholder, value: T) = apply {
name(placeholder.process(model.name, value))
lore(placeholder.process(model.lore, value))
}
/**
* Process this item stack with the specified placeholder and value
* by the model name and lore.
*/
fun ItemStack.process(model: ItemStack, value: Pair) = apply {
name(model.name.process(value))
lore(model.lore.process(value))
}
/**
* Process this item stack with the specified placeholder and value
* by the model name and lore.
*/
fun ItemStack.process(model: ItemStack, vararg value: Pair) = apply {
name(model.name.process(*value))
lore(model.lore.process(*value))
}
/**
* Process this item stack with the specified placeholder and value
* by the model name and lore.
*/
fun ItemStack.process(model: ItemStack, value: Map) = apply {
name(model.name.process(value))
lore(model.lore.process(value))
}
/**
* Process this item stack with the specified placeholder and value.
*/
fun ItemStack.process(placeholder: Placeholder, value: T) = apply {
name(placeholder.process(name, value))
lore(placeholder.process(lore, value))
}
/**
* Process only specified placeholder in this item stack.
*/
fun ItemStack.process(value: Pair) = apply {
name(name.process(value))
lore(lore.process(value))
}
/**
* Process all specifieds placeholders in this item stack.
*/
fun ItemStack.process(vararg values: Pair) = apply {
name(name.process(*values))
lore(lore.process(*values))
}
/**
* Process all specifieds placeholders in this item stack.
*/
fun ItemStack.process(values: Map) = apply {
name(name.process(values))
lore(lore.process(values))
}
/**
* Process this item stack with the specified placeholder and value
* by the model name and lore and returns a copy of them.
*/
fun ItemStack.processCopy(model: ItemStack, placeholder: Placeholder, value: T): ItemStack =
clone().process(model, placeholder, value)
/**
* Process this item stack with the specified placeholder and value
* by the model name and lore and returns a copy of them.
*/
fun ItemStack.processCopy(model: ItemStack, value: Pair) =
clone().process(model, value)
/**
* Process this item stack with the specified placeholder and value
* by the model name and lore and returns a copy of them.
*/
fun ItemStack.processCopy(model: ItemStack, vararg value: Pair): ItemStack =
clone().process(model, *value)
/**
* Process this item stack with the specified placeholder and value
* by the model name and lore and returns a copy of them.
*/
fun ItemStack.processCopy(model: ItemStack, value: Map): ItemStack =
clone().process(model, value)
/**
* Process this item stack with the specified placeholder and value and returns a copy of them.
*/
fun ItemStack.processCopy(placeholder: Placeholder, value: T): ItemStack =
clone().process(placeholder, value)
/**
* Process only specified placeholder in this item stack and returns a copy of them.
*/
fun ItemStack.processCopy(value: Pair): ItemStack = clone().process(value)
/**
* Process all specifieds placeholders in this item stack and returns a copy of them.
*/
fun ItemStack.processCopy(vararg values: Pair): ItemStack = clone().process(*values)
/**
* Process all specifieds placeholders in this item stack and returns a copy of them.
*/
fun ItemStack.processCopy(values: Map): ItemStack = clone().process(values)
/**
* Creates a new empty item stack.
*/
fun emptyItem(): ItemStack = ItemStack(Material.AIR, 0)
/**
* Builds a item stack by the specified [block].
*/
inline fun buildItem(block: ItemStack.() -> Unit): ItemStack = ItemStack(Materials.AIR, 1).apply(block)
/**
* Creates a new item stack by the specified model and amount.
*/
fun newItem(model: ItemStack, amount: Int = 1): ItemStack = model.amount(amount)
/**
* Creates a new item stack by the specified model and name.
*/
fun newItem(model: ItemStack, name: String, amount: Int = 1): ItemStack =
model.name(name).amount(amount)
/**
* Creates a new item stack by the specified model and lore.
*/
fun newItem(model: ItemStack, lore: List, amount: Int = 1): ItemStack =
model.lore(lore).amount(amount)
/**
* Creates a new item stack by the specified model, name and lore.
*/
fun newItem(model: ItemStack, name: String, lore: List, amount: Int = 1): ItemStack =
model.name(name).lore(lore).amount(amount)
/**
* Creates a new item stack by the specified material.
*/
fun newItem(material: Materials, amount: Int = 1): ItemStack = material.toItem(amount)
/**
* Creates a new item stack by the specified material data.
*/
fun newItem(material: MaterialData, amount: Int = 1): ItemStack = material.toItemStack(amount)
/**
* Creates a new item stack by the specified material and name.
*/
fun newItem(material: Materials, name: String, amount: Int = 1): ItemStack =
newItem(material, amount).name(name)
/**
* Creates a new item stack by the specified material and lore.
*/
fun newItem(material: Materials, lore: List, amount: Int = 1): ItemStack =
newItem(material, amount).lore(lore)
/**
* Creates a new item stack by the specified material, name and lore.
*/
fun newItem(material: Materials, name: String, lore: List, amount: Int = 1): ItemStack =
newItem(material, amount).name(name).lore(lore)
/**
* Creates a new item stack by the specified material data and name.
*/
fun newItem(material: MaterialData, name: String, amount: Int = 1): ItemStack =
material.toItemStack(amount).name(name)
/**
* Creates a new item stack by the specified material data and lore.
*/
fun newItem(material: MaterialData, lore: List, amount: Int = 1): ItemStack =
material.toItemStack(amount).lore(lore)
/**
* Creates a new item stack by the specified material data, name and lore.
*/
fun newItem(material: MaterialData, name: String, lore: List, amount: Int = 1): ItemStack =
material.toItemStack(amount).name(name).lore(lore)
/**
* Creates a new item stack head by the specified player id.
*/
fun newHeadOwner(owner: String, amount: Int = 1): ItemStack = createHeadOwner(owner).amount(amount)
/**
* Creates a new item stack head by the specified player id and lore.
*/
fun newHeadOwner(owner: String, lore: List, amount: Int = 1): ItemStack =
createHeadOwner(owner).amount(amount).lore(lore)
/**
* Creates a new item stack head by the specified player id and name.
*/
fun newHeadOwner(owner: String, name: String, amount: Int = 1): ItemStack =
createHeadOwner(owner).amount(amount).name(name)
/**
* Creates a new item stack head by the specified player id, name and lore.
*/
fun newHeadOwner(owner: String, name: String, lore: List, amount: Int = 1): ItemStack =
createHeadOwner(owner).amount(amount).name(name).lore(lore)
/**
* Creates a new item stack head by the specified url head.
*/
fun newHead(base: String, amount: Int = 1): ItemStack = createHead(base).amount(amount)
/**
* Creates a new item stack head by the specified url head and lore.
*/
fun newHead(base: String, lore: List, amount: Int = 1): ItemStack =
createHead(base).amount(amount).lore(lore)
/**
* Creates a new item stack head by the specified url head and name.
*/
fun newHead(base: String, name: String, amount: Int = 1): ItemStack =
createHead(base).amount(amount).name(name)
/**
* Creates a new item stack head by the specified url head, name and lore.
*/
fun newHead(base: String, name: String, lore: List, amount: Int = 1): ItemStack =
createHead(base).amount(amount).name(name).lore(lore)
/**
* Internal API to create empty heads with the specified base64.
*/
internal fun createHead(base: String): ItemStack = newItem(Materials.PLAYER_SKULL).apply {
data = SkullItem(base)
applyMetaTo {
url = base
}
}
/**
* Internal API to create empty heads with the specified player name as owner.
*/
internal fun createHeadOwner(name: String): ItemStack = newItem(Materials.PLAYER_SKULL).apply {
applyMetaTo {
owner = name
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy