看板素材対応・クリック方向対応
This commit is contained in:
parent
84c4252592
commit
65b3cfd8e2
|
|
@ -17,6 +17,60 @@ object ShopVisuals {
|
|||
org.bukkit.Material.COPPER_CHEST
|
||||
)
|
||||
|
||||
val VALID_SIGNS = setOfNotNull(
|
||||
// Standard Standing Signs
|
||||
org.bukkit.Material.OAK_SIGN, org.bukkit.Material.BIRCH_SIGN, org.bukkit.Material.SPRUCE_SIGN, org.bukkit.Material.JUNGLE_SIGN,
|
||||
org.bukkit.Material.ACACIA_SIGN, org.bukkit.Material.DARK_OAK_SIGN, org.bukkit.Material.MANGROVE_SIGN, org.bukkit.Material.CHERRY_SIGN,
|
||||
org.bukkit.Material.BAMBOO_SIGN, org.bukkit.Material.CRIMSON_SIGN, org.bukkit.Material.WARPED_SIGN, org.bukkit.Material.getMaterial("PALE_OAK_SIGN"),
|
||||
|
||||
// Wall Signs
|
||||
org.bukkit.Material.OAK_WALL_SIGN, org.bukkit.Material.BIRCH_WALL_SIGN, org.bukkit.Material.SPRUCE_WALL_SIGN, org.bukkit.Material.JUNGLE_WALL_SIGN,
|
||||
org.bukkit.Material.ACACIA_WALL_SIGN, org.bukkit.Material.DARK_OAK_WALL_SIGN, org.bukkit.Material.MANGROVE_WALL_SIGN, org.bukkit.Material.CHERRY_WALL_SIGN,
|
||||
org.bukkit.Material.BAMBOO_WALL_SIGN, org.bukkit.Material.CRIMSON_WALL_SIGN, org.bukkit.Material.WARPED_WALL_SIGN, org.bukkit.Material.getMaterial("PALE_OAK_WALL_SIGN"),
|
||||
|
||||
// Hanging Signs (Ceiling)
|
||||
org.bukkit.Material.OAK_HANGING_SIGN, org.bukkit.Material.BIRCH_HANGING_SIGN, org.bukkit.Material.SPRUCE_HANGING_SIGN, org.bukkit.Material.JUNGLE_HANGING_SIGN,
|
||||
org.bukkit.Material.ACACIA_HANGING_SIGN, org.bukkit.Material.DARK_OAK_HANGING_SIGN, org.bukkit.Material.MANGROVE_HANGING_SIGN, org.bukkit.Material.CHERRY_HANGING_SIGN,
|
||||
org.bukkit.Material.BAMBOO_HANGING_SIGN, org.bukkit.Material.CRIMSON_HANGING_SIGN, org.bukkit.Material.WARPED_HANGING_SIGN, org.bukkit.Material.getMaterial("PALE_OAK_HANGING_SIGN"),
|
||||
|
||||
// Wall Hanging Signs
|
||||
org.bukkit.Material.OAK_WALL_HANGING_SIGN, org.bukkit.Material.BIRCH_WALL_HANGING_SIGN, org.bukkit.Material.SPRUCE_WALL_HANGING_SIGN, org.bukkit.Material.JUNGLE_WALL_HANGING_SIGN,
|
||||
org.bukkit.Material.ACACIA_WALL_HANGING_SIGN, org.bukkit.Material.DARK_OAK_WALL_HANGING_SIGN, org.bukkit.Material.MANGROVE_WALL_HANGING_SIGN, org.bukkit.Material.CHERRY_WALL_HANGING_SIGN,
|
||||
org.bukkit.Material.BAMBOO_WALL_HANGING_SIGN, org.bukkit.Material.CRIMSON_WALL_HANGING_SIGN, org.bukkit.Material.WARPED_WALL_HANGING_SIGN, org.bukkit.Material.getMaterial("PALE_OAK_WALL_HANGING_SIGN")
|
||||
)
|
||||
|
||||
fun isShopSign(material: org.bukkit.Material): Boolean {
|
||||
return VALID_SIGNS.contains(material)
|
||||
}
|
||||
|
||||
fun isWallSign(material: org.bukkit.Material): Boolean {
|
||||
return material.name.contains("WALL_SIGN") && !material.name.contains("HANGING")
|
||||
}
|
||||
|
||||
fun isHangingSign(material: org.bukkit.Material): Boolean {
|
||||
return material.name.contains("HANGING_SIGN")
|
||||
}
|
||||
|
||||
fun getSignMaterial(key: String): org.bukkit.Material? {
|
||||
val upperKey = key.uppercase()
|
||||
// Map short names to materials
|
||||
return when (upperKey) {
|
||||
"OAK" -> org.bukkit.Material.OAK_SIGN
|
||||
"BIRCH" -> org.bukkit.Material.BIRCH_SIGN
|
||||
"SPRUCE" -> org.bukkit.Material.SPRUCE_SIGN
|
||||
"JUNGLE" -> org.bukkit.Material.JUNGLE_SIGN
|
||||
"ACACIA" -> org.bukkit.Material.ACACIA_SIGN
|
||||
"DARK_OAK" -> org.bukkit.Material.DARK_OAK_SIGN
|
||||
"MANGROVE" -> org.bukkit.Material.MANGROVE_SIGN
|
||||
"CHERRY" -> org.bukkit.Material.CHERRY_SIGN
|
||||
"BAMBOO" -> org.bukkit.Material.BAMBOO_SIGN
|
||||
"CRIMSON" -> org.bukkit.Material.CRIMSON_SIGN
|
||||
"WARPED" -> org.bukkit.Material.WARPED_SIGN
|
||||
"PALE" -> org.bukkit.Material.getMaterial("PALE_OAK_SIGN")
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSign(plugin: JavaPlugin, block: org.bukkit.block.Block, shopData: ShopData, side: Side) {
|
||||
val state = block.state as? Sign ?: return
|
||||
val signSide = state.getSide(side)
|
||||
|
|
@ -84,24 +138,28 @@ object ShopVisuals {
|
|||
}
|
||||
return count
|
||||
}
|
||||
fun removeDisplay(location: org.bukkit.Location, face: String) {
|
||||
fun removeDisplay(plugin: JavaPlugin, location: org.bukkit.Location, shopId: Int? = null) {
|
||||
val world = location.world ?: return
|
||||
val block = location.block
|
||||
val data = block.blockData as? org.bukkit.block.data.Rotatable ?: return
|
||||
val rotation = data.rotation
|
||||
|
||||
val yaw = yawFromBlockFace(rotation) + 90f
|
||||
// Search at center of block (0.5, 0.5, 0.5)
|
||||
val center = location.clone().add(0.5, 0.5, 0.5)
|
||||
|
||||
val offset = if (face == "FRONT") org.joml.Vector3f(0.25f, 0.25f, 0.0f) else org.joml.Vector3f(-0.25f, 0.25f, 0.0f)
|
||||
val rad = Math.toRadians(yaw.toDouble())
|
||||
offset.rotateY(-rad.toFloat())
|
||||
val key = org.bukkit.NamespacedKey(plugin, "shop_id")
|
||||
|
||||
val center = location.clone().add(0.5, 0.0, 0.5)
|
||||
val targetPos = center.clone().add(offset.x.toDouble(), offset.y.toDouble(), offset.z.toDouble())
|
||||
|
||||
// Search for entity
|
||||
val nearby = world.getNearbyEntities(targetPos, 0.2, 0.2, 0.2)
|
||||
nearby.filterIsInstance<org.bukkit.entity.ItemDisplay>().forEach { it.remove() }
|
||||
// Search for entity within strict block bounds
|
||||
val nearby = world.getNearbyEntities(center, 0.45, 0.45, 0.45)
|
||||
nearby.filterIsInstance<org.bukkit.entity.ItemDisplay>()
|
||||
.filter { it.scoreboardTags.contains("shop_display") }
|
||||
.forEach { entity ->
|
||||
if (shopId == null) {
|
||||
entity.remove() // Wipe all
|
||||
} else {
|
||||
val storedId = entity.persistentDataContainer.get(key, org.bukkit.persistence.PersistentDataType.STRING)
|
||||
if (storedId == shopId.toString()) {
|
||||
entity.remove() // Target match
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun yawFromBlockFace(face: org.bukkit.block.BlockFace): Float {
|
||||
|
|
|
|||
|
|
@ -37,16 +37,47 @@ object ShopCommands {
|
|||
defaultValue = org.bukkit.permissions.PermissionDefault.OP
|
||||
}
|
||||
|
||||
// Logic for /shop give (No tier specified, default 1)
|
||||
// Logic for /shop give (No arguments -> Oak, Tier 1)
|
||||
executes {
|
||||
giveShopSign(plugin, sender, 1, tierKey)
|
||||
giveShopSign(plugin, sender, 1, tierKey, Material.OAK_SIGN)
|
||||
}
|
||||
|
||||
// Logic for /shop give <tier>
|
||||
// Logic for /shop give <tier> (Default Oak)
|
||||
integer("tier", min = 1, max = 5) {
|
||||
executes {
|
||||
val tier: Int = argument("tier")
|
||||
giveShopSign(plugin, sender, tier, tierKey)
|
||||
giveShopSign(plugin, sender, tier, tierKey, Material.OAK_SIGN)
|
||||
}
|
||||
}
|
||||
|
||||
// Logic for /shop give <type> [tier]
|
||||
string("type") {
|
||||
suggests {
|
||||
listOf("oak", "birch", "spruce", "jungle", "acacia", "dark_oak", "mangrove", "cherry", "bamboo", "crimson", "warped", "pale")
|
||||
}
|
||||
executes {
|
||||
val typeName: String = argument("type")
|
||||
val material = net.hareworks.hcu.shop.ShopVisuals.getSignMaterial(typeName)
|
||||
|
||||
if (material != null) {
|
||||
giveShopSign(plugin, sender, 1, tierKey, material)
|
||||
} else {
|
||||
sender.sendMessage(Component.text("Invalid sign type: $typeName", NamedTextColor.RED))
|
||||
}
|
||||
}
|
||||
|
||||
integer("tier", min = 1, max = 5) {
|
||||
executes {
|
||||
val typeName: String = argument("type")
|
||||
val tier: Int = argument("tier")
|
||||
val material = net.hareworks.hcu.shop.ShopVisuals.getSignMaterial(typeName)
|
||||
|
||||
if (material != null) {
|
||||
giveShopSign(plugin, sender, tier, tierKey, material)
|
||||
} else {
|
||||
sender.sendMessage(Component.text("Invalid sign type: $typeName", NamedTextColor.RED))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -81,13 +112,13 @@ object ShopCommands {
|
|||
}
|
||||
}
|
||||
|
||||
private fun giveShopSign(plugin: JavaPlugin, sender: org.bukkit.command.CommandSender, tier: Int, key: NamespacedKey) {
|
||||
private fun giveShopSign(plugin: JavaPlugin, sender: org.bukkit.command.CommandSender, tier: Int, key: NamespacedKey, signType: Material) {
|
||||
if (sender !is Player) {
|
||||
sender.sendMessage(Component.text("Only players can use this command.", NamedTextColor.RED))
|
||||
return
|
||||
}
|
||||
|
||||
val signItem = ItemStack(Material.OAK_SIGN)
|
||||
val signItem = ItemStack(signType)
|
||||
val meta = signItem.itemMeta
|
||||
|
||||
meta.displayName(Component.text("Shop Sign (Tier $tier)").color(NamedTextColor.GOLD))
|
||||
|
|
@ -96,7 +127,7 @@ object ShopCommands {
|
|||
signItem.itemMeta = meta
|
||||
|
||||
sender.inventory.addItem(signItem)
|
||||
sender.sendMessage(Component.text("Given Shop Sign Tier $tier", NamedTextColor.GREEN))
|
||||
sender.sendMessage(Component.text("Given Shop Sign Tier $tier (${signType.name.lowercase()})", NamedTextColor.GREEN))
|
||||
}
|
||||
|
||||
private fun displayShopList(plugin: ShopPlugin, player: Player) {
|
||||
|
|
@ -150,10 +181,10 @@ object ShopCommands {
|
|||
val world = org.bukkit.Bukkit.getWorld(shop.worldUid)
|
||||
if (world != null) {
|
||||
val location = org.bukkit.Location(world, shop.x.toDouble(), shop.y.toDouble(), shop.z.toDouble())
|
||||
net.hareworks.hcu.shop.ShopVisuals.removeDisplay(location, shop.face)
|
||||
net.hareworks.hcu.shop.ShopVisuals.removeDisplay(plugin, location, shop.id)
|
||||
|
||||
val block = location.block
|
||||
if (block.type == Material.OAK_SIGN) {
|
||||
if (net.hareworks.hcu.shop.ShopVisuals.isShopSign(block.type)) {
|
||||
// Check for other shops at this location
|
||||
val otherFace = if (shop.face == "FRONT") "BACK" else "FRONT"
|
||||
val otherShop = net.hareworks.hcu.shop.database.ShopRepository.findByLocationAndFace(location, otherFace)
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
// Check if it is a shop sign
|
||||
val tier = meta.persistentDataContainer.get(tierKey, PersistentDataType.INTEGER) ?: return
|
||||
|
||||
// Check block type (Standing Sign)
|
||||
if (event.blockPlaced.type != Material.OAK_SIGN) {
|
||||
// Check block type (Standing Sign, Wall Sign, Hanging Sign)
|
||||
if (!ShopVisuals.isShopSign(event.blockPlaced.type)) {
|
||||
event.isCancelled = true
|
||||
return
|
||||
}
|
||||
|
|
@ -99,13 +99,21 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
)
|
||||
plugin.logger.info("Front shop created: ${frontShop != null} (ID: ${frontShop?.id})")
|
||||
|
||||
// Create BACK shop
|
||||
val backShop = ShopRepository.create(
|
||||
// Create BACK shop handling
|
||||
val backShop = if (!ShopVisuals.isWallSign(event.blockPlaced.type)) {
|
||||
ShopRepository.create(
|
||||
actorId = actorId,
|
||||
location = event.blockPlaced.location,
|
||||
face = "BACK"
|
||||
)
|
||||
plugin.logger.info("Back shop created: ${backShop != null} (ID: ${backShop?.id})")
|
||||
} else {
|
||||
null // Wall signs don't have a back shop
|
||||
}
|
||||
if (backShop != null) {
|
||||
plugin.logger.info("Back shop created: (ID: ${backShop.id})")
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Close UI and Update Visuals (Delayed to override client-side editor opening)
|
||||
// Close UI immediately (Next tick)
|
||||
|
|
@ -128,10 +136,17 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
plugin.logger.info("Updating BACK sign.")
|
||||
ShopVisuals.updateSign(plugin, event.blockPlaced, backShop, Side.BACK)
|
||||
} else {
|
||||
plugin.logger.warning("Back shop was null in delayed task.")
|
||||
// For wall signs, back shop is null is expected
|
||||
}
|
||||
|
||||
// Spawn Displays Only for Standard Standing Signs
|
||||
// User requested "DisplayEntity無しで" for the new types (Wall/Hanging)
|
||||
// Existing Standing Signs logic uses Rotatable (which Wall/Hanging might not fully support in spawnDisplays logic)
|
||||
// So restrict to Standing Signs (Rotatable && !Wall && !Hanging)
|
||||
val type = event.blockPlaced.type
|
||||
if (!ShopVisuals.isWallSign(type) && !ShopVisuals.isHangingSign(type)) {
|
||||
spawnDisplays(event.blockPlaced)
|
||||
}
|
||||
}, 1L)
|
||||
}
|
||||
}
|
||||
|
|
@ -141,60 +156,124 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
val data = block.blockData as? Rotatable ?: return
|
||||
val rotation = data.rotation // BlockFace
|
||||
|
||||
val yaw = ShopVisuals.yawFromBlockFace(rotation) + 90f
|
||||
// Keys
|
||||
val shopIdKey = org.bukkit.NamespacedKey(plugin, "shop_id")
|
||||
|
||||
// Calculate offsets relative to center (0.5, 0, 0.5)
|
||||
// Original request assumes 0,0,0 is block origin.
|
||||
// Front: 0.75 0.25 0.5 -> Rel: 0.25, 0.25, 0.0
|
||||
// Back: 0.25 0.25 0.5 -> Rel: -0.25, 0.25, 0.0
|
||||
// Find Shops
|
||||
val frontShop = net.hareworks.hcu.shop.database.ShopRepository.findByLocationAndFace(origin, "FRONT")
|
||||
val backShop = net.hareworks.hcu.shop.database.ShopRepository.findByLocationAndFace(origin, "BACK")
|
||||
|
||||
val frontOffset = Vector3f(0.25f, 0.25f, 0.0f)
|
||||
val backOffset = Vector3f(-0.25f, 0.25f, 0.0f)
|
||||
val rawYaw = ShopVisuals.yawFromBlockFace(rotation)
|
||||
|
||||
// Rotate offsets
|
||||
|
||||
val rad = Math.toRadians(yaw.toDouble())
|
||||
frontOffset.rotateY(-rad.toFloat())
|
||||
backOffset.rotateY(-rad.toFloat())
|
||||
|
||||
// Final positions
|
||||
// Final positions (No offsets, just center of block)
|
||||
val center = origin.clone().add(0.5, 0.0, 0.5)
|
||||
val frontPos = center.clone().add(frontOffset.x.toDouble(), frontOffset.y.toDouble(), frontOffset.z.toDouble())
|
||||
val backPos = center.clone().add(backOffset.x.toDouble(), backOffset.y.toDouble(), backOffset.z.toDouble())
|
||||
|
||||
val world = block.world
|
||||
|
||||
// Spawn Front
|
||||
// Check existing entities in block area
|
||||
// Search at center of block (0.5, 0.5, 0.5)
|
||||
val blockCenter = origin.clone().add(0.5, 0.5, 0.5)
|
||||
val existing = world.getNearbyEntities(blockCenter, 0.45, 0.45, 0.45)
|
||||
.filterIsInstance<ItemDisplay>()
|
||||
.filter { it.scoreboardTags.contains("shop_display") }
|
||||
|
||||
// --- FRONT ---
|
||||
if (frontShop != null) {
|
||||
val frontPos = center.clone().add( // Recalculate Front Pos for spawning if needed (though now we use center... wait, step 178 restored offsets?)
|
||||
// Step 178 restored offsets. I need to keep that logic if I want positions.
|
||||
// Re-reading Step 178: "Final positions ... frontPos ... backPos"
|
||||
// My previous spawnDisplays (Step 255) used frontPos/backPos.
|
||||
// I need to calculate them here again.
|
||||
0.0, 0.0, 0.0 // Placeholder, will fix below
|
||||
)
|
||||
// recalculate offsets
|
||||
val yawForOffset = rawYaw + 90f
|
||||
val frontOffset = Vector3f(0.25f, 0.25f, 0.0f)
|
||||
val rad = Math.toRadians(yawForOffset.toDouble())
|
||||
frontOffset.rotateY(-rad.toFloat())
|
||||
frontPos.set(center.x + frontOffset.x, center.y + frontOffset.y, center.z + frontOffset.z)
|
||||
|
||||
val existingEntity = existing.find {
|
||||
it.persistentDataContainer.get(shopIdKey, org.bukkit.persistence.PersistentDataType.STRING) == frontShop.id.toString()
|
||||
}
|
||||
|
||||
val itemStack = frontShop.item ?: ItemStack(Material.AIR)
|
||||
|
||||
if (existingEntity != null) {
|
||||
// Update
|
||||
existingEntity.setItemStack(itemStack)
|
||||
} else {
|
||||
// Spawn
|
||||
world.spawn(frontPos, ItemDisplay::class.java) { display ->
|
||||
display.setRotation(yaw, 0f)
|
||||
display.setItemDisplayTransform(org.bukkit.entity.ItemDisplay.ItemDisplayTransform.FIXED)
|
||||
display.setRotation(rawYaw, 0f)
|
||||
|
||||
// Transformation
|
||||
val left = Quaternionf(0.0f, -0.7071068f, 0.0f, 0.7071068f)
|
||||
val right = Quaternionf(0.0f, 0.0f, 0.0f, 1.0f)
|
||||
val scale = Vector3f(0.5f, 0.5f, 0.5f)
|
||||
val left = Quaternionf()
|
||||
val right = Quaternionf()
|
||||
val scale = Vector3f(1.0f, 1.0f, 1.0f)
|
||||
val translation = Vector3f(0.0f, 0.0f, 0.0f)
|
||||
|
||||
display.addScoreboardTag("shop_display")
|
||||
display.persistentDataContainer.set(shopIdKey, org.bukkit.persistence.PersistentDataType.STRING, frontShop.id.toString())
|
||||
|
||||
display.setTransformation(Transformation(translation, left, scale, right))
|
||||
display.interpolationDuration = 0
|
||||
|
||||
// Add custom tag or PDC to link to sign if needed?
|
||||
display.setItemStack(itemStack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn Back
|
||||
// --- BACK ---
|
||||
if (backShop != null) {
|
||||
// recalculate offsets
|
||||
val yawForOffset = rawYaw + 90f
|
||||
val backOffset = Vector3f(-0.25f, 0.25f, 0.0f)
|
||||
val rad = Math.toRadians(yawForOffset.toDouble())
|
||||
backOffset.rotateY(-rad.toFloat())
|
||||
val backPos = center.clone().add(backOffset.x.toDouble(), backOffset.y.toDouble(), backOffset.z.toDouble())
|
||||
|
||||
val existingEntity = existing.find {
|
||||
it.persistentDataContainer.get(shopIdKey, org.bukkit.persistence.PersistentDataType.STRING) == backShop.id.toString()
|
||||
}
|
||||
|
||||
val itemStack = backShop.item ?: ItemStack(Material.AIR)
|
||||
|
||||
if (existingEntity != null) {
|
||||
// Update
|
||||
existingEntity.setItemStack(itemStack)
|
||||
} else {
|
||||
// Spawn
|
||||
world.spawn(backPos, ItemDisplay::class.java) { display ->
|
||||
// display.setItemStack(ItemStack(Material.AIR)) // Default empty
|
||||
display.setRotation(yaw - 90f, 0f)
|
||||
display.setItemDisplayTransform(org.bukkit.entity.ItemDisplay.ItemDisplayTransform.FIXED)
|
||||
display.setRotation(rawYaw + 180f, 0f)
|
||||
|
||||
// Transformation
|
||||
val left = Quaternionf(0.0f, 1.0f, 0.0f, 0.0f)
|
||||
val right = Quaternionf(0.0f, 0.0f, 0.0f, 1.0f)
|
||||
val scale = Vector3f(0.5f, 0.5f, 0.5f)
|
||||
val left = Quaternionf()
|
||||
val right = Quaternionf()
|
||||
val scale = Vector3f(1.0f, 1.0f, 1.0f)
|
||||
val translation = Vector3f(0.0f, 0.0f, 0.0f)
|
||||
|
||||
display.addScoreboardTag("shop_display")
|
||||
display.persistentDataContainer.set(shopIdKey, org.bukkit.persistence.PersistentDataType.STRING, backShop.id.toString())
|
||||
|
||||
display.setTransformation(Transformation(translation, left, scale, right))
|
||||
display.interpolationDuration = 0
|
||||
|
||||
display.setItemStack(itemStack)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun updateShopDisplay(shopData: net.hareworks.hcu.shop.database.ShopData) {
|
||||
val world = org.bukkit.Bukkit.getWorld(shopData.worldUid) ?: return
|
||||
val block = world.getBlockAt(shopData.x, shopData.y, shopData.z)
|
||||
|
||||
// Spawn/Update displays
|
||||
spawnDisplays(block)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onSignChange(event: SignChangeEvent) {
|
||||
|
|
@ -275,15 +354,61 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
// Check if shop sign
|
||||
if (!state.persistentDataContainer.has(tierKey, PersistentDataType.INTEGER)) return
|
||||
|
||||
// Determine Face (Front/Back)
|
||||
val data = block.blockData as? Rotatable ?: return
|
||||
val rotation = data.rotation
|
||||
val clickedFace = event.blockFace
|
||||
// Use Player vs Block relative position
|
||||
val playerLoc = event.player.location
|
||||
val blockCenter = block.location.add(0.5, 0.5, 0.5)
|
||||
val vectorToPlayer = playerLoc.toVector().subtract(blockCenter.toVector())
|
||||
|
||||
val face = when (clickedFace) {
|
||||
rotation -> "FRONT"
|
||||
rotation.oppositeFace -> "BACK"
|
||||
else -> return // Clicked side/top/bottom, ignore or handle? Ignoring for now.
|
||||
var face = "FRONT"
|
||||
|
||||
// Handle Directional vs Rotatable
|
||||
// Standard Standing Sign: Rotatable
|
||||
// Wall Sign: Directional
|
||||
// Hanging Sign (Ceiling): Rotatable (but different?) -> It is Rotatable.
|
||||
// Hanging Sign (Wall): Directional
|
||||
|
||||
val bData = block.blockData
|
||||
val forwardVector: org.bukkit.util.Vector
|
||||
|
||||
if (bData is org.bukkit.block.data.Directional) {
|
||||
// Wall Sign / Wall Hanging Sign
|
||||
val facing = bData.facing // The direction the text faces (usually)
|
||||
// Create vector from facing
|
||||
forwardVector = facing.direction
|
||||
|
||||
// Dot product
|
||||
val dot = vectorToPlayer.normalize().dot(forwardVector)
|
||||
|
||||
// For Wall Signs (Strict), Back is impossible/invalid.
|
||||
// If dot < 0 (Behind), it means player is inside the wall? Or side?
|
||||
// User said: "Wall signs: Back unclickable".
|
||||
|
||||
if (dot > 0) {
|
||||
face = "FRONT"
|
||||
} else {
|
||||
face = "BACK"
|
||||
// If it is strictly a Wall Sign (not hanging), BACK is disabled.
|
||||
if (ShopVisuals.isWallSign(block.type)) {
|
||||
// Ignore click
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
} else if (bData is Rotatable) {
|
||||
// Standing Sign / Ceiling Hanging Sign
|
||||
val rotation = bData.rotation
|
||||
val signYaw = ShopVisuals.yawFromBlockFace(rotation)
|
||||
val rad = Math.toRadians(signYaw.toDouble())
|
||||
// Sign Yaw 0 = South (0,1).
|
||||
val signDirX = -Math.sin(rad)
|
||||
val signDirZ = Math.cos(rad)
|
||||
forwardVector = org.bukkit.util.Vector(signDirX, 0.0, signDirZ)
|
||||
|
||||
val dot = vectorToPlayer.normalize().dot(forwardVector)
|
||||
face = if (dot > 0) "FRONT" else "BACK"
|
||||
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
// Check Owner
|
||||
|
|
@ -363,7 +488,7 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
|
||||
// Check for Shop Sign above
|
||||
val signBlock = block.getRelative(BlockFace.UP)
|
||||
if (signBlock.type != Material.OAK_SIGN) return
|
||||
if (!ShopVisuals.isShopSign(signBlock.type)) return
|
||||
|
||||
val state = signBlock.state as? Sign ?: return
|
||||
if (!state.persistentDataContainer.has(tierKey, PersistentDataType.INTEGER)) return
|
||||
|
|
@ -491,7 +616,7 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
updateShopDisplay(updatedShop)
|
||||
val world = org.bukkit.Bukkit.getWorld(updatedShop.worldUid)
|
||||
val block = world?.getBlockAt(updatedShop.x, updatedShop.y, updatedShop.z)
|
||||
if (block != null && block.type == Material.OAK_SIGN) {
|
||||
if (block != null && ShopVisuals.isShopSign(block.type)) {
|
||||
val side = if (updatedShop.face == "FRONT") Side.FRONT else Side.BACK
|
||||
ShopVisuals.updateSign(plugin, block, updatedShop, side)
|
||||
}
|
||||
|
|
@ -517,7 +642,7 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
updateShopDisplay(updatedShop)
|
||||
val world = org.bukkit.Bukkit.getWorld(updatedShop.worldUid)
|
||||
val block = world?.getBlockAt(updatedShop.x, updatedShop.y, updatedShop.z)
|
||||
if (block != null && block.type == Material.OAK_SIGN) {
|
||||
if (block != null && ShopVisuals.isShopSign(block.type)) {
|
||||
val side = if (updatedShop.face == "FRONT") Side.FRONT else Side.BACK
|
||||
ShopVisuals.updateSign(plugin, block, updatedShop, side)
|
||||
}
|
||||
|
|
@ -560,7 +685,7 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
shopData.z.toDouble()
|
||||
)
|
||||
val block = location.block
|
||||
if (block.type != Material.OAK_SIGN) return
|
||||
if (!ShopVisuals.isShopSign(block.type)) return
|
||||
|
||||
val sign = block.state as? Sign ?: return
|
||||
|
||||
|
|
@ -595,7 +720,7 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
// Handle Container Break Protection
|
||||
if (block.type in ShopVisuals.VALID_CONTAINERS) {
|
||||
val signBlock = block.getRelative(BlockFace.UP)
|
||||
if (signBlock.type == Material.OAK_SIGN) {
|
||||
if (ShopVisuals.isShopSign(signBlock.type)) {
|
||||
val state = signBlock.state as? Sign
|
||||
if (state != null && state.persistentDataContainer.has(tierKey, PersistentDataType.INTEGER)) {
|
||||
event.isCancelled = true
|
||||
|
|
@ -606,7 +731,7 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
}
|
||||
|
||||
// Handle Shop Sign Break
|
||||
if (block.type != Material.OAK_SIGN) return
|
||||
if (!ShopVisuals.isShopSign(block.type)) return
|
||||
|
||||
val state = block.state as? Sign ?: return
|
||||
if (!state.persistentDataContainer.has(tierKey, PersistentDataType.INTEGER)) return
|
||||
|
|
@ -635,50 +760,24 @@ class ShopListener(private val plugin: ShopPlugin) : Listener {
|
|||
// Delete Shops
|
||||
if (frontShop != null) {
|
||||
ShopRepository.delete(frontShop.id)
|
||||
ShopVisuals.removeDisplay(location, "FRONT")
|
||||
ShopVisuals.removeDisplay(plugin, location, frontShop.id)
|
||||
}
|
||||
|
||||
if (backShop != null) {
|
||||
ShopRepository.delete(backShop.id)
|
||||
ShopVisuals.removeDisplay(location, "BACK")
|
||||
ShopVisuals.removeDisplay(plugin, location, backShop.id)
|
||||
}
|
||||
|
||||
event.player.sendMessage(Component.text("Shop removed.", NamedTextColor.GREEN))
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun updateShopDisplay(shopData: net.hareworks.hcu.shop.database.ShopData) {
|
||||
val world = org.bukkit.Bukkit.getWorld(shopData.worldUid) ?: return
|
||||
val block = world.getBlockAt(shopData.x, shopData.y, shopData.z)
|
||||
|
||||
// Ensure block is still a sign and rotatable
|
||||
val data = block.blockData as? Rotatable ?: return
|
||||
val rotation = data.rotation
|
||||
|
||||
val yaw = ShopVisuals.yawFromBlockFace(rotation) + 90f
|
||||
|
||||
val offset = if (shopData.face == "FRONT") Vector3f(0.25f, 0.25f, 0.0f) else Vector3f(-0.25f, 0.25f, 0.0f)
|
||||
val rad = Math.toRadians(yaw.toDouble())
|
||||
offset.rotateY(-rad.toFloat())
|
||||
|
||||
val center = block.location.clone().add(0.5, 0.0, 0.5)
|
||||
val targetPos = center.clone().add(offset.x.toDouble(), offset.y.toDouble(), offset.z.toDouble())
|
||||
|
||||
// Search for entity
|
||||
val nearby = world.getNearbyEntities(targetPos, 0.2, 0.2, 0.2)
|
||||
val display = nearby.filterIsInstance<ItemDisplay>().firstOrNull()
|
||||
|
||||
if (display != null) {
|
||||
if (shopData.item != null) {
|
||||
display.setItemStack(shopData.item)
|
||||
} else {
|
||||
display.setItemStack(ItemStack(Material.AIR))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
object ShopGuiMap {
|
||||
val openInvs = java.util.WeakHashMap<Inventory, Int>()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user