diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 30d399d8d..d3b83982b 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e18cba72f..bed6a43c4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Sep 14 12:28:28 PDT 2015 +#Sat Mar 10 11:15:39 EST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip diff --git a/gradlew b/gradlew index 91a7e269e..27309d923 100755 --- a/gradlew +++ b/gradlew @@ -6,12 +6,30 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` diff --git a/gradlew.bat b/gradlew.bat index 8a0b282aa..832fdb607 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,7 +46,7 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args diff --git a/src/main/java/net/minecraftforge/common/config/ConfigManager.java b/src/main/java/net/minecraftforge/common/config/ConfigManager.java index 750f461d1..5eb752c34 100644 --- a/src/main/java/net/minecraftforge/common/config/ConfigManager.java +++ b/src/main/java/net/minecraftforge/common/config/ConfigManager.java @@ -41,7 +41,7 @@ import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.LoaderException; import net.minecraftforge.fml.common.discovery.ASMDataTable; import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData; -import net.minecraftforge.fml.common.discovery.asm.ModAnnotation.EnumHolder; +import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation.EnumHolder; import org.apache.commons.lang3.StringUtils; diff --git a/src/main/java/net/minecraftforge/fml/FMLConfig.java b/src/main/java/net/minecraftforge/fml/FMLConfig.java new file mode 100644 index 000000000..ba9b33d07 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/FMLConfig.java @@ -0,0 +1,85 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import net.minecraftforge.fml.common.FMLPaths; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class FMLConfig +{ + private static FMLConfig INSTANCE; + private final Map configData = new HashMap<>(); + + private FMLConfig() { + configData.putAll(defaultValues()); + } + + private Map defaultValues() { + final Map result = new HashMap<>(); + result.put("splashscreen", "true"); + return result; + } + + private void loadFrom(final Path configFile) throws IOException + { + final Type type = new TypeToken>() {}.getType(); + final Gson gson = new Gson(); + final Map loadedConfig = gson.fromJson(Files.newBufferedReader(configFile), type); + if (loadedConfig != null) + configData.putAll(loadedConfig); + } + + private void saveConfigIfNecessary(final Path configFile) throws IOException { + final Type type = new TypeToken>() {}.getType(); + final Gson gson = new Gson(); + final BufferedWriter writer = Files.newBufferedWriter(configFile); + gson.toJson(configData, type, writer); + writer.flush(); + } + public static void load() + { + final Path configFile = FMLPaths.FMLCONFIG.get(); + INSTANCE = new FMLConfig(); + try + { + if (Files.exists(configFile)) + { + INSTANCE.loadFrom(configFile); + } + INSTANCE.saveConfigIfNecessary(configFile); + } + catch (IOException ioe) + { + fmlLog.error("Unable to read FML config at {}", configFile, ioe); + throw new RuntimeException("Unable to read FML config", ioe); + } + } +} diff --git a/src/main/java/net/minecraftforge/fml/FileUtils.java b/src/main/java/net/minecraftforge/fml/FileUtils.java new file mode 100644 index 000000000..e33ab2d91 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/FileUtils.java @@ -0,0 +1,51 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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; + +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class FileUtils +{ + public static Path getOrCreateDirectory(Path dirPath, String dirLabel) { + if (!Files.isDirectory(dirPath)) + { + fmlLog.debug("Making {} directory : {}", dirLabel, dirPath); + try { + Files.createDirectory(dirPath); + } catch (IOException e) { + if (e instanceof FileAlreadyExistsException) { + fmlLog.error("Failed to create {} directory - there is a file in the way", dirLabel); + } else { + fmlLog.error("Problem with creating {} directory (Permissions?)", dirLabel, e); + } + throw new RuntimeException("Problem creating directory", e); + } + fmlLog.debug("Created {} directory : {}", dirLabel, dirPath); + } else { + fmlLog.debug("Found existing {} directory : {}", dirLabel, dirPath); + } + return dirPath; + } +} diff --git a/src/main/java/net/minecraftforge/fml/LaunchTesting.java b/src/main/java/net/minecraftforge/fml/LaunchTesting.java new file mode 100644 index 000000000..c34b865a3 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/LaunchTesting.java @@ -0,0 +1,33 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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; + +import cpw.mods.modlauncher.Launcher; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.Configurator; + +public class LaunchTesting +{ + public static void main(String... args) + { + Configurator.setRootLevel(Level.DEBUG); + Launcher.main("--launchTarget", "fml","--gameDir", "projects/run"); + } +} diff --git a/src/main/java/net/minecraftforge/fml/Logging.java b/src/main/java/net/minecraftforge/fml/Logging.java new file mode 100644 index 000000000..e97b6b782 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/Logging.java @@ -0,0 +1,30 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.config.Configurator; + +public class Logging +{ + public static final Logger fmlLog = LogManager.getLogger("FML"); +} diff --git a/src/main/java/net/minecraftforge/fml/common/AutomaticEventSubscriber.java b/src/main/java/net/minecraftforge/fml/common/AutomaticEventSubscriber.java index f53898838..791f3544e 100644 --- a/src/main/java/net/minecraftforge/fml/common/AutomaticEventSubscriber.java +++ b/src/main/java/net/minecraftforge/fml/common/AutomaticEventSubscriber.java @@ -25,9 +25,8 @@ import com.google.common.collect.SetMultimap; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.discovery.ASMDataTable; import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData; -import net.minecraftforge.fml.common.discovery.asm.ModAnnotation; +import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation; import net.minecraftforge.fml.relauncher.Side; -import org.apache.logging.log4j.Level; import java.util.EnumSet; import java.util.List; diff --git a/src/main/java/net/minecraftforge/fml/common/FMLPaths.java b/src/main/java/net/minecraftforge/fml/common/FMLPaths.java new file mode 100644 index 000000000..f53e9e2a0 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/common/FMLPaths.java @@ -0,0 +1,84 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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.common; + +import cpw.mods.modlauncher.api.IEnvironment; +import net.minecraftforge.fml.FileUtils; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Objects; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public enum FMLPaths +{ + GAMEDIR(), + MODSDIR("mods"), + CONFIGDIR("config"), + FMLCONFIG(false, CONFIGDIR, "fml.cfg"); + + private final Path relativePath; + private final boolean isDirectory; + private Path absolutePath; + + FMLPaths() { + this(""); + } + + FMLPaths(String... path) { + relativePath = computePath(path); + this.isDirectory = true; + } + + private Path computePath(String... path) + { + return Paths.get(path[0], Arrays.copyOfRange(path, 1, path.length)); + } + + FMLPaths(boolean isDir, FMLPaths parent, String... path) { + this.relativePath = parent.relativePath.resolve(computePath(path)); + this.isDirectory = isDir; + } + + public static void setup(IEnvironment env) { + final Path rootPath = env.getProperty(IEnvironment.Keys.GAMEDIR.get()).orElseThrow(() -> new RuntimeException("No game path found")); + + loadAbsolutePaths(rootPath); + } + + public static void loadAbsolutePaths(Path rootPath) + { + for (FMLPaths path : FMLPaths.values()) + { + path.absolutePath = rootPath.resolve(path.relativePath).toAbsolutePath(); + fmlLog.debug("Path {} is {}", ()-> path, ()-> path.absolutePath); + if (path.isDirectory) + { + FileUtils.getOrCreateDirectory(path.absolutePath, path.name()); + } + } + } + + public Path get() { + return absolutePath; + } +} diff --git a/src/main/java/net/minecraftforge/fml/common/ModContainerFactory.java b/src/main/java/net/minecraftforge/fml/common/ModContainerFactory.java index bed362f78..1df9a3b85 100644 --- a/src/main/java/net/minecraftforge/fml/common/ModContainerFactory.java +++ b/src/main/java/net/minecraftforge/fml/common/ModContainerFactory.java @@ -22,11 +22,10 @@ package net.minecraftforge.fml.common; import java.io.File; import java.lang.reflect.Constructor; import java.util.Map; -import java.util.regex.Pattern; import net.minecraftforge.fml.common.discovery.ModCandidate; import net.minecraftforge.fml.common.discovery.asm.ASMModParser; -import net.minecraftforge.fml.common.discovery.asm.ModAnnotation; +import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation; import org.objectweb.asm.Type; diff --git a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ASMModParser.java b/src/main/java/net/minecraftforge/fml/common/discovery/asm/ASMModParser.java index 96b09d52f..68f1ca7e1 100644 --- a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ASMModParser.java +++ b/src/main/java/net/minecraftforge/fml/common/discovery/asm/ASMModParser.java @@ -29,6 +29,8 @@ import net.minecraftforge.fml.common.LoaderException; import net.minecraftforge.fml.common.discovery.ASMDataTable; import net.minecraftforge.fml.common.discovery.ModCandidate; +import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation; +import net.minecraftforge.fml.loading.moddiscovery.ModClassVisitor; import org.objectweb.asm.ClassReader; import org.objectweb.asm.Type; diff --git a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModClassVisitor.java b/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModClassVisitor.java deleted file mode 100644 index 2192fb054..000000000 --- a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModClassVisitor.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2018. - * - * 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.common.discovery.asm; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -public class ModClassVisitor extends ClassVisitor -{ - private ASMModParser discoverer; - - public ModClassVisitor(ASMModParser discoverer) - { - super(Opcodes.ASM5); - this.discoverer = discoverer; - } - - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) - { - discoverer.beginNewTypeName(name, version, superName, interfaces); - } - - @Override - public AnnotationVisitor visitAnnotation(String annotationName, boolean runtimeVisible) - { - discoverer.startClassAnnotation(annotationName); - return new ModAnnotationVisitor(discoverer); - } - - - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) - { - return new ModFieldVisitor(name, discoverer); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) - { - return new ModMethodVisitor(name, desc, discoverer); - } -} diff --git a/src/main/java/net/minecraftforge/fml/common/discovery/json/ASMInfo.java b/src/main/java/net/minecraftforge/fml/common/discovery/json/ASMInfo.java index 4afa6e348..5a740d00a 100644 --- a/src/main/java/net/minecraftforge/fml/common/discovery/json/ASMInfo.java +++ b/src/main/java/net/minecraftforge/fml/common/discovery/json/ASMInfo.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Map; import java.util.function.Function; -import org.apache.commons.lang3.Validate; import org.objectweb.asm.Type; import com.google.common.base.MoreObjects; @@ -31,7 +30,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import net.minecraftforge.fml.common.FMLLog; -import net.minecraftforge.fml.common.discovery.asm.ModAnnotation.EnumHolder; +import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation.EnumHolder; //Package private, modders shouldn't access this. Do it through ASMDataTable. class ASMInfo diff --git a/src/main/java/net/minecraftforge/fml/loading/FMLLaunchProvider.java b/src/main/java/net/minecraftforge/fml/loading/FMLLaunchProvider.java new file mode 100644 index 000000000..09fd12ec3 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/FMLLaunchProvider.java @@ -0,0 +1,46 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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; + +import cpw.mods.modlauncher.api.ILaunchHandlerService; + +import java.nio.file.Path; +import java.util.concurrent.Callable; + +public class FMLLaunchProvider implements ILaunchHandlerService +{ + @Override + public String name() + { + return "fml"; + } + + @Override + public Path[] identifyTransformationTargets() + { + return new Path[0]; + } + + @Override + public Callable launchService(String[] arguments, ClassLoader launchClassLoader) + { + return () -> { return null; }; + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java b/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java new file mode 100644 index 000000000..48db48ceb --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java @@ -0,0 +1,62 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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; + +import cpw.mods.modlauncher.api.IEnvironment; +import cpw.mods.modlauncher.api.ITransformationService; +import cpw.mods.modlauncher.api.IncompatibleEnvironmentException; +import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; +import net.minecraftforge.common.ForgeVersion; +import net.minecraftforge.fml.loading.moddiscovery.ModDiscoverer; + +import java.util.Set; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class FMLLoader +{ + + private static ILaunchPluginService accessTransformer; + private static ModDiscoverer modDiscoverer; + + static void initialize(IEnvironment environment, Set otherServices) throws IncompatibleEnvironmentException + { + final String version = ForgeVersion.getVersion(); + fmlLog.debug("FML {} loading", version); + final Package modLauncherPackage = ITransformationService.class.getPackage(); + fmlLog.debug("FML found ModLauncher version : {}", modLauncherPackage.getImplementationVersion()); + if (!modLauncherPackage.isCompatibleWith("1.0")) { + fmlLog.error("Found incompatible ModLauncher specification : {}, version {} from {}", modLauncherPackage.getSpecificationVersion(), modLauncherPackage.getImplementationVersion(), modLauncherPackage.getImplementationVendor()); + throw new IncompatibleEnvironmentException("Incompatible modlauncher found "+modLauncherPackage.getSpecificationVersion()); + } + + accessTransformer = environment.findLaunchPlugin("accesstransformer").orElseThrow(()-> new IncompatibleEnvironmentException("Missing AccessTransformer, cannot run")); + + final Package atPackage = accessTransformer.getClass().getPackage(); + fmlLog.debug("FML found AccessTransformer version : {}", atPackage.getImplementationVersion()); + if (!atPackage.isCompatibleWith("1.0")) { + fmlLog.error("Found incompatible AccessTransformer specification : {}, version {} from {}", atPackage.getSpecificationVersion(), atPackage.getImplementationVersion(), atPackage.getImplementationVendor()); + } +// final ILaunchPluginService coreMod = environment.findLaunchPlugin("coremod").orElseThrow(()-> new IncompatibleEnvironmentException("Missing CoreMod, cannot run")); + + fmlLog.debug("Scanning for Mod Locators"); + modDiscoverer = new ModDiscoverer(); + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java b/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java new file mode 100644 index 000000000..4cda27b40 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java @@ -0,0 +1,90 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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; + +import cpw.mods.modlauncher.api.IEnvironment; +import cpw.mods.modlauncher.api.ITransformationService; +import cpw.mods.modlauncher.api.ITransformer; +import cpw.mods.modlauncher.api.IncompatibleEnvironmentException; +import joptsimple.ArgumentAcceptingOptionSpec; +import joptsimple.OptionSpecBuilder; +import net.minecraftforge.fml.FMLConfig; +import net.minecraftforge.fml.common.FMLPaths; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.BiFunction; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class FMLServiceProvider implements ITransformationService +{ + + private ArgumentAcceptingOptionSpec modsOption; + private ArgumentAcceptingOptionSpec modListsOption; + private List modsArgumentList; + private List modListsArgumentList; + + @Override + public String name() + { + return "fml"; + } + + @Override + public void initialize(IEnvironment environment) + { + fmlLog.debug("Setting up basic FML game directories"); + FMLPaths.setup(environment); + fmlLog.debug("Loading configuration"); + FMLConfig.load(); + } + + @Override + public void onLoad(IEnvironment environment, Set otherServices) throws IncompatibleEnvironmentException + { + FMLLoader.initialize(environment, otherServices); + } + + @Override + public void arguments(BiFunction argumentBuilder) + { + modsOption = argumentBuilder.apply("mods", "List of mods to add").withRequiredArg().ofType(String.class).withValuesSeparatedBy(","); + modListsOption = argumentBuilder.apply("modLists", "JSON modlists").withRequiredArg().ofType(String.class).withValuesSeparatedBy(","); + } + + @Override + public void argumentValues(OptionResult option) + { + modsArgumentList = option.values(modsOption); + modListsArgumentList = option.values(modListsOption); + } + + @Nonnull + @Override + public List transformers() + { + return Collections.emptyList(); + } + +} diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java new file mode 100644 index 000000000..2e870f25c --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java @@ -0,0 +1,79 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class BackgroundScanHandler +{ + private final ExecutorService modContentScanner; + private final List pendingFiles; + private final List scannedFiles; + private final List allFiles; + + public BackgroundScanHandler() { + modContentScanner = Executors.newCachedThreadPool(); + scannedFiles = new ArrayList<>(); + pendingFiles = new ArrayList<>(); + allFiles = new ArrayList<>(); + } + + public void submitForScanning(final ModFile file) { + if (modContentScanner.isShutdown()) { + throw new IllegalStateException("Scanner has shutdown"); + } + allFiles.add(file); + pendingFiles.add(file); + final CompletableFuture future = CompletableFuture.supplyAsync(file::compileContent, modContentScanner) + .whenComplete(file::setScanResult) + .whenComplete((r,t)-> this.addCompletedFile(file,r,t)); + file.setFutureScanResult(future); + } + + private void addCompletedFile(final ModFile file, final ScanResult scanResult, final Throwable throwable) { + if (throwable != null) { + fmlLog.error("An error occurred scanning file {}", file, throwable); + } + pendingFiles.remove(file); + scannedFiles.add(file); + } + + public List getScannedFiles() { + if (!pendingFiles.isEmpty()) { + modContentScanner.shutdown(); + try { + modContentScanner.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); + } catch (InterruptedException e) { + } + } + return scannedFiles; + } + + public List getAllFiles() { + return allFiles; + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/CoreModFile.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/CoreModFile.java new file mode 100644 index 000000000..241055978 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/CoreModFile.java @@ -0,0 +1,42 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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; + +public class CoreModFile implements net.minecraftforge.forgespi.ICoreModFile { + private final java.nio.file.Path internalPath; + private final ModFile file; + private final String name; + + CoreModFile(final String name, final java.nio.file.Path path, final ModFile file) { + this.name = name; + this.internalPath = path; + this.file = file; + } + + @Override + public java.io.Reader readCoreMod() throws java.io.IOException { + return java.nio.file.Files.newBufferedReader(this.internalPath); + } + + @Override + public java.nio.file.Path getPath() { + return this.internalPath; + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ExplodedDirectoryLocator.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ExplodedDirectoryLocator.java new file mode 100644 index 000000000..cb5d10b76 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ExplodedDirectoryLocator.java @@ -0,0 +1,70 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class ExplodedDirectoryLocator implements IModLocator { + private static final String DIR = System.getProperty("fml.explodedDir", "modclasses"); + private final Path rootDir; + + ExplodedDirectoryLocator() { + this.rootDir = FileSystems.getDefault().getPath(DIR); + } + + @Override + public List scanMods() { + return Collections.singletonList(new ModFile(rootDir, this)); + } + + @Override + public String name() { + return "exploded directory"; + } + + @Override + public Path findPath(final ModFile modFile, final String... path) { + if (path.length < 1) { + throw new IllegalArgumentException("Missing path"); + } + return rootDir.resolve(FileSystems.getDefault().getPath(path[0], Arrays.copyOfRange(path, 1, path.length))); + } + + @Override + public void scanFile(final ModFile modFile, final Consumer pathConsumer) { + fmlLog.debug("Scanning directory {}", rootDir); + try (Stream files = Files.find(rootDir, Integer.MAX_VALUE, (p, a) -> p.getNameCount() > 0 && p.getFileName().toString().endsWith(".class"))) { + files.forEach(pathConsumer); + } catch (IOException e) { + e.printStackTrace(); + } + fmlLog.debug("Directory scan complete {}", rootDir); + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/IModLocator.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/IModLocator.java new file mode 100644 index 000000000..7ae91a3f6 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/IModLocator.java @@ -0,0 +1,42 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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.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 scanMods(); + + String name(); + + Path findPath(ModFile modFile, String... path); + + void scanFile(final ModFile modFile, Consumer pathConsumer); + + Optional findManifest(Path file); +} diff --git a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModAnnotation.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotation.java similarity index 87% rename from src/main/java/net/minecraftforge/fml/common/discovery/asm/ModAnnotation.java rename to src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotation.java index 173a8f9d2..8fa21037a 100644 --- a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModAnnotation.java +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotation.java @@ -17,13 +17,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.minecraftforge.fml.common.discovery.asm; +package net.minecraftforge.fml.loading.moddiscovery; +import java.lang.annotation.ElementType; import java.util.ArrayList; import java.util.Map; -import net.minecraftforge.fml.common.discovery.asm.ASMModParser.AnnotationType; - import org.objectweb.asm.Type; import com.google.common.base.MoreObjects; @@ -53,20 +52,21 @@ public class ModAnnotation return value; } } - AnnotationType type; + ElementType type; Type asmType; String member; Map values = Maps.newHashMap(); + private ArrayList arrayList; private String arrayName; - public ModAnnotation(AnnotationType type, Type asmType, String member) + public ModAnnotation(ElementType type, Type asmType, String member) { this.type = type; this.asmType = asmType; this.member = member; } - public ModAnnotation(AnnotationType type, Type asmType, ModAnnotation parent) + public ModAnnotation(ElementType type, Type asmType, ModAnnotation parent) { this.type = type; this.asmType = asmType; @@ -81,7 +81,8 @@ public class ModAnnotation .add("values", values) .toString(); } - public AnnotationType getType() + + public ElementType getType() { return type; } @@ -126,7 +127,7 @@ public class ModAnnotation } public ModAnnotation addChildAnnotation(String name, String desc) { - ModAnnotation child = new ModAnnotation(AnnotationType.SUBTYPE, Type.getType(desc), this); + ModAnnotation child = new ModAnnotation(ElementType.PARAMETER, Type.getType(desc), this); addProperty(name, child.getValues()); return child; } diff --git a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModAnnotationVisitor.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotationVisitor.java similarity index 56% rename from src/main/java/net/minecraftforge/fml/common/discovery/asm/ModAnnotationVisitor.java rename to src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotationVisitor.java index 86e834717..2ed0a6587 100644 --- a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModAnnotationVisitor.java +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotationVisitor.java @@ -17,72 +17,79 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.minecraftforge.fml.common.discovery.asm; +package net.minecraftforge.fml.loading.moddiscovery; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Opcodes; +import java.util.LinkedList; + public class ModAnnotationVisitor extends AnnotationVisitor { - private ASMModParser discoverer; + private final ModAnnotation annotation; + private LinkedList annotations; private boolean array; private String name; private boolean isSubAnnotation; - public ModAnnotationVisitor(ASMModParser discoverer) + public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation) { super(Opcodes.ASM5); - this.discoverer = discoverer; + this.annotations = annotations; + this.annotation = annotation; } - public ModAnnotationVisitor(ASMModParser discoverer, String name) + public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation, String name) { - this(discoverer); + this(annotations, annotation); this.array = true; this.name = name; - discoverer.addAnnotationArray(name); + annotation.addArray(name); } - public ModAnnotationVisitor(ASMModParser discoverer, boolean isSubAnnotation) + public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation, boolean isSubAnnotation) { - this(discoverer); + this(annotations, annotation); this.isSubAnnotation = true; } @Override public void visit(String key, Object value) { - discoverer.addAnnotationProperty(key, value); + annotation.addProperty(key, value); } @Override public void visitEnum(String name, String desc, String value) { - discoverer.addAnnotationEnumProperty(name, desc, value); + annotation.addEnumProperty(name, desc, value); } @Override public AnnotationVisitor visitArray(String name) { - return new ModAnnotationVisitor(discoverer, name); + return new ModAnnotationVisitor(annotations, annotation, name); } @Override public AnnotationVisitor visitAnnotation(String name, String desc) { - discoverer.addSubAnnotation(name, desc); - return new ModAnnotationVisitor(discoverer, true); + ModAnnotation ma = annotations.getFirst(); + final ModAnnotation childAnnotation = ma.addChildAnnotation(name, desc); + annotations.addFirst(childAnnotation); + return new ModAnnotationVisitor(annotations, childAnnotation,true); } @Override public void visitEnd() { if (array) { - discoverer.endArray(); + annotation.endArray(); } if (isSubAnnotation) { - discoverer.endSubAnnotation(); + ModAnnotation child = annotations.removeFirst(); + annotations.addLast(child); } } } diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModClassVisitor.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModClassVisitor.java new file mode 100644 index 000000000..f86263e2f --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModClassVisitor.java @@ -0,0 +1,84 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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 org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.lang.annotation.ElementType; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ModClassVisitor extends ClassVisitor +{ + private Type asmType; + private Type asmSuperType; + private Set interfaces; + private final LinkedList annotations = new LinkedList<>(); + public ModClassVisitor() + { + super(Opcodes.ASM5); + } + + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) + { + this.asmType = Type.getObjectType(name); + this.asmSuperType = superName != null && superName.length() > 0 ? Type.getObjectType(superName) : null; + this.interfaces = Stream.of(interfaces).map(Type::getObjectType).collect(Collectors.toSet()); + } + + @Override + public AnnotationVisitor visitAnnotation(final String annotationName, final boolean runtimeVisible) + { + ModAnnotation ann = new ModAnnotation(ElementType.TYPE, Type.getType(annotationName), this.asmType.getClassName()); + annotations.addFirst(ann); + return new ModAnnotationVisitor(annotations, ann); + } + + + @Override + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) + { + return new ModFieldVisitor(name, annotations); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) + { + return new ModMethodVisitor(name, desc, annotations); + } + + public void buildData(final List classes, final List annotations) { + classes.add(new ScanResult.ClassData(this.asmType, this.asmSuperType, this.interfaces)); + final List collect = this.annotations.stream().filter(ScanResult::interestingAnnotations). + map(a -> ScanResult.AnnotationData.fromModAnnotation(this.asmType, a)).collect(Collectors.toList()); + annotations.addAll(collect); + } + +} diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModDiscoverer.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModDiscoverer.java new file mode 100644 index 000000000..599891279 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModDiscoverer.java @@ -0,0 +1,66 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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 cpw.mods.modlauncher.ServiceLoaderStreamUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.stream.Collectors; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class ModDiscoverer { + private final ServiceLoader locators; + private final List locatorList; + + public ModDiscoverer() { + locators = ServiceLoader.load(IModLocator.class); + locatorList = ServiceLoaderStreamUtils.toList(this.locators); + fmlLog.debug("Found Mod Locators : {}", ()->locatorList.stream().map(IModLocator::name).collect(Collectors.joining(","))); + } + + ModDiscoverer(List locatorList) { + this.locatorList = locatorList; + this.locators = null; + } + + public BackgroundScanHandler discoverMods() { + fmlLog.debug("Scanning for mods and other resources to load. We know {} ways to find mods", locatorList.size()); + final Map> modFiles = locatorList.stream() + .peek(loc -> fmlLog.debug("Trying locator {}", loc)) + .map(IModLocator::scanMods) + .flatMap(Collection::stream) + .peek(mf -> fmlLog.debug("Found mod file {} of type {} with locator {}", mf.getFileName(), mf.getType(), mf.getLocator())) + .collect(Collectors.groupingBy(ModFile::getType)); + + ModLanguageProvider.loadAdditionalLanguages(modFiles.get(ModFile.Type.LANGPROVIDER)); + BackgroundScanHandler backgroundScanHandler = new BackgroundScanHandler(); + final List mods = modFiles.get(ModFile.Type.MOD); + mods.forEach(ModFile::identifyMods); + fmlLog.debug("Found {} mod files with {} mods", mods::size, ()->mods.stream().mapToInt(mf -> mf.getModInfos().size()).sum()); + mods.stream().map(ModFile::getCoreMods).flatMap(List::stream).forEach(ServiceProviders.getCoreModProvider()::addCoreMod); + mods.forEach(backgroundScanHandler::submitForScanning); + return backgroundScanHandler; + } + +} diff --git a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModFieldVisitor.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFieldVisitor.java similarity index 66% rename from src/main/java/net/minecraftforge/fml/common/discovery/asm/ModFieldVisitor.java rename to src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFieldVisitor.java index ba5ef281c..993ee79c8 100644 --- a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModFieldVisitor.java +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFieldVisitor.java @@ -17,29 +17,33 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.minecraftforge.fml.common.discovery.asm; +package net.minecraftforge.fml.loading.moddiscovery; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.lang.annotation.ElementType; +import java.util.LinkedList; public class ModFieldVisitor extends FieldVisitor { + private final LinkedList annotations; + private final String fieldName; - private String fieldName; - private ASMModParser discoverer; - - public ModFieldVisitor(String name, ASMModParser discoverer) + public ModFieldVisitor(String name, final LinkedList annotations) { super(Opcodes.ASM5); this.fieldName = name; - this.discoverer = discoverer; + this.annotations = annotations; } @Override public AnnotationVisitor visitAnnotation(String annotationName, boolean runtimeVisible) { - discoverer.startFieldAnnotation(fieldName, annotationName); - return new ModAnnotationVisitor(discoverer); + ModAnnotation ann = new ModAnnotation(ElementType.FIELD, Type.getType(annotationName), fieldName); + annotations.addFirst(ann); + return new ModAnnotationVisitor(annotations, ann); } } diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java new file mode 100644 index 000000000..8d995f513 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java @@ -0,0 +1,132 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class ModFile +{ + private static final Manifest DEFAULTMANIFEST; + static { + DEFAULTMANIFEST = new Manifest(); + DEFAULTMANIFEST.getMainAttributes().putValue("FMLModType", "MOD"); + } + + public enum Type { + MOD, LIBRARY, LANGPROVIDER + } + private final Path filePath; + private final Type modFileType; + private final Manifest manifest; + private List modInfos; + private final IModLocator locator; + private ScanResult fileScanResult; + private CompletableFuture futureScanResult; + private List coreMods; + + private static final Attributes.Name TYPE = new Attributes.Name("FMLModType"); + + public ModFile(final Path file, final IModLocator locator) { + this.locator = locator; + this.filePath = file; + manifest = locator.findManifest(file).orElse(DEFAULTMANIFEST); + if (manifest != DEFAULTMANIFEST) fmlLog.debug("Mod file {} has a manifest", file); + else fmlLog.debug("Mod file {} is missing a manifest", file); + modFileType = Type.valueOf(manifest.getMainAttributes().getValue(TYPE)); + } + + public Type getType() { + return modFileType; + } + + public Path getFilePath() { + return filePath; + } + + public List getModInfos() { + return modInfos; + } + + public void identifyMods() { + this.modInfos = ModFileParser.readModList(this); + this.modInfos.forEach(mi-> fmlLog.debug("Found mod {} for language {}", mi.getModId(), mi.getModLoader())); + this.coreMods = ModFileParser.getCoreMods(this); + this.coreMods.forEach(mi-> fmlLog.debug("Found coremod {}", mi.getPath())); + } + + + public List getCoreMods() { + return coreMods; + } + + /** + * Run in an executor thread to harvest the class and annotation list + */ + public ScanResult compileContent() { + return new Scanner(this).scan(); + } + + public void scanFile(Consumer pathConsumer) { + locator.scanFile(this, pathConsumer); + } + + public void setFutureScanResult(CompletableFuture future) + { + this.futureScanResult = future; + } + + public ScanResult getScanResult() { + if (this.futureScanResult != null) { + try { + this.futureScanResult.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + return this.fileScanResult; + } + + public void setScanResult(final ScanResult scanResult, final Throwable throwable) { + this.futureScanResult = null; + this.fileScanResult = scanResult; + } + + @Override + public String toString() { + return "Mod File: " + Objects.toString(this.filePath); + } + + public String getFileName() { + return getFilePath().getFileName().toString(); + } + + public IModLocator getLocator() { + return locator; + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFileParser.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFileParser.java new file mode 100644 index 000000000..1ab2163ba --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFileParser.java @@ -0,0 +1,71 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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 com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; +import com.google.gson.JsonDeserializer; +import com.google.gson.reflect.TypeToken; +import net.minecraftforge.fml.common.versioning.ArtifactVersion; +import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion; + +import java.util.Map; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class ModFileParser { + protected static java.util.List readModList(final ModFile modFile) { + fmlLog.debug("Parsing mod file candidate {}", modFile.getFilePath()); + try { + final java.nio.file.Path modsjson = modFile.getLocator().findPath(modFile, "META-INF", "mods.json"); + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(ModInfo.class, (InstanceCreator)ic -> new ModInfo(modFile, null, null, null, null, null, null, null)); + gsonBuilder.registerTypeAdapter(ArtifactVersion.class, (JsonDeserializer) (element, type, context) -> new DefaultArtifactVersion(element.getAsString())); + Gson gson = gsonBuilder.create(); + final ModInfo[] modInfos = gson.fromJson(java.nio.file.Files.newBufferedReader(modsjson), ModInfo[].class); + return java.util.stream.Stream.of(modInfos).collect(java.util.stream.Collectors.toList()); + } catch (java.io.IOException e) { + fmlLog.debug("Ignoring invalid JAR file {}", modFile.getFilePath()); + return java.util.Collections.emptyList(); + } + } + + protected static java.util.List getCoreMods(final ModFile modFile) { + java.util.Map coreModPaths; + try { + final java.nio.file.Path coremodsjson = modFile.getLocator().findPath(modFile, "META-INF", "coremods.json"); + if (!java.nio.file.Files.exists(coremodsjson)) { + return java.util.Collections.emptyList(); + } + final java.lang.reflect.Type type = new TypeToken>() {}.getType(); + final Gson gson = new Gson(); + coreModPaths = gson.fromJson(java.nio.file.Files.newBufferedReader(coremodsjson), type); + } catch (java.io.IOException e) { + fmlLog.debug("Failed to read coremod list coremods.json", e); + return java.util.Collections.emptyList(); + } + + return coreModPaths.entrySet().stream(). + peek(e-> fmlLog.debug("Found coremod {} with Javascript path {}", e.getKey(), e.getValue())). + map(e -> new CoreModFile(e.getKey(), modFile.getLocator().findPath(modFile, e.getValue()),modFile)). + collect(java.util.stream.Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModInfo.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModInfo.java new file mode 100644 index 000000000..2a3c1dea0 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModInfo.java @@ -0,0 +1,84 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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 net.minecraftforge.fml.common.versioning.ArtifactVersion; + +public class ModInfo { + private final ModFile owningFile; + private final String modId; + private final ArtifactVersion version; + private final String displayName; + private final String description; + private final java.net.URL updateJSONURL; + private final String modLoader; + private final java.util.List dependencies; + + public ModInfo(final ModFile owningFile, final String modLoader, final String modId, final String displayName, final ArtifactVersion version, final String description, final java.net.URL updateJSONURL, final java.util.List dependencies) { + this.owningFile = owningFile; + this.modLoader = modLoader; + this.modId = modId; + this.displayName = displayName; + this.version = version; + this.description = description; + this.updateJSONURL = updateJSONURL; + this.dependencies = dependencies; + } + + public ModFile getOwningFile() { + return owningFile; + } + + public String getModLoader() { + return modLoader; + } + + public String getModId() { + return modId; + } + + public ArtifactVersion getVersion() { + return version; + } + + public enum Ordering { + BEFORE, AFTER, NONE; + } + + public enum DependencySide { + CLIENT, SERVER, BOTH; + } + + public static class ModVersion { + private final String modId; + private final ArtifactVersion version; + private final boolean mandatory; + private final Ordering ordering; + private final DependencySide side; + + public ModVersion(final String modId, final ArtifactVersion version, final boolean mandatory, final Ordering ordering, final DependencySide side) { + this.modId = modId; + this.version = version; + this.mandatory = mandatory; + this.ordering = ordering; + this.side = side; + } + } +} diff --git a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModMethodVisitor.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModMethodVisitor.java similarity index 68% rename from src/main/java/net/minecraftforge/fml/common/discovery/asm/ModMethodVisitor.java rename to src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModMethodVisitor.java index fd372fc4b..123777664 100644 --- a/src/main/java/net/minecraftforge/fml/common/discovery/asm/ModMethodVisitor.java +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModMethodVisitor.java @@ -17,31 +17,36 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.minecraftforge.fml.common.discovery.asm; +package net.minecraftforge.fml.loading.moddiscovery; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.lang.annotation.ElementType; +import java.util.LinkedList; public class ModMethodVisitor extends MethodVisitor { + private final LinkedList annotations; private String methodName; private String methodDescriptor; - private ASMModParser discoverer; - public ModMethodVisitor(String name, String desc, ASMModParser discoverer) + public ModMethodVisitor(String name, String desc, final LinkedList annotations) { super(Opcodes.ASM5); this.methodName = name; this.methodDescriptor = desc; - this.discoverer = discoverer; + this.annotations = annotations; } @Override public AnnotationVisitor visitAnnotation(String annotationName, boolean runtimeVisible) { - discoverer.startMethodAnnotation(methodName, methodDescriptor, annotationName); - return new ModAnnotationVisitor(discoverer); + ModAnnotation ann = new ModAnnotation(ElementType.METHOD, Type.getType(annotationName), methodName+methodDescriptor); + annotations.addFirst(ann); + return new ModAnnotationVisitor(annotations, ann); } } diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModsFolderLocator.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModsFolderLocator.java new file mode 100644 index 000000000..8ab977d28 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModsFolderLocator.java @@ -0,0 +1,108 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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 net.minecraftforge.fml.common.FMLPaths; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipError; + +import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.uncheck; +import static net.minecraftforge.fml.Logging.fmlLog; + +/** + * Support loading mods located in JAR files in the mods folder + */ +public class ModsFolderLocator implements IModLocator { + private static final String SUFFIX = ".jar"; + private final Path modFolder; + private final Map modJars; + public ModsFolderLocator() { + this(FMLPaths.MODSDIR.get()); + } + + ModsFolderLocator(Path modFolder) { + this.modFolder = modFolder; + this.modJars = new HashMap<>(); + } + + @Override + public List scanMods() { + return uncheck(()-> Files.list(this.modFolder)). + sorted(Comparator.comparing(path-> StringUtils.toLowerCase(path.getFileName().toString()))). + filter(p->StringUtils.toLowerCase(p.getFileName().toString()).endsWith(SUFFIX)). + map(p->new ModFile(p, this)). + peek(f->modJars.compute(f, (mf, fs)->createFileSystem(mf))). + collect(Collectors.toList()); + } + + @Override + public String name() { + return "mods folder"; + } + + private FileSystem createFileSystem(ModFile modFile) { + try { + return FileSystems.newFileSystem(modFile.getFilePath(), modFile.getClass().getClassLoader()); + } catch (ZipError | IOException e) { + fmlLog.debug("Ignoring invalid JAR file {}", modFile.getFilePath()); + return null; + } + } + + @Override + public Path findPath(final ModFile modFile, final String... path) { + if (path.length < 1) { + throw new IllegalArgumentException("Missing path"); + } + return modJars.get(modFile).getPath(path[0], Arrays.copyOfRange(path, 1, path.length)); + } + + @Override + public void scanFile(final ModFile file, final Consumer pathConsumer) { + fmlLog.debug("Scan started: {}", file); + FileSystem fs = modJars.get(file); + fs.getRootDirectories().forEach(path -> { + try (Stream files = Files.find(path, Integer.MAX_VALUE, (p, a) -> p.getNameCount() > 0 && p.getFileName().toString().endsWith(".class"))) { + files.forEach(pathConsumer); + } catch (IOException e) { + e.printStackTrace(); + } + }); + fmlLog.debug("Scan finished: {}", file); + } + + @Override + public String toString() { + return "{FolderJar locator at "+this.modFolder+"}"; + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ScanResult.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ScanResult.java new file mode 100644 index 000000000..f35f6269c --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ScanResult.java @@ -0,0 +1,95 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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 org.objectweb.asm.Type; + +import java.util.Map; +import java.util.Set; + +public class ScanResult { + private final ModFile file; + private final java.util.List annotations = new java.util.ArrayList<>(); + private final java.util.List classes = new java.util.ArrayList<>(); + + public ScanResult(final ModFile file) { + this.file = file; + } + + public static boolean interestingAnnotations(final ModAnnotation annotation) { + return true; + } + + public java.util.List getClasses() { + return classes; + } + + public java.util.List getAnnotations() { + return annotations; + } + + public static class ClassData { + private final Type clazz; + private final Type parent; + private final Set interfaces; + + public ClassData(final Type clazz, final Type parent, final Set interfaces) { + this.clazz = clazz; + this.parent = parent; + this.interfaces = interfaces; + } + + } + public static class AnnotationData { + private final Type annotationType; + private final Type clazz; + private final String memberName; + private final Map annotationData; + + + public AnnotationData(final Type annotationType, final Type clazz, final String memberName, final Map annotationData) { + this.annotationType = annotationType; + this.clazz = clazz; + this.memberName = memberName; + this.annotationData = annotationData; + } + + public Type getAnnotationType() { + return annotationType; + } + + public Type getClassType() { + return clazz; + } + + public String getMemberName() { + return memberName; + } + + public Map getAnnotationData() { + return annotationData; + } + public static ScanResult.AnnotationData fromModAnnotation(final Type clazz, final ModAnnotation annotation) { + return new AnnotationData(annotation.asmType, clazz, annotation.member, annotation.values); + } + + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/moddiscovery/Scanner.java b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/Scanner.java new file mode 100644 index 000000000..58456fa14 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/moddiscovery/Scanner.java @@ -0,0 +1,50 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * 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 org.objectweb.asm.ClassReader; + +import static net.minecraftforge.fml.Logging.fmlLog; + +public class Scanner { + private final ModFile fileToScan; + + public Scanner(final ModFile fileToScan) { + this.fileToScan = fileToScan; + } + + public ScanResult scan() { + ScanResult result = new ScanResult(fileToScan); + fileToScan.scanFile(p -> fileVisitor(p, result)); + return result; + } + + private void fileVisitor(final java.nio.file.Path path, final ScanResult result) { + try { + fmlLog.debug("Scanning {} path {}", fileToScan, path); + ModClassVisitor mcv = new ModClassVisitor(); + org.objectweb.asm.ClassReader cr = new ClassReader(java.nio.file.Files.newInputStream(path)); + cr.accept(mcv, 0); + mcv.buildData(result.getClasses(), result.getAnnotations()); + } catch (java.io.IOException e) { + // mark path bad + } + } +} diff --git a/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService b/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService new file mode 100644 index 000000000..6b6ff6274 --- /dev/null +++ b/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService @@ -0,0 +1 @@ +net.minecraftforge.fml.loading.FMLLaunchProvider \ No newline at end of file diff --git a/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService new file mode 100644 index 000000000..99a564596 --- /dev/null +++ b/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService @@ -0,0 +1 @@ +net.minecraftforge.fml.loading.FMLServiceProvider \ No newline at end of file diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 1e2fe026b..3254c08bd 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -1,52 +1,59 @@ - + + + + - - - - - - - + - - - - - - - + - + - - + + - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - + + + + + + - + - - - - + + + + + + + +