mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 16:27:47 +00:00
Config GUIs in the modlist now work.
This commit is contained in:
1 parent
7a62801209
commit
aa963c5df6
10 files changed
+292
-3
No files matched your search
@@ -36,7 +36,10 @@ import net.minecraft.network.INetHandler;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
@@ -119,6 +122,8 @@ public class FMLClientHandler implements IFMLSidedHandler
|
||||
|
||||
private Map<String, IResourcePack> resourcePackMap;
|
||||
|
||||
private BiMap<ModContainer, IModGuiFactory> guiFactories;
|
||||
|
||||
/**
|
||||
* Called to start the whole game off
|
||||
*
|
||||
@@ -239,6 +244,26 @@ public class FMLClientHandler implements IFMLSidedHandler
|
||||
// Reload resources
|
||||
// client.func_110436_a();
|
||||
RenderingRegistry.instance().loadEntityRenderers((Map<Class<? extends Entity>, Render>)RenderManager.field_78727_a.field_78729_o);
|
||||
guiFactories = HashBiMap.create();
|
||||
for (ModContainer mc : Loader.instance().getActiveModList())
|
||||
{
|
||||
String className = mc.getGuiClassName();
|
||||
if (Strings.isNullOrEmpty(className))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
Class<?> clazz = Class.forName(className, true, Loader.instance().getModClassLoader());
|
||||
Class<? extends IModGuiFactory> guiClassFactory = clazz.asSubclass(IModGuiFactory.class);
|
||||
IModGuiFactory guiFactory = guiClassFactory.newInstance();
|
||||
guiFactory.initialize(client);
|
||||
guiFactories.put(mc, guiFactory);
|
||||
} catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "A critical error occurred instantiating the gui factory for mod %s", mc.getModId());
|
||||
}
|
||||
}
|
||||
loading = false;
|
||||
}
|
||||
|
||||
@@ -514,4 +539,9 @@ public class FMLClientHandler implements IFMLSidedHandler
|
||||
{
|
||||
showGuiScreen(new GuiIngameModOptions(guiIngameMenu));
|
||||
}
|
||||
|
||||
public IModGuiFactory getGuiFactoryFor(ModContainer selectedMod)
|
||||
{
|
||||
return guiFactories.get(selectedMod);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.util.Set;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
public class FMLConfigGuiFactory implements IModGuiFactory {
|
||||
public static class FMLConfigGuiScreen extends GuiScreen {
|
||||
private GuiScreen parent;
|
||||
|
||||
public FMLConfigGuiScreen(GuiScreen parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void func_73866_w_()
|
||||
{
|
||||
this.field_146292_n.add(new GuiButton(1, this.field_146294_l / 2 - 75, this.field_146295_m - 38, I18n.func_135052_a("gui.done")));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void func_146284_a(GuiButton p_73875_1_)
|
||||
{
|
||||
if (p_73875_1_.field_146124_l && p_73875_1_.field_146127_k == 1)
|
||||
{
|
||||
FMLClientHandler.instance().showGuiScreen(parent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_146276_q_();
|
||||
this.func_73732_a(this.field_146289_q, "Forge Mod Loader test config screen", this.field_146294_l / 2, 40, 0xFFFFFF);
|
||||
super.func_73863_a(p_73863_1_, p_73863_2_, p_73863_3_);
|
||||
}
|
||||
|
||||
}
|
||||
private Minecraft minecraft;
|
||||
@Override
|
||||
public void initialize(Minecraft minecraftInstance)
|
||||
{
|
||||
this.minecraft = minecraftInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends GuiScreen> mainConfigGuiClass()
|
||||
{
|
||||
return FMLConfigGuiScreen.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,10 +33,12 @@ import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.client.resources.IResourcePack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.ModContainer.Disableable;
|
||||
@@ -93,8 +95,8 @@ public class GuiModList extends GuiScreen
|
||||
}
|
||||
listWidth=Math.min(listWidth, 150);
|
||||
this.field_146292_n.add(new GuiButton(6, this.field_146294_l / 2 - 75, this.field_146295_m - 38, I18n.func_135052_a("gui.done")));
|
||||
configModButton = new GuiButton(7, 10, this.field_146295_m - 60, this.listWidth, 20, "Config");
|
||||
disableModButton = new GuiButton(8, 10, this.field_146295_m - 38, this.listWidth, 20, "Disable");
|
||||
configModButton = new GuiButton(20, 10, this.field_146295_m - 60, this.listWidth, 20, "Config");
|
||||
disableModButton = new GuiButton(21, 10, this.field_146295_m - 38, this.listWidth, 20, "Disable");
|
||||
this.field_146292_n.add(configModButton);
|
||||
this.field_146292_n.add(disableModButton);
|
||||
this.modList=new GuiSlotModList(this, mods, listWidth);
|
||||
@@ -110,6 +112,18 @@ public class GuiModList extends GuiScreen
|
||||
case 6:
|
||||
this.field_146297_k.func_147108_a(this.mainMenu);
|
||||
return;
|
||||
case 20:
|
||||
try
|
||||
{
|
||||
IModGuiFactory guiFactory = FMLClientHandler.instance().getGuiFactoryFor(selectedMod);
|
||||
GuiScreen newScreen = guiFactory.mainConfigGuiClass().getConstructor(GuiScreen.class).newInstance(this);
|
||||
this.field_146297_k.func_147108_a(newScreen);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "There was a critical issue trying to build the config GUI for %s", selectedMod.getModId());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.func_146284_a(button);
|
||||
@@ -222,6 +236,17 @@ public class GuiModList extends GuiScreen
|
||||
disableModButton.field_146125_m = true;
|
||||
disableModButton.field_146124_l = false;
|
||||
}
|
||||
IModGuiFactory guiFactory = FMLClientHandler.instance().getGuiFactoryFor(selectedMod);
|
||||
if (guiFactory == null || guiFactory.mainConfigGuiClass() == null)
|
||||
{
|
||||
configModButton.field_146125_m = true;
|
||||
configModButton.field_146124_l = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
configModButton.field_146125_m = true;
|
||||
configModButton.field_146124_l = true;
|
||||
}
|
||||
} else {
|
||||
offset = ( this.listWidth + this.field_146294_l ) / 2;
|
||||
this.func_73732_a(this.field_146289_q, selectedMod.getName(), offset, 35, 0xFFFFFF);
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.util.Set;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
public interface IModGuiFactory {
|
||||
/**
|
||||
* Called when instantiated to initialize with the active minecraft instance.
|
||||
*
|
||||
* @param minecraftInstance the instance
|
||||
*/
|
||||
public void initialize(Minecraft minecraftInstance);
|
||||
/**
|
||||
* Return the name of a class extending {@link GuiScreen}. This class will
|
||||
* be instantiated when the "config" button is pressed in the mod list. It will
|
||||
* have a single argument constructor - the "parent" screen, the same as all
|
||||
* Minecraft GUIs. The expected behaviour is that this screen will replace the
|
||||
* "mod list" screen completely, and will return to the mod list screen through
|
||||
* the parent link, once the appropriate action is taken from the config screen.
|
||||
*
|
||||
* A null from this method indicates that the mod does not provide a "config"
|
||||
* button GUI screen, and the config button will be hidden/disabled.
|
||||
*
|
||||
* This config GUI is anticipated to provide configuration to the mod in a friendly
|
||||
* visual way. It should not be abused to set internals such as IDs (they're gonna
|
||||
* keep disappearing anyway), but rather, interesting behaviours. This config GUI
|
||||
* is never run when a server game is running, and should be used to configure
|
||||
* desired behaviours that affect server state. Costs, mod game modes, stuff like that
|
||||
* can be changed here.
|
||||
*
|
||||
* @return A class that will be instantiated on clicks on the config button
|
||||
* or null if no GUI is desired.
|
||||
*/
|
||||
public Class<? extends GuiScreen> mainConfigGuiClass();
|
||||
|
||||
|
||||
/**
|
||||
* Return a list of the "runtime" categories this mod wishes to populate with
|
||||
* GUI elements.
|
||||
*
|
||||
* Runtime categories are created on demand and organized in a 'lite' tree format.
|
||||
* The parent represents the parent node in the tree. There is one special parent
|
||||
* 'Help' that will always list first, and is generally meant to provide Help type
|
||||
* content for mods. The remaining parents will sort alphabetically, though
|
||||
* this may change if there is a lot of alphabetic abuse. "AAA" is probably never a valid
|
||||
* category parent.
|
||||
*
|
||||
* Runtime configuration itself falls into two flavours: in-game help, which is
|
||||
* generally non interactive except for the text it wishes to show, and client-only
|
||||
* affecting behaviours. This would include things like toggling minimaps, or cheat modes
|
||||
* or anything NOT affecting the behaviour of the server. Please don't abuse this to
|
||||
* change the state of the server in any way, this is intended to behave identically
|
||||
* when the server is local or remote.
|
||||
*
|
||||
* @return the set of options this mod wishes to have available, or empty if none
|
||||
*/
|
||||
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories();
|
||||
|
||||
/**
|
||||
* Return an instance of a {@link RuntimeOptionGuiHandler} that handles painting the
|
||||
* right hand side option screen for the specified {@link RuntimeOptionCategoryElement}.
|
||||
*
|
||||
* @param element The element we wish to paint for
|
||||
* @return The Handler for painting it
|
||||
*/
|
||||
public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element);
|
||||
|
||||
/**
|
||||
* Represents an option category and entry in the runtime gui options list.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public static class RuntimeOptionCategoryElement {
|
||||
public final String parent;
|
||||
public final String child;
|
||||
|
||||
public RuntimeOptionCategoryElement(String parent, String child)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.child = child;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for painting the mod specific section of runtime options GUI for a particular category
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface RuntimeOptionGuiHandler {
|
||||
/**
|
||||
* Called to add widgets to the screen, such as buttons.
|
||||
* GUI identifier numbers should start at 100 and increase.
|
||||
* The callback will be through {@link #actionCallback(int)}
|
||||
*
|
||||
* @param x X
|
||||
* @param y Y
|
||||
* @param w width
|
||||
* @param h height
|
||||
*/
|
||||
public void addWidgets(int x, int y, int w, int h);
|
||||
|
||||
/**
|
||||
* Called to paint the rectangle specified.
|
||||
* @param x X
|
||||
* @param y Y
|
||||
* @param w width
|
||||
* @param h height
|
||||
*/
|
||||
public void paint(int x, int y, int w, int h);
|
||||
|
||||
/**
|
||||
* Called if a widget with id >= 100 is fired.
|
||||
*
|
||||
* @param actionId the actionId of the firing widget
|
||||
*/
|
||||
public void actionCallback(int actionId);
|
||||
|
||||
/**
|
||||
* Called when this handler is about to go away (probably replaced by another one, or closing the
|
||||
* option screen)
|
||||
*/
|
||||
public void close();
|
||||
}
|
||||
}
|
||||
@@ -186,4 +186,10 @@ public class DummyModContainer implements ModContainer
|
||||
{
|
||||
return Disableable.NEVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGuiClassName()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -215,4 +215,10 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
||||
{
|
||||
return getSource().isDirectory() ? FMLFolderResourcePack.class : FMLFileResourcePack.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGuiClassName()
|
||||
{
|
||||
return "cpw.mods.fml.client.FMLConfigGuiFactory";
|
||||
}
|
||||
}
|
||||
@@ -616,4 +616,10 @@ public class FMLModContainer implements ModContainer
|
||||
{
|
||||
return disableability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGuiClassName()
|
||||
{
|
||||
return (String) descriptor.get("guiFactory");
|
||||
}
|
||||
}
|
||||
@@ -174,4 +174,10 @@ public class InjectedModContainer implements ModContainer
|
||||
{
|
||||
return wrappedContainer.canBeDisabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGuiClassName()
|
||||
{
|
||||
return wrappedContainer.getGuiClassName();
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import cpw.mods.fml.client.IModGuiFactory;
|
||||
import cpw.mods.fml.common.event.FMLEvent;
|
||||
import cpw.mods.fml.common.event.FMLFingerprintViolationEvent;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
@@ -149,10 +150,20 @@ public @interface Mod
|
||||
* (minimap mods, graphical tweak mods) then you can set true here and receive the FMLDeactivationEvent to perform deactivation
|
||||
* tasks.
|
||||
* This does not affect administrative disabling through the system property fml.modStates or the config file fmlModState.properties.
|
||||
* The mod will only be deactivated outside of a running game world - FML will never allow mod deactivation whilst a game server
|
||||
* is running.
|
||||
*
|
||||
* @return if I can be deactivated whilst the game is running.
|
||||
* @return if this mod can be deactivated whilst the game is open.
|
||||
*/
|
||||
boolean canBeDeactivated() default false;
|
||||
|
||||
/**
|
||||
* An optional GUI factory for this mod. This is the name of a class implementing {@link IModGuiFactory} that will be instantiated
|
||||
* on the client side, and will have certain configuration/options guis requested from it.
|
||||
*
|
||||
* @return The name of a class implementing {@link IModGuiFactory}
|
||||
*/
|
||||
String guiFactory() default "";
|
||||
/**
|
||||
* A list of custom properties for this mod. Completely up to the mod author if/when they
|
||||
* want to put anything in here.
|
||||
|
||||
@@ -143,4 +143,6 @@ public interface ModContainer
|
||||
Map<String, String> getSharedModDescriptor();
|
||||
|
||||
Disableable canBeDisabled();
|
||||
|
||||
String getGuiClassName();
|
||||
}
|
||||
Reference in new issue
Block a user