-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ support preview of chiseled bookshelf
- Loading branch information
1 parent
410a4d3
commit 0e19579
Showing
4 changed files
with
122 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
src/main/kotlin/xyz/xasmc/hashbook/listener/BookshelfListener.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<aqua>${meta.title}\n<gray>${meta.author} 著") | ||
val generation = when (meta.generation) { | ||
ORIGINAL -> "原稿" | ||
COPY_OF_ORIGINAL -> "原稿的副本" | ||
COPY_OF_COPY -> "副本的副本" | ||
TATTERED -> "破烂不堪" | ||
null -> "原稿" | ||
} | ||
nameSb.append("\n<gray>$generation") | ||
} | ||
MarkUtil.updateMark(player, markLocation.toLocation(world), nameSb.toString()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Player, MutableList<ArmorStand>>() | ||
|
||
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<ArmorStand>().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) | ||
} | ||
} | ||
} |