Allow exporting modified classes and fix config

This commit is contained in:
JFronny 2021-10-16 16:15:22 +02:00
parent 7c78258bb3
commit c78f6d13b3
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
22 changed files with 167 additions and 78 deletions

View File

@ -6,7 +6,7 @@ minecraft_version=1.17.1
yarn_mappings=build.61
loader_version=0.12.1
# Mod Properties
mod_version=2.0.1
mod_version=2.1.0
maven_group=io.gitlab.jfronny
archives_base_name=libjf

View File

@ -0,0 +1,46 @@
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 org.jetbrains.annotations.ApiStatus;
import java.util.LinkedHashSet;
import java.util.Set;
@ApiStatus.Internal
public class Flags {
public static Set<StringFlag> getStringFlags(String name) {
Set<StringFlag> flags = new LinkedHashSet<>();
String propName = LibJf.MOD_ID + "." + name;
if (System.getProperty(propName) != null)
flags.add(new StringFlag("System Property", System.getProperty(propName)));
for (ModContainer mod : FabricLoader.getInstance().getAllMods()) {
if (!mod.getMetadata().containsCustomValue(LibJf.MOD_ID)) continue;
CustomValue.CvObject co = mod.getMetadata().getCustomValue(LibJf.MOD_ID).getAsObject();
if (!co.containsKey(name)) continue;
flags.add(new StringFlag("Mod: " + mod.getMetadata().getId(), co.get(name).getAsString()));
}
return flags;
}
public static Set<BooleanFlag> getBoolFlags(String name) {
Set<BooleanFlag> flags = new LinkedHashSet<>();
String propName = LibJf.MOD_ID + "." + name;
if (System.getProperty(propName) != null)
flags.add(new BooleanFlag("System Property", true));
for (ModContainer mod : FabricLoader.getInstance().getAllMods()) {
if (!mod.getMetadata().containsCustomValue(LibJf.MOD_ID)) continue;
CustomValue.CvObject co = mod.getMetadata().getCustomValue(LibJf.MOD_ID).getAsObject();
if (!co.containsKey(name)) continue;
flags.add(new BooleanFlag("Mod: " + mod.getMetadata().getId(), co.get(name).getAsBoolean()));
}
return flags;
}
public record StringFlag(String source, String value) {
}
public record BooleanFlag(String source, boolean value) {
}
}

View File

@ -3,7 +3,6 @@ package io.gitlab.jfronny.libjf;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.gitlab.jfronny.libjf.gson.HiddenAnnotationExclusionStrategy;
import net.fabricmc.loader.api.FabricLoader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -20,6 +19,4 @@ public class LibJf {
.addSerializationExclusionStrategy(new HiddenAnnotationExclusionStrategy())
.setPrettyPrinting()
.create();
// Only ever set through the libjf-unsafe-v0 testmod or user code since it causes logspam
public static boolean DEV = false;
}

View File

@ -0,0 +1,15 @@
package io.gitlab.jfronny.libjf.config.api;
import io.gitlab.jfronny.libjf.config.impl.Config;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolderImpl;
import java.util.Map;
public interface ConfigHolder {
static ConfigHolder getInstance() {
return ConfigHolderImpl.INSTANCE;
}
void register(String modId, Class<?> config);
Map<String, Config> getRegistered();
boolean isRegistered(Class<?> config);
}

View File

@ -1,29 +0,0 @@
package io.gitlab.jfronny.libjf.config.impl;
import com.google.common.collect.ImmutableMap;
import java.util.HashMap;
import java.util.Map;
public class ConfigHolder {
private ConfigHolder() {
}
private static final Map<String, Config> configs = new HashMap<>();
public static void registerConfig(String modId, Class<?> config) {
if (!isRegistered(config))
configs.put(modId, new Config(modId, config));
}
public static Map<String, Config> getConfigs() {
return ImmutableMap.copyOf(configs);
}
public static boolean isRegistered(Class<?> config) {
for (Config value : configs.values()) {
if (value.configClass.equals(config))
return true;
}
return false;
}
}

View File

