/** Initialise mod hooks */ private void initHooks() { try { // Chat hook if ((chatListeners.size() > 0 || chatFilters.size() > 0) && !chatHooked) { chatHooked = true; HookChat.Register(); HookChat.RegisterPacketHandler(this); } // Login hook if ((preLoginListeners.size() > 0 || loginListeners.size() > 0) && !loginHooked) { loginHooked = true; ModUtilities.registerPacketOverride(1, HookLogin.class); HookLogin.loader = this; } // Plugin channels hook if (pluginChannelListeners.size() > 0 && !pluginChannelHooked) { pluginChannelHooked = true; HookPluginChannels.Register(); HookPluginChannels.RegisterPacketHandler(this); } // Tick hook if (!tickHooked) { tickHooked = true; PrivateFields.minecraftProfiler.SetFinal(minecraft, new HookProfiler(this, logger)); } } catch (Exception ex) { logger.log(Level.WARNING, "Error creating hooks", ex); ex.printStackTrace(); } }
/** * 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; }
/** * Find mod files in the "mods" folder * * @param modFolder Folder to search * @param modFiles List of mod files to load */ protected void findModFiles(File modFolder, LinkedList<File> modFiles) { List<String> supportedVerions = Arrays.asList(SUPPORTED_VERSIONS); for (File modFile : modFolder.listFiles(this)) { try { // Check for a version file ZipFile modZip = new ZipFile(modFile); ZipEntry version = modZip.getEntry("version.txt"); if (version != null) { // Read the version string InputStream versionStream = modZip.getInputStream(version); BufferedReader versionReader = new BufferedReader(new InputStreamReader(versionStream)); String strVersion = versionReader.readLine(); versionReader.close(); // Only add the mod if the version matches and we were able to successfully add it to the // class path if (supportedVerions.contains(strVersion) && addURLToClassPath(modFile.toURI().toURL())) { modFiles.add(modFile); } } modZip.close(); } catch (Exception ex) { logger.warning( "Error enumerating '" + modFile.getAbsolutePath() + "': Invalid zip file or error reading file"); } } }
/** * @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); } }
/** Initialise the mods which were loaded */ private void initMods() { loadedModsList = ""; int loadedModsCount = 0; for (Iterator<LiteMod> iter = mods.iterator(); iter.hasNext(); ) { LiteMod mod = iter.next(); try { logger.info("Initialising mod " + mod.getName() + " version " + mod.getVersion()); mod.init(); if (mod instanceof Tickable) { addTickListener((Tickable) mod); } if (mod instanceof InitCompleteListener) { addInitListener((InitCompleteListener) mod); } if (mod instanceof RenderListener) { addRenderListener((RenderListener) mod); } if (mod instanceof ChatFilter) { addChatFilter((ChatFilter) mod); } if (mod instanceof ChatListener && !(mod instanceof ChatFilter)) { addChatListener((ChatListener) mod); } if (mod instanceof PreLoginListener) { addPreLoginListener((PreLoginListener) mod); } if (mod instanceof LoginListener) { addLoginListener((LoginListener) mod); } if (mod instanceof PluginChannelListener) { addPluginChannelListener((PluginChannelListener) mod); } loadedModsList += String.format("\n - %s version %s", mod.getName(), mod.getVersion()); loadedModsCount++; } catch (Throwable th) { logger.log(Level.WARNING, "Error initialising mod '" + mod.getName(), th); iter.remove(); } } loadedModsList = String.format("%s loaded mod(s)%s", loadedModsCount, loadedModsList); }
/** Enumerate the java class path and "mods" folder to find mod classes, then load the classes */ private void prepareMods() { // List of mod files in the "mods" folder LinkedList<File> modFiles = new LinkedList<File>(); // Find and enumerate the "mods" folder File modFolder = getModsFolder(); if (modFolder.exists() && modFolder.isDirectory()) { logger.info("Mods folder found, searching " + modFolder.getPath()); findModFiles(modFolder, modFiles); logger.info("Found " + modFiles.size() + " mod file(s)"); } // Find and enumerate classes on the class path HashMap<String, Class> modsToLoad = null; try { logger.info("Enumerating class path..."); String classPath = System.getProperty("java.class.path"); String classPathSeparator = System.getProperty("path.separator"); String[] classPathEntries = classPath.split(classPathSeparator); logger.info(String.format("Class path separator=\"%s\"", classPathSeparator)); logger.info( String.format( "Class path entries=(\n classpathEntry=%s\n)", classPath.replace(classPathSeparator, "\n classpathEntry="))); logger.info("Loading mods from class path..."); modsToLoad = findModClasses(classPathEntries, modFiles); logger.info("Mod class discovery completed"); } catch (Throwable th) { logger.log(Level.WARNING, "Mod class discovery failed", th); return; } loadMods(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(); } } }
/** @param pluginChannelListener */ public void addPluginChannelListener(PluginChannelListener pluginChannelListener) { if (!pluginChannelListeners.contains(pluginChannelListener)) { pluginChannelListeners.add(pluginChannelListener); if (loaderStartupComplete) initHooks(); } }
/** @param loginListener */ public void addLoginListener(LoginListener loginListener) { if (!loginListeners.contains(loginListener)) { loginListeners.add(loginListener); if (loaderStartupComplete) initHooks(); } }
/** @param chatListener */ public void addChatListener(ChatListener chatListener) { if (!chatListeners.contains(chatListener)) { chatListeners.add(chatListener); if (loaderStartupComplete) initHooks(); } }
/** @param tickable */ public void addRenderListener(RenderListener tickable) { if (!renderListeners.contains(tickable)) { renderListeners.add(tickable); if (loaderStartupComplete) initHooks(); } }
/** @param initCompleteListener */ public void addInitListener(InitCompleteListener initCompleteListener) { if (!initListeners.contains(initCompleteListener)) { initListeners.add(initCompleteListener); if (loaderStartupComplete) initHooks(); } }
/** @param tickable */ public void addTickListener(Tickable tickable) { if (!tickListeners.contains(tickable)) { tickListeners.add(tickable); if (loaderStartupComplete) initHooks(); } }