1
0
mirror of https://github.com/SKCraft/Launcher.git synced 2025-02-26 03:21:51 +01:00

Move curse plugin to separate project

This commit is contained in:
Henry Le Grys 2021-03-28 04:54:46 +01:00
parent a48dbf8ed9
commit e0a242cedc
14 changed files with 210 additions and 32 deletions

View File

@ -0,0 +1,11 @@
plugins {
id 'application'
id "com.github.johnrengelman.shadow"
id 'io.freefair.lombok'
}
dependencies {
implementation project(':launcher-builder')
}
build.dependsOn(jar)

View File

@ -0,0 +1,37 @@
package com.skcraft.plugin.curse;
import com.beust.jcommander.JCommander;
import com.skcraft.launcher.builder.BuilderOptions;
import com.skcraft.launcher.builder.plugin.Builder;
import com.skcraft.launcher.builder.plugin.BuilderPlugin;
import java.io.File;
import java.io.IOException;
public class CurseBuildPlugin extends BuilderPlugin {
private CurseOptions options = new CurseOptions();
@Override
public void acceptOptions(BuilderOptions builderOptions, String[] args) {
new JCommander(this.options, args);
if (options.getCachePath() == null) {
builderOptions.requireInputPath("--cache");
options.setCachePath(new File(builderOptions.getInputPath(), "cache"));
}
if (options.getCurseModsPath() == null) {
builderOptions.requireInputPath("--curse-mods");
options.setCachePath(new File(builderOptions.getInputPath(), "cursemods"));
}
}
@Override
public void onBuild(Builder builder) throws IOException {
CurseCachingResolver resolver = new CurseCachingResolver(options.getCachePath(), builder.getMapper());
CurseModCollector collector = new CurseModCollector(builder.getManifest(), builder.getApplicator(), resolver,
builder.getMapper());
collector.walk(options.getCurseModsPath());
}
}

View File

@ -0,0 +1,60 @@
package com.skcraft.plugin.curse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.skcraft.launcher.util.HttpRequest;
import lombok.RequiredArgsConstructor;
import java.io.File;
import java.io.IOException;
import static com.skcraft.launcher.util.HttpRequest.url;
@RequiredArgsConstructor
public class CurseCachingResolver {
private final File cacheDir;
private final ObjectMapper mapper;
public CurseFileMetadata resolveMetadata(CurseMod mod) throws IOException, InterruptedException {
CurseFileMetadata cached = getCachedMetadata(mod.getFileId());
if (cached != null) return cached;
String apiUrl = String.format("https://addons-ecs.forgesvc.net/api/v2/addon/%s/file/%s",
mod.getProjectId(), mod.getFileId());
return HttpRequest.get(url(apiUrl))
.execute()
.expectResponseCode(200)
.returnContent()
.saveContent(getMetadataFile(mod.getFileId()))
.asJson(CurseFileMetadata.class);
}
public File resolveModFile(CurseFileMetadata metadata) throws IOException, InterruptedException {
File cachedMod = getModFile(metadata.getId());
if (!cachedMod.exists()) {
HttpRequest.get(url(metadata.getDownloadUrl()))
.execute()
.expectResponseCode(200)
.saveContent(cachedMod);
}
return cachedMod;
}
public CurseFileMetadata getCachedMetadata(String fileId) throws IOException {
File target = getMetadataFile(fileId);
if (!target.exists()) return null;
return mapper.readValue(target, CurseFileMetadata.class);
}
private File getMetadataFile(String fileId) {
return new File(cacheDir, String.format("meta_%s.json", fileId));
}
private File getModFile(String fileId) {
return new File(cacheDir, String.format("%s.jar", fileId));
}
}

View File

@ -0,0 +1,15 @@
package com.skcraft.plugin.curse;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class CurseFileMetadata {
private String id;
private String displayName;
private String fileName;
private String fileDate;
private long fileLength;
private String downloadUrl;
}

View File

@ -0,0 +1,11 @@
package com.skcraft.plugin.curse;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class CurseMod {
private String projectId;
private String fileId;
}

View File

@ -0,0 +1,58 @@
package com.skcraft.plugin.curse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.skcraft.launcher.builder.DirectoryWalker;
import com.skcraft.launcher.builder.PropertiesApplicator;
import com.skcraft.launcher.model.modpack.FileInstall;
import com.skcraft.launcher.model.modpack.Manifest;
import lombok.RequiredArgsConstructor;
import lombok.extern.java.Log;
import java.io.File;
import java.io.IOException;
@Log
@RequiredArgsConstructor
public class CurseModCollector extends DirectoryWalker {
private final Manifest manifest;
private final PropertiesApplicator applicator;
private final CurseCachingResolver cache;
private final ObjectMapper mapper;
@Override
protected void onFile(File file, String relPath) throws IOException {
try {
CurseMod curseMod = mapper.readValue(file, CurseMod.class);
CurseFileMetadata metadata = cache.resolveMetadata(curseMod);
FileInstall entry = new FileInstall();
String to = String.format("mods/%s", metadata.getFileName());
entry.setVersion(metadata.getFileDate());
entry.setLocation(metadata.getDownloadUrl());
entry.setTo(to);
entry.setSize(metadata.getFileLength());
log.info(String.format("Adding Curse mod %s", metadata.getDisplayName()));
applicator.apply(entry);
manifest.getTasks().add(entry);
} catch (InterruptedException e) {
throw new IOException(e);
}
}
@Override
protected DirectoryBehavior getBehavior(String name) {
if (name.startsWith(".")) {
return DirectoryBehavior.SKIP;
} else if (name.equals("_OPTIONAL")) {
return DirectoryBehavior.IGNORE;
} else if (name.equals("_SERVER")) {
return DirectoryBehavior.SKIP;
} else if (name.equals("_CLIENT")) {
return DirectoryBehavior.IGNORE;
} else {
return DirectoryBehavior.CONTINUE;
}
}
}

View File

@ -1,4 +1,4 @@
package com.skcraft.launcher.builder.curse;
package com.skcraft.plugin.curse;
import com.beust.jcommander.Parameter;
import lombok.Data;
@ -7,6 +7,9 @@ import java.io.File;
@Data
public class CurseOptions {
@Parameter(names = "--curse-mods", description = "Folder of curse mod JSONs")
private File curseModsPath;
@Parameter(names = "--cache", description = "Path to cache folder where downloaded artifacts are stored.")
private File cachePath;

View File

@ -104,13 +104,13 @@ public class BuilderOptions {
}
}
private void requireOutputPath(String name) throws ParameterException {
public void requireOutputPath(String name) throws ParameterException {
if (outputPath == null) {
throw new ParameterException("Because " + name + " was not specified, --output needs to be specified as the output directory and then " + name + " will be default to a pre-set path within the output directory");
}
}
private void requireInputPath(String name) throws ParameterException {
public void requireInputPath(String name) throws ParameterException {
if (inputPath == null) {
throw new ParameterException("Because " + name + " was not specified, --input needs to be specified as the project directory and then " + name + " will be default to a pre-set path within the project directory");
}

View File

@ -55,10 +55,12 @@ import static com.skcraft.launcher.util.HttpRequest.url;
@Log
public class PackageBuilder implements Builder {
private final Properties properties;
@Getter
private final ObjectMapper mapper;
private ObjectWriter writer;
@Getter
private final Manifest manifest;
@Getter
private final PropertiesApplicator applicator;
@Getter
private boolean prettyPrint = false;

View File

@ -1,26 +0,0 @@
package com.skcraft.launcher.builder.curse;
import com.beust.jcommander.JCommander;
import com.skcraft.launcher.builder.BuilderOptions;
import com.skcraft.launcher.builder.plugin.Builder;
import com.skcraft.launcher.builder.plugin.BuilderPlugin;
import java.io.File;
public class CurseBuildPlugin extends BuilderPlugin {
private CurseOptions options = new CurseOptions();
@Override
public void acceptOptions(BuilderOptions builderOptions, String[] args) {
new JCommander(this.options, args);
if (options.getCachePath() == null) {
options.setCachePath(new File(builderOptions.getInputPath(), "cache"));
}
}
@Override
public void onBuild(Builder builder) {
}
}

View File

@ -1,10 +1,14 @@
package com.skcraft.launcher.builder.plugin;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.skcraft.launcher.builder.PropertiesApplicator;
import com.skcraft.launcher.model.modpack.Manifest;
/**
* Builder passed to plugins to allow restricted access
*/
public interface Builder {
ObjectMapper getMapper();
Manifest getManifest();
PropertiesApplicator getApplicator();
}

View File

@ -3,11 +3,13 @@ package com.skcraft.launcher.builder.plugin;
import com.skcraft.launcher.builder.BuilderOptions;
import com.skcraft.launcher.model.modpack.Manifest;
import java.io.IOException;
/**
* Class that all builder plugins should extend.
*/
public abstract class BuilderPlugin {
public void acceptOptions(BuilderOptions options, String[] args) {}
public void onManifestCreated(Manifest manifest) {}
public void onBuild(Builder builder) {}
public void onBuild(Builder builder) throws IOException, InterruptedException {}
}

View File

@ -5,6 +5,7 @@ import com.skcraft.launcher.builder.BuilderOptions;
import com.skcraft.launcher.model.modpack.Manifest;
import lombok.extern.java.Log;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
@ -61,7 +62,7 @@ public class BuilderPluginLoader {
}
}
public void dispatchBuild(Builder builder) {
public void dispatchBuild(Builder builder) throws IOException, InterruptedException {
for (BuilderPlugin plugin : loadedPlugins) {
plugin.onBuild(builder);
}

View File

@ -1,3 +1,3 @@
rootProject.name = 'launcher-parent'
include 'launcher', 'launcher-fancy', 'launcher-builder', 'launcher-bootstrap', 'creator-tools'
include 'launcher', 'launcher-fancy', 'launcher-builder', 'launcher-bootstrap', 'creator-tools', 'builder-plugin-curse'