/** Set up reflection methods required by the loader */ @SuppressWarnings("unchecked") private boolean prepareLoader() { try { // addURL method is used by the class loader to mAddUrl = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); mAddUrl.setAccessible(true); Formatter minecraftLogFormatter = null; try { Class<? extends Formatter> formatterClass = (Class<? extends Formatter>) Minecraft.class .getClassLoader() .loadClass( ModUtilities.getObfuscatedFieldName( "net.minecraft.src.ConsoleLogFormatter", "em")); Constructor<? extends Formatter> defaultConstructor = formatterClass.getDeclaredConstructor(); defaultConstructor.setAccessible(true); minecraftLogFormatter = defaultConstructor.newInstance(); } catch (Exception ex) { ConsoleLogManager.init(); minecraftLogFormatter = ConsoleLogManager.loggerLogManager.getHandlers()[0].getFormatter(); } logger.setUseParentHandlers(false); StreamHandler consoleHandler = new ConsoleHandler(); if (minecraftLogFormatter != null) consoleHandler.setFormatter(minecraftLogFormatter); logger.addHandler(consoleHandler); FileHandler logFileHandler = new FileHandler( new File(Minecraft.getMinecraftDir(), "LiteLoader.txt").getAbsolutePath()); if (minecraftLogFormatter != null) logFileHandler.setFormatter(minecraftLogFormatter); logger.addHandler(logFileHandler); } catch (Throwable th) { logger.log(Level.SEVERE, "Error initialising LiteLoader", th); return false; } return true; }
/** * @param classloader * @param superClass * @param classes * @param className */ @SuppressWarnings("unchecked") private static void checkAndAddClass( ClassLoader classloader, Class superClass, LinkedList<Class> classes, String className) { if (className.indexOf('$') > -1) return; try { Class subClass = classloader.loadClass(className); if (subClass != null && !superClass.equals(subClass) && superClass.isAssignableFrom(subClass) && !subClass.isInterface() && !classes.contains(subClass)) { classes.add(subClass); } } catch (Throwable th) { logger.log(Level.WARNING, "checkAndAddClass error", th); } }
/** * Find mod classes in the class path and enumerated mod files list * * @param classPathEntries Java class path split into string entries * @return map of classes to load */ private HashMap<String, Class> findModClasses( String[] classPathEntries, LinkedList<File> modFiles) { // To try to avoid loading the same mod multiple times if it appears in more than one entry in // the class path, we index // the mods by name and hopefully match only a single instance of a particular mod HashMap<String, Class> modsToLoad = new HashMap<String, Class>(); try { logger.info("Searching protection domain code source..."); File packagePath = new File(LiteLoader.class.getProtectionDomain().getCodeSource().getLocation().toURI()); LinkedList<Class> modClasses = getSubclassesFor(packagePath, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod"); for (Class mod : modClasses) { modsToLoad.put(mod.getSimpleName(), mod); } if (modClasses.size() > 0) logger.info(String.format("Found %s potential matches", modClasses.size())); } catch (Throwable th) { logger.warning("Error loading from local class path: " + th.getMessage()); } // Search through the class path and find mod classes for (String classPathPart : classPathEntries) { logger.info(String.format("Searching %s...", classPathPart)); File packagePath = new File(classPathPart); LinkedList<Class> modClasses = getSubclassesFor(packagePath, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod"); for (Class mod : modClasses) { modsToLoad.put(mod.getSimpleName(), mod); } if (modClasses.size() > 0) logger.info(String.format("Found %s potential matches", modClasses.size())); } // Search through mod files and find mod classes for (File modFile : modFiles) { logger.info(String.format("Searching %s...", modFile.getAbsolutePath())); LinkedList<Class> modClasses = getSubclassesFor(modFile, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod"); for (Class mod : modClasses) { modsToLoad.put(mod.getSimpleName(), mod); } if (modClasses.size() > 0) logger.info(String.format("Found %s potential matches", modClasses.size())); } return modsToLoad; }
/** * Create mod instances from the enumerated classes * * @param modsToLoad List of mods to load */ private void loadMods(HashMap<String, Class> modsToLoad) { if (modsToLoad == null) { logger.info("Mod class discovery failed. Not loading any mods!"); return; } logger.info("Discovered " + modsToLoad.size() + " total mod(s)"); for (Class mod : modsToLoad.values()) { try { logger.info("Loading mod from " + mod.getName()); LiteMod newMod = (LiteMod) mod.newInstance(); mods.add(newMod); logger.info( "Successfully added mod " + newMod.getName() + " version " + newMod.getVersion()); } catch (Throwable th) { logger.warning(th.toString()); th.printStackTrace(); } } }