2018-03-25 15:59:43 +00:00
/ *
* Minecraft Forge
2020-07-02 17:49:11 +00:00
* Copyright ( c ) 2016 - 2020 .
2018-03-25 15:59:43 +00:00
*
* 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 ;
2019-04-06 16:10:54 +00:00
import cpw.mods.modlauncher.Launcher ;
2019-02-26 15:28:41 +00:00
import cpw.mods.modlauncher.ServiceLoaderStreamUtils ;
2019-01-04 16:44:57 +00:00
import cpw.mods.modlauncher.TransformingClassLoader ;
2018-03-25 15:59:43 +00:00
import cpw.mods.modlauncher.api.IEnvironment ;
2018-04-08 00:38:43 +00:00
import cpw.mods.modlauncher.api.ILaunchHandlerService ;
2019-04-06 16:10:54 +00:00
import cpw.mods.modlauncher.api.INameMappingService ;
2018-03-25 15:59:43 +00:00
import cpw.mods.modlauncher.api.ITransformationService ;
2018-06-06 15:37:56 +00:00
import cpw.mods.modlauncher.api.ITransformingClassLoader ;
2018-03-25 15:59:43 +00:00
import cpw.mods.modlauncher.api.IncompatibleEnvironmentException ;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService ;
2019-04-06 16:10:54 +00:00
import net.minecraftforge.accesstransformer.service.AccessTransformerService ;
2018-06-21 19:37:32 +00:00
import net.minecraftforge.api.distmarker.Dist ;
2018-06-06 15:37:56 +00:00
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler ;
2018-03-25 15:59:43 +00:00
import net.minecraftforge.fml.loading.moddiscovery.ModDiscoverer ;
2018-04-07 22:15:32 +00:00
import net.minecraftforge.fml.loading.moddiscovery.ModFile ;
2020-11-14 00:12:33 +00:00
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo ;
2019-10-05 21:02:54 +00:00
import net.minecraftforge.fml.loading.progress.EarlyProgressVisualization ;
import net.minecraftforge.fml.loading.progress.StartupMessageManager ;
2019-03-02 00:27:22 +00:00
import net.minecraftforge.forgespi.Environment ;
2019-01-14 03:51:36 +00:00
import net.minecraftforge.forgespi.coremod.ICoreModProvider ;
2019-09-27 21:42:24 +00:00
import net.minecraftforge.forgespi.locating.IModFile ;
2019-04-06 16:10:54 +00:00
import org.apache.commons.lang3.tuple.Pair ;
2018-08-27 17:10:07 +00:00
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
2018-03-25 15:59:43 +00:00
2018-04-07 22:15:32 +00:00
import java.net.URL ;
import java.nio.file.Path ;
import java.nio.file.Paths ;
2019-04-06 16:10:54 +00:00
import java.util.ArrayList ;
2019-07-27 00:02:21 +00:00
import java.util.Collections ;
import java.util.List ;
2019-04-06 16:10:54 +00:00
import java.util.Map ;
import java.util.Optional ;
import java.util.Set ;
import java.util.function.BiFunction ;
2020-11-14 00:12:33 +00:00
import java.util.function.Function ;
2018-12-31 21:33:54 +00:00
import java.util.function.Predicate ;
2018-04-07 03:58:48 +00:00
import java.util.stream.Collectors ;
2018-03-25 15:59:43 +00:00
2018-12-31 21:33:54 +00:00
import static net.minecraftforge.fml.loading.LogMarkers.CORE ;
import static net.minecraftforge.fml.loading.LogMarkers.SCAN ;
2018-03-25 15:59:43 +00:00
public class FMLLoader
{
2018-08-27 17:10:07 +00:00
private static final Logger LOGGER = LogManager . getLogger ( ) ;
2019-04-06 16:10:54 +00:00
private static AccessTransformerService accessTransformer ;
2018-03-25 15:59:43 +00:00
private static ModDiscoverer modDiscoverer ;
2018-04-07 15:48:43 +00:00
private static ICoreModProvider coreModProvider ;
2018-06-11 01:12:46 +00:00
private static ILaunchPluginService eventBus ;
2018-04-07 15:48:43 +00:00
private static LanguageLoadingProvider languageLoadingProvider ;
2018-06-21 19:37:32 +00:00
private static Dist dist ;
2019-04-06 16:10:54 +00:00
private static String naming ;
2018-06-15 19:03:35 +00:00
private static LoadingModList loadingModList ;
2019-01-04 16:44:57 +00:00
private static TransformingClassLoader launchClassLoader ;
2018-06-21 19:37:32 +00:00
private static RuntimeDistCleaner runtimeDistCleaner ;
2018-06-22 18:38:53 +00:00
private static Path gamePath ;
2018-06-23 02:45:01 +00:00
private static Path forgePath ;
2018-12-31 21:33:54 +00:00
private static Path [ ] mcPaths ;
static String mcVersion ;
2019-01-01 21:50:04 +00:00
private static String mcpVersion ;
static String forgeVersion ;
private static String forgeGroup ;
2018-12-31 21:33:54 +00:00
private static Predicate < String > classLoaderExclusions ;
2019-07-27 00:02:21 +00:00
private static String launchHandlerName ;
2019-12-06 03:47:34 +00:00
private static FMLCommonLaunchHandler commonLaunchHandler ;
2020-04-26 22:24:48 +00:00
public static Runnable progressWindowTick ;
2020-04-27 01:03:43 +00:00
public static BackgroundScanHandler backgroundScanHandler ;
2020-05-24 21:40:52 +00:00
private static boolean production ;
2018-03-25 15:59:43 +00:00
2018-04-07 03:58:48 +00:00
static void onInitialLoad ( IEnvironment environment , Set < String > otherServices ) throws IncompatibleEnvironmentException
2018-03-25 15:59:43 +00:00
{
2018-12-31 21:33:54 +00:00
final String version = LauncherVersion . getVersion ( ) ;
2018-08-27 17:10:07 +00:00
LOGGER . debug ( CORE , " FML {} loading " , version ) ;
2018-03-25 15:59:43 +00:00
final Package modLauncherPackage = ITransformationService . class . getPackage ( ) ;
2018-08-27 17:10:07 +00:00
LOGGER . debug ( CORE , " FML found ModLauncher version : {} " , modLauncherPackage . getImplementationVersion ( ) ) ;
2019-09-27 21:42:24 +00:00
if ( ! modLauncherPackage . isCompatibleWith ( " 4.0 " ) ) {
2019-01-06 20:46:29 +00:00
LOGGER . fatal ( CORE , " Found incompatible ModLauncher specification : {}, version {} from {} " , modLauncherPackage . getSpecificationVersion ( ) , modLauncherPackage . getImplementationVersion ( ) , modLauncherPackage . getImplementationVendor ( ) ) ;
2018-03-25 15:59:43 +00:00
throw new IncompatibleEnvironmentException ( " Incompatible modlauncher found " + modLauncherPackage . getSpecificationVersion ( ) ) ;
}
2018-08-27 17:10:07 +00:00
LOGGER . debug ( CORE , " Initializing modjar URL handler " ) ;
2018-06-11 01:12:46 +00:00
URL . setURLStreamHandlerFactory ( p - > p . equals ( " modjar " ) ? new ModJarURLHandler ( ) : null ) ;
2018-03-25 15:59:43 +00:00
2019-04-06 16:10:54 +00:00
accessTransformer = ( AccessTransformerService ) environment . findLaunchPlugin ( " accesstransformer " ) . orElseThrow ( ( ) - > {
2019-02-26 15:28:41 +00:00
LOGGER . fatal ( CORE , " Access Transformer library is missing, we need this to run " ) ;
return new IncompatibleEnvironmentException ( " Missing AccessTransformer, cannot run " ) ;
} ) ;
2018-03-25 15:59:43 +00:00
final Package atPackage = accessTransformer . getClass ( ) . getPackage ( ) ;
2018-08-27 17:10:07 +00:00
LOGGER . debug ( CORE , " FML found AccessTransformer version : {} " , atPackage . getImplementationVersion ( ) ) ;
2018-03-25 15:59:43 +00:00
if ( ! atPackage . isCompatibleWith ( " 1.0 " ) ) {
2019-01-06 20:46:29 +00:00
LOGGER . fatal ( CORE , " Found incompatible AccessTransformer specification : {}, version {} from {} " , atPackage . getSpecificationVersion ( ) , atPackage . getImplementationVersion ( ) , atPackage . getImplementationVendor ( ) ) ;
2018-04-07 03:58:48 +00:00
throw new IncompatibleEnvironmentException ( " Incompatible accesstransformer found " + atPackage . getSpecificationVersion ( ) ) ;
2018-03-25 15:59:43 +00:00
}
2019-02-26 15:28:41 +00:00
eventBus = environment . findLaunchPlugin ( " eventbus " ) . orElseThrow ( ( ) - > {
LOGGER . fatal ( CORE , " Event Bus library is missing, we need this to run " ) ;
return new IncompatibleEnvironmentException ( " Missing EventBus, cannot run " ) ;
} ) ;
2018-06-11 01:12:46 +00:00
final Package eventBusPackage = eventBus . getClass ( ) . getPackage ( ) ;
2018-08-27 17:10:07 +00:00
LOGGER . debug ( CORE , " FML found EventBus version : {} " , eventBusPackage . getImplementationVersion ( ) ) ;
2018-06-11 01:12:46 +00:00
if ( ! eventBusPackage . isCompatibleWith ( " 1.0 " ) ) {
2019-01-06 20:46:29 +00:00
LOGGER . fatal ( CORE , " Found incompatible EventBus specification : {}, version {} from {} " , eventBusPackage . getSpecificationVersion ( ) , eventBusPackage . getImplementationVersion ( ) , eventBusPackage . getImplementationVendor ( ) ) ;
2018-06-11 01:12:46 +00:00
throw new IncompatibleEnvironmentException ( " Incompatible eventbus found " + eventBusPackage . getSpecificationVersion ( ) ) ;
}
2019-02-26 15:28:41 +00:00
runtimeDistCleaner = ( RuntimeDistCleaner ) environment . findLaunchPlugin ( " runtimedistcleaner " ) . orElseThrow ( ( ) - > {
LOGGER . fatal ( CORE , " Dist Cleaner is missing, we need this to run " ) ;
return new IncompatibleEnvironmentException ( " Missing DistCleaner, cannot run! " ) ;
} ) ;
2018-08-27 17:10:07 +00:00
LOGGER . debug ( CORE , " Found Runtime Dist Cleaner " ) ;
2018-06-21 19:37:32 +00:00
2018-04-07 03:58:48 +00:00
final ArrayList < ICoreModProvider > coreModProviders = new ArrayList < > ( ) ;
2019-02-26 15:28:41 +00:00
ServiceLoaderStreamUtils . errorHandlingServiceLoader ( ICoreModProvider . class , serviceConfigurationError - > LOGGER . fatal ( CORE , " Failed to load a coremod library, expect problems " , serviceConfigurationError ) ) . forEach ( coreModProviders : : add ) ;
2018-04-07 03:58:48 +00:00
if ( coreModProviders . isEmpty ( ) ) {
2019-01-06 20:46:29 +00:00
LOGGER . fatal ( CORE , " Found no coremod provider. Cannot run " ) ;
2018-04-07 03:58:48 +00:00
throw new IncompatibleEnvironmentException ( " No coremod library found " ) ;
} else if ( coreModProviders . size ( ) > 1 ) {
2019-01-06 20:46:29 +00:00
LOGGER . fatal ( CORE , " Found multiple coremod providers : {}. Cannot run " , coreModProviders . stream ( ) . map ( p - > p . getClass ( ) . getName ( ) ) . collect ( Collectors . toList ( ) ) ) ;
2018-04-07 03:58:48 +00:00
throw new IncompatibleEnvironmentException ( " Multiple coremod libraries found " ) ;
}
2018-04-07 15:48:43 +00:00
coreModProvider = coreModProviders . get ( 0 ) ;
final Package coremodPackage = coreModProvider . getClass ( ) . getPackage ( ) ;
2018-08-27 17:10:07 +00:00
LOGGER . debug ( CORE , " FML found CoreMod version : {} " , coremodPackage . getImplementationVersion ( ) ) ;
2019-02-11 04:41:40 +00:00
2019-03-02 00:27:22 +00:00
LOGGER . debug ( CORE , " Found ForgeSPI package implementation version {} " , Environment . class . getPackage ( ) . getImplementationVersion ( ) ) ;
LOGGER . debug ( CORE , " Found ForgeSPI package specification {} " , Environment . class . getPackage ( ) . getSpecificationVersion ( ) ) ;
if ( Integer . parseInt ( Environment . class . getPackage ( ) . getSpecificationVersion ( ) ) < 2 ) {
2019-03-02 00:48:25 +00:00
LOGGER . fatal ( CORE , " Found an out of date ForgeSPI implementation: {}, loading cannot continue " , Environment . class . getPackage ( ) . getSpecificationVersion ( ) ) ;
2019-03-02 00:27:22 +00:00
throw new IncompatibleEnvironmentException ( " ForgeSPI is out of date, we cannot continue " ) ;
}
2019-02-26 15:28:41 +00:00
try {
Class . forName ( " com.electronwill.nightconfig.core.Config " , false , environment . getClass ( ) . getClassLoader ( ) ) ;
Class . forName ( " com.electronwill.nightconfig.toml.TomlFormat " , false , environment . getClass ( ) . getClassLoader ( ) ) ;
} catch ( ClassNotFoundException e ) {
LOGGER . fatal ( CORE , " Failed to load NightConfig " ) ;
throw new IncompatibleEnvironmentException ( " Missing NightConfig " ) ;
}
2019-02-11 04:41:40 +00:00
FixSSL . fixup ( ) ;
2018-04-07 03:58:48 +00:00
}
2018-12-31 21:33:54 +00:00
static void setupLaunchHandler ( final IEnvironment environment , final Map < String , ? > arguments )
2018-04-08 00:38:43 +00:00
{
final String launchTarget = environment . getProperty ( IEnvironment . Keys . LAUNCHTARGET . get ( ) ) . orElse ( " MISSING " ) ;
final Optional < ILaunchHandlerService > launchHandler = environment . findLaunchHandler ( launchTarget ) ;
2018-08-27 17:10:07 +00:00
LOGGER . debug ( CORE , " Using {} as launch service " , launchTarget ) ;
2018-04-08 00:38:43 +00:00
if ( ! launchHandler . isPresent ( ) ) {
2019-01-06 20:46:29 +00:00
LOGGER . fatal ( CORE , " Missing LaunchHandler {}, cannot continue " , launchTarget ) ;
2018-06-06 15:37:56 +00:00
throw new RuntimeException ( " Missing launch handler " ) ;
2018-04-08 00:38:43 +00:00
}
if ( ! ( launchHandler . get ( ) instanceof FMLCommonLaunchHandler ) ) {
2019-01-06 20:46:29 +00:00
LOGGER . fatal ( CORE , " Incompatible Launch handler found - type {}, cannot continue " , launchHandler . get ( ) . getClass ( ) . getName ( ) ) ;
2018-06-06 15:37:56 +00:00
throw new RuntimeException ( " Incompatible launch handler found " ) ;
2018-04-08 00:38:43 +00:00
}
2019-07-27 00:02:21 +00:00
launchHandlerName = launchHandler . get ( ) . name ( ) ;
2018-06-22 18:38:53 +00:00
gamePath = environment . getProperty ( IEnvironment . Keys . GAMEDIR . get ( ) ) . orElse ( Paths . get ( " . " ) . toAbsolutePath ( ) ) ;
2018-04-08 00:38:43 +00:00
2019-12-06 03:47:34 +00:00
commonLaunchHandler = ( FMLCommonLaunchHandler ) launchHandler . get ( ) ;
2019-04-06 16:10:54 +00:00
naming = commonLaunchHandler . getNaming ( ) ;
2018-06-21 19:37:32 +00:00
dist = commonLaunchHandler . getDist ( ) ;
2020-05-24 21:40:52 +00:00
production = commonLaunchHandler . isProduction ( ) ;
2020-07-22 00:12:33 +00:00
progressWindowTick = EarlyProgressVisualization . INSTANCE . accept ( dist , commonLaunchHandler . isData ( ) ) ;
2019-10-05 21:02:54 +00:00
StartupMessageManager . modLoaderConsumer ( ) . ifPresent ( c - > c . accept ( " Early Loading! " ) ) ;
2019-04-06 16:10:54 +00:00
accessTransformer . getExtension ( ) . accept ( Pair . of ( naming , " srg " ) ) ;
2018-12-31 21:33:54 +00:00
mcVersion = ( String ) arguments . get ( " mcVersion " ) ;
2019-01-01 21:50:04 +00:00
mcpVersion = ( String ) arguments . get ( " mcpVersion " ) ;
2018-12-31 21:33:54 +00:00
forgeVersion = ( String ) arguments . get ( " forgeVersion " ) ;
2019-01-01 21:50:04 +00:00
forgeGroup = ( String ) arguments . get ( " forgeGroup " ) ;
2018-12-31 21:33:54 +00:00
2019-01-27 05:06:57 +00:00
LOGGER . debug ( CORE , " Received command line version data : MC Version: '{}' MCP Version: '{}' Forge Version: '{}' Forge group: '{}' " , mcVersion , mcpVersion , forgeVersion , forgeGroup ) ;
2019-01-01 21:50:04 +00:00
forgePath = commonLaunchHandler . getForgePath ( mcVersion , forgeVersion , forgeGroup ) ;
mcPaths = commonLaunchHandler . getMCPaths ( mcVersion , mcpVersion , forgeVersion , forgeGroup ) ;
2018-12-31 21:33:54 +00:00
2019-01-01 21:50:04 +00:00
commonLaunchHandler . validatePaths ( forgePath , mcPaths , forgeVersion , mcVersion , mcpVersion ) ;
2018-12-31 21:33:54 +00:00
commonLaunchHandler . setup ( environment , arguments ) ;
classLoaderExclusions = commonLaunchHandler . getPackagePredicate ( ) ;
2019-01-14 03:51:36 +00:00
2018-12-31 21:33:54 +00:00
languageLoadingProvider = new LanguageLoadingProvider ( ) ;
2019-01-01 21:50:04 +00:00
languageLoadingProvider . addForgeLanguage ( forgePath ) ;
2018-12-31 21:33:54 +00:00
2018-06-21 19:37:32 +00:00
runtimeDistCleaner . getExtension ( ) . accept ( dist ) ;
2020-04-26 22:24:48 +00:00
progressWindowTick . run ( ) ;
2018-04-08 00:38:43 +00:00
}
2019-09-27 21:42:24 +00:00
public static Map < IModFile . Type , List < ModFile > > beginModScan ( final Map < String , ? > arguments )
2018-04-07 03:58:48 +00:00
{
2018-08-27 17:10:07 +00:00
LOGGER . debug ( SCAN , " Scanning for Mod Locators " ) ;
2018-12-31 21:33:54 +00:00
modDiscoverer = new ModDiscoverer ( arguments ) ;
2020-04-27 01:03:43 +00:00
backgroundScanHandler = modDiscoverer . discoverMods ( ) ;
2018-06-15 19:03:35 +00:00
loadingModList = backgroundScanHandler . getLoadingModList ( ) ;
2019-12-06 03:47:34 +00:00
commonLaunchHandler . addLibraries ( backgroundScanHandler . getModFiles ( ) . getOrDefault ( IModFile . Type . LIBRARY , Collections . emptyList ( ) ) ) ;
2020-04-26 22:24:48 +00:00
progressWindowTick . run ( ) ;
2020-11-14 00:12:33 +00:00
return loadingModList . getModFiles ( ) . stream ( ) . map ( ModFileInfo : : getFile ) . collect ( Collectors . groupingBy ( ModFile : : getType ) ) ;
2018-03-25 15:59:43 +00:00
}
2018-04-07 15:48:43 +00:00
public static ICoreModProvider getCoreModProvider ( ) {
return coreModProvider ;
}
public static LanguageLoadingProvider getLanguageLoadingProvider ( )
{
return languageLoadingProvider ;
}
2018-04-07 22:15:32 +00:00
2018-12-31 21:33:54 +00:00
static ModDiscoverer getModDiscoverer ( ) {
return modDiscoverer ;
}
2018-04-07 22:15:32 +00:00
public static void addAccessTransformer ( Path atPath , ModFile modName )
{
2018-08-27 17:10:07 +00:00
LOGGER . debug ( SCAN , " Adding Access Transformer in {} " , modName . getFilePath ( ) ) ;
2020-07-27 21:36:30 +00:00
accessTransformer . offerResource ( atPath , modName . getFileName ( ) ) ;
2018-04-07 22:15:32 +00:00
}
2018-06-06 15:37:56 +00:00
2018-06-21 19:37:32 +00:00
public static Dist getDist ( )
2018-06-06 15:37:56 +00:00
{
2018-06-21 19:37:32 +00:00
return dist ;
2018-06-06 15:37:56 +00:00
}
2018-12-31 21:33:54 +00:00
public static void beforeStart ( ITransformingClassLoader launchClassLoader )
2018-06-06 15:37:56 +00:00
{
2019-01-04 16:44:57 +00:00
FMLLoader . launchClassLoader = ( TransformingClassLoader ) launchClassLoader . getInstance ( ) ;
2019-10-05 21:02:54 +00:00
StartupMessageManager . modLoaderConsumer ( ) . ifPresent ( c - > c . accept ( " Launching minecraft " ) ) ;
2020-04-26 22:24:48 +00:00
progressWindowTick . run ( ) ;
2018-06-06 15:37:56 +00:00
}
2018-06-15 19:03:35 +00:00
public static LoadingModList getLoadingModList ( )
{
return loadingModList ;
}
2019-01-04 16:44:57 +00:00
public static TransformingClassLoader getLaunchClassLoader ( )
2018-06-06 15:37:56 +00:00
{
2018-06-15 19:03:35 +00:00
return launchClassLoader ;
2018-06-06 15:37:56 +00:00
}
2018-06-22 18:38:53 +00:00
public static Path getGamePath ( )
{
return gamePath ;
}
2018-06-23 02:45:01 +00:00
public static Path getForgePath ( ) {
return forgePath ;
}
2018-12-31 21:33:54 +00:00
public static Path [ ] getMCPaths ( ) {
return mcPaths ;
}
public static Predicate < String > getClassLoaderExclusions ( ) {
return classLoaderExclusions ;
}
2019-04-06 16:10:54 +00:00
public static String getNaming ( ) {
return naming ;
}
public static Optional < BiFunction < INameMappingService . Domain , String , String > > getNameFunction ( final String naming ) {
return Launcher . INSTANCE . environment ( ) . findNameMapping ( naming ) ;
}
2019-07-03 08:08:20 +00:00
public static String getMcpVersion ( ) {
return mcpVersion ;
}
2019-07-27 00:02:21 +00:00
public static String getLauncherInfo ( ) {
return Launcher . INSTANCE . environment ( ) . getProperty ( IEnvironment . Keys . MLIMPL_VERSION . get ( ) ) . orElse ( " MISSING " ) ;
}
public static List < Map < String , String > > modLauncherModList ( ) {
return Launcher . INSTANCE . environment ( ) . getProperty ( IEnvironment . Keys . MODLIST . get ( ) ) . orElseGet ( Collections : : emptyList ) ;
}
public static String launcherHandlerName ( ) {
return launchHandlerName ;
}
2020-05-24 21:40:52 +00:00
public static boolean isProduction ( ) {
return production ;
}
2020-10-26 11:31:49 +00:00
public static boolean isSecureJarEnabled ( ) {
return Launcher . INSTANCE . environment ( ) . getProperty ( IEnvironment . Keys . SECURED_JARS_ENABLED . get ( ) ) . orElse ( false ) ;
}
2018-03-25 15:59:43 +00:00
}