package net.fourbytes.shadow.utils.backend; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Array; import net.fourbytes.shadow.Shadow; import net.fourbytes.shadow.mod.ChainClassLoader; import net.fourbytes.shadow.mod.IMod; import net.fourbytes.shadow.mod.ModFile; import net.fourbytes.shadow.mod.ModManager; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.net.URLDecoder; /** * DesktopModLoader is an implementation of ModLoader for * the LWJGL and JGLFW (and maybe other desktop) backends. */ public class DesktopModLoader extends ModLoader { public DesktopModLoader() { } public String root; @Override public void init(String root) { if (root == null) { String path = ""; try { String rawpath = Shadow.class.getProtectionDomain().getCodeSource().getLocation().getPath(); path = URLDecoder.decode(rawpath, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } FileHandle fh = Gdx.files.absolute(path).parent(); root = fh.path(); } this.root = root; FileHandle folder = Gdx.files.absolute(root); FileHandle fhbl = folder.child("blacklist.txt"); Array<String> blacklist = new Array<String>(); if (!fhbl.exists()) { try { fhbl.file().createNewFile(); } catch (IOException e) { e.printStackTrace(); } } else { BufferedReader reader = new BufferedReader(fhbl.reader()); try { String line; do { line = reader.readLine(); if (line != null) { blacklist.add(line); } } while (line != null); } catch (IOException e1) { e1.printStackTrace(); } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } init(folder.path(), blacklist); } @Override public void init(String root, Array<String> blacklist) { FileHandle folder = Gdx.files.absolute(root); for (FileHandle fh : folder.list()) { if (blacklist.contains(fh.name(), false)) { ModManager.filesIgnored.add(new ModFile(fh)); continue; } load(fh.path()); } } @Override public IMod load(ModFile mf) { return load(mf.fh.path()); } @Override public IMod load(String path) { FileHandle fh = Gdx.files.absolute(path); IMod mod = null; ModFile mf = new ModFile(fh); if (fh.exists() && !fh.isDirectory() && fh.name().startsWith("mod_") && (fh.extension().toLowerCase().contains("zip") || fh.extension().toLowerCase().contains("jar"))) { System.out.println(fh.name()+" seems to be mod.."); try { //Getting and creating needed class loaders ClassLoader ownCL = Shadow.class.getClassLoader(); ChainClassLoader chainCL = new ChainClassLoader(ownCL); URLClassLoader cl = new URLClassLoader(new URL[] {fh.file().toURI().toURL()}, chainCL); chainCL.blacklist = new String[] {"net.fourbytes.shadow.mod.Config"}; if (ModManager.mods.size < 0) { IMod pmod = ModManager.mods.items[ModManager.mods.size - 1]; ClassLoader parentCL = pmod.getClass().getClassLoader().getParent(); System.out.println(parentCL); if (parentCL instanceof ChainClassLoader) { ChainClassLoader parentChainCL = (ChainClassLoader) parentCL; parentChainCL.chainChild = chainCL; chainCL.chainParent = parentChainCL; } } //Getting mod class name Class<?> cConfig = cl.loadClass("net.fourbytes.shadow.mod.Config"); Method method = cConfig.getDeclaredMethod("getModClass"); Class<?> clazzNT = (Class<?>) method.invoke(null); if (IMod.class.isAssignableFrom(clazzNT)) { Class<? extends IMod> clazz = clazzNT.asSubclass(IMod.class); //Creating mod mod = clazz.getConstructor().newInstance(); //Adding mod to manager ModManager.mods.add(mod); mf.mod = mod; ModManager.filesLoaded.add(mf); ModManager.mapModFile.put(mod, mf); System.out.println("true story"); } else { System.out.println("it's a trap!"); } } catch (Exception e) { e.printStackTrace(); System.out.println(".. or not."); if (ModManager.filesFailed.contains(mf, false)) { ModManager.filesFailed.add(mf); } } } loadFailed(); return mod; } @Override public void blacklist(ModFile modfile, boolean blacklist) { FileHandle folder = Gdx.files.absolute(root); FileHandle fhbl = folder.child("blacklist.txt"); boolean blacklisted = false; Array<String> lines = new Array<String>(String.class); BufferedReader br = new BufferedReader(fhbl.reader()); try { String line; while ((line = br.readLine()) != null) { if (line.trim().equals(modfile.fh.name())) { blacklisted = true; } else { lines.add(line); } } } catch (IOException e) { e.printStackTrace(); } finally { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (!blacklist && blacklisted) { BufferedWriter bw = new BufferedWriter(fhbl.writer(false)); try { for (int i = 0; i < lines.size; i++) { String line = lines.items[i].trim(); if (line.length() > 0 && !line.equals(modfile.fh.name())) { bw.write(line + "\n"); } } bw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } else if (blacklist && !blacklisted) { try { fhbl.writeBytes((modfile.fh.name() + "\n").getBytes("UTF-8"), true); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } @Override public void delete(ModFile modfile) { if (!modfile.canDelete) { throw new RuntimeException("Can not uninstall "+modfile.pkg+" as ModFile.canDelete == false"); } modfile.fh.delete(); } }