From 0e19579a6773d1270f84dc336fa084919651eecb Mon Sep 17 00:00:00 2001 From: XiYang6666 <1782356858@qq.com> Date: Wed, 7 Aug 2024 21:17:19 +0800 Subject: [PATCH] :sparkles: support preview of chiseled bookshelf --- build.gradle.kts | 2 +- .../kotlin/xyz/xasmc/hashbook/HashBook.kt | 7 ++- .../hashbook/listener/BookshelfListener.kt | 61 +++++++++++++++++++ .../xyz/xasmc/hashbook/util/MarkUtil.kt | 55 +++++++++++++++++ 4 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/xyz/xasmc/hashbook/listener/BookshelfListener.kt create mode 100644 src/main/kotlin/xyz/xasmc/hashbook/util/MarkUtil.kt diff --git a/build.gradle.kts b/build.gradle.kts index 40ed399..519fce7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,7 +24,7 @@ repositories { } dependencies { - compileOnly("io.papermc.paper:paper-api:1.20-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT") compileOnly("dev.jorel:commandapi-bukkit-core:9.4.2") compileOnly("de.tr7zw:item-nbt-api-plugin:2.9.1") compileOnly("net.kyori:adventure-text-minimessage:4.17.0") {} diff --git a/src/main/kotlin/xyz/xasmc/hashbook/HashBook.kt b/src/main/kotlin/xyz/xasmc/hashbook/HashBook.kt index a6f81b3..4c24b9e 100644 --- a/src/main/kotlin/xyz/xasmc/hashbook/HashBook.kt +++ b/src/main/kotlin/xyz/xasmc/hashbook/HashBook.kt @@ -5,21 +5,24 @@ import org.bukkit.plugin.java.JavaPlugin import xyz.xasmc.hashbook.command.HashBookCommand import xyz.xasmc.hashbook.config.ConfigLoader import xyz.xasmc.hashbook.config.PluginConfig +import xyz.xasmc.hashbook.listener.BookshelfListener import xyz.xasmc.hashbook.listener.OpenBookListener import xyz.xasmc.hashbook.service.ItemDataServices import xyz.xasmc.hashbook.service.StorageServices +import xyz.xasmc.hashbook.util.MarkUtil class HashBook : JavaPlugin() { override fun onEnable() { - HashBook.instance = this + instance = this this.load() + Bukkit.getPluginManager().registerEvents(BookshelfListener(), this) Bukkit.getPluginManager().registerEvents(OpenBookListener(), this) HashBookCommand.create().register(this) } override fun onDisable() { - + MarkUtil.clearAllMark() } fun load() { diff --git a/src/main/kotlin/xyz/xasmc/hashbook/listener/BookshelfListener.kt b/src/main/kotlin/xyz/xasmc/hashbook/listener/BookshelfListener.kt new file mode 100644 index 0000000..845bd52 --- /dev/null +++ b/src/main/kotlin/xyz/xasmc/hashbook/listener/BookshelfListener.kt @@ -0,0 +1,61 @@ +package xyz.xasmc.hashbook.listener + +import org.bukkit.Material +import org.bukkit.block.ChiseledBookshelf +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerMoveEvent +import org.bukkit.inventory.meta.BookMeta +import org.bukkit.inventory.meta.BookMeta.Generation.* +import xyz.xasmc.hashbook.util.MarkUtil + + +class BookshelfListener : Listener { + + + @EventHandler + fun onPlayerMode(event: PlayerMoveEvent) { + val player = event.player + val world = player.world + val direction = player.eyeLocation.direction + val maxDistance = 4.0 + val result = player.world.rayTraceBlocks(player.eyeLocation, direction, maxDistance) + if (result == null) { + MarkUtil.removeMark(player) + return + } + val hitBlock = result.hitBlock + if (hitBlock == null) { + MarkUtil.removeMark(player) + return + } + val hitPosition = result.hitPosition + if (hitBlock.type != Material.CHISELED_BOOKSHELF) { + MarkUtil.removeMark(player) + return + } + val bookshelf = hitBlock.state as ChiseledBookshelf + val blockHitPosition = hitPosition.clone().subtract(hitBlock.location.toVector()) + val item = bookshelf.inventory.getItem(bookshelf.getSlot(blockHitPosition)) + if (item == null) { + MarkUtil.removeMark(player) + return + } + val normalizedEyeDirection = player.eyeLocation.direction.clone().normalize() + val markLocation = hitPosition.clone().subtract(normalizedEyeDirection.multiply(0.1)) + val nameSb = StringBuilder(item.type.name) + if (item.type == Material.WRITTEN_BOOK) { + val meta = item.itemMeta as BookMeta + nameSb.append("\n${meta.title}\n${meta.author} 著") + val generation = when (meta.generation) { + ORIGINAL -> "原稿" + COPY_OF_ORIGINAL -> "原稿的副本" + COPY_OF_COPY -> "副本的副本" + TATTERED -> "破烂不堪" + null -> "原稿" + } + nameSb.append("\n$generation") + } + MarkUtil.updateMark(player, markLocation.toLocation(world), nameSb.toString()) + } +} diff --git a/src/main/kotlin/xyz/xasmc/hashbook/util/MarkUtil.kt b/src/main/kotlin/xyz/xasmc/hashbook/util/MarkUtil.kt new file mode 100644 index 0000000..583add9 --- /dev/null +++ b/src/main/kotlin/xyz/xasmc/hashbook/util/MarkUtil.kt @@ -0,0 +1,55 @@ +package xyz.xasmc.hashbook.util + +import net.kyori.adventure.text.minimessage.MiniMessage +import org.bukkit.Location +import org.bukkit.World +import org.bukkit.entity.ArmorStand +import org.bukkit.entity.EntityType +import org.bukkit.entity.Player + +object MarkUtil { + private val mm = MiniMessage.miniMessage() + private val playerMark = mutableMapOf>() + + fun updateMark(player: Player, location: Location, name: String) { + val world = player.world + val textList = name.split("\n") + val count = textList.size + val interval = 0.2 + val offset = -0.4 + + val marks = playerMark[player] ?: mutableListOf().also { playerMark[player] = it } + + val currentCount = marks.size + when { + count > currentCount -> repeat(count - currentCount) { marks.add(createArmorStand(world)) } + count < currentCount -> repeat(currentCount - count) { marks.removeLast()?.remove() } + } + + val top = location.clone().add(0.0, interval * count / 2 + offset, 0.0) + textList.forEachIndexed { i, it -> + val mark = playerMark[player]!![i] + mark.teleport(top.clone().add(0.0, -i * interval, 0.0)) + mark.customName(mm.deserialize(it)) + } + } + + fun removeMark(player: Player) { + playerMark[player]?.forEach { it.remove() } + playerMark.remove(player) + } + + fun clearAllMark() { + playerMark.forEach { it.value.forEach { it.remove() } } + playerMark.clear() + } + + private fun createArmorStand(world: World): ArmorStand { + return (world.spawnEntity(Location(world, .0, .0, .0), EntityType.ARMOR_STAND) as ArmorStand).apply { + isVisible = false + isMarker = true + isCustomNameVisible = true + setGravity(false) + } + } +} \ No newline at end of file