Compare commits

..

No commits in common. "b3085264ee124abe2898402312c47740d011284c" and "bc520da577dee967ad79ff95fa2711208509554a" have entirely different histories.

7 changed files with 108 additions and 118 deletions

View file

@ -1,10 +1,43 @@
package dev.frogmc.frogloader.api.mod; package dev.frogmc.frogloader.api.mod;
import java.util.Collection; import java.util.*;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public interface ModDependencies { /**
* A mod's dependencies.
*
* <p>Mod dependencies are declared in four types:</p>
* <code>Type.DEPEND</code>, <code>Type.BREAK</code>, <code>Type.SUGGEST</code> and <code>Type.PROVIDE</code>
*
* <p>Note: The <code>Type.PROVIDE</code> is a bit of a special case in the way that it only supports a single SemVer version instead of a full version range.</p>
*
* @see ModDependencies.Type
* @see ModDependencies.Entry
* @see ModProperties
* @see SemVer
*/
public final class ModDependencies {
private final Map<Type, Collection<Entry>> entries = new HashMap<>();
/**
* Construct new mod dependencies for a mod.
* <p><strong>Internal use only.</strong></p>
*
* @param depends <code>Type.DEPEND</code> entries
* @param breaks <code>Type.BREAK</code> entries
* @param suggests <code>Type.SUGGEST</code> entries
* @param provides <code>Type.PROVIDE</code> entries
*/
@ApiStatus.Internal
public ModDependencies(Collection<Entry> depends, Collection<Entry> breaks, Collection<Entry> suggests, Collection<Entry> provides) {
entries.put(Type.DEPEND, depends);
entries.put(Type.BREAK, breaks);
entries.put(Type.SUGGEST, suggests);
entries.put(Type.PROVIDE, provides);
}
/** /**
* Get dependencies of a specific mod for a specific type * Get dependencies of a specific mod for a specific type
@ -12,7 +45,9 @@ public interface ModDependencies {
* @param type the dependency type to query for * @param type the dependency type to query for
* @return a collection of dependency entries * @return a collection of dependency entries
*/ */
Collection<Entry> getForType(Type type); public Collection<Entry> getForType(Type type) {
return entries.get(type);
}
/** /**
* Get entries that depend on a specific mod's id * Get entries that depend on a specific mod's id
@ -20,7 +55,17 @@ public interface ModDependencies {
* @param id the mod id to find dependency entries for * @param id the mod id to find dependency entries for
* @return a collection of entries that depend on the given mod id * @return a collection of entries that depend on the given mod id
*/ */
Collection<Entry> getForModId(String id); public Collection<ModEntry> getForModId(String id) {
List<ModEntry> entries = new ArrayList<>();
for (Type type : Type.values()) {
for (Entry entry : getForType(type)) {
if (entry.id.equals(id)) {
entries.add(new ModEntry(type, entry.range, entry.link, entry.name));
}
}
}
return entries;
}
/** /**
* Dependency types to distinguish their variants. * Dependency types to distinguish their variants.
@ -45,45 +90,69 @@ public interface ModDependencies {
} }
/** /**
* Represents a mod's dependency. * A data class to handle entries depending on a specific mod id
*/ */
interface Entry { public static class ModEntry {
private final Type type;
private final String range;
private final String link;
private final String name;
private ModEntry(Type type, String range, String link, String name) {
this.type = type;
this.range = range;
this.link = link;
this.name = name;
}
/** /**
* Get this dependency's type. * Get this dependency's type
* *
* @return This dependency's type. * @return This dependency's type
*/ */
Type type(); public Type type() {
return type;
}
/** /**
* Get this dependency's mod ID. * Get this dependency's version range
* *
* @return This dependency's mod ID. * @return This dependency's version range
*/ */
String id(); public String range() {
return range;
}
/** /**
* Get this dependency's version range. * Get this dependency's link
* <p>May be null.</p>
* *
* @return This dependency's version range. * @return This dependency's link
*/ */
@Nullable String range(); public @Nullable String link() {
return link;
}
/** /**
* Get this dependency's installation link. * Get this dependency's (friendly) name
* <p>May be null.</p>
* *
* @return This dependency's installation link. * @return This dependency's name
*/ */
@Nullable String link(); public @Nullable String name() {
return name;
/** }
* Get this dependency's friendly name.
*
* @return This dependency's name.
*/
@Nullable String name();
} }
/**
* General storage for dependencies
*
* @param id the mod's id
* @param range the dependency's version range
* @param link an optional link for information about this dependency
* @param name an optional (friendly) name for this dependency
*/
public record Entry(String id, String range, String link, String name) {
}
} }

View file

@ -6,13 +6,11 @@ import java.util.Map;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import dev.frogmc.frogloader.impl.mod.ModDependenciesImpl;
/** /**
* A mod's properties. This class represents a mod at runtime. * A mod's properties. This class represents a mod at runtime.
* It is read from each mod's <code>frog.mod.toml</code> file. * It is read from each mod's <code>frog.mod.toml</code> file.
* *
* @see ModDependenciesImpl * @see ModDependencies
* @see ModExtensions * @see ModExtensions
* @see SemVer * @see SemVer
*/ */
@ -67,7 +65,7 @@ public interface ModProperties {
* Get this mod's dependencies. * Get this mod's dependencies.
* *
* @return The mod's dependencies * @return The mod's dependencies
* @see ModDependenciesImpl * @see ModDependencies
*/ */
ModDependencies dependencies(); ModDependencies dependencies();

View file

@ -3,6 +3,7 @@ package dev.frogmc.frogloader.impl.mod;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import dev.frogmc.frogloader.api.mod.ModDependencies;
import dev.frogmc.frogloader.api.mod.ModExtensions; import dev.frogmc.frogloader.api.mod.ModExtensions;
import dev.frogmc.frogloader.api.mod.ModProperties; import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.impl.SemVerParseException; import dev.frogmc.frogloader.impl.SemVerParseException;
@ -23,7 +24,7 @@ public class JavaModProperties {
SemVerImpl.parse(System.getProperty("java.runtime.version")), SemVerImpl.parse(System.getProperty("java.runtime.version")),
"", "",
Map.of(System.getProperty("java.vm.vendor"), Collections.singleton("Vendor")), Map.of(System.getProperty("java.vm.vendor"), Collections.singleton("Vendor")),
new ModDependenciesImpl(Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet()), new ModDependencies(Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet()),
new ModExtensionsImpl(Collections.emptyMap()), Collections.emptySet()); new ModExtensionsImpl(Collections.emptyMap()), Collections.emptySet());
} }
return INSTANCE; return INSTANCE;

View file

@ -1,75 +0,0 @@
package dev.frogmc.frogloader.impl.mod;
import java.util.*;
import dev.frogmc.frogloader.api.mod.ModDependencies;
import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.api.mod.SemVer;
/**
* A mod's dependencies.
*
* <p>Mod dependencies are declared in four types:</p>
* <code>Type.DEPEND</code>, <code>Type.BREAK</code>, <code>Type.SUGGEST</code> and <code>Type.PROVIDE</code>
*
* <p>Note: The <code>Type.PROVIDE</code> is a bit of a special case in the way that it only supports a single SemVer version instead of a full version range.</p>
*
* @see ModDependenciesImpl.Type
* @see ModDependenciesImpl.Entry
* @see ModProperties
* @see SemVer
*/
public final class ModDependenciesImpl implements ModDependencies {
private final Map<Type, Collection<ModDependencies.Entry>> entries = new HashMap<>();
/**
* Construct new mod dependencies for a mod.
* <p><strong>Internal use only.</strong></p>
*
* @param depends <code>Type.DEPEND</code> entries
* @param breaks <code>Type.BREAK</code> entries
* @param suggests <code>Type.SUGGEST</code> entries
* @param provides <code>Type.PROVIDE</code> entries
*/
public ModDependenciesImpl(Collection<ModDependencies.Entry> depends, Collection<ModDependencies.Entry> breaks, Collection<ModDependencies.Entry> suggests, Collection<ModDependencies.Entry> provides) {
entries.put(Type.DEPEND, depends);
entries.put(Type.BREAK, breaks);
entries.put(Type.SUGGEST, suggests);
entries.put(Type.PROVIDE, provides);
}
/**
* Get dependencies of a specific mod for a specific type
*
* @param type the dependency type to query for
* @return a collection of dependency entries
*/
@Override
public Collection<ModDependencies.Entry> getForType(Type type) {
return entries.get(type);
}
/**
* Get entries that depend on a specific mod's id
*
* @param id the mod id to find dependency entries for
* @return a collection of entries that depend on the given mod id
*/
@Override
public Collection<ModDependencies.Entry> getForModId(String id) {
List<ModDependencies.Entry> entries = new ArrayList<>();
for (Type type : Type.values()) {
for (ModDependencies.Entry entry : getForType(type)) {
if (entry.id().equals(id)) {
entries.add(entry);
}
}
}
return entries;
}
public record Entry(Type type, String id, String range, String link, String name) implements ModDependencies.Entry {
}
}

