diff --git a/.gitignore b/.gitignore index 1b6985c..8e774d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -# Ignore Gradle project-specific cache directory .gradle - -# Ignore Gradle build output directory +bin build diff --git a/main/kotlin/net/hareworks/ghostdisplays/GhostDisplaysPlugin.kt b/src/main/kotlin/net/hareworks/ghostdisplays/GhostDisplaysPlugin.kt similarity index 93% rename from main/kotlin/net/hareworks/ghostdisplays/GhostDisplaysPlugin.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/GhostDisplaysPlugin.kt index d5942b0..98042a4 100644 --- a/main/kotlin/net/hareworks/ghostdisplays/GhostDisplaysPlugin.kt +++ b/src/main/kotlin/net/hareworks/ghostdisplays/GhostDisplaysPlugin.kt @@ -39,6 +39,12 @@ class GhostDisplaysPlugin : JavaPlugin() { instance = this logger.info("GhostDisplays ready: ${displayRegistry.controllerCount()} controllers active.") + + server.scheduler.runTaskTimer(this, Runnable { + server.onlinePlayers.forEach { player -> + displayRegistry.refreshAudiences(player) + } + }, 20L, 20L) } override fun onDisable() { diff --git a/main/kotlin/net/hareworks/ghostdisplays/api/DisplayController.kt b/src/main/kotlin/net/hareworks/ghostdisplays/api/DisplayController.kt similarity index 100% rename from main/kotlin/net/hareworks/ghostdisplays/api/DisplayController.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/api/DisplayController.kt diff --git a/main/kotlin/net/hareworks/ghostdisplays/api/DisplayService.kt b/src/main/kotlin/net/hareworks/ghostdisplays/api/DisplayService.kt similarity index 100% rename from main/kotlin/net/hareworks/ghostdisplays/api/DisplayService.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/api/DisplayService.kt diff --git a/main/kotlin/net/hareworks/ghostdisplays/api/InteractionOptions.kt b/src/main/kotlin/net/hareworks/ghostdisplays/api/InteractionOptions.kt similarity index 100% rename from main/kotlin/net/hareworks/ghostdisplays/api/InteractionOptions.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/api/InteractionOptions.kt diff --git a/main/kotlin/net/hareworks/ghostdisplays/api/audience/AudiencePredicate.kt b/src/main/kotlin/net/hareworks/ghostdisplays/api/audience/AudiencePredicate.kt similarity index 100% rename from main/kotlin/net/hareworks/ghostdisplays/api/audience/AudiencePredicate.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/api/audience/AudiencePredicate.kt diff --git a/main/kotlin/net/hareworks/ghostdisplays/api/audience/AudiencePredicates.kt b/src/main/kotlin/net/hareworks/ghostdisplays/api/audience/AudiencePredicates.kt similarity index 100% rename from main/kotlin/net/hareworks/ghostdisplays/api/audience/AudiencePredicates.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/api/audience/AudiencePredicates.kt diff --git a/main/kotlin/net/hareworks/ghostdisplays/api/click/DisplayClick.kt b/src/main/kotlin/net/hareworks/ghostdisplays/api/click/DisplayClick.kt similarity index 100% rename from main/kotlin/net/hareworks/ghostdisplays/api/click/DisplayClick.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/api/click/DisplayClick.kt diff --git a/main/kotlin/net/hareworks/ghostdisplays/command/CommandRegistrar.kt b/src/main/kotlin/net/hareworks/ghostdisplays/command/CommandRegistrar.kt similarity index 86% rename from main/kotlin/net/hareworks/ghostdisplays/command/CommandRegistrar.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/command/CommandRegistrar.kt index a432e09..6bb7d56 100644 --- a/main/kotlin/net/hareworks/ghostdisplays/command/CommandRegistrar.kt +++ b/src/main/kotlin/net/hareworks/ghostdisplays/command/CommandRegistrar.kt @@ -111,6 +111,9 @@ object CommandRegistrar { literal("delete") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } executes { val id = argument("id") try { @@ -139,6 +142,9 @@ object CommandRegistrar { literal("info") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } executes { val id = argument("id") val display = manager.findDisplay(id) @@ -161,6 +167,9 @@ object CommandRegistrar { literal("viewer") { literal("add") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } players("targets") { executes { val id = argument("id") @@ -177,6 +186,9 @@ object CommandRegistrar { } literal("remove") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } players("targets") { executes { val id = argument("id") @@ -193,6 +205,9 @@ object CommandRegistrar { } literal("clear") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } executes { val id = argument("id") try { @@ -209,6 +224,12 @@ object CommandRegistrar { literal("text") { literal("edit") { string("id") { + suggests { prefix -> + manager.listDisplays() + .filter { it.kind == DisplayKind.TEXT } + .map { it.id } + .filter { it.startsWith(prefix, ignoreCase = true) } + } executes { val player = sender.requirePlayer() ?: return@executes val id = argument("id") @@ -224,6 +245,12 @@ object CommandRegistrar { } literal("set") { string("id") { + suggests { prefix -> + manager.listDisplays() + .filter { it.kind == DisplayKind.TEXT } + .map { it.id } + .filter { it.startsWith(prefix, ignoreCase = true) } + } string("content") { executes { val id = argument("id") @@ -254,6 +281,12 @@ object CommandRegistrar { literal("block") { literal("set") { string("id") { + suggests { prefix -> + manager.listDisplays() + .filter { it.kind == DisplayKind.BLOCK } + .map { it.id } + .filter { it.startsWith(prefix, ignoreCase = true) } + } string("state") { executes { val id = argument("id") @@ -276,6 +309,12 @@ object CommandRegistrar { literal("item") { literal("set") { string("id") { + suggests { prefix -> + manager.listDisplays() + .filter { it.kind == DisplayKind.ITEM } + .map { it.id } + .filter { it.startsWith(prefix, ignoreCase = true) } + } string("material") { executes { val id = argument("id") @@ -301,6 +340,9 @@ object CommandRegistrar { literal("permission") { literal("add") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } string("permission") { executes { val id = argument("id") @@ -317,6 +359,9 @@ object CommandRegistrar { } literal("remove") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } string("permission") { executes { val id = argument("id") @@ -337,6 +382,9 @@ object CommandRegistrar { literal("near") { literal("set") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } float("radius", min = 1.0) { executes { val id = argument("id") @@ -354,6 +402,9 @@ object CommandRegistrar { } literal("clear") { string("id") { + suggests { prefix -> + manager.listDisplays().map { it.id }.filter { it.startsWith(prefix, ignoreCase = true) } + } executes { val id = argument("id") try { @@ -379,8 +430,11 @@ private fun CommandSender.showUsage() { info(" /ghostdisplay list | info | delete ") } -private fun Player.anchorLocation(): Location = - eyeLocation.clone().add(direction.normalize().multiply(1.5)) +private fun Player.anchorLocation(): Location { + val eye = eyeLocation.clone() + val forward = eye.direction.normalize().multiply(1.5) + return eye.add(forward) +} private fun parseBlockData(state: String): BlockData = Bukkit.createBlockData(state) diff --git a/main/kotlin/net/hareworks/ghostdisplays/display/DisplayManager.kt b/src/main/kotlin/net/hareworks/ghostdisplays/display/DisplayManager.kt similarity index 98% rename from main/kotlin/net/hareworks/ghostdisplays/display/DisplayManager.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/display/DisplayManager.kt index 41348d9..4e2fa31 100644 --- a/main/kotlin/net/hareworks/ghostdisplays/display/DisplayManager.kt +++ b/src/main/kotlin/net/hareworks/ghostdisplays/display/DisplayManager.kt @@ -79,7 +79,7 @@ class DisplayManager( ensureIdAvailable(normalized) val safeLocation = location.clone() val controller = service.createItemDisplay(safeLocation, itemStack.clone(), INTERACTION_DEFAULT) - controller.applyEntityUpdate { it.itemStack = itemStack.clone() } + controller.applyEntityUpdate { it.setItemStack(itemStack.clone()) } val managed = ManagedDisplay.Item( id = normalized, controller = controller, @@ -115,7 +115,7 @@ class DisplayManager( fun updateItem(id: String, itemStack: ItemStack) { val display = requireItem(id) val clone = itemStack.clone() - display.controller.applyEntityUpdate { it.itemStack = clone } + display.controller.applyEntityUpdate { it.setItemStack(clone) } display.itemStack = clone } diff --git a/main/kotlin/net/hareworks/ghostdisplays/display/EditSessionManager.kt b/src/main/kotlin/net/hareworks/ghostdisplays/display/EditSessionManager.kt similarity index 96% rename from main/kotlin/net/hareworks/ghostdisplays/display/EditSessionManager.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/display/EditSessionManager.kt index ba5979c..363b2bd 100644 --- a/main/kotlin/net/hareworks/ghostdisplays/display/EditSessionManager.kt +++ b/src/main/kotlin/net/hareworks/ghostdisplays/display/EditSessionManager.kt @@ -37,7 +37,7 @@ class EditSessionManager( event.player.sendMessage("GhostDisplays: editing for '$displayId' cancelled.") return } - Bukkit.getScheduler().runTask(plugin) { + Bukkit.getScheduler().runTask(plugin, Runnable { try { manager.updateText(displayId, message) event.player.sendMessage("GhostDisplays: updated text for '$displayId'.") @@ -46,7 +46,7 @@ class EditSessionManager( } finally { sessions.remove(event.player.uniqueId) } - } + }) } @EventHandler diff --git a/main/kotlin/net/hareworks/ghostdisplays/display/ManagedDisplay.kt b/src/main/kotlin/net/hareworks/ghostdisplays/display/ManagedDisplay.kt similarity index 100% rename from main/kotlin/net/hareworks/ghostdisplays/display/ManagedDisplay.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/display/ManagedDisplay.kt diff --git a/main/kotlin/net/hareworks/ghostdisplays/internal/DefaultDisplayService.kt b/src/main/kotlin/net/hareworks/ghostdisplays/internal/DefaultDisplayService.kt similarity index 96% rename from main/kotlin/net/hareworks/ghostdisplays/internal/DefaultDisplayService.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/internal/DefaultDisplayService.kt index 2e329f7..1a88a76 100644 --- a/main/kotlin/net/hareworks/ghostdisplays/internal/DefaultDisplayService.kt +++ b/src/main/kotlin/net/hareworks/ghostdisplays/internal/DefaultDisplayService.kt @@ -46,7 +46,7 @@ internal class DefaultDisplayService( interaction: InteractionOptions, builder: ItemDisplay.() -> Unit ): DisplayController = spawnDisplay(location, ItemDisplay::class.java, interaction) { - it.itemStack = itemStack.clone() + it.setItemStack(itemStack.clone()) builder(it) } @@ -94,7 +94,7 @@ internal class DefaultDisplayService( action() } else { val future = CompletableFuture() - Bukkit.getScheduler().runTask(plugin) { future.complete(action()) } + Bukkit.getScheduler().runTask(plugin, Runnable { future.complete(action()) }) future.join() } } diff --git a/main/kotlin/net/hareworks/ghostdisplays/internal/controller/BaseDisplayController.kt b/src/main/kotlin/net/hareworks/ghostdisplays/internal/controller/BaseDisplayController.kt similarity index 97% rename from main/kotlin/net/hareworks/ghostdisplays/internal/controller/BaseDisplayController.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/internal/controller/BaseDisplayController.kt index 5ed0dda..1b4d336 100644 --- a/main/kotlin/net/hareworks/ghostdisplays/internal/controller/BaseDisplayController.kt +++ b/src/main/kotlin/net/hareworks/ghostdisplays/internal/controller/BaseDisplayController.kt @@ -64,7 +64,6 @@ internal class BaseDisplayController( override fun applyEntityUpdate(mutator: (T) -> Unit) { callSync { mutator(display) - display.updateDisplay(false) } } @@ -143,7 +142,7 @@ internal class BaseDisplayController( if (Bukkit.isPrimaryThread()) { action() } else { - Bukkit.getScheduler().runTask(plugin, action) + Bukkit.getScheduler().runTask(plugin, Runnable { action() }) } } @@ -152,7 +151,7 @@ internal class BaseDisplayController( action() } else { val future = CompletableFuture() - Bukkit.getScheduler().runTask(plugin) { future.complete(action()) } + Bukkit.getScheduler().runTask(plugin, Runnable { future.complete(action()) }) future.join() } } diff --git a/main/kotlin/net/hareworks/ghostdisplays/internal/controller/DisplayRegistry.kt b/src/main/kotlin/net/hareworks/ghostdisplays/internal/controller/DisplayRegistry.kt similarity index 98% rename from main/kotlin/net/hareworks/ghostdisplays/internal/controller/DisplayRegistry.kt rename to src/main/kotlin/net/hareworks/ghostdisplays/internal/controller/DisplayRegistry.kt index 39f0c6d..4c2cb7d 100644 --- a/main/kotlin/net/hareworks/ghostdisplays/internal/controller/DisplayRegistry.kt +++ b/src/main/kotlin/net/hareworks/ghostdisplays/internal/controller/DisplayRegistry.kt @@ -76,7 +76,7 @@ internal class DisplayRegistry : Listener { private fun controllersSnapshot(): Collection> = displayControllers.values.toSet() - private fun refreshAudiences(player: Player) { + internal fun refreshAudiences(player: Player) { val controllers = controllersSnapshot() if (controllers.isEmpty()) return controllers.forEach { it.refreshAudience(player) }