mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-04 16:49:11 +00:00
Treat each plugin as an individual source set
Adds separate build tasks for each plugin by auto-discovering plugin meta files in the build script. Each plugin will automatically have its main sources and tests compiled, and then it's output added to the game modules classpath. This enables support for incremental compilation of scripts, as well as unit testing using Gradle's test framework.
This commit is contained in:
@@ -15,6 +15,9 @@ import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
|
||||
import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.plugin.kotlin.KotlinPluginCompiler;
|
||||
import org.apollo.game.plugin.kotlin.KotlinPluginScript;
|
||||
@@ -37,15 +40,14 @@ public class KotlinPluginEnvironment implements PluginEnvironment {
|
||||
@Override
|
||||
public void load(Collection<PluginMetaData> plugins) {
|
||||
List<KotlinPluginScript> pluginScripts = new ArrayList<>();
|
||||
List<Class<? extends KotlinPluginScript>> pluginClasses = new ArrayList<>();
|
||||
|
||||
try (InputStream resource = KotlinPluginEnvironment.class.getResourceAsStream("/manifest.txt")) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(resource));
|
||||
List<String> pluginClassNames = reader.lines().collect(Collectors.toList());
|
||||
|
||||
for (String pluginClassName : pluginClassNames) {
|
||||
Class<? extends KotlinPluginScript> pluginClass =
|
||||
(Class<? extends KotlinPluginScript>) Class.forName(pluginClassName);
|
||||
new FastClasspathScanner()
|
||||
.matchSubclassesOf(KotlinPluginScript.class, pluginClasses::add)
|
||||
.scan();
|
||||
|
||||
try {
|
||||
for (Class<? extends KotlinPluginScript> pluginClass : pluginClasses) {
|
||||
Constructor<? extends KotlinPluginScript> pluginConstructor =
|
||||
pluginClass.getConstructor(World.class, PluginContext.class);
|
||||
|
||||
@@ -55,7 +57,10 @@ public class KotlinPluginEnvironment implements PluginEnvironment {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
pluginScripts.forEach(script -> script.doStart(world));
|
||||
pluginScripts.forEach(script -> {
|
||||
logger.info("Starting script: " + script.getClass().getName());
|
||||
script.doStart(world);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -43,8 +43,6 @@ class KotlinPluginCompiler(val classpath: List<File>, val messageCollector: Mess
|
||||
|
||||
companion object {
|
||||
|
||||
private val maxSearchDepth = 1024;
|
||||
|
||||
fun currentClasspath(): List<File> {
|
||||
val classLoader = Thread.currentThread().contextClassLoader as? URLClassLoader ?:
|
||||
throw RuntimeException("Unable to resolve classpath for current ClassLoader")
|
||||
@@ -66,12 +64,10 @@ class KotlinPluginCompiler(val classpath: List<File>, val messageCollector: Mess
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
if (args.size < 4) throw RuntimeException("Usage: <inputDir> <outputDir> <manifestPath> <classpath>")
|
||||
if (args.size < 2) throw RuntimeException("Usage: <outputDirectory> script1.kts script2.kts ...")
|
||||
|
||||
val inputDir = Paths.get(args[0])
|
||||
val outputDir = Paths.get(args[1])
|
||||
val manifestPath = Paths.get(args[2])
|
||||
val classpathEntries = args[3].split(':')
|
||||
val outputDir = Paths.get(args[0])
|
||||
val inputScripts = args.slice(1..args.size - 1).map { Paths.get(it) }
|
||||
val classpath = mutableListOf<File>()
|
||||
|
||||
val runtimeBean = ManagementFactory.getRuntimeMXBean()
|
||||
@@ -83,15 +79,11 @@ class KotlinPluginCompiler(val classpath: List<File>, val messageCollector: Mess
|
||||
}
|
||||
|
||||
/**
|
||||
* Classpath entries on the command line contain the kotlin runtime
|
||||
* and plugin API code. We use our current classpath to provide
|
||||
* Kotlin with access to the JRE and apollo modules.
|
||||
* Our current classpath should contain all compile time dependencies for the plugin as well as Apollo's
|
||||
* own sources. We can also achieve this via Gradle but doing it at runtime prevents Gradle from thinking
|
||||
* the build has been modified after evaluation.
|
||||
*/
|
||||
classpath.addAll(currentClasspath())
|
||||
classpath.addAll(classpathEntries.map { File(it) })
|
||||
|
||||
val inputScriptsMatcher = { path: Path, _: BasicFileAttributes -> path.toString().endsWith(".plugin.kts") }
|
||||
val inputScripts = Files.find(inputDir, maxSearchDepth, BiPredicate(inputScriptsMatcher))
|
||||
|
||||
val compiler = KotlinPluginCompiler(classpath, MessageCollector.NONE)
|
||||
val compiledScriptClasses = mutableListOf<String>()
|
||||
@@ -106,8 +98,6 @@ class KotlinPluginCompiler(val classpath: List<File>, val messageCollector: Mess
|
||||
inputScripts.forEach {
|
||||
compiledScriptClasses.add(compiler.compile(it, outputDir).fqName)
|
||||
}
|
||||
|
||||
Files.write(manifestPath, compiledScriptClasses, CREATE, TRUNCATE_EXISTING)
|
||||
} catch (t: Throwable) {
|
||||
t.printStackTrace()
|
||||
System.exit(1)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
name = "Banking"
|
||||
package = "org.apollo.game.plugin.banking"
|
||||
authors = [ "Major" ]
|
||||
|
||||
[config]
|
||||
srcDir = "src/"
|
||||
testDir = "test/"
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<plugin>
|
||||
<id>bank</id>
|
||||
<version>1</version>
|
||||
<name>Bank</name>
|
||||
<description>Opens the bank interface when players select 'use-quickly' on a bank booth.</description>
|
||||
<authors>
|
||||
<author>Major</author>
|
||||
</authors>
|
||||
<scripts>
|
||||
<script>bank.plugin.kts</script>
|
||||
</scripts>
|
||||
<dependencies />
|
||||
</plugin>
|
||||
@@ -0,0 +1,8 @@
|
||||
name = "spawning"
|
||||
package = "org.apollo.game.plugin.entity"
|
||||
authors = [ "Gary Tierney" ]
|
||||
dependencies = [ "entity_lookup" ]
|
||||
|
||||
[config]
|
||||
srcDir = "src/"
|
||||
testDir = "test/"
|
||||
@@ -0,0 +1,8 @@
|
||||
name = "lumbridge npc spawns"
|
||||
package = "org.apollo.game.plugin.locations"
|
||||
authors = [ "Gary Tierney" ]
|
||||
dependencies = [ "spawning" ]
|
||||
|
||||
[config]
|
||||
srcDir = "src/"
|
||||
testDir = "test/"
|
||||
@@ -0,0 +1,2 @@
|
||||
name = "entity lookup"
|
||||
package = "org.apollo.game.plugins.util"
|
||||
@@ -0,0 +1,14 @@
|
||||
import org.apollo.cache.def.ItemDefinition
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class LookupTests {
|
||||
@Test fun itemLookup() {
|
||||
val testItem = ItemDefinition(0)
|
||||
testItem.name = "sword"
|
||||
|
||||
ItemDefinition.init(arrayOf(testItem))
|
||||
|
||||
assertEquals(testItem, lookup_item("sword"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user