type, Class clazz) {
- this.groovierModule.bindProvider(type, clazz);
- }
+ @Override
+ public void bindInstance(Class type, T ins) {
+ this.groovierModule.bindInstance(type, ins);
+ }
- @Override
- public Injector getBaseInjector() {
- return Optional.ofNullable(injector).orElseThrow(() -> new IllegalStateException("groovier not initialized"));
- }
+ @Override
+ public void bindType(Class type, Class clazz) {
+ this.groovierModule.bindType(type, clazz);
+ }
- @Override
- public ServiceInjector getServiceInjector() {
- return getBaseInjector().getInstance(ServiceInjector.class);
- }
+ @Override
+ public > void bindProvider(Class type, Class clazz) {
+ this.groovierModule.bindProvider(type, clazz);
+ }
- @Override
- public ArgumentParser getArgumentParser() {
- return getBaseInjector().getInstance(ArgumentParser.class);
- }
+ @Override
+ public void installModule(Module module) {
+ this.groovierModule.installModule(module);
+ }
- public void copyFromJar(String source, final Path target) throws URISyntaxException, IOException {
+ @Override
+ public Injector getBaseInjector() {
+ return Optional.ofNullable(injector).orElseThrow(() -> new IllegalStateException("groovier not initialized"));
+ }
- URL url = getClass().getResource("");
+ @Override
+ public ServiceInjector getServiceInjector() {
+ return getBaseInjector().getInstance(ServiceInjector.class);
+ }
- if (url == null) {
- throw new IllegalStateException("can't find resource inside jar");
- }
+ @Override
+ public ArgumentParser getArgumentParser() {
+ return getBaseInjector().getInstance(ArgumentParser.class);
+ }
- URI resource = url.toURI();
+ public void copyFromJar(String source, final Path target) throws URISyntaxException, IOException {
- try (FileSystem fileSystem = FileSystems.newFileSystem(
- resource,
- Collections.emptyMap()
- )) {
+ URL url = getClass().getResource("");
+
+ if (url == null) {
+ throw new IllegalStateException("can't find resource inside jar");
+ }
+
+ URI resource = url.toURI();
+ try (FileSystem fileSystem = FileSystems.newFileSystem(
+ resource,
+ Collections.emptyMap()
+ )) {
- final Path jarPath = fileSystem.getPath(source);
- Files.walkFileTree(jarPath, new SimpleFileVisitor<>() {
+ final Path jarPath = fileSystem.getPath(source);
- @Override
- public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
- Path currentTarget = target.resolve(jarPath.relativize(dir).toString());
- if (Files.notExists(currentTarget)) Files.createDirectories(currentTarget);
- return FileVisitResult.CONTINUE;
- }
+ Files.walkFileTree(jarPath, new SimpleFileVisitor<>() {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- var targetPath = target.resolve(jarPath.relativize(file).toString());
- if (Files.notExists(targetPath)) Files.copy(file, targetPath, StandardCopyOption.REPLACE_EXISTING);
- return FileVisitResult.CONTINUE;
- }
+ @Override
+ public @NotNull FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ Path currentTarget = target.resolve(jarPath.relativize(dir).toString());
+ if (Files.notExists(currentTarget)) Files.createDirectories(currentTarget);
+ return FileVisitResult.CONTINUE;
+ }
- });
+ @Override
+ public @NotNull FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ var targetPath = target.resolve(jarPath.relativize(file).toString());
+ if (Files.notExists(targetPath)) Files.copy(file, targetPath, StandardCopyOption.REPLACE_EXISTING);
+ return FileVisitResult.CONTINUE;
+ }
+
+ });
+
+ }
- }
-
- }
+ }
}
diff --git a/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/GroovierModule.groovy b/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/GroovierModule.groovy
index 4921f6e..2b9687f 100644
--- a/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/GroovierModule.groovy
+++ b/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/GroovierModule.groovy
@@ -1,6 +1,7 @@
package com.ericlam.mc.groovier
import com.google.inject.AbstractModule
+import com.google.inject.Module
import com.google.inject.Scopes
import com.google.inject.multibindings.Multibinder
@@ -13,7 +14,9 @@ class GroovierModule extends AbstractModule {
private final Map registerMap = new HashMap<>()
private final Map classMap = new HashMap<>()
- private final Map>> providerMap = new HashMap<>();
+ private final Map>> providerMap = new HashMap<>()
+
+ private final Set modules = new HashSet<>()
private final GroovyClassLoader classLoader = new GroovyClassLoader(getClass().getClassLoader())
@@ -34,6 +37,7 @@ class GroovierModule extends AbstractModule {
registerMap.forEach((type, obj) -> bind(type).toInstance(obj))
classMap.forEach((type, clazz) -> bind(type).to(clazz).in(Scopes.SINGLETON))
providerMap.forEach((type, provider) -> bind(type).toProvider(provider).in(Scopes.SINGLETON))
+ modules.forEach(this::install)
}
@@ -61,4 +65,8 @@ class GroovierModule extends AbstractModule {
this.registerMap.put(validator, ins)
}
+ def installModule(Module module) {
+ this.modules.add(module)
+ }
+
}
diff --git a/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/GroovierScriptLoader.groovy b/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/GroovierScriptLoader.groovy
index d7f7112..65a2a35 100644
--- a/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/GroovierScriptLoader.groovy
+++ b/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/GroovierScriptLoader.groovy
@@ -8,7 +8,7 @@ import java.util.concurrent.atomic.AtomicBoolean
class GroovierScriptLoader {
- private final AtomicBoolean loading = new AtomicBoolean(false)
+ private final AtomicBoolean reloading = new AtomicBoolean(false)
private final List loaders
@Inject
@@ -25,54 +25,59 @@ class GroovierScriptLoader {
@Inject
private GroovyClassLoader classLoader
+ void addClassPath() {
+ classLoader.addClasspath(plugin.pluginFolder.path)
+ }
+
CompletableFuture loadAllScripts() {
- this.loading.compareAndSet(false, true)
CompletableFuture future = new CompletableFuture<>()
plugin.runAsyncTask {
- var globalLibraries = new File(plugin.getPluginFolder(), "grapesConfig.groovy")
- if (globalLibraries.exists()) {
- plugin.logger.info("loading global libraries...")
- classLoader.parseClass(globalLibraries)
- plugin.logger.info("global libraries loaded.")
- }
- loaders.forEach(loader -> {
- plugin.getLogger().info("Loading ${loader.class.simpleName}")
- loader.load(classLoader)
- plugin.getLogger().info("${loader.class.simpleName} loading completed.")
- })
- loaders.forEach(loader -> {
- plugin.getLogger().info("Initializing ${loader.class.simpleName}")
- loader.afterLoad()
- plugin.getLogger().info("${loader.class.simpleName} initializing completed.")
- })
- ((GroovierCacheManager)cacheManager).flush()
- plugin.logger.info("All Scripts loaded.")
- plugin.runSyncTask {
- lifeCycle.onScriptLoad()
- this.loading.compareAndSet(true, false)
- future.complete(null)
+ try {
+ var globalLibraries = new File(plugin.pluginFolder, "grapesConfig.groovy")
+ if (globalLibraries.exists()) {
+ plugin.logger.info("loading global libraries...")
+ classLoader.parseClass(globalLibraries)
+ plugin.logger.info("global libraries loaded.")
+ }
+ loaders.each { loader ->
+ plugin.logger.info("Loading ${loader.class.simpleName}")
+ loader.load(classLoader)
+ plugin.logger.info("${loader.class.simpleName} loading completed.")
+ }
+ loaders.each { loader ->
+ plugin.logger.info("Initializing ${loader.class.simpleName}")
+ loader.afterLoad()
+ plugin.logger.info("${loader.class.simpleName} initializing completed.")
+ }
+ ((GroovierCacheManager)cacheManager).flush()
+ plugin.logger.info("All Scripts loaded.")
+ plugin.runSyncTask {
+ lifeCycle.onScriptLoad()
+ future.complete(null)
+ }
+ } catch (Exception e) {
+ future.completeExceptionally(e)
}
}
return future
}
void unloadAllScripts() {
- this.loading.compareAndSet(false, true)
lifeCycle.onScriptUnload()
- loaders.forEach(loader -> {
- plugin.getLogger().info("Unloading ${loader.class.simpleName}")
+ loaders.each { loader ->
+ plugin.logger.info("Unloading ${loader.class.simpleName}")
loader.unload()
- plugin.getLogger().info("${loader.class.simpleName} unloaded.")
- })
- this.loading.compareAndSet(true, false)
+ plugin.logger.info("${loader.class.simpleName} unloaded.")
+ }
+ classLoader.clearCache()
}
CompletableFuture reloadAllScripts() {
- if (loading.get()) {
+ if (!reloading.compareAndSet(false, true)) {
return CompletableFuture.failedFuture(new ScriptLoadingException())
}
this.unloadAllScripts()
- return this.loadAllScripts()
+ return this.loadAllScripts().whenComplete { reloading.set(false) }
}
}
diff --git a/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/scriptloaders/LifeCycleScriptsManager.groovy b/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/scriptloaders/LifeCycleScriptsManager.groovy
index f9e77ad..2321430 100644
--- a/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/scriptloaders/LifeCycleScriptsManager.groovy
+++ b/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/scriptloaders/LifeCycleScriptsManager.groovy
@@ -35,8 +35,8 @@ class LifeCycleScriptsManager implements ScriptLoader, ScriptValidator, Groovier
@Override
void load(GroovyClassLoader classLoader) {
- File listenerFolder = new File(plugin.getPluginFolder(), "lifecycles")
- var files = listenerFolder.listFiles()
+ File lifecycleFolder = new File(plugin.getPluginFolder(), "lifecycles")
+ var files = lifecycleFolder.listFiles()
if (files == null) {
plugin.getLogger().info("No lifecycles scripts found.")
@@ -55,7 +55,7 @@ class LifeCycleScriptsManager implements ScriptLoader, ScriptValidator, Groovier
plugin.getLogger().warning("Lifecycle Script '${file.getName()}' validation failed: ${e.getMessage()}")
} catch (Exception e) {
e.printStackTrace()
- plugin.getLogger().warning("Failed to load event script: " + file.getName())
+ plugin.getLogger().warning("Failed to load lifecycle script: " + file.getName())
}
}
}
diff --git a/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/scriptloaders/ServiceScriptsManager.groovy b/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/scriptloaders/ServiceScriptsManager.groovy
index 2cb2e1e..8d3cfa5 100644
--- a/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/scriptloaders/ServiceScriptsManager.groovy
+++ b/groovier-plugin/src/main/groovy/com/ericlam/mc/groovier/scriptloaders/ServiceScriptsManager.groovy
@@ -29,8 +29,8 @@ class ServiceScriptsManager implements ScriptLoader, ServiceInjector {
@Override
void load(GroovyClassLoader classLoader) {
- File listenerFolder = new File(plugin.getPluginFolder(), "services")
- var files = listenerFolder.listFiles()
+ File servicesFolder = new File(plugin.getPluginFolder(), "services")
+ var files = servicesFolder.listFiles()
if (files == null) {
plugin.getLogger().info("No services scripts found.")
@@ -46,7 +46,7 @@ class ServiceScriptsManager implements ScriptLoader, ServiceInjector {
plugin.getLogger().warning("Service Script '${file.getName()}' validation failed: ${e.getMessage()}")
} catch (Exception e) {
e.printStackTrace()
- plugin.getLogger().warning("Failed to load event script: " + file.getName())
+ plugin.getLogger().warning("Failed to load service script: " + file.getName())
}
}
}
diff --git a/groovier-plugin/src/main/resources/plugin.yml b/groovier-plugin/src/main/resources/plugin.yml
index b240db6..2ccb16b 100644
--- a/groovier-plugin/src/main/resources/plugin.yml
+++ b/groovier-plugin/src/main/resources/plugin.yml
@@ -3,6 +3,7 @@ description: "A Scripts Engine based on Groovy"
author: "Eric Lam"
website: "https://github.com/eric2788"
version: ${project.version}
+api-version: "1.21"
main: com.ericlam.mc.groovier.spigot.GroovierPlugin
commands:
groovier:
diff --git a/groovier-plugin/src/main/resources_bungee/grapesConfig.groovy b/groovier-plugin/src/main/resources_bungee/grapesConfig.groovy
index 28313fe..f412f0b 100644
--- a/groovier-plugin/src/main/resources_bungee/grapesConfig.groovy
+++ b/groovier-plugin/src/main/resources_bungee/grapesConfig.groovy
@@ -1,5 +1,5 @@
@GrabResolver(name = 'bungee-repo', root = 'https://oss.sonatype.org/content/repositories/snapshots')
-@Grab(group = 'net.md-5', module = 'bungeecord-api', version = '1.21-R0.1-SNAPSHOT')
+@Grab(group = 'net.md-5', module = 'bungeecord-api', version = '1.20-R0.1')
@GrabResolver(name = 'groovier', root = 'https://maven.pkg.github.com/groovier-minecraft/groovier')
@Grab(group = 'org.groovier', module = 'groovier-scripts', version = '0.0.4')
import java.lang.Object
diff --git a/groovier-plugin/src/main/resources_common/services/mathService.groovy b/groovier-plugin/src/main/resources_common/services/MathService.groovy
similarity index 99%
rename from groovier-plugin/src/main/resources_common/services/mathService.groovy
rename to groovier-plugin/src/main/resources_common/services/MathService.groovy
index 3517815..98473e6 100644
--- a/groovier-plugin/src/main/resources_common/services/mathService.groovy
+++ b/groovier-plugin/src/main/resources_common/services/MathService.groovy
@@ -1,6 +1,5 @@
package services
-
class MathService {
int add(int a, int b) {
diff --git a/groovier-plugin/src/main/resources_spigot/grapesConfig.groovy b/groovier-plugin/src/main/resources_spigot/grapesConfig.groovy
index 2858c0d..1b355bb 100644
--- a/groovier-plugin/src/main/resources_spigot/grapesConfig.groovy
+++ b/groovier-plugin/src/main/resources_spigot/grapesConfig.groovy
@@ -1,5 +1,5 @@
@GrabResolver(name = 'spigot-repo', root = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/')
-@Grab(group = 'org.spigotmc', module = 'spigot-api', version = '1.20.4-R0.1-SNAPSHOT')
+@Grab(group = 'org.spigotmc', module = 'spigot-api', version = '1.21.1-R0.1-SNAPSHOT')
@GrabResolver(name = 'groovier', root = 'https://maven.pkg.github.com/groovier-minecraft/groovier')
@Grab(group = 'org.groovier', module = 'groovier-scripts', version = '0.0.4')
import java.lang.Object
diff --git a/groovier-plugin/src/test/groovy/com/ericlam/mc/groovytest/TestGroovyDelegate.groovy b/groovier-plugin/src/test/groovy/com/ericlam/mc/groovytest/TestGroovyDelegate.groovy
new file mode 100644
index 0000000..b34255e
--- /dev/null
+++ b/groovier-plugin/src/test/groovy/com/ericlam/mc/groovytest/TestGroovyDelegate.groovy
@@ -0,0 +1,80 @@
+package com.ericlam.mc.groovytest
+
+import org.bukkit.Material
+import org.junit.jupiter.api.Test
+
+class TestGroovyDelegate {
+
+ @Test
+ void testGroovyDelegate() {
+ def builder = new ItemBuilderImpl() as ItemBuilder
+ builder.item = new Item()
+ builder.meta = builder.item.meta
+
+ builder.with {
+ type = Material.DIAMOND
+ displayName = "Hello Diamond!"
+ lore = ["Hello", "Diamond!"]
+ }
+
+ println builder.item.toString()
+ }
+
+
+ trait ItemBuilder {
+ @Delegate Item item
+ @Delegate ItemMeta meta
+ }
+
+ class ItemBuilderImpl implements ItemBuilder {
+ ItemBuilderImpl(){
+ this.item = new Item()
+ this.meta = item.meta
+ }
+ }
+
+
+ class Item {
+ private Material type = Material.STONE
+ private ItemMeta meta = new ItemMeta()
+
+ void setType(Material type) {
+ this.type = type
+ }
+
+ ItemMeta getMeta() {
+ return meta
+ }
+
+
+ @Override
+ public String toString() {
+ return "Item{" +
+ "type=" + type +
+ ", meta=" + meta +
+ '}';
+ }
+ }
+
+ class ItemMeta {
+ private String displayName;
+ private List lore;
+
+ void setDisplayName(String displayName) {
+ this.displayName = displayName
+ }
+
+ void setLore(List lore) {
+ this.lore = lore
+ }
+
+
+ @Override
+ public String toString() {
+ return "ItemMeta{" +
+ "displayName='" + displayName + '\'' +
+ ", lore=" + lore +
+ '}';
+ }
+ }
+}
diff --git a/groovier-plugin/src/test/groovy/com/ericlam/mc/groovytest/TestGroovyLoader.groovy b/groovier-plugin/src/test/groovy/com/ericlam/mc/groovytest/TestGroovyLoader.groovy
new file mode 100644
index 0000000..3ea0f20
--- /dev/null
+++ b/groovier-plugin/src/test/groovy/com/ericlam/mc/groovytest/TestGroovyLoader.groovy
@@ -0,0 +1,21 @@
+package com.ericlam.mc.groovytest
+
+import org.junit.jupiter.api.Test
+
+class TestGroovyLoader {
+
+ private final GroovyClassLoader classLoader = new GroovyClassLoader(getClass().getClassLoader())
+
+ @Test
+ void testGroovyLoadDependencies() {
+ classLoader.addClasspath(new File("src/test/resources").path)
+ println classLoader.getURLs().collect { it.toString() }
+ println classLoader.getLoadedClasses()
+ //def serviceBCls = classLoader.parseClass(new File("src/test/resources/services/ServiceB.groovy"))
+ //def serviceACls = classLoader.parseClass(new File("src/test/resources/services/ServiceA.groovy"))
+ def mainCls = classLoader.parseClass(new File("src/test/resources/main/main.groovy"))
+ println classLoader.getLoadedClasses()
+ def main = mainCls.getConstructor().newInstance()
+ main.main()
+ }
+}
diff --git a/groovier-plugin/src/test/resources/main/main.groovy b/groovier-plugin/src/test/resources/main/main.groovy
new file mode 100644
index 0000000..dbd084a
--- /dev/null
+++ b/groovier-plugin/src/test/resources/main/main.groovy
@@ -0,0 +1,6 @@
+package main
+
+import services.ServiceB
+
+def sb = new ServiceB()
+sb.greeting()
diff --git a/groovier-plugin/src/test/resources/services/ServiceA.groovy b/groovier-plugin/src/test/resources/services/ServiceA.groovy
new file mode 100644
index 0000000..9c128e0
--- /dev/null
+++ b/groovier-plugin/src/test/resources/services/ServiceA.groovy
@@ -0,0 +1,12 @@
+package services
+
+class ServiceA {
+
+ void sayHello() {
+ println "Hello from serviceA"
+ }
+
+ void sayGoodbye() {
+ println "Goodbye from serviceA"
+ }
+}
diff --git a/groovier-plugin/src/test/resources/services/ServiceB.groovy b/groovier-plugin/src/test/resources/services/ServiceB.groovy
new file mode 100644
index 0000000..d61b245
--- /dev/null
+++ b/groovier-plugin/src/test/resources/services/ServiceB.groovy
@@ -0,0 +1,14 @@
+package services
+
+class ServiceB {
+
+ private final serviceA = new ServiceA()
+
+ void greeting() {
+ serviceA.sayHello()
+ }
+
+ void farewell() {
+ serviceA.sayGoodbye()
+ }
+}
diff --git a/groovier-scripts/pom.xml b/groovier-scripts/pom.xml
index 505389b..2e9d239 100644
--- a/groovier-scripts/pom.xml
+++ b/groovier-scripts/pom.xml
@@ -5,18 +5,13 @@
groovier
org.groovier
- 0.0.4
+ 0.0.51-SNAPSHOT
4.0.0
groovier-scripts
-
- 17
- 17
-
-
diff --git a/pom.xml b/pom.xml
index b22f847..737f0e9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
org.groovier
groovier
- 0.0.4
+ 0.0.51-SNAPSHOT
pom
Groovier
@@ -18,7 +18,8 @@
- 17
+ 21
+ 21
UTF-8
@@ -28,7 +29,7 @@
org.codehaus.gmavenplus
gmavenplus-plugin
- 1.13.1
+ 4.0.1
@@ -57,7 +58,7 @@
org.apache.maven.plugins
maven-resources-plugin
- 3.2.0
+ 3.3.1
save-resources
@@ -89,7 +90,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.3.2
+ 3.11.1
attach-javadocs
@@ -106,7 +107,6 @@
https://docs.groovy-lang.org/latest/html/api/
public
- false
true
UTF-8
Groovier
@@ -116,7 +116,6 @@
true
true
true
- ${project.build.directory}
../javadocs
true
@@ -124,7 +123,7 @@
org.apache.maven.plugins
maven-source-plugin
- 2.4
+ 3.3.1
attach-sources
@@ -137,11 +136,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
-
-
- ${java.version}
-
+ 3.13.0
org.codehaus.groovy
@@ -153,7 +148,7 @@
org.apache.maven.plugins
maven-shade-plugin
- 3.2.4
+ 3.6.0
package
@@ -211,12 +206,12 @@
net.bytebuddy
byte-buddy-dep
- 1.12.10
+ 1.15.10
org.jetbrains
annotations
- 23.0.0
+ 26.0.1
org.groovier
@@ -231,20 +226,20 @@
org.spigotmc
spigot-api
- 1.20.4-R0.1-SNAPSHOT
+ 1.21.1-R0.1-SNAPSHOT
provided
net.md-5
bungeecord-api
- 1.19-R0.1-SNAPSHOT
+ 1.20-R0.1
jar
provided
com.google.inject
guice
- 5.1.0
+ 6.0.0
javax.inject
@@ -260,12 +255,12 @@
org.apache.groovy
groovy
- 4.0.22
+ 4.0.24
org.junit.jupiter
junit-jupiter-engine
- 5.3.1
+ 5.11.4
test