Downloaded LWJGL libraries

- LWJGL is no longer shaded into the Bukkit jar
- plugin.yml lists the LWJGL jars and Linux natives as Spigot libraries
- The Paper loader resolves the same plugin.yml list through the Maven Central mirror
- The packed payload no longer reserves the LWJGL natives prefix
- Tests cover reading the library list from the plugin jar
This commit is contained in:
Brian Neumann-Fopiano committed 2026-10-28 21:55:09 -04:00
1 parent aec8f5be8e
commit 0d76d81dab
5 files changed
+67 -8

No files matched your search

+11
View File
@@ -28,6 +28,16 @@ dependencies {
}
}
String lwjglVersion = libs.versions.lwjgl.get()
List<String> mavenLibraries = [
"org.lwjgl:lwjgl:${lwjglVersion}",
"org.lwjgl:lwjgl:jar:natives-linux:${lwjglVersion}",
"org.lwjgl:lwjgl-opengl:${lwjglVersion}",
"org.lwjgl:lwjgl-opengl:jar:natives-linux:${lwjglVersion}",
"org.lwjgl:lwjgl-egl:${lwjglVersion}",
"org.lwjgl:lwjgl-jawt:${lwjglVersion}",
].collect { GString coordinate -> coordinate.toString() }
tasks.named('processResources').configure {
def pluginProperties = [
name : rootProject.name,
@@ -35,6 +45,7 @@ tasks.named('processResources').configure {
apiVersion: apiVersion,
main : mainClass,
bootstrapper: bootstrapperClass,
libraries : mavenLibraries.collect { String coordinate -> "'${coordinate}'" }.join(', '),
]
inputs.properties(pluginProperties)
filesMatching(['**/paper-plugin.yml', '**/plugin.yml']) {
@@ -6,12 +6,22 @@ import io.papermc.paper.plugin.bootstrap.PluginProviderContext;
import io.papermc.paper.plugin.loader.PluginClasspathBuilder;
import io.papermc.paper.plugin.loader.PluginLoader;
import io.papermc.paper.plugin.loader.library.impl.JarLibrary;
import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver;
import org.bukkit.configuration.file.YamlConfiguration;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.repository.RemoteRepository;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@SuppressWarnings("UnstableApiUsage")
public final class IrisPluginLoader implements PluginLoader {
@@ -40,6 +50,21 @@ public final class IrisPluginLoader implements PluginLoader {
classpathBuilder.addLibrary(new JarLibrary(library));
}
}
classpathBuilder.addLibrary(mavenResolver(mavenLibraries(context.getPluginSource())));
}
static List<String> mavenLibraries(Path pluginJar) {
try (ZipFile jar = new ZipFile(pluginJar.toFile())) {
ZipEntry descriptor = jar.getEntry("plugin.yml");
if (descriptor == null) {
throw new IllegalStateException("The Iris jar " + pluginJar + " has no plugin.yml library list.");
}
try (Reader reader = new InputStreamReader(jar.getInputStream(descriptor), StandardCharsets.UTF_8)) {
return YamlConfiguration.loadConfiguration(reader).getStringList("libraries");
}
} catch (IOException failure) {
throw new IllegalStateException("Unable to read the Iris library list from " + pluginJar + ".", failure);
}
}
static List<Path> relocatedLibraries(Path libraryRoot) {
@@ -59,6 +84,16 @@ public final class IrisPluginLoader implements PluginLoader {
}
}
private static MavenLibraryResolver mavenResolver(List<String> coordinates) {
MavenLibraryResolver resolver = new MavenLibraryResolver();
resolver.addRepository(new RemoteRepository.Builder("central", "default",
MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR).build());
for (String coordinate : coordinates) {
resolver.addDependency(new Dependency(new DefaultArtifact(coordinate), null));
}
return resolver;
}
private static boolean isRelocatedLibrary(Path path) {
int count = path.getNameCount();
for (int i = 0; i < count - 2; i++) {
@@ -27,3 +27,4 @@ permissions:
description: Allows survival players to fell Iris-managed trees with an axe.
default: op
api-version: '${apiVersion}'
libraries: [ ${libraries} ]
@@ -4,9 +4,13 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import static org.junit.Assert.assertEquals;
@@ -31,4 +35,19 @@ public class IrisPluginLoaderTest {
assertEquals(List.of(relocatedCaffeine, relocatedGson), libraries);
}
@Test
public void readsMavenLibrariesFromTheSpigotDescriptorInThePluginJar() throws Exception {
Path jar = temporaryFolder.getRoot().toPath().resolve("Iris.jar");
try (OutputStream file = Files.newOutputStream(jar); ZipOutputStream zip = new ZipOutputStream(file)) {
zip.putNextEntry(new ZipEntry("plugin.yml"));
zip.write("name: Iris\nlibraries: [ 'org.lwjgl:lwjgl:3.4.3', 'org.lwjgl:lwjgl:jar:natives-linux:3.4.3' ]\n"
.getBytes(StandardCharsets.UTF_8));
zip.closeEntry();
}
List<String> libraries = IrisPluginLoader.mavenLibraries(jar);
assertEquals(List.of("org.lwjgl:lwjgl:3.4.3", "org.lwjgl:lwjgl:jar:natives-linux:3.4.3"), libraries);
}
}
+1 -8
View File
@@ -179,13 +179,6 @@ def jarJar = configurations.create('jarJar')
dependencies {
add('included', project(path: ':core', configuration: 'shadow'))
add('included', project(path: ':adapters:bukkit:plugin', configuration: 'runtimeElements'))
// Shaded: the runtime downloader can neither fetch the natives classifiers nor relocate lwjgl's own jar.
add('included', libs.lwjgl)
add('included', libs.lwjgl.opengl)
add('included', libs.lwjgl.egl)
add('included', libs.lwjgl.jawt)
add('included', variantOf(libs.lwjgl) { classifier('natives-linux') })
add('included', variantOf(libs.lwjgl.opengl) { classifier('natives-linux') })
add('jarJar', project(':core:agent'))
}
@@ -742,7 +735,7 @@ pluginPackaging {
policyName = 'Iris Bukkit'
packed = true
packedJarAccessors = ['art/arcane/iris/platform/bukkit/plugin/VolmitPlugin#getJarFile']
packedPayloadOnlyPrefixes = ['linux/x64/org/lwjgl/', 'iris-language-guides/']
packedPayloadOnlyPrefixes = ['iris-language-guides/']
stripDirectories = true
stripLocalVariables = true
releaseCompression = providers.gradleProperty('compactRelease')