Modernize, support CfCore and update for 1.19-rc2

This commit is contained in:
Johannes Frohnmeyer 2022-06-05 17:40:50 +02:00
parent 906a0a4d74
commit f699ab3bf3
Signed by: Johannes
GPG Key ID: E76429612C2929F4
32 changed files with 197 additions and 227 deletions

View File

@ -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"
}

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -20,4 +20,4 @@ public class RescloneEntryDefault implements RescloneEntry {
api.addProcessor(new PruneVanillaProcessor());
ConfigLoader.load(api);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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) { }
}

View File

@ -4,4 +4,4 @@ import java.nio.file.FileSystem;
public interface PackProcessor {
void process(FileSystem p) throws Exception;
}
}

View File

@ -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();
}
}

View File

@ -2,4 +2,4 @@ package io.gitlab.jfronny.resclone.api;
public interface RescloneEntry {
void init(RescloneApi api) throws Exception;
}
}

View File

@ -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;
}

View File

@ -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) {
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -0,0 +1,9 @@
package io.gitlab.jfronny.resclone.data.curseforge;
public class GetModResponse {
public Data data;
public static class Data {
public Boolean allowModDistribution;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,5 @@
package io.gitlab.jfronny.resclone.data.github;
public class Repository {
public String default_branch;
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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 {
}
}
}
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}
}

View File

@ -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 {
}
}
}
}
}

View File

@ -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 {
}
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}