@ -0,0 +1,32 @@
package io.gitlab.jfronny.libjf.config.impl;
import com.google.common.collect.ImmutableMap;
import io.gitlab.jfronny.libjf.config.api.ConfigHolder;
import java.util.HashMap;
import java.util.Map;
public class ConfigHolderImpl implements ConfigHolder {
@Deprecated public static final ConfigHolderImpl INSTANCE = new ConfigHolderImpl();
private ConfigHolderImpl() {}
private final Map<String, Config> configs = new HashMap<>();
@Override
public void register(String modId, Class<?> config) {
if (!isRegistered(config))
configs.put(modId, new Config(modId, config));
}
@Override
public Map<String, Config> getRegistered() {
return ImmutableMap.copyOf(configs);
}
public boolean isRegistered(Class<?> config) {
for (Config value : configs.values()) {
if (value.configClass.equals(config))
return true;
}
return false;
}
}

View File

@ -2,6 +2,7 @@ package io.gitlab.jfronny.libjf.config.impl;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import io.gitlab.jfronny.libjf.config.api.ConfigHolder;
import io.gitlab.jfronny.libjf.config.impl.gui.TinyConfigScreen;
import io.gitlab.jfronny.libjf.LibJf;
@ -12,7 +13,7 @@ public class ModMenu implements ModMenuApi {
@Override
public Map<String, ConfigScreenFactory<?>> getProvidedConfigScreenFactories() {
Map<String, ConfigScreenFactory<?>> factories = new HashMap<>();
for (Map.Entry<String, Config> entry : ConfigHolder.getConfigs().entrySet()) {
for (Map.Entry<String, Config> entry : ConfigHolder.getInstance().getRegistered().entrySet()) {
if (!LibJf.MOD_ID.equals(entry.getKey()))
factories.put(entry.getKey(), buildFactory(entry.getValue()));
}

View File

@ -1,18 +1,16 @@
package io.gitlab.jfronny.libjf.config.impl.entry;
import io.gitlab.jfronny.libjf.config.api.ConfigHolder;
import io.gitlab.jfronny.libjf.config.impl.Config;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolder;
import io.gitlab.jfronny.libjf.config.impl.EntryInfo;
import io.gitlab.jfronny.libjf.config.api.Entry;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolderImpl;
import io.gitlab.jfronny.libjf.config.impl.gui.EntryInfoWidgetBuilder;
import io.gitlab.jfronny.libjf.gson.GsonHidden;
import io.gitlab.jfronny.libjf.LibJf;
import net.fabricmc.api.ClientModInitializer;
public class JfConfigClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
for (Config config : ConfigHolder.getConfigs().values()) {
for (Config config : ConfigHolder.getInstance().getRegistered().values()) {
LibJf.LOGGER.info("Registring config UI for " + config.modid);
EntryInfoWidgetBuilder.initConfig(config);
}

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.libjf.config.impl.entry;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolder;
import io.gitlab.jfronny.libjf.config.api.ConfigHolder;
import io.gitlab.jfronny.libjf.config.api.JfConfig;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.entrypoint.EntrypointContainer;
@ -11,7 +11,7 @@ public class JfConfigSafe implements PreLaunchEntrypoint {
@Override
public void onPreLaunch() {
for (EntrypointContainer<JfConfig> config : FabricLoader.getInstance().getEntrypointContainers(LibJf.MOD_ID + ":config", JfConfig.class)) {
ConfigHolder.registerConfig(config.getProvider().getMetadata().getId(), config.getEntrypoint().getClass());
ConfigHolder.getInstance().register(config.getProvider().getMetadata().getId(), config.getEntrypoint().getClass());
LibJf.LOGGER.info("Registering config for " + config.getProvider().getMetadata().getId());
}
}

View File

@ -1,7 +1,8 @@
package io.gitlab.jfronny.libjf.config.impl.entry;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolder;
import io.gitlab.jfronny.libjf.config.api.ConfigHolder;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolderImpl;
import io.gitlab.jfronny.libjf.config.api.JfConfig;
import io.gitlab.jfronny.libjf.unsafe.DynamicEntry;
import io.gitlab.jfronny.libjf.unsafe.UltraEarlyInit;
@ -10,7 +11,7 @@ public class JfConfigUnsafe implements UltraEarlyInit {
@Override
public void init() {
DynamicEntry.execute(LibJf.MOD_ID + ":config", JfConfig.class, s -> {
ConfigHolder.registerConfig(s.modId(), s.instance().getClass());
ConfigHolder.getInstance().register(s.modId(), s.instance().getClass());
LibJf.LOGGER.info("Registering config for " + s.modId());
});
LibJf.LOGGER.info("Finished LibJF config entrypoint");

View File

@ -44,10 +44,10 @@ public class EntryInfoWidgetBuilder {
if (e == null) return;
if (type == int.class) textField(config, info, Integer::parseInt, INTEGER_ONLY, e.min(), e.max(), true);
else if (type == double.class) textField(config, info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(),false);
if (type == int.class || type == Integer.class) textField(config, info, Integer::parseInt, INTEGER_ONLY, e.min(), e.max(), true);
else if (type == double.class || type == Double.class) textField(config, info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(),false);
else if (type == String.class) textField(config, info, String::length, null, Math.min(e.min(),0), Math.max(e.max(),1),true);
else if (type == boolean.class) {
else if (type == boolean.class || type == Boolean.class) {
Function<Object, Text> func = value -> new LiteralText((Boolean) value ? "True" : "False").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED);
info.widget = new AbstractMap.SimpleEntry<ButtonWidget.PressAction, Function<Object, Text>>(button -> {
info.value = !(Boolean) info.value;

View File

@ -6,6 +6,7 @@ import io.gitlab.jfronny.libjf.gson.GsonHidden;
public class TestConfig implements JfConfig {
@Entry public static boolean disablePacks = false;
@Entry public static Boolean disablePacks2 = false;
@Entry public static int intTest = 20;
@Entry public static double decimalTest = 20;
@Entry public static String dieStr = "lolz";

View File

@ -7,7 +7,4 @@ import java.util.Set;
public interface AsmConfig {
Set<String> skipClasses();
Set<Patch> getPatches();
default boolean export() {
return false;
}
}

View File

@ -1,5 +1,6 @@
package io.gitlab.jfronny.libjf.unsafe.asm;
import io.gitlab.jfronny.libjf.Flags;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.unsafe.asm.patch.Patch;
import net.fabricmc.loader.api.FabricLoader;
@ -27,19 +28,33 @@ public class AsmTransformer implements IMixinTransformer {
public Set<BakedAsmConfig> asmConfigs;
private AsmConfig currentConfig = null;
private boolean export;
private boolean debugLog;
public void init() {
Set<String> exportReasons = new LinkedHashSet<>();
if (System.getProperty("libjf.asm.export") != null)
exportReasons.add("Property: libjf.asm.export");
for (BakedAsmConfig config : asmConfigs) {
if (config.export())
exportReasons.add("Mod: " + config.getSource());
}
export = !exportReasons.isEmpty();
Set<Flags.BooleanFlag> flags = Flags.getBoolFlags("asm.export");
flags.removeIf(flag -> !flag.value());
export = !flags.isEmpty();
if (export) {
LibJf.LOGGER.info("Exporting ASM due to: " + String.join(", ", exportReasons));
Set<String> flagNames = new LinkedHashSet<>();
for (Flags.BooleanFlag flag : flags) {
flagNames.add(flag.source());
}
LibJf.LOGGER.info("Exporting ASM due to: " + String.join(", ", flagNames));
}
flags = Flags.getBoolFlags("asm.log");
flags.removeIf(flag -> !flag.value());
debugLog = !flags.isEmpty();
if (debugLog) {
Set<String> flagNames = new LinkedHashSet<>();
for (Flags.BooleanFlag flag : flags) {
flagNames.add(flag.source());
}
LibJf.LOGGER.info("Logging ASM logs due to: " + String.join(", ", flagNames));
}
}
public boolean debugLogsEnabled() {
return debugLog;
}
@Override
@ -63,7 +78,7 @@ public class AsmTransformer implements IMixinTransformer {
if (classBytes == null || name == null)
return classBytes;
if (isClassUnmoddable(name, null)) {
if (LibJf.DEV) LibJf.LOGGER.info("Skipping " + name);
if (debugLogsEnabled()) LibJf.LOGGER.info("Skipping " + name);
return classBytes;
}

View File

@ -7,12 +7,10 @@ import java.util.Set;
public class BakedAsmConfig implements AsmConfig {
private final Set<String> skipClasses;
private final Set<Patch> patches;
private final Boolean export;
private final String source;
public BakedAsmConfig(AsmConfig config, String source) {
skipClasses = config.skipClasses();
patches = config.getPatches();
export = config.export();
this.source = source;
}
@ -26,11 +24,6 @@ public class BakedAsmConfig implements AsmConfig {
return patches;
}
@Override
public boolean export() {
return export;
}
public String getSource() {
return source;
}

View File

@ -22,7 +22,7 @@ public class MethodModificationPatch implements Patch {
);
}
for (String s : this.patches.keySet()) {
if (LibJf.DEV) LibJf.LOGGER.info("Registered patch for " + s);
if (AsmTransformer.INSTANCE.debugLogsEnabled()) LibJf.LOGGER.info("Registered patch for " + s);
}
}
@ -30,7 +30,7 @@ public class MethodModificationPatch implements Patch {
public void apply(ClassNode klazz) {
for (MethodNode method : klazz.methods) {
if (patches.containsKey(method.name)) {
if (LibJf.DEV) LibJf.LOGGER.info("Patching " + method.name);
if (AsmTransformer.INSTANCE.debugLogsEnabled()) LibJf.LOGGER.info("Patching " + method.name);
patches.get(method.name).apply(method);
}
}

View File

@ -25,7 +25,7 @@ public class InterfaceImplTargetPatch implements Patch {
public void apply(ClassNode klazz) {
scanInterfaces(klazz);
if (getUpper(klazz.name).contains(targetInterface)) {
if (LibJf.DEV) LibJf.LOGGER.info("Found " + klazz.name + " implementing " + targetInterface);
if (AsmTransformer.INSTANCE.debugLogsEnabled()) LibJf.LOGGER.info("Found " + klazz.name + " implementing " + targetInterface);
methodPatch.apply(klazz);
}
}
@ -86,7 +86,7 @@ public class InterfaceImplTargetPatch implements Patch {
&& !className.startsWith("it/unimi/dsi/fastutil/")
&& !className.startsWith("com/google/")
) {
if (LibJf.DEV) LibJf.LOGGER.info("Non-default class not considered for interface scanning: " + className);
if (AsmTransformer.INSTANCE.debugLogsEnabled()) LibJf.LOGGER.info("Non-default class not considered for interface scanning: " + className);
INTERFACES.put(className, Set.of());
return Set.of();
}

View File

@ -40,9 +40,4 @@ public class AsmTest implements AsmConfig {
" ##:::: ##:. ######:: ##:::: ##:::: ##:::: ########:. ######::::: ##::::\n" +
"..:::::..:::......:::..:::::..:::::..:::::........:::......::::::..:::::");
}
@Override
public boolean export() {
return false;
}
}

View File

@ -14,6 +14,5 @@ public class UnsafeEntryTest implements UltraEarlyInit {
" '|..' .||. '|.' .||. '|..'|' .||.....| '|..'|' .||. .||. '| \n" +
" .. | \n" +
" '' ");
LibJf.DEV = true;
}
}

View File

@ -10,5 +10,11 @@
"libjf:early": [
"io.gitlab.jfronny.libjf.unsafe.test.UnsafeEntryTest"
]
},
"custom": {
"libjf": {
"asm.export": true,
"asm.log": true
}
}
}

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.libjf;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolder;
import io.gitlab.jfronny.libjf.config.api.ConfigHolder;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolderImpl;
import io.gitlab.jfronny.libjf.data.WrappedPack;
import io.gitlab.jfronny.libjf.data.manipulation.api.UserResourceEvents;
import net.fabricmc.api.ModInitializer;
@ -10,7 +11,7 @@ import net.fabricmc.api.ModInitializer;
public class Libjf implements ModInitializer {
@Deprecated(forRemoval = true)
public static void registerConfig(String modId, Class<?> config) {
ConfigHolder.registerConfig(modId, config);
ConfigHolder.getInstance().register(modId, config);
}
@Override

View File

@ -0,0 +1,21 @@
package io.gitlab.jfronny.libjf.config.impl;
import java.util.Map;
@Deprecated
public class ConfigHolder {
@Deprecated
public static void registerConfig(String modId, Class<?> config) {
ConfigHolderImpl.INSTANCE.register(modId, config);
}
@Deprecated
public static Map<String, Config> getConfigs() {
return ConfigHolderImpl.INSTANCE.getRegistered();
}
@Deprecated
public static boolean isRegistered(Class<?> config) {
return ConfigHolderImpl.INSTANCE.isRegistered(config);
}
}