diff --git a/build.gradle.kts b/build.gradle.kts index 49fd187..bc7b84e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,6 +35,9 @@ repositories { dependencies { compileOnly("org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT") compileOnly(kotlin("stdlib")) + compileOnly(fileTree("libs") { + include("*.jar") + }) } tasks.withType { @@ -81,4 +84,4 @@ tasks.register("publishMatrixApi") { group = "publishing" description = "Publish MatrixLib API artifact to the shared local repository." dependsOn("publishAllPublicationsToMatrixPublicRepository") -} +} \ No newline at end of file diff --git a/libs/FancyHolograms-2.9.1.jar b/libs/FancyHolograms-2.9.1.jar new file mode 100644 index 0000000..41d2fd7 Binary files /dev/null and b/libs/FancyHolograms-2.9.1.jar differ diff --git a/src/main/kotlin/com/y54895/matrixlib/api/hologram/internal/FancyHologramsAdapter.kt b/src/main/kotlin/com/y54895/matrixlib/api/hologram/internal/FancyHologramsAdapter.kt index b66a118..b2e1d38 100644 --- a/src/main/kotlin/com/y54895/matrixlib/api/hologram/internal/FancyHologramsAdapter.kt +++ b/src/main/kotlin/com/y54895/matrixlib/api/hologram/internal/FancyHologramsAdapter.kt @@ -1,22 +1,19 @@ package com.y54895.matrixlib.api.hologram.internal +import de.oliver.fancyholograms.api.FancyHologramsPlugin +import de.oliver.fancyholograms.api.data.TextHologramData +import de.oliver.fancyholograms.api.hologram.Hologram import org.bukkit.Bukkit import org.bukkit.Location -import org.bukkit.plugin.Plugin import taboolib.common.platform.function.warning -import java.lang.reflect.Constructor -import java.lang.reflect.Method -import java.lang.reflect.Modifier -import java.util.Optional import java.util.concurrent.ConcurrentHashMap -internal class FancyHologramsAdapter private constructor( - private val bridge: ApiBridge -) : MatrixHologramAdapter { +internal class FancyHologramsAdapter : MatrixHologramAdapter { override val name: String = "FancyHolograms" - private val holograms = ConcurrentHashMap() + private val holograms = ConcurrentHashMap() + private val hologramManager = FancyHologramsPlugin.get().hologramManager override fun createOrUpdate(entry: MatrixRenderedHologram) { if (entry.lines.isEmpty()) { @@ -31,12 +28,13 @@ internal class FancyHologramsAdapter private constructor( } runCatching { - val hologramData = bridge.getDataMethod.invoke(hologram) ?: return@runCatching - bridge.setLocationMethod.invoke(hologramData, entry.location) - bridge.setTextMethod.invoke(hologramData, entry.lines) - bridge.forceUpdateMethod.invoke(hologram) - bridge.queueUpdateMethod.invoke(hologram) - bridge.refreshForViewersMethod?.invoke(hologram) + val hologramData = hologram.data + hologramData.setLocation(entry.location) + if (hologramData is TextHologramData) { + hologramData.setText(entry.lines) + } + hologram.forceUpdate() + hologram.queueUpdate() holograms[entry.qualifiedId] = hologram }.onFailure { warning("MatrixLib failed to update FancyHolograms hologram ${entry.qualifiedId}: ${it.message}") @@ -46,14 +44,10 @@ internal class FancyHologramsAdapter private constructor( } override fun remove(qualifiedId: String) { - val manager = manager() ?: return val hologram = holograms.remove(qualifiedId) ?: findHologram(qualifiedId) runCatching { - when { - bridge.removeByNameMethod != null -> bridge.removeByNameMethod.invoke(manager, qualifiedId) - hologram != null && bridge.removeByHologramMethod != null -> { - bridge.removeByHologramMethod.invoke(manager, hologram) - } + if (hologram != null) { + hologramManager.removeHologram(hologram) } }.onFailure { warning("MatrixLib failed to remove FancyHolograms hologram $qualifiedId: ${it.message}") @@ -66,36 +60,23 @@ internal class FancyHologramsAdapter private constructor( } private fun create(entry: MatrixRenderedHologram) { - val manager = manager() ?: return runCatching { - val hologramData = bridge.textHologramDataConstructor.newInstance(entry.qualifiedId, entry.location) - bridge.setTextMethod.invoke(hologramData, entry.lines) + val hologramData = TextHologramData(entry.qualifiedId, entry.location) + hologramData.setText(entry.lines) - val hologram = bridge.createMethod.invoke(manager, hologramData) ?: return@runCatching - bridge.setPersistent(hologram, hologramData) - bridge.addHologramMethod.invoke(manager, hologram) - bridge.forceUpdateMethod.invoke(hologram) - bridge.queueUpdateMethod.invoke(hologram) - bridge.refreshForViewersMethod?.invoke(hologram) + val hologram = hologramManager.create(hologramData) ?: return@runCatching + hologramManager.addHologram(hologram) + hologram.forceUpdate() + hologram.queueUpdate() holograms[entry.qualifiedId] = hologram }.onFailure { warning("MatrixLib failed to create FancyHolograms hologram ${entry.qualifiedId}: ${it.message}") } } - private fun manager(): Any? { + private fun findHologram(id: String): Hologram? { return runCatching { - bridge.hologramManagerGetter.invoke(bridge.managerOwner) - }.getOrNull() - } - - private fun findHologram(id: String): Any? { - val manager = manager() ?: return null - return runCatching { - when (val result = bridge.getHologramMethod.invoke(manager, id)) { - is Optional<*> -> result.orElse(null) - else -> result - } + hologramManager.getHologram(id).orElse(null) }.getOrNull() } @@ -105,162 +86,11 @@ internal class FancyHologramsAdapter private constructor( val plugin = Bukkit.getPluginManager().getPlugin("FancyHolograms") ?.takeIf { it.isEnabled } ?: return null - val bridge = listOf( - PackageLayout( - basePackage = "de.oliver.fancyholograms", - apiPackage = "de.oliver.fancyholograms.api" - ), - PackageLayout( - basePackage = "com.fancyinnovations.fancyholograms", - apiPackage = "com.fancyinnovations.fancyholograms.api" - ) - ).firstNotNullOfOrNull { layout -> - buildBridge(plugin, layout) - } - - if (bridge == null) { - warning("MatrixLib could not resolve a compatible FancyHolograms API bridge.") - return null - } - return FancyHologramsAdapter(bridge) - } - - private fun buildBridge(plugin: Plugin, layout: PackageLayout): ApiBridge? { - val loader = plugin.javaClass.classLoader - return runCatching { - val textHologramDataClass = Class.forName("${layout.apiPackage}.data.TextHologramData", false, loader) - val hologramClass = Class.forName("${layout.apiPackage}.hologram.Hologram", false, loader) - val hologramDataClass = Class.forName("${layout.apiPackage}.data.HologramData", false, loader) - - val managerOwner = resolveManagerOwner(plugin, layout.basePackage, loader) - val hologramManagerGetter = managerOwner.javaClass.methods.firstOrNull { method -> - method.name == "getHologramManager" && method.parameterCount == 0 - } ?: throw IllegalStateException("getHologramManager() is not available") - val managerClass = hologramManagerGetter.returnType - - val getHologramMethod = managerClass.getMethod("getHologram", String::class.java) - val createMethod = managerClass.methods.first { method -> - method.name == "create" && - method.parameterCount == 1 && - method.parameterTypes[0].isAssignableFrom(hologramDataClass) - } - val addHologramMethod = managerClass.methods.first { method -> - method.name == "addHologram" && - method.parameterCount == 1 && - method.parameterTypes[0].isAssignableFrom(hologramClass) - } - val removeByNameMethod = managerClass.methods.firstOrNull { method -> - method.name == "removeHologram" && - method.parameterCount == 1 && - method.parameterTypes[0] == String::class.java - } - val removeByHologramMethod = managerClass.methods.firstOrNull { method -> - method.name == "removeHologram" && - method.parameterCount == 1 && - method.parameterTypes[0].isAssignableFrom(hologramClass) - } - - val textHologramDataConstructor = textHologramDataClass.getConstructor( - String::class.java, - Location::class.java - ) - val setTextMethod = textHologramDataClass.methods.first { method -> - method.name == "setText" && method.parameterCount == 1 - } - val setLocationMethod = hologramDataClass.getMethod("setLocation", Location::class.java) - val getDataMethod = hologramClass.getMethod("getData") - val queueUpdateMethod = hologramClass.getMethod("queueUpdate") - val forceUpdateMethod = hologramClass.getMethod("forceUpdate") - val refreshForViewersMethod = hologramClass.methods.firstOrNull { method -> - method.name == "refreshForViewers" && method.parameterCount == 0 - } - val setPersistentOnHologramMethod = hologramClass.methods.firstOrNull { method -> - method.name == "setPersistent" && - method.parameterCount == 1 && - isBooleanParameter(method) - } - val setPersistentOnDataMethod = hologramDataClass.methods.firstOrNull { method -> - method.name == "setPersistent" && - method.parameterCount == 1 && - isBooleanParameter(method) - } - - ApiBridge( - managerOwner = managerOwner, - hologramManagerGetter = hologramManagerGetter, - getHologramMethod = getHologramMethod, - createMethod = createMethod, - addHologramMethod = addHologramMethod, - removeByNameMethod = removeByNameMethod, - removeByHologramMethod = removeByHologramMethod, - textHologramDataConstructor = textHologramDataConstructor, - setTextMethod = setTextMethod, - setLocationMethod = setLocationMethod, - getDataMethod = getDataMethod, - queueUpdateMethod = queueUpdateMethod, - forceUpdateMethod = forceUpdateMethod, - refreshForViewersMethod = refreshForViewersMethod, - setPersistentOnHologramMethod = setPersistentOnHologramMethod, - setPersistentOnDataMethod = setPersistentOnDataMethod - ) + FancyHologramsAdapter() }.onFailure { - warning("MatrixLib FancyHolograms bootstrap failed for ${layout.apiPackage}: ${it.message}") + warning("MatrixLib FancyHolograms bootstrap failed: ${it.message}") }.getOrNull() } - - private fun resolveManagerOwner(plugin: Plugin, basePackage: String, loader: ClassLoader): Any { - val pluginSingleton = listOf( - "$basePackage.FancyHologramsPlugin", - "$basePackage.FancyHolograms" - ).firstNotNullOfOrNull { className -> - runCatching { Class.forName(className, false, loader) }.getOrNull() - ?.methods - ?.firstOrNull { method -> - method.name == "get" && - method.parameterCount == 0 && - Modifier.isStatic(method.modifiers) - } - ?.let { method -> runCatching { method.invoke(null) }.getOrNull() } - } - return pluginSingleton ?: plugin - } - - private fun isBooleanParameter(method: Method): Boolean { - val parameterType = method.parameterTypes.singleOrNull() ?: return false - return parameterType == Boolean::class.javaPrimitiveType || parameterType == Boolean::class.javaObjectType - } - } - - private data class PackageLayout( - val basePackage: String, - val apiPackage: String - ) - - private data class ApiBridge( - val managerOwner: Any, - val hologramManagerGetter: Method, - val getHologramMethod: Method, - val createMethod: Method, - val addHologramMethod: Method, - val removeByNameMethod: Method?, - val removeByHologramMethod: Method?, - val textHologramDataConstructor: Constructor<*>, - val setTextMethod: Method, - val setLocationMethod: Method, - val getDataMethod: Method, - val queueUpdateMethod: Method, - val forceUpdateMethod: Method, - val refreshForViewersMethod: Method?, - val setPersistentOnHologramMethod: Method?, - val setPersistentOnDataMethod: Method? - ) { - - fun setPersistent(hologram: Any, hologramData: Any) { - when { - setPersistentOnHologramMethod != null -> setPersistentOnHologramMethod.invoke(hologram, false) - setPersistentOnDataMethod != null -> setPersistentOnDataMethod.invoke(hologramData, false) - } - } } -} +} \ No newline at end of file