diff --git a/.gitignore b/.gitignore index 67bcc2f..0b5cc2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,35 @@ +# gradle + .gradle/ build/ +out/ +classes/ + +# eclipse + +*.launch + +# idea + +.idea/ +*.iml +*.ipr +*.iws + +# vscode + +.settings/ +.vscode/ +.vs/ +bin/ +.classpath +.project + +# macos + +*.DS_Store + +# fabric + +run/ +remappedSrc/ \ No newline at end of file diff --git a/README.md b/README.md index 2f28bda..3519a25 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ In your build.gradle, at the very top (before `plugins`), add this: ``` buildscript { dependencies { - classpath 'de.guntram.mcmod:crowdin-translate:1.2' + classpath 'de.guntram.mcmod:crowdin-translate:1.5+1.21' } repositories { maven { @@ -53,7 +53,7 @@ buildscript { } ``` -and somewhere later (after plugins) add: +Then, somewhere later (after plugins) add: ``` apply plugin: 'de.guntram.mcmod.crowdin-translate' @@ -91,8 +91,8 @@ repositories { } } dependencies { - modImplementation "de.guntram.mcmod:crowdin-translate:1.2" - include "de.guntram.mcmod:crowdin-translate:1.2" + modImplementation "de.guntram.mcmod:crowdin-translate:1.5+1.21" + include "de.guntram.mcmod:crowdin-translate:1.5+1.21" } ``` @@ -126,20 +126,31 @@ This will download the translations from `https://crowdin.com/project/projectname` to `assets/modid/lang`. +### What if I have the translation files for several mods in the same crowdin project? +Since version 1.3, you can override the translation source name that +crowdin-translate checks for. So, if your mods are named foo, bar, and baz, +you can have one single crowdin project that has them all, and have file names +`foo.json`, `bar.json` and `thisisnotbaz.json` for your source. -### Getting started -(this needs some redoing) -- Create an account on CrowdIn (https://crowdin.com) -- Optional but recommended: apply for a open source membership so you can start multiple projects, for free -- Create a project. This will ask for a project name, and a project address. -If possible, select your address so the identifier matches your mod id -(the mod `foobar` should have `https://crowdin.com/project/foobar`). -- Switch the source language from English to English, United States. This is not -100% neccesary, but will make things easier, especially if your original json -file is named `en_us.json`. -- Add the target languages you want to use. (In a future version of CrowdinTranslate, -there will be an easy way to consistently set the languages for a collection -of mods) -- Once your project is created, upload your en_us.json. Then, do some translations, -or get people to do that for you. +Assuming your crowdin project name is `allmymods`, +adjust the above use cases like this: + +* manual usage: +``` +java -jar crowdintranslate-.jar allmymods foo foo +java -jar crowdintranslate-.jar allmymods bar bar +java -jar crowdintranslate-.jar allmymods baz thisisnotbaz +``` + +* usage in gradle: add a 'jsonSourceName' parameter + +``` +crowdintranslate.jsonSourceName = 'thisisnotbaz' +``` + +* usage in your `ClientModInitializer`: use the 3 argument call: + +``` +CrowdinTranslate.downloadTranslations("allmymods", "baz", "thisisnotbaz"); +``` diff --git a/build.gradle b/build.gradle index 7b2246c..6353aa8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,58 +1,52 @@ plugins { - id 'fabric-loom' version '0.4-SNAPSHOT' + id 'fabric-loom' version '1.6.+' id 'java-gradle-plugin' + id 'maven-publish' } -apply plugin: 'maven' - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 +sourceCompatibility = 21 +targetCompatibility = 21 archivesBaseName = "crowdin-translate" -version = "1.3-pre1-hugman" +version = "1.5+1.21" -minecraft { - refmapName = "crowdin-translate-refmap.json"; +loom { + mixin.defaultRefmapName = "crowdin-translate-refmap.json" } processResources { - inputs.property "version", project.version + inputs.property "version", project.version - from(sourceSets.main.resources.srcDirs) { - include "fabric.mod.json" - expand "version": project.version - } - from(sourceSets.main.resources.srcDirs) { - exclude "fabric.mod.json" - } + filesMatching("fabric.mod.json") { + expand "version": project.version + } } // These are, actually, not even used in this project. // They are only included to make loom happy. // Use old versions intentionally to make this work with a broad range of MCs. dependencies { - minecraft "com.mojang:minecraft:1.15.2" - mappings "net.fabricmc:yarn:1.15.2+build.7:v2" - modImplementation "net.fabricmc:fabric-loader:0.7.2+build.174" + minecraft "com.mojang:minecraft:1.21" + mappings "net.fabricmc:yarn:1.21+build.2" + modImplementation "net.fabricmc:fabric-loader:0.15.11" + modRuntimeOnly fabricApi.module("fabric-resource-loader-v0", "0.100.1+1.21") } // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task // if it is present. // If you remove this task, sources will not be generated. -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource +java { + withSourcesJar() } jar { - from "LICENSE" + from "LICENSE" manifest { attributes( 'Main-Class': 'de.guntram.mcmod.crowdintranslate.CrowdinTranslate' ) } - } gradlePlugin { @@ -65,14 +59,19 @@ gradlePlugin { } group = "de.guntram.mcmod" -uploadArchives { +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } repositories { - mavenDeployer { - repository(url: "file://localhost/tmp/mymavenrepo") + maven { + url = "file://tmp/mymavenrepo" } } } -task publish(dependsOn: uploadArchives, type: Exec) { +task mypublish(dependsOn: publish, type: Exec) { commandLine "rsync", "-av", "/tmp/mymavenrepo/", "maven@minecraft.guntram.de:/var/www/html/maven/" } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..15c32df --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx2G +action.custom-1=publish +action.custom-1.args=--configure-on-demand -w -x check publish diff --git a/settings.gradle b/settings.gradle index 5b60df3..e17db3c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,3 +8,5 @@ pluginManagement { gradlePluginPortal() } } + +rootProject.name = 'crowdin-translate' diff --git a/src/main/java/de/guntram/mcmod/crowdintranslate/CTResourcePack.java b/src/main/java/de/guntram/mcmod/crowdintranslate/CTResourcePack.java index f4a2bf4..1ac39ae 100644 --- a/src/main/java/de/guntram/mcmod/crowdintranslate/CTResourcePack.java +++ b/src/main/java/de/guntram/mcmod/crowdintranslate/CTResourcePack.java @@ -1,16 +1,17 @@ package de.guntram.mcmod.crowdintranslate; +import com.mojang.logging.LogUtils; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.*; -import java.util.function.Predicate; import java.util.stream.Collectors; -import net.minecraft.resource.ResourcePack; -import net.minecraft.resource.ResourceType; + +import net.minecraft.resource.*; import net.minecraft.resource.metadata.ResourceMetadataReader; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import org.slf4j.Logger; /** * Code taken from LambdAurora, oral permission on Discord on 2020-10-04 @@ -18,7 +19,8 @@ public class CTResourcePack implements ResourcePack { - private final List namespaces = new ArrayList<>(); + private final List namespaces = new ArrayList<>(); + private static final Logger LOGGER = LogUtils.getLogger(); public CTResourcePack() { for (String s: CrowdinTranslate.registeredMods()) { @@ -37,40 +39,40 @@ public boolean put(String resource) } @Override - public InputStream openRoot(String fileName) throws IOException + public InputSupplier openRoot(String ... fileName) { - File file = new File(CrowdinTranslate.getRootDir(), fileName); - return new FileInputStream(file); + File file = new File(CrowdinTranslate.getRootDir(), fileName[0]); + if (file.exists()) { + return InputSupplier.create(file.toPath()); + } else { + return null; + } } @Override - public InputStream open(ResourceType type, Identifier id) throws IOException + public InputSupplier open(ResourceType type, Identifier id) { - if (type == ResourceType.SERVER_DATA) throw new IOException("Reading server data from MCPatcherPatcher client resource pack"); return this.openRoot(type.getDirectory() + "/" + id.getNamespace() + "/" + id.getPath()); } @Override - public Collection findResources(ResourceType type, String namespace, String prefix, int maxDepth, Predicate pathFilter) - { - if (type == ResourceType.SERVER_DATA) return Collections.emptyList(); + public void findResources(ResourceType type, String namespace, String prefix, ResourcePack.ResultConsumer consumer) { String start = CrowdinTranslate.getRootDir()+"/assets/" + namespace + "/" + prefix; String[] files = new File(start).list(); + //LOGGER.info("finding resources for {} {}", namespace, prefix); if (files == null || files.length == 0) { - return Collections.EMPTY_LIST; + //LOGGER.info("found nothing"); + return; } - List result = Arrays.asList(files) + //LOGGER.info("found {} files, first is {}", files.length, files[0]); + List resultList = Arrays.asList(files) .stream() .map(CTResourcePack::fromPath) .collect(Collectors.toList()); - return result; - } - - @Override - public boolean contains(ResourceType type, Identifier id) - { - String path = CrowdinTranslate.getRootDir() + "/" + type.getDirectory() + "/" + id.getNamespace() + "/" + id.getPath(); - return new File(path).exists(); + for(Identifier result: resultList) { + //LOGGER.info("sending {} to consumer", result.toString()); + consumer.accept(result, open(type, result)); + } } @Override @@ -86,10 +88,15 @@ public T parseMetadata(ResourceMetadataReader metaReader) throws IOExcept } @Override + public ResourcePackInfo getInfo() { + return new ResourcePackInfo("CrowdinTranslate internal Resource Pack", Text.of("CrowdinTranslate internal Resource Pack"), ResourcePackSource.BUILTIN, Optional.empty()); + } + + /*@Override public String getName() { return "CrowdinTranslate internal Resource Pack"; - } + }*/ @Override public void close() @@ -101,6 +108,6 @@ private static Identifier fromPath(String path) if (path.startsWith("assets/")) path = path.substring("assets/".length()); String[] split = path.split("/", 2); - return new Identifier(split[0], split[1]); + return Identifier.of(split[0], split[1]); } } diff --git a/src/main/java/de/guntram/mcmod/crowdintranslate/ClientInit.java b/src/main/java/de/guntram/mcmod/crowdintranslate/ClientInit.java new file mode 100644 index 0000000..87d09a3 --- /dev/null +++ b/src/main/java/de/guntram/mcmod/crowdintranslate/ClientInit.java @@ -0,0 +1,103 @@ +package de.guntram.mcmod.crowdintranslate; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.metadata.CustomValue; + +import java.util.Optional; +import java.util.function.Function; + +import static de.guntram.mcmod.crowdintranslate.ClientInit.Keys.*; +import static de.guntram.mcmod.crowdintranslate.CrowdinTranslate.*; +import static net.fabricmc.loader.api.metadata.CustomValue.CvType.*; + +public class ClientInit implements ClientModInitializer { + private static String getRequiredString(CustomValue.CvObject object, String key, String modId) { + return getValue(object, key, STRING, CustomValue::getAsString, modId, true).orElse(null); + } + + private static Optional getOptionalValue( + CustomValue.CvObject object, String key, + CustomValue.CvType type, Function getter, + String modId + ) { + return getValue(object, key, type, getter, modId, false); + } + + private static Optional getValue( + CustomValue.CvObject object, String key, + CustomValue.CvType type, Function getter, + String modId, boolean logMissing + ) { + final var value = object.get(key); + if (value == null) { + if (logMissing) LOGGER.error( + "Missing \"{}\" key in object for \"" + NAME + "\" entrypoint in " + + "fabric.mod.json of mod: {}", + key, modId + ); + + return Optional.empty(); + } else { + final var valueType = value.getType(); + if (valueType == type) return Optional.of(getter.apply(value)); + else { + LOGGER.error( + "Invalid type for \"{}\" key in object for \"" + NAME + "\" entrypoint in " + + "fabric.mod.json of mod: {}\nExpected {}; found {}", + key, modId, type, valueType + ); + + return Optional.empty(); + } + } + } + + @Override + public void onInitializeClient() { + for (ModContainer container : FabricLoader.getInstance().getAllMods()) { + final var metadata = container.getMetadata(); + final var customValue = metadata.getCustomValue(NAME); + if (customValue == null) continue; + + final var type = customValue.getType(); + final String modId = metadata.getId(); + switch (type) { + case BOOLEAN -> { if (customValue.getAsBoolean()) downloadTranslations(modId); } + case STRING -> downloadTranslations(customValue.getAsString()); + case OBJECT -> { + final var object = customValue.getAsObject(); + + final var crowdinProjectName = getRequiredString(object, CROWDIN_PROJECT_NAME, modId); + if (crowdinProjectName == null) return; + + final var minecraftProjectName = getRequiredString(object, MINECRAFT_PROJECT_NAME, modId); + if (minecraftProjectName == null) return; + + final var verbose = + getOptionalValue(object, VERBOSE, BOOLEAN, CustomValue::getAsBoolean, modId) + .orElse(false); + + final var sourcefileOverride = + getOptionalValue(object, SOURCE_FILE_OVERRIDE, STRING, CustomValue::getAsString, modId) + .orElse(null); + + downloadTranslations(crowdinProjectName, minecraftProjectName, sourcefileOverride, verbose); + } + default -> LOGGER.error( + "Invalid type for \"" + NAME + "\" entrypoint in " + + "fabric.mod.json of mod: {}\nExpected {}, {}, or {}; found {}", + modId, BOOLEAN, STRING, OBJECT, type + ); + } + } + } + + public interface Keys { + String CROWDIN_PROJECT_NAME = "crowdinProjectName"; + String MINECRAFT_PROJECT_NAME = "minecraftProjectName"; + String SOURCE_FILE_OVERRIDE = "sourceFileOverride"; + String VERBOSE = "verbose"; + } +} diff --git a/src/main/java/de/guntram/mcmod/crowdintranslate/CrowdinTranslate.java b/src/main/java/de/guntram/mcmod/crowdintranslate/CrowdinTranslate.java index db7b7bc..f2297fe 100644 --- a/src/main/java/de/guntram/mcmod/crowdintranslate/CrowdinTranslate.java +++ b/src/main/java/de/guntram/mcmod/crowdintranslate/CrowdinTranslate.java @@ -1,8 +1,14 @@ package de.guntram.mcmod.crowdintranslate; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.BufferedReader; import java.io.Closeable; import java.io.File; import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -16,46 +22,144 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; + public class CrowdinTranslate extends Thread { - + public static final String NAME = "crowdin-translate"; + public static final Logger LOGGER = LogManager.getLogger(); + private static final Map mcCodetoCrowdinCode; /* The directory to download to. This is used in the mod; main will overwrite this. */ private static String rootDir = "ModTranslations"; private static boolean thisIsAMod = true; private static final Set registeredMods; + enum Tristate { UNKNOWN,YES,NO }; + private static Tristate downloadsAllowed = Tristate.UNKNOWN; static { mcCodetoCrowdinCode = new HashMap<>(); registeredMods = new HashSet<>(); + add("af_za", "af"); + add("ar_sa", "ar"); + add("ast_es", "ast"); + add("az_az", "az"); + add("ba_ru", "ba"); + //add("bar", "bar"); // Bavaria + add("be_by", "be"); + add("bg_bg", "bg"); + add("br_fr", "br-FR"); + //add("brb", "brb"); // Brabantian + add("bs_ba", "bs"); + add("ca_es", "ca"); add("cs_cz", "cs"); + add("cy_gb", "cy"); + add("da_dk", "da"); + add("de_at", "de-AT,de"); + add("de_ch", "de-CH,de"); add("de_de", "de"); add("el_gr", "el"); - add("es_ar", "es-ES"); - add("es_cl", "es-ES"); - add("es_ec", "es-ES"); + add("en_au", "en-AU,en-GB,en-US"); + add("en_ca", "en-CA,en-GB,en-US"); + add("en_gb", "en-GB,en-US"); + add("en_nz", "en-NZ,en-GB,en-US"); + add("en_pt", "en-PT,en-GB,en-US"); + add("en_ud", "en-UD,en-GB,en-US"); + add("en_us", "en-US"); + //add("enp", "enp"); // Anglish + add("en_ws", "en-WS"); + add("en_7s", "en-PT"); + add("en_ud", "en-UD"); + add("eo_uy", "eo"); + add("es_ar", "es-AR,es-ES"); + add("es_cl", "es-CL,es-ES"); + add("es_ec", "es-EC,es-ES"); add("es_es", "es-ES"); - add("es_mx", "es-ES"); - add("es_uy", "es-ES"); - add("es_ve", "es-ES"); + add("es_mx", "es-MX,es-ES"); + add("es_uy", "es-UY,es-ES"); + add("es_ve", "es-VE,es-ES"); + //add("esan", "esan"); // Andalusian add("et_ee", "et"); + add("eu_es", "eu"); + add("fa_ir", "fa"); add("fi_fi", "fi"); + add("fil_ph", "fil"); + add("fo_fo", "fo"); + add("fr_ca", "fr-CA,fr"); add("fr_fr", "fr"); + add("fra_de", "fra-DE"); + add("fy_nl", "fy-NL"); + add("ga_ie", "ga-IE"); + add("gd_gb", "gd"); + add("gl_es", "gl"); + add("haw_us", "haw"); add("he_il", "he"); + add("hi_in", "hi"); + add("hr_hr", "hr"); + add("hu_hu", "hu"); + add("hy_am", "hy-AM"); + add("id_id", "id"); + add("ig_ng", "ig"); + add("io_en", "ido"); + add("is_is", "is"); + //add("isv", "isv"); // Interslavic add("it_it", "it"); add("ja_jp", "ja"); + add("jbo_en", "jbo"); + add("ka_ge", "ka"); + add("kk_kz", "kk"); + add("kn_in", "kn"); add("ko_kr", "ko"); + //add("ksh", "ksh"); // Ripuarian + add("kw_gb", "kw"); + add("la_la", "la-LA"); + add("lb_lu", "lb"); + add("li_li", "li"); + add("lol_us", "lol"); + add("lt_lt", "lt"); + add("lv_lv", "lv"); + //add("lzh", "lzh"); // Classical Chinese + add("mi_NZ", "mi"); + add("mk_mk", "mk"); + add("mn_mn", "mn"); + add("ms_my", "ms"); + add("mt_mt", "mt"); + add("nds_de", "nds"); + add("nl_be", "nl-BE,nl"); add("nl_nl", "nl"); - add("no_no", "no"); + add("nn_no", "nn-NO,no"); + add("no_no", "no,nb"); + add("oc_fr", "oc"); + //add("ovd", "ovd"); // Elfdalian add("pl_pl", "pl"); - add("pt_br", "pt-PT"); - add("pt_pt", "pt-PT"); + add("pt_br", "pt-BR,pt-PT"); + add("pt_pt", "pt-PT,pt-BR"); + add("qya_aa", "qya-AA"); add("ro_ro", "ro"); + //add("rpr", "rpr"); // Russian (pre-revolutionary) add("ru_ru", "ru"); + add("se_no", "se"); + add("sk_sk", "sk"); + add("sl_si", "sl"); + add("so_so", "so"); + add("sq_al", "sq"); add("sr_sp", "sr"); add("sv_se", "sv-SE"); + //add("sxu", "sxu"); // Upper Saxon German + //add("szl", "szl"); // Silesian + add("ta_in", "ta"); + add("th_th", "th"); + add("tl_ph", "tl"); + add("tlh_aa", "tlh-AA"); add("tr_tr", "tr"); - add("zh_cn", "zh-CN"); + add("tt_ru", "tt-RU"); + add("uk_ua", "uk"); + add("val_es", "val-ES"); + add("vec_it", "vec"); + add("vi_vn", "vi"); + add("yi_de", "yi"); + add("yo_ng", "yo"); + add("zh_cn", "zh-CN,zh-HK"); + add("zh_hk", "zh-HK,zh-CN"); add("zh_tw", "zh-TW"); } @@ -75,18 +179,22 @@ public static void downloadTranslations(String crowdinProjectName, String minecr downloadTranslations(crowdinProjectName, minecraftProjectName, null, verbose); } - public static void downloadTranslations(String crowdinProjectName, String minecraftProjectName, String sourcefileOverride, boolean verbose) { + public static void downloadTranslations(String crowdinProjectName, String minecraftProjectName, String sourceFileOverride) { + downloadTranslations(crowdinProjectName, minecraftProjectName, sourceFileOverride, false); + } + + public static void downloadTranslations(String crowdinProjectName, String minecraftProjectName, String sourceFileOverride, boolean verbose) { registeredMods.add(minecraftProjectName); - if (thisIsAMod && projectDownloadedRecently(minecraftProjectName)) { + if (thisIsAMod && ( !downloadsAllowed() || projectDownloadedRecently(minecraftProjectName))) { return; } CrowdinTranslate runner = new CrowdinTranslate(crowdinProjectName, minecraftProjectName); if (verbose) { runner.setVerbose(); } - if (sourcefileOverride != null) { - runner.setSourceFileOverride(sourcefileOverride); + if (sourceFileOverride != null) { + runner.setSourceFileOverride(sourceFileOverride); } runner.start(); if (!thisIsAMod) { @@ -97,6 +205,44 @@ public static void downloadTranslations(String crowdinProjectName, String minecr } } } + + // This is a bit of a stretch, but the method gets called in fabric mod + // context only. We don't want to add a dependency on a whole json library + // or anything, so we just check if there's a config/crowdin.txt file. + // If there is, and it contains "download=no" or "download=false" or "download=0", + // we don't download anything. + // This should be synchronized in case Fabric ever initializes two mods at + // once; they shouldn't access the file at the same time. + private static synchronized boolean downloadsAllowed() { + if (downloadsAllowed != Tristate.UNKNOWN) { + return downloadsAllowed == Tristate.YES; + } + File file = new File("config/crowdin.txt"); + if (file.exists()) { + try (FileReader fr = new FileReader(file); + BufferedReader br = new BufferedReader(fr)) + { + String line; + while ((line = br.readLine()) != null) { + if (line.startsWith("download=")) { + String val = line.substring(9); + if ("0".equals(val) || "false".equalsIgnoreCase(val) || "no".equalsIgnoreCase(val)) { + downloadsAllowed=Tristate.NO; + return false; + } + } + } + } catch (IOException ex) { + } + } else { + try (FileWriter fw = new FileWriter(file)) { + fw.append("#Change this to no to prevent mod translation downloads\ndownload=yes\n"); + } catch (IOException ex) { + } + } + downloadsAllowed=Tristate.YES; + return true; + } private static void forceClose(Closeable c) { try { @@ -153,13 +299,17 @@ public void run() { new File(assetDir).mkdirs(); for (Map.Entry entry: mcCodetoCrowdinCode.entrySet()) { - byte[] buffer = translations.get(entry.getValue()); - if (buffer != null) { - String filePath = assetDir+File.separatorChar+entry.getKey()+".json"; - if (verbose) { - System.out.println("writing "+buffer.length+" bytes from \""+entry.getValue()+"\" to MC file "+filePath); + String[] sourcesByPreference = entry.getValue().split(","); + for (String attemptingSource: sourcesByPreference) { + byte[] buffer = translations.get(attemptingSource); + if (buffer != null) { + String filePath = assetDir+File.separatorChar+entry.getKey()+".json"; + if (verbose) { + System.out.println("writing "+buffer.length+" bytes from \""+attemptingSource+"\" to MC file "+filePath); + } + saveBufferToJsonFile(buffer, filePath); + break; } - saveBufferToJsonFile(buffer, filePath); } } if (thisIsAMod) { @@ -238,6 +388,8 @@ private void saveBufferToJsonFile(byte[] buffer, String filename) { stream.write(buffer); } catch (IOException ex) { System.err.println("failed to write "+filename); + System.err.println("absolute path is "+file.getAbsolutePath()); + ex.printStackTrace(System.err); } } diff --git a/src/main/java/de/guntram/mcmod/crowdintranslate/GradlePlugin/DownloadTask.java b/src/main/java/de/guntram/mcmod/crowdintranslate/GradlePlugin/DownloadTask.java index 059c248..3e0832a 100644 --- a/src/main/java/de/guntram/mcmod/crowdintranslate/GradlePlugin/DownloadTask.java +++ b/src/main/java/de/guntram/mcmod/crowdintranslate/GradlePlugin/DownloadTask.java @@ -1,10 +1,10 @@ package de.guntram.mcmod.crowdintranslate.GradlePlugin; import de.guntram.mcmod.crowdintranslate.CrowdinTranslate; -import org.gradle.api.internal.AbstractTask; +import org.gradle.api.DefaultTask; import org.gradle.api.tasks.TaskAction; -public class DownloadTask extends AbstractTask { +public class DownloadTask extends DefaultTask { @TaskAction public void action() { CrowdinTranslateParameters parms = CrowdinTranslatePlugin.parameters; diff --git a/src/main/java/de/guntram/mcmod/crowdintranslate/mixins/ReloadableResourceManagerImplMixin.java b/src/main/java/de/guntram/mcmod/crowdintranslate/mixins/ReloadableResourceManagerImplMixin.java index e2a8191..ceffb42 100644 --- a/src/main/java/de/guntram/mcmod/crowdintranslate/mixins/ReloadableResourceManagerImplMixin.java +++ b/src/main/java/de/guntram/mcmod/crowdintranslate/mixins/ReloadableResourceManagerImplMixin.java @@ -1,43 +1,36 @@ package de.guntram.mcmod.crowdintranslate.mixins; import de.guntram.mcmod.crowdintranslate.CTResourcePack; + +import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; import net.minecraft.resource.*; -import net.minecraft.util.Unit; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.ModifyArg; @Mixin(ReloadableResourceManagerImpl.class) -public abstract class ReloadableResourceManagerImplMixin implements ReloadableResourceManager +public abstract class ReloadableResourceManagerImplMixin { @Shadow @Final private ResourceType type; - @Shadow - public abstract void addPack(ResourcePack resourcePack); - - @Inject( - method = "beginMonitoredReload", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/resource/ReloadableResourceManagerImpl;beginReloadInner(Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/List;Ljava/util/concurrent/CompletableFuture;)Lnet/minecraft/resource/ResourceReloadMonitor;", - shift = At.Shift.BEFORE - ) + @ModifyArg( + method = "reload", + at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/LifecycledResourceManagerImpl;(Lnet/minecraft/resource/ResourceType;Ljava/util/List;)V"), + index = 1 ) - private void onPostReload(Executor prepareExecutor, Executor applyExecutor, CompletableFuture initialStage, List packs, CallbackInfoReturnable cir) + private List onPostReload(List packs) { if (this.type != ResourceType.CLIENT_RESOURCES) - return; + return packs; - System.out.println("Inject generated resource packs."); - this.addPack(new CTResourcePack()); + List list = new ArrayList<>(packs); + list.add(new CTResourcePack()); + return list; } -} \ No newline at end of file +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index b15ba7c..512de98 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -3,16 +3,22 @@ "id": "crowdin-translate", "version": "${version}", "entrypoints": { + "client": [ "de.guntram.mcmod.crowdintranslate.ClientInit" ] }, "custom": { "ThanksGoTo": "LambdAurora for letting me use the virtual resource pack loader", - "modmenu:api": true + "modmenu": { + "badges": [ + "library" + ] + } }, "mixins": [ "mixins.crowdintranslate.json" ], "depends": { - "fabric": "*" + "fabric-resource-loader-v0": "*", + "fabricloader": "*" }, "name": "CrowdinTranslate", "description": "Downloads translations (xx_xx.json) files from Crowdin",