View file

@ -8,7 +8,6 @@ import java.util.stream.Collectors;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder; import com.google.common.collect.MultimapBuilder;
import dev.frogmc.frogloader.api.mod.ModDependencies; import dev.frogmc.frogloader.api.mod.ModDependencies;
import dev.frogmc.frogloader.api.mod.ModProperties; import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.api.mod.SemVer; import dev.frogmc.frogloader.api.mod.SemVer;

View file

@ -7,7 +7,6 @@ import java.nio.file.FileSystem;
import java.nio.file.FileSystems; import java.nio.file.FileSystems;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -15,7 +14,6 @@ import com.electronwill.nightconfig.core.CommentedConfig;
import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.electronwill.nightconfig.core.file.FileNotFoundAction; import com.electronwill.nightconfig.core.file.FileNotFoundAction;
import com.electronwill.nightconfig.toml.TomlParser; import com.electronwill.nightconfig.toml.TomlParser;
import dev.frogmc.frogloader.api.mod.ModDependencies; import dev.frogmc.frogloader.api.mod.ModDependencies;
import dev.frogmc.frogloader.api.mod.ModExtensions; import dev.frogmc.frogloader.api.mod.ModExtensions;
import dev.frogmc.frogloader.api.mod.ModProperties; import dev.frogmc.frogloader.api.mod.ModProperties;
@ -126,7 +124,7 @@ public class ModPropertiesReader {
} }
} }
BiFunction<ModDependencies.Type, String, Collection<ModDependencies.Entry>> parseDependencies = (type, key) -> { Function<String, Collection<ModDependencies.Entry>> parseDependencies = key -> {
Collection<ModDependencies.Entry> result = new HashSet<>(); Collection<ModDependencies.Entry> result = new HashSet<>();
List<UnmodifiableConfig> dependenciesConfig = config.get("frog.dependencies." + key); List<UnmodifiableConfig> dependenciesConfig = config.get("frog.dependencies." + key);
@ -140,7 +138,7 @@ public class ModPropertiesReader {
if (entryId == null || entryId.isEmpty()) if (entryId == null || entryId.isEmpty())
badProperties.add("frog.dependencies." + key + '.' + i + ".id"); badProperties.add("frog.dependencies." + key + '.' + i + ".id");
result.add(new ModDependenciesImpl.Entry(type, entryId, entryVersions, entry.get("link"), entry.get("name"))); result.add(new ModDependencies.Entry(entryId, entryVersions, entry.get("link"), entry.get("name")));
++i; ++i;
} }
@ -150,10 +148,10 @@ public class ModPropertiesReader {
}; };
var depends = parseDependencies.apply(ModDependencies.Type.DEPEND, "depends"); var depends = parseDependencies.apply("depends");
var breaks = parseDependencies.apply(ModDependencies.Type.BREAK, "breaks"); var breaks = parseDependencies.apply("breaks");
var suggests = parseDependencies.apply(ModDependencies.Type.SUGGEST, "suggests"); var suggests = parseDependencies.apply("suggests");
var provides = parseDependencies.apply(ModDependencies.Type.PROVIDE, "provides"); var provides = parseDependencies.apply("provides");
UnmodifiableConfig extensionsConfig = config.get("frog.extensions"); UnmodifiableConfig extensionsConfig = config.get("frog.extensions");
Map<ModExtensionsImpl.Key, Object> extensions = new HashMap<>(); Map<ModExtensionsImpl.Key, Object> extensions = new HashMap<>();
@ -171,7 +169,7 @@ public class ModPropertiesReader {
return new ModPropertiesImpl(id, name, icon, semVer, license, Collections.unmodifiableMap(credits), return new ModPropertiesImpl(id, name, icon, semVer, license, Collections.unmodifiableMap(credits),
new ModDependenciesImpl(depends, breaks, suggests, provides), new ModExtensionsImpl(extensions), sources); new ModDependencies(depends, breaks, suggests, provides), new ModExtensionsImpl(extensions), sources);
}); });
private static final Map<String, Parser> versions = Arrays.stream(values()).collect(Collectors.toMap(v -> v.version, v -> v.parser)); private static final Map<String, Parser> versions = Arrays.stream(values()).collect(Collectors.toMap(v -> v.version, v -> v.parser));

View file

@ -16,11 +16,11 @@ import java.util.stream.Collectors;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import dev.frogmc.frogloader.api.FrogLoader; import dev.frogmc.frogloader.api.FrogLoader;
import dev.frogmc.frogloader.api.mod.ModDependencies;
import dev.frogmc.frogloader.api.mod.ModExtensions; import dev.frogmc.frogloader.api.mod.ModExtensions;
import dev.frogmc.frogloader.api.mod.ModProperties; import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.api.plugin.GamePlugin; import dev.frogmc.frogloader.api.plugin.GamePlugin;
import dev.frogmc.frogloader.impl.FrogLoaderImpl; import dev.frogmc.frogloader.impl.FrogLoaderImpl;
import dev.frogmc.frogloader.impl.mod.ModDependenciesImpl;
import dev.frogmc.frogloader.impl.mod.ModExtensionsImpl; import dev.frogmc.frogloader.impl.mod.ModExtensionsImpl;
import dev.frogmc.frogloader.impl.mod.ModPropertiesImpl; import dev.frogmc.frogloader.impl.mod.ModPropertiesImpl;
import dev.frogmc.frogloader.impl.util.SystemProperties; import dev.frogmc.frogloader.impl.util.SystemProperties;
@ -203,7 +203,7 @@ public class MinecraftGamePlugin implements GamePlugin {
return new ModPropertiesImpl("minecraft", "Minecraft", "/assets/minecraft/textures/block/grass_block_side.png", return new ModPropertiesImpl("minecraft", "Minecraft", "/assets/minecraft/textures/block/grass_block_side.png",
MinecraftSemVerImpl.get(version), "MC-EULA", MinecraftSemVerImpl.get(version), "MC-EULA",
Map.of("Mojang AB", Collections.singleton("Author")), Map.of("Mojang AB", Collections.singleton("Author")),
new ModDependenciesImpl(Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet()), new ModDependencies(Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet()),
new ModExtensionsImpl(Collections.emptyMap()), Collections.emptySet()); new ModExtensionsImpl(Collections.emptyMap()), Collections.emptySet());
} }
} }