Better error passing from early to game client launch.
This commit is contained in:
parent
c6e7bbe18b
commit
d5e04dbcb5
|
@ -180,7 +180,11 @@ project(':forge') {
|
||||||
main 'net.minecraftforge.fml.LaunchTesting'
|
main 'net.minecraftforge.fml.LaunchTesting'
|
||||||
systemProperties = [
|
systemProperties = [
|
||||||
"org.lwjgl.util.Debug": "true",
|
"org.lwjgl.util.Debug": "true",
|
||||||
"org.lwjgl.util.DebugLoader": "true"
|
"org.lwjgl.util.DebugLoader": "true",
|
||||||
|
"mc.version": "${MC_VERSION}",
|
||||||
|
"mcp.version": "${MCP_VERSION}",
|
||||||
|
"forge.version": "${project.version}",
|
||||||
|
"forge.spec":"${SPEC_VERSION}"
|
||||||
]
|
]
|
||||||
environment += [
|
environment += [
|
||||||
target:'fmldevclient',
|
target:'fmldevclient',
|
||||||
|
|
|
@ -39,14 +39,23 @@ public class ForgeVersion
|
||||||
|
|
||||||
private static final String forgeVersion;
|
private static final String forgeVersion;
|
||||||
|
|
||||||
|
private static final String forgeSpec;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String vers = ForgeVersion.class.getPackage().getImplementationVersion();
|
String vers = ForgeVersion.class.getPackage().getImplementationVersion();
|
||||||
if (vers == null) {
|
if (vers == null) {
|
||||||
vers = System.getProperty("forge.version");
|
vers = System.getProperty("forge.version");
|
||||||
}
|
}
|
||||||
if (vers == null) throw new RuntimeException("Missing forge version, cannot continue");
|
if (vers == null) throw new RuntimeException("Missing forge version, cannot continue");
|
||||||
|
String spec = ForgeVersion.class.getPackage().getSpecificationVersion();
|
||||||
|
if (spec == null) {
|
||||||
|
spec = System.getProperty("forge.spec");
|
||||||
|
}
|
||||||
|
if (spec == null) throw new RuntimeException("Missing forge spec, cannot continue");
|
||||||
forgeVersion = vers;
|
forgeVersion = vers;
|
||||||
|
forgeSpec = spec;
|
||||||
LOGGER.info(CORE, "Found Forge version {}", forgeVersion);
|
LOGGER.info(CORE, "Found Forge version {}", forgeVersion);
|
||||||
|
LOGGER.info(CORE, "Found Forge spec {}", forgeSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getVersion()
|
public static String getVersion()
|
||||||
|
@ -64,5 +73,9 @@ public class ForgeVersion
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getSpec() {
|
||||||
|
return forgeSpec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,10 @@ package net.minecraftforge.fml;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import net.minecraft.nbt.INBTBase;
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.nbt.NBTTagList;
|
import net.minecraft.nbt.NBTTagList;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
@ -65,7 +64,7 @@ public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.Worl
|
||||||
{
|
{
|
||||||
final NBTTagCompound mod = new NBTTagCompound();
|
final NBTTagCompound mod = new NBTTagCompound();
|
||||||
mod.setString("ModId", mi.getModId());
|
mod.setString("ModId", mi.getModId());
|
||||||
mod.setString("ModVersion", mi.getVersion().getVersionString());
|
mod.setString("ModVersion", MavenVersionStringHelper.artifactVersionToString(mi.getVersion()));
|
||||||
modList.add(mod);
|
modList.add(mod);
|
||||||
});
|
});
|
||||||
fmlData.setTag("LoadingModList", modList);
|
fmlData.setTag("LoadingModList", modList);
|
||||||
|
@ -98,9 +97,9 @@ public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.Worl
|
||||||
LOGGER.error(WORLDPERSISTENCE,"This world was saved with mod {} which appears to be missing, things may not work well", modId);
|
LOGGER.error(WORLDPERSISTENCE,"This world was saved with mod {} which appears to be missing, things may not work well", modId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!modVersion.equals(container.get().getModInfo().getVersion().getVersionString()))
|
if (!Objects.equals(modVersion, MavenVersionStringHelper.artifactVersionToString(container.get().getModInfo().getVersion())))
|
||||||
{
|
{
|
||||||
LOGGER.info(WORLDPERSISTENCE,"This world was saved with mod {} version {} and it is now at version {}, things may not work well", modId, modVersion, container.get().getModInfo().getVersion().getVersionString());
|
LOGGER.info(WORLDPERSISTENCE,"This world was saved with mod {} version {} and it is now at version {}, things may not work well", modId, modVersion, MavenVersionStringHelper.artifactVersionToString(container.get().getModInfo().getVersion()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ public class ForgeI18n {
|
||||||
customFactories.put("lower", (name, formatString, locale) -> new CustomReadOnlyFormat((stringBuffer, objectToParse) -> stringBuffer.append(StringUtils.toLowerCase((String)objectToParse))));
|
customFactories.put("lower", (name, formatString, locale) -> new CustomReadOnlyFormat((stringBuffer, objectToParse) -> stringBuffer.append(StringUtils.toLowerCase((String)objectToParse))));
|
||||||
customFactories.put("upper", (name, formatString, locale) -> new CustomReadOnlyFormat((stringBuffer, objectToParse) -> stringBuffer.append(StringUtils.toUpperCase((String)objectToParse))));
|
customFactories.put("upper", (name, formatString, locale) -> new CustomReadOnlyFormat((stringBuffer, objectToParse) -> stringBuffer.append(StringUtils.toUpperCase((String)objectToParse))));
|
||||||
customFactories.put("exc", (name, formatString, locale) -> new CustomReadOnlyFormat((stringBuffer, objectToParse) -> parseException(formatString, stringBuffer, objectToParse)));
|
customFactories.put("exc", (name, formatString, locale) -> new CustomReadOnlyFormat((stringBuffer, objectToParse) -> parseException(formatString, stringBuffer, objectToParse)));
|
||||||
|
customFactories.put("vr", (name, formatString, locale) -> new CustomReadOnlyFormat(((stringBuffer, o) -> MavenVersionStringHelper.parseVersionRange(formatString, stringBuffer, o))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseException(final String formatString, final StringBuffer stringBuffer, final Object objectToParse) {
|
private static void parseException(final String formatString, final StringBuffer stringBuffer, final Object objectToParse) {
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||||
|
import org.apache.maven.artifact.versioning.Restriction;
|
||||||
|
import org.apache.maven.artifact.versioning.VersionRange;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class MavenVersionStringHelper {
|
||||||
|
public static String artifactVersionToString(final ArtifactVersion artifactVersion) {
|
||||||
|
return artifactVersion.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String versionRangeToString(final VersionRange range) {
|
||||||
|
return range.getRestrictions().stream().map(MavenVersionStringHelper::restrictionToString).collect(Collectors.joining(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String restrictionToString(final Restriction restriction) {
|
||||||
|
if ( restriction.getLowerBound() == null && restriction.getUpperBound() == null )
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.any");
|
||||||
|
}
|
||||||
|
else if ( restriction.getLowerBound() != null && restriction.getUpperBound() != null )
|
||||||
|
{
|
||||||
|
if (Objects.equals(artifactVersionToString(restriction.getLowerBound()), artifactVersionToString(restriction.getUpperBound())))
|
||||||
|
{
|
||||||
|
return artifactVersionToString(restriction.getLowerBound());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (restriction.isLowerBoundInclusive() && restriction.isUpperBoundInclusive())
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.inclusive", restriction.getLowerBound(), restriction.getUpperBound());
|
||||||
|
}
|
||||||
|
else if (restriction.isLowerBoundInclusive())
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.upperexclusive", restriction.getLowerBound(), restriction.getUpperBound());
|
||||||
|
}
|
||||||
|
else if (restriction.isUpperBoundInclusive())
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.lowerexclusive", restriction.getLowerBound(), restriction.getUpperBound());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.exclusive", restriction.getLowerBound(), restriction.getUpperBound());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( restriction.getLowerBound() != null )
|
||||||
|
{
|
||||||
|
if ( restriction.isLowerBoundInclusive() )
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.lower.inclusive", restriction.getLowerBound());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.lower.exclusive", restriction.getLowerBound());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( restriction.isUpperBoundInclusive() )
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.upper.inclusive", restriction.getUpperBound());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ForgeI18n.parseMessage("fml.messages.version.restriction.upper.exclusive", restriction.getUpperBound());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void parseVersionRange(final String formatString, final StringBuffer stringBuffer, final Object range) {
|
||||||
|
stringBuffer.append(versionRangeToString((VersionRange) range));
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,7 +60,7 @@ public class ModLoader
|
||||||
this.loadingModList = FMLLoader.getLoadingModList();
|
this.loadingModList = FMLLoader.getLoadingModList();
|
||||||
this.modClassLoader = new ModLoadingClassLoader(this.launchClassLoader);
|
this.modClassLoader = new ModLoadingClassLoader(this.launchClassLoader);
|
||||||
this.loadingExceptions = FMLLoader.getLoadingModList().
|
this.loadingExceptions = FMLLoader.getLoadingModList().
|
||||||
getErrors().stream().map(ModLoadingException::fromEarlyException).collect(Collectors.toList());
|
getErrors().stream().flatMap(ModLoadingException::fromEarlyException).collect(Collectors.toList());
|
||||||
Thread.currentThread().setContextClassLoader(this.modClassLoader);
|
Thread.currentThread().setContextClassLoader(this.modClassLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,9 +75,6 @@ public class ModLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadMods() {
|
public void loadMods() {
|
||||||
if (!this.loadingExceptions.isEmpty()) {
|
|
||||||
throw new LoadingFailedException(loadingExceptions);
|
|
||||||
}
|
|
||||||
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods());
|
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods());
|
||||||
ModContainer forgeModContainer;
|
ModContainer forgeModContainer;
|
||||||
try
|
try
|
||||||
|
@ -88,9 +85,12 @@ public class ModLoader
|
||||||
catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException e)
|
catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException e)
|
||||||
{
|
{
|
||||||
LOGGER.error(CORE,"Unable to load the Forge Mod Container", e);
|
LOGGER.error(CORE,"Unable to load the Forge Mod Container", e);
|
||||||
loadingExceptions.add(new ModLoadingException(DefaultModInfos.forgeModInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadforge", e));
|
loadingExceptions.add(new ModLoadingException(DefaultModInfos.forgeModInfo, ModLoadingStage.VALIDATE, "fml.modloading.failedtoloadforge", e));
|
||||||
forgeModContainer = null;
|
forgeModContainer = null;
|
||||||
}
|
}
|
||||||
|
if (!this.loadingExceptions.isEmpty()) {
|
||||||
|
throw new LoadingFailedException(loadingExceptions);
|
||||||
|
}
|
||||||
final Stream<ModContainer> modContainerStream = loadingModList.getModFiles().stream().
|
final Stream<ModContainer> modContainerStream = loadingModList.getModFiles().stream().
|
||||||
map(ModFileInfo::getFile).
|
map(ModFileInfo::getFile).
|
||||||
map(mf -> buildMods(mf, modClassLoader)).
|
map(mf -> buildMods(mf, modClassLoader)).
|
||||||
|
|
|
@ -59,8 +59,8 @@ public class ModLoadingException extends RuntimeException
|
||||||
this.context = Arrays.asList(context);
|
this.context = Arrays.asList(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ModLoadingException fromEarlyException(final EarlyLoadingException e) {
|
static Stream<ModLoadingException> fromEarlyException(final EarlyLoadingException e) {
|
||||||
return new ModLoadingException(null, ModLoadingStage.VALIDATE, e.getI18NMessage(), e, e.getContext().toArray());
|
return e.getAllData().stream().map(ed->new ModLoadingException(null, ModLoadingStage.VALIDATE, ed.getI18message(), e.getCause(), ed.getArgs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getI18NMessage() {
|
public String getI18NMessage() {
|
||||||
|
|
|
@ -37,14 +37,10 @@ import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.text.ITextComponent;
|
import net.minecraft.util.text.ITextComponent;
|
||||||
import net.minecraft.util.text.TextComponentString;
|
import net.minecraft.util.text.TextComponentString;
|
||||||
import net.minecraftforge.common.ForgeHooks;
|
import net.minecraftforge.common.ForgeHooks;
|
||||||
import net.minecraftforge.fml.ForgeI18n;
|
import net.minecraftforge.fml.*;
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
import net.minecraftforge.fml.ModList;
|
|
||||||
import net.minecraftforge.fml.VersionChecker;
|
|
||||||
import net.minecraftforge.fml.client.ConfigGuiHandler;
|
import net.minecraftforge.fml.client.ConfigGuiHandler;
|
||||||
import net.minecraftforge.fml.client.ResourcePackLoader;
|
import net.minecraftforge.fml.client.ResourcePackLoader;
|
||||||
import net.minecraftforge.fml.language.IModInfo;
|
import net.minecraftforge.fml.language.IModInfo;
|
||||||
import net.minecraftforge.fml.loading.MavenVersionAdapter;
|
|
||||||
import net.minecraftforge.fml.loading.StringUtils;
|
import net.minecraftforge.fml.loading.StringUtils;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
@ -291,7 +287,7 @@ public class GuiModList extends GuiScreen
|
||||||
for (ModInfo mod : mods)
|
for (ModInfo mod : mods)
|
||||||
{
|
{
|
||||||
listWidth = Math.max(listWidth,getFontRenderer().getStringWidth(mod.getDisplayName()) + 10);
|
listWidth = Math.max(listWidth,getFontRenderer().getStringWidth(mod.getDisplayName()) + 10);
|
||||||
listWidth = Math.max(listWidth,getFontRenderer().getStringWidth(MavenVersionAdapter.artifactVersionToString(mod.getVersion())) + 5);
|
listWidth = Math.max(listWidth,getFontRenderer().getStringWidth(MavenVersionStringHelper.artifactVersionToString(mod.getVersion())) + 5);
|
||||||
}
|
}
|
||||||
listWidth = Math.min(listWidth, 150);
|
listWidth = Math.min(listWidth, 150);
|
||||||
listWidth += listWidth % numButtons != 0 ? (numButtons - listWidth % numButtons) : 0;
|
listWidth += listWidth % numButtons != 0 ? (numButtons - listWidth % numButtons) : 0;
|
||||||
|
@ -455,7 +451,7 @@ public class GuiModList extends GuiScreen
|
||||||
}).orElse(Pair.of(null, new Dimension(0, 0)));
|
}).orElse(Pair.of(null, new Dimension(0, 0)));
|
||||||
|
|
||||||
lines.add(selectedMod.getDisplayName());
|
lines.add(selectedMod.getDisplayName());
|
||||||
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.version", MavenVersionAdapter.artifactVersionToString(selectedMod.getVersion())));
|
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.version", MavenVersionStringHelper.artifactVersionToString(selectedMod.getVersion())));
|
||||||
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.idstate", selectedMod.getModId(), ModList.get().getModContainerById(selectedMod.getModId()).
|
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.idstate", selectedMod.getModId(), ModList.get().getModContainerById(selectedMod.getModId()).
|
||||||
map(ModContainer::getCurrentState).map(Object::toString).orElse("NONE")));
|
map(ModContainer::getCurrentState).map(Object::toString).orElse("NONE")));
|
||||||
|
|
||||||
|
|
|
@ -19,16 +19,14 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml.client.gui;
|
package net.minecraftforge.fml.client.gui;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.FontRenderer;
|
import net.minecraft.client.gui.FontRenderer;
|
||||||
import net.minecraft.client.gui.Gui;
|
import net.minecraft.client.gui.Gui;
|
||||||
import net.minecraft.client.gui.GuiListExtended;
|
import net.minecraft.client.gui.GuiListExtended;
|
||||||
import net.minecraft.client.renderer.GlStateManager;
|
import net.minecraft.client.renderer.GlStateManager;
|
||||||
import net.minecraft.client.renderer.Tessellator;
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.common.ForgeVersion;
|
import net.minecraftforge.common.ForgeVersion;
|
||||||
|
import net.minecraftforge.fml.MavenVersionStringHelper;
|
||||||
import net.minecraftforge.fml.VersionChecker;
|
import net.minecraftforge.fml.VersionChecker;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||||
|
|
||||||
|
@ -97,7 +95,7 @@ public class GuiSlotModList extends GuiListExtended<GuiSlotModList.ModEntry>
|
||||||
int top = this.getY();
|
int top = this.getY();
|
||||||
int left = this.getX();
|
int left = this.getX();
|
||||||
String name = stripControlCodes(modInfo.getDisplayName());
|
String name = stripControlCodes(modInfo.getDisplayName());
|
||||||
String version = stripControlCodes(modInfo.getVersion().getVersionString());
|
String version = stripControlCodes(MavenVersionStringHelper.artifactVersionToString(modInfo.getVersion()));
|
||||||
VersionChecker.CheckResult vercheck = VersionChecker.getResult(modInfo);
|
VersionChecker.CheckResult vercheck = VersionChecker.getResult(modInfo);
|
||||||
FontRenderer font = this.parent.getFontRenderer();
|
FontRenderer font = this.parent.getFontRenderer();
|
||||||
font.drawString(font.trimStringToWidth(name, listWidth),left + 3, top + 2, 0xFFFFFF);
|
font.drawString(font.trimStringToWidth(name, listWidth),left + 3, top + 2, 0xFFFFFF);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package net.minecraftforge.fml.common.toposort;
|
package net.minecraftforge.fml.common.toposort;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import net.minecraftforge.fml.loading.EarlyLoadingException;
|
||||||
import org.apache.logging.log4j.message.Message;
|
import org.apache.logging.log4j.message.Message;
|
||||||
import org.apache.logging.log4j.util.StringBuilderFormattable;
|
import org.apache.logging.log4j.util.StringBuilderFormattable;
|
||||||
|
|
||||||
|
@ -35,6 +36,8 @@ import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Topological sort for mod loading
|
* Topological sort for mod loading
|
||||||
|
@ -250,6 +253,13 @@ public class TopologicalSort
|
||||||
buffer.append("Explored node set : {}\n").append(expandedNodes);
|
buffer.append("Explored node set : {}\n").append(expandedNodes);
|
||||||
buffer.append("Likely cycle is in : {}\n").append(Sets.difference(visitedNodes, expandedNodes));
|
buffer.append("Likely cycle is in : {}\n").append(Sets.difference(visitedNodes, expandedNodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<EarlyLoadingException.ExceptionData> toExceptionData(Function<T, String> nodeMapper) {
|
||||||
|
return Collections.singletonList(
|
||||||
|
new EarlyLoadingException.ExceptionData("fml.messages.cycleproblem",
|
||||||
|
nodeMapper.apply(node),
|
||||||
|
visitedNodes.stream().map(nodeMapper).collect(Collectors.joining(","))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> TopoSortException(TopoSortExceptionData<T> data)
|
public <T> TopoSortException(TopoSortExceptionData<T> data)
|
||||||
|
|
|
@ -8,20 +8,34 @@ import java.util.List;
|
||||||
* or server.
|
* or server.
|
||||||
*/
|
*/
|
||||||
public class EarlyLoadingException extends RuntimeException {
|
public class EarlyLoadingException extends RuntimeException {
|
||||||
private final String i18nMessage;
|
public static class ExceptionData {
|
||||||
private final List<Object> context;
|
|
||||||
|
|
||||||
public EarlyLoadingException(final String message, final String i18nMessage, final Throwable originalException, Object... context) {
|
|
||||||
|
private final String i18message;
|
||||||
|
private final Object[] args;
|
||||||
|
public ExceptionData(final String message, Object... args) {
|
||||||
|
this.i18message = message;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getI18message() {
|
||||||
|
return i18message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getArgs() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private final List<ExceptionData> errorMessages;
|
||||||
|
|
||||||
|
public List<ExceptionData> getAllData() {
|
||||||
|
return errorMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
EarlyLoadingException(final String message, final Throwable originalException, List<ExceptionData> errorMessages) {
|
||||||
super(message, originalException);
|
super(message, originalException);
|
||||||
this.i18nMessage = i18nMessage;
|
this.errorMessages = errorMessages;
|
||||||
this.context = Arrays.asList(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getI18NMessage() {
|
|
||||||
return this.i18nMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Object> getContext() {
|
|
||||||
return this.context;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.core.config.Configurator;
|
import org.apache.logging.log4j.core.config.Configurator;
|
||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -51,14 +52,20 @@ public class FMLClientLaunchProvider extends FMLCommonLaunchHandler implements I
|
||||||
"net.minecraftforge.fml.common.versioning."
|
"net.minecraftforge.fml.common.versioning."
|
||||||
);
|
);
|
||||||
static {
|
static {
|
||||||
|
Path forgePath1 = null;
|
||||||
|
Path patchedBinariesPath1 = null;
|
||||||
|
Path srgMcPath1 = null;
|
||||||
try {
|
try {
|
||||||
forgePath = Paths.get(FMLClientLaunchProvider.class.getProtectionDomain().getCodeSource().getLocation().toURI());
|
forgePath1 = Paths.get(FMLClientLaunchProvider.class.getProtectionDomain().getCodeSource().getLocation().toURI());
|
||||||
patchedBinariesPath = forgePath.resolveSibling("forge-"+MCPVersion.getMCVersion()+"-"+ForgeVersion.getVersion()+"-client.jar");
|
patchedBinariesPath1 = forgePath1.resolveSibling("forge-"+MCPVersion.getMCVersion()+"-"+ForgeVersion.getVersion()+"-client.jar");
|
||||||
Path libs = forgePath.getParent().getParent().getParent().getParent().getParent();
|
Path libs = forgePath1.getParent().getParent().getParent().getParent().getParent();
|
||||||
srgMcPath = libs.resolve(Paths.get("net","minecraft", "client", MCPVersion.getMCPandMCVersion(), "client-"+MCPVersion.getMCPandMCVersion()+"-srg.jar")).toAbsolutePath();
|
srgMcPath1 = libs.resolve(Paths.get("net","minecraft", "client", MCPVersion.getMCPandMCVersion(), "client-"+MCPVersion.getMCPandMCVersion()+"-srg.jar")).toAbsolutePath();
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new RuntimeException("Unable to locate myself!");
|
|
||||||
}
|
}
|
||||||
|
forgePath = forgePath1;
|
||||||
|
patchedBinariesPath = patchedBinariesPath1;
|
||||||
|
srgMcPath = srgMcPath1;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String name()
|
public String name()
|
||||||
|
@ -69,9 +76,12 @@ public class FMLClientLaunchProvider extends FMLCommonLaunchHandler implements I
|
||||||
@Override
|
@Override
|
||||||
public Path[] identifyTransformationTargets()
|
public Path[] identifyTransformationTargets()
|
||||||
{
|
{
|
||||||
LOGGER.info("Found SRG MC at {}", srgMcPath.toString());
|
LOGGER.info("SRG MC at {} is {}", srgMcPath.toString(), Files.exists(srgMcPath) ? "present" : "missing");
|
||||||
LOGGER.info("Found Forge patches at {}", patchedBinariesPath.toString());
|
LOGGER.info("Forge patches at {} is {}", patchedBinariesPath.toString(), Files.exists(patchedBinariesPath) ? "present" : "missing");
|
||||||
LOGGER.info("Found Forge at {}", forgePath.toString());
|
LOGGER.info("Forge at {} is {}", forgePath.toString(), Files.exists(forgePath) ? "present" : "missing");
|
||||||
|
if (!(Files.exists(srgMcPath) && Files.exists(patchedBinariesPath) && Files.exists(forgePath))) {
|
||||||
|
throw new RuntimeException("Failed to find patched jars");
|
||||||
|
}
|
||||||
return new Path[] {forgePath, patchedBinariesPath, srgMcPath};
|
return new Path[] {forgePath, patchedBinariesPath, srgMcPath};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class LanguageLoadingProvider
|
||||||
final Package pkg = lp.getClass().getPackage();
|
final Package pkg = lp.getClass().getPackage();
|
||||||
String implementationVersion = pkg.getImplementationVersion();
|
String implementationVersion = pkg.getImplementationVersion();
|
||||||
if (implementationVersion == null) {
|
if (implementationVersion == null) {
|
||||||
implementationVersion = ForgeVersion.getVersion();
|
implementationVersion = ForgeVersion.getSpec();
|
||||||
}
|
}
|
||||||
LOGGER.debug(CORE, "Found system classpath language provider {}, version {}", lp.name(), implementationVersion);
|
LOGGER.debug(CORE, "Found system classpath language provider {}, version {}", lp.name(), implementationVersion);
|
||||||
languageProviderMap.put(lp.name(), new ModLanguageWrapper(lp, new DefaultArtifactVersion(implementationVersion)));
|
languageProviderMap.put(lp.name(), new ModLanguageWrapper(lp, new DefaultArtifactVersion(implementationVersion)));
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
package net.minecraftforge.fml.loading;
|
package net.minecraftforge.fml.loading;
|
||||||
|
|
||||||
import net.minecraftforge.fml.ForgeI18n;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
|
||||||
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
|
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
|
||||||
import org.apache.maven.artifact.versioning.Restriction;
|
|
||||||
import org.apache.maven.artifact.versioning.VersionRange;
|
import org.apache.maven.artifact.versioning.VersionRange;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static net.minecraftforge.fml.Logging.CORE;
|
import static net.minecraftforge.fml.Logging.CORE;
|
||||||
|
|
||||||
public final class MavenVersionAdapter {
|
public final class MavenVersionAdapter {
|
||||||
|
@ -25,66 +19,5 @@ public final class MavenVersionAdapter {
|
||||||
throw new RuntimeException("Failed to parse spec", e);
|
throw new RuntimeException("Failed to parse spec", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String artifactVersionToString(final ArtifactVersion artifactVersion) {
|
|
||||||
return artifactVersion.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String versionRangeToString(final VersionRange range) {
|
|
||||||
return range.getRestrictions().stream().map(MavenVersionAdapter::restrictionToString).collect(Collectors.joining(","));
|
|
||||||
}
|
|
||||||
public static String restrictionToString(final Restriction restriction) {
|
|
||||||
if ( restriction.getLowerBound() == null && restriction.getUpperBound() == null )
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.any");
|
|
||||||
}
|
|
||||||
else if ( restriction.getLowerBound() != null && restriction.getUpperBound() != null )
|
|
||||||
{
|
|
||||||
if (Objects.equals(artifactVersionToString(restriction.getLowerBound()), artifactVersionToString(restriction.getUpperBound())))
|
|
||||||
{
|
|
||||||
return artifactVersionToString(restriction.getLowerBound());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (restriction.isLowerBoundInclusive() && restriction.isUpperBoundInclusive())
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.inclusive", restriction.getLowerBound(), restriction.getUpperBound());
|
|
||||||
}
|
|
||||||
else if (restriction.isLowerBoundInclusive())
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.upperexclusive", restriction.getLowerBound(), restriction.getUpperBound());
|
|
||||||
}
|
|
||||||
else if (restriction.isUpperBoundInclusive())
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.lowerexclusive", restriction.getLowerBound(), restriction.getUpperBound());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.exclusive", restriction.getLowerBound(), restriction.getUpperBound());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( restriction.getLowerBound() != null )
|
|
||||||
{
|
|
||||||
if ( restriction.isLowerBoundInclusive() )
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.lower.inclusive", restriction.getLowerBound());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.lower.exclusive", restriction.getLowerBound());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( restriction.isUpperBoundInclusive() )
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.upper.inclusive", restriction.getUpperBound());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ForgeI18n.parseMessage("fml.messages.version.restriction.upper.exclusive", restriction.getUpperBound());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,9 @@ import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||||
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -62,6 +60,7 @@ public class ModSorter
|
||||||
ms.sort();
|
ms.sort();
|
||||||
} catch (EarlyLoadingException ele) {
|
} catch (EarlyLoadingException ele) {
|
||||||
earlyLoadingException = ele;
|
earlyLoadingException = ele;
|
||||||
|
ms.sortedList = Collections.emptyList();
|
||||||
}
|
}
|
||||||
return LoadingModList.of(ms.modFiles, ms.sortedList, earlyLoadingException);
|
return LoadingModList.of(ms.modFiles, ms.sortedList, earlyLoadingException);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +69,8 @@ public class ModSorter
|
||||||
{
|
{
|
||||||
final TopologicalSort.DirectedGraph<Supplier<ModFileInfo>> topoGraph = new TopologicalSort.DirectedGraph<>();
|
final TopologicalSort.DirectedGraph<Supplier<ModFileInfo>> topoGraph = new TopologicalSort.DirectedGraph<>();
|
||||||
modFiles.stream().map(ModFile::getModFileInfo).map(ModFileInfo.class::cast).forEach(mi -> topoGraph.addNode(() -> mi));
|
modFiles.stream().map(ModFile::getModFileInfo).map(ModFileInfo.class::cast).forEach(mi -> topoGraph.addNode(() -> mi));
|
||||||
modFiles.stream().map(ModFile::getModInfos).flatMap(Collection::stream).map(IModInfo::getDependencies).flatMap(Collection::stream).
|
modFiles.stream().map(ModFile::getModInfos).flatMap(Collection::stream).
|
||||||
|
map(IModInfo::getDependencies).flatMap(Collection::stream).
|
||||||
forEach(dep -> addDependency(topoGraph, dep));
|
forEach(dep -> addDependency(topoGraph, dep));
|
||||||
final List<Supplier<ModFileInfo>> sorted;
|
final List<Supplier<ModFileInfo>> sorted;
|
||||||
try
|
try
|
||||||
|
@ -81,7 +81,7 @@ public class ModSorter
|
||||||
{
|
{
|
||||||
TopologicalSort.TopoSortException.TopoSortExceptionData<Supplier<ModInfo>> data = e.getData();
|
TopologicalSort.TopoSortException.TopoSortExceptionData<Supplier<ModInfo>> data = e.getData();
|
||||||
LOGGER.error(LOADING, ()-> data);
|
LOGGER.error(LOADING, ()-> data);
|
||||||
throw new EarlyLoadingException("Sorting error", "fml.modloading.sortingerror", e, e.getData());
|
throw new EarlyLoadingException("Sorting error", e, data.toExceptionData(mi-> mi.get().getModId()));
|
||||||
}
|
}
|
||||||
this.sortedList = sorted.stream().map(Supplier::get).map(ModFileInfo::getMods).
|
this.sortedList = sorted.stream().map(Supplier::get).map(ModFileInfo::getMods).
|
||||||
flatMap(Collection::stream).map(ModInfo.class::cast).collect(Collectors.toList());
|
flatMap(Collection::stream).map(ModInfo.class::cast).collect(Collectors.toList());
|
||||||
|
@ -111,7 +111,10 @@ public class ModSorter
|
||||||
final List<Map.Entry<String, List<ModInfo>>> dupedMods = modIds.entrySet().stream().filter(e -> e.getValue().size() > 1).collect(Collectors.toList());
|
final List<Map.Entry<String, List<ModInfo>>> dupedMods = modIds.entrySet().stream().filter(e -> e.getValue().size() > 1).collect(Collectors.toList());
|
||||||
|
|
||||||
if (!dupedMods.isEmpty()) {
|
if (!dupedMods.isEmpty()) {
|
||||||
throw new EarlyLoadingException("Duplicate mods found", "fml.modloading.dupesfound", null, dupedMods);
|
final List<EarlyLoadingException.ExceptionData> duplicateModErrors = dupedMods.stream().
|
||||||
|
map(dm -> new EarlyLoadingException.ExceptionData("fml.modloading.dupedmod", dm.getValue().get(0))).
|
||||||
|
collect(Collectors.toList());
|
||||||
|
throw new EarlyLoadingException("Duplicate mods found", null, duplicateModErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
modIdNameLookup = modIds.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
|
modIdNameLookup = modIds.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
|
||||||
|
@ -131,7 +134,12 @@ public class ModSorter
|
||||||
LOGGER.debug(LOADING, "Found {} mandatory mod requirements missing", missingVersions.size());
|
LOGGER.debug(LOADING, "Found {} mandatory mod requirements missing", missingVersions.size());
|
||||||
|
|
||||||
if (!missingVersions.isEmpty()) {
|
if (!missingVersions.isEmpty()) {
|
||||||
throw new EarlyLoadingException("Missing mods", "fml.modloading.missingmods", null, missingVersions);
|
final List<EarlyLoadingException.ExceptionData> exceptionData = missingVersions.stream().map(mv ->
|
||||||
|
new EarlyLoadingException.ExceptionData("fml.modloading.missingdependency", mv.getModId(),
|
||||||
|
mv.getOwner().getModId(), mv.getVersionRange(),
|
||||||
|
modVersions.containsKey(mv.getModId()) ? modVersions.get(mv.getModId()) : "NONE" )).
|
||||||
|
collect(Collectors.toList());
|
||||||
|
throw new EarlyLoadingException("Missing mods", null, exceptionData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
"fml.modloading.failedtoloadmod":"{0,modinfo,name} ({0,modinfo,id}) has failed to load correctly\n\u00a77{2,exc,msg}",
|
"fml.modloading.failedtoloadmod":"{0,modinfo,name} ({0,modinfo,id}) has failed to load correctly\n\u00a77{2,exc,msg}",
|
||||||
"fml.modloading.errorduringevent":"{0,modinfo,name} ({0,modinfo,id}) encountered an error during the {1,lower} event phase\n\u00a77{2,exc,msg}",
|
"fml.modloading.errorduringevent":"{0,modinfo,name} ({0,modinfo,id}) encountered an error during the {1,lower} event phase\n\u00a77{2,exc,msg}",
|
||||||
"fml.modloading.failedtoloadforge": "Failed to load forge",
|
"fml.modloading.failedtoloadforge": "Failed to load forge",
|
||||||
|
"fml.modloading.missingdependency": "Mod {4} has missing dependency {3}\n\u00a77Want {5,vr}, have {6}",
|
||||||
|
|
||||||
"fml.messages.version.restriction.any":"any",
|
"fml.messages.version.restriction.any":"any",
|
||||||
"fml.messages.version.restriction.lower.inclusive":"{0} or above",
|
"fml.messages.version.restriction.lower.inclusive":"{0} or above",
|
||||||
|
|
Loading…
Reference in New Issue