diff options
Diffstat (limited to 'src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java')
-rw-r--r-- | src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java new file mode 100644 index 0000000..a682a00 --- /dev/null +++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/ConfiguredModConfigSelectionScreenMixin.java @@ -0,0 +1,212 @@ +package com.anthonyhilyard.iceberg.mixin; + +import java.lang.reflect.Field; + +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) + 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, "Root", ((IcebergConfigSpec) config.getSpec()).getValues(), dummySpec, true, (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; + public IcebergFolderEntry(ConfigScreen configScreen, String label, UnmodifiableConfig config, ForgeConfigSpec spec, boolean root, IcebergConfigSpec icebergSpec) + { + configScreen.super(label, config, spec, root); + icebergConfigSpec = icebergSpec; + this.spec = spec; + this.configScreen = configScreen; + this.config = config; + 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) + { + builder.add(new IcebergFolderEntry(configScreen, key, (UnmodifiableConfig) value, spec, false, icebergConfigSpec)); + } + else if (value instanceof ForgeConfigSpec.ConfigValue<?>) + { + ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) value; + Loader.LOGGER.info(configValue.getPath()); + 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; + } + } + + } +} |