LibJF
This commit is contained in:
parent
bd1ff5a0e7
commit
a2693f08ad
|
@ -1,4 +1,4 @@
|
||||||
image: gradle:alpine
|
image: gradle:jdk16
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
||||||
|
|
105
build.gradle
105
build.gradle
|
@ -1,21 +1,10 @@
|
||||||
plugins {
|
apply from: "https://gitlab.com/-/snippets/2121059/raw/master/jfbase.gradle"
|
||||||
id 'fabric-loom' version '0.5-SNAPSHOT'
|
|
||||||
id 'maven-publish'
|
|
||||||
id "com.modrinth.minotaur" version "1.1.0"
|
|
||||||
id "com.matthewprenger.cursegradle" version "1.4.0"
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
|
|
||||||
archivesBaseName = project.archives_base_name
|
|
||||||
version = project.mod_version
|
|
||||||
group = project.maven_group
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven {url = "https://dl.bintray.com/user11681/maven"}
|
maven {
|
||||||
maven { url = 'https://jitpack.io' }
|
name = 'TerraformersMC'
|
||||||
maven { url = 'https://maven.terraformersmc.com/'; name = "ModMenu" }
|
url = 'https://maven.terraformersmc.com/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -24,87 +13,7 @@ dependencies {
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
|
|
||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
download("https://gitlab.com/jfmods/LibJF/-/jobs/artifacts/master/raw/latest-dev.jar?job=build_test", "libjf")
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
|
||||||
|
|
||||||
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
|
modImplementation "com.terraformersmc:modmenu:1.16.9"
|
||||||
// You may need to force-disable transitiveness on them.
|
|
||||||
|
|
||||||
modCompile "me.sargunvohra.mcmods:autoconfig1u:3.2.0-unstable"
|
|
||||||
include "me.sargunvohra.mcmods:autoconfig1u:3.2.0-unstable"
|
|
||||||
modApi ("me.shedaniel.cloth:config-2:4.8.3") {
|
|
||||||
transitive = false
|
|
||||||
}
|
|
||||||
include ("me.shedaniel.cloth:config-2:4.8.3") {
|
|
||||||
transitive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
modCompile "com.terraformersmc:modmenu:1.14.15"
|
|
||||||
}
|
|
||||||
|
|
||||||
processResources {
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
|
||||||
// this fixes some edge cases with special characters not displaying correctly
|
|
||||||
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
from "LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
import com.modrinth.minotaur.TaskModrinthUpload
|
|
||||||
|
|
||||||
task publishModrinth (type: TaskModrinthUpload){
|
|
||||||
token = System.getenv("MODRINTH_API_TOKEN") // Use an environment property!
|
|
||||||
projectId = '4GhX11Ed'
|
|
||||||
versionNumber = "${project.mod_version}"
|
|
||||||
uploadFile = remapJar // This is the java jar task
|
|
||||||
addGameVersion("${project.minecraft_version}")
|
|
||||||
addLoader('fabric')
|
|
||||||
versionName = "[${project.minecraft_version}] ${project.mod_version}"
|
|
||||||
afterEvaluate {
|
|
||||||
tasks.publishModrinth.dependsOn(remapJar)
|
|
||||||
tasks.publishModrinth.dependsOn(sourcesJar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curseforge {
|
|
||||||
apiKey = System.getenv("CURSEFORGE_API_TOKEN") == null ? "###" : System.getenv("CURSEFORGE_API_TOKEN")
|
|
||||||
project {
|
|
||||||
id = "405095"
|
|
||||||
releaseType = 'release'
|
|
||||||
addGameVersion "Fabric"
|
|
||||||
addGameVersion "${project.minecraft_version}"
|
|
||||||
changelog = ""
|
|
||||||
mainArtifact(file("${project.buildDir}/libs/${archivesBaseName}-${version}.jar"))
|
|
||||||
mainArtifact.displayName = "[${project.minecraft_version}] ${project.mod_version}"
|
|
||||||
afterEvaluate {
|
|
||||||
uploadTask.dependsOn(remapJar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options {
|
|
||||||
forgeGradleIntegration = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,17 @@ org.gradle.jvmargs=-Xmx1G
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://modmuss50.me/fabric.html
|
# check these on https://modmuss50.me/fabric.html
|
||||||
minecraft_version=1.16.5
|
minecraft_version=1.16.5
|
||||||
yarn_mappings=1.16.5+build.3
|
yarn_mappings=1.16.5+build.9
|
||||||
loader_version=0.11.1
|
loader_version=0.11.3
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=2.1
|
mod_version=2.2
|
||||||
maven_group=io.gitlab.jfronny
|
maven_group=io.gitlab.jfronny
|
||||||
archives_base_name=modsmod
|
archives_base_name=modsmod
|
||||||
# Dependencies
|
|
||||||
# check this on https://modmuss50.me/fabric.html
|
modrinth_id=4GhX11Ed
|
||||||
fabric_version=0.29.4+1.16
|
modrinth_required_dependencies=7a9qcRLy
|
||||||
|
modrinth_optional_dependencies=Gz5wa6j2
|
||||||
|
curseforge_id=405095
|
||||||
|
curseforge_required_dependencies=libjf
|
||||||
|
curseforge_optional_dependencies=modmenu
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
pluginManagement {
|
|
||||||
repositories {
|
|
||||||
jcenter()
|
|
||||||
maven {
|
|
||||||
name = 'Fabric'
|
|
||||||
url = 'https://maven.fabricmc.net/'
|
|
||||||
}
|
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +1,13 @@
|
||||||
package io.gitlab.jfronny.modsmod;
|
package io.gitlab.jfronny.modsmod;
|
||||||
|
|
||||||
import me.sargunvohra.mcmods.autoconfig1u.ConfigData;
|
import io.gitlab.jfronny.libjf.config.Entry;
|
||||||
import me.sargunvohra.mcmods.autoconfig1u.annotation.Config;
|
import io.gitlab.jfronny.libjf.config.JfConfig;
|
||||||
import me.sargunvohra.mcmods.autoconfig1u.annotation.ConfigEntry.Gui.RequiresRestart;
|
|
||||||
import me.sargunvohra.mcmods.autoconfig1u.shadowed.blue.endless.jankson.Comment;
|
|
||||||
|
|
||||||
@Config(name = "ModsMod")
|
public class Cfg implements JfConfig {
|
||||||
public class Cfg implements ConfigData {
|
@Entry
|
||||||
@Comment("The amount of mods to generate. Don't set this too high")
|
public static int modsCount = 26;
|
||||||
@RequiresRestart
|
@Entry
|
||||||
public int modsCount = 263;
|
public static boolean parent = false;
|
||||||
@Comment("Show the mods as children of ModsMod in ModMenu")
|
@Entry
|
||||||
@RequiresRestart
|
public static boolean cache = true;
|
||||||
public boolean parent = false;
|
|
||||||
@Comment("Cache the generated files. Increases performance. Disable when this stops working to regenerate")
|
|
||||||
public boolean cache = true;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,10 @@ import org.apache.logging.log4j.Logger;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class FabricLoaderInterface {
|
public class FabricLoaderInterface {
|
||||||
public static final Logger logger = LogManager.getLogger("modsmod");
|
public static final Logger logger = LogManager.getLogger(ModsMod.MOD_ID);
|
||||||
|
|
||||||
private static final Method addModMethod;
|
private static final Method addModMethod;
|
||||||
private static final Field modsField;
|
private static final Field modsField;
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package io.gitlab.jfronny.modsmod;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.MappedByteBuffer;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
|
||||||
|
public class IOUtil {
|
||||||
|
public static void deleteRecursive(Path path) throws IOException {
|
||||||
|
Files.walkFileTree(path, new FileVisitor<Path>() {
|
||||||
|
@Override
|
||||||
|
public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
|
||||||
|
Files.delete(path);
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFileFailed(Path path, IOException e) throws IOException {
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult postVisitDirectory(Path path, IOException e) throws IOException {
|
||||||
|
Files.delete(path);
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearDirectory(Path path) throws IOException {
|
||||||
|
deleteRecursive(path);
|
||||||
|
Files.createDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contentEquals(final Path a, final Path b) throws IOException {
|
||||||
|
try (final FileChannel fca = FileChannel.open(a, StandardOpenOption.READ);
|
||||||
|
final FileChannel fcb = FileChannel.open(b, StandardOpenOption.READ)) {
|
||||||
|
final MappedByteBuffer mbba = fca.map(FileChannel.MapMode.READ_ONLY, 0, fca.size());
|
||||||
|
final MappedByteBuffer mbbb = fcb.map(FileChannel.MapMode.READ_ONLY, 0, fcb.size());
|
||||||
|
return mbba.equals(mbbb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,8 +7,8 @@ import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class IteratorCallbackList implements List<ModContainer> {
|
public class IteratorCallbackList implements List<ModContainer> {
|
||||||
private List<ModContainer> containers;
|
private final List<ModContainer> containers;
|
||||||
private Consumer<List<ModContainer>> reset;
|
private final Consumer<List<ModContainer>> reset;
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
public IteratorCallbackList(List<ModContainer> base, Consumer<List<ModContainer>> reset) {
|
public IteratorCallbackList(List<ModContainer> base, Consumer<List<ModContainer>> reset) {
|
||||||
containers = Collections.synchronizedList(base);
|
containers = Collections.synchronizedList(base);
|
||||||
|
@ -34,7 +34,7 @@ public class IteratorCallbackList implements List<ModContainer> {
|
||||||
@Override
|
@Override
|
||||||
public Iterator<ModContainer> iterator() {
|
public Iterator<ModContainer> iterator() {
|
||||||
if (!modified) {
|
if (!modified) {
|
||||||
PreLaunch.init();
|
ModsMod.init();
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
reset.accept(containers);
|
reset.accept(containers);
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package io.gitlab.jfronny.modsmod;
|
|
||||||
|
|
||||||
import io.github.prospector.modmenu.api.ConfigScreenFactory;
|
|
||||||
import io.github.prospector.modmenu.api.ModMenuApi;
|
|
||||||
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
|
|
||||||
import net.fabricmc.api.EnvType;
|
|
||||||
import net.fabricmc.api.Environment;
|
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
|
||||||
public class ModMenu implements ModMenuApi {
|
|
||||||
@Override
|
|
||||||
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
|
||||||
return screen -> AutoConfig.getConfigScreen(Cfg.class, screen).get();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package io.gitlab.jfronny.modsmod;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
|
||||||
|
public class ModMeta {
|
||||||
|
public final FileSystem fs;
|
||||||
|
public final URL url;
|
||||||
|
|
||||||
|
public ModMeta(FileSystem fs, URL url) {
|
||||||
|
this.fs = fs;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
package io.gitlab.jfronny.modsmod;
|
||||||
|
|
||||||
|
import io.gitlab.jfronny.libjf.Libjf;
|
||||||
|
import net.fabricmc.loader.FabricLoader;
|
||||||
|
import net.fabricmc.loader.discovery.ModCandidate;
|
||||||
|
import net.fabricmc.loader.discovery.ModResolver;
|
||||||
|
import net.fabricmc.loader.discovery.RuntimeModRemapper;
|
||||||
|
import net.fabricmc.loader.launch.common.FabricLauncherBase;
|
||||||
|
import net.fabricmc.loader.metadata.LoaderModMetadata;
|
||||||
|
import net.fabricmc.loader.metadata.ModMetadataParser;
|
||||||
|
import net.fabricmc.loader.metadata.ParseMetadataException;
|
||||||
|
import net.fabricmc.loader.util.FileSystemUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class ModsMod {
|
||||||
|
static HashSet<ModMeta> m;
|
||||||
|
static FabricLoader loader;
|
||||||
|
public static final String MOD_ID = "modsmod";
|
||||||
|
private static final String CACHE_NAME = MOD_ID + "cache";
|
||||||
|
public static void prepare() throws IOException {
|
||||||
|
loader = FabricLoader.INSTANCE;
|
||||||
|
//Load config
|
||||||
|
Libjf.registerConfig(MOD_ID, Cfg.class);
|
||||||
|
Path configDir = loader.getConfigDir();
|
||||||
|
Path modsmodCfgFile = Libjf.getConfigs().get(MOD_ID).path;
|
||||||
|
//make sure the modsmodcache dir is ok
|
||||||
|
Path path = configDir.resolve(CACHE_NAME);
|
||||||
|
if (!Files.isDirectory(path)) {
|
||||||
|
if (Files.exists(path))
|
||||||
|
Files.delete(path);
|
||||||
|
Files.createDirectories(path);
|
||||||
|
}
|
||||||
|
//remove modsmodcache if the cache is outdated
|
||||||
|
try {
|
||||||
|
Path cfgCache = configDir.resolve(CACHE_NAME + "_basecfg");
|
||||||
|
if (Files.exists(cfgCache)) {
|
||||||
|
if (Files.isRegularFile(cfgCache)) {
|
||||||
|
if (!IOUtil.contentEquals(modsmodCfgFile, cfgCache)) {
|
||||||
|
IOUtil.clearDirectory(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
IOUtil.clearDirectory(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Files.copy(modsmodCfgFile, cfgCache, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Failed to validate modsmod config cache, caching will not be available");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
m = new HashSet<>();
|
||||||
|
//Generate mods
|
||||||
|
for (int i = 0; i < Cfg.modsCount; i++) {
|
||||||
|
Path f = path.resolve("f" + (i + 1) + ".jar");
|
||||||
|
boolean exists = Files.exists(f);
|
||||||
|
FileSystem fs = FileSystemUtil.getJarFileSystem(f, !exists).get();
|
||||||
|
m.add(new ModMeta(fs, f.toUri().toURL()));
|
||||||
|
//Do not load if cached
|
||||||
|
if (exists) {
|
||||||
|
if (Cfg.cache) continue;
|
||||||
|
else Files.delete(f);
|
||||||
|
}
|
||||||
|
//META-INF/MANIFEST.MF (java jar file spec)
|
||||||
|
Path inf = fs.getPath("META-INF");
|
||||||
|
Files.createDirectory(inf);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Manifest-Version: 1.0\n");
|
||||||
|
Files.write(inf.resolve("MANIFEST.MF"), sb.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
sb.delete(0, sb.length());
|
||||||
|
//fabric.mod.json (fabric mod metadata)
|
||||||
|
sb.append("{");
|
||||||
|
sb.append("\"schemaVersion\": 1,");
|
||||||
|
sb.append("\"id\": \"modmod_").append(i + 1).append("\",");
|
||||||
|
sb.append("\"version\": \"1.0\",");
|
||||||
|
sb.append("\"name\": \"ModsMod ").append(i + 1).append("\",");
|
||||||
|
sb.append("\"entrypoints\": {},");
|
||||||
|
sb.append("\"custom\": {");
|
||||||
|
if (Cfg.parent) {
|
||||||
|
sb.append("\"modmenu:parent\": \"modsmod\"");
|
||||||
|
}
|
||||||
|
sb.append("}");
|
||||||
|
sb.append("}");
|
||||||
|
Files.write(fs.getPath("fabric.mod.json"), sb.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
sb.delete(0, sb.length());
|
||||||
|
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
FabricLoaderInterface.synchronize(loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
for (ModMeta f : m) {
|
||||||
|
loadMod(loader, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void loadMod(FabricLoader loader, ModMeta meta) {
|
||||||
|
ModCandidate candidate = parseMod(meta.fs.getPath("fabric.mod.json"), meta.url);
|
||||||
|
|
||||||
|
if (loader.isDevelopmentEnvironment()) {
|
||||||
|
candidate = RuntimeModRemapper.remap(Collections.singletonList(candidate), ModResolver.getInMemoryFs()).stream().findFirst().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
FabricLoaderInterface.addMod(loader, candidate);
|
||||||
|
FabricLauncherBase.getLauncher().propose(candidate.getOriginUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ModCandidate parseMod(Path fabricModJson, URL originUrl) {
|
||||||
|
try {
|
||||||
|
LoaderModMetadata info = ModMetadataParser.parseMetadata(FabricLoaderInterface.logger, fabricModJson);
|
||||||
|
return new ModCandidate(info, originUrl, 0, true);
|
||||||
|
} catch (IOException | ParseMetadataException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,17 @@ package io.gitlab.jfronny.modsmod;
|
||||||
|
|
||||||
import net.fabricmc.loader.api.LanguageAdapter;
|
import net.fabricmc.loader.api.LanguageAdapter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class ModsModAdapter implements LanguageAdapter {
|
public class ModsModAdapter implements LanguageAdapter {
|
||||||
@Override
|
@Override
|
||||||
public native <T> T create(net.fabricmc.loader.api.ModContainer mod, String value, Class<T> type);
|
public native <T> T create(net.fabricmc.loader.api.ModContainer mod, String value, Class<T> type);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
PreLaunch.prepare();
|
try {
|
||||||
|
ModsMod.prepare();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
package io.gitlab.jfronny.modsmod;
|
|
||||||
|
|
||||||
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
|
|
||||||
import me.sargunvohra.mcmods.autoconfig1u.serializer.JanksonConfigSerializer;
|
|
||||||
import net.fabricmc.loader.FabricLoader;
|
|
||||||
import net.fabricmc.loader.discovery.ModCandidate;
|
|
||||||
import net.fabricmc.loader.discovery.ModResolver;
|
|
||||||
import net.fabricmc.loader.discovery.RuntimeModRemapper;
|
|
||||||
import net.fabricmc.loader.launch.common.FabricLauncherBase;
|
|
||||||
import net.fabricmc.loader.metadata.LoaderModMetadata;
|
|
||||||
import net.fabricmc.loader.metadata.ModMetadataParser;
|
|
||||||
import net.fabricmc.loader.metadata.ParseMetadataException;
|
|
||||||
import net.fabricmc.loader.util.FileSystemUtil;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
public class PreLaunch {
|
|
||||||
static HashSet<File> m;
|
|
||||||
static FabricLoader loader;
|
|
||||||
public static void prepare() {
|
|
||||||
loader = FabricLoader.INSTANCE;
|
|
||||||
//Load config
|
|
||||||
AutoConfig.register(Cfg.class, JanksonConfigSerializer::new);
|
|
||||||
Cfg cfg = AutoConfig.getConfigHolder(Cfg.class).getConfig();
|
|
||||||
Path configDir = loader.getConfigDir();
|
|
||||||
String modsmodCfgFileName = "ModsMod.json5";
|
|
||||||
//make sure the modsmodcache dir is ok
|
|
||||||
File path = new File(configDir.toFile(), "modsmodcache");
|
|
||||||
if (!path.isDirectory()) {
|
|
||||||
if (path.exists())
|
|
||||||
path.delete();
|
|
||||||
path.mkdir();
|
|
||||||
}
|
|
||||||
//remove modsmodcache if the cache is outdated
|
|
||||||
try {
|
|
||||||
File cfgCache = new File(path, "_basecfg");
|
|
||||||
if (cfgCache.exists()) {
|
|
||||||
if (cfgCache.isFile()) {
|
|
||||||
if (!FileUtils.contentEquals(new File(configDir.toFile(), modsmodCfgFileName), cfgCache)) {
|
|
||||||
FileUtils.deleteDirectory(path);
|
|
||||||
path.mkdir();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FileUtils.deleteDirectory(path);
|
|
||||||
path.mkdir();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Files.copy(Paths.get(configDir.toString(), modsmodCfgFileName), cfgCache.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("Failed to validate modsmod config cache, caching will not be available");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
m = new HashSet<>();
|
|
||||||
//Generate mods
|
|
||||||
for (int i = 0; i < cfg.modsCount; i++) {
|
|
||||||
File f = new File(path, "f" + (i + 1) + ".jar");
|
|
||||||
m.add(f);
|
|
||||||
//Do not load if cached
|
|
||||||
if (f.exists()) {
|
|
||||||
if (cfg.cache) continue;
|
|
||||||
else f.delete();
|
|
||||||
}
|
|
||||||
//Generate jar
|
|
||||||
ZipOutputStream out;
|
|
||||||
try {
|
|
||||||
out = new ZipOutputStream(new FileOutputStream(f));
|
|
||||||
//META-INF/MANIFEST.MF (java jar file spec)
|
|
||||||
ZipEntry e = new ZipEntry("META-INF/MANIFEST.MF");
|
|
||||||
out.putNextEntry(e);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("Manifest-Version: 1.0\n");
|
|
||||||
out.write(sb.toString().getBytes());
|
|
||||||
out.closeEntry();
|
|
||||||
//fabric.mod.json (fabric mod metadata)
|
|
||||||
e = new ZipEntry("fabric.mod.json");
|
|
||||||
out.putNextEntry(e);
|
|
||||||
sb = new StringBuilder();
|
|
||||||
sb.append("{");
|
|
||||||
sb.append("\"schemaVersion\": 1,");
|
|
||||||
sb.append("\"id\": \"modmod_").append(i + 1).append("\",");
|
|
||||||
sb.append("\"version\": \"1.0\",");
|
|
||||||
sb.append("\"name\": \"ModsMod ").append(i + 1).append("\",");
|
|
||||||
//sb.append("\"icon\": \"assets/modsmod/icon_1.png\",");
|
|
||||||
sb.append("\"entrypoints\": {},");
|
|
||||||
sb.append("\"custom\": {");
|
|
||||||
if (cfg.parent) {
|
|
||||||
sb.append("\"modmenu:parent\": \"modsmod\"");
|
|
||||||
}
|
|
||||||
sb.append("}");
|
|
||||||
sb.append("}");
|
|
||||||
out.write(sb.toString().getBytes());
|
|
||||||
out.closeEntry();
|
|
||||||
//Make file available
|
|
||||||
out.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("Failed to generate mod!");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
System.gc();
|
|
||||||
}
|
|
||||||
FabricLoaderInterface.synchronize(loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void init() {
|
|
||||||
for (File f : m) {
|
|
||||||
loadMod(loader, f.toPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void loadMod(FabricLoader loader, Path modPath) {
|
|
||||||
ModCandidate candidate = parseMod(modPath);
|
|
||||||
|
|
||||||
if (loader.isDevelopmentEnvironment()) {
|
|
||||||
candidate = RuntimeModRemapper.remap(Collections.singletonList(candidate), ModResolver.getInMemoryFs()).stream().findFirst().get();
|
|
||||||
}
|
|
||||||
|
|
||||||
FabricLoaderInterface.addMod(loader, candidate);
|
|
||||||
FabricLauncherBase.getLauncher().propose(candidate.getOriginUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ModCandidate parseMod(Path modPath) {
|
|
||||||
try {
|
|
||||||
FileSystemUtil.FileSystemDelegate jarFs = FileSystemUtil.getJarFileSystem(modPath, false);
|
|
||||||
|
|
||||||
Path modJson = jarFs.get().getPath("fabric.mod.json");
|
|
||||||
|
|
||||||
LoaderModMetadata info = ModMetadataParser.parseMetadata(FabricLoaderInterface.logger, modJson);
|
|
||||||
|
|
||||||
return new ModCandidate(info, modPath.toUri().toURL(), 0, true);
|
|
||||||
} catch (IOException | ParseMetadataException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,9 @@
|
||||||
{
|
{
|
||||||
"text.autoconfig.ModsMod.title": "ModsMod",
|
"ModsMod.jfconfig.title": "ModsMod",
|
||||||
"text.autoconfig.ModsMod.option.modsCount": "Mods count",
|
"ModsMod.jfconfig.modsCount": "Mods count",
|
||||||
"text.autoconfig.ModsMod.option.parent": "Parent",
|
"ModsMod.jfconfig.modsCount.tooltip": "The amount of mods to generate. Don't set this too high",
|
||||||
"text.autoconfig.ModsMod.option.cache": "Cache"
|
"ModsMod.jfconfig.parent": "Parent",
|
||||||
|
"ModsMod.jfconfig.parent.tooltip": "Show the mods as children of ModsMod in ModMenu",
|
||||||
|
"ModsMod.jfconfig.cache": "Cache",
|
||||||
|
"ModsMod.jfconfig.cache.tooltip": "Cache the generated files. Increases performance. Disable when this stops working to regenerate"
|
||||||
}
|
}
|
|
@ -15,16 +15,14 @@
|
||||||
"icon": "assets/modsmod/icon.png",
|
"icon": "assets/modsmod/icon.png",
|
||||||
"environment": "*",
|
"environment": "*",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
"modmenu": [
|
"libjf:config": ["io.gitlab.jfronny.modsmod.Cfg"]
|
||||||
"io.gitlab.jfronny.modsmod.ModMenu"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"languageAdapters": {
|
"languageAdapters": {
|
||||||
"modsmod": "io.gitlab.jfronny.modsmod.ModsModAdapter"
|
"modsmod": "io.gitlab.jfronny.modsmod.ModsModAdapter"
|
||||||
},
|
},
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.9.2+build.206",
|
"fabricloader": ">=0.9.2+build.206",
|
||||||
"fabric": "*",
|
"libjf": "*",
|
||||||
"minecraft": "*"
|
"minecraft": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue