package net.hareworks.ghostdisplays.internal import java.util.UUID import java.util.concurrent.CopyOnWriteArraySet import net.hareworks.ghostdisplays.api.DisplayController import net.hareworks.ghostdisplays.api.DisplayService import net.hareworks.ghostdisplays.api.InteractionController import net.hareworks.ghostdisplays.api.InteractionOptions import net.hareworks.ghostdisplays.internal.controller.BaseDisplayController import net.hareworks.ghostdisplays.internal.controller.BaseInteractionController import net.hareworks.ghostdisplays.internal.controller.DisplayRegistry import net.hareworks.ghostdisplays.internal.fake.FakeBlockDisplay import net.hareworks.ghostdisplays.internal.fake.FakeInteraction import net.hareworks.ghostdisplays.internal.fake.FakeItemDisplay import net.hareworks.ghostdisplays.internal.fake.FakeTextDisplay import net.hareworks.ghostdisplays.internal.nms.DisplayPacketFactory import org.bukkit.Location import org.bukkit.inventory.ItemStack import org.bukkit.plugin.java.JavaPlugin internal class DefaultDisplayService( private val plugin: JavaPlugin, private val registry: DisplayRegistry ) : DisplayService { private val controllers = CopyOnWriteArraySet() private val interactionControllers = CopyOnWriteArraySet() override fun createTextDisplay( location: Location, interaction: InteractionOptions, builder: FakeTextDisplay.() -> Unit ): DisplayController { val fake = FakeTextDisplay( entityId = DisplayPacketFactory.nextEntityId(), uuid = UUID.randomUUID(), location = location.clone() ) builder(fake) return register(fake, location, interaction) } override fun createBlockDisplay( location: Location, interaction: InteractionOptions, builder: FakeBlockDisplay.() -> Unit ): DisplayController { val fake = FakeBlockDisplay( entityId = DisplayPacketFactory.nextEntityId(), uuid = UUID.randomUUID(), location = location.clone() ) builder(fake) return register(fake, location, interaction) } override fun createItemDisplay( location: Location, itemStack: ItemStack, interaction: InteractionOptions, builder: FakeItemDisplay.() -> Unit ): DisplayController { val fake = FakeItemDisplay( entityId = DisplayPacketFactory.nextEntityId(), uuid = UUID.randomUUID(), location = location.clone() ) fake.itemStack = itemStack.clone() builder(fake) return register(fake, location, interaction) } override fun createInteraction( location: Location, builder: FakeInteraction.() -> Unit ): InteractionController { val fake = FakeInteraction( entityId = DisplayPacketFactory.nextEntityId(), uuid = UUID.randomUUID(), location = location.clone() ) builder(fake) val controller = BaseInteractionController(plugin, fake, registry) interactionControllers += controller registry.registerInteraction(controller) return controller } override fun destroyAll() { controllers.forEach { it.destroy() } controllers.clear() interactionControllers.forEach { it.destroy() } interactionControllers.clear() } private fun register( fake: net.hareworks.ghostdisplays.internal.fake.FakeDisplay, location: Location, interactionOptions: InteractionOptions ): DisplayController { val fakeInteraction = if (interactionOptions.enabled) { FakeInteraction( entityId = DisplayPacketFactory.nextEntityId(), uuid = UUID.randomUUID(), location = location.clone() ).apply { width = interactionOptions.effectiveWidth().toFloat() height = interactionOptions.effectiveHeight().toFloat() responsive = interactionOptions.responsive } } else null val controller = BaseDisplayController(plugin, fake, fakeInteraction, registry) controllers += controller registry.register(controller) return controller } }