Skip to content

Commit

Permalink
Add more fields for the response, add dependency support
Browse files Browse the repository at this point in the history
  • Loading branch information
Geometrically committed Apr 12, 2021
1 parent 29a2ab6 commit 1b9fe1f
Show file tree
Hide file tree
Showing 9 changed files with 432 additions and 82 deletions.
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,15 @@ task publishModrinth (type: TaskModrinthUpload){ // Make sure it runs after buil
| versionName | false | The name of the version. |
| changelog | false | The changelog for the file. Allows Markdown formatting. |
| uploadFile | true | The file to upload. Can be an actual file or a file task. |
| releaseType | false | The release status of the file. Defaults to "alpha". |
| versionType | false | The version type of the version. Defaults to "RELEASE". |
| failSilently | false | When true an upload failure will not fail your build. |
| addGameVersion(version) | true | Adds a game version that this file supports. At least one is needed. |
| addLoader(loader) | true | Allows supported mod loaders to be specified for the file. |
| addFile(file) | false | Method to add additional files to be uploaded to a version. |
| detectLoaders | false | Disabling this will prevent the auto detection of mod loaders. |
| addGameVersion(version) | false | Adds a game version that this file supports. At least one is needed. |
| addLoader(loader) | false | Allows supported mod loaders to be specified for the file. |
| addFile(file) | false | Method to add additional files to be uploaded to a version. |
| addDependency(versionId, dependencyType) | false | Adds a dependency to the uploaded version. |

**Note:** In some scenarios the `gameVersion` property can be detected automatically. For example the ForgeGradle and LoomGradle environments. For best results you should set this property manually.
**Note:** In most scenarios the `gameVersion` and `loaders` property can be detected automatically. For example the ForgeGradle and LoomGradle environments.

### Additional Properties

Expand All @@ -76,8 +78,19 @@ task publishModrinth (type: TaskModrinthUpload){ // Make sure it runs after buil
| Property | Type | Description |
|---------------------|-------------|---------------------------------------------------------|
| id | String | The ID for the uploaded version. |

More properties coming soon!
| modId | String | The ID of the mod this version is for. |
| authorId | String | The ID of the author who published this version |
| featured | Boolean | Whether the version is featured or not |
| name | String | The name of this version |
| versionNumber | String | The version number. Ideally will follow semantic versioning |
| changelog | String | The changelog for this version of the mod. |
| datePublished | Date | The date that this version was published. |
| downloads | Integer | The number of downloads this specific version has had.|
| versionType | VersionType | The type of the release - `ALPHA`, `BETA`, or `RELEASE`.|
| files | List | A list of files available for download for this version.|
| gameVersions | List | A list of versions of Minecraft that this version of the mod supports.|
| loaders | List | The loaders that this version works on |
| dependency | Dependency | A list of mods that this version depends on. |

#### Error Info

Expand Down
5 changes: 2 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'java'
id "com.gradle.plugin-publish" version "0.12.0"
id "com.gradle.plugin-publish" version "0.13.0"
id "java-gradle-plugin"
}

Expand All @@ -18,14 +18,13 @@ repositories {
}

dependencies {

compile gradleApi()

implementation group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.13'
implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6'

testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.7.0'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.7.1'
}

test {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
org.gradle.daemon=false

project_version=1.1.0
project_version=1.2.0
group=com.modrinth.minotaur
archivesBaseName=Minotaur
vendor=Modrinth
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
186 changes: 122 additions & 64 deletions src/main/java/com/modrinth/minotaur/TaskModrinthUpload.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

import javax.annotation.Nullable;

import com.modrinth.minotaur.request.Dependency;
import com.modrinth.minotaur.request.VersionType;
import com.modrinth.minotaur.responses.ResponseError;
import com.modrinth.minotaur.responses.ResponseUpload;
import org.apache.http.HttpResponse;
Expand All @@ -23,6 +25,8 @@
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.plugins.AppliedPlugin;
import org.gradle.api.plugins.ExtraPropertiesExtension;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;

Expand Down Expand Up @@ -81,9 +85,9 @@ public class TaskModrinthUpload extends DefaultTask {
public Collection<Object> additionalFiles = new ArrayList<>();

/**
* The release type for the project.
* The version type for the project.
*/
public String releaseType = "release";
public VersionType versionType = VersionType.RELEASE;

/**
* The game versions of the game the version supports.
Expand All @@ -94,11 +98,22 @@ public class TaskModrinthUpload extends DefaultTask {
* The mod loaders of the game the version supports.
*/
public Set<String> loaders = new HashSet<>();

/**
* The dependencies of the version.
*/
public Set<Dependency> dependencies = new HashSet<>();

/**
* Allows build to continue even if the upload failed.
*/
public boolean failSilently = false;

/**
* If enabled the plugin will try to define loaders based on other plugins in the project
* environment.
*/
public boolean detectLoaders = true;

/**
* The response from the API when the file was uploaded successfully.
Expand Down Expand Up @@ -136,6 +151,19 @@ public void addLoader (String loader) {
}
}

/**
* Adds a dependency to the uploaded version. This determines things like
* dependencies and incompatibilities.
*
* @param versionId The version to add a dependency with.
* @param type The type of dependency to add.
*/
private void addDependency(String versionId, Dependency.DependencyType type) {

this.dependencies.add(new Dependency(versionId, type));
this.getLogger().debug("Added {} dependency with version ID {}.", type, versionId);
}

public void addFile(Object file) {
additionalFiles.add(file);
}
Expand All @@ -152,22 +180,20 @@ public boolean wasUploadSuccessful () {

@TaskAction
public void apply () {

try {

// Attempt to automatically resolve the game version if one wasn't specified.
if (this.gameVersions.isEmpty()) {
this.detectGameVersionForge();
this.detectGameVersionFabric();
}

final String detectedVersion = detectGameVersion(this.getProject());

if (detectedVersion == null) {

throw new GradleException("Can not upload to Modrinth. No game version specified.");
}
if (this.gameVersions.isEmpty()) {
throw new GradleException("Can not upload to Modrinth. No game versions specified.");
}

else {
this.addGameVersion(detectedVersion);
}
if(this.loaders.isEmpty()) {
this.addLoaderForPlugin("net.minecraftforge.gradle", "forge");
this.addLoaderForPlugin("fabric-loom", "fabric");
}

if (this.loaders.isEmpty()) {
Expand All @@ -185,8 +211,7 @@ public void apply () {

// Set a default changelog if the dev hasn't provided one.
if (this.changelog == null) {

this.changelog = "The project has been updated to " + this.getProject() + ". No changelog was specified.";
this.changelog = "The project has been updated to " + this.versionName + ". No changelog was specified.";
}

List<File> filesToUpload = new ArrayList<>();
Expand Down Expand Up @@ -217,36 +242,27 @@ public void apply () {
try {

final URI endpoint = new URI(this.getUploadEndpoint());

try {

this.upload(endpoint, filesToUpload);
}

catch (final IOException e) {

this.getProject().getLogger().error("Failed to upload the file!", e);
throw new GradleException("Failed to upload the file!", e);
}
}

catch (final URISyntaxException e) {

this.getProject().getLogger().error("Invalid endpoint URI!", e);
throw new GradleException("Invalid endpoint URI!", e);
}
}

catch (final Exception e) {

if (this.failSilently) {

this.getLogger().info("Failed to upload to Modrinth. Check logs for more info.");
this.getLogger().error("Modrinth upload failed silently.", e);
}

else {

throw e;
}
}
Expand Down Expand Up @@ -278,9 +294,10 @@ public void upload (URI endpoint, List<File> files) throws IOException {
data.setVersionNumber(this.versionNumber);
data.setVersionTitle(this.versionName);
data.setChangelog(this.changelog);
data.setReleaseType(this.releaseType);
data.setVersionType(this.versionType);
data.setGameVersions(this.gameVersions);
data.setLoaders(this.loaders);
data.setDependencies(this.dependencies);
data.setFileParts(fileParts);

form.addTextBody("data", GSON.toJson(data), ContentType.APPLICATION_JSON);
Expand Down Expand Up @@ -364,52 +381,93 @@ else if (in instanceof AbstractArchiveTask) {
// Fallback to Gradle's built in file resolution mechanics.
return project.file(in);
}

/**
* Attempts to automatically detect a game version based on the script environment. This is
* intended as a fallback and should never override user specified data.
*
* @param project The Gradle project to look through.
* @return A detected game version string. This will be null if nothing was found.
* Attempts to detect the game version by detecting ForgeGradle data in the build
* environment.
*/
@Nullable
private static String detectGameVersion (Project project) {

String version = null;

// ForgeGradle will store the game version here.
// https://github.com/MinecraftForge/ForgeGradle/blob/9252ffe1fa5c2acf133f35d169ba4ffc84e6a9fd/src/userdev/java/net/minecraftforge/gradle/userdev/MinecraftUserRepo.java#L179
if (project.getExtensions().getExtraProperties().has("MC_VERSION")) {

version = project.getExtensions().getExtraProperties().get("MC_VERSION").toString();
private void detectGameVersionForge () {

try {

final ExtraPropertiesExtension extraProps = this.getProject().getExtensions().getExtraProperties();

// ForgeGradle will store the game version here.
// https://github.com/MinecraftForge/ForgeGradle/blob/9252ffe1fa5c2acf133f35d169ba4ffc84e6a9fd/src/userdev/java/net/minecraftforge/gradle/userdev/MinecraftUserRepo.java#L179
if (extraProps.has("MC_VERSION")) {

final String forgeGameVersion = extraProps.get("MC_VERSION").toString();

if (forgeGameVersion != null && !forgeGameVersion.isEmpty()) {

this.getLogger().debug("Detected fallback game version {} from ForgeGradle.", forgeGameVersion);
this.addGameVersion(forgeGameVersion);
}
}
}

else {

// Loom/Fabric Gradle detection.

catch (final Exception e) {

this.getLogger().debug("Failed to detect ForgeGradle game version.", e);
}
}

/**
* Attempts to detect the game version by detecting LoomGradle data in the build
* environment.
*/
private void detectGameVersionFabric() {
// Loom/Fabric Gradle detection.
try {
// Using reflection because loom isn't always available.
final Class<?> loomType = Class.forName("net.fabricmc.loom.LoomGradleExtension");
final Method getProvider = loomType.getMethod("getMinecraftProvider");

final Class<?> minecraftProvider = Class.forName("net.fabricmc.loom.providers.MinecraftProvider");
final Method getVersion = minecraftProvider.getMethod("getMinecraftVersion");

final Object loomExt = this.getProject().getExtensions().getByType(loomType);
final Object loomProvider = getProvider.invoke(loomExt);
final Object loomVersion = getVersion.invoke(loomProvider);

final String loomGameVersion = loomVersion.toString();

if (loomGameVersion != null && !loomGameVersion.isEmpty()) {

this.getLogger().debug("Detected fallback game version {} from Loom.", loomGameVersion);
this.addGameVersion(loomGameVersion);
}
}
catch (final Exception e) {
this.getLogger().debug("Failed to detect Loom game version.", e);
}
}

/**
* Applies a mod loader automatically if a plugin with the specified name has been applied.
*
* @param pluginName The plugin to search for.
* @param loaderName The mod loader to apply.
*/
private void addLoaderForPlugin(String pluginName, String loaderName) {
if (this.detectLoaders) {
try {

// Using reflection because loom isn't always available.
final Class<?> loomType = Class.forName("net.fabricmc.loom.LoomGradleExtension");
final Method getProvider = loomType.getMethod("getMinecraftProvider");

final Class<?> minecraftProvider = Class.forName("net.fabricmc.loom.providers.MinecraftProvider");
final Method getVersion = minecraftProvider.getMethod("getMinecraftVersion");

final Object loomExt = project.getExtensions().getByType(loomType);
final Object loomProvider = getProvider.invoke(loomExt);
final Object loomVersion = getVersion.invoke(loomProvider);

version = loomVersion.toString();
final AppliedPlugin plugin = this.getProject().getPluginManager().findPlugin(pluginName);

if (plugin != null) {

this.addLoader(loaderName);
this.getLogger().debug("Applying loader {} because plugin {} was found.", loaderName, pluginName);
}

else {

this.getLogger().debug("Could not automatically apply loader {} because plugin {} has not been applied.", loaderName, pluginName);
}
}

catch (final Exception e) {

project.getLogger().debug("Failed to detect loom game version.", e);
this.getLogger().debug("Failed to detect plugin {}.", pluginName, e);
}
}

project.getLogger().debug("Using fallback game version {}.", version);
return version;
}
}
Loading

0 comments on commit 1b9fe1f

Please sign in to comment.