mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 08:14:00 +02:00
dialog rename working good enough
This commit is contained in:
parent
05951d0ace
commit
31f9e7e281
9 changed files with 276 additions and 27 deletions
|
|
@ -22,7 +22,7 @@ plugins {
|
|||
}
|
||||
|
||||
group = "xyz.alexcrea"
|
||||
version = "1.16.3"
|
||||
version = "1.17.0"
|
||||
|
||||
val isDevBuild = System.getenv("SMALL_COMMIT_HASH") != null
|
||||
val isPreRelease = System.getenv("IS_GITHUB_PRERELEASE") == "true"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package xyz.alexcrea.cuanvil.dialog
|
||||
|
||||
import org.bukkit.entity.HumanEntity
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
|
||||
interface AnvilRenameDialog {
|
||||
|
||||
fun canSendDialog(): Boolean
|
||||
|
||||
fun tryShowDialog(player: HumanEntity, event: PrepareAnvilEvent)
|
||||
|
||||
fun closeInventory(player: HumanEntity)
|
||||
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ dependencies {
|
|||
implementation(project(":nms:nms-common"))
|
||||
|
||||
// Used for nms
|
||||
paperweight.paperDevBundle("1.20.6-R0.1-SNAPSHOT")
|
||||
paperweight.paperDevBundle("1.21.7-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
package xyz.alexcrea.cuanvil.dialog
|
||||
|
||||
import io.papermc.paper.dialog.Dialog
|
||||
import io.papermc.paper.registry.data.dialog.ActionButton
|
||||
import io.papermc.paper.registry.data.dialog.DialogBase
|
||||
import io.papermc.paper.registry.data.dialog.action.DialogAction
|
||||
import io.papermc.paper.registry.data.dialog.body.DialogBody
|
||||
import io.papermc.paper.registry.data.dialog.input.DialogInput
|
||||
import io.papermc.paper.registry.data.dialog.type.DialogType
|
||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.event.ClickCallback
|
||||
import net.kyori.adventure.text.format.TextColor
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer
|
||||
import net.minecraft.world.inventory.AnvilMenu
|
||||
import org.bukkit.craftbukkit.event.CraftEventFactory
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryView
|
||||
import org.bukkit.craftbukkit.inventory.view.CraftAnvilView
|
||||
import org.bukkit.entity.HumanEntity
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.plugin.Plugin
|
||||
import java.util.UUID
|
||||
import java.util.function.BiFunction
|
||||
import java.util.function.Consumer
|
||||
import java.util.function.Supplier
|
||||
import kotlin.collections.set
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
class AnvilRenameDialogImpl(
|
||||
val fromFormated: BiFunction<HumanEntity, Component?, String?>,
|
||||
val maxLength: Supplier<Int>,
|
||||
val plugin: Plugin,
|
||||
): AnvilRenameDialog {
|
||||
|
||||
companion object {
|
||||
private const val RENAME_TEXT_KEY = "rename"
|
||||
|
||||
private const val MAX_WIDTH = 512
|
||||
|
||||
private val PLAIN_TEXT_SERIALIZER = PlainTextComponentSerializer.plainText()
|
||||
|
||||
// Need to be able to translate it later !
|
||||
private val USER_FACING_RENAME_TITLE = Component.text("Rename Your Item")
|
||||
private val USER_FACING_WARNING = Component.text("Note that the repair text will appear blank after Confirm\n" +
|
||||
"But the name will be correctly applied")
|
||||
private val USER_FACING_CONFIRM = Component.text("Confirm").color(TextColor.fromHexString("#40FF40"))
|
||||
private val USER_FACING_CANCEL = Component.text("Cancel").color(TextColor.fromHexString("#FF4040"))
|
||||
}
|
||||
|
||||
private val lastNames = HashMap<UUID, String>()
|
||||
private val lastLeftItem = HashMap<UUID, String>()
|
||||
private val runTaskMap = HashMap<UUID, ScheduledTask>()
|
||||
|
||||
private val containerField = CraftInventoryView::class.java.getDeclaredField("container")
|
||||
|
||||
init {
|
||||
containerField.setAccessible(true)
|
||||
}
|
||||
|
||||
override fun canSendDialog(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
fun makeDialog(initial: String?, callback: Consumer<String?>): Dialog {
|
||||
val maxLength = this.maxLength.get()
|
||||
val initialFinal = initial?.take(maxLength)
|
||||
|
||||
val baseBuilder = DialogBase.builder(USER_FACING_RENAME_TITLE)
|
||||
.canCloseWithEscape(true)
|
||||
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||
.inputs(listOf(
|
||||
DialogInput.text(RENAME_TEXT_KEY, Component.text("Rename text"))
|
||||
.maxLength(maxLength)
|
||||
.initial(initialFinal ?: "")
|
||||
.labelVisible(false)
|
||||
.width(MAX_WIDTH)
|
||||
.build(),
|
||||
),
|
||||
)
|
||||
baseBuilder.body(listOf(
|
||||
DialogBody.plainMessage(USER_FACING_WARNING, MAX_WIDTH)
|
||||
))
|
||||
|
||||
return Dialog.create { builder -> builder.empty()
|
||||
.base(baseBuilder.build())
|
||||
.type(DialogType.confirmation(
|
||||
ActionButton.builder(USER_FACING_CONFIRM)
|
||||
.action(DialogAction.customClick({ response, _ ->
|
||||
val text = response.getText(RENAME_TEXT_KEY)!!
|
||||
callback.accept(text)
|
||||
}, ClickCallback.Options.builder().build()))
|
||||
.build(),
|
||||
ActionButton.builder(USER_FACING_CANCEL)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
private fun setResult(player: HumanEntity, view: CraftAnvilView, result: String?) {
|
||||
val defaultName = PLAIN_TEXT_SERIALIZER.serializeOrNull(view.getItem(0)?.effectiveName())
|
||||
if(defaultName == result) {
|
||||
setName(player, view, "")
|
||||
if(defaultName != null) lastNames[player.uniqueId] = defaultName
|
||||
}
|
||||
else setName(player, view, result)
|
||||
}
|
||||
|
||||
private fun setName(player: HumanEntity, view: CraftAnvilView, name: String?) {
|
||||
val menu = (containerField.get(view) as AnvilMenu)
|
||||
menu.itemName = name
|
||||
|
||||
if(name == null)
|
||||
lastNames.remove(player.uniqueId)
|
||||
else
|
||||
lastNames[player.uniqueId] = name
|
||||
CraftEventFactory.callPrepareResultEvent(menu, 2);
|
||||
}
|
||||
|
||||
private fun nameFromItem(player: HumanEntity, item: ItemStack?): String? {
|
||||
return if(item?.hasItemMeta() != true || !item.itemMeta.hasCustomName())
|
||||
PLAIN_TEXT_SERIALIZER.serializeOrNull(item?.effectiveName())
|
||||
else fromFormated.apply(player, item.effectiveName())
|
||||
}
|
||||
|
||||
private fun tryShowDialogScheduled(player: HumanEntity, event: PrepareAnvilEvent) {
|
||||
val view = event.view
|
||||
if(view !is CraftAnvilView) return
|
||||
|
||||
val renameText = view.renameText
|
||||
val leftItem = view.getItem(0)
|
||||
val leftItemStr = leftItem?.toString()
|
||||
val lastName = lastNames.getOrDefault(player.uniqueId, null)
|
||||
|
||||
if(lastLeftItem.getOrDefault(player.uniqueId, null) != leftItemStr) {
|
||||
if(leftItemStr == null)
|
||||
lastLeftItem.remove(player.uniqueId)
|
||||
else lastLeftItem[player.uniqueId] = leftItemStr
|
||||
|
||||
setName(player, view, nameFromItem(player, leftItem))
|
||||
return
|
||||
}
|
||||
|
||||
if(lastName == renameText)
|
||||
return
|
||||
|
||||
if(renameText?.isBlank() == true) {
|
||||
setName(player, view, lastNames[player.uniqueId])
|
||||
return
|
||||
}
|
||||
|
||||
val dialog = makeDialog(lastName)
|
||||
{ result -> setResult(player, view, result) }
|
||||
player.showDialog(dialog)
|
||||
}
|
||||
|
||||
// We need to wait for a short time as changing item will change the name BEFORE the item change
|
||||
// no guaranty both of them came in the same tick too so let's wait 2 tick....
|
||||
override fun tryShowDialog(player: HumanEntity, event: PrepareAnvilEvent) {
|
||||
runTaskMap.remove(player.uniqueId)?.cancel()
|
||||
|
||||
val task = player.scheduler.runDelayed(
|
||||
plugin,
|
||||
{ _ ->
|
||||
run { tryShowDialogScheduled(player, event) }
|
||||
},
|
||||
{},
|
||||
2
|
||||
)
|
||||
if(task == null) return
|
||||
|
||||
runTaskMap[player.uniqueId] = task
|
||||
}
|
||||
|
||||
override fun closeInventory(player: HumanEntity) {
|
||||
lastNames.remove(player.uniqueId)
|
||||
lastLeftItem.remove(player.uniqueId)
|
||||
runTaskMap.remove(player.uniqueId)?.cancel()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import org.bukkit.event.Listener
|
|||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
|
||||
import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil
|
||||
|
||||
class AnvilCloseListener(private val packetManager: PacketManager) : Listener {
|
||||
|
||||
|
|
@ -18,6 +19,7 @@ class AnvilCloseListener(private val packetManager: PacketManager) : Listener {
|
|||
packetManager.setInstantBuild(player, false)
|
||||
}
|
||||
|
||||
AnvilRenameDialogUtil.anvilRenameDialog.closeInventory(player)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import org.bukkit.event.EventPriority
|
|||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta
|
||||
import org.bukkit.inventory.meta.ItemMeta
|
||||
|
|
@ -26,6 +27,7 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantment
|
|||
import xyz.alexcrea.cuanvil.util.*
|
||||
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir
|
||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||
import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
/**
|
||||
|
|
@ -41,6 +43,8 @@ class PrepareAnvilListener : Listener {
|
|||
const val ANVIL_OUTPUT_SLOT = 2
|
||||
|
||||
var IS_EMPTY_TEST = false
|
||||
|
||||
const val RENAME_DIALOG_PERMISSION = "ca.rename.dialog"
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -80,6 +84,8 @@ class PrepareAnvilListener : Listener {
|
|||
return
|
||||
}
|
||||
|
||||
tryRenameDialog(player, event)
|
||||
|
||||
// Test if the event should bypass custom anvil.
|
||||
if (DependencyManager.tryEventPreAnvilBypass(event, player)) {
|
||||
// even if we got bypassed we still want to set price
|
||||
|
|
@ -117,6 +123,16 @@ class PrepareAnvilListener : Listener {
|
|||
|
||||
}
|
||||
|
||||
private fun tryRenameDialog(
|
||||
player: HumanEntity,
|
||||
event: PrepareAnvilEvent
|
||||
) {
|
||||
if(!ConfigOptions.doRenameDialog || !AnvilRenameDialogUtil.anvilRenameDialog.canSendDialog()) return
|
||||
if(ConfigOptions.doRenameDialogUsePermission && !player.hasPermission(RENAME_DIALOG_PERMISSION)) return
|
||||
|
||||
AnvilRenameDialogUtil.anvilRenameDialog.tryShowDialog(player, event)
|
||||
}
|
||||
|
||||
private fun isImmutable(item: ItemStack?): Boolean {
|
||||
if (item.isAir) return false
|
||||
|
||||
|
|
@ -208,11 +224,8 @@ class PrepareAnvilListener : Listener {
|
|||
var useColor = false
|
||||
if (ConfigOptions.renameColorPossible && renameText != null) {
|
||||
val component = AnvilColorUtil.handleColor(
|
||||
renameText, player,
|
||||
ConfigOptions.permissionNeededForColor,
|
||||
ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, ConfigOptions.allowMinimessage,
|
||||
AnvilColorUtil.ColorUseType.RENAME
|
||||
)
|
||||
renameText,
|
||||
AnvilColorUtil.renamePermission(player))
|
||||
|
||||
if (component != null) {
|
||||
renameText = MiniMessageUtil.legacy_mm.serialize(component)
|
||||
|
|
|
|||
|
|
@ -60,25 +60,11 @@ object AnvilColorUtil {
|
|||
return ColorPermissions(canUseColorCode, canUseHexColor, canUseMinimessage, player)
|
||||
}
|
||||
|
||||
/**
|
||||
* Color a string depending on allowed color type, color use type and player permissions
|
||||
* @return colored component or null if nothing has been colored
|
||||
*/
|
||||
fun handleColor(
|
||||
textToColorText: String,
|
||||
player: Permissible,
|
||||
usePermission: Boolean,
|
||||
allowColorCode: Boolean,
|
||||
allowHexadecimalColor: Boolean,
|
||||
allowMinimessage: Boolean,
|
||||
useType: ColorUseType
|
||||
): Component? {
|
||||
val permission = calculatePermissions(
|
||||
player, usePermission,
|
||||
allowColorCode, allowHexadecimalColor, allowMinimessage,
|
||||
useType
|
||||
)
|
||||
return handleColor(textToColorText, permission)
|
||||
fun renamePermission(player: Permissible): ColorPermissions {
|
||||
return calculatePermissions(player,
|
||||
ConfigOptions.permissionNeededForColor,
|
||||
ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, ConfigOptions.allowMinimessage,
|
||||
ColorUseType.RENAME)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package xyz.alexcrea.cuanvil.util.dialog
|
||||
|
||||
import io.delilaheve.CustomAnvil
|
||||
import io.delilaheve.util.ConfigOptions
|
||||
import net.kyori.adventure.text.Component
|
||||
import org.bukkit.entity.HumanEntity
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
|
||||
import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog
|
||||
import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialogImpl
|
||||
import xyz.alexcrea.cuanvil.update.UpdateUtils
|
||||
import xyz.alexcrea.cuanvil.util.AnvilColorUtil
|
||||
|
||||
object AnvilRenameDialogUtil {
|
||||
|
||||
val anvilRenameDialog: AnvilRenameDialog;
|
||||
|
||||
init {
|
||||
val version = UpdateUtils.currentMinecraftVersion()
|
||||
anvilRenameDialog = (if(!PlatformUtil.isPaper ||
|
||||
(version.major <= 1 && version.minor <= 21 && version.patch <= 6)) {
|
||||
NoImplAnvilRenameDialog()
|
||||
} else {
|
||||
AnvilRenameDialogImpl({ player, component -> AnvilColorUtil.revertColorSmallest(
|
||||
component, AnvilColorUtil.renamePermission(player)
|
||||
) },
|
||||
{ ConfigOptions.renameDialogMaxSize },
|
||||
CustomAnvil.instance,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
class NoImplAnvilRenameDialog: AnvilRenameDialog {
|
||||
|
||||
override fun canSendDialog(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun tryShowDialog(
|
||||
player: HumanEntity,
|
||||
event: PrepareAnvilEvent
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
override fun closeInventory(player: HumanEntity) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -102,7 +102,9 @@ permission_needed_for_color: true
|
|||
use_of_color_cost: 0
|
||||
|
||||
# Dialogue rename menu make use of dialog menu to allow bigger rename
|
||||
# You can change the maximum size
|
||||
# You can also change the maximum size up to 2147483647
|
||||
#
|
||||
# This feature only work on paper 1.21.7 or later
|
||||
#
|
||||
# At the moment only english is available for this menu... sorry !
|
||||
#
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue