fix dependency resolving, fix minecraft version parsing

(since 1.21 isn't valid semver but we can expand it)
This commit is contained in:
moehreag 2024-06-15 19:59:27 +02:00
parent a3aab3d87c
commit f0f742925b
4 changed files with 78 additions and 50 deletions

View file

@ -115,7 +115,7 @@ public class FrogLoaderImpl implements FrogLoader {
gamePlugin = plugin;
}
private void loadModProviders() {
private void loadModProviders() throws Exception {
PluginLoader.discoverModProviders(gameDir, mods, modIds, modProviders);
}

View file

@ -5,13 +5,17 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import dev.frogmc.frogloader.api.FrogLoader;
import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.api.plugin.FrogGamePlugin;
import dev.frogmc.frogloader.api.plugin.FrogModProvider;
import dev.frogmc.frogloader.impl.gui.LoaderGui;
import dev.frogmc.frogloader.impl.mixin.AWProcessor;
import dev.frogmc.frogloader.impl.mod.BuiltinExtensions;
import dev.frogmc.frogloader.impl.mod.ModDependencyResolver;
import dev.frogmc.frogloader.impl.util.CrashReportGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.asm.mixin.Mixins;
@ -19,7 +23,7 @@ import org.spongepowered.asm.mixin.Mixins;
public class PluginLoader {
private static final Logger LOGGER = LoggerFactory.getLogger("FrogLoader/Plugins");
public static void discoverModProviders(Path gameDir, Map<String, Map<String, ModProperties>> mods, Collection<String> modIds, Collection<FrogModProvider> modProviders) {
public static void discoverModProviders(Path gameDir, Map<String, Map<String, ModProperties>> mods, Collection<String> modIds, Collection<FrogModProvider> modProviders) throws ModDependencyResolver.ResolverException {
LOGGER.info("Discovering mod providers...");
for (FrogModProvider plugin : ServiceLoader.load(FrogModProvider.class)) {
@ -44,6 +48,16 @@ public class PluginLoader {
LOGGER.error("Error during plugin initialisation: ", e);
}
}
Collection<ModProperties> properties = mods.values().stream().map(Map::values).flatMap(Collection::stream).collect(Collectors.toUnmodifiableSet());
try {
Collection<ModProperties> solved = new ModDependencyResolver(properties).solve();
mods.forEach((s, map) -> map.values().retainAll(solved));
} catch (ModDependencyResolver.UnfulfilledDependencyException e) {
LoaderGui.execUnfulfilledDep(CrashReportGenerator.writeReport(e, properties), e, false);
} catch (ModDependencyResolver.BreakingModException e) {
LoaderGui.execBreakingDep(CrashReportGenerator.writeReport(e, properties), e, false);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})

View file

@ -230,18 +230,10 @@ public class ModDependencyResolver {
throw new IllegalArgumentException(comparator);
}
var type = DependencyType.of(matcher.group(1));
StringBuilder version = new StringBuilder(matcher.group(2));
while (version.length() < 5) {
if (version.charAt(version.length() - 1) == '.') {
version.append('0');
} else {
version.append('.');
}
}
var version = matcher.group(2);
try {
return new Comparator(type, SemVerImpl.parse(version.toString()));
return new Comparator(type, SemVerImpl.parse(version));
} catch (SemVerParseException e) {
throw new UncheckedIOException(e);
}
@ -325,6 +317,7 @@ public class ModDependencyResolver {
public record VersionRange(Collection<ComparatorSet> sets) {
private static final Pattern NUMBER_EXTRACTOR = Pattern.compile("[^~]?(\\d+)(?:\\.(?:([\\dxX*]+)(?:\\.([\\dxX*]+)?)?)?)?(.*)");
private static final Pattern FILL_PATTERN = Pattern.compile("[><=]+(\\d+)\\.?(\\d+)?\\.?(\\d+)?");
public static VersionRange parse(String range) throws ResolverException {
@ -365,13 +358,7 @@ public class ModDependencyResolver {
private static void handleTilde(String s, List<String> ranges) throws ResolverException {
{
StringBuilder builder = new StringBuilder(">=" + s.substring(1));
while (builder.length() < 7) {
if (builder.charAt(builder.length() - 1) == '.') {
builder.append('0');
} else {
builder.append('.');
}
}
fillVersion(builder);
ranges.add(builder.toString());
}
ranges.add(" ");
@ -393,13 +380,7 @@ public class ModDependencyResolver {
private static void handleXRanges(String s, List<String> ranges) throws ResolverException {
{
StringBuilder builder = new StringBuilder(">=" + s.replaceAll("[xX*]", "0"));
while (builder.length() < 7) {
if (builder.charAt(builder.length() - 1) == '.') {
builder.append('0');
} else {
builder.append('.');
}
}
fillVersion(builder);
ranges.add(builder.toString());
}
@ -424,13 +405,7 @@ public class ModDependencyResolver {
break;
}
}
while (builder.length() < 6) {
if (builder.charAt(builder.length() - 1) == '.') {
builder.append('0');
} else {
builder.append('.');
}
}
fillVersion(builder);
ranges.add(builder.toString());
}
}
@ -456,26 +431,21 @@ public class ModDependencyResolver {
break;
}
}
while (builder.length() < 6) {
fillVersion(builder);
/*while (builder.length() < 6) {
if (builder.charAt(builder.length() - 1) == '.') {
builder.append('0');
} else {
builder.append('.');
}
}
}*/
ranges.add(builder.toString());
}
private static void handleHyphenRange(String s, List<String> ranges, String end) throws ResolverException {
{
StringBuilder builder = new StringBuilder(">=" + s);
while (builder.length() < 7) {
if (builder.charAt(builder.length() - 1) == '.') {
builder.append('0');
} else {
builder.append('.');
}
}
fillVersion(builder);
ranges.add(builder.toString());
ranges.add(" ");
}
@ -499,19 +469,35 @@ public class ModDependencyResolver {
break;
}
}
while (builder.length() < 6) {
if (builder.charAt(builder.length() - 1) == '.') {
builder.append('0');
} else {
builder.append('.');
}
}
fillVersion(builder);
ranges.add(builder.toString());
} else {
ranges.add("<=" + end);
}
}
private static void fillVersion(StringBuilder builder) {
Matcher matcher = FILL_PATTERN.matcher(builder);
if (!matcher.find()) {
return;
}
if (matcher.group(3) != null) {
return;
}
if (builder.charAt(builder.length() - 1) != '.') {
builder.append(".");
}
if (matcher.group(2) == null) {
builder.append("0.0");
return;
}
builder.append("0");
}
private static @NotNull List<String> extractRanges(String range) {
if (!range.contains(" ") && !range.contains(" - ") && !range.contains("||")) {
return List.of(range);

View file

@ -1,5 +1,8 @@
package dev.frogmc.frogloader.impl.plugin.game.minecraft;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import dev.frogmc.frogloader.api.mod.SemVer;
import dev.frogmc.frogloader.impl.SemVerParseException;
import dev.frogmc.frogloader.impl.mod.SemVerImpl;
@ -7,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
public class MinecraftSemVerImpl implements SemVer {
private static final Pattern FILL_PATTERN = Pattern.compile("(\\d+)\\.?(\\d+)?\\.?(\\d+)?");
private final String version;
private MinecraftSemVerImpl(String version) {
@ -15,12 +19,36 @@ public class MinecraftSemVerImpl implements SemVer {
static SemVer get(String version) {
try {
return SemVerImpl.parse(version);
StringBuilder builder = new StringBuilder(version);
fillVersion(builder);
return SemVerImpl.parse(builder.toString());
} catch (SemVerParseException e) {
return new MinecraftSemVerImpl(version);
}
}
private static void fillVersion(StringBuilder builder) {
Matcher matcher = FILL_PATTERN.matcher(builder);
if (!matcher.find()) {
return;
}
if (matcher.group(3) != null) {
return;
}
if (builder.charAt(builder.length() - 1) != '.') {
builder.append(".");
}
if (matcher.group(2) == null) {
builder.append("0.0");
return;
}
builder.append("0");
}
@Override
public int major() {
throw new UnsupportedOperationException("Minecraft version " + version + " does not represent a semver-compatible version");