From 81b94a655b77ea274a7131a3ec12ebd5e053d518 Mon Sep 17 00:00:00 2001 From: Technici4n <13494793+Technici4n@users.noreply.github.com> Date: Tue, 23 Jan 2024 14:02:12 +0100 Subject: [PATCH] Move config screen event registration to an event --- .../neoforge/client/ConfigScreenHandler.java | 37 ++++++++++++++ .../neoforge/client/IConfigScreenFactory.java | 22 ++++++++ .../event/RegisterConfigScreenEvent.java | 51 +++++++++++++++++++ .../neoforge/client/gui/ModListScreen.java | 8 ++- 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/neoforged/neoforge/client/IConfigScreenFactory.java create mode 100644 src/main/java/net/neoforged/neoforge/client/event/RegisterConfigScreenEvent.java diff --git a/src/main/java/net/neoforged/neoforge/client/ConfigScreenHandler.java b/src/main/java/net/neoforged/neoforge/client/ConfigScreenHandler.java index 99e3ba2eaa..ec27248f6c 100644 --- a/src/main/java/net/neoforged/neoforge/client/ConfigScreenHandler.java +++ b/src/main/java/net/neoforged/neoforge/client/ConfigScreenHandler.java @@ -5,18 +5,55 @@ package net.neoforged.neoforge.client; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.function.BiFunction; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.neoforged.fml.IExtensionPoint; import net.neoforged.fml.ModList; +import net.neoforged.fml.ModLoader; +import net.neoforged.neoforge.client.event.RegisterConfigScreenEvent; import net.neoforged.neoforgespi.language.IModInfo; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; public class ConfigScreenHandler { + private static final Map factories = new HashMap<>(); + + /** + * Retrieves the config screen factory for a mod, if present. + */ + @Nullable + public static IConfigScreenFactory getScreenFactory(String modid) { + var ret = factories.get(modid); + if (ret != null) { + return ret; + } + + // support legacy system + return ModList.get().getModContainerById(modid) + .flatMap(mc -> mc.getCustomExtension(ConfigScreenFactory.class)) + .map(f -> (IConfigScreenFactory) f.screenFunction()::apply) + .orElse(null); + } + + @ApiStatus.Internal + public static void init() { + ModLoader.get().postEvent(new RegisterConfigScreenEvent(factories)); + } + + @Deprecated(forRemoval = true, since = "1.20.4") public record ConfigScreenFactory(BiFunction screenFunction) implements IExtensionPoint {} + @Deprecated(forRemoval = true, since = "1.20.4") public static Optional> getScreenFactoryFor(IModInfo selectedMod) { + var factory = factories.get(selectedMod.getModId()); + if (factory != null) { + return Optional.of(factory::createScreen); + } + return ModList.get().getModContainerById(selectedMod.getModId()).flatMap(mc -> mc.getCustomExtension(ConfigScreenFactory.class).map(ConfigScreenFactory::screenFunction)); } } diff --git a/src/main/java/net/neoforged/neoforge/client/IConfigScreenFactory.java b/src/main/java/net/neoforged/neoforge/client/IConfigScreenFactory.java new file mode 100644 index 0000000000..2b899a1583 --- /dev/null +++ b/src/main/java/net/neoforged/neoforge/client/IConfigScreenFactory.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) NeoForged and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.neoforged.neoforge.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.neoforged.neoforge.client.event.RegisterConfigScreenEvent; + +/** + * Factory for mod-provided config screens accessed via NeoForge's mod list menu. + * Register to {@link RegisterConfigScreenEvent}. + */ +public interface IConfigScreenFactory { + /** + * Creates a config screen. + * Setting the screen back to the provided {@code modListScreen} will return the user to the mod list menu. + */ + Screen createScreen(Minecraft minecraft, Screen modListScreen); +} diff --git a/src/main/java/net/neoforged/neoforge/client/event/RegisterConfigScreenEvent.java b/src/main/java/net/neoforged/neoforge/client/event/RegisterConfigScreenEvent.java new file mode 100644 index 0000000000..f3b2bd5534 --- /dev/null +++ b/src/main/java/net/neoforged/neoforge/client/event/RegisterConfigScreenEvent.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) NeoForged and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.neoforged.neoforge.client.event; + +import java.util.Map; +import java.util.Objects; +import net.neoforged.bus.api.Event; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.event.IModBusEvent; +import net.neoforged.neoforge.client.IConfigScreenFactory; +import org.jetbrains.annotations.ApiStatus; + +/** + * Event to register {@link IConfigScreenFactory} instances for mods. + */ +public class RegisterConfigScreenEvent extends Event implements IModBusEvent { + private final Map factories; + + @ApiStatus.Internal + public RegisterConfigScreenEvent(Map factories) { + this.factories = factories; + } + + /** + * Registers a config screen factory for the given mod. + * + * @param modid the mod id + * @param factory the factory + */ + public void register(String modid, IConfigScreenFactory factory) { + Objects.requireNonNull(modid, "modid may not be null"); + Objects.requireNonNull(factory, "factory may not be null"); + + if (factories.putIfAbsent(modid, factory) != null) { + throw new IllegalArgumentException("A config screen factory for mod " + modid + " is already registered"); + } + } + + /** + * Registers a config screen factory for the given mod. + * + * @param container the mod container + * @param factory the factory + */ + public void register(ModContainer container, IConfigScreenFactory factory) { + register(container.getModId(), factory); + } +} diff --git a/src/main/java/net/neoforged/neoforge/client/gui/ModListScreen.java b/src/main/java/net/neoforged/neoforge/client/gui/ModListScreen.java index 0620ffb5cb..3d0e11ca18 100644 --- a/src/main/java/net/neoforged/neoforge/client/gui/ModListScreen.java +++ b/src/main/java/net/neoforged/neoforge/client/gui/ModListScreen.java @@ -294,7 +294,11 @@ public void init() { private void displayModConfig() { if (selected == null) return; try { - ConfigScreenHandler.getScreenFactoryFor(selected.getInfo()).map(f -> f.apply(this.minecraft, this)).ifPresent(newScreen -> this.minecraft.setScreen(newScreen)); + var factory = ConfigScreenHandler.getScreenFactory(selected.getInfo().getModId()); + if (factory != null) { + var newScreen = factory.createScreen(this.minecraft, this); + this.minecraft.setScreen(newScreen); + } } catch (final Exception e) { LOGGER.error("There was a critical issue trying to build the config GUI for {}", selected.getInfo().getModId(), e); } @@ -373,7 +377,7 @@ private void updateCache() { return; } IModInfo selectedMod = selected.getInfo(); - this.configButton.active = ConfigScreenHandler.getScreenFactoryFor(selectedMod).isPresent(); + this.configButton.active = ConfigScreenHandler.getScreenFactory(selectedMod.getModId()) != null; List lines = new ArrayList<>(); VersionChecker.CheckResult vercheck = VersionChecker.getResult(selectedMod);