Fixed 1.21.5 support

This commit is contained in:
Will FP
2025-06-02 15:01:33 +01:00
parent 76144013d5
commit 08455b3694
8 changed files with 327 additions and 9 deletions

View File

@@ -6,10 +6,51 @@ import org.jetbrains.annotations.NotNull;
/**
* Represents a packet.
*
* @param handle The NMS handle.
*/
public record Packet(@NotNull Object handle) {
public class Packet {
/**
* The packet handle.
*/
private Object handle;
/**
* Create a new packet.
*
* @param handle The packet handle.
*/
public Packet(@NotNull final Object handle) {
this.handle = handle;
}
/**
* Get the packet handle.
*
* @return The packet handle.
*/
public Object getHandle() {
return handle;
}
/**
* Set the packet handle.
*
* @param handle The packet handle.
*/
public void setHandle(@NotNull final Object handle) {
this.handle = handle;
}
/**
* Get the packet handle, compatible with the old record-based packet system.
*
* @return The packet handle.
* @deprecated Use {@link #getHandle()} instead.
*/
@Deprecated
public Object handle() {
return handle;
}
/**
* Send to a player.
*

View File

@@ -23,7 +23,7 @@ class EcoChannelDuplexHandler(
event.handleReceive()
if (!event.isCancelled) {
super.channelRead(ctx, msg)
super.channelRead(ctx, event.packet.handle)
}
} else {
super.channelRead(ctx, msg)
@@ -39,7 +39,7 @@ class EcoChannelDuplexHandler(
event.handleSend()
if (!event.isCancelled) {
super.write(ctx, msg, promise)
super.write(ctx, event.packet.handle, promise)
}
} else {
super.write(ctx, msg, promise)

View File

@@ -144,7 +144,7 @@ open class NewEcoFastItemStack(
override fun getDisplayName(): String = displayNameComponent.toLegacy()
private fun <T> net.minecraft.world.item.ItemStack.modifyComponent(
protected fun <T> net.minecraft.world.item.ItemStack.modifyComponent(
component: DataComponentType<T>,
modifier: (T) -> T
) {

View File

@@ -6,6 +6,7 @@ import com.willfp.eco.core.packet.PacketListener
import com.willfp.eco.internal.spigot.proxy.common.asBukkitStack
import com.willfp.eco.internal.spigot.proxy.common.packet.display.frame.DisplayFrame
import com.willfp.eco.internal.spigot.proxy.common.packet.display.frame.lastDisplayFrame
import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket
import net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket
object NewItemsPacketSetCreativeSlot : PacketListener {

View File

@@ -3,10 +3,11 @@ package com.willfp.eco.internal.spigot.proxy.v1_21_5
import com.willfp.eco.core.fast.FastItemStack
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
import com.willfp.eco.internal.spigot.proxy.common.modern.NewEcoFastItemStack
import com.willfp.eco.internal.spigot.proxy.v1_21_5.item.NewerEcoFastItemStack
import org.bukkit.inventory.ItemStack
class FastItemStackFactory : FastItemStackFactoryProxy {
override fun create(itemStack: ItemStack): FastItemStack {
return NewEcoFastItemStack(itemStack)
return NewerEcoFastItemStack(itemStack)
}
}

View File

@@ -5,10 +5,10 @@ import com.willfp.eco.core.packet.PacketListener
import com.willfp.eco.internal.spigot.proxy.PacketHandlerProxy
import com.willfp.eco.internal.spigot.proxy.common.packet.display.PacketHeldItemSlot
import com.willfp.eco.internal.spigot.proxy.common.packet.display.PacketSetSlot
import com.willfp.eco.internal.spigot.proxy.common.packet.display.PacketWindowItems
import com.willfp.eco.internal.spigot.proxy.common.packet.display.frame.clearFrames
import com.willfp.eco.internal.spigot.proxy.v1_21_5.packet.NewItemsPacketOpenWindowMerchant
import com.willfp.eco.internal.spigot.proxy.v1_21_5.packet.NewItemsPacketSetCreativeSlot
import com.willfp.eco.internal.spigot.proxy.v1_21_5.packet.NewItemsPacketWindowItems
import net.minecraft.network.protocol.Packet
import org.bukkit.craftbukkit.entity.CraftPlayer
import org.bukkit.entity.Player
@@ -40,7 +40,7 @@ class PacketHandler : PacketHandlerProxy {
NewItemsPacketOpenWindowMerchant,
NewItemsPacketSetCreativeSlot,
PacketSetSlot,
PacketWindowItems(plugin)
NewItemsPacketWindowItems(plugin)
)
}
}

View File

@@ -0,0 +1,185 @@
package com.willfp.eco.internal.spigot.proxy.v1_21_5.item
import com.willfp.eco.internal.spigot.proxy.common.modern.NewEcoFastItemStack
import net.minecraft.core.component.DataComponents
import net.minecraft.world.item.component.TooltipDisplay
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.ItemStack
open class NewerEcoFastItemStack(
bukkit: ItemStack,
) : NewEcoFastItemStack(bukkit) {
override fun addItemFlags(vararg hideFlags: ItemFlag) {
for (flag in hideFlags) {
when (flag) {
ItemFlag.HIDE_ENCHANTS -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.ENCHANTMENTS, true)
}
}
ItemFlag.HIDE_ATTRIBUTES -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.ATTRIBUTE_MODIFIERS, true)
}
}
ItemFlag.HIDE_UNBREAKABLE -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.UNBREAKABLE, true)
}
}
ItemFlag.HIDE_DESTROYS -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.CAN_BREAK, true)
}
}
ItemFlag.HIDE_PLACED_ON -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.CAN_PLACE_ON, true)
}
}
ItemFlag.HIDE_ADDITIONAL_TOOLTIP -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
TooltipDisplay(true, tooltip.hiddenComponents)
}
}
ItemFlag.HIDE_DYE -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.DYED_COLOR, true)
}
}
ItemFlag.HIDE_ARMOR_TRIM -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.TRIM, true)
}
}
ItemFlag.HIDE_STORED_ENCHANTS -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.STORED_ENCHANTMENTS, true)
}
}
}
}
apply()
}
override fun removeItemFlags(vararg hideFlags: ItemFlag) {
for (flag in hideFlags) {
when (flag) {
ItemFlag.HIDE_ENCHANTS -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.ENCHANTMENTS, false)
}
}
ItemFlag.HIDE_ATTRIBUTES -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.ATTRIBUTE_MODIFIERS, false)
}
}
ItemFlag.HIDE_UNBREAKABLE -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.UNBREAKABLE, false)
}
}
ItemFlag.HIDE_DESTROYS -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.CAN_BREAK, false)
}
}
ItemFlag.HIDE_PLACED_ON -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.CAN_PLACE_ON, false)
}
}
ItemFlag.HIDE_ADDITIONAL_TOOLTIP -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
TooltipDisplay(false, tooltip.hiddenComponents)
}
}
ItemFlag.HIDE_DYE -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.DYED_COLOR, false)
}
}
ItemFlag.HIDE_ARMOR_TRIM -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.TRIM, false)
}
}
ItemFlag.HIDE_STORED_ENCHANTS -> {
handle.modifyComponent(DataComponents.TOOLTIP_DISPLAY) { tooltip ->
tooltip.withHidden(DataComponents.STORED_ENCHANTMENTS, false)
}
}
}
}
apply()
}
override fun hasItemFlag(flag: ItemFlag): Boolean {
return when (flag) {
ItemFlag.HIDE_ENCHANTS -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
!tooltip.shows(DataComponents.ENCHANTMENTS)
}
ItemFlag.HIDE_ATTRIBUTES -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
!tooltip.shows(DataComponents.ATTRIBUTE_MODIFIERS)
}
ItemFlag.HIDE_UNBREAKABLE -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
!tooltip.shows(DataComponents.UNBREAKABLE)
}
ItemFlag.HIDE_DESTROYS -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
!tooltip.shows(DataComponents.CAN_BREAK)
}
ItemFlag.HIDE_PLACED_ON -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
!tooltip.shows(DataComponents.CAN_PLACE_ON)
}
ItemFlag.HIDE_ADDITIONAL_TOOLTIP -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
tooltip.hideTooltip
}
ItemFlag.HIDE_DYE -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
!tooltip.shows(DataComponents.DYED_COLOR)
}
ItemFlag.HIDE_ARMOR_TRIM -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
!tooltip.shows(DataComponents.TRIM)
}
ItemFlag.HIDE_STORED_ENCHANTS -> {
val tooltip = handle.get(DataComponents.TOOLTIP_DISPLAY) ?: return false
!tooltip.shows(DataComponents.STORED_ENCHANTMENTS)
}
}
}
}

View File

@@ -0,0 +1,90 @@
package com.willfp.eco.internal.spigot.proxy.v1_21_5.packet
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.display.Display
import com.willfp.eco.core.items.HashedItem
import com.willfp.eco.core.packet.PacketEvent
import com.willfp.eco.core.packet.PacketListener
import com.willfp.eco.internal.spigot.proxy.common.asBukkitStack
import com.willfp.eco.internal.spigot.proxy.common.asNMSStack
import com.willfp.eco.internal.spigot.proxy.common.packet.display.frame.DisplayFrame
import com.willfp.eco.internal.spigot.proxy.common.packet.display.frame.lastDisplayFrame
import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
class NewItemsPacketWindowItems(
private val plugin: EcoPlugin
) : PacketListener {
private val lastKnownWindowIDs = ConcurrentHashMap<UUID, Int>()
override fun onSend(event: PacketEvent) {
val packet = event.packet.handle as? ClientboundContainerSetContentPacket ?: return
val player = event.player
Display.display(packet.carriedItem.asBukkitStack(), player)
val windowId = packet.containerId
val lastKnownID = lastKnownWindowIDs[player.uniqueId]
lastKnownWindowIDs[player.uniqueId] = windowId
// If there is any change in window ID at any point,
// Remove the last display frame to prevent any potential conflicts.
// If the window ID is not zero (not a player inventory), then remove too,
// as GUIs are not player inventories.
if (lastKnownID != windowId || windowId != 0) {
player.lastDisplayFrame = DisplayFrame.EMPTY
}
val itemStacks = packet.items.map { it.asBukkitStack() }
val newItems = modifyWindowItems(itemStacks.toMutableList(), windowId, player)
val newPacket = ClientboundContainerSetContentPacket(
packet.containerId,
packet.stateId,
newItems.map { it.asNMSStack() },
packet.carriedItem,
)
event.packet.handle = newPacket
}
private fun modifyWindowItems(
itemStacks: MutableList<ItemStack>,
windowId: Int,
player: Player
): MutableList<ItemStack> {
if (plugin.configYml.getBool("use-display-frame") && windowId == 0) {
val frameMap = mutableMapOf<Byte, HashedItem>()
for (index in itemStacks.indices) {
frameMap[index.toByte()] = HashedItem.of(itemStacks[index])
}
val newFrame = DisplayFrame(frameMap)
val lastFrame = player.lastDisplayFrame
player.lastDisplayFrame = newFrame
val changes = lastFrame.getChangedSlots(newFrame)
for (index in changes) {
Display.display(itemStacks[index.toInt()], player)
}
for (index in (itemStacks.indices subtract changes.toSet())) {
itemStacks[index.toInt()] = lastFrame.getItem(index.toByte()) ?: itemStacks[index.toInt()]
}
} else {
itemStacks.forEach { Display.display(it, player) }
}
return itemStacks
}
}