Skip to content

Commit

Permalink
Add ModEntrypoint as an API for AdapterLoadableClassEntry (#380)
Browse files Browse the repository at this point in the history
Since the only public changes are generics, existing mods which use `getEntrypoints()` (which they shouldn't as it's all either `PLUGIN_API` or `LEGACY_EXPOSED`) will continue to work in binary (compiled) form, but not source form.

`ModEntrypoint` intentionally doesn't expose the `adapter` or `value` at the moment since only loader itself should need it, at least in theory.

This also removes the `plugins` field from the QMJ reader, since it used to use `AdapterLoadableClassEntry` but isn't actually hooked up anywhere (as actual plugins don't get defined in this way)

This also has two extra API changes:

- Adds `ModLicense.fromIdentifier` & `fromIdentifierOrDefault`, which exposes the same methods in `ModLicenseImpl`
- Adds `QuiltPluginManager.loadZipNow`, which is an immediate version of `loadZip`
  • Loading branch information
AlexIIL authored Nov 23, 2023
1 parent f77c428 commit 80f6abe
Show file tree
Hide file tree
Showing 15 changed files with 109 additions and 55 deletions.
18 changes: 18 additions & 0 deletions src/main/java/org/quiltmc/loader/api/ModLicense.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
package org.quiltmc.loader.api;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import org.quiltmc.loader.impl.metadata.qmj.ModLicenseImpl;

