diff --git a/src/main/java/ru/bclib/gui/modmenu/EntryPoint.java b/src/main/java/ru/bclib/gui/modmenu/EntryPoint.java
new file mode 100644
index 00000000..18f3e4d5
--- /dev/null
+++ b/src/main/java/ru/bclib/gui/modmenu/EntryPoint.java
@@ -0,0 +1,12 @@
+package ru.bclib.gui.modmenu;
+
+import com.terraformersmc.modmenu.util.ModMenuApiMarker;
+import ru.bclib.integration.ModMenuIntegration;
+
+public class EntryPoint extends ModMenuIntegration {
+ public static final ModMenuApiMarker entrypointObject = createEntrypoint(new EntryPoint());
+
+ public EntryPoint() {
+ super(MainScreen::new);
+ }
+}
diff --git a/src/main/java/ru/bclib/gui/screens/ModMenu/MainScreen.java b/src/main/java/ru/bclib/gui/modmenu/MainScreen.java
similarity index 95%
rename from src/main/java/ru/bclib/gui/screens/ModMenu/MainScreen.java
rename to src/main/java/ru/bclib/gui/modmenu/MainScreen.java
index e56f2f3c..086da6b2 100644
--- a/src/main/java/ru/bclib/gui/screens/ModMenu/MainScreen.java
+++ b/src/main/java/ru/bclib/gui/modmenu/MainScreen.java
@@ -1,4 +1,4 @@
-package ru.bclib.gui.screens.ModMenu;
+package ru.bclib.gui.modmenu;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents;
diff --git a/src/main/java/ru/bclib/integration/ModMenuIntegration.java b/src/main/java/ru/bclib/integration/ModMenuIntegration.java
index e05b3afb..53301931 100644
--- a/src/main/java/ru/bclib/integration/ModMenuIntegration.java
+++ b/src/main/java/ru/bclib/integration/ModMenuIntegration.java
@@ -3,23 +3,18 @@ package ru.bclib.integration;
import com.google.common.collect.ImmutableMap;
import com.terraformersmc.modmenu.util.ModMenuApiMarker;
import net.minecraft.client.gui.screens.Screen;
-import ru.bclib.gui.screens.ModMenu.MainScreen;
+import ru.bclib.integration.ModMenuIntegration.ModMenuScreenFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
-@FunctionalInterface
-interface IModMenuScreenFactory {
- S create(Screen parent);
-}
-
-class ModMenuScreenFactory {
+class ModMenuScreenFactoryImpl {
static class ScreenFactoryInvocationHandler implements InvocationHandler {
- private final IModMenuScreenFactory act;
+ private final ModMenuScreenFactory act;
- public ScreenFactoryInvocationHandler(IModMenuScreenFactory act) {
+ public ScreenFactoryInvocationHandler(ModMenuScreenFactory act) {
this.act = act;
}
@@ -29,7 +24,7 @@ class ModMenuScreenFactory {
}
}
- public static IModMenuScreenFactory create(IModMenuScreenFactory act) {
+ public static ModMenuScreenFactory create(ModMenuScreenFactory act) {
Class> iConfigScreenFactory = null;
try {
iConfigScreenFactory = Class.forName("com.terraformersmc.modmenu.api.ConfigScreenFactory");
@@ -40,14 +35,128 @@ class ModMenuScreenFactory {
Object o = Proxy.newProxyInstance(
ModMenuIntegration.class.getClassLoader(),
- new Class[] {iConfigScreenFactory, IModMenuScreenFactory.class},
+ new Class[] {iConfigScreenFactory, ModMenuScreenFactory.class},
new ScreenFactoryInvocationHandler(act));
- return (IModMenuScreenFactory)o;
+ return (ModMenuScreenFactory)o;
}
}
-public class ModMenuIntegration {
+/**
+ * Integration, to provide a custom Screen for ModMenu.
+ *
+ * This integration allows you to use ModMenu without adding a dependency to your project. If the + * Mod is installed on the Client, and the correct ModMenu-EntryPoint is registered in your fabric.mod.json + * the screen will show up. + *
+ * You only need to subclass this class, and initialize a static Field of Type {@link ModMenuApiMarker} using + * the {@link #createEntrypoint(ModMenuIntegration)}-Method. + *
+ * Example: + *
{@code public class ModMenu extends ModMenuIntegration { + * public static final ModMenuApiMarker entrypointObject = createEntrypoint(new EntryPoint()); + * + * public EntryPoint() { + * super(GridScreen::new); + * } + * }+ * You'd also need to add the ModMenu-Entrypoint to your fabric.mod.json: + *
"entrypoints": { + * ... + * "modmenu": [ "your.mod.ModMenu::entrypointObject" ] + * }+ */ +public abstract class ModMenuIntegration { + /** + * Creates a new EntryPoint Object that is accepted by ModMenu + * @param target The delegate Object that will receive calls from ModMenu + * @return A Proxy that conforms to the ModMenu spec + */ + public static ModMenuApiMarker createEntrypoint(ModMenuIntegration target) { + Class> iModMenuAPI = null; + //Class> iModMenuAPIMarker = null; + try { + iModMenuAPI = Class.forName("com.terraformersmc.modmenu.api.ModMenuApi"); + //iModMenuAPIMarker = Class.forName("com.terraformersmc.modmenu.util.ModMenuApiMarker"); + } + catch (ClassNotFoundException e) { + e.printStackTrace(); + return (ModMenuApiMarker)new Object(); + } + + Object o = Proxy.newProxyInstance( + ModMenuIntegration.class.getClassLoader(), + new Class[] {iModMenuAPI}, + new BCLibModMenuInvocationHandler(target)); + + return (ModMenuApiMarker)o; + } + + protected final ModMenuScreenFactory screenFactory; + + /** + * Create a new ModMenu delegate + * @param screenFactory A Factory. The Factory receives the currently visible {@code parent}-Screen + * and must return a new Screen Object. + */ + public ModMenuIntegration(ModMenuScreenFactory screenFactory){ + this.screenFactory = screenFactory; + } + + /** + * A Helper class to make a BCLib-Factory conform to the ModMenu-Factory Interface. + * @param factory + * @return A ModMenu Factory for a Screen + */ + final protected ModMenuScreenFactory createFactory(ModMenuScreenFactory factory){ + return ModMenuScreenFactoryImpl.create( factory ); + } + + /** + * Used to construct a new config screen instance when your mod's + * configuration button is selected on the mod menu screen. The + * screen instance parameter is the active mod menu screen. + * (Text copied from ModMenu) + * + * @return A factory for constructing config screen instances. + * + */ + public ModMenuScreenFactory getModConfigScreenFactory() { + return createFactory(screenFactory); + } + + /** + * Used to provide config screen factories for other mods. This takes second + * priority to a mod's own config screen factory provider. For example, if + * mod `xyz` supplies a config screen factory, mod `abc` providing a config + * screen to `xyz` will be pointless, as the one provided by `xyz` will be + * used. + *
+ * This method is NOT meant to be used to add a config screen factory to
+ * your own mod.
+ * (Text copied from ModMenu)
+ *
+ * @return a map of mod ids to screen factories.
+ */
+ public Map
+ * The Interface matches {@code com.terraformersmc.modmenu.api.ConfigScreenFactory}
+ */
+ @FunctionalInterface
+ public static interface ModMenuScreenFactory {
+ Screen create(Screen parent);
+ }
+
static class BCLibModMenuInvocationHandler implements InvocationHandler {
private final ModMenuIntegration target;
@@ -68,39 +177,4 @@ public class ModMenuIntegration {
}
}
}
-
- public static final ModMenuApiMarker entrypointObject = create();
-
- public static ModMenuApiMarker create() {
- Class> iModMenuAPI = null;
- //Class> iModMenuAPIMarker = null;
- try {
- iModMenuAPI = Class.forName("com.terraformersmc.modmenu.api.ModMenuApi");
- //iModMenuAPIMarker = Class.forName("com.terraformersmc.modmenu.util.ModMenuApiMarker");
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- return (ModMenuApiMarker)new Object();
- }
-
- Object o = Proxy.newProxyInstance(
- ModMenuIntegration.class.getClassLoader(),
- new Class[] {iModMenuAPI},
- new BCLibModMenuInvocationHandler(new ModMenuIntegration()));
-
- return (ModMenuApiMarker)o;
- }
-
- IModMenuScreenFactory> getModConfigScreenFactory() {
- return ModMenuScreenFactory.create( MainScreen::new );
- }
-
- Map