Modernize, support CfCore and update for 1.19-rc2
This commit is contained in:
parent
906a0a4d74
commit
f699ab3bf3
|
@ -1,5 +1,6 @@
|
|||
apply from: "https://jfmods.gitlab.io/scripts/jfmod.gradle"
|
||||
|
||||
dependencies {
|
||||
modImplementation "com.terraformersmc:modmenu:3.1.0"
|
||||
include modImplementation("io.gitlab.jfronny.libjf:libjf-base:${project.jfapi_version}") // for JfCommons
|
||||
modImplementation "com.terraformersmc:modmenu:4.0.0-beta.4"
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
# https://fabricmc.net/develop
|
||||
minecraft_version=1.18.2
|
||||
minecraft_version=1.19-rc2
|
||||
yarn_mappings=build.1
|
||||
loader_version=0.13.3
|
||||
loader_version=0.14.6
|
||||
maven_group=io.gitlab.jfronny
|
||||
archives_base_name=resclone
|
||||
|
||||
fabric_version=0.47.8+1.18.2
|
||||
fabric_version=0.55.1+1.19
|
||||
jfapi_version=2.8.1-1654352298
|
||||
|
||||
modrinth_id=kVAQyCLX
|
|
@ -1,79 +1,69 @@
|
|||
package io.gitlab.jfronny.resclone;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.gitlab.jfronny.resclone.api.PackFetcher;
|
||||
import io.gitlab.jfronny.resclone.api.RescloneApi;
|
||||
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.api.PackProcessor;
|
||||
import io.gitlab.jfronny.resclone.processors.RemoveEmptyProcessor;
|
||||
import io.gitlab.jfronny.resclone.processors.RootPathProcessor;
|
||||
import io.gitlab.jfronny.resclone.util.PackUrlCache;
|
||||
import io.gitlab.jfronny.resclone.util.Result;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.google.gson.*;
|
||||
import io.gitlab.jfronny.commons.log.*;
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.*;
|
||||
import io.gitlab.jfronny.resclone.api.*;
|
||||
import io.gitlab.jfronny.resclone.data.*;
|
||||
import io.gitlab.jfronny.resclone.processors.*;
|
||||
import io.gitlab.jfronny.resclone.util.*;
|
||||
import net.fabricmc.api.*;
|
||||
import net.fabricmc.loader.api.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class Resclone implements ModInitializer, RescloneApi {
|
||||
public static final Set<PackMetaUnloaded> conf = new LinkedHashSet<>();
|
||||
public static final Map<String, PackFetcher> fetcherInstances = new LinkedHashMap<>();
|
||||
public static final Set<PackProcessor> processors = new LinkedHashSet<>();
|
||||
public static final Set<PackMetaLoaded> downloadedPacks = new LinkedHashSet<>();
|
||||
public static final Set<PackMetaLoaded> newPacks = new LinkedHashSet<>();
|
||||
public static final Gson gson = new Gson();
|
||||
public static final Set<PackMetaUnloaded> CONF = new LinkedHashSet<>();
|
||||
public static final Map<String, PackFetcher> FETCHER_INSTANCES = new LinkedHashMap<>();
|
||||
public static final Set<PackProcessor> PROCESSORS = new LinkedHashSet<>();
|
||||
public static final Set<PackMetaLoaded> DOWNLOADED_PACKS = new LinkedHashSet<>();
|
||||
public static final Set<PackMetaLoaded> NEW_PACKS = new LinkedHashSet<>();
|
||||
|
||||
public static final String MOD_ID = "resclone";
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||
public static final Logger LOGGER = Logger.forName(MOD_ID);
|
||||
|
||||
public static PackUrlCache urlCache;
|
||||
|
||||
public static int COUNT = 0;
|
||||
public static int packCount = 0;
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
LOGGER.info("Initialising Resclone.");
|
||||
GsonHolder.register();
|
||||
|
||||
urlCache = new PackUrlCache(getConfigPath().resolve("urlCache.properties"));
|
||||
conf.clear();
|
||||
fetcherInstances.clear();
|
||||
processors.clear();
|
||||
downloadedPacks.clear();
|
||||
CONF.clear();
|
||||
FETCHER_INSTANCES.clear();
|
||||
PROCESSORS.clear();
|
||||
DOWNLOADED_PACKS.clear();
|
||||
|
||||
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)) {
|
||||
try {
|
||||
entry.init(this);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Resclone.LOGGER.error("Could not initialize resclone pack supplier", e);
|
||||
}
|
||||
}
|
||||
addProcessor(new RemoveEmptyProcessor());
|
||||
reload();
|
||||
|
||||
LOGGER.info("Installed {} resource pack{}.", COUNT, COUNT == 1 ? "" : "s");
|
||||
LOGGER.info("Installed {} resource pack{}.", packCount, packCount == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetcher(PackFetcher fetcher) {
|
||||
fetcherInstances.put(fetcher.getSourceTypeName(), fetcher);
|
||||
FETCHER_INSTANCES.put(fetcher.getSourceTypeName(), fetcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProcessor(PackProcessor processor) {
|
||||
processors.add(processor);
|
||||
PROCESSORS.add(processor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,19 +78,19 @@ public class Resclone implements ModInitializer, RescloneApi {
|
|||
|
||||
@Override
|
||||
public void addPack(String fetcher, String pack, String name, boolean forceRedownload, boolean forceEnable) {
|
||||
conf.add(new PackMetaUnloaded(fetcher, pack, name, forceRedownload, forceEnable));
|
||||
CONF.add(new PackMetaUnloaded(fetcher, pack, name, forceRedownload, forceEnable));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
Set<PackMetaLoaded> metas = new LinkedHashSet<>();
|
||||
try {
|
||||
if (conf.isEmpty()) {
|
||||
if (CONF.isEmpty()) {
|
||||
LOGGER.info("No resclone pack was specified, add one");
|
||||
}
|
||||
else {
|
||||
ExecutorService pool = Executors.newFixedThreadPool(conf.size());
|
||||
for (PackMetaUnloaded s : conf) {
|
||||
ExecutorService pool = Executors.newFixedThreadPool(CONF.size());
|
||||
for (PackMetaUnloaded s : CONF) {
|
||||
pool.submit(generateTask(s, metas));
|
||||
}
|
||||
pool.shutdown();
|
||||
|
@ -109,40 +99,39 @@ public class Resclone implements ModInitializer, RescloneApi {
|
|||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Could not execute pack download task", e);
|
||||
}
|
||||
urlCache.save();
|
||||
downloadedPacks.clear();
|
||||
downloadedPacks.addAll(metas);
|
||||
DOWNLOADED_PACKS.clear();
|
||||
DOWNLOADED_PACKS.addAll(metas);
|
||||
}
|
||||
|
||||
private Runnable generateTask(PackMetaUnloaded meta, Set<PackMetaLoaded> metas) {
|
||||
return () -> {
|
||||
try {
|
||||
if (!fetcherInstances.containsKey(meta.fetcher))
|
||||
if (!FETCHER_INSTANCES.containsKey(meta.fetcher))
|
||||
throw new Exception("Invalid fetcher: " + meta.fetcher);
|
||||
Path cacheDir = getConfigPath().resolve("cache");
|
||||
PackMetaLoaded p;
|
||||
try {
|
||||
boolean isNew = !urlCache.containsKey(meta.source);
|
||||
//Download
|
||||
Result fr = fetcherInstances.get(meta.fetcher).get(meta.source, cacheDir, meta.forceDownload);
|
||||
p = new PackMetaLoaded(fr.downloadPath, meta.name, meta.forceEnable);
|
||||
PackFetcher.Result fr = FETCHER_INSTANCES.get(meta.fetcher).get(meta.source, cacheDir, meta.forceDownload);
|
||||
p = new PackMetaLoaded(fr.downloadPath(), meta.name, meta.forceEnable);
|
||||
metas.add(p);
|
||||
if (isNew)
|
||||
newPacks.add(p);
|
||||
if (fr.freshDownload) {
|
||||
NEW_PACKS.add(p);
|
||||
if (fr.freshDownload()) {
|
||||
//Process
|
||||
Map<String, String> props = new HashMap<>();
|
||||
props.put("create", "false");
|
||||
URI zipfile = URI.create("jar:" + p.zipPath.toUri());
|
||||
URI zipfile = URI.create("jar:" + p.zipPath().toUri());
|
||||
try (FileSystem zipfs = FileSystems.newFileSystem(zipfile, props)) {
|
||||
for (PackProcessor processor : processors) {
|
||||
for (PackProcessor processor : PROCESSORS) {
|
||||
processor.process(zipfs);
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Could not run pack processors on " + p.zipPath(), e);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
|
@ -161,9 +150,9 @@ public class Resclone implements ModInitializer, RescloneApi {
|
|||
try {
|
||||
Files.createDirectories(configPath.resolve("cache"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Could not create cache directory", e);
|
||||
}
|
||||
}
|
||||
return configPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,4 +20,4 @@ public class RescloneEntryDefault implements RescloneEntry {
|
|||
api.addProcessor(new PruneVanillaProcessor());
|
||||
ConfigLoader.load(api);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import net.minecraft.resource.ZipResourcePack;
|
|||
import java.io.File;
|
||||
|
||||
public class RescloneResourcePack extends ZipResourcePack implements ModResourcePack {
|
||||
|
||||
private static final ModMetadata METADATA = FabricLoader.getInstance().getModContainer(Resclone.MOD_ID).get().getMetadata();
|
||||
private final String name;
|
||||
|
||||
public RescloneResourcePack(File file, String name) {
|
||||
|
@ -23,7 +23,6 @@ public class RescloneResourcePack extends ZipResourcePack implements ModResource
|
|||
|
||||
@Override
|
||||
public ModMetadata getFabricModMetadata() {
|
||||
return FabricLoader.getInstance().getModContainer(Resclone.MOD_ID).get().getMetadata();
|
||||
return METADATA;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package io.gitlab.jfronny.resclone.api;
|
||||
|
||||
import io.gitlab.jfronny.resclone.util.Result;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public interface PackFetcher {
|
||||
Result get(String baseUrl, Path targetDir, boolean forceDownload) throws Exception;
|
||||
String getSourceTypeName(); // The name for users to specify in the config
|
||||
|
||||
record Result(Path downloadPath, boolean freshDownload) { }
|
||||
}
|
||||
|
|
|
@ -4,4 +4,4 @@ import java.nio.file.FileSystem;
|
|||
|
||||
public interface PackProcessor {
|
||||
void process(FileSystem p) throws Exception;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package io.gitlab.jfronny.resclone.api;
|
|||
import java.nio.file.Path;
|
||||
|
||||
public interface RescloneApi {
|
||||
|
||||
void addFetcher(PackFetcher fetcher);
|
||||
|
||||
void addProcessor(PackProcessor processor);
|
||||
|
@ -17,5 +16,4 @@ public interface RescloneApi {
|
|||
void reload();
|
||||
|
||||
Path getConfigPath();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,4 +2,4 @@ package io.gitlab.jfronny.resclone.api;
|
|||
|
||||
public interface RescloneEntry {
|
||||
void init(RescloneApi api) throws Exception;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package io.gitlab.jfronny.resclone.data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class CfAddon {
|
||||
|
||||
public String downloadUrl;
|
||||
public String fileDate;
|
||||
public Set<String> gameVersion;
|
||||
|
||||
}
|
|
@ -2,14 +2,5 @@ package io.gitlab.jfronny.resclone.data;
|
|||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class PackMetaLoaded {
|
||||
public final Path zipPath;
|
||||
public final String name;
|
||||
public final boolean forceEnable;
|
||||
|
||||
public PackMetaLoaded(Path zipPath, String name, boolean forceEnable) {
|
||||
this.zipPath = zipPath;
|
||||
this.name = name;
|
||||
this.forceEnable = forceEnable;
|
||||
}
|
||||
}
|
||||
public record PackMetaLoaded(Path zipPath, String name, boolean forceEnable) {
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.resclone.data;
|
||||
|
||||
// Represents a pack as present in the config
|
||||
// Can't be a record since it'll need to be parsed by Gson
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class PackMetaUnloaded {
|
||||
public final String fetcher;
|
||||
public final String source;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package io.gitlab.jfronny.resclone.data.curseforge;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class GetModFilesResponse {
|
||||
public List<Data> data;
|
||||
|
||||
public static class Data {
|
||||
public String downloadUrl;
|
||||
public Date fileDate;
|
||||
public List<String> gameVersions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package io.gitlab.jfronny.resclone.data.curseforge;
|
||||
|
||||
public class GetModResponse {
|
||||
public Data data;
|
||||
|
||||
public static class Data {
|
||||
public Boolean allowModDistribution;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package io.gitlab.jfronny.resclone.data.github;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Release {
|
||||
public List<Asset> assets;
|
||||
public String zipball_url;
|
||||
|
||||
public static class Asset {
|
||||
public String name;
|
||||
public String content_type;
|
||||
public String browser_download_url;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package io.gitlab.jfronny.resclone.data.github;
|
||||
|
||||
public class Repository {
|
||||
public String default_branch;
|
||||
}
|
|
@ -2,7 +2,6 @@ package io.gitlab.jfronny.resclone.fetchers;
|
|||
|
||||
import io.gitlab.jfronny.resclone.Resclone;
|
||||
import io.gitlab.jfronny.resclone.api.PackFetcher;
|
||||
import io.gitlab.jfronny.resclone.util.Result;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
@ -20,7 +19,7 @@ public abstract class BasePackFetcher implements PackFetcher {
|
|||
Resclone.urlCache.set(baseUrl, url);
|
||||
} catch (Exception e) {
|
||||
if (Resclone.urlCache.containsKey(baseUrl)) {
|
||||
e.printStackTrace();
|
||||
Resclone.LOGGER.error("Could not get download URL for " + baseUrl + ", using cached", e);
|
||||
url = Resclone.urlCache.get(baseUrl);
|
||||
} else {
|
||||
throw e;
|
||||
|
@ -29,7 +28,7 @@ public abstract class BasePackFetcher implements PackFetcher {
|
|||
Path p = targetDir.resolve(Integer.toHexString(url.hashCode()));
|
||||
|
||||
if (!forceDownload && Files.exists(p)) {
|
||||
Resclone.COUNT++;
|
||||
Resclone.packCount++;
|
||||
return new Result(p, false);
|
||||
}
|
||||
|
||||
|
@ -46,7 +45,7 @@ public abstract class BasePackFetcher implements PackFetcher {
|
|||
} catch (Throwable e) {
|
||||
throw new Exception("Could not download pack", e);
|
||||
}
|
||||
Resclone.COUNT++;
|
||||
Resclone.packCount++;
|
||||
return new Result(p, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.gitlab.jfronny.resclone.fetchers;
|
||||
|
||||
public class BasicFileFetcher extends BasePackFetcher {
|
||||
|
||||
@Override
|
||||
public String getSourceTypeName() {
|
||||
return "file";
|
||||
|
@ -11,5 +10,4 @@ public class BasicFileFetcher extends BasePackFetcher {
|
|||
public String getDownloadUrl(String baseUrl) {
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,27 @@
|
|||
package io.gitlab.jfronny.resclone.fetchers;
|
||||
|
||||
import io.gitlab.jfronny.resclone.Resclone;
|
||||
import io.gitlab.jfronny.resclone.data.CfAddon;
|
||||
import io.gitlab.jfronny.resclone.util.UrlUtils;
|
||||
import net.minecraft.MinecraftVersion;
|
||||
import io.gitlab.jfronny.commons.*;
|
||||
import io.gitlab.jfronny.resclone.*;
|
||||
import io.gitlab.jfronny.resclone.data.curseforge.*;
|
||||
import net.minecraft.*;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class CurseforgeFetcher extends BasePackFetcher {
|
||||
// So you found the API key.
|
||||
// Please be aware that CurseForge requires you to change this if you make any kind of derivative work
|
||||
// Creating your own API key is relatively simple, so please don't abuse this
|
||||
private static final String API_KEY = new String(unsalt(new byte[] {
|
||||
-30, 50, -60, -121, 62, -31, 35, 17, 16, -53,
|
||||
-53, -88, 21, -21, 15, -105, -115, -108, 114, -50,
|
||||
-49, -4, 56, -65, -70, 108, -65, -3, -55, -4,
|
||||
36, -86, -40, 116, 71, -5, 75, -9, -43, 4,
|
||||
91, -91, -29, 40, 66, 87, -80, -74, 71, 41,
|
||||
76, -96, 108, -61, -113, 118, 7, -39, -116, -120
|
||||
}, 1024));
|
||||
|
||||
@Override
|
||||
public String getSourceTypeName() {
|
||||
return "curseforge";
|
||||
|
@ -17,25 +30,26 @@ public class CurseforgeFetcher extends BasePackFetcher {
|
|||
@Override
|
||||
public String getDownloadUrl(String baseUrl) throws Exception {
|
||||
try {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'");
|
||||
GetModResponse response = GET(baseUrl, GetModResponse.class);
|
||||
if (!response.data.allowModDistribution)
|
||||
throw new Exception("The author of " + baseUrl + " disabled access to this pack outside of the curseforge launcher");
|
||||
|
||||
String version = MinecraftVersion.CURRENT.getName();
|
||||
|
||||
CfAddon latest = null;
|
||||
GetModFilesResponse.Data latest = null;
|
||||
Date latestDate = null;
|
||||
boolean foundMatchingVersion = false;
|
||||
|
||||
for (CfAddon addon : UrlUtils.readJsonFromURLSet("https://addons-ecs.forgesvc.net/api/v2/addon/" + baseUrl + "/files", CfAddon.class)) {
|
||||
Date d = df.parse(addon.fileDate);
|
||||
if (foundMatchingVersion && !addon.gameVersion.contains(version))
|
||||
for (GetModFilesResponse.Data addon : GET(baseUrl + "/files", GetModFilesResponse.class).data) {
|
||||
if (foundMatchingVersion && !addon.gameVersions.contains(version))
|
||||
continue;
|
||||
if (!foundMatchingVersion && addon.gameVersion.contains(version)) {
|
||||
if (!foundMatchingVersion && addon.gameVersions.contains(version)) {
|
||||
foundMatchingVersion = true;
|
||||
latest = null;
|
||||
}
|
||||
if (latest == null || d.after(latestDate)) {
|
||||
if (latest == null || addon.fileDate.after(latestDate)) {
|
||||
latest = addon;
|
||||
latestDate = d;
|
||||
latestDate = addon.fileDate;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,4 +60,17 @@ public class CurseforgeFetcher extends BasePackFetcher {
|
|||
throw new Exception("Could not get CF download for " + baseUrl, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> T GET(String suffix, Class<T> klazz) throws URISyntaxException, IOException {
|
||||
return HttpUtils.get("https://api.curseforge.com/v1/mods/" + suffix).header("x-api-key", API_KEY).sendSerialized(klazz);
|
||||
}
|
||||
|
||||
private static byte[] unsalt(byte[] data, int salt) {
|
||||
byte[] result = new byte[data.length];
|
||||
new Random(salt).nextBytes(result);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
result[i] ^= data[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package io.gitlab.jfronny.resclone.fetchers;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.gitlab.jfronny.commons.*;
|
||||
import io.gitlab.jfronny.resclone.Resclone;
|
||||
import io.gitlab.jfronny.resclone.util.UrlUtils;
|
||||
import io.gitlab.jfronny.resclone.data.github.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
|
||||
public class GitHubFetcher extends BasePackFetcher {
|
||||
@Override
|
||||
|
@ -39,20 +39,19 @@ public class GitHubFetcher extends BasePackFetcher {
|
|||
//"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);
|
||||
Release latestRelease = HttpUtils.get("https://api.github.com/repos/" + parts[0] + "/" + parts[1] + "/releases/latest").sendSerialized(Release.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();
|
||||
for (Release.Asset asset : latestRelease.assets) {
|
||||
if ("application/x-zip-compressed".equals(asset.content_type) || asset.name.endsWith(".zip")) {
|
||||
res = asset.browser_download_url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Resclone.LOGGER.info("Getting from latest release.");
|
||||
|
||||
if (res == null) return latestRelease.get("zipball_url").getAsString();
|
||||
if (res == null) return latestRelease.zipball_url;
|
||||
else return res;
|
||||
|
||||
} catch (Throwable e) {
|
||||
|
@ -74,8 +73,8 @@ public class GitHubFetcher extends BasePackFetcher {
|
|||
private String getFromBranch(String repo, @Nullable String branch) {
|
||||
if (branch == null) {
|
||||
try {
|
||||
branch = UrlUtils.readJsonFromURL("https://api.github.com/repos/" + repo, JsonObject.class).get("default_branch").getAsString();
|
||||
} catch (IOException e) {
|
||||
branch = HttpUtils.get("https://api.github.com/repos/" + repo).<Repository>sendSerialized(Repository.class).default_branch;
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
Resclone.LOGGER.error("Failed to fetch branch for " + repo + ". Choosing \"main\"", e);
|
||||
branch = "main";
|
||||
}
|
||||
|
@ -88,4 +87,4 @@ public class GitHubFetcher extends BasePackFetcher {
|
|||
Resclone.LOGGER.info("Getting from tag " + tag + ".");
|
||||
return "https://codeload.github.com/" + repo + "/legacy.zip/refs/tags/" + tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@ public class FileResourcePackProviderMixin {
|
|||
|
||||
@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) {
|
||||
for (PackMetaLoaded meta : Resclone.downloadedPacks) {
|
||||
for (PackMetaLoaded meta : Resclone.DOWNLOADED_PACKS) {
|
||||
ResourcePackProfile resourcePackProfile = ResourcePackProfile.of(
|
||||
"resclone/" + meta.name,
|
||||
meta.forceEnable,
|
||||
() -> new RescloneResourcePack(meta.zipPath.toFile(), meta.name),
|
||||
"resclone/" + meta.name(),
|
||||
meta.forceEnable(),
|
||||
() -> new RescloneResourcePack(meta.zipPath().toFile(), meta.name()),
|
||||
factory,
|
||||
ResourcePackProfile.InsertionPosition.TOP,
|
||||
this.source
|
||||
|
@ -35,4 +35,4 @@ public class FileResourcePackProviderMixin {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ public abstract class GameOptionsMixin {
|
|||
|
||||
@Inject(at = @At("TAIL"), method = "load()V")
|
||||
public void load(CallbackInfo ci) {
|
||||
for (PackMetaLoaded meta : Resclone.newPacks) {
|
||||
Resclone.LOGGER.info(Resclone.MOD_ID + "/" + meta.name);
|
||||
resourcePacks.add(Resclone.MOD_ID + "/" + meta.name);
|
||||
for (PackMetaLoaded meta : Resclone.NEW_PACKS) {
|
||||
Resclone.LOGGER.info(Resclone.MOD_ID + "/" + meta.name());
|
||||
resourcePacks.add(Resclone.MOD_ID + "/" + meta.name());
|
||||
}
|
||||
if (!Resclone.newPacks.isEmpty())
|
||||
if (!Resclone.NEW_PACKS.isEmpty())
|
||||
write();
|
||||
Resclone.newPacks.clear();
|
||||
Resclone.NEW_PACKS.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.gitlab.jfronny.resclone.processors;
|
||||
|
||||
import io.gitlab.jfronny.resclone.*;
|
||||
import io.gitlab.jfronny.resclone.api.PackProcessor;
|
||||
import io.gitlab.jfronny.resclone.util.io.PathPruneVisitor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
@ -12,7 +13,6 @@ import java.nio.file.Files;
|
|||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
public class PruneVanillaProcessor implements PackProcessor {
|
||||
|
||||
@Override
|
||||
public void process(FileSystem p) throws Exception {
|
||||
ClassLoader cl = MinecraftClient.class.getClassLoader();
|
||||
|
@ -29,7 +29,7 @@ public class PruneVanillaProcessor implements PackProcessor {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Resclone.LOGGER.error("Could not prune unchanged assets", e);
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
|
@ -38,5 +38,4 @@ public class PruneVanillaProcessor implements PackProcessor {
|
|||
throw new Exception("Could not prune vanilla files", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.gitlab.jfronny.resclone.processors;
|
||||
|
||||
import io.gitlab.jfronny.resclone.*;
|
||||
import io.gitlab.jfronny.resclone.api.PackProcessor;
|
||||
import io.gitlab.jfronny.resclone.util.io.PathPruneVisitor;
|
||||
|
||||
|
@ -10,7 +11,6 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
|
||||
public class RemoveEmptyProcessor implements PackProcessor {
|
||||
|
||||
@Override
|
||||
public void process(FileSystem p) throws Exception {
|
||||
if (Files.exists(p.getPath("/assets"))) {
|
||||
|
@ -20,7 +20,7 @@ public class RemoveEmptyProcessor implements PackProcessor {
|
|||
try (DirectoryStream<Path> paths = Files.newDirectoryStream(s)) {
|
||||
return !paths.iterator().hasNext();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Resclone.LOGGER.error("Could not check whether directory has entries", e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -30,5 +30,4 @@ public class RemoveEmptyProcessor implements PackProcessor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.io.IOException;
|
|||
import java.nio.file.*;
|
||||
|
||||
public class RootPathProcessor implements PackProcessor {
|
||||
|
||||
@Override
|
||||
public void process(FileSystem p) throws Exception {
|
||||
if (!Files.exists(p.getPath("/pack.mcmeta"))) {
|
||||
|
@ -25,5 +24,4 @@ public class RootPathProcessor implements PackProcessor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.gitlab.jfronny.resclone.util;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.*;
|
||||
import io.gitlab.jfronny.resclone.Resclone;
|
||||
import io.gitlab.jfronny.resclone.api.RescloneApi;
|
||||
import io.gitlab.jfronny.resclone.data.PackMetaUnloaded;
|
||||
|
@ -23,23 +24,23 @@ public class ConfigLoader {
|
|||
text.append("\r\n");
|
||||
text.append(s);
|
||||
}
|
||||
Set<PackMetaUnloaded> data = Resclone.gson.fromJson(text.toString(), new TypeToken<Set<PackMetaUnloaded>>(){}.getType());
|
||||
Set<PackMetaUnloaded> data = GsonHolder.getGson().fromJson(text.toString(), new TypeToken<Set<PackMetaUnloaded>>(){}.getType());
|
||||
for (PackMetaUnloaded meta : data) {
|
||||
api.addPack(meta.fetcher, meta.source, meta.name, meta.forceDownload, meta.forceEnable);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Resclone.LOGGER.error("Could not load config", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void save(RescloneApi api, Set<PackMetaUnloaded> data) {
|
||||
Path configPath = api.getConfigPath().resolve("config.json");
|
||||
Set<String> text = new HashSet<>();
|
||||
text.add(Resclone.gson.toJson(data));
|
||||
text.add(GsonHolder.getGson().toJson(data));
|
||||
try {
|
||||
Files.write(configPath, text);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Resclone.LOGGER.error("Could not write config", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package io.gitlab.jfronny.resclone.util;
|
||||
|
||||
import io.gitlab.jfronny.resclone.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
|
@ -8,7 +10,6 @@ import java.nio.file.Path;
|
|||
import java.util.Properties;
|
||||
|
||||
public class PackUrlCache {
|
||||
|
||||
private final Path file;
|
||||
Properties properties = new Properties();
|
||||
|
||||
|
@ -18,7 +19,7 @@ public class PackUrlCache {
|
|||
try (BufferedReader r = Files.newBufferedReader(file)) {
|
||||
properties.load(r);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Resclone.LOGGER.error("Could not load pack URL cache");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +28,7 @@ public class PackUrlCache {
|
|||
try (BufferedWriter w = Files.newBufferedWriter(file)) {
|
||||
properties.store(w, "This is an internal file used for offline pack loading, do not edit");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Resclone.LOGGER.error("Could not write pack URL cache");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,5 +43,4 @@ public class PackUrlCache {
|
|||
public void set(String key, String value) {
|
||||
properties.setProperty(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
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());
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,6 @@ import java.nio.file.*;
|
|||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
|
||||
public class MoveDirVisitor extends SimpleFileVisitor<Path> {
|
||||
|
||||
private final Path fromPath;
|
||||
private final Path toPath;
|
||||
private final CopyOption copyOption;
|
||||
|
@ -36,5 +35,4 @@ public class MoveDirVisitor extends SimpleFileVisitor<Path> {
|
|||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@ import java.nio.file.attribute.BasicFileAttributes;
|
|||
import java.util.function.Predicate;
|
||||
|
||||
public class PathPruneVisitor extends SimpleFileVisitor<Path> {
|
||||
|
||||
Predicate<Path> removalSelector;
|
||||
private final Predicate<Path> removalSelector;
|
||||
|
||||
public PathPruneVisitor(Predicate<Path> removalSelector) {
|
||||
this.removalSelector = removalSelector;
|
||||
|
@ -27,5 +26,4 @@ public class PathPruneVisitor extends SimpleFileVisitor<Path> {
|
|||
if (removalSelector.test(dir)) Files.walkFileTree(dir, new RemoveDirVisitor());
|
||||
return super.postVisitDirectory(dir, exc);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.nio.file.SimpleFileVisitor;
|
|||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
|
||||
public class RemoveDirVisitor extends SimpleFileVisitor<Path> {
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
Files.delete(file);
|
||||
|
@ -20,5 +19,4 @@ public class RemoveDirVisitor extends SimpleFileVisitor<Path> {
|
|||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue