Compare commits

...

5 Commits

Author SHA1 Message Date
Johannes Frohnmeyer 6788c1a335
feat: some porting work
ci/woodpecker/push/docs Pipeline was successful Details
ci/woodpecker/push/jfmod Pipeline failed Details
2024-04-10 19:23:31 +02:00
Johannes Frohnmeyer 68b8e2de26
feat: add back code for libjf-unsafe but keep disabled
to reduce differences with master branch
2024-04-10 17:17:48 +02:00
Johannes Frohnmeyer 1ff666f393
feat: disable config-compiler-plugin
this needs no forge-specific changes and can thus live in the fabric variant
2024-04-10 17:16:22 +02:00
Johannes Frohnmeyer 9528a402cc
feat: get rid of libjf-unsafe
this will never work on Forge.
data-manipulation will need to be ported to something else.
2024-04-10 16:59:18 +02:00
Johannes Frohnmeyer 05425ec293
feat: forge part 1: gradle sync 2024-04-10 16:55:49 +02:00
62 changed files with 698 additions and 653 deletions

View File

@ -1,17 +1,14 @@
import io.gitlab.jfronny.scripts.isFabric
plugins {
id("jfmod")
}
allprojects { group = "io.gitlab.jfronny.libjf" }
allprojects { group = "io.gitlab.jfronny.libjf.forge" }
subprojects { version = rootProject.version }
jfMod {
minecraftVersion = libs.versions.minecraft
yarn(libs.versions.yarn.get())
loaderVersion = libs.versions.fabric.loader
fabricApiVersion = libs.versions.fabric.api
loaderVersion = libs.versions.forge.loader
modrinth {
projectId = "libjf"
@ -27,17 +24,15 @@ base {
archivesName = "libjf"
}
allprojects {
if (!rootProject.jfMod.isMod(this)) return@allprojects
if (lom.isFabric) {
dependencies {
modLocalRuntime(libs.modmenu) {
exclude("net.fabricmc") // required to work around duplicate fabric loaders
}
modLocalRuntime("net.fabricmc.fabric-api:fabric-command-api-v2")
modLocalRuntime("net.fabricmc.fabric-api:fabric-networking-api-v1")
compileOnly(libs.bundles.commons)
}
dependencies {
subprojects {
if (rootProject.jfMod.isMod(this)) "loomDevelopmentDependencies"(this)
}
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -1 +1,2 @@
fabric.loom.multiProjectOptimisation=true
fabric.loom.multiProjectOptimisation=true
loom.platform=neoforge

View File

@ -2,10 +2,9 @@
[versions]
minecraft = "1.20.4"
yarn = "build.3"
fabric-loader = "0.15.7"
fabric-api = "0.96.4+1.20.4"
forge-loader = "20.4.210"
libjf-fabric-version = "3.13.3"
jf-commons = "1.6-SNAPSHOT"
modmenu = "9.0.0"
gson-compile = "1.4-SNAPSHOT"
annotations = "24.1.0"
javapoet = "1.13.0"
@ -18,7 +17,6 @@ commons-logger = { module = "io.gitlab.jfronny:commons-logger", version.ref="jf-
commons-serialize = { module = "io.gitlab.jfronny:commons-serialize", version.ref="jf-commons" }
commons-serialize-gson = { module = "io.gitlab.jfronny:commons-serialize-gson", version.ref="jf-commons" }
commons-unsafe = { module = "io.gitlab.jfronny:commons-unsafe", version.ref="jf-commons" }
modmenu = { module = "com.terraformersmc:modmenu", version.ref="modmenu" }
gson-compile-processor-core = { module = "io.gitlab.jfronny.gson:gson-compile-processor-core", version.ref="gson-compile" }
annotations = { module = "org.jetbrains:annotations", version.ref="annotations" }
javapoet = { module = "com.squareup:javapoet", version.ref="javapoet" }

View File

@ -12,10 +12,16 @@ base {
}
dependencies {
include(modImplementation("net.fabricmc.fabric-api:fabric-lifecycle-events-v1")!!)
shadow(libs.bundles.commons)
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}
// workaround to ensure our custom System.LoggerFinder is initialized early
// ideally, we would use the configuration API, but that seems to cause a class loading issue with fabric loader
tasks.shadowJar {

View File

@ -1,11 +1,11 @@
package io.gitlab.jfronny.libjf;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.metadata.CustomValue;
import net.neoforged.fml.ModList;
import net.neoforged.neoforgespi.language.IModInfo;
import org.jetbrains.annotations.ApiStatus;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
@ -14,25 +14,27 @@ public class Flags {
public static Set<StringFlag> getStringFlags(String name) {
return getFlags(name,
(source, value) -> new StringFlag(source, value),
(source, value) -> new StringFlag(source, value.getAsString()));
(source, value) -> value instanceof String s ? new StringFlag(source, s) : null);
}
public static Set<BooleanFlag> getBoolFlags(String name) {
return getFlags(name,
(source, value) -> new BooleanFlag(source, true),
(source, value) -> new BooleanFlag(source, value.getAsBoolean()));
(source, value) -> value instanceof Boolean b ? new BooleanFlag(source, b) : null);
}
private static <T> Set<T> getFlags(String name, BiFunction<String, String, T> makeFromProp, BiFunction<String, CustomValue, T> makeFromFmj) {
private static <T> Set<T> getFlags(String name, BiFunction<String, String, T> makeFromProp, BiFunction<String, Object, T> makeFromFmj) {
Set<T> flags = new LinkedHashSet<>();
String propName = "libjf." + name;
if (System.getProperty(propName) != null)
flags.add(makeFromProp.apply("System Property", System.getProperty(propName)));
for (ModContainer mod : FabricLoader.getInstance().getAllMods()) {
if (!mod.getMetadata().containsCustomValue("libjf")) continue;
CustomValue.CvObject co = mod.getMetadata().getCustomValue("libjf").getAsObject();
if (!co.containsKey(name)) continue;
flags.add(makeFromFmj.apply("Mod: " + mod.getMetadata().getId(), co.get(name)));
if (System.getProperty(propName) != null) {
T created = makeFromProp.apply("System Property", System.getProperty(propName));
if (created != null) flags.add(created);
}
for (IModInfo mod : ModList.get().getMods()) {
Map<String, Object> co = (Map<String, Object>) mod.getModProperties().get("libjf");
if (co == null || !co.containsKey(name)) continue;
T created = makeFromFmj.apply("Mod: " + mod.getModId(), co.get(name));
if (created != null) flags.add(created);
}
return flags;
}

View File

@ -4,23 +4,27 @@ import io.gitlab.jfronny.commons.logger.DelegateLogger;
import io.gitlab.jfronny.commons.logger.HotswapLoggerFinder;
import io.gitlab.jfronny.commons.logger.SystemLoggerPlus;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders;
import io.gitlab.jfronny.libjf.coprocess.CoProcessManager;
import io.gitlab.jfronny.libjf.gson.HiddenAnnotationExclusionStrategy;
import io.gitlab.jfronny.libjf.log.JULBridge;
import io.gitlab.jfronny.libjf.log.SLF4JPlatformLogger;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.common.NeoForge;
import org.slf4j.LoggerFactory;
public class LibJf implements PreLaunchEntrypoint {
@Mod(LibJf.MOD_ID)
public class LibJf {
public static final String MOD_ID = "libjf";
public static final SystemLoggerPlus LOGGER = SystemLoggerPlus.forName(MOD_ID);
public static final CoProcessManager CO_PROCESS = new CoProcessManager();
static {
HiddenAnnotationExclusionStrategy.register();
GsonHolders.registerSerializer();
}
@Override
public void onPreLaunch() {
public LibJf() {
NeoForge.EVENT_BUS.register(CO_PROCESS);
setup();
}

View File

@ -1,25 +1,41 @@
package io.gitlab.jfronny.libjf.coprocess;
import io.gitlab.jfronny.libjf.LibJf;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.event.server.ServerStoppedEvent;
import java.io.Closeable;
import java.io.IOException;
import java.util.*;
public class CoProcessManager implements ModInitializer {
public class CoProcessManager {
private boolean started = false;
private final List<CoProcess> coProcesses = new ArrayList<>();
@Override
public void onInitialize() {
coProcesses.addAll(FabricLoader.getInstance().getEntrypoints(LibJf.MOD_ID + ":coprocess", CoProcess.class));
@SubscribeEvent
public void onInitialize(FMLCommonSetupEvent event) {
synchronized (coProcesses) {
started = true;
}
Runtime.getRuntime().addShutdownHook(new Thread(this::stop));
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) ServerLifecycleEvents.SERVER_STOPPED.register(server -> this.stop());
start();
}
@SubscribeEvent
public void onServerStop(ServerStoppedEvent event) {
if (FMLEnvironment.dist == Dist.DEDICATED_SERVER) stop();
}
public void register(CoProcess coProcess) {
synchronized (coProcesses) {
if (started) throw new IllegalStateException("Cannot register co-process after initialization");
coProcesses.add(coProcess);
}
}
private void start() {
for (CoProcess coProcess : coProcesses) {
coProcess.start();

View File

@ -1,30 +0,0 @@
package io.gitlab.jfronny.libjf.gson;
import io.gitlab.jfronny.gson.*;
import net.fabricmc.loader.api.metadata.CustomValue;
import java.util.Map;
public class FabricLoaderGsonGenerator {
public static JsonElement toGson(CustomValue customValue) {
if (customValue == null) return null;
return switch (customValue.getType()) {
case OBJECT -> {
JsonObject jo = new JsonObject();
for (Map.Entry<String, CustomValue> value : customValue.getAsObject())
jo.add(value.getKey(), toGson(value.getValue()));
yield jo;
}
case ARRAY -> {
JsonArray jo = new JsonArray();
for (CustomValue value : customValue.getAsArray())
jo.add(toGson(value));
yield jo;
}
case STRING -> new JsonPrimitive(customValue.getAsString());
case NUMBER -> new JsonPrimitive(customValue.getAsNumber());
case BOOLEAN -> new JsonPrimitive(customValue.getAsBoolean());
case NULL -> JsonNull.INSTANCE;
};
}
}

View File

@ -0,0 +1,33 @@
package io.gitlab.jfronny.libjf.gson;
import io.gitlab.jfronny.gson.*;
import java.util.List;
import java.util.Map;
public class ForgeGsonGenerator {
public static JsonElement toGson(Object customValue) {
//TODO use pattern matching for switch
if (customValue == null) {
return JsonNull.INSTANCE;
} else if (customValue instanceof Map<?, ?> map) {
JsonObject jo = new JsonObject();
for (Map.Entry<?, ?> value : map.entrySet())
jo.add((String) value.getKey(), toGson(value.getValue()));
return jo;
} else if (customValue instanceof List<?> array) {
JsonArray jo = new JsonArray();
for (Object value : array)
jo.add(toGson(value));
return jo;
} else if (customValue instanceof String s) {
return new JsonPrimitive(s);
} else if (customValue instanceof Number n) {
return new JsonPrimitive(n);
} else if (customValue instanceof Boolean b) {
return new JsonPrimitive(b);
} else {
throw new IllegalArgumentException("Unsupported type: " + customValue.getClass());
}
}
}

View File

@ -3,15 +3,15 @@ package io.gitlab.jfronny.libjf.gson;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders;
import io.gitlab.jfronny.gson.ExclusionStrategy;
import io.gitlab.jfronny.gson.FieldAttributes;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.loading.FMLEnvironment;
public class HiddenAnnotationExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT
return FMLEnvironment.dist == Dist.CLIENT
? fieldAttributes.getAnnotation(ServerOnly.class) != null
: fieldAttributes.getAnnotation(ClientOnly.class) != null;
}

View File

@ -4,13 +4,12 @@ import io.gitlab.jfronny.commons.logger.HotswapLoggerFinder;
import io.gitlab.jfronny.commons.logger.LeveledLoggerFinder;
import io.gitlab.jfronny.commons.logger.SystemLoggerPlus;
import org.jetbrains.annotations.Nullable;
import org.slf4j.LoggerFactory;
public class EarlyLoggerSetup extends LeveledLoggerFinder {
static {
// When a logger is used before the game is initialized, SLF4J is not yet available.
// To support that, this implementation which redirects to Fabric Loader's internal logging abstraction is used instead.
// After the game is initialized, something calls LibJF.setup (usually preEntry), which replaces this factory with a SLF4J-based one.
HotswapLoggerFinder.updateAllStrategies((name, module, level) -> new LoaderPlatformLogger(name));
// On Forge, we shouldn't run the risk of initializing too early, so this should be fine.
HotswapLoggerFinder.updateAllStrategies((name, module, level) -> new SLF4JPlatformLogger(LoggerFactory.getLogger(name)));
}
private final LeveledLoggerFinder delegate = new HotswapLoggerFinder();

View File

@ -1,57 +0,0 @@
package io.gitlab.jfronny.libjf.log;
import io.gitlab.jfronny.commons.logger.CompactLogger;
import net.fabricmc.loader.impl.util.log.Log;
import net.fabricmc.loader.impl.util.log.LogCategory;
import net.fabricmc.loader.impl.util.log.LogLevel;
public class LoaderPlatformLogger implements CompactLogger {
private final LogCategory category;
public LoaderPlatformLogger(String context, String... names) {
this.category = LogCategory.createCustom(context, names);
}
@Override
public String getName() {
return category.name;
}
@Override
public Level getLevel() {
for (Level value : Level.values()) {
if (value == Level.ALL || value == Level.OFF) continue;
if (isLoggable(value)) return value;
}
return Level.INFO; // should not happen, but if it does, INFO is a reasonable default
}
@Override
public void log(Level level, String message) {
Log.log(jplLevelToFabricLevel(level), category, message);
}
@Override
public void log(Level level, String message, Throwable throwable) {
Log.log(jplLevelToFabricLevel(level), category, message, throwable);
}
@Override
public boolean isLoggable(Level level) {
if (level == Level.ALL) return true;
if (level == Level.OFF) return false;
return Log.shouldLog(jplLevelToFabricLevel(level), category);
}
private LogLevel jplLevelToFabricLevel(Level jplLevel) {
return switch (jplLevel) {
case TRACE -> LogLevel.TRACE;
case DEBUG -> LogLevel.DEBUG;
case INFO -> LogLevel.INFO;
case WARNING -> LogLevel.WARN;
case ERROR -> LogLevel.ERROR;
// should not happen, but if it does, INFO is a reasonable default
default -> LogLevel.INFO;
};
}
}

View File

@ -0,0 +1,25 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-base"
version = "${version}"
displayName = "LibJF Base"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-base]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-base]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"

View File

@ -1,30 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-base",
"name": "LibJF Base",
"version": "${version}",
"authors": ["JFronny"],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "*",
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"fabric-lifecycle-events-v1": "*"
},
"entrypoints": {
"main": ["io.gitlab.jfronny.libjf.coprocess.CoProcessManager"],
"preLaunch": ["io.gitlab.jfronny.libjf.LibJf"]
},
"custom": {
"modmenu": {
"parent": "libjf",
"badges": ["library"]
}
}
}

View File

@ -11,5 +11,11 @@ base {
dependencies {
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
include(modImplementation("net.fabricmc.fabric-api:fabric-command-api-v2")!!)
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -11,12 +11,14 @@ import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.*;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type;
import io.gitlab.jfronny.libjf.config.impl.ConfigCore;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Language;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import java.util.function.Consumer;
import java.util.function.Function;
@ -24,48 +26,51 @@ import java.util.function.Function;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
public class JfConfigCommand implements ModInitializer {
private static final String MOD_ID = "libjf-config-commands";
@Mod(JfConfigCommand.MOD_ID)
public class JfConfigCommand {
public static final String MOD_ID = "libjf-config-commands";
private MutableText text(String text) {
return Text.literal("[" + MOD_ID + "] " + text);
}
@Override
public void onInitialize() {
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
LiteralArgumentBuilder<ServerCommandSource> c_libjf = literal(LibJf.MOD_ID);
LiteralArgumentBuilder<ServerCommandSource> c_config = literal("config")
.requires((serverCommandSource) -> serverCommandSource.hasPermissionLevel(4))
.executes(context -> {
MutableText text = text("Loaded configs for:");
ConfigHolder.getInstance().getRegistered().forEach((s, config) -> text.append("\n- " + s));
context.getSource().sendFeedback(() -> text, false);
return Command.SINGLE_SUCCESS;
});
LiteralArgumentBuilder<ServerCommandSource> c_reload = literal("reload").executes(context -> {
ConfigHolder.getInstance().getRegistered().forEach((mod, config) -> config.load());
context.getSource().sendFeedback(() -> text("Reloaded configs"), true);
return Command.SINGLE_SUCCESS;
});
LiteralArgumentBuilder<ServerCommandSource> c_reset = literal("reset").executes(context -> {
context.getSource().sendError(text("Please specify a config to reset"));
return Command.SINGLE_SUCCESS;
});
ConfigHolder.getInstance().getRegistered().forEach((id, config) -> {
c_reload.then(literal(id).executes(context -> {
config.load();
context.getSource().sendFeedback(() -> text("Reloaded config for " + id), true);
public JfConfigCommand() {
NeoForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void onRegisterCommands(RegisterCommandsEvent event) {
LiteralArgumentBuilder<ServerCommandSource> c_libjf = literal(LibJf.MOD_ID);
LiteralArgumentBuilder<ServerCommandSource> c_config = literal("config")
.requires((serverCommandSource) -> serverCommandSource.hasPermissionLevel(4))
.executes(context -> {
MutableText text = text("Loaded configs for:");
ConfigHolder.getInstance().getRegistered().forEach((s, config) -> text.append("\n- " + s));
context.getSource().sendFeedback(() -> text, false);
return Command.SINGLE_SUCCESS;
}));
registerEntries(config, id, c_config, c_reset, cns -> {
LiteralArgumentBuilder<ServerCommandSource> c_instance = literal(id);
cns.accept(c_instance);
return c_instance;
});
});
dispatcher.register(c_libjf.then(c_config.then(c_reload).then(c_reset)));
LiteralArgumentBuilder<ServerCommandSource> c_reload = literal("reload").executes(context -> {
ConfigHolder.getInstance().getRegistered().forEach((mod, config) -> config.load());
context.getSource().sendFeedback(() -> text("Reloaded configs"), true);
return Command.SINGLE_SUCCESS;
});
LiteralArgumentBuilder<ServerCommandSource> c_reset = literal("reset").executes(context -> {
context.getSource().sendError(text("Please specify a config to reset"));
return Command.SINGLE_SUCCESS;
});
ConfigHolder.getInstance().getRegistered().forEach((id, config) -> {
c_reload.then(literal(id).executes(context -> {
config.load();
context.getSource().sendFeedback(() -> text("Reloaded config for " + id), true);
return Command.SINGLE_SUCCESS;
}));
registerEntries(config, id, c_config, c_reset, cns -> {
LiteralArgumentBuilder<ServerCommandSource> c_instance = literal(id);
cns.accept(c_instance);
return c_instance;
});
});
event.getDispatcher().register(c_libjf.then(c_config.then(c_reload).then(c_reset)));
}
private void registerEntries(ConfigCategory config, String subpath, LiteralArgumentBuilder<ServerCommandSource> c_config, LiteralArgumentBuilder<ServerCommandSource> c_reset, Function<Consumer<LiteralArgumentBuilder<ServerCommandSource>>, LiteralArgumentBuilder<ServerCommandSource>> pathGen) {

View File

@ -0,0 +1,39 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-config-commands"
version = "${version}"
displayName = "LibJF Config Commands"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-config-commands]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-config-commands]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-config-commands]]
modId = "libjf-base"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-config-commands]]
modId = "libjf-config-core-v2"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"

View File

@ -1,31 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-config-commands",
"name": "LibJF Config Commands",
"version": "${version}",
"authors": ["JFronny"],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "*",
"entrypoints": {
"main": ["io.gitlab.jfronny.libjf.config.impl.commands.JfConfigCommand"]
},
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"fabric-command-api-v2": "*",
"libjf-base": ">=${version}",
"libjf-config-core-v2": ">=${version}"
},
"custom": {
"modmenu": {
"badges": ["library"],
"parent": "libjf"
}
}
}

View File

@ -10,5 +10,11 @@ base {
dependencies {
api(devProject(":libjf-base"))
modCompileOnly(libs.modmenu)
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -1,27 +1,22 @@
package io.gitlab.jfronny.libjf.config.impl.ui;
import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory;
import net.fabricmc.loader.api.FabricLoader;
import java.util.Comparator;
import java.util.List;
public class ConfigScreenFactoryDiscovery {
private static ConfigScreenFactory<?, ?> discovered2 = null;
public static io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory<?, ?> getConfigured2() {
if (discovered2 == null) {
discovered2 = getEntrypoints()
.stream()
.filter(it -> it instanceof io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory<?,?>)
.<ConfigScreenFactory<?, ?>>map(it -> (ConfigScreenFactory<?, ?>) it)
.max(Comparator.comparing(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory::getPriority))
.orElseGet(PlaceholderScreenFactory::new);
return new PlaceholderScreenFactory();
}
return discovered2;
}
private static List<Object> getEntrypoints() {
return FabricLoader.getInstance().getEntrypoints("libjf:config_screen", Object.class);
public static void register(Object factory) {
if (factory instanceof ConfigScreenFactory<?,?> f) {
if (discovered2 == null || f.getPriority() > discovered2.getPriority()) {
discovered2 = f;
}
}
}
}

View File

@ -1,32 +1,33 @@
package io.gitlab.jfronny.libjf.config.impl.ui;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance;
import io.gitlab.jfronny.libjf.config.impl.ConfigCore;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModList;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.client.ConfigScreenHandler;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
public class ModMenuAdapter implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return buildFactory(ConfigCore.CONFIG_INSTANCE);
public class ModMenuAdapter {
public static void register(String modId, ConfigInstance config) {
ModList.get().getModContainerById(modId).ifPresent(modContainer -> {
modContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory(buildFactory(config)));
});
}
@Override
public Map<String, ConfigScreenFactory<?>> getProvidedConfigScreenFactories() {
Map<String, ConfigScreenFactory<?>> factories = new HashMap<>();
@SubscribeEvent
public void onInitialize(FMLCommonSetupEvent event) {
// In case we missed something
for (Map.Entry<String, ConfigInstance> entry : ConfigHolder.getInstance().getRegistered().entrySet()) {
if (!LibJf.MOD_ID.equals(entry.getKey()))
factories.put(entry.getKey(), buildFactory(entry.getValue()));
register(entry.getKey(), entry.getValue());
}
return factories;
}
private static ConfigScreenFactory<?> buildFactory(ConfigInstance config) {
return s -> io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory.getInstance().create(config, s).get();
private static BiFunction<MinecraftClient, Screen, Screen> buildFactory(ConfigInstance config) {
return (client, screen) -> io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory.getInstance().create(config, screen).get();
}
}

View File

@ -4,13 +4,13 @@ import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders;
import io.gitlab.jfronny.libjf.config.api.v2.Category;
import io.gitlab.jfronny.libjf.config.api.v2.JfConfig;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import io.gitlab.jfronny.libjf.gson.FabricLoaderGsonGenerator;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.metadata.CustomValue;
import io.gitlab.jfronny.libjf.gson.ForgeGsonGenerator;
import net.neoforged.fml.ModList;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import static io.gitlab.jfronny.libjf.config.impl.ConfigCore.MODULE_ID;
@ -35,16 +35,11 @@ public class AuxiliaryMetadata {
var metaRef = new Object() {
AuxiliaryMetadata meta = null;
};
FabricLoader.getInstance().getModContainer(modId).ifPresent(container -> {
CustomValue cv = container.getMetadata().getCustomValue(MODULE_ID);
if (cv == null) {
cv = container.getMetadata().getCustomValue("libjf");
if (cv != null) {
cv = cv.getAsObject().get("config");
}
}
if (cv != null) metaRef.meta = GsonHolders.API.getGson().fromJson(FabricLoaderGsonGenerator.toGson(cv), AuxiliaryMetadata.class);
});
ModList.get().getModContainerById("")
.flatMap(s -> Optional.ofNullable(s.getModInfo().getModProperties().get(MODULE_ID)))
.ifPresent(cv -> {
metaRef.meta = GsonHolders.API.getGson().fromJson(ForgeGsonGenerator.toGson(cv), AuxiliaryMetadata.class);
});
return metaRef.meta;
}

View File

@ -1,9 +1,16 @@
package io.gitlab.jfronny.libjf.config.impl;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL;
import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
import io.gitlab.jfronny.libjf.config.impl.ui.ModMenuAdapter;
import io.gitlab.jfronny.libjf.config.impl.watch.ToggleableConfigWatchService;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.common.NeoForge;
@Mod(ConfigCore.MOD_ID)
public class ConfigCore {
public static final String MOD_ID = "libjf-config-core-v2";
public static final String MODULE_ID = "libjf:config";
@ -16,4 +23,10 @@ public class ConfigCore {
.value("watchForChanges", watchForChanges, () -> watchForChanges, b -> watchForChanges = b)
);
}
public ConfigCore() {
NeoForge.EVENT_BUS.register(new ModMenuAdapter());
JfConfigSafe.initialize();
LibJf.CO_PROCESS.register(new ToggleableConfigWatchService());
}
}

View File

@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableMap;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance;
import net.fabricmc.loader.api.FabricLoader;
import io.gitlab.jfronny.libjf.config.impl.ui.ModMenuAdapter;
import net.neoforged.fml.ModList;
import net.neoforged.fml.loading.FMLPaths;
import org.jetbrains.annotations.ApiStatus;
import java.io.IOException;
@ -29,6 +31,7 @@ public class ConfigHolderImpl implements ConfigHolder {
}
LibJf.LOGGER.info("Registering config for " + modId);
configs.put(modId, config);
ModMenuAdapter.register(modId, config);
config.getFilePath().ifPresent(path -> configsByPath.put(path, config));
}
@ -59,7 +62,7 @@ public class ConfigHolderImpl implements ConfigHolder {
@Override
public void migrateFiles(String modId) {
Path cfg = FabricLoader.getInstance().getConfigDir();
Path cfg = FMLPaths.CONFIGDIR.get();
Path target = cfg.resolve(modId + ".json5");
if (Files.exists(target)) return;
if (Files.exists(cfg.resolve(modId + ".json"))) {
@ -68,20 +71,6 @@ public class ConfigHolderImpl implements ConfigHolder {
} catch (IOException ignored) {
}
}
FabricLoader.getInstance().getModContainer(modId).ifPresent(mod -> {
try {
for (String id : mod.getMetadata().getProvides()) {
if (Files.exists(cfg.resolve(id + ".json"))) {
Files.move(cfg.resolve(id + ".json"), target);
return;
}
if (Files.exists(cfg.resolve(id + ".json5"))) {
Files.move(cfg.resolve(id + ".json5"), target);
return;
}
}
} catch (IOException ignored) {
}
});
// "provides" is not a thing on Forge
}
}

View File

@ -2,7 +2,7 @@ package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.ConfigBuilder;
import net.fabricmc.loader.api.FabricLoader;
import net.neoforged.fml.loading.FMLPaths;
import java.nio.file.Path;
import java.util.function.Consumer;
@ -17,7 +17,7 @@ public class ConfigBuilderImpl extends CategoryBuilderImpl<ConfigBuilderImpl> im
super(id, "");
load = DefaultConfigIO.loader(id);
write = DefaultConfigIO.writer(id);
path = FabricLoader.getInstance().getConfigDir().resolve(id + ".json5");
path = FMLPaths.CONFIGDIR.get().resolve(id + ".json5");
}
@Override

View File

@ -1,30 +1,19 @@
package io.gitlab.jfronny.libjf.config.impl.entrypoint;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.JfCustomConfig;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL;
import io.gitlab.jfronny.libjf.config.impl.ConfigCore;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.entrypoint.EntrypointContainer;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import net.minecraft.util.Language;
import java.util.HashSet;
import java.util.Set;
import java.util.function.UnaryOperator;
public class JfConfigSafe implements PreLaunchEntrypoint {
public class JfConfigSafe {
public static UnaryOperator<String> TRANSLATION_SUPPLIER = s -> null;
public static final Set<String> REGISTERED_MODS = new HashSet<>();
@Override
public void onPreLaunch() {
public static void initialize() {
LibJf.setup();
for (EntrypointContainer<Object> custom : FabricLoader.getInstance().getEntrypointContainers(ConfigCore.MODULE_ID, Object.class)) {
String id = custom.getProvider().getMetadata().getId();
if (custom.getEntrypoint() instanceof JfCustomConfig cfg && REGISTERED_MODS.add(id)) {
cfg.register(DSL.create(id));
}
}
// On Forge, configs need to be registered manually
TRANSLATION_SUPPLIER = s -> {
String translated;
try {

View File

@ -3,7 +3,7 @@ package io.gitlab.jfronny.libjf.config.impl.watch;
import io.gitlab.jfronny.commons.throwable.ThrowingRunnable;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder;
import net.fabricmc.loader.api.FabricLoader;
import net.neoforged.fml.loading.FMLPaths;
import java.io.IOException;
import java.nio.file.*;
@ -15,7 +15,7 @@ import java.util.Set;
import static java.nio.file.StandardWatchEventKinds.*;
public class JfConfigWatchServiceImpl implements JfConfigWatchService {
private static final Path CONFIG_DIR = FabricLoader.getInstance().getConfigDir();
private static final Path CONFIG_DIR = FMLPaths.CONFIGDIR.get();
private static final Set<JfConfigWatchServiceImpl> REGISTERED_INSTANCES = new HashSet<>();
private final WatchService service;
private static final Map<Path, Integer> locked = new HashMap<>();

View File

@ -0,0 +1,32 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-config-core-v2"
version = "${version}"
displayName = "LibJF Config Core"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-config-core-v2]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-config-core-v2]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-config-core-v2]]
modId = "libjf-base"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"

View File

@ -1,33 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-config-core-v2",
"provides": ["libjf-config-core-v1"],
"name": "LibJF Config",
"version": "${version}",
"authors": ["JFronny"],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "*",
"entrypoints": {
"preLaunch": ["io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe"],
"libjf:coprocess": ["io.gitlab.jfronny.libjf.config.impl.watch.ToggleableConfigWatchService"],
"libjf:config_screen": ["io.gitlab.jfronny.libjf.config.impl.ui.PlaceholderScreenFactory"],
"modmenu": ["io.gitlab.jfronny.libjf.config.impl.ui.ModMenuAdapter"]
},
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"libjf-base": ">=${version}"
},
"custom": {
"modmenu": {
"badges": ["library"],
"parent": "libjf"
}
}
}

View File

@ -11,7 +11,4 @@ base {
dependencies {
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
modCompileOnly(libs.modmenu)
include(modImplementation("net.fabricmc.fabric-api:fabric-networking-api-v1")!!)
include(modImplementation("net.fabricmc.fabric-api:fabric-command-api-v2")!!)
}

View File

@ -8,12 +8,15 @@ import io.gitlab.jfronny.libjf.config.impl.network.RequestRouter;
import io.gitlab.jfronny.libjf.config.impl.network.rci.MirrorConfigHolder;
import io.gitlab.jfronny.libjf.config.impl.ui.PlaceholderScreen;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
public class JfConfigNetworkModMenu implements ModMenuApi {
@Override
public com.terraformersmc.modmenu.api.ConfigScreenFactory<?> getModConfigScreenFactory() {
return parent -> {
import java.util.function.BiFunction;
public class JfConfigNetworkModMenu {
public BiFunction<MinecraftClient, Screen, Screen> getModConfigScreenFactory() {
return (client, parent) -> {
if (!JfConfigNetworkClient.isAvailable) return new PlaceholderScreen(
parent,
Text.translatable(RequestRouter.MOD_ID + ".modmenu.unavailable.title"),

View File

@ -1,13 +1,22 @@
package io.gitlab.jfronny.libjf.config.impl.network;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.impl.network.client.JfConfigNetworkClient;
import io.gitlab.jfronny.libjf.config.impl.network.client.JfConfigNetworkModMenu;
import io.gitlab.jfronny.libjf.config.impl.network.server.JfConfigNetworkServer;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
import net.neoforged.fml.DistExecutor;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.client.ConfigScreenHandler;
import java.util.*;
@Mod(RequestRouter.MOD_ID)
public class RequestRouter {
public static final String MOD_ID = "libjf-config-network-v0";
public static final Identifier RESPONSE_ID = new Identifier(MOD_ID, "response");
@ -18,6 +27,17 @@ public class RequestRouter {
private static final Map<Long, Request> currentRequests = new HashMap<>(); //TODO implement timeout and prune old requests
private static final Random random = new Random();
public RequestRouter() {
if (FMLEnvironment.dist.isClient()) {
ModList.get().getModContainerById(MOD_ID).ifPresent(container -> {
container.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory(new JfConfigNetworkModMenu().getModConfigScreenFactory()));
});
JfConfigNetworkClient.initialize();
} else {
JfConfigNetworkServer.initialize();
}
}
public static void acceptResponse(PacketByteBuf buf, PacketSender responseSender) {
Request request = currentRequests.remove(buf.readLong());
if (request != null) {

View File

@ -11,5 +11,11 @@ base {
dependencies {
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
include("net.fabricmc.fabric-api:fabric-resource-loader-v0")
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -0,0 +1,11 @@
package io.gitlab.jfronny.libjf.config.impl.ui.tiny;
import io.gitlab.jfronny.libjf.config.impl.ui.ConfigScreenFactoryDiscovery;
import net.neoforged.fml.common.Mod;
@Mod("libjf-config-ui-tiny")
public class ConfigUITiny {
public ConfigUITiny() {
ConfigScreenFactoryDiscovery.register(new TinyConfigScreenFactory());
}
}

View File

@ -9,8 +9,6 @@ import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.EntryListWidget;
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.WidgetState;
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.presets.PresetsScreen;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
@ -24,10 +22,13 @@ import net.minecraft.screen.ScreenTexts;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
import net.neoforged.api.distmarker.OnlyIn;
import java.util.*;
@Environment(EnvType.CLIENT)
import static net.neoforged.api.distmarker.Dist.CLIENT;
@OnlyIn(CLIENT)
public class TinyConfigScreen extends ScreenWithSaveHook {
public static Text getTitle(String categoryPath) {
final String titlePath = categoryPath + "title";

View File

@ -9,8 +9,6 @@ import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type;
import io.gitlab.jfronny.libjf.config.impl.ConfigCore;
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.EditorScreen;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.resource.language.I18n;
@ -18,6 +16,7 @@ import net.minecraft.client.toast.SystemToast;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Language;
import net.neoforged.api.distmarker.OnlyIn;
import java.util.LinkedList;
import java.util.List;
@ -25,7 +24,9 @@ import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
@Environment(EnvType.CLIENT)
import static net.neoforged.api.distmarker.Dist.CLIENT;
@OnlyIn(CLIENT)
public class EntryInfoWidgetBuilder {
private static final Pattern INTEGER_ONLY = Pattern.compile("(-?\\d*)");
private static final Pattern DECIMAL_ONLY = Pattern.compile("-?(\\d+\\.?\\d*|\\d*\\.?\\d+|\\.)");

View File

@ -1,7 +1,5 @@
package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.*;
@ -9,14 +7,16 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.*;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.text.*;
import net.minecraft.util.math.MathHelper;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
@Environment(EnvType.CLIENT)
import static net.neoforged.api.distmarker.Dist.CLIENT;
@OnlyIn(CLIENT)
public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEntry> {
private final TextRenderer textRenderer;
private final boolean background;
@ -95,7 +95,7 @@ public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEnt
if (getScrollAmount() < getMaxScroll()) context.fillGradient(RenderLayer.getGuiOverlay(), getX(), getBottom() - 4, getRight(), getBottom(), 0x00000000, 0xff000000, 0);
}
@Environment(EnvType.CLIENT)
@OnlyIn(CLIENT)
public abstract static class ConfigEntry extends Entry<ConfigEntry> implements Reflowable {
@Override
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
@ -105,7 +105,7 @@ public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEnt
}
}
@Environment(EnvType.CLIENT)
@OnlyIn(CLIENT)
public class ConfigTextEntry extends ConfigEntry {
private int width;
private final OrderedText text;
@ -169,7 +169,7 @@ public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEnt
}
}
@Environment(EnvType.CLIENT)
@OnlyIn(CLIENT)
public static class ConfigReferenceEntry extends ConfigEntry {
private final ClickableWidget button;
@ -202,7 +202,7 @@ public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEnt
}
}
@Environment(EnvType.CLIENT)
@OnlyIn(CLIENT)
public static class ConfigScreenEntry extends ConfigEntry {
private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
public final ClickableWidget button;
@ -251,7 +251,7 @@ public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEnt
}
}
@Environment(EnvType.CLIENT)
@OnlyIn(CLIENT)
public static class ConfigUnknownEntry extends ConfigEntry {
private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
private final BooleanSupplier resetVisible;

View File

@ -3,17 +3,18 @@ package io.gitlab.jfronny.libjf.config.impl.ui.tiny.presets;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigCategory;
import io.gitlab.jfronny.libjf.config.impl.ConfigCore;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text;
import net.neoforged.api.distmarker.OnlyIn;
import java.util.Map;
import java.util.Objects;
@Environment(EnvType.CLIENT)
import static net.neoforged.api.distmarker.Dist.CLIENT;
@OnlyIn(CLIENT)
public class PresetsScreen extends Screen {
private final Screen parent;
private final ConfigCategory config;

View File

@ -0,0 +1,39 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-config-ui-tiny"
version = "${version}"
displayName = "LibJF Config UI: Tiny"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-config-ui-tiny]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-config-ui-tiny]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-config-ui-tiny]]
modId = "libjf-base"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-config-ui-tiny]]
modId = "libjf-config-core-v2"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"

View File

@ -1,31 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-config-ui-tiny",
"name": "LibJF Config UI: Tiny",
"version": "${version}",
"authors": ["JFronny"],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "client",
"entrypoints": {
"libjf:config_screen": ["io.gitlab.jfronny.libjf.config.impl.ui.tiny.TinyConfigScreenFactory"]
},
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"fabric-resource-loader-v0": "*",
"libjf-base": ">=${version}",
"libjf-config-core-v2": ">=${version}"
},
"custom": {
"modmenu": {
"badges": ["library"],
"parent": "libjf"
}
}
}

View File

@ -10,6 +10,11 @@ base {
dependencies {
api(devProject(":libjf-base"))
api(devProject(":libjf-unsafe-v0"))
modApi("net.fabricmc.fabric-api:fabric-api-base")
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -0,0 +1,35 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-data-manipulation-v0"
version = "${version}"
displayName = "LibJF Data Manipulation"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-data-manipulation-v0]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-data-manipulation-v0]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-data-manipulation-v0]]
modId = "libjf-base"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"
[[mixins]]
config = "libjf-data-manipulation-v0.mixins.json"

View File

@ -1,36 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-data-manipulation-v0",
"name": "LibJF Data Manipulation",
"version": "${version}",
"authors": [
"JFronny"
],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "*",
"mixins": ["libjf-data-manipulation-v0.mixins.json"],
"entrypoints": {
"libjf:asm": [
"io.gitlab.jfronny.libjf.data.manipulation.impl.ResourcePackHookPatch"
]
},
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"fabric-api-base": "*",
"libjf-base": ">=${version}",
"libjf-unsafe-v0": ">=${version}"
},
"custom": {
"modmenu": {
"parent": "libjf",
"badges": ["library"]
}
}
}

View File

@ -10,5 +10,11 @@ base {
dependencies {
api(devProject(":libjf-base"))
include("net.fabricmc.fabric-api:fabric-resource-loader-v0")
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -0,0 +1,35 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-data-v0"
version = "${version}"
displayName = "LibJF Data"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-data-v0]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-data-v0]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-data-v0]]
modId = "libjf-base"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"
[[mixins]]
config = "libjf-data-v0.mixins.json"

View File

@ -1,30 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-data-v0",
"name": "LibJF Data",
"version": "${version}",
"authors": [
"JFronny"
],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "*",
"mixins": ["libjf-data-v0.mixins.json"],
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"fabric-resource-loader-v0": "*",
"libjf-base": ">=${version}"
},
"custom": {
"modmenu": {
"parent": "libjf",
"badges": ["library"]
}
}
}

View File

@ -15,3 +15,10 @@ base {
dependencies {
api(devProject(":libjf-base"))
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -0,0 +1,38 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-devutil"
version = "${version}"
displayName = "LibJF Development Util"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-devutil]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-devutil]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-devutil]]
modId = "libjf-base"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"
[[mixins]]
config = "libjf-devutil.mixins.json"
[[mixins]]
config = "libjf-devutil.client.mixins.json"

View File

@ -1,40 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-devutil",
"name": "LibJF Development Util",
"version": "${version}",
"authors": [
"JFronny"
],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "*",
"entrypoints": {
"main": [
"io.gitlab.jfronny.libjf.devutil.DevUtilMain"
]
},
"mixins": [
"libjf-devutil-v0.mixins.json",
{
"config": "libjf-devutil-v0.client.mixins.json",
"environment": "client"
}
],
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"libjf-base": ">=${version}"
},
"custom": {
"modmenu": {
"parent": "libjf",
"badges": ["library"]
}
}
}

View File

@ -7,5 +7,11 @@ base {
}
dependencies {
modImplementation("net.fabricmc.fabric-api:fabric-api-base")
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -0,0 +1,28 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-mainhttp-v0"
version = "${version}"
displayName = "LibJF MainHTTP"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-mainhttp-v0]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-mainhttp-v0]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[mixins]]
config = "libjf-mainhttp-v0.mixins.json"

View File

@ -1,28 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-mainhttp-v0",
"name": "LibJF MainHTTP",
"version": "${version}",
"authors": [
"JFronny"
],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "*",
"mixins": ["libjf-mainhttp-v0.mixins.json"],
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*"
},
"custom": {
"modmenu": {
"parent": "libjf",
"badges": ["library"]
}
}
}

View File

@ -12,3 +12,10 @@ dependencies {
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -0,0 +1,32 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-translate-v1"
version = "${version}"
displayName = "LibJF Translate"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-translate-v1]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-translate-v1]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-translate-v1]]
modId = "libjf-base"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"

View File

@ -1,31 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-translate-v1",
"name": "LibJF Translate",
"version": "${version}",
"environment": "*",
"license": "MIT",
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"authors": [
"JFronny"
],
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"libjf-base": ">=${version}"
},
"entrypoints": {
"libjf:config": ["io.gitlab.jfronny.libjf.translate.impl.TranslateConfig"]
},
"custom": {
"modmenu": {
"parent": "libjf",
"badges": ["library"]
}
}
}

