aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergConfigPlugin.java199
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergConfigProvider.java45
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergFolderEntry.java160
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredConfigHelperMixin.java55
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java216
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/MixinConfig.java22
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java20
7 files changed, 418 insertions, 299 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergConfigPlugin.java b/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergConfigPlugin.java
new file mode 100644
index 0000000..7f230de
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergConfigPlugin.java
@@ -0,0 +1,199 @@
+package com.anthonyhilyard.iceberg.compat.configured;
+
+import com.anthonyhilyard.iceberg.config.IcebergConfigSpec;
+import com.electronwill.nightconfig.core.AbstractConfig;
+import com.electronwill.nightconfig.core.CommentedConfig;
+import com.electronwill.nightconfig.core.UnmodifiableConfig;
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import com.google.common.collect.ImmutableList;
+import com.mojang.datafixers.util.Pair;
+import com.mrcrayfish.configured.Configured;
+import com.mrcrayfish.configured.api.ConfigType;
+import com.mrcrayfish.configured.api.IConfigEntry;
+import com.mrcrayfish.configured.api.IConfigValue;
+import com.mrcrayfish.configured.api.IModConfig;
+import com.mrcrayfish.configured.impl.forge.ForgeListValue;
+import com.mrcrayfish.configured.impl.forge.ForgeValue;
+import com.mrcrayfish.configured.util.ConfigHelper;
+import net.minecraft.Util;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.fml.config.ModConfig;
+import net.minecraftforge.fml.event.config.ModConfigEvent;
+
+import java.nio.file.Path;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.commons.compress.utils.Lists;
+
+public class IcebergConfigPlugin implements IModConfig
+{
+ protected static final EnumMap<ModConfig.Type, ConfigType> TYPE_RESOLVER = Util.make(new EnumMap<>(ModConfig.Type.class), (map) -> {
+ map.put(ModConfig.Type.CLIENT, ConfigType.CLIENT);
+ map.put(ModConfig.Type.COMMON, ConfigType.UNIVERSAL);
+ map.put(ModConfig.Type.SERVER, ConfigType.WORLD_SYNC);
+ });
+
+ protected final ModConfig config;
+ protected final List<IcebergValueEntry> allConfigValues;
+
+ public IcebergConfigPlugin(ModConfig config)
+ {
+ this.config = config;
+ this.allConfigValues = getAllConfigValues(config);
+ }
+
+ @Override
+ public void update(IConfigEntry entry)
+ {
+ Set<IConfigValue<?>> changedValues = ConfigHelper.getChangedValues(entry);
+ if (!changedValues.isEmpty())
+ {
+ CommentedConfig newConfig = CommentedConfig.copy(this.config.getConfigData());
+ changedValues.forEach(value ->
+ {
+ if (value instanceof ForgeValue<?> forge)
+ {
+ if (forge instanceof ForgeListValue forgeList)
+ {
+ Function<List<?>, List<?>> converter = forgeList.getConverter();
+ if (converter != null)
+ {
+ newConfig.set(forge.configValue.getPath(), converter.apply(forgeList.get()));
+ return;
+ }
+ }
+ newConfig.set(forge.configValue.getPath(), value.get());
+ }
+ });
+ this.config.getConfigData().putAll(newConfig);
+ }
+
+ if (this.getType() == ConfigType.WORLD_SYNC)
+ {
+ if (!ConfigHelper.isPlayingGame())
+ {
+ // Unload server configs since still in main menu
+ this.config.getHandler().unload(this.config.getFullPath().getParent(), this.config);
+ ConfigHelper.setForgeConfigData(this.config, null);
+ }
+ }
+ else if (!changedValues.isEmpty())
+ {
+ Configured.LOGGER.info("Sending config reloading event for {}", this.config.getFileName());
+ this.config.getSpec().afterReload();
+ ConfigHelper.fireForgeConfigEvent(this.config, new ModConfigEvent.Reloading(this.config));
+ }
+ }
+
+ @Override
+ public IConfigEntry getRoot()
+ {
+ return new IcebergFolderEntry(((IcebergConfigSpec) this.config.getSpec()).getValues(), (IcebergConfigSpec) this.config.getSpec());
+ }
+
+ @Override
+ public ConfigType getType()
+ {
+ return TYPE_RESOLVER.get(this.config.getType());
+ }
+
+ @Override
+ public String getFileName()
+ {
+ return this.config.getFileName();
+ }
+
+ @Override
+ public String getModId()
+ {
+ return this.config.getModId();
+ }
+
+ @Override
+ public void loadWorldConfig(Path path, Consumer<IModConfig> result)
+ {
+ final CommentedFileConfig data = this.config.getHandler().reader(path).apply(this.config);
+ ConfigHelper.setForgeConfigData(this.config, data);
+ result.accept(this);
+ }
+
+ @Override
+ public void stopEditing()
+ {
+ // Attempts to unload the server config if player simply just went back
+ if (this.config != null && this.getType() == ConfigType.WORLD)
+ {
+ if (!ConfigHelper.isPlayingGame())
+ {
+ // Unload server configs since still in main menu
+ this.config.getHandler().unload(this.config.getFullPath().getParent(), this.config);
+ ConfigHelper.setForgeConfigData(this.config, null);
+ }
+ }
+ }
+
+ @Override
+ public boolean isChanged()
+ {
+ // Block world configs since the path is dynamic
+ if (ConfigHelper.isWorldConfig(this) && this.config.getConfigData() == null)
+ {
+ return false;
+ }
+
+ // Check if any config value doesn't equal it's default
+ return this.allConfigValues.stream().anyMatch(entry -> {
+ return !Objects.equals(entry.value.get(), entry.spec.getDefault());
+ });
+ }
+
+ @Override
+ public void restoreDefaults()
+ {
+ // Block world configs since the path is dynamic
+ if (ConfigHelper.isWorldConfig(this) && this.config.getConfigData() == null)
+ {
+ return;
+ }
+
+ // Creates a copy of the config data then pushes all at once to avoid multiple IO ops
+ CommentedConfig newConfig = CommentedConfig.copy(this.config.getConfigData());
+ this.allConfigValues.forEach(entry -> newConfig.set(entry.value.getPath(), entry.spec.getDefault()));
+ this.config.getConfigData().putAll(newConfig);
+
+ // Finally clear cache of all config values
+ this.allConfigValues.forEach(pair -> pair.value.clearCache());
+ }
+
+ private static List<IcebergValueEntry> getAllConfigValues(ModConfig config)
+ {
+ IcebergConfigSpec icebergConfigSpec = (IcebergConfigSpec) config.getSpec();
+ List<Pair<ForgeConfigSpec.ConfigValue<?>, ForgeConfigSpec.ValueSpec>> values = Lists.newArrayList();
+ gatherValuesFromIcebergConfig(icebergConfigSpec.getValues(), icebergConfigSpec, values);
+ return ImmutableList.copyOf(values).stream().map(pair -> new IcebergValueEntry(pair.getFirst(), pair.getSecond())).collect(Collectors.toList());
+ }
+
+ private static void gatherValuesFromIcebergConfig(UnmodifiableConfig config, IcebergConfigSpec spec, List<Pair<ForgeConfigSpec.ConfigValue<?>, ForgeConfigSpec.ValueSpec>> values)
+ {
+ config.valueMap().forEach((key, value) ->
+ {
+ if (value instanceof AbstractConfig)
+ {
+ gatherValuesFromIcebergConfig((UnmodifiableConfig) value, spec, values);
+ }
+ else if (value instanceof ForgeConfigSpec.ConfigValue<?> configValue)
+ {
+ ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
+ values.add(Pair.of(configValue, valueSpec));
+ }
+ });
+ }
+
+ private record IcebergValueEntry(ForgeConfigSpec.ConfigValue<?> value, ForgeConfigSpec.ValueSpec spec) {}
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergConfigProvider.java b/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergConfigProvider.java
new file mode 100644
index 0000000..6eda2ee
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergConfigProvider.java
@@ -0,0 +1,45 @@
+package com.anthonyhilyard.iceberg.compat.configured;
+
+import java.util.EnumMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import com.anthonyhilyard.iceberg.config.IcebergConfigSpec;
+import com.mrcrayfish.configured.api.IConfigProvider;
+import com.mrcrayfish.configured.api.IModConfig;
+
+import net.minecraftforge.fml.ModContainer;
+import net.minecraftforge.fml.config.ConfigTracker;
+import net.minecraftforge.fml.config.ModConfig;
+import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
+
+public class IcebergConfigProvider implements IConfigProvider
+{
+ @Override
+ public Set<IModConfig> getConfigurationsForMod(ModContainer container)
+ {
+ // Add Iceberg configurations
+ Set<IModConfig> configs = new HashSet<>();
+ addIcebergConfigsToMap(container, ModConfig.Type.CLIENT, configs::add);
+ addIcebergConfigsToMap(container, ModConfig.Type.COMMON, configs::add);
+ addIcebergConfigsToMap(container, ModConfig.Type.SERVER, configs::add);
+ return configs;
+ }
+
+ private static void addIcebergConfigsToMap(ModContainer container, ModConfig.Type type, Consumer<IModConfig> consumer)
+ {
+ getForgeTrackedConfigs().get(type).stream()
+ .filter(config -> config.getModId().equals(container.getModId()) && config.getSpec() instanceof IcebergConfigSpec)
+ .map(IcebergConfigPlugin::new)
+ .collect(Collectors.toSet())
+ .forEach(consumer);
+ }
+
+ private static EnumMap<ModConfig.Type, Set<ModConfig>> getForgeTrackedConfigs()
+ {
+ return ObfuscationReflectionHelper.getPrivateValue(ConfigTracker.class, ConfigTracker.INSTANCE, "configSets");
+ }
+
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergFolderEntry.java b/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergFolderEntry.java
new file mode 100644
index 0000000..c9d3612
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/compat/configured/IcebergFolderEntry.java
@@ -0,0 +1,160 @@
+package com.anthonyhilyard.iceberg.compat.configured;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import com.anthonyhilyard.iceberg.config.IcebergConfigSpec;
+import com.electronwill.nightconfig.core.UnmodifiableConfig;
+import com.google.common.collect.ImmutableList;
+import com.mrcrayfish.configured.api.IConfigEntry;
+import com.mrcrayfish.configured.api.IConfigValue;
+import com.mrcrayfish.configured.api.ValueEntry;
+import com.mrcrayfish.configured.impl.forge.ForgeEnumValue;
+import com.mrcrayfish.configured.impl.forge.ForgeListValue;
+import com.mrcrayfish.configured.impl.forge.ForgeValue;
+
+import net.minecraft.client.resources.language.I18n;
+import net.minecraft.network.chat.Component;
+import net.minecraftforge.common.ForgeConfigSpec;
+
+public class IcebergFolderEntry implements IConfigEntry
+{
+ protected final List<String> path;
+ protected final UnmodifiableConfig config;
+ protected final IcebergConfigSpec spec;
+ private final String customComment;
+ protected List<IConfigEntry> entries;
+
+ public IcebergFolderEntry(UnmodifiableConfig config, IcebergConfigSpec spec)
+ {
+ this(new ArrayList<>(), config, spec);
+ }
+
+ public IcebergFolderEntry(List<String> path, UnmodifiableConfig config, IcebergConfigSpec spec)
+ {
+ this(path, config, spec, null);
+ }
+
+ public IcebergFolderEntry(List<String> path, UnmodifiableConfig config, IcebergConfigSpec spec, String customComment)
+ {
+ this.path = path;
+ this.config = config;
+ this.spec = spec;
+ this.customComment = customComment;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<IConfigEntry> getChildren()
+ {
+ if (this.entries == null)
+ {
+ ImmutableList.Builder<IConfigEntry> builder = ImmutableList.builder();
+
+ this.config.valueMap().forEach((key, value) ->
+ {
+ if (value instanceof ForgeConfigSpec.ValueSpec valueSpec && valueSpec.getDefault() instanceof UnmodifiableConfig)
+ {
+ value = valueSpec.getDefault();
+ }
+
+ if (value instanceof UnmodifiableConfig)
+ {
+ List<String> path = new ArrayList<>(this.path);
+ path.add(key);
+ builder.add(new IcebergFolderEntry(path, (UnmodifiableConfig) value, this.spec));
+ }
+ else if (value instanceof ForgeConfigSpec.ConfigValue<?> configValue)
+ {
+ ForgeConfigSpec.ValueSpec valueSpec = this.spec.getRaw(configValue.getPath());
+ if (valueSpec != null)
+ {
+ if (configValue.get() instanceof List<?>)
+ {
+ builder.add(new ValueEntry(new ForgeListValue((ForgeConfigSpec.ConfigValue<List<?>>) configValue, valueSpec)));
+ }
+ else if (configValue.get() instanceof Enum<?>)
+ {
+ builder.add(new ValueEntry(new ForgeEnumValue<>((ForgeConfigSpec.EnumValue<?>) configValue, valueSpec)));
+ }
+ // Configured doesn't currently support map configuration values, so leave a message for users.
+ else if (configValue.get() instanceof UnmodifiableConfig)
+ {
+ List<String> path = new ArrayList<>(this.path);
+ path.add(key);
+ builder.add(new IcebergFolderEntry(path, (UnmodifiableConfig) configValue.get(), this.spec, "This is a map configuration value, which is not currently supported by Configured. To edit this value, please modify the configuration file directly."));
+ }
+ else
+ {
+ builder.add(new ValueEntry(new ForgeValue<>(configValue, valueSpec)));
+ }
+ }
+ }
+ });
+ this.entries = builder.build();
+ }
+ return this.entries;
+ }
+
+ @Override
+ public boolean isRoot()
+ {
+ return this.path.isEmpty();
+ }
+
+ @Override
+ public boolean isLeaf()
+ {
+ return false;
+ }
+
+ @Override
+ public IConfigValue<?> getValue()
+ {
+ return null;
+ }
+
+ @Override
+ public String getEntryName()
+ {
+ return ForgeValue.lastValue(this.path, "Root");
+ }
+
+ @Nullable
+ @Override
+ public Component getTooltip()
+ {
+ if (customComment != null)
+ {
+ return Component.translatable(customComment);
+ }
+ else
+ {
+ String translationKey = this.getTranslationKey();
+ if (translationKey != null)
+ {
+ String tooltipKey = translationKey + ".tooltip";
+ if (I18n.exists(tooltipKey))
+ {
+ return Component.translatable(tooltipKey);
+ }
+ }
+ String comment = this.spec.getLevelComment(this.path);
+ if (comment != null)
+ {
+ return Component.literal(comment);
+ }
+ return null;
+ }
+ }
+
+ @Nullable
+ @Override
+ public String getTranslationKey()
+ {
+ return this.spec.getLevelTranslationKey(this.path);
+ }
+
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredConfigHelperMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredConfigHelperMixin.java
deleted file mode 100644
index 9918740..0000000
--- a/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredConfigHelperMixin.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.anthonyhilyard.iceberg.mixin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.anthonyhilyard.iceberg.config.IcebergConfigSpec;
-import com.electronwill.nightconfig.core.AbstractConfig;
-import com.electronwill.nightconfig.core.UnmodifiableConfig;
-
-
-import org.apache.commons.lang3.tuple.Pair;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-
-import net.minecraftforge.common.ForgeConfigSpec;
-import net.minecraftforge.fml.config.ModConfig;
-
-
-import com.mrcrayfish.configured.util.ConfigHelper;
-
-
-@Mixin(ConfigHelper.class)
-public class ConfiguredConfigHelperMixin
-{
- @Inject(method = "gatherAllConfigValues(Lnet/minecraftforge/fml/config/ModConfig;)Ljava/util/List;",
- at = @At(value = "HEAD"), cancellable = true, remap = false, require = 0)
- private static void gatherAllConfigValuesIcebergSupport(ModConfig config, CallbackInfoReturnable<List<?>> info)
- {
- if (config.getSpec() instanceof IcebergConfigSpec icebergConfigSpec)
- {
- List<Pair<ForgeConfigSpec.ConfigValue<?>, ForgeConfigSpec.ValueSpec>> values = new ArrayList<>();
- gatherValuesFromIcebergConfig(icebergConfigSpec.getValues(), icebergConfigSpec, values);
- info.setReturnValue(values);
- }
- }
-
- private static void gatherValuesFromIcebergConfig(UnmodifiableConfig config, IcebergConfigSpec spec, List<Pair<ForgeConfigSpec.ConfigValue<?>, ForgeConfigSpec.ValueSpec>> values)
- {
- config.valueMap().forEach((s, o) ->
- {
- if (o instanceof AbstractConfig)
- {
- gatherValuesFromIcebergConfig((UnmodifiableConfig) o, spec, values);
- }
- else if (o instanceof ForgeConfigSpec.ConfigValue<?>)
- {
- ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) o;
- ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
- values.add(Pair.of(configValue, valueSpec));
- }
- });
- }
-} \ No newline at end of file
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java
deleted file mode 100644
index 1d0882a..0000000
--- a/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package com.anthonyhilyard.iceberg.mixin;
-
-import java.lang.reflect.Field;
-import java.util.List;
-import java.util.ArrayList;
-
-import com.anthonyhilyard.iceberg.Loader;
-import com.anthonyhilyard.iceberg.config.IcebergConfigSpec;
-import com.electronwill.nightconfig.core.UnmodifiableConfig;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.mrcrayfish.configured.client.screen.ConfigScreen;
-import com.mrcrayfish.configured.client.screen.ListMenuScreen;
-import com.mrcrayfish.configured.client.screen.ModConfigSelectionScreen;
-import com.mrcrayfish.configured.client.screen.ModConfigSelectionScreen.FileItem;
-import com.mrcrayfish.configured.client.screen.WorldSelectionScreen;
-import com.mrcrayfish.configured.client.screen.ConfigScreen.FolderEntry;
-import com.mrcrayfish.configured.client.screen.ConfigScreen.IEntry;
-import com.mrcrayfish.configured.client.screen.widget.IconButton;
-import com.mrcrayfish.configured.util.ConfigHelper;
-
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.commons.lang3.reflect.FieldUtils;
-import org.spongepowered.asm.mixin.Final;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Shadow;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-import org.spongepowered.asm.mixin.injection.At;
-
-import net.minecraft.ChatFormatting;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.components.Button;
-import net.minecraft.client.gui.narration.ScreenNarrationCollector;
-import net.minecraft.client.gui.screens.Screen;
-import net.minecraft.network.chat.Component;
-import net.minecraft.resources.ResourceLocation;
-import net.minecraftforge.common.ForgeConfigSpec;
-import net.minecraftforge.fml.ModList;
-import net.minecraftforge.fml.config.ModConfig;
-import net.minecraftforge.fml.unsafe.UnsafeHacks;
-
-@Mixin(FileItem.class)
-public class ConfiguredModConfigSelectionScreenMixin
-{
- @Shadow(aliases = "this$0", remap = false)
- @Final
- ModConfigSelectionScreen this$0;
-
- @Shadow(remap = false)
- @Final
- protected ModConfig config;
-
- @Shadow(remap = false)
- @Final
- protected Component title;
-
- @Shadow(remap = false)
- private boolean hasRequiredPermission() { return true; }
-
- @Inject(method = "createModifyButton", at = @At(value = "HEAD"), remap = false, cancellable = true, require = 0)
- private void createModifyButton(ModConfig config, CallbackInfoReturnable<Button> info)
- {
- if (config.getSpec() instanceof IcebergConfigSpec)
- {
- Minecraft minecraft = Minecraft.getInstance();
- boolean serverConfig = config.getType() == ModConfig.Type.SERVER && Minecraft.getInstance().level == null;
- String langKey = serverConfig ? "configured.gui.select_world" : "configured.gui.modify";
-
- ResourceLocation backgroundTemp = null;
- try
- {
- Field backgroundField = ListMenuScreen.class.getDeclaredField("background");
- backgroundField.setAccessible(true);
- backgroundTemp = (ResourceLocation) backgroundField.get(this$0);
- }
- catch (Exception e)
- {
- Loader.LOGGER.error(ExceptionUtils.getStackTrace(e));
- }
-
- final ResourceLocation background = backgroundTemp;
-
- info.setReturnValue(new IconButton(0, 0, serverConfig ? 44 : 33, 0, serverConfig ? 80 : 60, Component.translatable(langKey), onPress ->
- {
- if (ConfigScreen.isPlayingGame() && this.config.getType() == ModConfig.Type.SERVER && (!ConfigHelper.isConfiguredInstalledOnServer() || !this.hasRequiredPermission()))
- {
- return;
- }
-
- if (serverConfig)
- {
- minecraft.setScreen(new WorldSelectionScreen(this$0, background, config, this.title));
- }
- else
- {
- ModList.get().getModContainerById(config.getModId()).ifPresent(container ->
- {
- try
- {
- ConfigScreen configScreen = UnsafeHacks.newInstance(ConfigScreen.class);
-
- Field titleField = Screen.class.getDeclaredField("f_96539_");
- Field childrenField = Screen.class.getDeclaredField("f_96540_");
- Field narratablesField = Screen.class.getDeclaredField("f_169368_");
- Field renderablesField = Screen.class.getDeclaredField("f_169369_");
- Field narrationStateField = Screen.class.getDeclaredField("f_169375_");
- Field parentField = configScreen.getClass().getSuperclass().getDeclaredField("parent");
- Field backgroundField = configScreen.getClass().getSuperclass().getDeclaredField("background");
- Field itemHeightField = configScreen.getClass().getSuperclass().getDeclaredField("itemHeight");
- titleField.setAccessible(true);
- childrenField.setAccessible(true);
- narratablesField.setAccessible(true);
- renderablesField.setAccessible(true);
- narrationStateField.setAccessible(true);
- parentField.setAccessible(true);
- backgroundField.setAccessible(true);
- itemHeightField.setAccessible(true);
-
- titleField.set(configScreen, Component.literal(container.getModInfo().getDisplayName()));
- childrenField.set(configScreen, Lists.newArrayList());
- narratablesField.set(configScreen, Lists.newArrayList());
- renderablesField.set(configScreen, Lists.newArrayList());
- narrationStateField.set(configScreen, new ScreenNarrationCollector());
- parentField.set(configScreen, this$0);
- backgroundField.set(configScreen, background);
- itemHeightField.set(configScreen, 24);
-
- ForgeConfigSpec dummySpec = new ForgeConfigSpec.Builder().build();
- FieldUtils.writeDeclaredField(configScreen, "folderEntry", new IcebergFolderEntry(configScreen, List.of(), ((IcebergConfigSpec) config.getSpec()).getValues(), dummySpec, (IcebergConfigSpec) config.getSpec()), true);
- FieldUtils.writeDeclaredField(configScreen, "config", config, true);
-
- minecraft.setScreen(configScreen);
- }
- catch (Exception e)
- {
- Loader.LOGGER.error(ExceptionUtils.getStackTrace(e));
- }
- });
- }
- }, (button, poseStack, mouseX, mouseY) ->
- {
- if (button.isHoveredOrFocused())
- {
- if (ConfigScreen.isPlayingGame() && !ConfigHelper.isConfiguredInstalledOnServer())
- {
- this$0.renderTooltip(poseStack, minecraft.font.split(Component.translatable("configured.gui.not_installed").withStyle(ChatFormatting.RED), Math.max(this$0.width / 2 - 43, 170)), mouseX, mouseY);
- }
- else if (!this.hasRequiredPermission())
- {
- this$0.renderTooltip(poseStack, minecraft.font.split(Component.translatable("configured.gui.no_permission").withStyle(ChatFormatting.RED), Math.max(this$0.width / 2 - 43, 170)), mouseX, mouseY);
- }
- }
- }));
- }
- }
-
- public class IcebergFolderEntry extends FolderEntry
- {
- private IcebergConfigSpec icebergConfigSpec;
- private ForgeConfigSpec spec;
- private ConfigScreen configScreen;
- private UnmodifiableConfig config;
- private final List<String> path;
- public IcebergFolderEntry(ConfigScreen configScreen, List<String> path, UnmodifiableConfig config, ForgeConfigSpec spec, IcebergConfigSpec icebergSpec)
- {
- configScreen.super(path, config, spec);
- icebergConfigSpec = icebergSpec;
- this.spec = spec;
- this.configScreen = configScreen;
- this.config = config;
- this.path = path;
- init();
- }
-
- private void init()
- {
- try
- {
- Field entriesField = getClass().getSuperclass().getDeclaredField("entries");
- entriesField.setAccessible(true);
-
- ImmutableList.Builder<IEntry> builder = ImmutableList.builder();
- config.valueMap().forEach((key, value) ->
- {
- if (value instanceof ForgeConfigSpec.ValueSpec valueSpec && valueSpec.getDefault() instanceof UnmodifiableConfig)
- {
- value = valueSpec.getDefault();
- }
-
- if (value instanceof UnmodifiableConfig)
- {
- List<String> path = new ArrayList<>(this.path);
- path.add(key);
- builder.add(new IcebergFolderEntry(configScreen, path, (UnmodifiableConfig) value, spec, icebergConfigSpec));
- }
- else if (value instanceof ForgeConfigSpec.ConfigValue<?>)
- {
- ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) value;
- ForgeConfigSpec.ValueSpec valueSpec = icebergConfigSpec.getRaw(configValue.getPath());
- if (valueSpec != null)
- {
- builder.add(configScreen.new ValueEntry(configValue, valueSpec));
- }
- }
- });
- entriesField.set(this, builder.build());
- }
- catch (Exception e)
- {
- Loader.LOGGER.error(ExceptionUtils.getStackTrace(e));
- return;
- }
- }
- }
-}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/MixinConfig.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/MixinConfig.java
index 566843c..f71f4aa 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/mixin/MixinConfig.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/MixinConfig.java
@@ -7,12 +7,11 @@ import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
-import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.LoadingModList;
-import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
public class MixinConfig implements IMixinConfigPlugin
{
+ @SuppressWarnings("unused")
private LoadingModList loadingModList = null;
@Override
@@ -24,25 +23,6 @@ public class MixinConfig implements IMixinConfigPlugin
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName)
{
- if (mixinClassName.toLowerCase().contains("configured"))
- {
- if (loadingModList == null)
- {
- loadingModList = FMLLoader.getLoadingModList();
- }
-
- // Check if Config Menus for Forge is available.
- for (ModInfo modInfo : loadingModList.getMods())
- {
- // If configured is present, load the mixin.
- if (modInfo.getModId().equals("configured"))
- {
- return true;
- }
- }
-
- return false;
- }
return true;
}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
index 63ec096..6bcb2b0 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
@@ -40,6 +40,7 @@ import net.minecraftforge.common.MinecraftForge;
public class Tooltips
{
+ private static final FormattedCharSequence SPACE = FormattedCharSequence.forward(" ", Style.EMPTY);
private static ItemRenderer itemRenderer = null;
public static class TooltipInfo
@@ -56,6 +57,7 @@ public class Tooltips
}
public int getTooltipWidth() { return tooltipWidth; }
+ public int getTooltipHeight() { return components.size() > titleLines ? components.size() * 10 + 2 : 8; }
public int getTitleLines() { return titleLines; }
public Font getFont() { return font; }
public List<ClientTooltipComponent> getComponents() { return components; }
@@ -64,16 +66,21 @@ public class Tooltips
public int getMaxLineWidth()
{
- int width = 0;
+ return getMaxLineWidth(0);
+ }
+
+ public int getMaxLineWidth(int minWidth)
+ {
+ int textWidth = minWidth;
for (ClientTooltipComponent component : components)
{
int componentWidth = component.getWidth(font);
- if (componentWidth > width)
+ if (componentWidth > textWidth)
{
- width = componentWidth;
+ textWidth = componentWidth;
}
}
- return width;
+ return textWidth;
}
}
@@ -179,7 +186,7 @@ public class Tooltips
for (int componentNumber = 0; componentNumber < info.getComponents().size(); ++componentNumber)
{
ClientTooltipComponent imageComponent = info.getComponents().get(componentNumber);
- imageComponent.renderImage(preEvent.getFont(), rectX, tooltipTop, poseStack, itemRenderer, 400);
+ imageComponent.renderImage(preEvent.getFont(), rectX, tooltipTop, poseStack, itemRenderer, zLevel);
tooltipTop += imageComponent.getHeight() + (componentNumber == 0 ? 2 : 0);
}
@@ -348,10 +355,9 @@ public class Tooltips
List<ClientTooltipComponent> result = new ArrayList<>(components);
FormattedCharSequence title = Language.getInstance().getVisualOrder(recomposedLines.get(0));
- FormattedCharSequence space = FormattedCharSequence.forward(" ", Style.EMPTY);
while (result.get(0).getWidth(font) < tooltipWidth)
{
- title = FormattedCharSequence.fromList(List.of(space, title, space));
+ title = FormattedCharSequence.fromList(List.of(SPACE, title, SPACE));
if (title == null)
{
break;