Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
javaVersion=25
mcVersion=26.2
group=dev.slne.surf.api
version=3.26.0
version=3.27.0
relocationPrefix=dev.slne.surf.api.libs
snapshot=false
5 changes: 5 additions & 0 deletions surf-api-core/surf-api-core/api/surf-api-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -11057,6 +11057,11 @@ public final class dev/slne/surf/api/core/util/SerializableErrorKt {
public static final fun toSerializableError (Ljava/lang/Throwable;)Ldev/slne/surf/api/core/util/SerializableError;
}

public final class dev/slne/surf/api/core/util/ServiceUtil {
public static final field INSTANCE Ldev/slne/surf/api/core/util/ServiceUtil;
public final fun serviceWithFallback (Ljava/util/ServiceLoader;Ljava/lang/Class;)Ljava/lang/Object;
}

public abstract class dev/slne/surf/api/core/util/SurfTypeParameterMatcher {
public static final field Companion Ldev/slne/surf/api/core/util/SurfTypeParameterMatcher$Companion;
public fun <init> ()V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ internal class SurfComponentBuilderImpl(private val delegate: TextComponent.Buil
override fun content(content: String) = withDelegate { content(content) }
override fun content() = delegate.content()
override fun children(): List<Component> = delegate.children()
override fun build() = delegate.build()
override fun build(): TextComponent {
// Adventure 4 backward compatibility. #build() would return BuildableComponent instead of TextComponent in adventure 4
return delegate.asComponent() as TextComponent
}

override fun append(builder: ComponentBuilder<*, *>) = withDelegate { append(builder) }
override fun append(component: Component) = withDelegate { append(component) }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.slne.surf.api.core.util

import net.kyori.adventure.internal.properties.AdventureProperties
import net.kyori.adventure.util.Services
import java.util.*

Expand All @@ -12,9 +13,41 @@ import java.util.*
* @return the service instance of type [T]
* @throws ServiceConfigurationError if the service of type [T] is not available
*/
inline fun <reified T : Any> requiredService(): T = Services.serviceWithFallback<T>(
inline fun <reified T : Any> requiredService(): T = ServiceUtil.serviceWithFallback<T>(
ServiceLoader.load(
T::class.java,
getCallerClass()?.classLoader ?: T::class.java.classLoader
), T::class.java
).orElseThrow { ServiceConfigurationError("Service ${T::class.java.name} not available") }
) ?: throw ServiceConfigurationError("Service ${T::class.java.name} not available")

object ServiceUtil {
@Suppress("UnstableApiUsage")
private val SERVICE_LOAD_FAILURES_ARE_FATAL = AdventureProperties.SERVICE_LOAD_FAILURES_ARE_FATAL.value() == true

@PublishedApi
internal fun <T> serviceWithFallback(loader: ServiceLoader<T>, type: Class<T>): T? {
val iterator = loader.iterator()
var firstFallback: T? = null

while (iterator.hasNext()) {
try {
val next = iterator.next()
if (next is Services.Fallback) {
if (firstFallback == null) {
firstFallback = next
}
} else {
return next
}
} catch (t: Throwable) {
if (SERVICE_LOAD_FAILURES_ARE_FATAL) {
throw ServiceConfigurationError("Failed to load service $type", t)
} else {
continue
}
}
}

return firstFallback
}
}