From b46a5c0bdae09de33925f2b3b336f9afebe3b733 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 19 Feb 2021 09:45:51 -0500 Subject: [PATCH] Allow JSON mod content types from other class loaders --- .../src/mindustry/android/AndroidLauncher.java | 5 ++--- core/src/mindustry/core/Platform.java | 7 +++---- core/src/mindustry/mod/ContentParser.java | 8 ++++++++ core/src/mindustry/mod/Mods.java | 15 +++++++++++---- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/android/src/mindustry/android/AndroidLauncher.java b/android/src/mindustry/android/AndroidLauncher.java index b92865c68a..cd813c6ff0 100644 --- a/android/src/mindustry/android/AndroidLauncher.java +++ b/android/src/mindustry/android/AndroidLauncher.java @@ -72,9 +72,8 @@ public class AndroidLauncher extends AndroidApplication{ } @Override - public Class loadJar(Fi jar, String mainClass) throws Exception{ - DexClassLoader loader = new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, getClassLoader()); - return Class.forName(mainClass, true, loader); + public ClassLoader loadJar(Fi jar, String mainClass) throws Exception{ + return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, getClassLoader()); } @Override diff --git a/core/src/mindustry/core/Platform.java b/core/src/mindustry/core/Platform.java index bddcd3d749..911583f822 100644 --- a/core/src/mindustry/core/Platform.java +++ b/core/src/mindustry/core/Platform.java @@ -20,10 +20,9 @@ import static mindustry.Vars.*; public interface Platform{ - /** Dynamically loads a jar file. */ - default Class loadJar(Fi jar, String mainClass) throws Exception{ - URLClassLoader classLoader = new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, getClass().getClassLoader()); - return Class.forName(mainClass, true, classLoader); + /** Dynamically creates a class loader for a jar file. */ + default ClassLoader loadJar(Fi jar, String mainClass) throws Exception{ + return new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, getClass().getClassLoader()); } /** Steam: Update lobby visibility.*/ diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 1279a98ea4..12fb11fde8 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -705,6 +705,14 @@ public class ContentParser{ try{ return (Class)Class.forName(base); }catch(Exception ignored){ + //try to load from a mod's class loader + for(LoadedMod mod : mods.mods){ + if(mod.loader != null){ + try{ + return (Class)Class.forName(base, true, mod.loader); + }catch(Exception ignore){} + } + } } } diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index 3566b08ebe..41e2bf31ea 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -92,6 +92,8 @@ public class Mods implements Loadable{ var loaded = loadMod(dest, true); mods.add(loaded); requiresReload = true; + //enable the mod on import + Core.settings.put("mod-" + loaded.name + "-enabled", true); sortMods(); //try to load the mod's icon so it displays on import Core.app.post(() -> { @@ -664,9 +666,10 @@ public class Mods implements Loadable{ } } + ClassLoader loader = null; Mod mainMod; - Fi mainFile = zip; + if(android){ mainFile = mainFile.child("classes.dex"); }else{ @@ -687,7 +690,8 @@ public class Mods implements Loadable{ throw new IllegalArgumentException("Java class mods are not supported on iOS."); } - Class main = platform.loadJar(sourceFile, mainClass); + loader = platform.loadJar(sourceFile, mainClass); + Class main = Class.forName(mainClass, true, loader); metas.put(main, meta); mainMod = (Mod)main.getDeclaredConstructor().newInstance(); }else{ @@ -710,7 +714,7 @@ public class Mods implements Loadable{ if(!headless){ Log.info("Loaded mod '@' in @ms", meta.name, Time.elapsed()); } - return new LoadedMod(sourceFile, zip, mainMod, meta); + return new LoadedMod(sourceFile, zip, mainMod, loader, meta); }catch(Exception e){ //delete root zip file so it can be closed on windows @@ -743,10 +747,13 @@ public class Mods implements Loadable{ public ModState state = ModState.enabled; /** Icon texture. Should be disposed. */ public @Nullable Texture iconTexture; + /** Class loader for JAR mods. Null if the mod isn't loaded or this isn't a jar mod. */ + public @Nullable ClassLoader loader; - public LoadedMod(Fi file, Fi root, Mod main, ModMeta meta){ + public LoadedMod(Fi file, Fi root, Mod main, ClassLoader loader, ModMeta meta){ this.root = root; this.file = file; + this.loader = loader; this.main = main; this.meta = meta; this.name = meta.name.toLowerCase().replace(" ", "-");