Merge branch 'master' into 'master'
Improved the GithubFetcher See merge request jfmods/resclone!1
This commit is contained in:
commit
64b13031f7
@ -8,8 +8,9 @@ import java.nio.file.Path;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class PackUrlCache {
|
public class PackUrlCache {
|
||||||
|
|
||||||
|
private final Path file;
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
private Path file;
|
|
||||||
|
|
||||||
public PackUrlCache(Path file) {
|
public PackUrlCache(Path file) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
@ -41,4 +42,5 @@ public class PackUrlCache {
|
|||||||
public void set(String key, String value) {
|
public void set(String key, String value) {
|
||||||
properties.setProperty(key, value);
|
properties.setProperty(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,17 +1,19 @@
|
|||||||
package io.gitlab.jfronny.resclone;
|
package io.gitlab.jfronny.resclone;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import io.gitlab.jfronny.resclone.data.PackMetaLoaded;
|
|
||||||
import io.gitlab.jfronny.resclone.api.RescloneApi;
|
import io.gitlab.jfronny.resclone.api.RescloneApi;
|
||||||
import io.gitlab.jfronny.resclone.api.RescloneEntry;
|
import io.gitlab.jfronny.resclone.api.RescloneEntry;
|
||||||
|
import io.gitlab.jfronny.resclone.data.PackMetaLoaded;
|
||||||
import io.gitlab.jfronny.resclone.data.PackMetaUnloaded;
|
import io.gitlab.jfronny.resclone.data.PackMetaUnloaded;
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
|
||||||
import io.gitlab.jfronny.resclone.fetchers.PackFetcher;
|
import io.gitlab.jfronny.resclone.fetchers.PackFetcher;
|
||||||
import io.gitlab.jfronny.resclone.processors.PackProcessor;
|
import io.gitlab.jfronny.resclone.processors.PackProcessor;
|
||||||
import io.gitlab.jfronny.resclone.processors.RemoveEmptyProcessor;
|
import io.gitlab.jfronny.resclone.processors.RemoveEmptyProcessor;
|
||||||
import io.gitlab.jfronny.resclone.processors.RootPathProcessor;
|
import io.gitlab.jfronny.resclone.processors.RootPathProcessor;
|
||||||
|
import io.gitlab.jfronny.resclone.util.Result;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@ -22,33 +24,42 @@ import java.nio.file.Path;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class Resclone implements ModInitializer, RescloneApi {
|
public class Resclone implements ModInitializer, RescloneApi {
|
||||||
|
|
||||||
public static final Set<PackMetaUnloaded> conf = new LinkedHashSet<>();
|
public static final Set<PackMetaUnloaded> conf = new LinkedHashSet<>();
|
||||||
public static final Map<String, PackFetcher> fetcherInstances = new LinkedHashMap<>();
|
public static final Map<String, PackFetcher> fetcherInstances = new LinkedHashMap<>();
|
||||||
public static final Set<PackProcessor> processors = new LinkedHashSet<>();
|
public static final Set<PackProcessor> processors = new LinkedHashSet<>();
|
||||||
public static final Set<PackMetaLoaded> downloadedPacks = new LinkedHashSet<>();
|
public static final Set<PackMetaLoaded> downloadedPacks = new LinkedHashSet<>();
|
||||||
public static final Gson gson = new Gson();
|
public static final Gson gson = new Gson();
|
||||||
|
|
||||||
public static final String MOD_ID = "resclone";
|
public static final String MOD_ID = "resclone";
|
||||||
|
public static final Logger LOGGER = LogManager.getLogger(MOD_ID);
|
||||||
|
|
||||||
public static PackUrlCache urlCache;
|
public static PackUrlCache urlCache;
|
||||||
|
|
||||||
|
public static int COUNT = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
System.out.println("[resclone] Beginning init, will download packs");
|
LOGGER.info("Initialising Resclone.");
|
||||||
|
|
||||||
urlCache = new PackUrlCache(getConfigPath().resolve("urlCache.properties"));
|
urlCache = new PackUrlCache(getConfigPath().resolve("urlCache.properties"));
|
||||||
conf.clear();
|
conf.clear();
|
||||||
fetcherInstances.clear();
|
fetcherInstances.clear();
|
||||||
processors.clear();
|
processors.clear();
|
||||||
downloadedPacks.clear();
|
downloadedPacks.clear();
|
||||||
|
|
||||||
addProcessor(new RootPathProcessor()); //This should be run before any other processor to make sure the path is valid
|
addProcessor(new RootPathProcessor()); //This should be run before any other processor to make sure the path is valid
|
||||||
for (RescloneEntry entry : FabricLoader.getInstance().getEntrypoints(MOD_ID, RescloneEntry.class)) {
|
for (RescloneEntry entry : FabricLoader.getInstance().getEntrypoints(MOD_ID, RescloneEntry.class)) {
|
||||||
try {
|
try {
|
||||||
entry.init(this);
|
entry.init(this);
|
||||||
} catch (RescloneException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addProcessor(new RemoveEmptyProcessor());
|
addProcessor(new RemoveEmptyProcessor());
|
||||||
reload();
|
reload();
|
||||||
System.out.println("[resclone] Completed");
|
|
||||||
|
LOGGER.info("Installed {} resource pack{}.", COUNT, COUNT == 1 ? "" : "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -79,19 +90,19 @@ public class Resclone implements ModInitializer, RescloneApi {
|
|||||||
for (PackMetaUnloaded s : conf) {
|
for (PackMetaUnloaded s : conf) {
|
||||||
try {
|
try {
|
||||||
if (!fetcherInstances.containsKey(s.fetcher))
|
if (!fetcherInstances.containsKey(s.fetcher))
|
||||||
throw new RescloneException("Invalid fetcher: " + s.fetcher);
|
throw new Exception("Invalid fetcher: " + s.fetcher);
|
||||||
Path cacheDir = getConfigPath().resolve("cache");
|
Path cacheDir = getConfigPath().resolve("cache");
|
||||||
PackMetaLoaded p;
|
PackMetaLoaded p;
|
||||||
try {
|
try {
|
||||||
//Download
|
//Download
|
||||||
PackFetcher.Result fr = fetcherInstances.get(s.fetcher).get(s.source, cacheDir, s.forceDownload);
|
Result fr = fetcherInstances.get(s.fetcher).get(s.source, cacheDir, s.forceDownload);
|
||||||
p = new PackMetaLoaded(fr.downloadPath, s.name);
|
p = new PackMetaLoaded(fr.downloadPath, s.name);
|
||||||
metas.add(p);
|
metas.add(p);
|
||||||
if (fr.freshDownload) {
|
if (fr.freshDownload) {
|
||||||
//Process
|
//Process
|
||||||
Map<String, String> props = new HashMap<>();
|
Map<String, String> props = new HashMap<>();
|
||||||
props.put("create", "false");
|
props.put("create", "false");
|
||||||
URI zipfile = URI.create("jar:" + p.zipPath.toUri().toString());
|
URI zipfile = URI.create("jar:" + p.zipPath.toUri());
|
||||||
try (FileSystem zipfs = FileSystems.newFileSystem(zipfile, props)) {
|
try (FileSystem zipfs = FileSystems.newFileSystem(zipfile, props)) {
|
||||||
for (PackProcessor processor : processors) {
|
for (PackProcessor processor : processors) {
|
||||||
processor.process(zipfs);
|
processor.process(zipfs);
|
||||||
@ -101,9 +112,8 @@ public class Resclone implements ModInitializer, RescloneApi {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (Throwable e) {
|
||||||
catch (Throwable e) {
|
throw new Exception("Failed to download pack", e);
|
||||||
throw new RescloneException("Failed to download pack", e);
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
System.err.println("Encountered issue while preparing " + s.name);
|
System.err.println("Encountered issue while preparing " + s.name);
|
||||||
@ -128,4 +138,5 @@ public class Resclone implements ModInitializer, RescloneApi {
|
|||||||
}
|
}
|
||||||
return configPath;
|
return configPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -5,21 +5,21 @@ import io.gitlab.jfronny.resclone.api.RescloneEntry;
|
|||||||
import io.gitlab.jfronny.resclone.config.ConfigLoader;
|
import io.gitlab.jfronny.resclone.config.ConfigLoader;
|
||||||
import io.gitlab.jfronny.resclone.fetchers.BasicFileFetcher;
|
import io.gitlab.jfronny.resclone.fetchers.BasicFileFetcher;
|
||||||
import io.gitlab.jfronny.resclone.fetchers.CurseforgeFetcher;
|
import io.gitlab.jfronny.resclone.fetchers.CurseforgeFetcher;
|
||||||
import io.gitlab.jfronny.resclone.fetchers.GithubMasterFetcher;
|
import io.gitlab.jfronny.resclone.fetchers.GitHubFetcher;
|
||||||
import io.gitlab.jfronny.resclone.fetchers.GithubReleaseFetcher;
|
|
||||||
import io.gitlab.jfronny.resclone.processors.PruneVanillaProcessor;
|
import io.gitlab.jfronny.resclone.processors.PruneVanillaProcessor;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
|
||||||
public class RescloneEntryDefault implements RescloneEntry {
|
public class RescloneEntryDefault implements RescloneEntry {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(RescloneApi api) {
|
public void init(RescloneApi api) {
|
||||||
api.addFetcher(new BasicFileFetcher());
|
api.addFetcher(new BasicFileFetcher());
|
||||||
api.addFetcher(new GithubMasterFetcher());
|
api.addFetcher(new GitHubFetcher());
|
||||||
api.addFetcher(new GithubReleaseFetcher());
|
|
||||||
api.addFetcher(new CurseforgeFetcher());
|
api.addFetcher(new CurseforgeFetcher());
|
||||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT)
|
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT)
|
||||||
api.addProcessor(new PruneVanillaProcessor());
|
api.addProcessor(new PruneVanillaProcessor());
|
||||||
ConfigLoader.load(api);
|
ConfigLoader.load(api);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -8,7 +8,9 @@ import net.minecraft.resource.ZipResourcePack;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class RescloneResourcePack extends ZipResourcePack implements ModResourcePack {
|
public class RescloneResourcePack extends ZipResourcePack implements ModResourcePack {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public RescloneResourcePack(File file, String name) {
|
public RescloneResourcePack(File file, String name) {
|
||||||
super(file);
|
super(file);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -23,4 +25,5 @@ public class RescloneResourcePack extends ZipResourcePack implements ModResource
|
|||||||
public ModMetadata getFabricModMetadata() {
|
public ModMetadata getFabricModMetadata() {
|
||||||
return FabricLoader.getInstance().getModContainer(Resclone.MOD_ID).get().getMetadata();
|
return FabricLoader.getInstance().getModContainer(Resclone.MOD_ID).get().getMetadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,10 +6,17 @@ import io.gitlab.jfronny.resclone.processors.PackProcessor;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public interface RescloneApi {
|
public interface RescloneApi {
|
||||||
|
|
||||||
void addFetcher(PackFetcher fetcher);
|
void addFetcher(PackFetcher fetcher);
|
||||||
|
|
||||||
void addProcessor(PackProcessor processor);
|
void addProcessor(PackProcessor processor);
|
||||||
|
|
||||||
void addPack(String fetcher, String pack, String name);
|
void addPack(String fetcher, String pack, String name);
|
||||||
|
|
||||||
void addPack(String fetcher, String pack, String name, boolean forceRedownload);
|
void addPack(String fetcher, String pack, String name, boolean forceRedownload);
|
||||||
|
|
||||||
void reload();
|
void reload();
|
||||||
|
|
||||||
Path getConfigPath();
|
Path getConfigPath();
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package io.gitlab.jfronny.resclone.api;
|
package io.gitlab.jfronny.resclone.api;
|
||||||
|
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
|
||||||
|
|
||||||
public interface RescloneEntry {
|
public interface RescloneEntry {
|
||||||
void init(RescloneApi api) throws RescloneException;
|
void init(RescloneApi api) throws Exception;
|
||||||
}
|
}
|
@ -12,6 +12,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ConfigLoader {
|
public class ConfigLoader {
|
||||||
|
|
||||||
public static void load(RescloneApi api) {
|
public static void load(RescloneApi api) {
|
||||||
Path configPath = api.getConfigPath().resolve("config.json");
|
Path configPath = api.getConfigPath().resolve("config.json");
|
||||||
if (!Files.exists(configPath)) {
|
if (!Files.exists(configPath)) {
|
||||||
@ -42,4 +43,5 @@ public class ConfigLoader {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,7 +3,9 @@ package io.gitlab.jfronny.resclone.data;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class CfAddon {
|
public class CfAddon {
|
||||||
|
|
||||||
public String downloadUrl;
|
public String downloadUrl;
|
||||||
public String fileDate;
|
public String fileDate;
|
||||||
public Set<String> gameVersion;
|
public Set<String> gameVersion;
|
||||||
|
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package io.gitlab.jfronny.resclone.data;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public class PackMetaLoaded {
|
public class PackMetaLoaded {
|
||||||
|
|
||||||
public Path zipPath;
|
public Path zipPath;
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
@ -10,4 +11,5 @@ public class PackMetaLoaded {
|
|||||||
this.zipPath = zipPath;
|
this.zipPath = zipPath;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package io.gitlab.jfronny.resclone.data;
|
package io.gitlab.jfronny.resclone.data;
|
||||||
|
|
||||||
public class PackMetaUnloaded {
|
public class PackMetaUnloaded {
|
||||||
|
|
||||||
public final String fetcher;
|
public final String fetcher;
|
||||||
public final String source;
|
public final String source;
|
||||||
public final String name;
|
public final String name;
|
||||||
@ -12,4 +13,5 @@ public class PackMetaUnloaded {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
this.forceDownload = forceDownload;
|
this.forceDownload = forceDownload;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,11 +0,0 @@
|
|||||||
package io.gitlab.jfronny.resclone.data;
|
|
||||||
|
|
||||||
public class RescloneException extends Exception {
|
|
||||||
public RescloneException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RescloneException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package io.gitlab.jfronny.resclone.fetchers;
|
package io.gitlab.jfronny.resclone.fetchers;
|
||||||
|
|
||||||
public class BasicFileFetcher extends PackFetcher {
|
public class BasicFileFetcher extends PackFetcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSourceTypeName() {
|
public String getSourceTypeName() {
|
||||||
return "file";
|
return "file";
|
||||||
@ -10,4 +11,5 @@ public class BasicFileFetcher extends PackFetcher {
|
|||||||
public String getDownloadUrl(String baseUrl) {
|
public String getDownloadUrl(String baseUrl) {
|
||||||
return baseUrl;
|
return baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,20 +1,21 @@
|
|||||||
package io.gitlab.jfronny.resclone.fetchers;
|
package io.gitlab.jfronny.resclone.fetchers;
|
||||||
|
|
||||||
import io.gitlab.jfronny.resclone.data.CfAddon;
|
import io.gitlab.jfronny.resclone.data.CfAddon;
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
import io.gitlab.jfronny.resclone.util.UrlUtils;
|
||||||
import net.minecraft.MinecraftVersion;
|
import net.minecraft.MinecraftVersion;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class CurseforgeFetcher extends PackFetcher {
|
public class CurseforgeFetcher extends PackFetcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSourceTypeName() {
|
public String getSourceTypeName() {
|
||||||
return "curseforge";
|
return "curseforge";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDownloadUrl(String baseUrl) throws RescloneException {
|
public String getDownloadUrl(String baseUrl) throws Exception {
|
||||||
try {
|
try {
|
||||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'");
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'");
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ public class CurseforgeFetcher extends PackFetcher {
|
|||||||
Date latestDate = null;
|
Date latestDate = null;
|
||||||
boolean foundMatchingVersion = false;
|
boolean foundMatchingVersion = false;
|
||||||
|
|
||||||
for (CfAddon addon : readJsonFromURLSet("https://addons-ecs.forgesvc.net/api/v2/addon/" + baseUrl + "/files", CfAddon.class)) {
|
for (CfAddon addon : UrlUtils.readJsonFromURLSet("https://addons-ecs.forgesvc.net/api/v2/addon/" + baseUrl + "/files", CfAddon.class)) {
|
||||||
Date d = df.parse(addon.fileDate);
|
Date d = df.parse(addon.fileDate);
|
||||||
if (foundMatchingVersion && !addon.gameVersion.contains(version))
|
if (foundMatchingVersion && !addon.gameVersion.contains(version))
|
||||||
continue;
|
continue;
|
||||||
@ -42,7 +43,8 @@ public class CurseforgeFetcher extends PackFetcher {
|
|||||||
System.err.println("Could not find pack for matching version, using latest");
|
System.err.println("Could not find pack for matching version, using latest");
|
||||||
return latest.downloadUrl;
|
return latest.downloadUrl;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RescloneException("Could not get CF download for " + baseUrl, e);
|
throw new Exception("Could not get CF download for " + baseUrl, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package io.gitlab.jfronny.resclone.fetchers;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import io.gitlab.jfronny.resclone.Resclone;
|
||||||
|
import io.gitlab.jfronny.resclone.util.UrlUtils;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class GitHubFetcher extends PackFetcher {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSourceTypeName() {
|
||||||
|
return "github";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getDownloadUrl(String baseUrl) throws Exception {
|
||||||
|
String[] parts = baseUrl.split("/");
|
||||||
|
|
||||||
|
if (parts.length < 2) {
|
||||||
|
throw new Exception("Minimum source must contain \"user/repo\".");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "user/repo" - Gets from latest commit of main/master branch. */
|
||||||
|
else if (parts.length == 2) {
|
||||||
|
return getFromBranch(parts[0], parts[1], null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "user/repo/branch/branchName" - Gets from latest commit of specified branch. */
|
||||||
|
else if (parts[2].equalsIgnoreCase("branch")) {
|
||||||
|
if (parts.length < 4) throw new Exception("Missing branch name in source definition.");
|
||||||
|
else {
|
||||||
|
Resclone.LOGGER.info("Getting from " + parts[3] + " branch.");
|
||||||
|
return getFromBranch(parts[0], parts[1], parts[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "user/repo/release" - Gets from the latest release. */
|
||||||
|
else if (parts[2].equalsIgnoreCase("release")) {
|
||||||
|
try {
|
||||||
|
JsonObject latestRelease = UrlUtils.readJsonFromURL("https://api.github.com/repos/" + parts[0] + "/" + parts[1] + "/releases/latest", JsonObject.class);
|
||||||
|
String res = null;
|
||||||
|
|
||||||
|
for (JsonElement element : latestRelease.get("assets").getAsJsonArray()) {
|
||||||
|
JsonObject o = element.getAsJsonObject();
|
||||||
|
if ("application/x-zip-compressed".equals(o.get("content_type").getAsString()) || o.get("name").getAsString().endsWith(".zip")) {
|
||||||
|
res = o.get("browser_download_url").getAsString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resclone.LOGGER.info("Getting from latest release.");
|
||||||
|
|
||||||
|
if (res == null) return latestRelease.get("zipball_url").getAsString();
|
||||||
|
else return res;
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new Exception("Failed to get github release asset", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "user/repo/tag/tagNum" - Gets from a specified tag. */
|
||||||
|
else if (parts[2].equalsIgnoreCase("tag")) {
|
||||||
|
if (parts.length < 4) throw new Exception("Missing tag number in source definition.");
|
||||||
|
else {
|
||||||
|
return getFromTag(parts[0], parts[1], parts[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFromBranch(String user, String repo, @Nullable String branch) {
|
||||||
|
boolean main = branch == null;
|
||||||
|
String url;
|
||||||
|
|
||||||
|
if (main) {
|
||||||
|
url = "https://codeload.github.com/" + user + "/" + repo + "/legacy.zip/refs/heads/main";
|
||||||
|
if (!UrlUtils.urlValid(url)) url = "https://codeload.github.com/" + user + "/" + repo + "/legacy.zip/refs/heads/master";
|
||||||
|
Resclone.LOGGER.info("Getting from main branch.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
url = "https://codeload.github.com/" + user + "/" + repo + "/legacy.zip/refs/heads/" + branch;
|
||||||
|
Resclone.LOGGER.info("Getting from " + branch + " branch.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFromTag(String user, String repo, String tag) {
|
||||||
|
Resclone.LOGGER.info("Getting from tag " + tag + ".");
|
||||||
|
return "https://codeload.github.com/" + user + "/" + repo + "/legacy.zip/refs/tags/" + tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,32 +0,0 @@
|
|||||||
package io.gitlab.jfronny.resclone.fetchers;
|
|
||||||
|
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
|
||||||
|
|
||||||
public class GithubMasterFetcher extends PackFetcher {
|
|
||||||
@Override
|
|
||||||
public String getSourceTypeName() {
|
|
||||||
return "github-master";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDownloadUrl(String baseUrl) throws RescloneException {
|
|
||||||
String[] parts = baseUrl.split("/");
|
|
||||||
String url = "";
|
|
||||||
if (parts.length == 2) {
|
|
||||||
url = getStr(parts[0], parts[1], "main");
|
|
||||||
if (!urlValid(url))
|
|
||||||
url = getStr(parts[0], parts[1], "master");
|
|
||||||
}
|
|
||||||
else if (parts.length == 3) {
|
|
||||||
url = getStr(parts[0], parts[1], parts[2]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new RescloneException("Format for github-master is USER/REPO[/BRANCH]");
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getStr(String user, String repo, String branch) {
|
|
||||||
return "https://github.com/" + user + "/" + repo + "/archive/" + branch + ".zip";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package io.gitlab.jfronny.resclone.fetchers;
|
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
|
||||||
|
|
||||||
public class GithubReleaseFetcher extends PackFetcher {
|
|
||||||
@Override
|
|
||||||
public String getSourceTypeName() {
|
|
||||||
return "github-release";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
String getDownloadUrl(String baseUrl) throws RescloneException {
|
|
||||||
String[] parts = baseUrl.split("/");
|
|
||||||
if (parts.length == 2) {
|
|
||||||
try {
|
|
||||||
JsonObject latestRelease = readJsonFromURL("https://api.github.com/repos/" + parts[0] + "/" + parts[1] + "/releases/latest", JsonObject.class);
|
|
||||||
String res = null;
|
|
||||||
for (JsonElement element : latestRelease.get("assets").getAsJsonArray()) {
|
|
||||||
JsonObject o = element.getAsJsonObject();
|
|
||||||
if ("application/x-zip-compressed".equals(o.get("content_type").getAsString())
|
|
||||||
|| o.get("name").getAsString().endsWith(".zip")) {
|
|
||||||
res = o.get("browser_download_url").getAsString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res == null) {
|
|
||||||
System.out.println("Could not find release asset for " + baseUrl + ", using zipball");
|
|
||||||
return latestRelease.get("zipball_url").getAsString();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
throw new RescloneException("Failed to get github release asset", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new RescloneException("Format for github-release is USER/REPO");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +1,42 @@
|
|||||||
package io.gitlab.jfronny.resclone.fetchers;
|
package io.gitlab.jfronny.resclone.fetchers;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import io.gitlab.jfronny.resclone.Resclone;
|
import io.gitlab.jfronny.resclone.Resclone;
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
import io.gitlab.jfronny.resclone.util.Result;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Scanner;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public abstract class PackFetcher {
|
public abstract class PackFetcher {
|
||||||
|
|
||||||
abstract public String getSourceTypeName(); // The name for users to specify in the config
|
abstract public String getSourceTypeName(); // The name for users to specify in the config
|
||||||
abstract String getDownloadUrl(String baseUrl) throws RescloneException; // Return the actual download URL for the file based on the provided string
|
|
||||||
protected final Gson gson = Resclone.gson;
|
|
||||||
protected boolean urlValid(String url) {
|
|
||||||
try {
|
|
||||||
HttpURLConnection connection = (HttpURLConnection)new URL(url).toURI().toURL().openConnection();
|
|
||||||
connection.setRequestMethod("GET");
|
|
||||||
connection.connect();
|
|
||||||
return connection.getResponseCode() == 200;
|
|
||||||
}
|
|
||||||
catch (Throwable e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String readStringFromURL(String requestURL) throws IOException {
|
abstract String getDownloadUrl(String baseUrl) throws Exception; // Return the actual download URL for the file based on the provided string
|
||||||
try (Scanner scanner = new Scanner(new URL(requestURL).openStream(), StandardCharsets.UTF_8.toString()))
|
|
||||||
{
|
|
||||||
scanner.useDelimiter("\\A");
|
|
||||||
return scanner.hasNext() ? scanner.next() : "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T readJsonFromURL(String requestUrl, Class<T> classOfT) throws IOException {
|
public Result get(String baseUrl, Path targetDir, boolean forceDownload) throws Exception {
|
||||||
return gson.fromJson(readStringFromURL(requestUrl), classOfT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> Set<T> readJsonFromURLSet(String requestUrl, Class<T> classOfT) throws IOException {
|
|
||||||
return gson.fromJson(readStringFromURL(requestUrl), TypeToken.getParameterized(Set.class, classOfT).getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result get(String baseUrl, Path targetDir, boolean forceDownload) throws RescloneException {
|
|
||||||
String url;
|
String url;
|
||||||
try {
|
try {
|
||||||
url = getDownloadUrl(baseUrl);
|
url = getDownloadUrl(baseUrl);
|
||||||
Resclone.urlCache.set(baseUrl, url);
|
Resclone.urlCache.set(baseUrl, url);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (RescloneException e) {
|
|
||||||
if (Resclone.urlCache.containsKey(baseUrl)) {
|
if (Resclone.urlCache.containsKey(baseUrl)) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
url = Resclone.urlCache.get(baseUrl);
|
url = Resclone.urlCache.get(baseUrl);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Path p = targetDir.resolve(Integer.toHexString(url.hashCode()));
|
Path p = targetDir.resolve(Integer.toHexString(url.hashCode()));
|
||||||
if (!forceDownload && Files.exists(p))
|
|
||||||
|
if (!forceDownload && Files.exists(p)) {
|
||||||
|
Resclone.COUNT++;
|
||||||
return new Result(p, false);
|
return new Result(p, false);
|
||||||
System.out.println("Downloading pack " + url);
|
}
|
||||||
|
|
||||||
|
Resclone.LOGGER.info("Downloading pack: " + url);
|
||||||
|
|
||||||
try (InputStream is = new URL(url).openStream()) {
|
try (InputStream is = new URL(url).openStream()) {
|
||||||
FileOutputStream os = new FileOutputStream(p.toFile());
|
FileOutputStream os = new FileOutputStream(p.toFile());
|
||||||
byte[] dataBuffer = new byte[1024];
|
byte[] dataBuffer = new byte[1024];
|
||||||
@ -74,21 +44,12 @@ public abstract class PackFetcher {
|
|||||||
while ((bytesRead = is.read(dataBuffer, 0, 1024)) != -1) {
|
while ((bytesRead = is.read(dataBuffer, 0, 1024)) != -1) {
|
||||||
os.write(dataBuffer, 0, bytesRead);
|
os.write(dataBuffer, 0, bytesRead);
|
||||||
}
|
}
|
||||||
System.out.println("Completed download");
|
Resclone.LOGGER.info("Finished downloading.");
|
||||||
}
|
} catch (Throwable e) {
|
||||||
catch (Throwable e) {
|
throw new Exception("Could not download pack", e);
|
||||||
throw new RescloneException("Could not download pack", e);
|
|
||||||
}
|
}
|
||||||
|
Resclone.COUNT++;
|
||||||
return new Result(p, true);
|
return new Result(p, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Result {
|
|
||||||
public final Path downloadPath;
|
|
||||||
public final boolean freshDownload;
|
|
||||||
|
|
||||||
public Result(Path downloadPath, boolean freshDownload) {
|
|
||||||
this.downloadPath = downloadPath;
|
|
||||||
this.freshDownload = freshDownload;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -5,29 +5,27 @@ import java.nio.file.*;
|
|||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
|
||||||
public class MoveDirVisitor extends SimpleFileVisitor<Path> {
|
public class MoveDirVisitor extends SimpleFileVisitor<Path> {
|
||||||
|
|
||||||
private final Path fromPath;
|
private final Path fromPath;
|
||||||
private final Path toPath;
|
private final Path toPath;
|
||||||
private final CopyOption copyOption;
|
private final CopyOption copyOption;
|
||||||
|
|
||||||
public MoveDirVisitor(Path fromPath, Path toPath, CopyOption copyOption)
|
public MoveDirVisitor(Path fromPath, Path toPath, CopyOption copyOption) {
|
||||||
{
|
|
||||||
this.fromPath = fromPath;
|
this.fromPath = fromPath;
|
||||||
this.toPath = toPath;
|
this.toPath = toPath;
|
||||||
this.copyOption = copyOption;
|
this.copyOption = copyOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
{
|
|
||||||
Path targetPath = toPath.resolve(fromPath.relativize(dir));
|
Path targetPath = toPath.resolve(fromPath.relativize(dir));
|
||||||
if(!Files.exists(targetPath))
|
if (!Files.exists(targetPath))
|
||||||
Files.createDirectory(targetPath);
|
Files.createDirectory(targetPath);
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
{
|
|
||||||
Files.copy(file, toPath.resolve(fromPath.relativize(file)), copyOption);
|
Files.copy(file, toPath.resolve(fromPath.relativize(file)), copyOption);
|
||||||
Files.delete(file);
|
Files.delete(file);
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
@ -38,4 +36,5 @@ public class MoveDirVisitor extends SimpleFileVisitor<Path> {
|
|||||||
Files.delete(dir);
|
Files.delete(dir);
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -9,7 +9,9 @@ import java.nio.file.attribute.BasicFileAttributes;
|
|||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class PathPruneVisitor extends SimpleFileVisitor<Path> {
|
public class PathPruneVisitor extends SimpleFileVisitor<Path> {
|
||||||
|
|
||||||
Predicate<Path> removalSelector;
|
Predicate<Path> removalSelector;
|
||||||
|
|
||||||
public PathPruneVisitor(Predicate<Path> removalSelector) {
|
public PathPruneVisitor(Predicate<Path> removalSelector) {
|
||||||
this.removalSelector = removalSelector;
|
this.removalSelector = removalSelector;
|
||||||
}
|
}
|
||||||
@ -25,4 +27,5 @@ public class PathPruneVisitor extends SimpleFileVisitor<Path> {
|
|||||||
if (removalSelector.test(dir)) Files.walkFileTree(dir, new RemoveDirVisitor());
|
if (removalSelector.test(dir)) Files.walkFileTree(dir, new RemoveDirVisitor());
|
||||||
return super.postVisitDirectory(dir, exc);
|
return super.postVisitDirectory(dir, exc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,14 @@
|
|||||||
package io.gitlab.jfronny.resclone.io;
|
package io.gitlab.jfronny.resclone.io;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.*;
|
import java.nio.file.FileVisitResult;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
|
||||||
public class RemoveDirVisitor extends SimpleFileVisitor<Path> {
|
public class RemoveDirVisitor extends SimpleFileVisitor<Path> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
Files.delete(file);
|
Files.delete(file);
|
||||||
@ -16,4 +20,5 @@ public class RemoveDirVisitor extends SimpleFileVisitor<Path> {
|
|||||||
Files.delete(dir);
|
Files.delete(dir);
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,7 +3,9 @@ package io.gitlab.jfronny.resclone.mixin;
|
|||||||
import io.gitlab.jfronny.resclone.Resclone;
|
import io.gitlab.jfronny.resclone.Resclone;
|
||||||
import io.gitlab.jfronny.resclone.RescloneResourcePack;
|
import io.gitlab.jfronny.resclone.RescloneResourcePack;
|
||||||
import io.gitlab.jfronny.resclone.data.PackMetaLoaded;
|
import io.gitlab.jfronny.resclone.data.PackMetaLoaded;
|
||||||
import net.minecraft.resource.*;
|
import net.minecraft.resource.FileResourcePackProvider;
|
||||||
|
import net.minecraft.resource.ResourcePackProfile;
|
||||||
|
import net.minecraft.resource.ResourcePackSource;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@ -15,7 +17,10 @@ import java.util.function.Consumer;
|
|||||||
|
|
||||||
@Mixin(FileResourcePackProvider.class)
|
@Mixin(FileResourcePackProvider.class)
|
||||||
public class FileResourcePackProviderMixin {
|
public class FileResourcePackProviderMixin {
|
||||||
@Shadow @Final private ResourcePackSource field_25345;
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private ResourcePackSource field_25345;
|
||||||
|
|
||||||
@Inject(at = @At("TAIL"), method = "register(Ljava/util/function/Consumer;Lnet/minecraft/resource/ResourcePackProfile$Factory;)V")
|
@Inject(at = @At("TAIL"), method = "register(Ljava/util/function/Consumer;Lnet/minecraft/resource/ResourcePackProfile$Factory;)V")
|
||||||
public void registerExtra(Consumer<ResourcePackProfile> consumer, ResourcePackProfile.Factory factory, CallbackInfo info) {
|
public void registerExtra(Consumer<ResourcePackProfile> consumer, ResourcePackProfile.Factory factory, CallbackInfo info) {
|
||||||
@ -33,4 +38,5 @@ public class FileResourcePackProviderMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,9 +1,7 @@
|
|||||||
package io.gitlab.jfronny.resclone.processors;
|
package io.gitlab.jfronny.resclone.processors;
|
||||||
|
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
|
||||||
|
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
|
|
||||||
public abstract class PackProcessor {
|
public abstract class PackProcessor {
|
||||||
public abstract void process(FileSystem p) throws RescloneException;
|
public abstract void process(FileSystem p) throws Exception;
|
||||||
}
|
}
|
@ -1,13 +1,7 @@
|
|||||||
package io.gitlab.jfronny.resclone.processors;
|
package io.gitlab.jfronny.resclone.processors;
|
||||||
|
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
|
||||||
import io.gitlab.jfronny.resclone.io.PathPruneVisitor;
|
import io.gitlab.jfronny.resclone.io.PathPruneVisitor;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.resource.ResourcePack;
|
|
||||||
import net.minecraft.resource.ResourcePackManager;
|
|
||||||
import net.minecraft.resource.ResourcePackProfile;
|
|
||||||
import net.minecraft.resource.ResourceType;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -17,8 +11,9 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
|
|
||||||
public class PruneVanillaProcessor extends PackProcessor {
|
public class PruneVanillaProcessor extends PackProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(FileSystem p) throws RescloneException {
|
public void process(FileSystem p) throws Exception {
|
||||||
ClassLoader cl = MinecraftClient.class.getClassLoader();
|
ClassLoader cl = MinecraftClient.class.getClassLoader();
|
||||||
try {
|
try {
|
||||||
if (Files.isDirectory(p.getPath("/assets/minecraft"))) {
|
if (Files.isDirectory(p.getPath("/assets/minecraft"))) {
|
||||||
@ -32,15 +27,15 @@ public class PruneVanillaProcessor extends PackProcessor {
|
|||||||
return IOUtils.contentEquals(vn, pk);
|
return IOUtils.contentEquals(vn, pk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (Throwable e) {
|
||||||
catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RescloneException("Could not prune vanilla files", e);
|
throw new Exception("Could not prune vanilla files", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package io.gitlab.jfronny.resclone.processors;
|
package io.gitlab.jfronny.resclone.processors;
|
||||||
|
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
|
||||||
import io.gitlab.jfronny.resclone.io.PathPruneVisitor;
|
import io.gitlab.jfronny.resclone.io.PathPruneVisitor;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -10,8 +9,9 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public class RemoveEmptyProcessor extends PackProcessor {
|
public class RemoveEmptyProcessor extends PackProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(FileSystem p) throws RescloneException {
|
public void process(FileSystem p) throws Exception {
|
||||||
if (Files.exists(p.getPath("/assets"))) {
|
if (Files.exists(p.getPath("/assets"))) {
|
||||||
try {
|
try {
|
||||||
Files.walkFileTree(p.getPath("/assets"), new PathPruneVisitor(s -> {
|
Files.walkFileTree(p.getPath("/assets"), new PathPruneVisitor(s -> {
|
||||||
@ -25,8 +25,9 @@ public class RemoveEmptyProcessor extends PackProcessor {
|
|||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RescloneException("Failed to prune empty directories", e);
|
throw new Exception("Failed to prune empty directories", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
package io.gitlab.jfronny.resclone.processors;
|
package io.gitlab.jfronny.resclone.processors;
|
||||||
|
|
||||||
import io.gitlab.jfronny.resclone.io.MoveDirVisitor;
|
import io.gitlab.jfronny.resclone.io.MoveDirVisitor;
|
||||||
import io.gitlab.jfronny.resclone.data.RescloneException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
|
|
||||||
public class RootPathProcessor extends PackProcessor {
|
public class RootPathProcessor extends PackProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(FileSystem p) throws RescloneException {
|
public void process(FileSystem p) throws Exception {
|
||||||
if (!Files.exists(p.getPath("/pack.mcmeta"))) {
|
if (!Files.exists(p.getPath("/pack.mcmeta"))) {
|
||||||
try {
|
try {
|
||||||
Path root = p.getPath("/");
|
Path root = p.getPath("/");
|
||||||
@ -20,8 +20,9 @@ public class RootPathProcessor extends PackProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RescloneException("Could not fix root path", e);
|
throw new Exception("Could not fix root path", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
15
src/main/java/io/gitlab/jfronny/resclone/util/Result.java
Normal file
15
src/main/java/io/gitlab/jfronny/resclone/util/Result.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package io.gitlab.jfronny.resclone.util;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class Result {
|
||||||
|
|
||||||
|
public final Path downloadPath;
|
||||||
|
public final boolean freshDownload;
|
||||||
|
|
||||||
|
public Result(Path downloadPath, boolean freshDownload) {
|
||||||
|
this.downloadPath = downloadPath;
|
||||||
|
this.freshDownload = freshDownload;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
src/main/java/io/gitlab/jfronny/resclone/util/UrlUtils.java
Normal file
41
src/main/java/io/gitlab/jfronny/resclone/util/UrlUtils.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package io.gitlab.jfronny.resclone.util;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import io.gitlab.jfronny.resclone.Resclone;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class UrlUtils {
|
||||||
|
|
||||||
|
public static boolean urlValid(String url) {
|
||||||
|
try {
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new URL(url).toURI().toURL().openConnection();
|
||||||
|
connection.setRequestMethod("GET");
|
||||||
|
connection.connect();
|
||||||
|
return connection.getResponseCode() == 200;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readStringFromURL(String requestURL) throws IOException {
|
||||||
|
try (Scanner scanner = new Scanner(new URL(requestURL).openStream(), StandardCharsets.UTF_8.toString())) {
|
||||||
|
scanner.useDelimiter("\\A");
|
||||||
|
return scanner.hasNext() ? scanner.next() : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T readJsonFromURL(String requestUrl, Class<T> classOfT) throws IOException {
|
||||||
|
return Resclone.gson.fromJson(readStringFromURL(requestUrl), classOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Set<T> readJsonFromURLSet(String requestUrl, Class<T> classOfT) throws IOException {
|
||||||
|
return Resclone.gson.fromJson(readStringFromURL(requestUrl), TypeToken.getParameterized(Set.class, classOfT).getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
"id": "resclone",
|
"id": "resclone",
|
||||||
"version": "${version}",
|
"version": "${version}",
|
||||||
"name": "Resclone",
|
"name": "Resclone",
|
||||||
"description": "Downloads and updates resourcepacks",
|
"description": "Downloads and updates resourcepacks.",
|
||||||
"authors": [
|
"authors": [
|
||||||
"JFronny"
|
"JFronny"
|
||||||
],
|
],
|
||||||
|
Loading…
Reference in New Issue
Block a user