Migrate to LibJF 3 for config instead of cloth

This commit is contained in:
Johannes Frohnmeyer 2022-08-28 16:27:55 +02:00
parent 69b46c124e
commit ca2e166a9d
Signed by: Johannes
GPG Key ID: E76429612C2929F4
22 changed files with 113 additions and 244 deletions

3
.gitignore vendored
View File

@ -118,4 +118,5 @@ run/
!gradle-wrapper.jar
# No temporary natives!
src/main/c/natives.dll
src/main/c/natives.dll
src/main/java/io/gitlab/jfronny/breakme/crash/KnownProviders.java

View File

@ -23,12 +23,14 @@ build_test:
stage: deploy
script:
- gradle --build-cache deployDebug -Pmaven="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/maven"
- rm src/main/java/io/gitlab/jfronny/breakme/crash/KnownProviders.java
- mv build/libs/* ./
- mv build/devlibs/*-dev.jar ./
- rm *-maven.jar *-sources.jar *-testmod.jar
- mv *-dev.jar dev-free.zip
- mv *.jar latest.zip
- gradle --build-cache -Pflavor=curseforge build
- rm src/main/java/io/gitlab/jfronny/breakme/crash/KnownProviders.java
- cp build/libs/* ./
- cp build/devlibs/*-dev.jar ./
- rm *-maven.jar *-sources.jar *-testmod.jar
@ -53,6 +55,7 @@ deploy:
stage: deploy
script:
- gradle --build-cache build publish modrinth modrinthSyncBody -Prelease -Pmaven="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/maven"
- rm src/main/java/io/gitlab/jfronny/breakme/crash/KnownProviders.java
- rm build/libs/*
- rm build/devlibs/*
- gradle --build-cache -Pflavor=curseforge build curseforge -Prelease

View File

@ -1,21 +1,48 @@
apply from: "https://jfmods.gitlab.io/scripts/jfmod.gradle"
import java.util.stream.Collectors
import java.nio.file.Files
import java.nio.file.Path
apply from: "https://jfmods.gitlab.io/scripts/gradle/v2.gradle"
ext.flavor = project.hasProperty('flavor') ? project.getProperty('flavor') : 'modrinth'
repositories {
maven { url = "https://maven.shedaniel.me/"; name = "Cloth Config" }
}
dependencies {
modRuntimeOnly "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:$project.libjf_version")
modApi("me.shedaniel.cloth:cloth-config-fabric:7.0.73") {
exclude(group: "net.fabricmc.fabric-api")
}
modImplementation "com.terraformersmc:modmenu:4.0.5"
// Dev env
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:$project.libjf_version")
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:$project.libjf_version")
modLocalRuntime("net.fabricmc.fabric-api:fabric-api:${project.fabric_version}")
modLocalRuntime("com.terraformersmc:modmenu:4.0.6")
}
def list(String dir) {
return Files.list(Path.of("$projectDir/$dir"))
.map(p -> p.fileName.toString())
.map(p -> p.substring(0, p.lastIndexOf('.')))
.filter(p -> p.endsWith("Provider"))
.toArray(String[]::new)
}
String[] paths = list("src/main/java/io/gitlab/jfronny/breakme/crash/safe")
if (flavor == "curseforge") {
sourceSets.main.java.filter.exclude("**/unsafe/*")
sourceSets.main.resources.exclude("**/native/*")
} else {
paths += list("src/main/java/io/gitlab/jfronny/breakme/crash/unsafe")
}
Files.writeString(Path.of("$projectDir/src/main/java/io/gitlab/jfronny/breakme/crash/KnownProviders.java"), """
package io.gitlab.jfronny.breakme.crash;
import io.gitlab.jfronny.breakme.crash.safe.*;
${if (flavor == "curseforge") "" else "import io.gitlab.jfronny.breakme.crash.unsafe.*;"}
import java.util.Map;
public class KnownProviders {
public static final Map<String, CrashProvider> PROVIDERS = Map.of(
${Arrays.stream(paths).map(path -> "\"${path.substring(0, path.length() - "Provider".length())}\", new $path()").collect(Collectors.joining(",\n "))}
);
}
""")

View File

@ -1,13 +1,16 @@
# https://fabricmc.net/develop/
minecraft_version=1.19.1
yarn_mappings=build.1
loader_version=0.14.8
minecraft_version=1.19.2
yarn_mappings=build.8
loader_version=0.14.9
maven_group=io.gitlab.jfronny
archives_base_name=breakme
fabric_version=0.58.5+1.19.1
fabric_version=0.60.0+1.19.2
libjf_version=3.0.3
modrinth_id=breakme
modrinth_optional_dependencies=modmenu, cloth-config
modrinth_required_dependencies=libjf
modrinth_optional_dependencies=modmenu
curseforge_id=400842
curseforge_optional_dependencies=modmenu, cloth-config
curseforge_required_dependencies=libjf
curseforge_optional_dependencies=modmenu

View File

@ -1,13 +0,0 @@
package io.gitlab.jfronny.breakme;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import io.gitlab.jfronny.breakme.config.Cfg;
import me.shedaniel.autoconfig.AutoConfig;
public class ModMenuAPI implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return screen -> AutoConfig.getConfigScreen(Cfg.class, screen).get();
}
}

View File

@ -1,53 +1,13 @@
package io.gitlab.jfronny.breakme;
import io.gitlab.jfronny.breakme.config.Cfg;
import io.gitlab.jfronny.breakme.config.CrashCause;
import io.gitlab.jfronny.breakme.crash.CrashProvider;
import me.shedaniel.autoconfig.AutoConfig;
import me.shedaniel.autoconfig.serializer.JanksonConfigSerializer;
import io.gitlab.jfronny.breakme.crash.KnownProviders;
import io.gitlab.jfronny.commons.log.Logger;
import net.fabricmc.api.ModInitializer;
import net.minecraft.entity.player.PlayerEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BreakMe implements ModInitializer {
public static final String MOD_ID = "breakme";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
public static final Cfg cfg;
private static final Map<String, CrashProvider> crashProviders;
static {
//Get config
AutoConfig.register(Cfg.class, JanksonConfigSerializer::new);
cfg = AutoConfig.getConfigHolder(Cfg.class).getConfig();
//Get crash providers
crashProviders = new HashMap<>();
try {
List<Class<?>> classes = ClassFinder.find(CrashProvider.class.getPackage().getName());
for (Class<?> clazz : classes) {
if (CrashProvider.class.isAssignableFrom(clazz) && !CrashProvider.class.equals(clazz)) {
try {
CrashProvider provider = (CrashProvider) clazz.getDeclaredConstructor().newInstance();
crashProviders.put(provider.getName(), provider);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
LOGGER.error("Could not initialize crash provider", e);
}
}
}
if (!crashProviders.containsKey(cfg.method)) {
cfg.method = "None";
LOGGER.warn("Could not find specified crash provider, defaulting to None");
}
} catch (IOException e) {
LOGGER.error("Could not load crash providers", e);
}
}
public static final Logger LOGGER = Logger.forName(MOD_ID);
@Override
public void onInitialize() {
@ -55,17 +15,11 @@ public class BreakMe implements ModInitializer {
}
public static void tryInvokeCrash(PlayerEntity player) throws Exception {
if (cfg.event == CrashCause.All || cfg.event == CrashCause.Damage || (cfg.event == CrashCause.Death && player.isDead())) {
if (BreakMeConfig.event == BreakMeConfig.Cause.All
|| BreakMeConfig.event == BreakMeConfig.Cause.Damage
|| (BreakMeConfig.event == BreakMeConfig.Cause.Death && player.isDead())) {
LOGGER.info("Invoking the crash");
if (!crashProviders.containsKey(cfg.method)) {
cfg.method = "None";
LOGGER.error("Could not find specified crash provider, defaulting to None");
}
crashProviders.get(cfg.method).crash();
KnownProviders.PROVIDERS.get(BreakMeConfig.method).crash();
}
}
public static String[] getProviders() {
return crashProviders.keySet().toArray(new String[0]);
}
}

View File

@ -1,40 +0,0 @@
package io.gitlab.jfronny.breakme;
import io.gitlab.jfronny.breakme.config.Cfg;
import io.gitlab.jfronny.breakme.config.CrashMethod;
import me.shedaniel.autoconfig.AutoConfig;
import me.shedaniel.autoconfig.gui.registry.GuiRegistry;
import me.shedaniel.autoconfig.gui.registry.api.GuiRegistryAccess;
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
import net.fabricmc.api.ClientModInitializer;
import net.minecraft.text.*;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import static me.shedaniel.autoconfig.util.Utils.getUnsafely;
import static me.shedaniel.autoconfig.util.Utils.setUnsafely;
public class BreakMeClient implements ClientModInitializer {
ConfigEntryBuilder builder = ConfigEntryBuilder.create();
@Override
public void onInitializeClient() {
GuiRegistry registry = AutoConfig.getGuiRegistry(Cfg.class);
registry.registerAnnotationProvider(this::get, CrashMethod.class);
registry.registerTypeProvider(this::get, String.class);
}
private List<AbstractConfigListEntry> get(String i13n, Field field, Object config, Object defaults, GuiRegistryAccess guiProvider) {
return Collections.singletonList(
builder.startSelector(
Text.translatable(i13n),
BreakMe.getProviders(),
getUnsafely(field, config, getUnsafely(field, defaults))
).setDefaultValue(() -> "None")
.setSaveConsumer(newValue -> setUnsafely(field, config, newValue))
.build()
);
}
}

View File

@ -0,0 +1,32 @@
package io.gitlab.jfronny.breakme;
import io.gitlab.jfronny.breakme.crash.KnownProviders;
import io.gitlab.jfronny.libjf.config.api.v1.JfCustomConfig;
import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL;
public class BreakMeConfig implements JfCustomConfig {
public static Cause event = Cause.Death;
public static String method = "Exception";
public enum Cause {
Damage,
Death,
All,
None
}
@Override
public void register(DSL.Defaulted dsl) {
dsl.register(builder -> builder
.value("event", event, Cause.class, () -> event, v -> event = v)
.value("method", method, KnownProviders.PROVIDERS.keySet().toArray(String[]::new), () -> method, v -> method = v)
.addVerifier(() -> {
if (!KnownProviders.PROVIDERS.containsKey(BreakMeConfig.method)) {
BreakMeConfig.method = "None";
BreakMe.LOGGER.error("Could not find specified crash provider, defaulting to None");
}
})
);
}
}

View File

@ -1,44 +0,0 @@
package io.gitlab.jfronny.breakme;
import net.fabricmc.loader.api.FabricLoader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Stream;
public class ClassFinder {
public static List<Class<?>> find(String packageName) throws NoSuchElementException, IOException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Path p = FabricLoader.getInstance()
.getModContainer(BreakMe.MOD_ID)
.orElseThrow(FileNotFoundException::new)
.findPath(".")
.orElseThrow(FileNotFoundException::new)
.toAbsolutePath();
return findInternal(p, p.resolve(packageName.replace('.', '/')), classLoader);
}
private static List<Class<?>> findInternal(Path rootPath, Path path, ClassLoader classLoader) throws IOException {
List<Class<?>> result = new ArrayList<>();
try (Stream<Path> files = Files.list(path)) {
files.forEach(s -> {
try {
if (Files.isDirectory(s)) {
result.addAll(findInternal(rootPath, s, classLoader));
} else if (s.getFileName().toString().endsWith(".class")) {
String p = rootPath.relativize(s).toString().replace('/', '.');
result.add(classLoader.loadClass(p.substring(0, p.length() - ".class".length())));
}
} catch (Throwable e) {
BreakMe.LOGGER.error("Could not scan classpath for crash method", e);
}
});
}
return result;
}
}

View File

@ -1,17 +0,0 @@
package io.gitlab.jfronny.breakme.config;
import io.gitlab.jfronny.breakme.BreakMe;
import me.shedaniel.autoconfig.ConfigData;
import me.shedaniel.autoconfig.annotation.Config;
import me.shedaniel.autoconfig.annotation.ConfigEntry.Gui.EnumHandler;
import me.shedaniel.cloth.clothconfig.shadowed.blue.endless.jankson.Comment;
@Config(name = BreakMe.MOD_ID)
public class Cfg implements ConfigData {
@Comment("What should cause a crash")
@EnumHandler(option = EnumHandler.EnumDisplayOption.BUTTON)
public CrashCause event = CrashCause.Death;
@Comment("The method used to perform the crash")
@CrashMethod
public String method = "Safe_Universal_Exception";
}

View File

@ -1,9 +0,0 @@
package io.gitlab.jfronny.breakme.config;
public enum CrashCause {
Damage,
Death,
All,
None
}

View File

@ -1,4 +0,0 @@
package io.gitlab.jfronny.breakme.config;
public @interface CrashMethod {
}

View File

@ -2,5 +2,4 @@ package io.gitlab.jfronny.breakme.crash;
public interface CrashProvider {
void crash() throws Exception;
String getName();
}

View File

@ -7,9 +7,4 @@ public class ExceptionProvider implements CrashProvider {
public void crash() throws Exception {
throw new Exception("You did bad, now die");
}
@Override
public String getName() {
return "Safe_Universal_Exception";
}
}

View File

@ -7,9 +7,4 @@ public class ExitCodeProvider implements CrashProvider {
public void crash() {
System.exit(-1);
}
@Override
public String getName() {
return "Broken_Universal_ExitCode";
}
}

View File

@ -1,13 +1,10 @@
package io.gitlab.jfronny.breakme.crash;
package io.gitlab.jfronny.breakme.crash.safe;
import io.gitlab.jfronny.breakme.crash.CrashProvider;
public class NoneProvider implements CrashProvider {
@Override
public void crash() throws Exception {
}
@Override
public String getName() {
return "None";
}
}

View File

@ -7,9 +7,4 @@ public class SecurityExceptionProvider implements CrashProvider {
public void crash() throws Exception {
throw new SecurityException("You did bad, now die");
}
@Override
public String getName() {
return "SemiUnsafe_Universal_Exception";
}
}

View File

@ -7,9 +7,4 @@ public class ForkbombProvider implements CrashProvider {
public void crash() {
forkbomb.main(new String[0]);
}
@Override
public String getName() {
return "Unsafe_Universal_Forkbomb";
}
}

View File

@ -19,9 +19,4 @@ public class ShutdownProvider implements CrashProvider {
runtime.exec("shutdown 0");
}
}
@Override
public String getName() {
return "SemiUnsafe_Universal_Shutdown";
}
}

View File

@ -11,14 +11,9 @@ public class WinApiProvider implements CrashProvider {
public void crash() {
try {
NativeUtils.loadLibraryFromJar("/native/natives.dll");
new WinApiProvider().CrashWindows_Native();
this.CrashWindows_Native();
} catch (IOException e) {
BreakMe.LOGGER.error("Could not load windows native", e);
}
}
@Override
public String getName() {
return "Unsafe_Windows_WinAPI";
}
}

View File

@ -1,5 +1,18 @@
{
"text.autoconfig.breakme.title": "BreakMe",
"text.autoconfig.breakme.option.event": "Event",
"text.autoconfig.breakme.option.method": "Method"
"breakme.jfconfig.title": "BreakMe",
"breakme.jfconfig.event": "Event",
"breakme.jfconfig.event.tooltip": "What should cause a crash",
"breakme.jfconfig.enum.Cause.Damage": "Damage",
"breakme.jfconfig.enum.Cause.Death": "Death",
"breakme.jfconfig.enum.Cause.All": "Damage or Death",
"breakme.jfconfig.enum.Cause.None": "None",
"breakme.jfconfig.method": "Method",
"breakme.jfconfig.method.tooltip": "The method used to perform the crash",
"breakme.jfconfig.method.Exception": "Safe_Universal_Exception",
"breakme.jfconfig.method.ExitCode": "Broken_Universal_ExitCode",
"breakme.jfconfig.method.SecurityException": "SemiUnsafe_Universal_Exception",
"breakme.jfconfig.method.Forkbomb": "Unsafe_Universal_Forkbomb",
"breakme.jfconfig.method.Shutdown": "SemiUnsafe_Universal_Shutdown",
"breakme.jfconfig.method.WinApi": "Unsafe_Windows_WinAPI",
"breakme.jfconfig.method.None": "None"
}

View File

@ -18,11 +18,8 @@
"main": [
"io.gitlab.jfronny.breakme.BreakMe"
],
"client": [
"io.gitlab.jfronny.breakme.BreakMeClient"
],
"modmenu": [
"io.gitlab.jfronny.breakme.ModMenuAPI"
"libjf:config": [
"io.gitlab.jfronny.breakme.BreakMeConfig"
]
},
"mixins": [
@ -31,6 +28,6 @@
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"cloth-config": "*"
"libjf-config-core-v1": "*"
}
}