Added API to load all ModMetadata from the 'mods' folder (classpath is not included)
This commit is contained in:
parent
6837c7d081
commit
de5e56cc04
2 changed files with 78 additions and 9 deletions
|
@ -30,9 +30,7 @@ import java.util.function.BiConsumer;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
abstract public class DataExchange {
|
||||
private final Path GAME_FOLDER = FabricLoader.getInstance()
|
||||
.getGameDir()
|
||||
.normalize();
|
||||
|
||||
public final static SyncFolderDescriptor SYNC_FOLDER = new SyncFolderDescriptor("BCLIB-SYNC", FabricLoader.getInstance()
|
||||
.getGameDir()
|
||||
.resolve("bclib-sync")
|
||||
|
@ -430,7 +428,7 @@ abstract public class DataExchange {
|
|||
|
||||
protected void registerSyncFolder(String folderID, Path localBaseFolder, boolean removeAdditionalFiles) {
|
||||
localBaseFolder = localBaseFolder.normalize();
|
||||
if (PathUtil.isChildOf(GAME_FOLDER, localBaseFolder)) {
|
||||
if (PathUtil.isChildOf(PathUtil.GAME_FOLDER, localBaseFolder)) {
|
||||
final SyncFolderDescriptor desc = new SyncFolderDescriptor(folderID, localBaseFolder, removeAdditionalFiles);
|
||||
if (this.syncFolderDescriptions.contains(desc)) {
|
||||
BCLib.LOGGER.warning("Tried to override Folder Sync '" + folderID + "' again.");
|
||||
|
@ -440,7 +438,7 @@ abstract public class DataExchange {
|
|||
}
|
||||
}
|
||||
else {
|
||||
BCLib.LOGGER.error(localBaseFolder + " (from " + folderID + ") is outside the game directory " + GAME_FOLDER + ". Sync is not allowed.");
|
||||
BCLib.LOGGER.error(localBaseFolder + " (from " + folderID + ") is outside the game directory " + PathUtil.GAME_FOLDER + ". Sync is not allowed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,44 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.metadata.ModMetadata;
|
||||
import net.fabricmc.loader.metadata.ModMetadataParser;
|
||||
import net.fabricmc.loader.metadata.ParseMetadataException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import ru.bclib.BCLib;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class PathUtil {
|
||||
public final static Path GAME_FOLDER = FabricLoader.getInstance()
|
||||
.getGameDir()
|
||||
.normalize();
|
||||
|
||||
public final static Path MOD_FOLDER = FabricLoader.getInstance()
|
||||
.getGameDir()
|
||||
.resolve("mods")
|
||||
.normalize();
|
||||
|
||||
/**
|
||||
* Tests if a path is a child-path.
|
||||
* <p>
|
||||
* A path is a child of another if it is located in the parent or any of the parents subdirectories
|
||||
*
|
||||
* @param parent The folder we search for the {@code child}
|
||||
* @param child The folder you want to test
|
||||
* @param child The folder you want to test
|
||||
* @return {@code true} if {@code child} is in {@code parent} or any of its sub directories
|
||||
*/
|
||||
public static boolean isChildOf(Path parent, Path child){
|
||||
if (child==null || parent==null) return false;
|
||||
public static boolean isChildOf(Path parent, Path child) {
|
||||
if (child == null || parent == null) return false;
|
||||
|
||||
final int pCount = parent.getNameCount();
|
||||
final int cCount = child.getNameCount();
|
||||
|
@ -24,6 +48,7 @@ public class PathUtil {
|
|||
|
||||
return child.equals(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple directory walker that ignores dot-files
|
||||
*
|
||||
|
@ -39,7 +64,7 @@ public class PathUtil {
|
|||
* A simple directory walker that ignores dot-files
|
||||
*
|
||||
* @param path The path where you want to start
|
||||
* @param recursive if {@code false}, only the {@code path} is traversed
|
||||
* @param recursive if {@code false}, only the {@code path} is traversed
|
||||
* @param pathConsumer The consumer called for each valid file. The consumer will get an absolute {@link Path}-Object
|
||||
* for each visited file
|
||||
*/
|
||||
|
@ -56,4 +81,50 @@ public class PathUtil {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, ModMetadata> mods;
|
||||
|
||||
/**
|
||||
* Unloads the cache of available mods created from {@link #getMods()}
|
||||
*/
|
||||
public static void invalidateCachedMods() {
|
||||
mods = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a map of all mods that were found in the 'mods'-folder.
|
||||
* <p>
|
||||
* The method will cache the results. You can clear that cache (and free the memory) by
|
||||
* calling {@link #invalidateCachedMods()}
|
||||
* <p>
|
||||
* An error message is printed if a mod fails to load, but the parsing will continue.
|
||||
* @return A map of all found mods. (key=ModID, value={@link ModMetadata})
|
||||
*/
|
||||
public static Map<String, ModMetadata> getMods() {
|
||||
if (mods!=null) return mods;
|
||||
|
||||
mods = new HashMap<>();
|
||||
org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger("BCLib|ModLoader");
|
||||
PathUtil.fileWalker(MOD_FOLDER.toFile(), false, (file -> {
|
||||
try {
|
||||
URI uri = URI.create("jar:" + file.toUri());
|
||||
|
||||
try (FileSystem fs = FileSystems.getFileSystem(uri)) {
|
||||
final JarFile jarFile = new JarFile(file.toString());
|
||||
Path modMetaFile = fs.getPath("fabric.mod.json");
|
||||
|
||||
ModMetadata mc = ModMetadataParser.parseMetadata(logger, modMetaFile);
|
||||
mods.put(mc.getId(), mc);
|
||||
}
|
||||
catch (ParseMetadataException e) {
|
||||
BCLib.LOGGER.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
BCLib.LOGGER.error(e.getMessage());
|
||||
}
|
||||
}));
|
||||
|
||||
return mods;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue