Refactor to use naming service, and provide an MCP naming service when

in userdev. Step 1 to supporting loading SRG mods in userdev.

Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
cpw 2019-04-06 12:10:54 -04:00
parent 323fdb014d
commit cdbd842494
No known key found for this signature in database
GPG Key ID: 8EB3DF749553B1B7
13 changed files with 188 additions and 72 deletions

View File

@ -288,8 +288,8 @@ project(':forge') {
installer 'org.ow2.asm:asm:6.2'
installer 'org.ow2.asm:asm-commons:6.2'
installer 'org.ow2.asm:asm-tree:6.2'
installer 'cpw.mods:modlauncher:0.12.+'
installer 'net.minecraftforge:accesstransformers:0.15.+:shadowed'
installer 'cpw.mods:modlauncher:1.0.+'
installer 'net.minecraftforge:accesstransformers:0.16.+:shadowed'
installer 'net.minecraftforge:eventbus:0.8.+:service'
installer 'net.minecraftforge:forgespi:0.11.+'
installer 'net.minecraftforge:coremods:0.4.+'

View File

@ -80,4 +80,9 @@ public class FMLClientLaunchProvider extends FMLCommonLaunchHandler implements I
{
return Dist.CLIENT;
}
@Override
protected String getNaming() {
return "srg";
}
}

View File

@ -135,4 +135,6 @@ public abstract class FMLCommonLaunchHandler
return Optional.empty();
};
}
protected abstract String getNaming();
}

View File

@ -26,8 +26,10 @@ import net.minecraftforge.forgespi.Environment;
public class FMLEnvironment
{
public static final Dist dist = FMLLoader.getDist();
public static final String naming = FMLLoader.getNaming();
static void setupInteropEnvironment(IEnvironment environment) {
environment.computePropertyIfAbsent(IEnvironment.Keys.NAMING.get(), v->naming);
environment.computePropertyIfAbsent(Environment.Keys.DIST.get(), v->dist);
}
}

View File

