Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6e7d52c
added some item components
Chaosgh Aug 24, 2025
88893db
added some item components
Chaosgh Aug 24, 2025
22b5a40
fixed default mismatch
Chaosgh Aug 24, 2025
9ef42b2
refactor ItemComponents Add InteractionContext for parity and added b…
Chaosgh Aug 24, 2025
0add039
Better handeling of invalide namespaces in ItemPDCComponent (for exam…
Chaosgh Aug 24, 2025
c5dd35e
Merge branch 'develop' into develop
Chaosgh Aug 26, 2025
57df20e
Merge branch 'develop' into develop
Chaosgh Aug 27, 2025
feedee3
Small fix in `ItemNameComponent`: `effectiveName()` is only available…
Chaosgh Aug 27, 2025
5356714
Merge remote-tracking branch 'origin/develop' into develop
Chaosgh Aug 27, 2025
dbbb85f
Merge pull request #1 from gabber235/develop
Chaosgh Sep 4, 2025
8bc8515
- Data types were added to 'pdc' and 'CustomModelDataType'.
Chaosgh Sep 4, 2025
99077b6
- Data types were added to 'pdc' and 'CustomModelDataType'.
Chaosgh Sep 4, 2025
8478c5c
small fixes to stay compatible with the typewriter panel
Chaosgh Sep 4, 2025
aa3f821
Merge pull request #2 from Chaosgh/components
Chaosgh Sep 4, 2025
5c88045
- different unsupported message to make it clearer
Chaosgh Sep 5, 2025
9518b06
small cleanups
Chaosgh Sep 5, 2025
a500a66
Merge branch 'develop' into develop
Chaosgh Sep 15, 2025
6e2eef9
small cleanups like gabber told me
Chaosgh Sep 19, 2025
0f61b85
small cleanups like gabber told me
Chaosgh Sep 19, 2025
47d31fc
Merge branch 'develop' into develop
Chaosgh Sep 19, 2025
38192a5
Merge remote-tracking branch 'origin/develop' into develop
Chaosgh Sep 19, 2025
e330496
Merge branch 'develop' into develop
Chaosgh Sep 20, 2025
dc1fef0
Merge branch 'develop' into develop
Chaosgh Sep 26, 2025
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
@@ -1,7 +1,10 @@
package com.typewritermc.engine.paper.utils.item.components

import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.*
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.extension.annotations.Default
import com.typewritermc.core.extension.annotations.InnerMin
import com.typewritermc.core.extension.annotations.Min
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.entry.entries.ConstVar
import com.typewritermc.engine.paper.entry.entries.Var
Expand All @@ -14,7 +17,7 @@ class ItemAmountComponent(
@InnerMin(Min(0))
@Default("1")
val amount: Var<Int> = ConstVar(1),
): ItemComponent {
) : ItemComponent {
override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
item.amount = amount.get(player, interactionContext) ?: 1
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.typewritermc.engine.paper.utils.item.components

import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.entry.entries.ConstVar
import com.typewritermc.engine.paper.entry.entries.Var
import com.typewritermc.engine.paper.entry.entries.get
import com.typewritermc.engine.paper.utils.item.components.customModelDataTypes.CustomModelDataType
import com.typewritermc.engine.paper.utils.item.components.customModelDataTypes.LegacyCustomModelData
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

@AlgebraicTypeInfo("custom_model_data", Colors.GREEN, "fa6-solid:shapes")
class ItemCustomModelDataComponent(
val customModelData: Var<CustomModelDataType> = ConstVar(LegacyCustomModelData(0)),
) : ItemComponent {
override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
customModelData.get(player, interactionContext)?.apply(player, interactionContext, item)
}

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
val modelData = customModelData.get(player, interactionContext) ?: return false
return modelData.matches(player, interactionContext, item)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.typewritermc.engine.paper.utils.item.components

import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.entry.entries.ConstVar
import com.typewritermc.engine.paper.entry.entries.Var
import com.typewritermc.engine.paper.entry.entries.get
import com.typewritermc.engine.paper.utils.Sound
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

@Suppress("UnstableApiUsage")
@AlgebraicTypeInfo("jukebox_playable", Colors.RED, "fa6-solid:music")
class ItemJukeboxPlayableComponent(
val sound: Var<Sound> = ConstVar(Sound.EMPTY)
) : ItemComponent {
override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
item.editMeta { meta ->
val resolvedSound = sound.get(player, interactionContext)
if (resolvedSound == null || resolvedSound == Sound.EMPTY) {
meta.setJukeboxPlayable(null)
return@editMeta
}

val soundKey = resolvedSound.soundId.namespacedKey ?: return@editMeta
val jukeboxComponent = meta.jukeboxPlayable
jukeboxComponent.songKey = soundKey
meta.setJukeboxPlayable(jukeboxComponent)
}
}

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
val expectedSound = sound.get(player, interactionContext)
val actualComponent = item.itemMeta?.jukeboxPlayable

if (expectedSound == null || expectedSound == Sound.EMPTY) {
return actualComponent == null
}

return actualComponent?.songKey == expectedSound.soundId.namespacedKey
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.typewritermc.engine.paper.utils.item.components

import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.entry.entries.ConstVar
import com.typewritermc.engine.paper.entry.entries.Var
import com.typewritermc.engine.paper.entry.entries.get
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

@AlgebraicTypeInfo("item_model", Colors.BLUE, "fa6-solid:layer-group")
class ItemModelComponent(
val modelKey: Var<String> = ConstVar("")
) : ItemComponent {

override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
item.editMeta { meta ->
val raw = modelKey.get(player, interactionContext)?.trim().orEmpty()
if (raw.isEmpty()) {
meta.itemModel = null
return@editMeta
}

val key = NamespacedKey.fromString(raw)
if (key == null) {
meta.itemModel = null
return@editMeta
}

meta.itemModel = key
}
}

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
val expectedRaw = modelKey.get(player, interactionContext)?.trim().orEmpty()
val actual = item.itemMeta?.itemModel

if (expectedRaw.isEmpty()) {
return actual == null
}

val expected = NamespacedKey.fromString(expectedRaw) ?: return actual == null
return actual == expected
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.typewritermc.engine.paper.utils.item.components

import com.github.retrooper.packetevents.manager.server.ServerVersion
import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.extension.annotations.Colored
Expand All @@ -11,6 +12,7 @@ import com.typewritermc.engine.paper.entry.entries.get
import com.typewritermc.engine.paper.extensions.placeholderapi.parsePlaceholders
import com.typewritermc.engine.paper.utils.asMini
import com.typewritermc.engine.paper.utils.plainText
import com.typewritermc.engine.paper.utils.serverVersion
import com.typewritermc.engine.paper.utils.stripped
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
Expand All @@ -30,6 +32,12 @@ class ItemNameComponent(

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
val name = name.get(player) ?: return false
return item.effectiveName().plainText() == name.parsePlaceholders(player).stripped()


return if (serverVersion.isNewerThan(ServerVersion.V_1_21_3)) {
item.effectiveName().plainText() == name.parsePlaceholders(player).stripped()
} else {
item.displayName().plainText() == name.parsePlaceholders(player).stripped()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.typewritermc.engine.paper.utils.item.components

import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.entry.entries.ConstVar
import com.typewritermc.engine.paper.entry.entries.Var
import com.typewritermc.engine.paper.entry.entries.get
import com.typewritermc.engine.paper.utils.item.components.pdcTypes.PdcDataType
import com.typewritermc.engine.paper.utils.item.components.pdcTypes.StringPdcData
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

@AlgebraicTypeInfo("persistent_data_container", Colors.PURPLE, "fa6-solid:database")
class ItemPDCComponent(

val dataKey: Var<String> = ConstVar("typewriter:custom_data"),
val data: Var<PdcDataType> = ConstVar(StringPdcData("")),
) : ItemComponent {

override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
val raw = dataKey.get(player, interactionContext)?.trim().orEmpty()
if (raw.isEmpty()) return

val namespacedKey = NamespacedKey.fromString(raw) ?: return
data.get(player, interactionContext)?.apply(player, interactionContext, item, namespacedKey)
}

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
val raw = dataKey.get(player, interactionContext)?.trim().orEmpty()
if (raw.isEmpty()) return false

val namespacedKey = NamespacedKey.fromString(raw) ?: return false
val pdcData = data.get(player, interactionContext) ?: return false
return pdcData.matches(player, interactionContext, item, namespacedKey)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.typewritermc.engine.paper.utils.item.components

import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.entry.entries.ConstVar
import com.typewritermc.engine.paper.entry.entries.Var
import com.typewritermc.engine.paper.entry.entries.get
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

@AlgebraicTypeInfo("tooltip_style", Colors.CYAN, "fa6-solid:palette")
class ItemTooltipStyleComponent(

val styleKey: Var<String> = ConstVar("minecraft:diamond"),
) : ItemComponent {

override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
item.editMeta { meta ->
val raw = styleKey.get(player, interactionContext)?.trim().orEmpty()
if (raw.isEmpty()) {
meta.tooltipStyle = null
return@editMeta
}

val key = NamespacedKey.fromString(raw)
if (key == null) {
meta.tooltipStyle = null
return@editMeta
}

if (meta.tooltipStyle != key) {
meta.tooltipStyle = key
}
}
}

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
val raw = styleKey.get(player, interactionContext)?.trim().orEmpty()
val actual = item.itemMeta?.tooltipStyle

if (raw.isEmpty()) {
return actual == null
}

val expected = NamespacedKey.fromString(raw) ?: return actual == null
return actual == expected
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.typewritermc.engine.paper.utils.item.components.customModelDataTypes

import com.github.retrooper.packetevents.manager.server.ServerVersion
import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.logger
import com.typewritermc.engine.paper.utils.serverVersion
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

@AlgebraicTypeInfo("boolean_array", Colors.GREEN, "fa6-solid:shapes")
data class BooleansCustomModelData(
val value: List<Boolean> = emptyList()

) : CustomModelDataType {
override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
if (!serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
logger.warning("${this::class.simpleName} is only supported in versions 1.21.4 and above")
return
}
item.editMeta { meta ->
val component = meta.customModelDataComponent
if (component.flags == value) return@editMeta
component.flags = value
meta.setCustomModelDataComponent(component)
}
}

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
if (!serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
logger.warning("${this::class.simpleName} is only supported in versions 1.21.4 and above")
return false
}
val meta = item.itemMeta ?: return false
return meta.customModelDataComponent.flags == value
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.typewritermc.engine.paper.utils.item.components.customModelDataTypes

import com.github.retrooper.packetevents.manager.server.ServerVersion
import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.logger
import com.typewritermc.engine.paper.utils.Color
import com.typewritermc.engine.paper.utils.serverVersion
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

@AlgebraicTypeInfo("color_array", Colors.GREEN, "fa6-solid:shapes")
data class ColorsCustomModelData(
val value: List<Color> = emptyList()
) : CustomModelDataType {
override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
if (!serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
logger.warning("${this::class.simpleName} is only supported in versions 1.21.4 and above")
return
}
item.editMeta { meta ->
val component = meta.customModelDataComponent
val bukkitColors = value.map { it.toBukkitColor() }

if (component.colors == bukkitColors) return@editMeta
component.colors = bukkitColors
meta.setCustomModelDataComponent(component)
}
}

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
if (!serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
logger.warning("${this::class.simpleName} is only supported in versions 1.21.4 and above")
return false
}
val meta = item.itemMeta ?: return false
val bukkitColors = value.map { it.toBukkitColor() }
return meta.customModelDataComponent.colors == bukkitColors
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.typewritermc.engine.paper.utils.item.components.customModelDataTypes

import com.typewritermc.core.interaction.InteractionContext
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

sealed interface CustomModelDataType {
fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack)
fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.typewritermc.engine.paper.utils.item.components.customModelDataTypes

import com.github.retrooper.packetevents.manager.server.ServerVersion
import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.extension.annotations.AlgebraicTypeInfo
import com.typewritermc.core.interaction.InteractionContext
import com.typewritermc.engine.paper.logger
import com.typewritermc.engine.paper.utils.serverVersion
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

@AlgebraicTypeInfo("float_array", Colors.GREEN, "fa6-solid:shapes")
data class FloatsCustomModelData(
val value: List<Float> = emptyList()
) : CustomModelDataType {
override fun apply(player: Player?, interactionContext: InteractionContext?, item: ItemStack) {
if (!serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
logger.warning("${this::class.simpleName} is only supported in versions 1.21.4 and above")
return
}
item.editMeta { meta ->
val component = meta.customModelDataComponent
if (component.floats == value) return@editMeta
component.floats = value
meta.setCustomModelDataComponent(component)
}
}

override fun matches(player: Player?, interactionContext: InteractionContext?, item: ItemStack): Boolean {
if (!serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
logger.warning("${this::class.simpleName} is only supported in versions 1.21.4 and above")
return false
}
val meta = item.itemMeta ?: return false
return meta.customModelDataComponent.floats == value
}
}
Loading