Support backwards loading 1.16.3 mods in 1.16.4, because we are able to do that. Tweak loading a bit to be smarter about dependency errors of various kinds.
Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
parent
45e38859ed
commit
160f3f88f9
4 changed files with 65 additions and 34 deletions
|
@ -29,8 +29,6 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class EarlyLoadingException extends RuntimeException {
|
public class EarlyLoadingException extends RuntimeException {
|
||||||
public static class ExceptionData {
|
public static class ExceptionData {
|
||||||
|
|
||||||
|
|
||||||
private final IModInfo modInfo;
|
private final IModInfo modInfo;
|
||||||
private final String i18message;
|
private final String i18message;
|
||||||
private final Object[] args;
|
private final Object[] args;
|
||||||
|
|
|
@ -170,7 +170,7 @@ public class LanguageLoadingProvider
|
||||||
LOGGER.error("Missing language {} version {} wanted by {}", modLoader, modLoaderVersion, languageFileName);
|
LOGGER.error("Missing language {} version {} wanted by {}", modLoader, modLoaderVersion, languageFileName);
|
||||||
throw new EarlyLoadingException("Missing language "+modLoader, null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, "null")));
|
throw new EarlyLoadingException("Missing language "+modLoader, null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, "null")));
|
||||||
}
|
}
|
||||||
if (!modLoaderVersion.containsVersion(mlw.getVersion())) {
|
if (!VersionSupportMatrix.testVersionSupportMatrix(modLoaderVersion, modLoader, "languageloader", (llid, range) -> range.containsVersion(mlw.getVersion()))) {
|
||||||
LOGGER.error("Missing language {} version {} wanted by {}, found {}", modLoader, modLoaderVersion, languageFileName, mlw.getVersion());
|
LOGGER.error("Missing language {} version {} wanted by {}, found {}", modLoader, modLoaderVersion, languageFileName, mlw.getVersion());
|
||||||
throw new EarlyLoadingException("Missing language "+ modLoader + " matching range "+modLoaderVersion + " found "+mlw.getVersion(), null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, mlw.getVersion())));
|
throw new EarlyLoadingException("Missing language "+ modLoader + " matching range "+modLoaderVersion + " found "+mlw.getVersion(), null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, mlw.getVersion())));
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,17 +36,11 @@ import org.apache.logging.log4j.util.StringBuilderFormattable;
|
||||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||||
|
|
||||||
import java.util.AbstractMap;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
||||||
|
|
||||||
|
@ -65,26 +59,41 @@ public class ModSorter
|
||||||
public static LoadingModList sort(List<ModFile> mods)
|
public static LoadingModList sort(List<ModFile> mods)
|
||||||
{
|
{
|
||||||
final ModSorter ms = new ModSorter(mods);
|
final ModSorter ms = new ModSorter(mods);
|
||||||
|
try {
|
||||||
|
ms.buildUniqueList();
|
||||||
|
} catch (EarlyLoadingException e) {
|
||||||
|
// We cannot build any list with duped mods. We have to abort immediately and report it
|
||||||
|
return LoadingModList.of(Collections.emptyList(), Collections.emptyList(), e);
|
||||||
|
}
|
||||||
|
// try and locate languages and validate dependencies
|
||||||
|
List<EarlyLoadingException.ExceptionData> missingLangs = ms.findLanguages();
|
||||||
|
List<EarlyLoadingException.ExceptionData> missingDeps = ms.verifyDependencyVersions();
|
||||||
|
final List<ExceptionData> failedList = Stream.concat(missingLangs.stream(), missingDeps.stream()).collect(Collectors.toList());
|
||||||
|
// if we miss one or the other, we abort now
|
||||||
|
if (!failedList.isEmpty()) {
|
||||||
|
return LoadingModList.of(Collections.emptyList(), Collections.emptyList(), new EarlyLoadingException("failure to validate mod list", null, failedList));
|
||||||
|
} else {
|
||||||
|
// Otherwise, lets try and sort the modlist and proceed
|
||||||
EarlyLoadingException earlyLoadingException = null;
|
EarlyLoadingException earlyLoadingException = null;
|
||||||
try {
|
try {
|
||||||
ms.findLanguages();
|
|
||||||
ms.buildUniqueList();
|
|
||||||
ms.verifyDependencyVersions();
|
|
||||||
ms.sort();
|
ms.sort();
|
||||||
} catch (EarlyLoadingException ele) {
|
} catch (EarlyLoadingException e) {
|
||||||
earlyLoadingException = ele;
|
earlyLoadingException = e;
|
||||||
ms.sortedList = Collections.emptyList();
|
|
||||||
try {
|
|
||||||
ms.buildUniqueList();
|
|
||||||
} catch (EarlyLoadingException ele2) {
|
|
||||||
//IGNORE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return LoadingModList.of(ms.modFiles, ms.sortedList, earlyLoadingException);
|
return LoadingModList.of(ms.modFiles, ms.sortedList, earlyLoadingException);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void findLanguages() {
|
private List<EarlyLoadingException.ExceptionData> findLanguages() {
|
||||||
modFiles.forEach(ModFile::identifyLanguage);
|
List<EarlyLoadingException.ExceptionData> errorData = new ArrayList<>();
|
||||||
|
modFiles.forEach(modFile -> {
|
||||||
|
try {
|
||||||
|
modFile.identifyLanguage();
|
||||||
|
} catch (EarlyLoadingException e) {
|
||||||
|
errorData.addAll(e.getAllData());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return errorData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
|
@ -218,7 +227,7 @@ public class ModSorter
|
||||||
return new AbstractMap.SimpleImmutableEntry<>(fullList.getKey(), modInfoList.get(0));
|
return new AbstractMap.SimpleImmutableEntry<>(fullList.getKey(), modInfoList.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyDependencyVersions()
|
private List<EarlyLoadingException.ExceptionData> verifyDependencyVersions()
|
||||||
{
|
{
|
||||||
final Map<String, ArtifactVersion> modVersions = modFiles
|
final Map<String, ArtifactVersion> modVersions = modFiles
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -242,24 +251,24 @@ public class ModSorter
|
||||||
LOGGER.debug(LOADING, "Found {} mandatory requirements", mandatoryModVersions.size());
|
LOGGER.debug(LOADING, "Found {} mandatory requirements", mandatoryModVersions.size());
|
||||||
final Set<IModInfo.ModVersion> missingVersions = mandatoryModVersions
|
final Set<IModInfo.ModVersion> missingVersions = mandatoryModVersions
|
||||||
.stream()
|
.stream()
|
||||||
.filter(mv->this.modVersionMatches(mv, modVersions))
|
.filter(mv->this.modVersionNotContained(mv, modVersions))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
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()) {
|
||||||
final List<EarlyLoadingException.ExceptionData> exceptionData = missingVersions
|
return missingVersions
|
||||||
.stream()
|
.stream()
|
||||||
.map(mv -> new EarlyLoadingException.ExceptionData("fml.modloading.missingdependency", mv.getOwner(),
|
.map(mv -> new ExceptionData("fml.modloading.missingdependency", mv.getOwner(),
|
||||||
mv.getModId(), mv.getOwner().getModId(), mv.getVersionRange(),
|
mv.getModId(), mv.getOwner().getModId(), mv.getVersionRange(),
|
||||||
modVersions.getOrDefault(mv.getModId(), new DefaultArtifactVersion("null"))))
|
modVersions.getOrDefault(mv.getModId(), new DefaultArtifactVersion("null"))))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
throw new EarlyLoadingException("Missing mods", null, exceptionData);
|
|
||||||
}
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean modVersionMatches(final IModInfo.ModVersion mv, final Map<String, ArtifactVersion> modVersions)
|
private boolean modVersionNotContained(final IModInfo.ModVersion mv, final Map<String, ArtifactVersion> modVersions)
|
||||||
{
|
{
|
||||||
return !(modVersions.containsKey(mv.getModId()) &&
|
return !(VersionSupportMatrix.testVersionSupportMatrix(mv.getVersionRange(), mv.getModId(), "mod", (modId, range) -> modVersions.containsKey(modId) &&
|
||||||
(mv.getVersionRange().containsVersion(modVersions.get(mv.getModId())) || modVersions.get(mv.getModId()).toString().equals("NONE")));
|
(range.containsVersion(modVersions.get(modId)) || modVersions.get(modId).toString().equals("NONE"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package net.minecraftforge.fml.loading;
|
||||||
|
|
||||||
|
import net.minecraftforge.forgespi.language.MavenVersionAdapter;
|
||||||
|
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||||
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||||
|
import org.apache.maven.artifact.versioning.VersionRange;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
|
||||||
|
public class VersionSupportMatrix {
|
||||||
|
private static final HashMap<String, ArtifactVersion> overrideVersions = new HashMap<>();
|
||||||
|
static {
|
||||||
|
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.mcVersion);
|
||||||
|
if (MavenVersionAdapter.createFromVersionSpec("[1.16.4]").containsVersion(version)) {
|
||||||
|
overrideVersions.put("languageloader.javafml", new DefaultArtifactVersion("34")); // we also work with javafml 34
|
||||||
|
overrideVersions.put("mod.minecraft", new DefaultArtifactVersion("1.16.3")); // we work with anything declaring 1.16.3
|
||||||
|
overrideVersions.put("mod.forge", new DefaultArtifactVersion("34.1.42")); // we work with anything that supports forge 34.1.42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static <T> boolean testVersionSupportMatrix(VersionRange declaredRange, String lookupId, String type, BiPredicate<String, VersionRange> standardLookup) {
|
||||||
|
return standardLookup.test(lookupId, declaredRange) || overrideVersions.containsKey(type +"." +lookupId) && declaredRange.containsVersion(overrideVersions.get(type +"." +lookupId));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue