From 65b3cfd8e23da99fa269e90a770ce95490a6b91b Mon Sep 17 00:00:00 2001 From: Hare Date: Sat, 20 Dec 2025 06:05:47 +0900 Subject: [PATCH] =?UTF-8?q?=E7=9C=8B=E6=9D=BF=E7=B4=A0=E6=9D=90=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C=E3=83=BB=E3=82=AF=E3=83=AA=E3=83=83=E3=82=AF=E6=96=B9?= =?UTF-8?q?=E5=90=91=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../net/hareworks/hcu/shop/ShopVisuals.kt | 86 ++++- .../hcu/shop/command/ShopCommands.kt | 49 ++- .../hcu/shop/listeners/ShopListener.kt | 301 ++++++++++++------ 3 files changed, 312 insertions(+), 124 deletions(-) diff --git a/src/main/kotlin/net/hareworks/hcu/shop/ShopVisuals.kt b/src/main/kotlin/net/hareworks/hcu/shop/ShopVisuals.kt index f39ef97..e3c6215 100644 --- a/src/main/kotlin/net/hareworks/hcu/shop/ShopVisuals.kt +++ b/src/main/kotlin/net/hareworks/hcu/shop/ShopVisuals.kt @@ -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().forEach { it.remove() } + // Search for entity within strict block bounds + val nearby = world.getNearbyEntities(center, 0.45, 0.45, 0.45) + nearby.filterIsInstance() + .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 { diff --git a/src/main/kotlin/net/hareworks/hcu/shop/command/ShopCommands.kt b/src/main/kotlin/net/hareworks/hcu/shop/command/ShopCommands.kt index e0d75ce..c50e588 100644 --- a/src/main/kotlin/net/hareworks/hcu/shop/command/ShopCommands.kt +++ b/src/main/kotlin/net/hareworks/hcu/shop/command/ShopCommands.kt @@ -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 + // Logic for /shop give (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 [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) diff --git a/src/main/kotlin/net/hareworks/hcu/shop/listeners/ShopListener.kt b/src/main/kotlin/net/hareworks/hcu/shop/listeners/ShopListener.kt index c8bb61c..e1a6b4d 100644 --- a/src/main/kotlin/net/hareworks/hcu/shop/listeners/ShopListener.kt +++ b/src/main/kotlin/net/hareworks/hcu/shop/listeners/ShopListener.kt @@ -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( - actorId = actorId, - location = event.blockPlaced.location, - face = "BACK" - ) - plugin.logger.info("Back shop created: ${backShop != null} (ID: ${backShop?.id})") + // Create BACK shop handling + val backShop = if (!ShopVisuals.isWallSign(event.blockPlaced.type)) { + ShopRepository.create( + actorId = actorId, + location = event.blockPlaced.location, + face = "BACK" + ) + } 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 } - spawnDisplays(event.blockPlaced) + // 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 rawYaw = ShopVisuals.yawFromBlockFace(rotation) - val frontOffset = Vector3f(0.25f, 0.25f, 0.0f) - val backOffset = Vector3f(-0.25f, 0.25f, 0.0f) - - // 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 + + // 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() + .filter { it.scoreboardTags.contains("shop_display") } - // Spawn Front - world.spawn(frontPos, ItemDisplay::class.java) { display -> - display.setRotation(yaw, 0f) + // --- 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() + } - // 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 translation = Vector3f(0.0f, 0.0f, 0.0f) - - display.setTransformation(Transformation(translation, left, scale, right)) - display.interpolationDuration = 0 - - // Add custom tag or PDC to link to sign if needed? + val itemStack = frontShop.item ?: ItemStack(Material.AIR) + + if (existingEntity != null) { + // Update + existingEntity.setItemStack(itemStack) + } else { + // Spawn + world.spawn(frontPos, ItemDisplay::class.java) { display -> + display.setItemDisplayTransform(org.bukkit.entity.ItemDisplay.ItemDisplayTransform.FIXED) + display.setRotation(rawYaw, 0f) + + 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 + + display.setItemStack(itemStack) + } + } } - // Spawn Back - world.spawn(backPos, ItemDisplay::class.java) { display -> - // display.setItemStack(ItemStack(Material.AIR)) // Default empty - display.setRotation(yaw - 90f, 0f) + // --- 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() + } - // 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 translation = Vector3f(0.0f, 0.0f, 0.0f) - - display.setTransformation(Transformation(translation, left, scale, right)) - display.interpolationDuration = 0 + val itemStack = backShop.item ?: ItemStack(Material.AIR) + + if (existingEntity != null) { + // Update + existingEntity.setItemStack(itemStack) + } else { + // Spawn + world.spawn(backPos, ItemDisplay::class.java) { display -> + display.setItemDisplayTransform(org.bukkit.entity.ItemDisplay.ItemDisplayTransform.FIXED) + display.setRotation(rawYaw + 180f, 0f) + + 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 - - val face = when (clickedFace) { - rotation -> "FRONT" - rotation.oppositeFace -> "BACK" - else -> return // Clicked side/top/bottom, ignore or handle? Ignoring for now. + // 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()) + + 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().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() }