GhostDisplays/main/kotlin/net/hareworks/ghostdisplays/internal/controller/DisplayRegistry.kt
2025-12-06 04:40:18 +09:00

85 lines
2.9 KiB
Kotlin

package net.hareworks.ghostdisplays.internal.controller
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import net.hareworks.ghostdisplays.api.click.ClickSurface
import org.bukkit.entity.Display
import org.bukkit.entity.Entity
import org.bukkit.entity.Interaction
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerChangedWorldEvent
import org.bukkit.event.player.PlayerInteractEntityEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.event.player.PlayerRespawnEvent
internal class DisplayRegistry : Listener {
private val displayControllers = ConcurrentHashMap<UUID, BaseDisplayController<out Display>>()
private val interactionControllers = ConcurrentHashMap<UUID, BaseDisplayController<out Display>>()
fun register(controller: BaseDisplayController<out Display>) {
displayControllers[controller.display.uniqueId] = controller
controller.interaction?.let {
interactionControllers[it.uniqueId] = controller
}
}
fun unregister(controller: BaseDisplayController<out Display>) {
displayControllers.remove(controller.display.uniqueId, controller)
controller.interaction?.let {
interactionControllers.remove(it.uniqueId, controller)
}
}
fun controllerCount(): Int = displayControllers.size
fun shutdown() {
displayControllers.clear()
interactionControllers.clear()
}
@EventHandler
fun onPlayerInteractEntity(event: PlayerInteractEntityEvent) {
val entity = event.rightClicked
val controller = lookupController(entity) ?: return
val surface = if (entity is Interaction) ClickSurface.INTERACTION else ClickSurface.DISPLAY
controller.handleClick(event, entity, surface)
}
@EventHandler
fun onPlayerQuit(event: PlayerQuitEvent) {
controllersSnapshot().forEach { it.handlePlayerQuit(event.player) }
}
@EventHandler
fun onPlayerJoin(event: PlayerJoinEvent) {
refreshAudiences(event.player)
}
@EventHandler
fun onPlayerChangedWorld(event: PlayerChangedWorldEvent) {
refreshAudiences(event.player)
}
@EventHandler
fun onPlayerRespawn(event: PlayerRespawnEvent) {
refreshAudiences(event.player)
}
private fun lookupController(entity: Entity): BaseDisplayController<out Display>? {
return displayControllers[entity.uniqueId]
?: interactionControllers[entity.uniqueId]
}
private fun controllersSnapshot(): Collection<BaseDisplayController<out Display>> =
displayControllers.values.toSet()
private fun refreshAudiences(player: Player) {
val controllers = controllersSnapshot()
if (controllers.isEmpty()) return
controllers.forEach { it.refreshAudience(player) }
}
}