View File

@ -12,11 +12,17 @@ dependencies {
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
api(devProject(":libjf-mainhttp-v0"))
include(modImplementation("net.fabricmc.fabric-api:fabric-command-api-v2")!!)
annotationProcessor(project(":libjf-config-compiler-plugin-v2"))
annotationProcessor("io.gitlab.jfronny.libjf:libjf-config-compiler-plugin-v2:${libs.versions.libjf.fabric.version.get()}")
}
tasks.compileJava {
options.compilerArgs.add("-AmodId=" + base.archivesName.get())
}
sourceSets {
main {
java.srcDir("src/client/java")
resources.srcDir("src/client/resources")
}
}

View File

@ -0,0 +1,32 @@
modLoader = "javafml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf-web-v1"
version = "${version}"
displayName = "LibJF Web"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf-web-v1]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-web-v1]]
modId = "minecraft"
type = "required"
versionRange = "[${minecraft_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf-web-v1]]
modId = "libjf-base"
type = "required"
versionRange = "[${version},)"
ordering = "NONE"
side = "BOTH"

View File

@ -1,38 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf-web-v1",
"provides": ["libjf-web-v0"],
"name": "LibJF Web",
"version": "${version}",
"authors": [
"JFronny"
],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"environment": "*",
"entrypoints": {
"main": ["io.gitlab.jfronny.libjf.web.impl.JfWeb"],
"libjf:coprocess": ["io.gitlab.jfronny.libjf.web.impl.JfWeb"],
"libjf:config": ["io.gitlab.jfronny.libjf.web.impl.JFC_JfWebConfig"],
"libjf-mainhttp:v0": ["io.gitlab.jfronny.libjf.web.impl.variant.shared.MainHttpHandlerImpl"]
},
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"libjf-base": ">=${version}",
"libjf-config-core-v2": ">=${version}",
"libjf-mainhttp-v0": ">=${version}",
"fabric-command-api-v2": "*"
},
"custom": {
"modmenu": {
"parent": "libjf",
"badges": ["library"]
}
}
}

