Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.

Commit 49d3919

Browse files
committed
feat: add PluginCommand and enhance Entrypoint debug capabilities
- Introduced `PluginCommand` for managing and displaying plugin-related information via console commands. - Enhanced `Entrypoint` with a `toString` override for improved debug output. - Made `LaunchEntryPointHandler.get` function public to enable wider reuse within the application.
1 parent 6cf981a commit 49d3919

File tree

3 files changed

+149
-1
lines changed

3 files changed

+149
-1
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package dev.slne.surf.cloud.standalone.commands.impl
2+
3+
import com.mojang.brigadier.Command
4+
import com.mojang.brigadier.CommandDispatcher
5+
import dev.slne.surf.cloud.api.common.util.mutableObjectListOf
6+
import dev.slne.surf.cloud.api.server.command.AbstractConsoleCommand
7+
import dev.slne.surf.cloud.api.server.command.CommandSource
8+
import dev.slne.surf.cloud.api.server.command.ConsoleCommand
9+
import dev.slne.surf.cloud.api.server.command.literal
10+
import dev.slne.surf.cloud.api.server.plugin.PluginManager
11+
import dev.slne.surf.cloud.api.server.plugin.StandalonePlugin
12+
import dev.slne.surf.cloud.standalone.plugin.entrypoint.Entrypoint
13+
import dev.slne.surf.cloud.standalone.plugin.entrypoint.LaunchEntryPointHandler
14+
import dev.slne.surf.cloud.standalone.plugin.provider.PluginProvider
15+
import dev.slne.surf.cloud.standalone.plugin.provider.ProviderStatus
16+
import dev.slne.surf.cloud.standalone.plugin.provider.ProviderStatusHolder
17+
import dev.slne.surf.cloud.standalone.plugin.provider.impl.StandalonePluginParent
18+
import dev.slne.surf.surfapi.core.api.messages.adventure.buildText
19+
import dev.slne.surf.surfapi.core.api.messages.adventure.text
20+
import io.leangen.geantyref.GenericTypeReflector
21+
import io.leangen.geantyref.TypeToken
22+
import net.kyori.adventure.text.Component
23+
import net.kyori.adventure.text.JoinConfiguration
24+
import net.kyori.adventure.text.format.NamedTextColor
25+
import net.kyori.adventure.text.format.TextColor
26+
import java.lang.reflect.Type
27+
import java.util.*
28+
29+
@ConsoleCommand
30+
class PluginCommand : AbstractConsoleCommand() {
31+
32+
override fun register(dispatcher: CommandDispatcher<CommandSource>) {
33+
val root = literal<CommandSource>("plugins") {
34+
executes { ctx ->
35+
val plugins =
36+
TreeMap<String, PluginProvider<StandalonePlugin>>(String.CASE_INSENSITIVE_ORDER)
37+
val providers = LaunchEntryPointHandler.get(Entrypoint.SPRING_PLUGIN)
38+
?.getRegisteredProviders()
39+
?: error("No storage for entrypoint ${Entrypoint.SPRING_PLUGIN}")
40+
41+
for (provider in providers) {
42+
val meta = provider.meta
43+
plugins.put(meta.displayName, provider)
44+
}
45+
46+
val infoMessage = buildText {
47+
info("")
48+
text("Plugins (${plugins.size}): ", NamedTextColor.WHITE)
49+
append(
50+
Component.join(
51+
JoinConfiguration.newlines(),
52+
formatProviders(plugins)
53+
)
54+
)
55+
}
56+
57+
ctx.source.sendMessage(infoMessage)
58+
Command.SINGLE_SUCCESS
59+
}
60+
}
61+
62+
dispatcher.register(root)
63+
dispatcher.register(literal("pl") {
64+
redirect(root.build())
65+
})
66+
}
67+
68+
private fun <T> formatProviders(plugins: TreeMap<String, PluginProvider<T>>): List<Component> {
69+
val components = mutableObjectListOf<Component>(plugins.size)
70+
for (entry in plugins.values) {
71+
components.add(formatProvider(entry))
72+
}
73+
74+
var isFirst = true
75+
val formattedSubLists = mutableObjectListOf<Component>()
76+
77+
for (componentSublist in components.chunked(10)) {
78+
var component = Component.space()
79+
if (isFirst) {
80+
component =
81+
component.append(text("", NamedTextColor.DARK_GRAY))
82+
isFirst = false
83+
} else {
84+
component = Component.space()
85+
}
86+
87+
formattedSubLists.add(
88+
component.append(
89+
Component.join(
90+
JoinConfiguration.commas(true),
91+
componentSublist
92+
)
93+
)
94+
)
95+
}
96+
97+
return formattedSubLists
98+
}
99+
100+
101+
private fun formatProvider(provider: PluginProvider<*>): Component {
102+
return text(provider.meta.name, fromStatus(provider))
103+
}
104+
105+
private fun fromStatus(provider: PluginProvider<*>): TextColor {
106+
when (provider) {
107+
is ProviderStatusHolder -> {
108+
val status = provider.status
109+
110+
if (status == ProviderStatus.INITIALIZED && GenericTypeReflector.isSuperType(
111+
STANDALONE_PLUGIN_PROVIDER_TYPE,
112+
provider.javaClass
113+
)
114+
) {
115+
val plugin = PluginManager.instance.getPlugin(provider.meta.name)
116+
if (plugin == null) {
117+
return NamedTextColor.RED
118+
}
119+
120+
return if (plugin.enabled) NamedTextColor.GREEN else NamedTextColor.RED
121+
}
122+
123+
return when (status) {
124+
ProviderStatus.INITIALIZED -> NamedTextColor.GREEN
125+
ProviderStatus.ERRORED -> NamedTextColor.RED
126+
ProviderStatus.UNINITIALIZED -> NamedTextColor.YELLOW
127+
}
128+
}
129+
130+
is StandalonePluginParent.StandalonePluginProvider if provider.shouldSkipCreation() -> {
131+
return NamedTextColor.RED
132+
}
133+
134+
else -> {
135+
return NamedTextColor.RED
136+
}
137+
}
138+
}
139+
140+
companion object {
141+
private val STANDALONE_PLUGIN_PROVIDER_TYPE: Type =
142+
object : TypeToken<PluginProvider<StandalonePlugin>>() {}.type
143+
}
144+
}

surf-cloud-standalone/src/main/kotlin/dev/slne/surf/cloud/standalone/plugin/entrypoint/Entrypoint.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@ class Entrypoint<T>(
1111
val SPRING_PLUGIN_BOOTSTRAPPER =
1212
Entrypoint<StandalonePluginBootstrap>("spring-plugin-bootstrapper")
1313
}
14+
15+
override fun toString(): String {
16+
return "Entrypoint(debugName='$debugName')"
17+
}
1418
}

surf-cloud-standalone/src/main/kotlin/dev/slne/surf/cloud/standalone/plugin/entrypoint/LaunchEntryPointHandler.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ object LaunchEntryPointHandler : EntrypointHandler {
4040
return enteredMap.getBoolean(entrypoint)
4141
}
4242

43-
private fun <T> get(entrypoint: Entrypoint<T>): ProviderStorage<T>? {
43+
fun <T> get(entrypoint: Entrypoint<T>): ProviderStorage<T>? {
4444
@Suppress("UNCHECKED_CAST")
4545
return storage[entrypoint] as? ProviderStorage<T>
4646
}

0 commit comments

Comments
 (0)