Skip to content

Commit f8034ed

Browse files
committed
Fix: Better plugin loader
1 parent b32726f commit f8034ed

File tree

4 files changed

+38
-118
lines changed

4 files changed

+38
-118
lines changed

common/src/main/kotlin/com/lambda/plugin/PluginLoader.kt

Lines changed: 0 additions & 49 deletions
This file was deleted.

common/src/main/kotlin/com/lambda/plugin/PluginRegistry.kt

Lines changed: 34 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,89 +2,56 @@ package com.lambda.plugin
22

33
import com.lambda.Lambda.LOG
44
import com.lambda.core.Loadable
5+
import com.lambda.plugin.api.Plugin
56
import com.lambda.util.FolderRegister.listRecursive
67
import com.lambda.util.FolderRegister.mods
8+
import org.reflections.Reflections
9+
import org.reflections.scanners.Scanners
10+
import org.reflections.util.ConfigurationBuilder
711
import java.io.File
12+
import java.lang.reflect.Method
13+
import java.net.URI
14+
import java.net.URL
15+
import java.net.URLClassLoader
816
import java.util.jar.JarFile
917

1018
object PluginRegistry : Loadable {
11-
private val classLoaderError = """
12-
An error occurred while retrieving the thread class loader.
13-
This likely mean that newer versions of the mod loader
14-
have changed the way mods are loaded, affecting the plugin system.
15-
Please report this error to the Lambda developers with the following information:
16-
- The version of Lambda
17-
- The version of the mod loader (ex. Fabric, Forge, etc.)
18-
- The version of Minecraft you are using
19-
- The version of Java you are using
20-
21-
Plugin: %s
22-
Stacktrace:
23-
%s
24-
""".trimIndent()
19+
val plugins = mutableListOf<Plugin>()
2520

2621
private val loadingError = """
2722
An error occurred while loading a plugin.
28-
If you are a developer, please check the plugin's main class and load method.
23+
If you are a developer, please check the plugin's main class, instance or load method.
2924
If you are a regular user, please report this issue to the plugin developer.
3025
3126
Plugin: %s
3227
Error: %s
33-
Stacktrace:
34-
%s
3528
""".trimIndent()
3629

37-
private fun loadPlugin(file: File) {
38-
runCatching {
39-
val jar = JarFile(file)
40-
41-
val mainClass = jar.manifest.mainAttributes.getValue("Main-Class")
42-
?: return LOG.error("The plugin $jar does not have a main class")
43-
44-
val loader = PluginLoader(jar,
45-
Thread.currentThread().contextClassLoader ?:
46-
return classLoaderError.format(
47-
file,
48-
Thread.currentThread().stackTrace.joinToString("\n")
49-
)
50-
.split("\n")
51-
.forEach(LOG::error))
52-
53-
val loadClass = loader.loadClass(mainClass)
54-
55-
val loadInstance =
56-
loadClass.declaredFields.firstOrNull { it.name == "INSTANCE" }?.get(null)
57-
?: loadClass.constructors.firstOrNull()?.newInstance()
58-
?: return LOG.error("The plugin $jar does not have an object instance or a public constructor")
59-
val loadMethod =
60-
loadClass?.methods?.find { it.name == "load" }
61-
?: return LOG.warn("The plugin $jar does not have a load method")
62-
63-
loadMethod.invoke(loadInstance)
64-
}.onFailure {
65-
loadingError.format(
66-
file,
67-
it.message,
68-
it.stackTraceToString()
69-
)
70-
.split("\n")
71-
.forEach(LOG::error)
72-
}
73-
}
74-
7530
override fun load(): String {
76-
val plugins = mods
77-
.listRecursive {
78-
it.isFile && it.extension == "jar"
79-
// Not a fan of creating a new JarFile instance every iteration
80-
&& JarFile(it).manifest.mainAttributes.getValue("Lambda-Plugin") == "true"
81-
}
82-
val size = plugins.count()
83-
84-
plugins.forEach(::loadPlugin)
85-
86-
val plural = if (size == 1) "" else "s"
31+
Reflections(
32+
ConfigurationBuilder()
33+
.addUrls(
34+
mods.listRecursive { it.extension == "jar" }
35+
.map { it.toURI().toURL() }
36+
.toList()
37+
)
38+
.addScanners(Scanners.SubTypes)
39+
).getSubTypesOf(Plugin::class.java).forEach { pluginClass ->
40+
val instance = (pluginClass.declaredFields.find { it.name == "INSTANCE" }?.get(null)
41+
?: pluginClass.constructors.firstOrNull()?.newInstance()) as? Plugin
42+
?: null.also {
43+
loadingError.format(
44+
pluginClass,
45+
"The plugin does not have an object instance or a public constructor"
46+
).also { LOG.warn(it) }
47+
}
48+
49+
if (instance == null) return@forEach
50+
51+
instance.load()
52+
plugins.add(instance)
53+
}
8754

88-
return "Loaded $size plugin$plural"
55+
return "Registered ${plugins.size} plugins"
8956
}
9057
}

gradle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,7 @@ neo_version=20.4.234
2828
kotlin.code.style=official
2929

3030
# Gradle https://gradle.org/
31-
org.gradle.jvmargs=-Xmx2048M
31+
org.gradle.jvmargs=-Xmx2048M \
32+
-XX:MaxMetaspaceSize=256m \
33+
-XX:+HeapDumpOnOutOfMemoryError
3234
org.gradle.parallel=true

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-rc-4-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

0 commit comments

Comments
 (0)