@ -19,27 +19,35 @@
package net.minecraftforge.fml.loading;
import cpw.mods.modlauncher.Launcher;
import cpw.mods.modlauncher.ServiceLoaderStreamUtils;
import cpw.mods.modlauncher.TransformingClassLoader;
import cpw.mods.modlauncher.api.IEnvironment;
import cpw.mods.modlauncher.api.ILaunchHandlerService;
import cpw.mods.modlauncher.api.INameMappingService;
import cpw.mods.modlauncher.api.ITransformationService;
import cpw.mods.modlauncher.api.ITransformingClassLoader;
import cpw.mods.modlauncher.api.IncompatibleEnvironmentException;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
import net.minecraftforge.accesstransformer.service.AccessTransformerService;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
import net.minecraftforge.fml.loading.moddiscovery.ModDiscoverer;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.forgespi.Environment;
import net.minecraftforge.forgespi.coremod.ICoreModProvider;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.ArrayList;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -49,12 +57,13 @@ import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
public class FMLLoader
{
private static final Logger LOGGER = LogManager.getLogger();
private static ILaunchPluginService accessTransformer;
private static AccessTransformerService accessTransformer;
private static ModDiscoverer modDiscoverer;
private static ICoreModProvider coreModProvider;
private static ILaunchPluginService eventBus;
private static LanguageLoadingProvider languageLoadingProvider;
private static Dist dist;
private static String naming;
private static LoadingModList loadingModList;
private static TransformingClassLoader launchClassLoader;
private static RuntimeDistCleaner runtimeDistCleaner;
@ -73,14 +82,14 @@ public class FMLLoader
LOGGER.debug(CORE,"FML {} loading", version);
final Package modLauncherPackage = ITransformationService.class.getPackage();
LOGGER.debug(CORE,"FML found ModLauncher version : {}", modLauncherPackage.getImplementationVersion());
if (!modLauncherPackage.isCompatibleWith("1.0")) {
if (!modLauncherPackage.isCompatibleWith("2.0")) {
LOGGER.fatal(CORE,"Found incompatible ModLauncher specification : {}, version {} from {}", modLauncherPackage.getSpecificationVersion(), modLauncherPackage.getImplementationVersion(), modLauncherPackage.getImplementationVendor());
throw new IncompatibleEnvironmentException("Incompatible modlauncher found "+modLauncherPackage.getSpecificationVersion());
}
LOGGER.debug(CORE, "Initializing modjar URL handler");
URL.setURLStreamHandlerFactory(p->p.equals("modjar") ? new ModJarURLHandler() : null);
accessTransformer = environment.findLaunchPlugin("accesstransformer").orElseThrow(()-> {
accessTransformer = (AccessTransformerService) environment.findLaunchPlugin("accesstransformer").orElseThrow(()-> {
LOGGER.fatal(CORE,"Access Transformer library is missing, we need this to run");
return new IncompatibleEnvironmentException("Missing AccessTransformer, cannot run");
});
@ -160,7 +169,9 @@ public class FMLLoader
gamePath = environment.getProperty(IEnvironment.Keys.GAMEDIR.get()).orElse(Paths.get(".").toAbsolutePath());
FMLCommonLaunchHandler commonLaunchHandler = (FMLCommonLaunchHandler)launchHandler.get();
naming = commonLaunchHandler.getNaming();
dist = commonLaunchHandler.getDist();
accessTransformer.getExtension().accept(Pair.of(naming, "srg"));
mcVersion = (String) arguments.get("mcVersion");
mcpVersion = (String) arguments.get("mcpVersion");
@ -245,4 +256,12 @@ public class FMLLoader
public static Predicate<String> getClassLoaderExclusions() {
return classLoaderExclusions;
}
public static String getNaming() {
return naming;
}
public static Optional<BiFunction<INameMappingService.Domain, String, String>> getNameFunction(final String naming) {
return Launcher.INSTANCE.environment().findNameMapping(naming);
}
}

View File

@ -19,7 +19,6 @@
package net.minecraftforge.fml.loading;
import com.google.common.collect.ObjectArrays;
import cpw.mods.modlauncher.api.IEnvironment;
import cpw.mods.modlauncher.api.ILaunchHandlerService;
import cpw.mods.modlauncher.api.ITransformingClassLoader;
@ -27,7 +26,6 @@ import net.minecraftforge.api.distmarker.Dist;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -74,4 +72,10 @@ public class FMLServerLaunchProvider extends FMLCommonLaunchHandler implements I
{
return Dist.DEDICATED_SERVER;
}
@Override
protected String getNaming() {
return "srg";
}
}

View File

@ -55,6 +55,7 @@ public class FMLServiceProvider implements ITransformationService
private String targetMcpVersion;
private String targetMcpMappings;
private String targetForgeGroup;
private Map<String, Object> arguments;
@Override
public String name()
@ -63,13 +64,12 @@ public class FMLServiceProvider implements ITransformationService
}
@Override
public void initialize(IEnvironment environment)
{
LOGGER.debug(CORE,"Setting up basic FML game directories");
public void initialize(IEnvironment environment) {
LOGGER.debug(CORE, "Setting up basic FML game directories");
FMLPaths.setup(environment);
LOGGER.debug(CORE,"Loading configuration");
LOGGER.debug(CORE, "Loading configuration");
FMLConfig.load();
final Map<String, Object> arguments = new HashMap<>();
arguments = new HashMap<>();
arguments.put("modLists", modListsArgumentList);
arguments.put("mods", modsArgumentList);
arguments.put("mavenRoots", mavenRootsArgumentList);
@ -82,6 +82,10 @@ public class FMLServiceProvider implements ITransformationService
FMLLoader.setupLaunchHandler(environment, arguments);
FMLEnvironment.setupInteropEnvironment(environment);
Environment.build(environment);
}
@Override
public void beginScanning(final IEnvironment environment) {
LOGGER.debug(CORE,"Initiating mod scan");
FMLLoader.beginModScan(arguments);
}

View File

@ -18,19 +18,17 @@
*/
package net.minecraftforge.fml.common;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
import javax.annotation.Nonnull;
import cpw.mods.modlauncher.api.INameMappingService;
import net.minecraftforge.fml.loading.FMLLoader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
@ -59,25 +57,9 @@ public class ObfuscationReflectionHelper
public static String[] remapNames(String... names)
public static String remapName(INameMappingService.Domain domain, String name)
{
loadMappings();
if (map.isEmpty())
return names;
String[] mappedNames = new String[names.length];
int i = 0;
for (String name : names)
mappedNames[i++] = map.getOrDefault(name, name);
return mappedNames;
}
public static String remapName(String name)
{
loadMappings();
if (map.isEmpty())
return name;
return map.getOrDefault(name, name);
return FMLLoader.getNameFunction("srg").map(f->f.apply(domain, name)).orElse(name);
}
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, E instance, int fieldIndex)
@ -99,16 +81,16 @@ public class ObfuscationReflectionHelper
{
try
{
return (T)findField(classToAccess, remapName(fieldName)).get(instance);
return (T)findField(classToAccess, remapName(INameMappingService.Domain.FIELD, fieldName)).get(instance);
}
catch (UnableToFindFieldException e)
{
LOGGER.error("Unable to locate field {} ({}) on type {}", fieldName, remapName(fieldName), classToAccess.getName(), e);
LOGGER.error(REFLECTION,"Unable to locate field {} ({}) on type {}", fieldName, remapName(INameMappingService.Domain.FIELD, fieldName), classToAccess.getName(), e);
throw e;
}
catch (IllegalAccessException e)
{
LOGGER.error("Unable to access field {} ({}) on type {}", fieldName, remapName(fieldName), classToAccess.getName(), e);
LOGGER.error(REFLECTION,"Unable to access field {} ({}) on type {}", fieldName, remapName(INameMappingService.Domain.FIELD, fieldName), classToAccess.getName(), e);
throw new UnableToAccessFieldException(e);
}
}
@ -132,7 +114,7 @@ public class ObfuscationReflectionHelper
{
try
{
findField(classToAccess, remapName(fieldName)).set(instance, value);
findField(classToAccess, remapName(INameMappingService.Domain.FIELD, fieldName)).set(instance, value);
}
catch (UnableToFindFieldException e)
{
@ -166,7 +148,7 @@ public class ObfuscationReflectionHelper
try
{
Method m = clazz.getDeclaredMethod(remapName(methodName), parameterTypes);
Method m = clazz.getDeclaredMethod(remapName(INameMappingService.Domain.METHOD, methodName), parameterTypes);
m.setAccessible(true);
return m;
}
@ -229,38 +211,6 @@ public class ObfuscationReflectionHelper
}
}
private static void loadMappings()
{
if (loaded)
return;
synchronized(map) //Just in case?
{
if (loaded) //Incase something else loaded while we were here, jump out
return;
for (String file : new String[]{"fields.csv", "methods.csv"})
{
URL path = ClassLoader.getSystemResource(file); //We EXPLICITLY go throught the SystemClassLoader here because this is dev-time only. And will be on the root classpath.
if (path == null)
continue;
int count = map.size();
LOGGER.info(REFLECTION, "Loading Mappings: {}", path);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(path.openStream())))
{
reader.lines().skip(1).map(e -> e.split(",")).forEach(e -> map.put(e[0], e[1]));
}
catch (IOException e1)
{
LOGGER.error(REFLECTION, "Error reading mappings", e1);
}
LOGGER.info(REFLECTION, "Loaded {} entries", map.size() - count);
}
loaded = true;
}
}
//Add SRG names to these exception?
public static class UnableToAccessFieldException extends RuntimeException
{
private UnableToAccessFieldException(Exception e)

View File

@ -107,4 +107,10 @@ public class FMLDevClientLaunchProvider extends FMLCommonLaunchHandler implement
@Override
protected void validatePaths(final Path forgePath, final Path[] mcPaths, final String forgeVersion, final String mcVersion, final String mcpVersion) {
}
@Override
protected String getNaming() {
return "mcp";
}
}