View File

@ -18,9 +18,7 @@ include("libjf-base")
include("libjf-config-core-v2")
include("libjf-config-commands")
include("libjf-config-network-v0")
include("libjf-config-ui-tiny")
include("libjf-config-compiler-plugin-v2")
include("libjf-data-v0")
include("libjf-data-manipulation-v0")
@ -29,8 +27,6 @@ include("libjf-devutil")
include("libjf-translate-v1")
include("libjf-unsafe-v0")
include("libjf-mainhttp-v0")
include("libjf-web-v1")

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,29 @@
modLoader = "lowcodefml"
loaderVersion = "[1,)"
issueTrackerURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues"
license = "MIT"
[[mods]]
modId = "libjf"
version = "${version}"
displayName = "LibJF"
description = '''
Library mod by JFronny
'''
logoFile = "icon.png"
authors = "JFronny"
displayURL = "https://git.frohnmeyer-wds.de/JfMods/LibJF"
[[dependencies.libjf]]
modId = "neoforge"
type = "required"
versionRange = "[${loader_version},)"
ordering = "NONE"
side = "BOTH"
[[dependencies.libjf]]
modId = "minecraft"
type = "required"
versionRange = "${minecraft_version}"
ordering = "NONE"
side = "BOTH"

View File

@ -1,30 +0,0 @@
{
"schemaVersion": 1,
"id": "libjf",
"name": "LibJF",
"version": "${version}",
"description": "Library mod by JFronny",
"authors": ["JFronny"],
"contact": {
"email": "projects.contact@frohnmeyer-wds.de",
"homepage": "https://jfronny.gitlab.io",
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
},
"license": "MIT",
"icon": "assets/libjf/icon.png",
"environment": "*",
"entrypoints": {},
"depends": {
"fabricloader": ">=0.12.0",
"minecraft": "*",
"fabric-resource-loader-v0": "*",
"fabric-lifecycle-events-v1": "*",
"fabric-command-api-v2": "*"
},
"custom": {
"modmenu": {
"badges": ["library"]
}
}
}