Skip to content
This repository was archived by the owner on Apr 23, 2025. It is now read-only.

Commit f9896de

Browse files
committed
feat(item-builder): add new ItemBuilder
1 parent 2a16e09 commit f9896de

File tree

10 files changed

+268
-12
lines changed

10 files changed

+268
-12
lines changed

build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ plugins {
1212
}
1313

1414
apply(plugin = "maven-publish")
15-
val versionVar = "0.5.83"
15+
val versionVar = "0.5.84"
1616
val groupIdVar = "com.undefined"
1717
val artifactIdVar = "api"
1818

@@ -79,6 +79,7 @@ allprojects {
7979
implementation("net.kyori:adventure-platform-bukkit:4.3.3")
8080
implementation("net.kyori:adventure-text-minimessage:4.17.0")
8181
implementation("net.kyori:adventure-text-serializer-plain:4.17.0")
82+
implementation("net.kyori:adventure-text-serializer-legacy:4.17.0")
8283
implementation("org.json:json:20231013")
8384
implementation("com.googlecode.json-simple:json-simple:1.1.1")
8485
}

common/src/main/java/com/undefined/api/builders/ItemBuilder.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ import org.bukkit.inventory.meta.SkullMeta
1111
import java.util.*
1212
import kotlin.collections.HashMap
1313

14+
@Deprecated("Outdated ItemBuilder, use the new one at com.undefined.api.utils.item.ItemBuilder.", ReplaceWith("ItemBuilder", "com.undefined.api.utils.item.ItemBuilder"))
1415
/**
1516
* Represents a builder for creating ItemStack objects.
1617
*
1718
* The ItemBuilder class provides methods to conveniently set various properties of an ItemStack object,
1819
* such as display name, lore, amount, custom model data, and localized name.
20+
*
21+
* @see com.undefined.api.utils.item.ItemBuilder
1922
*/
2023
class ItemBuilder(private var itemStack: ItemStack) {
2124

@@ -35,15 +38,14 @@ class ItemBuilder(private var itemStack: ItemStack) {
3538
*
3639
* @param material The material of the item.
3740
*/
38-
constructor(material: Material): this(ItemStack(material))
41+
constructor(material: Material) : this(ItemStack(material))
3942

4043
/**
4144
* Creates a new instance of the class using a base64 string representation of an ItemStack.
4245
*
4346
* @param base64String The base64 string representation of an ItemStack.
4447
*/
45-
constructor(base64String: String): this(base64String.asItemStack())
46-
48+
constructor(base64String: String) : this(base64String.asItemStack())
4749

4850
/**
4951
* Sets the name of the ItemStack.

common/src/main/java/com/undefined/api/extension/string/StringExtension.kt

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import net.md_5.bungee.api.ChatColor
66
import java.util.regex.Matcher
77
import java.util.regex.Pattern
88

9-
private val miniMessage = MiniMessage.miniMessage()
10-
119
/**
1210
* Converts the given string to small text.
1311
*
@@ -48,7 +46,21 @@ fun String.toSmallText(): String {
4846
*
4947
* @return The converted Component.
5048
*/
51-
fun String.toComponent(): Component = miniMessage.deserialize(this)
49+
fun String.toComponent(): Component = MiniMessage.miniMessage().deserialize(this)
50+
51+
/**
52+
* Converts the given string to a Component.
53+
*
54+
* @return The converted Component.
55+
*/
56+
fun String.component(): Component = Component.text(this)
57+
58+
/**
59+
* Converts the given string to a Component using the MiniMessage deserialization.
60+
*
61+
* @return The converted Component.
62+
*/
63+
fun String.miniMessage(): Component = MiniMessage.miniMessage().deserialize(this)
5264

5365
/**
5466
* Map of replacement values for color formatting. This map is used to replace color placeholders in strings with their corresponding ChatColor values.
@@ -129,5 +141,3 @@ fun String.translateColor(): String {
129141

130142
return string
131143
}
132-
133-

common/src/main/java/com/undefined/api/menu/Panes.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.undefined.api.menu
22

3+
import com.undefined.api.utils.item.ItemBuilder
34
import org.bukkit.Material
45

56
/**
@@ -13,7 +14,7 @@ object Panes {
1314
* @param type the type of material to use for the pane
1415
* @return the created pane
1516
*/
16-
private fun pane(type: Material) = com.undefined.api.builders.ItemBuilder(type).setName(" ").build()
17+
private fun pane(type: Material) = ItemBuilder(type).setPlainName(" ").build()
1718

1819
/**
1920
* Represents a clear glass pane.

common/src/main/java/com/undefined/api/scoreboard/UndefinedScoreboard.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import org.bukkit.scoreboard.Team
3232
*/
3333

3434
@Deprecated("Old and outdated")
35-
class UndefinedScoreboard(private val title: String, private val scoreboard: Scoreboard) {
35+
class UndefinedScoreboard(private val title: String, private val scoreboard: Scoreboard) {
3636

3737
/**
3838
* Creates a new object of type "Scoreboard" with the given title.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.undefined.api.utils
2+
3+
import net.kyori.adventure.text.Component
4+
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
5+
6+
/**
7+
* Convert component into a string that uses the legacy format.
8+
*
9+
* @return A string in legacy format.
10+
*/
11+
fun Component.legacyString(): String = LegacyComponentSerializer.legacy('§').serialize(this)
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
package com.undefined.api.utils.item
2+
3+
import com.undefined.api.extension.getNMSVersion
4+
import com.undefined.api.extension.string.component
5+
import com.undefined.api.extension.string.miniMessage
6+
import com.undefined.api.utils.legacyString
7+
import net.kyori.adventure.text.Component
8+
import org.bukkit.Bukkit
9+
import org.bukkit.Material
10+
import org.bukkit.NamespacedKey
11+
import org.bukkit.attribute.Attribute
12+
import org.bukkit.attribute.AttributeModifier
13+
import org.bukkit.enchantments.Enchantment
14+
import org.bukkit.inventory.ItemFlag
15+
import org.bukkit.inventory.ItemStack
16+
import org.bukkit.inventory.meta.SkullMeta
17+
import org.bukkit.persistence.PersistentDataType
18+
import java.util.*
19+
import kotlin.collections.HashMap
20+
21+
/**
22+
* Represents a builder for creating ItemStack objects.
23+
*/
24+
class ItemBuilder(private val material: Material) {
25+
26+
private var name: Component? = null
27+
private var lore: MutableList<Component> = mutableListOf()
28+
private var amount: Int = 1
29+
private var customModelData: Int = 0
30+
private var persistentDataContainers: HashMap<NamespacedKey, UndefinedPersistentDataContainer<*, *>> = hashMapOf()
31+
private var enchantments: HashMap<Enchantment, Int> = HashMap()
32+
private var unsafeEnchantments: HashMap<Enchantment, Int> = HashMap()
33+
private var unbreakable: Boolean = false
34+
private var skullOwner: UUID? = null
35+
private var skullTexture: String? = null
36+
private var flags: MutableList<ItemFlag> = mutableListOf()
37+
private var attributeModifiers: HashMap<Attribute, AttributeModifier> = hashMapOf()
38+
39+
fun setName(name: Component): ItemBuilder {
40+
this.name = name
41+
return this
42+
}
43+
44+
fun setName(name: String): ItemBuilder {
45+
this.name = name.miniMessage()
46+
return this
47+
}
48+
49+
fun setPlainName(name: String): ItemBuilder {
50+
this.name = name.component()
51+
return this
52+
}
53+
54+
fun setLore(vararg lore: Component): ItemBuilder {
55+
this.lore = lore.toMutableList()
56+
return this
57+
}
58+
59+
fun setLore(lore: List<String>): ItemBuilder {
60+
this.lore = lore.map { it.miniMessage() }.toMutableList()
61+
return this
62+
}
63+
64+
fun addLore(vararg lore: Component): ItemBuilder {
65+
this.lore.addAll(lore.toList())
66+
return this
67+
}
68+
69+
fun addLore(vararg lore: String): ItemBuilder {
70+
this.lore.addAll(lore.map { it.miniMessage() }.toList())
71+
return this
72+
}
73+
74+
fun addPlainLore(vararg lore: String): ItemBuilder {
75+
this.lore.addAll(lore.map { it.component() }.toList())
76+
return this
77+
}
78+
79+
fun setAmount(amount: Int): ItemBuilder {
80+
this.amount = amount
81+
return this
82+
}
83+
84+
fun addAmount(amount: Int): ItemBuilder {
85+
this.amount += amount
86+
return this
87+
}
88+
89+
fun setCustomModelData(customModelData: Int): ItemBuilder {
90+
this.customModelData = customModelData
91+
return this
92+
}
93+
94+
fun <P, C : Any> addPersistentDataType(key: NamespacedKey, persistentDataType: PersistentDataType<P, C>, value: C): ItemBuilder {
95+
this.persistentDataContainers[key] = UndefinedPersistentDataContainer(persistentDataType, value)
96+
return this
97+
}
98+
99+
fun addEnchantment(enchantment: Enchantment, level: Int = 1): ItemBuilder {
100+
this.enchantments[enchantment] = level
101+
return this
102+
}
103+
104+
fun setEnchantments(enchantments: HashMap<Enchantment, Int>): ItemBuilder {
105+
this.enchantments = enchantments
106+
return this
107+
}
108+
109+
fun addUnsafeEnchantment(enchantment: Enchantment, level: Int = 1): ItemBuilder {
110+
this.unsafeEnchantments[enchantment] = level
111+
return this
112+
}
113+
114+
fun setUnsafeEnchantments(enchantments: HashMap<Enchantment, Int>): ItemBuilder {
115+
this.unsafeEnchantments = enchantments
116+
return this
117+
}
118+
119+
fun setUnbreakable(unbreakable: Boolean): ItemBuilder {
120+
this.unbreakable = unbreakable
121+
return this
122+
}
123+
124+
fun setSkullOwner(skullOwner: UUID): ItemBuilder {
125+
this.skullOwner = skullOwner
126+
return this
127+
}
128+
129+
fun setSkullTexture(skullTexture: String): ItemBuilder {
130+
this.skullTexture = skullTexture
131+
return this
132+
}
133+
134+
fun addFlag(flag: ItemFlag): ItemBuilder {
135+
this.flags.add(flag)
136+
return this
137+
}
138+
139+
fun addFlags(vararg flag: ItemFlag): ItemBuilder {
140+
this.flags.addAll(flag)
141+
return this
142+
}
143+
144+
fun addFlags(flag: List<ItemFlag>): ItemBuilder {
145+
this.flags.addAll(flag)
146+
return this
147+
}
148+
149+
fun setFlags(flags: List<ItemFlag>): ItemBuilder {
150+
this.flags = flags.toMutableList()
151+
return this
152+
}
153+
154+
fun addAttributeModifier(attribute: Attribute, modifier: AttributeModifier): ItemBuilder {
155+
this.attributeModifiers[attribute] = modifier
156+
return this
157+
}
158+
159+
fun addAttributeModifiers(attributeModifiers: HashMap<Attribute, AttributeModifier>): ItemBuilder {
160+
attributeModifiers.forEach { attribute, modifier -> this.attributeModifiers[attribute] = modifier }
161+
return this
162+
}
163+
164+
fun setAttributeModifiers(attributeModifiers: HashMap<Attribute, AttributeModifier>): ItemBuilder {
165+
this.attributeModifiers = attributeModifiers
166+
return this
167+
}
168+
169+
fun build(): ItemStack {
170+
val item = ItemStack(material)
171+
item.addEnchantments(enchantments)
172+
item.addUnsafeEnchantments(unsafeEnchantments)
173+
item.amount = this.amount
174+
175+
var meta = item.itemMeta ?: return item
176+
177+
meta.setDisplayName(this.name?.legacyString())
178+
meta.lore = this.lore.map { it.legacyString() }
179+
meta.setCustomModelData(this.customModelData)
180+
this.persistentDataContainers.forEach { key, container ->
181+
meta.persistentDataContainer[key, container.type as PersistentDataType<Any, Any>] = container.value
182+
}
183+
meta.isUnbreakable = this.unbreakable
184+
if (meta is SkullMeta) {
185+
this.skullOwner?.let { (meta as SkullMeta).setOwningPlayer(Bukkit.getOfflinePlayer(it)) }
186+
187+
this.skullTexture?.let { texture ->
188+
val versionHandler = hashMapOf(
189+
"1.20.4" to com.undefined.api.nms.v1_20_4.extensions.ItemUtil::setSkullTexture,
190+
"1.20.6" to com.undefined.api.nms.v1_20_6.extensions.ItemUtil::setSkullTexture,
191+
"1.21" to com.undefined.api.nms.v1_21.extensions.ItemUtil::setSkullTexture
192+
)
193+
194+
versionHandler[getNMSVersion()]?.invoke(meta as SkullMeta, texture)?.let { meta = it }
195+
}
196+
}
197+
meta.addItemFlags(*this.flags.toTypedArray())
198+
this.attributeModifiers.forEach { attribute, modifier -> meta.addAttributeModifier(attribute, modifier) }
199+
200+
item.itemMeta = meta
201+
return item
202+
}
203+
204+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.undefined.api.utils.item
2+
3+
import org.bukkit.persistence.PersistentDataType
4+
5+
data class UndefinedPersistentDataContainer<P, C : Any>(val type: PersistentDataType<P, C>, val value: C)

server/src/main/java/com/undefined/api/Main.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@ package com.undefined.api
33
import com.undefined.api.command.UndefinedCommand
44
import com.undefined.api.extension.sendActionBar
55
import com.undefined.api.scheduler.TimeUnit
6+
import com.undefined.api.utils.item.ItemBuilder
67
import net.kyori.adventure.text.Component
8+
import org.bukkit.Material
9+
import org.bukkit.NamespacedKey
10+
import org.bukkit.attribute.Attribute
11+
import org.bukkit.attribute.AttributeModifier
12+
import org.bukkit.enchantments.Enchantment
13+
import org.bukkit.inventory.ItemFlag
14+
import org.bukkit.persistence.PersistentDataType
715
import org.bukkit.plugin.java.JavaPlugin
816

917
class Main : JavaPlugin() {
@@ -21,6 +29,20 @@ class Main : JavaPlugin() {
2129
.addIncorrectMessage("hi")
2230
.addExecutePlayer {
2331
sendActionBar(Component.text("hi!"), 1, TimeUnit.SECONDS)
32+
val item = ItemBuilder(Material.DIAMOND_SWORD)
33+
.setName("<reset><red>Test!")
34+
.addLore(Component.text("test"))
35+
.addAmount(2)
36+
.setCustomModelData(2)
37+
.addPersistentDataType(NamespacedKey(this@Main, "test"), PersistentDataType.BOOLEAN, true)
38+
.addEnchantment(Enchantment.DAMAGE_ALL, 2)
39+
.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 7)
40+
.setUnbreakable(true)
41+
.setSkullOwner(player!!.uniqueId)
42+
.addFlag(ItemFlag.HIDE_ATTRIBUTES)
43+
.addAttributeModifier(Attribute.GENERIC_MAX_HEALTH, AttributeModifier("generic.max_health", 100.0, AttributeModifier.Operation.ADD_NUMBER))
44+
.build()
45+
player!!.inventory.addItem(item)
2446
return@addExecutePlayer true
2547
}
2648
}

v1_20_4/src/main/java/com/undefined/api/nms/v1_20_4/entity/entityClasses/display/NMSBlockDisplayEntity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import org.bukkit.block.data.BlockData
99
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData
1010
import org.bukkit.entity.EntityType
1111

12-
class NMSBlockDisplayEntity(block: BlockData): NMSDisplayEntity(EntityType.BLOCK_DISPLAY), NMSBlockDisplayEntity {
12+
class NMSBlockDisplayEntity(block: BlockData) : NMSDisplayEntity(EntityType.BLOCK_DISPLAY), NMSBlockDisplayEntity {
1313

1414
override var blockData: BlockData = block
1515
set(value) {

0 commit comments

Comments
 (0)