Skip to content
Merged
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
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
javaVersion=25
mcVersion=1.21.11
group=dev.slne.surf
version=1.21.11-2.63.0
version=1.21.11-2.63.1
relocationPrefix=dev.slne.surf.surfapi.libs
snapshot=false
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,67 @@ import dev.slne.surf.surfapi.bukkit.api.packet.listener.listener.PacketListener
import dev.slne.surf.surfapi.bukkit.api.packet.listener.listener.annotation.ClientboundListener
import dev.slne.surf.surfapi.bukkit.api.packet.listener.listener.annotation.ServerboundListener
import dev.slne.surf.surfapi.bukkit.api.packet.lore.SurfBukkitPacketLoreHandler
import dev.slne.surf.surfapi.bukkit.api.util.key
import dev.slne.surf.surfapi.bukkit.server.nms.toBukkit
import dev.slne.surf.surfapi.bukkit.server.nms.toNms
import dev.slne.surf.surfapi.core.api.util.*
import it.unimi.dsi.fastutil.objects.ObjectSet
import dev.slne.surf.surfapi.core.api.util.mutableObjectListOf
import net.kyori.adventure.text.format.TextDecoration
import net.minecraft.core.component.DataComponents
import net.minecraft.network.chat.Component
import net.minecraft.network.protocol.game.*
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.component.CustomData
import net.minecraft.world.item.component.ItemLore
import org.bukkit.NamespacedKey
import org.bukkit.plugin.Plugin
import java.util.concurrent.ConcurrentHashMap

/**
* PacketLoreListener is a class that implements PacketListenerAbstract and is responsible for
* handling the modification of lore on item stacks in packet events.
*/
@OptIn(NmsUseWithCaution::class)
object PacketLoreListener : PacketListener {
private val loreHandlers =
mutableObject2ObjectMapOf<NamespacedKey, SurfBukkitPacketLoreHandler>().synchronize()
private val loreHandlersGlobal =
mutableObject2ObjectMapOf<Plugin, ObjectSet<SurfBukkitPacketLoreHandler>>().synchronize()
private val loreHandlers = ConcurrentHashMap<NamespacedKey, SurfBukkitPacketLoreHandler>()
private val loreHandlersGlobal = ConcurrentHashMap<Plugin, MutableSet<SurfBukkitPacketLoreHandler>>()


private const val LORE_PREFIX_STRING = "§q"
private val lorePrefix = Component.literal(LORE_PREFIX_STRING)
private val ORIGINAL_LORE_KEY = key("original_lore")

@ServerboundListener
fun onPacketReceive(event: ServerboundSetCreativeModeSlotPacket) {
makeCleanItemStack(event.itemStack())
}

@ClientboundListener
fun onWindowItem(event: ClientboundContainerSetContentPacket) {
for (item in event.items) {
makeUpdatedItemStack(item)
}
fun onWindowItem(event: ClientboundContainerSetContentPacket): ClientboundContainerSetContentPacket {
return ClientboundContainerSetContentPacket(
event.containerId(),
event.stateId(),
event.items.map { makeUpdatedItemStack(it.copy()) },
makeUpdatedItemStack(event.carriedItem().copy())
)
}

@ClientboundListener
fun onContainerData(event: ClientboundContainerSetSlotPacket) {
makeUpdatedItemStack(event.item)
fun onContainerData(event: ClientboundContainerSetSlotPacket): ClientboundContainerSetSlotPacket {
return ClientboundContainerSetSlotPacket(
event.containerId,
event.stateId,
event.slot,
makeUpdatedItemStack(event.item.copy())
)
Comment on lines 48 to +55
}

@ClientboundListener
fun onSetPlayerInventoryPacket(event: ClientboundSetPlayerInventoryPacket) {
makeUpdatedItemStack(event.contents)
fun onSetPlayerInventoryPacket(event: ClientboundSetPlayerInventoryPacket): ClientboundSetPlayerInventoryPacket {
return ClientboundSetPlayerInventoryPacket(
event.slot(),
makeUpdatedItemStack(event.contents.copy())
)
}

@ClientboundListener
fun onSetCursorItemPacket(event: ClientboundSetCursorItemPacket) {
makeUpdatedItemStack(event.contents)
fun onSetCursorItemPacket(event: ClientboundSetCursorItemPacket): ClientboundSetCursorItemPacket {
return ClientboundSetCursorItemPacket(makeUpdatedItemStack(event.contents.copy()))
}

private fun makeUpdatedItemStack(
Expand All @@ -68,54 +76,57 @@ object PacketLoreListener : PacketListener {

val bukkitStack = item.asBukkitMirror()
val pdc = bukkitStack.persistentDataContainer
val nmsLore = item.get(DataComponents.LORE)
val lines = nmsLore?.lines
val lore =
lines?.mapTo(mutableObjectListOf(lines.size)) { it.toBukkit() } ?: emptyObjectList()
val nmsLore = item.getOrDefault(DataComponents.LORE, ItemLore.EMPTY)
val lines = nmsLore.lines
val mutableLore = lines.mapTo(mutableObjectListOf(lines.size)) { it.toBukkit() }

loreHandlers.forEach { (identifier, handler) ->
if (pdc.has(identifier)) {
handler.handleLore(lore, pdc, bukkitStack)
handler.handleLore(mutableLore, pdc, bukkitStack)
}
}

loreHandlersGlobal.forEach { (plugin, handlers) ->
if (plugin.isEnabled) {
handlers.forEach { it.handleLore(lore, pdc, bukkitStack) }
handlers.forEach { it.handleLore(mutableLore, pdc, bukkitStack) }
}
}

val updatedNmsLore = ItemLore(
lore.asSequence()
mutableLore.asSequence()
.map { it.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE) }
.map { it.toNms() }
.map { lorePrefix.copy().append(it) }
.toList()
)

item.set(DataComponents.LORE, updatedNmsLore)
CustomData.update(DataComponents.CUSTOM_DATA, item) { tag ->
tag.store(ORIGINAL_LORE_KEY.asString(), ItemLore.CODEC, nmsLore)
}
Comment on lines 95 to +105

return item
}

private fun makeCleanItemStack(
stack: ItemStack?,
): ItemStack? {
if (stack == null) return null

val updatedLore = stack.components.get(DataComponents.LORE)
?.lines?.filter { !it.string.startsWith(LORE_PREFIX_STRING) }
?: return stack
stack: ItemStack,
): ItemStack {
CustomData.update(DataComponents.CUSTOM_DATA, stack) { tag ->
val originalLore = tag.read(ORIGINAL_LORE_KEY.asString(), ItemLore.CODEC)
originalLore.ifPresent { lore ->
stack.set(DataComponents.LORE, lore)
tag.remove(ORIGINAL_LORE_KEY.asString())
}
}

stack.set(DataComponents.LORE, ItemLore(updatedLore))
return stack
}

fun register(identifier: NamespacedKey, listener: SurfBukkitPacketLoreHandler) {
loreHandlers.put(identifier, listener)
loreHandlers[identifier] = listener
}

fun register(plugin: Plugin, listener: SurfBukkitPacketLoreHandler) {
loreHandlersGlobal.computeIfAbsent(plugin) { mutableObjectSetOf() }.add(listener)
loreHandlersGlobal.computeIfAbsent(plugin) { ConcurrentHashMap.newKeySet() }.add(listener)
}

fun unregister(identifier: NamespacedKey) {
Expand Down
Loading