View File

@ -92,4 +92,10 @@ public class FMLDevServerLaunchProvider extends FMLCommonLaunchHandler implement
{
return Dist.DEDICATED_SERVER;
}
@Override
protected String getNaming() {
return "srg";
}
}

View File

@ -89,4 +89,10 @@ public abstract class FMLUserdevLaunchProvider extends FMLCommonLaunchHandler {
mcJars = LibraryFinder.findJarPathFor("en_us.json","mcdata", mcDataPath);
return new Path[] {mcJars};
}
@Override
protected String getNaming() {
return "mcp";
}
}

View File

@ -0,0 +1,111 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2019.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.userdev;
import cpw.mods.modlauncher.api.INameMappingService;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
public class MCPNamingService implements INameMappingService {
private static final Logger LOGGER = LogManager.getLogger();
private HashMap<String, String> methods;
private HashMap<String, String> fields;
@Override
public String mappingName() {
return "srgtomcp";
}
@Override
public String mappingVersion() {
return "1234";
}
@Override
public Map.Entry<String, String> understanding() {
return Pair.of("srg", "mcp");
}
@Override
public BiFunction<Domain, String, String> namingFunction() {
return this::findMapping;
}
private String findMapping(final Domain domain, final String srgName) {
switch (domain) {
case CLASS:
return srgName;
case FIELD:
return findFieldMapping(srgName);
case METHOD:
return findMethodMapping(srgName);
}
return srgName;
}
private String findMethodMapping(final String origin) {
if (methods == null) {
HashMap<String,String> tmpmethods = new HashMap<>(1000);
loadMappings("methods.csv", tmpmethods::put);
methods = tmpmethods;
LOGGER.debug(CORE, "Loaded {} method mappings from methods.csv", methods.size());
}
return methods.getOrDefault(origin, origin);
}
private String findFieldMapping(final String origin) {
if (fields == null) {
HashMap<String,String> tmpfields = new HashMap<>(1000);
loadMappings("fields.csv", tmpfields::put);
fields = tmpfields;
LOGGER.debug(CORE, "Loaded {} field mappings from fields.csv", fields.size());
}
return fields.getOrDefault(origin, origin);
}
private static void loadMappings(final String mappingFileName, BiConsumer<String, String> mapStore)
{
URL path = ClassLoader.getSystemResource(mappingFileName); //We EXPLICITLY go throught the SystemClassLoader here because this is dev-time only. And will be on the root classpath.
if (path == null)
return;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(path.openStream())))
{
reader.lines().skip(1).map(e -> e.split(",")).forEach(e -> mapStore.accept(e[0], e[1]));
}
catch (IOException e1)
{
LOGGER.error(CORE, "Error reading mappings", e1);
}
}
}

View File

@ -0,0 +1 @@
net.minecraftforge.userdev.MCPNamingService