diff --git a/.idea/codeStyles/Plexus_Code_Style.xml b/.idea/codeStyles/Plexus_Code_Style.xml
index a7db3e4..3dc4a27 100644
--- a/.idea/codeStyles/Plexus_Code_Style.xml
+++ b/.idea/codeStyles/Plexus_Code_Style.xml
@@ -1,33 +1,8 @@
-
-
-
-
-
-
-
-
-
+
+
+
@@ -36,14 +11,10 @@
-
-
-
-
\ No newline at end of file
diff --git a/server/build.gradle b/server/build.gradle
index 1407cb8..986c687 100644
--- a/server/build.gradle
+++ b/server/build.gradle
@@ -1,28 +1,18 @@
plugins {
- id "net.minecrell.plugin-yml.bukkit" version "0.5.3"
+ id "net.minecrell.plugin-yml.paper" version "0.6.0"
}
dependencies {
library "org.projectlombok:lombok:1.18.28"
annotationProcessor "org.projectlombok:lombok:1.18.28"
- library "org.json:json:20230227"
- library "commons-io:commons-io:2.12.0"
- library "dev.morphia.morphia:morphia-core:2.3.4"
- library "redis.clients:jedis:4.4.2"
+ library "org.json:json:20230618"
+ library "commons-io:commons-io:2.13.0"
+ library "dev.morphia.morphia:morphia-core:2.3.5"
+ library "redis.clients:jedis:5.0.0-beta2"
library "org.mariadb.jdbc:mariadb-java-client:3.1.4"
library "com.zaxxer:HikariCP:5.0.1"
- library "org.apache.httpcomponents.client5:httpclient5:5.2.1"
- library "org.apache.commons:commons-lang3:3.12.0"
- library "org.apache.maven.resolver:maven-resolver-api:1.9.10"
- library "org.apache.maven.resolver:maven-resolver-impl:1.9.10"
- library "org.apache.maven.resolver:maven-resolver-connector-basic:1.9.10"
- library "org.apache.maven.resolver:maven-resolver-transport-http:1.9.10"
- library "org.apache.maven:maven-resolver-provider:3.9.2"
- library "org.eclipse.jetty:jetty-server:11.0.15"
- library "org.eclipse.jetty:jetty-servlet:11.0.15"
- library "org.eclipse.jetty:jetty-proxy:11.0.15"
- library "com.google.code.gson:gson:2.10.1"
- compileOnly "io.papermc.paper:paper-api:1.20-R0.1-SNAPSHOT"
+ library "org.apache.maven.resolver:maven-resolver-transport-http:1.9.13"
+ compileOnly "io.papermc.paper:paper-api:1.20.1-R0.1-SNAPSHOT"
compileOnly("com.github.MilkBowl:VaultAPI:1.7.1") {
exclude group: "org.bukkit", module: "bukkit"
}
@@ -40,16 +30,31 @@ shadowJar {
relocate "org.bstats", "dev.plex"
}
-bukkit {
+paper {
name = "Plex"
version = project.version
description = "Plex provides a new experience for freedom servers."
main = "dev.plex.Plex"
+ loader = "dev.plex.PlexLibraryManager"
website = "https://plex.us.org"
authors = ["Telesphoreo", "taahanis", "supernt"]
// Load BukkitTelnet and LibsDisguises before Plex so the modules register properly
- softDepend = ["BukkitTelnet", "LibsDisguises", "Vault"]
- apiVersion = "1.18"
+ apiVersion = "1.19"
+ generateLibrariesJson = true
+ serverDependencies {
+ 'BukkitTelnet' {
+ required = false
+ load = 'BEFORE'
+ }
+ 'LibsDisguises' {
+ required = false
+ load = 'BEFORE'
+ }
+ 'Vault' {
+ required = false
+ load = 'BEFORE'
+ }
+ }
}
String getGitHash() {
diff --git a/server/src/main/java/dev/plex/PlexLibraryManager.java b/server/src/main/java/dev/plex/PlexLibraryManager.java
new file mode 100644
index 0000000..eaea137
--- /dev/null
+++ b/server/src/main/java/dev/plex/PlexLibraryManager.java
@@ -0,0 +1,66 @@
+package dev.plex;
+
+import com.google.gson.Gson;
+import io.papermc.paper.plugin.loader.PluginClasspathBuilder;
+import io.papermc.paper.plugin.loader.PluginLoader;
+import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+public class PlexLibraryManager implements PluginLoader
+{
+ @Override
+ public void classloader(@NotNull PluginClasspathBuilder classpathBuilder)
+ {
+
+ MavenLibraryResolver resolver = new MavenLibraryResolver();
+ PluginLibraries pluginLibraries = load();
+ pluginLibraries.asDependencies().forEach(resolver::addDependency);
+ pluginLibraries.asRepositories().forEach(resolver::addRepository);
+ // The plugin is null, a hacky way to check whether to load Jetty or not
+ if (new File("plugins/Plex/modules/Plex-HTTPD.jar").isFile())
+ {
+ resolver.addDependency(new Dependency(new DefaultArtifact("org.eclipse.jetty:jetty-server:11.0.15"), null));
+ resolver.addDependency(new Dependency(new DefaultArtifact("org.eclipse.jetty:jetty-servlet:11.0.15"), null));
+ resolver.addDependency(new Dependency(new DefaultArtifact("org.eclipse.jetty:jetty-proxy:11.0.15"), null));
+ }
+ classpathBuilder.addLibrary(resolver);
+ }
+
+ public PluginLibraries load()
+ {
+ try (var in = getClass().getResourceAsStream("/paper-libraries.json"))
+ {
+ return new Gson().fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), PluginLibraries.class);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private record PluginLibraries(Map repositories, List dependencies)
+ {
+ public Stream asDependencies()
+ {
+ return dependencies.stream()
+ .map(d -> new Dependency(new DefaultArtifact(d), null));
+ }
+
+ public Stream asRepositories()
+ {
+ return repositories.entrySet().stream()
+ .map(e -> new RemoteRepository.Builder(e.getKey(), "default", e.getValue()).build());
+ }
+ }
+}
diff --git a/server/src/main/java/dev/plex/module/ModuleManager.java b/server/src/main/java/dev/plex/module/ModuleManager.java
index 7a07d62..82cebd6 100644
--- a/server/src/main/java/dev/plex/module/ModuleManager.java
+++ b/server/src/main/java/dev/plex/module/ModuleManager.java
@@ -3,7 +3,6 @@ package dev.plex.module;
import com.google.common.collect.Lists;
import dev.plex.Plex;
import dev.plex.module.exception.ModuleLoadException;
-import dev.plex.module.loader.LibraryLoader;
import dev.plex.util.PlexLog;
import lombok.Getter;
import org.apache.logging.log4j.LogManager;
@@ -24,11 +23,9 @@ import java.util.List;
public class ModuleManager
{
private final List modules = Lists.newArrayList();
- private final LibraryLoader libraryLoader;
public ModuleManager()
{
- this.libraryLoader = new LibraryLoader(Plex.get().getLogger());
}
public void loadAllModules()
diff --git a/server/src/main/java/dev/plex/module/exception/ModuleLoadException.java b/server/src/main/java/dev/plex/module/exception/ModuleLoadException.java
index 0a46640..23b76a2 100644
--- a/server/src/main/java/dev/plex/module/exception/ModuleLoadException.java
+++ b/server/src/main/java/dev/plex/module/exception/ModuleLoadException.java
@@ -6,5 +6,4 @@ public class ModuleLoadException extends RuntimeException
{
super(s);
}
-
}
diff --git a/server/src/main/java/dev/plex/module/loader/CustomClassLoader.java b/server/src/main/java/dev/plex/module/loader/CustomClassLoader.java
deleted file mode 100644
index 740e8fd..0000000
--- a/server/src/main/java/dev/plex/module/loader/CustomClassLoader.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package dev.plex.module.loader;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-
-public class CustomClassLoader extends URLClassLoader
-{
- /*public CustomClassLoader(URL[] urls, ClassLoader parent) {
- super(urls, parent);
- for (URL url : urls) {
- super.addURL(url);
- }
- }*/
-
- public CustomClassLoader(URL jarInJar, ClassLoader parent)
- {
- super(new URL[]{extractJar(jarInJar)}, parent);
- addURL(jarInJar);
- }
-
-
- static URL extractJar(URL jarInJar) throws RuntimeException
- {
- // get the jar-in-jar resource
- if (jarInJar == null)
- {
- throw new RuntimeException("Could not locate jar-in-jar");
- }
-
- // create a temporary file
- // on posix systems by default this is only read/writable by the process owner
- Path path;
- try
- {
- path = Files.createTempFile("plex-jarinjar", ".jar.tmp");
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to create a temporary file", e);
- }
-
- // mark that the file should be deleted on exit
- path.toFile().deleteOnExit();
-
- // copy the jar-in-jar to the temporary file path
- try (InputStream in = jarInJar.openStream())
- {
- Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to copy jar-in-jar to temporary path", e);
- }
-
- try
- {
- return path.toUri().toURL();
- }
- catch (MalformedURLException e)
- {
- throw new RuntimeException("Unable to get URL from path", e);
- }
- }
-}
diff --git a/server/src/main/java/dev/plex/module/loader/LibraryLoader.java b/server/src/main/java/dev/plex/module/loader/LibraryLoader.java
deleted file mode 100644
index 97bcf74..0000000
--- a/server/src/main/java/dev/plex/module/loader/LibraryLoader.java
+++ /dev/null
@@ -1,266 +0,0 @@
-package dev.plex.module.loader;
-
-import com.google.common.collect.Lists;
-import dev.plex.Plex;
-import dev.plex.module.PlexModule;
-import dev.plex.module.PlexModuleFile;
-import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
-import org.eclipse.aether.DefaultRepositorySystemSession;
-import org.eclipse.aether.RepositorySystem;
-import org.eclipse.aether.artifact.Artifact;
-import org.eclipse.aether.artifact.DefaultArtifact;
-import org.eclipse.aether.collection.CollectRequest;
-import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
-import org.eclipse.aether.graph.Dependency;
-import org.eclipse.aether.impl.DefaultServiceLocator;
-import org.eclipse.aether.repository.LocalRepository;
-import org.eclipse.aether.repository.RemoteRepository;
-import org.eclipse.aether.repository.RepositoryPolicy;
-import org.eclipse.aether.resolution.ArtifactResult;
-import org.eclipse.aether.resolution.DependencyRequest;
-import org.eclipse.aether.resolution.DependencyResolutionException;
-import org.eclipse.aether.resolution.DependencyResult;
-import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
-import org.eclipse.aether.spi.connector.transport.TransporterFactory;
-import org.eclipse.aether.transfer.AbstractTransferListener;
-import org.eclipse.aether.transfer.TransferCancelledException;
-import org.eclipse.aether.transfer.TransferEvent;
-import org.eclipse.aether.transport.http.HttpTransporterFactory;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.JarURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-//TODO: doesn't work
-
-public class LibraryLoader
-{
- private final Logger logger;
- private final RepositorySystem repository;
- private final DefaultRepositorySystemSession session;
- private final List repositories;
-
- public LibraryLoader(@NotNull Logger logger)
- {
- this.logger = logger;
-
- DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
- locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
- locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
-
- this.repository = locator.getService(RepositorySystem.class);
- this.session = MavenRepositorySystemUtils.newSession();
-
- session.setChecksumPolicy(RepositoryPolicy.CHECKSUM_POLICY_FAIL);
- session.setLocalRepositoryManager(repository.newLocalRepositoryManager(session, new LocalRepository("libraries")));
- session.setTransferListener(new AbstractTransferListener()
- {
- @Override
- public void transferStarted(@NotNull TransferEvent event) throws TransferCancelledException
- {
- logger.log(Level.INFO, "Downloading {0}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName());
- }
- });
- session.setReadOnly();
-
- this.repositories = repository.newResolutionRepositories(session, Arrays.asList(new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2").build()));
- }
-
- @Nullable
- public ClassLoader createLoader(@NotNull PlexModule module, @NotNull PlexModuleFile moduleFile)
- {
- if (moduleFile.getLibraries().isEmpty())
- {
- return null;
- }
- logger.log(Level.INFO, "Loading libraries for {0}", new Object[]{moduleFile.getName()});
- logger.log(Level.INFO, "[{0}] Loading {1} libraries... please wait", new Object[]
- {
- moduleFile.getName(), moduleFile.getLibraries().size()
- });
-
- List dependencies = new ArrayList<>();
- List> classes = Lists.newArrayList();
- List files = Lists.newArrayList();
- for (String library : moduleFile.getLibraries())
- {
- Artifact artifact = new DefaultArtifact(library);
- Dependency dependency = new Dependency(artifact, null);
-
- dependencies.add(dependency);
- }
-
- DependencyResult result;
- try
- {
- result = repository.resolveDependencies(session, new DependencyRequest(new CollectRequest((Dependency) null, dependencies, repositories), null));
- }
- catch (DependencyResolutionException ex)
- {
- throw new RuntimeException("Error resolving libraries", ex);
- }
-
- List jarFiles = new ArrayList<>();
- for (ArtifactResult artifact : result.getArtifactResults())
- {
- File file = artifact.getArtifact().getFile();
- files.add(file);
- URL url;
- try
- {
- url = file.toURI().toURL();
- }
- catch (MalformedURLException ex)
- {
- throw new AssertionError(ex);
- }
-
- jarFiles.add(url);
- logger.log(Level.INFO, "[{0}] Loaded library {1}", new Object[]
- {
- moduleFile.getName(), file
- });
- }
-
- /*List jarFiles = Lists.newArrayList();
- List artifacts = Lists.newArrayList();
-
-
- List> classes = new ArrayList<>();
-
- for (String library : moduleFile.getLibraries()) {
- Artifact artifact = new DefaultArtifact(library);
- ArtifactRequest request = new ArtifactRequest();
- request.setArtifact(artifact);
- request.addRepository(this.repositories.get(0));
- try {
- ArtifactResult result = this.repository.resolveArtifact(this.session, request);
- artifact = result.getArtifact();
- jarFiles.add(artifact.getFile().toURI().toURL());
- logger.log(Level.INFO, "Loaded library {0} for {1}", new Object[]{
- artifact.getFile().toURI().toURL().toString(),
- moduleFile.getName()
- });
- artifacts.add(artifact);
- } catch (ArtifactResolutionException | MalformedURLException e) {
- e.printStackTrace();
- }
-
- }*/
- logger.log(Level.INFO, "Loaded {0} libraries for {1}", new Object[]{jarFiles.size(), moduleFile.getName()});
-
- // jarFiles.forEach(jar -> new CustomClassLoader(jar, Plex.class.getClassLoader()));
- // jarFiles.forEach(jar -> new CustomClassLoader(jar, Plex.class.getClassLoader()));
-
- /*URLClassLoader loader = new URLClassLoader(jarFiles.toArray(URL[]::new), Plex.class.getClassLoader());
-
- dependencies.forEach(artifact -> {
- ArrayList classNames;
- try {
- classNames = getClassNamesFromJar(new JarFile(artifact.getArtifact().getFile()));
- for (String className : classNames) {
- Class> classToLoad = Class.forName(className, true, loader);
- classes.add(classToLoad);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- });
-
- classes.forEach(clazz -> logger.log(Level.INFO, "Loading class {0}", new Object[]{clazz.getName()}));*/
- jarFiles.forEach(url ->
- {
- JarURLConnection connection;
- try
- {
- URL url2 = new URL("jar:" + url.toString() + "!/");
- /*
- connection = (JarURLConnection) url2.openConnection();
- logger.log(Level.INFO, "Jar File: " + connection.getJarFileURL().toString());*/
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- });
- return new URLClassLoader(files.stream().map(File::toURI).map(uri ->
- {
- try
- {
- return uri.toURL();
- }
- catch (MalformedURLException e)
- {
- e.printStackTrace();
- return null;
- }
- }).toList().toArray(URL[]::new)/*jarFiles.stream().map(url -> {
- try {
- return new URL("jar:" + url.toString() + "!/");
- } catch (MalformedURLException e) {
- e.printStackTrace();
- return null;
- }
- }).toList().toArray(URL[]::new)*/, Plex.class.getClassLoader())/*new CustomClassLoader(jarFiles.toArray(URL[]::new), Plex.class.getClassLoader())*/;
- }
-
- /*public List> loadDependency(List paths) throws Exception {
-
- List> classes = new ArrayList<>();
-
- for (Path path : paths) {
-
- URL url = path.toUri().toURL();
- URLClassLoader child = new URLClassLoader(new URL[]{url}, this.getClass().getClassLoader());
-
- ArrayList classNames = getClassNamesFromJar(path.toString());
-
- for (String className : classNames) {
- Class classToLoad = Class.forName(className, true, child);
- classes.add(classToLoad);
- }
- }
-
- return classes;
- }*/
-
-
- private ArrayList getClassNamesFromJar(JarFile file) throws Exception
- {
- ArrayList classNames = new ArrayList<>();
- try
- {
- //Iterate through the contents of the jar file
- Enumeration entries = file.entries();
- while (entries.hasMoreElements())
- {
- JarEntry entry = entries.nextElement();
- //Pick file that has the extension of .class
- if ((entry.getName().endsWith(".class")))
- {
- String className = entry.getName().replaceAll("/", "\\.");
- String myClass = className.substring(0, className.lastIndexOf('.'));
- classNames.add(myClass);
- }
- }
- }
- catch (Exception e)
- {
- throw new Exception("Error while getting class names from jar", e);
- }
- return classNames;
- }
-}