Class ModrinthService
- Namespace
- McServerLauncher.Services
- Assembly
- McServerLauncher.dll
The app's whole conversation with Modrinth: searching the store, reading a project, resolving a version for this server, identifying installed jars by hash, and downloading a file.
public class ModrinthService
- Inheritance
-
ModrinthService
- Inherited Members
Remarks
Every query is already narrowed by the server's loader and game version, because a result the server cannot run is worse than no result: it installs, and then the server does not come up. The loader a type browses under comes from ServerTypeCatalog, so Purpur searching Paper's plugins is a property of the table rather than a branch in here.
Reads go through StoreCache with a per-endpoint freshness window (see the constants below), which is what makes opening a mod, going back and opening it again cost one request — and what makes a project already seen open with no connection at all.
The hash endpoints answer two different questions off the same scan, and the difference matters: GetVersionsByHashAsync(IEnumerable<string>, CancellationToken) says what each jar is (its project and its declared dependencies), while GetLatestVersionsByHashAsync(IEnumerable<string>, ServerType, string, CancellationToken) says what could replace it. The update check needs the second; the missing-library check needs the first.
Methods
DownloadModAsync(string, string, string?, string?, IProgress<double>?, CancellationToken)
Downloads a mod/plugin file from Modrinth. Mods are third-party jars chosen by the user, so the download is verified against the hash Modrinth publishes for it; a mismatch deletes the file and throws instead of installing it. Sha512 is preferred (stronger); Sha1 is used only if Modrinth didn't provide a Sha512 for this file.
public virtual Task DownloadModAsync(string downloadUrl, string destinationPath, string? expectedSha512 = null, string? expectedSha1 = null, IProgress<double>? progress = null, CancellationToken ct = default)
Parameters
downloadUrlstringdestinationPathstringexpectedSha512stringexpectedSha1stringprogressIProgress<double>ctCancellationToken
Returns
Remarks
Neither hash means no install. Modrinth always publishes one, so its absence is an answer the app does not understand rather than a normal case — and the rule written down for mods (see VerifiedJarDownload) was "no checksum, no install", while this went ahead and installed the jar unverified.
GetLatestProjectVersionAsync(string, ServerType, string, CancellationToken)
public virtual Task<VersionResult?> GetLatestProjectVersionAsync(string projectId, ServerType loader, string mcVersion, CancellationToken ct = default)
Parameters
projectIdstringloaderServerTypemcVersionstringctCancellationToken
Returns
GetLatestVersionsByHashAsync(IEnumerable<string>, ServerType, string, CancellationToken)
Given the SHA-1 of each installed jar, asks Modrinth (in a single request) for the latest version of each corresponding project that is compatible with this server's loader and Minecraft version. Returns a map keyed by the SAME input hash the caller passed. Hashes that Modrinth doesn't recognise (jars from CurseForge or built by hand) are simply absent from the result.
public virtual Task<Dictionary<string, VersionResult>?> GetLatestVersionsByHashAsync(IEnumerable<string> sha1Hashes, ServerType loader, string mcVersion, CancellationToken ct = default)
Parameters
sha1HashesIEnumerable<string>loaderServerTypemcVersionstringctCancellationToken
Returns
- Task<Dictionary<string, VersionResult>>
The map, or null when Modrinth could not be asked. Deliberately not an empty map: that is what "every mod is on its newest version" looks like, and a failure that reads as good news is one nobody ever reports. The upper-case hashes fixed in 1.12.3 hid for exactly that reason, and "no connection" was taking the same way out.
GetProjectAsync(string, CancellationToken)
Full project: long description, gallery, links and licence.
public Task<ProjectDetail?> GetProjectAsync(string idOrSlug, CancellationToken ct = default)
Parameters
idOrSlugstringctCancellationToken
Returns
GetProjectVersionsAsync(string, ServerType, string?, CancellationToken)
Every published version of a project, newest first. When mcVersion is
given the list is narrowed to what runs on this server's loader and Minecraft version — the
same filter the installer uses, so what the details page offers is what actually installs.
public Task<List<VersionResult>?> GetProjectVersionsAsync(string projectId, ServerType loader, string? mcVersion = null, CancellationToken ct = default)
Parameters
projectIdstringloaderServerTypemcVersionstringctCancellationToken
Returns
GetProjectsAsync(IEnumerable<string>, CancellationToken)
Several projects in a single request. Used for dependencies and related mods, so opening a mod with five dependencies costs one request rather than five.
public Task<List<ProjectDetail>?> GetProjectsAsync(IEnumerable<string> ids, CancellationToken ct = default)
Parameters
idsIEnumerable<string>ctCancellationToken
Returns
GetTeamMembersAsync(string, CancellationToken)
The project's team, which is where the author names live.
public Task<List<TeamMember>?> GetTeamMembersAsync(string teamId, CancellationToken ct = default)
Parameters
teamIdstringctCancellationToken
Returns
GetVersionAsync(string, CancellationToken)
One exact version, by its Modrinth id. Used for dependencies that pin a version rather than naming a project, where "the newest compatible one" would be the wrong answer.
public Task<VersionResult?> GetVersionAsync(string versionId, CancellationToken ct = default)
Parameters
versionIdstringctCancellationToken
Returns
GetVersionsByHashAsync(IEnumerable<string>, CancellationToken)
Which Modrinth version each installed jar actually is, keyed by the SHA-1 that was passed in.
public virtual Task<Dictionary<string, VersionResult>> GetVersionsByHashAsync(IEnumerable<string> sha1Hashes, CancellationToken ct = default)
Parameters
sha1HashesIEnumerable<string>ctCancellationToken
Returns
Remarks
Unlike GetLatestVersionsByHashAsync(IEnumerable<string>, ServerType, string, CancellationToken) this asks what a jar is, not what could replace it — so the answer carries the project id and the dependency list of the file on disk. That is what makes it possible to tell a server that is missing a library mod from one that is complete. Jars Modrinth does not know are simply absent from the result.
SearchModsAsync(string, ServerType, string, string, int, int, IReadOnlyCollection<string>?, StoreSideFilter, CancellationToken)
Searches Modrinth for content compatible with a server. extraFacetGroups
adds already-formatted facet groups (e.g. ["categories:optimization"]) that are ANDed
with the loader/version/type filter — this is what the category chips use.
side picks the projects by where they run; plugins are always server-side.
public virtual Task<SearchResponse?> SearchModsAsync(string query, ServerType loader, string mcVersion, string index = "relevance", int offset = 0, int limit = 20, IReadOnlyCollection<string>? extraFacetGroups = null, StoreSideFilter side = StoreSideFilter.All, CancellationToken ct = default)
Parameters
querystringloaderServerTypemcVersionstringindexstringoffsetintlimitintextraFacetGroupsIReadOnlyCollection<string>sideStoreSideFilterctCancellationToken