Peel IModLocator into the SPI package and extract a small IModFile

interface as well. This allows building external IModLocator
implementations.

Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
cpw 2019-09-01 11:31:09 -04:00
parent a4aa85259e
commit 734a3d76aa
No known key found for this signature in database
GPG key ID: 8EB3DF749553B1B7
11 changed files with 56 additions and 81 deletions

View file

@ -408,7 +408,7 @@ project(':forge') {
installer 'cpw.mods:grossjava9hacks:1.1.+' installer 'cpw.mods:grossjava9hacks:1.1.+'
installer 'net.minecraftforge:accesstransformers:1.0.+:shadowed' installer 'net.minecraftforge:accesstransformers:1.0.+:shadowed'
installer 'net.minecraftforge:eventbus:1.0.+:service' installer 'net.minecraftforge:eventbus:1.0.+:service'
installer 'net.minecraftforge:forgespi:1.1.+' installer 'net.minecraftforge:forgespi:1.2.+'
installer 'net.minecraftforge:coremods:1.0.+' installer 'net.minecraftforge:coremods:1.0.+'
installer 'net.minecraftforge:unsafe:0.2.+' installer 'net.minecraftforge:unsafe:0.2.+'
installer 'com.electronwill.night-config:core:3.6.0' installer 'com.electronwill.night-config:core:3.6.0'

View file

@ -19,6 +19,8 @@
package net.minecraftforge.fml.loading.moddiscovery; package net.minecraftforge.fml.loading.moddiscovery;
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.forgespi.locating.IModLocator;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -41,13 +43,13 @@ import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
public abstract class AbstractJarFileLocator implements IModLocator { public abstract class AbstractJarFileLocator implements IModLocator {
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
protected final Map<ModFile, FileSystem> modJars; protected final Map<IModFile, FileSystem> modJars;
public AbstractJarFileLocator() { public AbstractJarFileLocator() {
this.modJars = new HashMap<>(); this.modJars = new HashMap<>();
} }
protected FileSystem createFileSystem(ModFile modFile) { protected FileSystem createFileSystem(IModFile modFile) {
try { try {
return FileSystems.newFileSystem(modFile.getFilePath(), modFile.getClass().getClassLoader()); return FileSystems.newFileSystem(modFile.getFilePath(), modFile.getClass().getClassLoader());
} catch (ZipError | IOException e) { } catch (ZipError | IOException e) {
@ -56,14 +58,16 @@ public abstract class AbstractJarFileLocator implements IModLocator {
} }
} }
public Path findPath(final ModFile modFile, final String... path) { @Override
public Path findPath(final IModFile modFile, final String... path) {
if (path.length < 1) { if (path.length < 1) {
throw new IllegalArgumentException("Missing path"); throw new IllegalArgumentException("Missing path");
} }
return modJars.get(modFile).getPath(path[0], Arrays.copyOfRange(path, 1, path.length)); return modJars.get(modFile).getPath(path[0], Arrays.copyOfRange(path, 1, path.length));
} }
public void scanFile(final ModFile file, final Consumer<Path> pathConsumer) { @Override
public void scanFile(final IModFile file, final Consumer<Path> pathConsumer) {
LOGGER.debug(SCAN,"Scan started: {}", file); LOGGER.debug(SCAN,"Scan started: {}", file);
FileSystem fs = modJars.get(file); FileSystem fs = modJars.get(file);
fs.getRootDirectories().forEach(path -> { fs.getRootDirectories().forEach(path -> {
@ -76,6 +80,7 @@ public abstract class AbstractJarFileLocator implements IModLocator {
LOGGER.debug(SCAN,"Scan finished: {}", file); LOGGER.debug(SCAN,"Scan finished: {}", file);
} }
@Override
public Optional<Manifest> findManifest(final Path file) public Optional<Manifest> findManifest(final Path file)
{ {
try (JarFile jf = new JarFile(file.toFile())) try (JarFile jf = new JarFile(file.toFile()))
@ -89,7 +94,7 @@ public abstract class AbstractJarFileLocator implements IModLocator {
} }
@Override @Override
public boolean isValid(final ModFile modFile) { public boolean isValid(final IModFile modFile) {
return modJars.get(modFile) != null; return modJars.get(modFile) != null;
} }
} }

View file

@ -19,6 +19,8 @@
package net.minecraftforge.fml.loading.moddiscovery; package net.minecraftforge.fml.loading.moddiscovery;
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.forgespi.locating.IModLocator;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -36,7 +38,7 @@ import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
public class ExplodedDirectoryLocator implements IModLocator { public class ExplodedDirectoryLocator implements IModLocator {
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
private final List<Pair<Path,List<Path>>> rootDirs; private final List<Pair<Path,List<Path>>> rootDirs;
private final Map<ModFile, Pair<Path,List<Path>>> mods; private final Map<IModFile, Pair<Path,List<Path>>> mods;
public ExplodedDirectoryLocator() { public ExplodedDirectoryLocator() {
this.rootDirs = new ArrayList<>(); this.rootDirs = new ArrayList<>();
@ -44,7 +46,7 @@ public class ExplodedDirectoryLocator implements IModLocator {
} }
@Override @Override
public List<ModFile> scanMods() { public List<IModFile> scanMods() {
final Path modstoml = Paths.get("META-INF", "mods.toml"); final Path modstoml = Paths.get("META-INF", "mods.toml");
// Collect all the mods.toml files found // Collect all the mods.toml files found
rootDirs.forEach(pathPathPair -> { rootDirs.forEach(pathPathPair -> {
@ -67,7 +69,7 @@ public class ExplodedDirectoryLocator implements IModLocator {
} }
@Override @Override
public Path findPath(final ModFile modFile, final String... path) { public Path findPath(final IModFile modFile, final String... path) {
if (path.length < 1) { if (path.length < 1) {
throw new IllegalArgumentException("Missing path"); throw new IllegalArgumentException("Missing path");
} }
@ -81,7 +83,7 @@ public class ExplodedDirectoryLocator implements IModLocator {
} }
@Override @Override
public void scanFile(final ModFile modFile, final Consumer<Path> pathConsumer) { public void scanFile(final IModFile modFile, final Consumer<Path> pathConsumer) {
LOGGER.debug(SCAN,"Scanning exploded directory {}", modFile.getFilePath().toString()); LOGGER.debug(SCAN,"Scanning exploded directory {}", modFile.getFilePath().toString());
final Pair<Path, List<Path>> pathPathPair = mods.get(modFile); final Pair<Path, List<Path>> pathPathPair = mods.get(modFile);
// classes are in the right branch of the pair // classes are in the right branch of the pair
@ -119,7 +121,7 @@ public class ExplodedDirectoryLocator implements IModLocator {
} }
@Override @Override
public boolean isValid(final ModFile modFile) { public boolean isValid(final IModFile modFile) {
return mods.get(modFile) != null; return mods.get(modFile) != null;
} }
} }

View file

@ -1,47 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2019.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.loading.moddiscovery;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.jar.Manifest;
/**
* Loaded as a ServiceLoader. Takes mechanisms for locating candidate "mods"
* and transforms them into {@link ModFile} objects.
*/
public interface IModLocator {
List<ModFile> scanMods();
String name();
Path findPath(ModFile modFile, String... path);
void scanFile(final ModFile modFile, Consumer<Path> pathConsumer);
Optional<Manifest> findManifest(Path file);
void initArguments(Map<String, ?> arguments);
boolean isValid(ModFile modFile);
}

View file

@ -21,6 +21,7 @@ package net.minecraftforge.fml.loading.moddiscovery;
import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.fml.loading.FMLPaths;
import net.minecraftforge.fml.loading.MavenCoordinateResolver; import net.minecraftforge.fml.loading.MavenCoordinateResolver;
import net.minecraftforge.forgespi.locating.IModFile;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -33,11 +34,11 @@ public class MavenDirectoryLocator extends AbstractJarFileLocator {
private List<Path> modCoords; private List<Path> modCoords;
@Override @Override
public List<ModFile> scanMods() { public List<IModFile> scanMods() {
return modCoords.stream(). return modCoords.stream()
map(mc -> new ModFile(mc, this)). .map(mc -> new ModFile(mc, this))
peek(f->modJars.compute(f, (mf, fs)->createFileSystem(mf))). .peek(f->modJars.compute(f, (mf, fs)->createFileSystem(mf)))
collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override @Override

View file

@ -23,6 +23,8 @@ import cpw.mods.modlauncher.ServiceLoaderStreamUtils;
import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.fml.loading.LoadingModList;
import net.minecraftforge.fml.loading.ModSorter; import net.minecraftforge.fml.loading.ModSorter;
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.forgespi.locating.IModLocator;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -75,16 +77,17 @@ public class ModDiscoverer {
public BackgroundScanHandler discoverMods() { public BackgroundScanHandler discoverMods() {
LOGGER.debug(SCAN,"Scanning for mods and other resources to load. We know {} ways to find mods", locatorList.size()); LOGGER.debug(SCAN,"Scanning for mods and other resources to load. We know {} ways to find mods", locatorList.size());
final Map<ModFile.Type, List<ModFile>> modFiles = locatorList.stream() final Map<IModFile.Type, List<ModFile>> modFiles = locatorList.stream()
.peek(loc -> LOGGER.debug(SCAN,"Trying locator {}", loc)) .peek(loc -> LOGGER.debug(SCAN,"Trying locator {}", loc))
.map(IModLocator::scanMods) .map(IModLocator::scanMods)
.flatMap(Collection::stream) .flatMap(Collection::stream)
.peek(mf -> LOGGER.debug(SCAN,"Found mod file {} of type {} with locator {}", mf.getFileName(), mf.getType(), mf.getLocator())) .peek(mf -> LOGGER.debug(SCAN,"Found mod file {} of type {} with locator {}", mf.getFileName(), mf.getType(), mf.getLocator()))
.collect(Collectors.groupingBy(ModFile::getType)); .map(ModFile.class::cast)
.collect(Collectors.groupingBy(IModFile::getType));
FMLLoader.getLanguageLoadingProvider().addAdditionalLanguages(modFiles.get(ModFile.Type.LANGPROVIDER)); FMLLoader.getLanguageLoadingProvider().addAdditionalLanguages(modFiles.get(IModFile.Type.LANGPROVIDER));
BackgroundScanHandler backgroundScanHandler = new BackgroundScanHandler(); BackgroundScanHandler backgroundScanHandler = new BackgroundScanHandler();
final List<ModFile> mods = modFiles.getOrDefault(ModFile.Type.MOD, Collections.emptyList()); final List<ModFile> mods = modFiles.getOrDefault(IModFile.Type.MOD, Collections.emptyList());
final List<ModFile> brokenFiles = new ArrayList<>(); final List<ModFile> brokenFiles = new ArrayList<>();
for (Iterator<ModFile> iterator = mods.iterator(); iterator.hasNext(); ) for (Iterator<ModFile> iterator = mods.iterator(); iterator.hasNext(); )
{ {
@ -122,7 +125,7 @@ public class ModDiscoverer {
} }
@Override @Override
public List<ModFile> scanMods() { public List<IModFile> scanMods() {
return Collections.singletonList(new ModFile(mcJar, this)); return Collections.singletonList(new ModFile(mcJar, this));
} }
@ -132,7 +135,7 @@ public class ModDiscoverer {
} }
@Override @Override
public Path findPath(final ModFile modFile, final String... path) { public Path findPath(final IModFile modFile, final String... path) {
String[] newPath = Arrays.copyOf(path, path.length); String[] newPath = Arrays.copyOf(path, path.length);
if (path.length == 2 && Objects.equals(path[1], "mods.toml")) { if (path.length == 2 && Objects.equals(path[1], "mods.toml")) {
final URI jarFileURI; final URI jarFileURI;
@ -152,7 +155,7 @@ public class ModDiscoverer {
return findPathJar(modFile, path); return findPathJar(modFile, path);
} }
private Path findPathDirectory(final ModFile modFile, final String... path) { private Path findPathDirectory(final IModFile modFile, final String... path) {
if (path.length < 1) { if (path.length < 1) {
throw new IllegalArgumentException("Missing path"); throw new IllegalArgumentException("Missing path");
} }
@ -161,11 +164,11 @@ public class ModDiscoverer {
return mcJar.resolve(target); return mcJar.resolve(target);
} }
private Path findPathJar(final ModFile modFile, final String... path) { private Path findPathJar(final IModFile modFile, final String... path) {
return fileSystem.getPath(path[0], Arrays.copyOfRange(path, 1, path.length)); return fileSystem.getPath(path[0], Arrays.copyOfRange(path, 1, path.length));
} }
@Override @Override
public void scanFile(final ModFile modFile, final Consumer<Path> pathConsumer) { public void scanFile(final IModFile modFile, final Consumer<Path> pathConsumer) {
LOGGER.debug(SCAN,"Scan started: {}", modFile); LOGGER.debug(SCAN,"Scan started: {}", modFile);
Path path; Path path;
if (Files.isDirectory(mcJar)) if (Files.isDirectory(mcJar))
@ -191,7 +194,7 @@ public class ModDiscoverer {
} }
@Override @Override
public boolean isValid(final ModFile modFile) { public boolean isValid(final IModFile modFile) {
return true; return true;
} }
} }

View file

@ -25,6 +25,8 @@ import net.minecraftforge.forgespi.language.IModInfo;
import net.minecraftforge.forgespi.language.ModFileScanData; import net.minecraftforge.forgespi.language.ModFileScanData;
import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.forgespi.language.IModLanguageProvider; import net.minecraftforge.forgespi.language.IModLanguageProvider;
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.forgespi.locating.IModLocator;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -44,8 +46,7 @@ import java.util.jar.Manifest;
import static net.minecraftforge.fml.loading.LogMarkers.LOADING; import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
import static net.minecraftforge.fml.loading.LogMarkers.SCAN; import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
public class ModFile public class ModFile implements IModFile {
{
private static final Manifest DEFAULTMANIFEST; private static final Manifest DEFAULTMANIFEST;
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
@ -64,11 +65,13 @@ public class ModFile
this.fileProperties = fileProperties; this.fileProperties = fileProperties;
} }
@Override
public IModLanguageProvider getLoader() public IModLanguageProvider getLoader()
{ {
return loader; return loader;
} }
@Override
public Path findResource(String className) public Path findResource(String className)
{ {
return locator.findPath(this, className); return locator.findPath(this, className);
@ -78,9 +81,6 @@ public class ModFile
this.loader = FMLLoader.getLanguageLoadingProvider().findLanguage(this, this.modFileInfo.getModLoader(), this.modFileInfo.getModLoaderVersion()); this.loader = FMLLoader.getLanguageLoadingProvider().findLanguage(this, this.modFileInfo.getModLoader(), this.modFileInfo.getModLoaderVersion());
} }
public enum Type {
MOD, LIBRARY, LANGPROVIDER
}
private final Path filePath; private final Path filePath;
private final Type modFileType; private final Type modFileType;
private final Manifest manifest; private final Manifest manifest;
@ -104,17 +104,21 @@ public class ModFile
jarVersion = Optional.ofNullable(manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION)).orElse("NONE"); jarVersion = Optional.ofNullable(manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION)).orElse("NONE");
} }
@Override
public Supplier<Map<String,Object>> getSubstitutionMap() { public Supplier<Map<String,Object>> getSubstitutionMap() {
return () -> ImmutableMap.<String,Object>builder().put("jarVersion", jarVersion).putAll(fileProperties).build(); return () -> ImmutableMap.<String,Object>builder().put("jarVersion", jarVersion).putAll(fileProperties).build();
} }
@Override
public Type getType() { public Type getType() {
return modFileType; return modFileType;
} }
@Override
public Path getFilePath() { public Path getFilePath() {
return filePath; return filePath;
} }
@Override
public List<IModInfo> getModInfos() { public List<IModInfo> getModInfos() {
return modFileInfo.getMods(); return modFileInfo.getMods();
} }
@ -122,6 +126,7 @@ public class ModFile
public Optional<Path> getAccessTransformer() { public Optional<Path> getAccessTransformer() {
return Optional.ofNullable(Files.exists(accessTransformer) ? accessTransformer : null); return Optional.ofNullable(Files.exists(accessTransformer) ? accessTransformer : null);
} }
public boolean identifyMods() { public boolean identifyMods() {
this.modFileInfo = ModFileParser.readModList(this); this.modFileInfo = ModFileParser.readModList(this);
if (this.modFileInfo == null) return false; if (this.modFileInfo == null) return false;
@ -132,7 +137,6 @@ public class ModFile
return true; return true;
} }
public List<CoreModFile> getCoreMods() { public List<CoreModFile> getCoreMods() {
return coreMods; return coreMods;
} }
@ -147,11 +151,13 @@ public class ModFile
public void scanFile(Consumer<Path> pathConsumer) { public void scanFile(Consumer<Path> pathConsumer) {
locator.scanFile(this, pathConsumer); locator.scanFile(this, pathConsumer);
} }
public void setFutureScanResult(CompletableFuture<ModFileScanData> future) public void setFutureScanResult(CompletableFuture<ModFileScanData> future)
{ {
this.futureScanResult = future; this.futureScanResult = future;
} }
@Override
public ModFileScanData getScanResult() { public ModFileScanData getScanResult() {
if (this.futureScanResult != null) { if (this.futureScanResult != null) {
try { try {
@ -179,14 +185,17 @@ public class ModFile
return "Mod File: " + Objects.toString(this.filePath); return "Mod File: " + Objects.toString(this.filePath);
} }
@Override
public String getFileName() { public String getFileName() {
return getFilePath().getFileName().toString(); return getFilePath().getFileName().toString();
} }
@Override
public IModLocator getLocator() { public IModLocator getLocator() {
return locator; return locator;
} }
@Override
public IModFileInfo getModFileInfo() { public IModFileInfo getModFileInfo() {
return modFileInfo; return modFileInfo;
} }

View file

@ -22,6 +22,7 @@ package net.minecraftforge.fml.loading.moddiscovery;
import net.minecraftforge.fml.loading.ModDirTransformerDiscoverer; import net.minecraftforge.fml.loading.ModDirTransformerDiscoverer;
import net.minecraftforge.fml.loading.StringUtils; import net.minecraftforge.fml.loading.StringUtils;
import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.fml.loading.FMLPaths;
import net.minecraftforge.forgespi.locating.IModFile;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -53,7 +54,7 @@ public class ModsFolderLocator extends AbstractJarFileLocator {
} }
@Override @Override
public List<ModFile> scanMods() { public List<IModFile> scanMods() {
LOGGER.debug(SCAN,"Scanning mods dir {} for mods", this.modFolder); LOGGER.debug(SCAN,"Scanning mods dir {} for mods", this.modFolder);
List<Path> excluded = new ModDirTransformerDiscoverer().candidates(FMLPaths.GAMEDIR.get()); List<Path> excluded = new ModDirTransformerDiscoverer().candidates(FMLPaths.GAMEDIR.get());
return uncheck(()-> Files.list(this.modFolder)). return uncheck(()-> Files.list(this.modFolder)).

View file

@ -31,6 +31,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import net.minecraftforge.forgespi.locating.IModFile;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -44,7 +45,7 @@ public class ClasspathLocator extends AbstractJarFileLocator {
private List<Path> modCoords; private List<Path> modCoords;
@Override @Override
public List<ModFile> scanMods() { public List<IModFile> scanMods() {
return modCoords.stream(). return modCoords.stream().
map(mc -> new ModFile(mc, this)). map(mc -> new ModFile(mc, this)).
peek(f->modJars.compute(f, (mf, fs)->createFileSystem(mf))). peek(f->modJars.compute(f, (mf, fs)->createFileSystem(mf))).