/**
* Representation of a license a mod may use.
*
* @see <a href="https://spdx.org/licenses/">SPDX identifier</a>
*/
@ApiStatus.NonExtendable
public interface ModLicense {
Expand All @@ -44,4 +48,18 @@ public interface ModLicense {
* @return a short description of the license, empty if there is no description
*/
String description();

/** Looks up a {@link ModLicense} from the given SPDX license ID, returning null if quilt-loader is unaware of
* it. */
@Nullable
public static ModLicense fromIdentifier(String identifier) {
return ModLicenseImpl.fromIdentifier(identifier);
}

/** Looks up a {@link ModLicense} from the given SPDX license ID, returning a new {@link ModLicense} (with
* {@link #name()} and {@link #id()} set to the passed identifier, the other fields blank) if quilt-loader is
* unaware of it. */
public static ModLicense fromIdentifierOrDefault(String identifier) {
return ModLicenseImpl.fromIdentifierOrDefault(identifier);
}
}
18 changes: 17 additions & 1 deletion src/main/java/org/quiltmc/loader/api/plugin/ModMetadataExt.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import java.util.Collections;
import java.util.Map;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import org.quiltmc.loader.api.LanguageAdapter;
import org.quiltmc.loader.api.ModMetadata;
import org.quiltmc.loader.api.ModMetadataToBeMovedToPlugins;
import org.quiltmc.loader.api.Version;
Expand Down Expand Up @@ -70,7 +72,21 @@ public interface ModPlugin {

// Runtime

Map<String, Collection<AdapterLoadableClassEntry>> getEntrypoints();
Map<String, Collection<ModEntrypoint>> getEntrypoints();

Map<String, String> languageAdapters();

/** Entrypoint holder. Since plugins aren't expected to read from this only creation is supported. */
@ApiStatus.NonExtendable
public interface ModEntrypoint {

/** @return A new {@link ModEntrypoint} using the default adapter and the given value. */
public static ModEntrypoint create(String value) {
return new AdapterLoadableClassEntry(value);
}

public static ModEntrypoint create(String adapter, String value) {
return new AdapterLoadableClassEntry(adapter, value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
* will be opened, and checked for a "quilt.mod.json" file. If one is found, then it is loaded as a quilt mod (and
* possibly as a new plugin - which will be loaded instantly, rather than waiting until the next cycle).</li>
* <li>If "quilt.mod.json" couldn't be found then the zip root will be passed to
* {@link #scanZip(Path, boolean, PluginGuiTreeNode)}</li>
* <li>Otherwise it will be passed to {@link #scanUnknownFile(Path, boolean, PluginGuiTreeNode)}</li>
* {@link #scanZip(Path, ModLocation, PluginGuiTreeNode)}</li>
* <li>Otherwise it will be passed to {@link #scanUnknownFile(Path, ModLocation, PluginGuiTreeNode)}</li>
* </ol>
* </li>
* <li>{@link #beforeSolve()} is called.</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public interface QuiltPluginContext {
/** Submits a task to be completed after plugin resolution, but before the current cycle ends. The task may be
* executed on a different thread, depending on loaders config options.
* <p>
* This should only be called by {@link QuiltLoaderPlugin#resolve(QuiltPluginContext, Object)},
* This should only be called by {@link QuiltLoaderPlugin#resolve(TentativeLoadOption)},
* {@link QuiltLoaderPlugin#finish(org.quiltmc.loader.api.plugin.solver.ModSolveResult)}, or by any tasks that are
* passed to this function during their execution.
*
Expand Down Expand Up @@ -139,12 +139,12 @@ default <V> QuiltPluginTask<V> addGuiRequest() {
void addModLoadOption(ModLoadOption mod, PluginGuiTreeNode fileNode);

/** Adds a tentative option which can be resolved later by
* {@link QuiltLoaderPlugin#resolve(QuiltPluginContext, TentativeLoadOption)}, if it is selected.
* {@link QuiltLoaderPlugin#resolve(TentativeLoadOption)}, if it is selected.
*
* @param option */
<T extends LoadOption & TentativeLoadOption> void addTentativeOption(T option);

/** Only callable during {@link QuiltLoaderPlugin#handleError(java.util.List)} to identify the given rule as one
/** Only callable during {@link QuiltLoaderPlugin#handleError(java.util.Collection)} to identify the given rule as one
* which can be removed for the purposes of error message generation. */
void blameRule(Rule rule);
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,25 @@ public interface QuiltPluginManager {
* <li>{@link NonZipException} if {@link FileSystems#newFileSystem(Path, ClassLoader)} throws a
* {@link ProviderNotFoundException}.</li>
* </ul>
*/
*
* @see #loadZipNow(Path) */
QuiltPluginTask<Path> loadZip(Path zip);

/** Loads the specified zip file and returns a path to the root of it's contents.
* <p>
* How the given zip is loaded depends on loaders config settings - in particular the zip could be extracted to a
* temporary folder on the same filesystem as the original zip.
* <p>
* WARNING: if this method allocates a new {@link FileSystem} then that will be closed, <em>unless</em> at least one
* of the {@link QuiltLoaderPlugin}s {@link QuiltPluginContext#lockZip(Path) locks} it, or if a chosen mod is loaded
* from it.
*
* @throws IOException if something went wrong while loading the file.
* @throws NonZipException if {@link FileSystems#newFileSystem(Path, ClassLoader)} throws a
* {@link ProviderNotFoundException}.
* @see #loadZip(Path) */
Path loadZipNow(Path zip) throws IOException, NonZipException;

/** Creates a new in-memory read-write file system. This can be used for mods that aren't loaded from zips.
*
* @return The root {@link Path} of the newly allocated {@link FileSystem} */
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/quiltmc/loader/impl/QuiltLoaderImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import org.quiltmc.loader.api.gui.QuiltLoaderText;
import org.quiltmc.loader.api.plugin.ModContainerExt;
import org.quiltmc.loader.api.plugin.ModMetadataExt;
import org.quiltmc.loader.api.plugin.ModMetadataExt.ModEntrypoint;
import org.quiltmc.loader.api.plugin.gui.PluginGuiTreeNode.WarningLevel;
import org.quiltmc.loader.api.plugin.solver.LoadOption;
import org.quiltmc.loader.api.plugin.solver.ModLoadOption;
Expand Down Expand Up @@ -1130,8 +1131,8 @@ private void setupMods() {
}
}

for (Map.Entry<String, Collection<AdapterLoadableClassEntry>> entry : mod.metadata().getEntrypoints().entrySet()) {
for (AdapterLoadableClassEntry e : entry.getValue()) {
for (Map.Entry<String, Collection<ModEntrypoint>> entry : mod.metadata().getEntrypoints().entrySet()) {
for (ModEntrypoint e : entry.getValue()) {
entrypointStorage.add(mod, entry.getKey(), e, adapterMap);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.quiltmc.loader.api.entrypoint.EntrypointContainer;
import org.quiltmc.loader.api.entrypoint.EntrypointException;
import org.quiltmc.loader.api.plugin.ModContainerExt;
import org.quiltmc.loader.api.plugin.ModMetadataExt.ModEntrypoint;
import org.quiltmc.loader.impl.launch.common.QuiltLauncherBase;
import org.quiltmc.loader.impl.metadata.qmj.AdapterLoadableClassEntry;
import org.quiltmc.loader.impl.util.QuiltLoaderInternal;
Expand Down Expand Up @@ -146,14 +147,15 @@ public void addDeprecated(ModContainerExt modContainer, String adapter, String v
getOrCreateEntries("server").add(oe);
}

public void add(ModContainerExt modContainer, String key, AdapterLoadableClassEntry metadata, Map<String, LanguageAdapter> adapterMap) throws Exception {
if (!adapterMap.containsKey(metadata.getAdapter())) {
throw new Exception("Could not find adapter '" + metadata.getAdapter() + "' (mod " + modContainer.metadata().id() + "!)");
public void add(ModContainerExt modContainer, String key, ModEntrypoint metadata, Map<String, LanguageAdapter> adapterMap) throws Exception {
AdapterLoadableClassEntry data = (AdapterLoadableClassEntry) metadata;
if (!adapterMap.containsKey(data.getAdapter())) {
throw new Exception("Could not find adapter '" + data.getAdapter() + "' (mod " + modContainer.metadata().id() + "!)");
}

Log.debug(LogCategory.ENTRYPOINT, "Registering new-style initializer %s for mod %s (key %s)", metadata.getValue(), modContainer.metadata().id(), key);
Log.debug(LogCategory.ENTRYPOINT, "Registering new-style initializer %s for mod %s (key %s)", data.getValue(), modContainer.metadata().id(), key);
getOrCreateEntries(key).add(new NewEntry(
modContainer, adapterMap.get(metadata.getAdapter()), metadata.getValue()
modContainer, adapterMap.get(data.getAdapter()), data.getValue()
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
import org.quiltmc.loader.api.LoaderValue;
import org.quiltmc.loader.api.ModContributor;
import org.quiltmc.loader.api.ModLicense;
import org.quiltmc.loader.api.ModMetadata;
import org.quiltmc.loader.api.ModMetadata.ProvidedMod;
import org.quiltmc.loader.api.plugin.ModContainerExt;
import org.quiltmc.loader.api.plugin.ModMetadataExt;
import org.quiltmc.loader.api.plugin.ModMetadataExt.ModEntrypoint;
import org.quiltmc.loader.impl.fabric.metadata.CustomValueImpl;
import org.quiltmc.loader.impl.fabric.metadata.MapBackedContactInformation;
import org.quiltmc.loader.impl.fabric.metadata.SimplePerson;
Expand Down Expand Up @@ -340,20 +342,21 @@ public Collection<String> getOldInitializers() {
@Override
public List<EntrypointMetadata> getEntrypoints(String type) {
List<EntrypointMetadata> list = new ArrayList<>();
Collection<AdapterLoadableClassEntry> quiltList = meta.getEntrypoints().get(type);
Collection<ModEntrypoint> quiltList = meta.getEntrypoints().get(type);
if (quiltList == null) {
return list;
}
for (AdapterLoadableClassEntry entrypoint : quiltList) {
for (ModEntrypoint entrypoint : quiltList) {
AdapterLoadableClassEntry data = (AdapterLoadableClassEntry) entrypoint;
list.add(new EntrypointMetadata() {
@Override
public String getValue() {
return entrypoint.getValue();
return data.getValue();
}

@Override
public String getAdapter() {
return entrypoint.getAdapter();
return data.getAdapter();
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,23 @@

package org.quiltmc.loader.impl.metadata.qmj;

import org.quiltmc.loader.api.plugin.ModMetadataExt.ModEntrypoint;
import org.quiltmc.loader.impl.util.QuiltLoaderInternal;
import org.quiltmc.loader.impl.util.QuiltLoaderInternalType;

/**
* Represents a class entry inside of that specifies a language adapter to use to load the class.
*/
@QuiltLoaderInternal(QuiltLoaderInternalType.LEGACY_EXPOSED)
public final class AdapterLoadableClassEntry {
public final class AdapterLoadableClassEntry implements ModEntrypoint {
private final String adapter;
private final String value;

public AdapterLoadableClassEntry(String value) {
this.adapter = "default";
this.value = value;
}

public AdapterLoadableClassEntry(String adapter, String value) {
this.adapter = adapter;
this.value = value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public class FabricModMetadataWrapper implements InternalModMetadata {
private final Collection<ModContributor> contributors;
private final List<String> jars;
private final Map<String, LoaderValue> customValues;
private final Map<String, Collection<AdapterLoadableClassEntry>> entrypoints;
private final Map<String, Collection<ModEntrypoint>> entrypoints;
private final List<ProvidedMod> provides;

public FabricModMetadataWrapper(FabricLoaderModMetadata fabricMeta) {
Expand All @@ -79,11 +79,11 @@ public FabricModMetadataWrapper(FabricLoaderModMetadata fabricMeta) {
fabricMeta.getCustomValues().forEach((key, value) -> customValues.put(key, convertCustomValue(value)));
this.customValues = Collections.unmodifiableMap(customValues);

Map<String, Collection<AdapterLoadableClassEntry>> e = new HashMap<>();
Map<String, Collection<ModEntrypoint>> e = new HashMap<>();
for (String key : fabricMeta.getEntrypointKeys()) {
Collection<AdapterLoadableClassEntry> c = new ArrayList<>();
Collection<ModEntrypoint> c = new ArrayList<>();
for (EntrypointMetadata entrypoint : fabricMeta.getEntrypoints(key)) {
c.add(new AdapterLoadableClassEntry(entrypoint.getAdapter(), entrypoint.getValue()));
c.add(ModEntrypoint.create(entrypoint.getAdapter(), entrypoint.getValue()));
}
e.put(key, Collections.unmodifiableCollection(c));
}
Expand Down Expand Up @@ -283,7 +283,7 @@ public Collection<ProvidedMod> provides() {
}

@Override
public Map<String, Collection<AdapterLoadableClassEntry>> getEntrypoints() {
public Map<String, Collection<ModEntrypoint>> getEntrypoints() {
return entrypoints;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public Collection<? extends ProvidedMod> provides() {
}

@Override
public Map<String, Collection<AdapterLoadableClassEntry>> getEntrypoints() {
public Map<String, Collection<ModEntrypoint>> getEntrypoints() {
return metadata.getEntrypoints();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.quiltmc.loader.api.ModLicense;
import org.quiltmc.loader.api.ModMetadata.ProvidedMod;
import org.quiltmc.loader.api.Version;
import org.quiltmc.loader.api.plugin.ModMetadataExt.ModEntrypoint;
import org.quiltmc.loader.api.plugin.ModMetadataExt.ModLoadType;
import org.quiltmc.loader.impl.metadata.qmj.JsonLoaderValue.ObjectImpl;
import org.quiltmc.loader.impl.util.QuiltLoaderInternal;
Expand Down Expand Up @@ -55,8 +56,7 @@ public class V1ModMetadataBuilder {
/* Internal fields */
public ModLoadType loadType = ModLoadType.IF_REQUIRED;
public final List<ProvidedMod> provides = new ArrayList<>();
public final Map<String, List<AdapterLoadableClassEntry>> entrypoints = new LinkedHashMap<>();
public final List<AdapterLoadableClassEntry> plugins = new ArrayList<>();
public final Map<String, List<ModEntrypoint>> entrypoints = new LinkedHashMap<>();
public final List<String> jars = new ArrayList<>();
public final Map<String, String> languageAdapters = new LinkedHashMap<>();
public final List<String> repositories = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ final class V1ModMetadataImpl implements InternalModMetadata {
/* Internal fields */
private final ModLoadType loadType;
private final Collection<ProvidedMod> provides;
private final Map<String, Collection<AdapterLoadableClassEntry>> entrypoints;
// private final Collection<AdapterLoadableClassEntry> plugins;
private final Map<String, Collection<ModEntrypoint>> entrypoints;
private final Collection<String> jars;
private final Map<String, String> languageAdapters;
private final Collection<String> repositories;
Expand Down Expand Up @@ -127,7 +126,6 @@ final class V1ModMetadataImpl implements InternalModMetadata {
this.loadType = builder.loadType;
this.provides = Collections.unmodifiableCollection(builder.provides);
this.entrypoints = Collections.unmodifiableMap(builder.entrypoints);
// this.plugins = Collections.unmodifiableCollection(builder.plugins);
this.jars = Collections.unmodifiableCollection(builder.jars);
this.languageAdapters = Collections.unmodifiableMap(builder.languageAdapters);
this.repositories = Collections.unmodifiableCollection(builder.repositories);
Expand Down Expand Up @@ -288,7 +286,7 @@ public Collection<ProvidedMod> provides() {

@Nullable
@Override
public Map<String, Collection<AdapterLoadableClassEntry>> getEntrypoints() {
public Map<String, Collection<ModEntrypoint>> getEntrypoints() {
return this.entrypoints;
}

Expand Down
Loading

0 comments on commit 80f6abe

Please sign in to comment.