diff --git a/fml/client/cpw/mods/fml/client/FMLClientHandler.java b/fml/client/cpw/mods/fml/client/FMLClientHandler.java index aef3afd8b..b36b910fd 100644 --- a/fml/client/cpw/mods/fml/client/FMLClientHandler.java +++ b/fml/client/cpw/mods/fml/client/FMLClientHandler.java @@ -43,6 +43,7 @@ import javax.imageio.ImageIO; import org.lwjgl.opengl.GL11; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; import net.minecraft.client.Minecraft; @@ -173,6 +174,12 @@ public class FMLClientHandler implements IFMLSidedHandler public void onPreLoad(Minecraft minecraft) { + if (minecraft.func_55063_q()) + { + FMLLog.severe("DEMO MODE DETECTED, FML will not work. Finishing now."); + haltGame("FML will not run in demo mode", new RuntimeException()); + return; + } client = minecraft; ObfuscationReflectionHelper.detectObfuscation(World.class); FMLCommonHandler.instance().beginLoading(this); @@ -205,6 +212,7 @@ public class FMLClientHandler implements IFMLSidedHandler public void haltGame(String message, Throwable t) { client.func_55071_b(new CrashReport(message, t)); + throw Throwables.propagate(t); } /** * Called a bit later on during initialization to finish loading mods @@ -740,7 +748,7 @@ public class FMLClientHandler implements IFMLSidedHandler } public void registerTextureOverrides(RenderEngine renderer) { - for (ModContainer mod : Loader.getModList()) { + for (ModContainer mod : Loader.instance().getActiveModList()) { registerAnimatedTexturesFor(mod); } diff --git a/fml/client/cpw/mods/fml/client/GuiModList.java b/fml/client/cpw/mods/fml/client/GuiModList.java index abe68c490..065cdc7f1 100644 --- a/fml/client/cpw/mods/fml/client/GuiModList.java +++ b/fml/client/cpw/mods/fml/client/GuiModList.java @@ -55,7 +55,7 @@ public class GuiModList extends GuiScreen this.mainMenu=mainMenu; this.mods=new ArrayList(); FMLClientHandler.instance().addSpecialModEntries(mods); - for (ModContainer mod : Loader.getModList()) { + for (ModContainer mod : Loader.instance().getModList()) { if (mod.getMetadata()!=null && mod.getMetadata().parentMod != null) { continue; } @@ -123,6 +123,7 @@ public class GuiModList extends GuiScreen shifty += 12; shifty = drawLine(String.format("Version: %s (%s)", selectedMod.getMetadata().version, selectedMod.getVersion()), offset, shifty); + shifty = drawLine(String.format("Mod State: %s", Loader.instance().getModState(selectedMod)), offset, shifty); if (!selectedMod.getMetadata().credits.isEmpty()) { shifty = drawLine(String.format("Credits: %s", selectedMod.getMetadata().credits), offset, shifty); } @@ -134,8 +135,9 @@ public class GuiModList extends GuiScreen offset = ( this.listWidth + this.field_951_c ) / 2; this.func_548_a(this.field_6451_g, selectedMod.getName(), offset, 35, 0xFFFFFF); this.func_548_a(this.field_6451_g, String.format("Version: %s",selectedMod.getVersion()), offset, 45, 0xFFFFFF); - this.func_548_a(this.field_6451_g, "No mod information found", offset, 55, 0xDDDDDD); - this.func_548_a(this.field_6451_g, "Ask your mod author to provide a mod .info file", offset, 65, 0xDDDDDD); + this.func_548_a(this.field_6451_g, String.format("Mod State: %s",Loader.instance().getModState(selectedMod)), offset, 55, 0xFFFFFF); + this.func_548_a(this.field_6451_g, "No mod information found", offset, 65, 0xDDDDDD); + this.func_548_a(this.field_6451_g, "Ask your mod author to provide a mod mcmod.info file", offset, 75, 0xDDDDDD); } } super.func_571_a(p_571_1_, p_571_2_, p_571_3_); diff --git a/fml/client/cpw/mods/fml/client/GuiSlotModList.java b/fml/client/cpw/mods/fml/client/GuiSlotModList.java index 8398d743c..c5c0257cd 100644 --- a/fml/client/cpw/mods/fml/client/GuiSlotModList.java +++ b/fml/client/cpw/mods/fml/client/GuiSlotModList.java @@ -17,6 +17,7 @@ package cpw.mods.fml.client; import java.util.ArrayList; import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.LoaderState.ModState; import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModMetadata; import net.minecraft.client.Minecraft; @@ -75,9 +76,18 @@ public class GuiSlotModList extends GuiScrollingList protected void drawSlot(int listIndex, int var2, int var3, int var4, Tessellator var5) { ModContainer mc=mods.get(listIndex); - this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a(mc.getName(), listWidth - 11), this.left + 3 , var3 + 2, 0xFFFFFF); - this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a(mc.getVersion(), listWidth - 11), this.left + 3 , var3 + 12, 0xCCCCCC); - this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a(mc.getMetadata() !=null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 9), this.left + 3 , var3 + 22, 0xCCCCCC); + if (Loader.instance().getModState(mc)==ModState.DISABLED) + { + this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a(mc.getName(), listWidth - 11), this.left + 3 , var3 + 2, 0xFF2222); + this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a(mc.getVersion(), listWidth - 11), this.left + 3 , var3 + 12, 0xFF2222); + this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a("DISABLED", listWidth - 11), this.left + 3 , var3 + 22, 0xFF2222); + } + else + { + this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a(mc.getName(), listWidth - 11), this.left + 3 , var3 + 2, 0xFFFFFF); + this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a(mc.getVersion(), listWidth - 11), this.left + 3 , var3 + 12, 0xCCCCCC); + this.parent.getFontRenderer().func_873_b(this.parent.getFontRenderer().func_50107_a(mc.getMetadata() !=null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 9), this.left + 3 , var3 + 22, 0xCCCCCC); + } } } diff --git a/fml/common/cpw/mods/fml/common/FMLCommonHandler.java b/fml/common/cpw/mods/fml/common/FMLCommonHandler.java index 994ffa3f2..6e827272f 100644 --- a/fml/common/cpw/mods/fml/common/FMLCommonHandler.java +++ b/fml/common/cpw/mods/fml/common/FMLCommonHandler.java @@ -38,9 +38,16 @@ import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; +import net.minecraft.src.CallableMinecraftVersion; + +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.Lists; + import cpw.mods.fml.common.discovery.ContainerType; import cpw.mods.fml.common.registry.TickRegistry; -import cpw.mods.fml.common.registry.WorldRegistry; +import cpw.mods.fml.common.registry.GameRegistry; /** @@ -158,7 +165,7 @@ public class FMLCommonHandler */ public ModContainer findContainerFor(Object mod) { - for (ModContainer mc : Loader.getModList()) + for (ModContainer mc : Loader.instance().getActiveModList()) { if (mc.matches(mod)) { @@ -405,6 +412,7 @@ public class FMLCommonHandler private Class forge; private boolean noForge; + private List brandings; private Class findMinecraftForge() { @@ -442,27 +450,35 @@ public class FMLCommonHandler * @param string * @return */ - public String[] getBrandingStrings(String mcVersion) + public void computeBranding() { - ArrayList brandings=new ArrayList(); - brandings.add(mcVersion); - brandings.add(Loader.instance().getFMLVersionString()); - String forgeVersion = (String)callForgeMethod("getVersionString"); - if (forgeVersion != null) + if (brandings == null) { - brandings.add(forgeVersion); + Builder brd = ImmutableList.builder(); + brd.add("Minecraft "+CallableMinecraftVersion.func_55337_a()); + brd.add(Loader.instance().getFMLVersionString()); + brd.add(Strings.nullToEmpty((String)callForgeMethod("getVersionString"))); + brd.addAll(sidedDelegate.getAdditionalBrandingInformation()); + try { + Properties props=new Properties(); + props.load(getClass().getClassLoader().getResourceAsStream("fmlbranding.properties")); + brd.add(props.getProperty("fmlbranding")); + } catch (Exception ex) { + // Ignore - no branding file found + } + int tModCount = Loader.instance().getModList().size(); + int aModCount = Loader.instance().getActiveModList().size(); + brd.add(String.format("%d mod%s loaded, %d mod%s active", tModCount, tModCount!=1 ? "s" :"", aModCount, aModCount!=1 ? "s" :"" )); + brandings = brd.build(); } - brandings.addAll(sidedDelegate.getAdditionalBrandingInformation()); - try { - Properties props=new Properties(); - props.load(FMLCommonHandler.class.getClassLoader().getResourceAsStream("fmlbranding.properties")); - brandings.add(props.getProperty("fmlbranding")); - } catch (Exception ex) { - // Ignore - no branding file found + } + public List getBrandings() + { + if (brandings == null) + { + computeBranding(); } - brandings.add(String.format("%d mod%s loaded",Loader.getModList().size(), Loader.getModList().size()!=1?"s":"")); - Collections.reverse(brandings); - return brandings.toArray(new String[brandings.size()]); + return ImmutableList.copyOf(brandings); } /** @@ -487,7 +503,7 @@ public class FMLCommonHandler public void handleWorldGeneration(int chunkX, int chunkZ, long worldSeed, Object... data) { - WorldRegistry.generateWorld(chunkX, chunkZ, worldSeed, data); + GameRegistry.generateWorld(chunkX, chunkZ, worldSeed, data); } public void onPostServerTick() diff --git a/fml/common/cpw/mods/fml/common/FMLLoadCompleteEvent.java b/fml/common/cpw/mods/fml/common/FMLLoadCompleteEvent.java new file mode 100644 index 000000000..0a50164c5 --- /dev/null +++ b/fml/common/cpw/mods/fml/common/FMLLoadCompleteEvent.java @@ -0,0 +1,20 @@ +package cpw.mods.fml.common; + +import cpw.mods.fml.common.LoaderState.ModState; +import cpw.mods.fml.common.event.FMLStateEvent; + +public class FMLLoadCompleteEvent extends FMLStateEvent +{ + + public FMLLoadCompleteEvent(Object... data) + { + super(data); + } + + @Override + public ModState getModState() + { + return ModState.AVAILABLE; + } + +} diff --git a/fml/common/cpw/mods/fml/common/FMLModContainer.java b/fml/common/cpw/mods/fml/common/FMLModContainer.java index a1121dae8..fbc38753d 100644 --- a/fml/common/cpw/mods/fml/common/FMLModContainer.java +++ b/fml/common/cpw/mods/fml/common/FMLModContainer.java @@ -36,6 +36,8 @@ import cpw.mods.fml.common.event.FMLConstructionEvent; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.registry.FMLRegistry; +import cpw.mods.fml.common.registry.GameRegistry; public class FMLModContainer implements ModContainer { @@ -229,6 +231,7 @@ public class FMLModContainer implements ModContainer for (Object o : annotations.get(Block.class)) { Field f = (Field) o; + f.set(modInstance, GameRegistry.buildBlock(this, f.getType(), f.getAnnotation(Block.class))); } } diff --git a/fml/common/cpw/mods/fml/common/LoadController.java b/fml/common/cpw/mods/fml/common/LoadController.java index b43fa553b..2ca8bc42d 100644 --- a/fml/common/cpw/mods/fml/common/LoadController.java +++ b/fml/common/cpw/mods/fml/common/LoadController.java @@ -1,5 +1,6 @@ package cpw.mods.fml.common; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; @@ -7,7 +8,10 @@ import java.util.logging.Level; import com.google.common.base.Joiner; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.collect.Iterators; import com.google.common.collect.Multimap; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; @@ -24,6 +28,8 @@ public class LoadController private Multimap modStates = ArrayListMultimap.create(); private Multimap errors = ArrayListMultimap.create(); private Map modList; + private List activeModList = Lists.newArrayList(); + private String activeContainer; public LoadController(Loader loader) { @@ -34,13 +40,14 @@ public class LoadController Builder eventBus = ImmutableMap.builder(); - for (ModContainer mod : Loader.getModList()) + for (ModContainer mod : loader.getModList()) { EventBus bus = new EventBus(mod.getModId()); boolean isActive = mod.registerBus(bus, this); if (isActive) { FMLLog.fine("Activating mod %s", mod.getModId()); + activeModList.add(mod); modStates.put(mod.getModId(), ModState.UNLOADED); eventBus.put(mod.getModId(), bus); } @@ -59,6 +66,11 @@ public class LoadController public void distributeStateMessage(Object... eventData) { + if (state==LoaderState.ERRORED) + { + throw new LoaderException(); + } + if (state.hasEvent()) { masterChannel.post(state.getEvent(eventData)); @@ -81,16 +93,23 @@ public class LoadController FMLLog.log(Level.SEVERE, error.getValue(), "Caught exception from %s", error.getKey()); } - throw new LoaderException(); + // Throw embedding the first error (usually the only one) + throw new LoaderException(errors.values().iterator().next()); } } + public ModContainer activeContainer() + { + return activeContainer!=null ? modList.get(activeContainer) : null; + } @Subscribe public void propogateStateMessage(FMLStateEvent stateEvent) { for (Map.Entry entry : eventChannels.entrySet()) { + activeContainer = entry.getKey(); entry.getValue().post(stateEvent); + activeContainer = null; if (!errors.containsKey(entry.getKey())) { modStates.put(entry.getKey(), stateEvent.getModState()); @@ -116,4 +135,14 @@ public class LoadController Joiner.on("->"). appendTo(ret, modStates.get(modId)); } } + + public List getActiveModList() + { + return activeModList; + } + + public ModState getModState(ModContainer selectedMod) + { + return Iterables.getLast(modStates.get(selectedMod.getModId()), ModState.AVAILABLE); + } } diff --git a/fml/common/cpw/mods/fml/common/Loader.java b/fml/common/cpw/mods/fml/common/Loader.java index 58bcabbbd..ca8b37930 100644 --- a/fml/common/cpw/mods/fml/common/Loader.java +++ b/fml/common/cpw/mods/fml/common/Loader.java @@ -23,9 +23,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.Callable; import java.util.logging.Level; import java.util.regex.Matcher; @@ -40,6 +42,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import cpw.mods.fml.common.LoaderState.ModState; import cpw.mods.fml.common.discovery.ContainerType; import cpw.mods.fml.common.discovery.ModDiscoverer; import cpw.mods.fml.common.functions.ModIdFunction; @@ -320,7 +323,7 @@ public class Loader } } - public static List getModList() + public List getModList() { return ImmutableList.copyOf(instance().mods); } @@ -417,7 +420,9 @@ public class Loader public String getCrashInformation() { StringBuilder ret = new StringBuilder(); - Joiner.on('\n').appendTo(ret, FMLCommonHandler.instance().getBrandingStrings("")); + List branding = FMLCommonHandler.instance().getBrandings(); + + Joiner.on(' ').skipNulls().appendTo(ret, branding.subList(1, branding.size())); if (modController!=null) { modController.printModStates(ret); @@ -513,6 +518,28 @@ public class Loader modController.transition(LoaderState.POSTINITIALIZATION); modController.distributeStateMessage(); modController.transition(LoaderState.LOADCOMPLETE); + modController.distributeStateMessage(); FMLLog.info("Forge Mod Loader has successfully loaded %d mod%s", mods.size(), mods.size()==1 ? "" : "s"); } + + public Callable getCallableCrashInformation() + { + return new Callable() { + @Override + public String call() throws Exception + { + return getCrashInformation(); + } + }; + } + + public List getActiveModList() + { + return modController.getActiveModList(); + } + + public ModState getModState(ModContainer selectedMod) + { + return modController.getModState(selectedMod); + } } diff --git a/fml/common/cpw/mods/fml/common/LoaderState.java b/fml/common/cpw/mods/fml/common/LoaderState.java index addfe779f..8e50853a2 100644 --- a/fml/common/cpw/mods/fml/common/LoaderState.java +++ b/fml/common/cpw/mods/fml/common/LoaderState.java @@ -21,7 +21,7 @@ public enum LoaderState PREINITIALIZATION("Pre-initializing mods", FMLPreInitializationEvent.class), INITIALIZATION("Initializing mods", FMLInitializationEvent.class), POSTINITIALIZATION("Post-initializing mods", FMLPostInitializationEvent.class), - LOADCOMPLETE("Mod loading complete", null), + LOADCOMPLETE("Mod loading complete", FMLLoadCompleteEvent.class), ERRORED("Mod Loading errored",null); private Class eventClass; diff --git a/fml/common/cpw/mods/fml/common/ModContainer.java b/fml/common/cpw/mods/fml/common/ModContainer.java index 36298bd78..7c7a08264 100644 --- a/fml/common/cpw/mods/fml/common/ModContainer.java +++ b/fml/common/cpw/mods/fml/common/ModContainer.java @@ -18,6 +18,8 @@ import java.util.List; import com.google.common.eventbus.EventBus; +import cpw.mods.fml.common.LoaderState.ModState; + /** * The container that wraps around mods in the system. *

diff --git a/fml/common/cpw/mods/fml/common/asm/ASMTransformer.java b/fml/common/cpw/mods/fml/common/asm/ASMTransformer.java new file mode 100644 index 000000000..a4b106e73 --- /dev/null +++ b/fml/common/cpw/mods/fml/common/asm/ASMTransformer.java @@ -0,0 +1,31 @@ +package cpw.mods.fml.common.asm; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; + +import cpw.mods.fml.common.registry.BlockProxy; +import cpw.mods.fml.relauncher.IClassTransformer; + +public class ASMTransformer implements IClassTransformer +{ + @Override + public byte[] transform(String name, byte[] bytes) + { + if ("net.minecraft.src.Block".equals(name)) + { + ClassReader cr = new ClassReader(bytes); + ClassNode cn = new ClassNode(Opcodes.ASM4); + cr.accept(cn, ClassReader.EXPAND_FRAMES); + cn.interfaces.add(Type.getInternalName(BlockProxy.class)); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cn.accept(cw); + return cw.toByteArray(); + } + + return bytes; + } + +} diff --git a/fml/common/cpw/mods/fml/common/modloader/ModLoaderModContainer.java b/fml/common/cpw/mods/fml/common/modloader/ModLoaderModContainer.java index 754e6eeeb..89b3af010 100644 --- a/fml/common/cpw/mods/fml/common/modloader/ModLoaderModContainer.java +++ b/fml/common/cpw/mods/fml/common/modloader/ModLoaderModContainer.java @@ -60,7 +60,7 @@ import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.registry.TickRegistry; -import cpw.mods.fml.common.registry.WorldRegistry; +import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModMetadata; import cpw.mods.fml.common.ProxyInjector; @@ -348,7 +348,7 @@ public class ModLoaderModContainer implements ModContainer { ArrayList modList = new ArrayList(); - for (ModContainer mc : Loader.getModList()) + for (ModContainer mc : Loader.instance().getActiveModList()) { if (mc instanceof ModLoaderModContainer && mc.getMod()!=null) { @@ -508,7 +508,7 @@ public class ModLoaderModContainer implements ModContainer this.guiTickHandler.setMod(mod); TickRegistry.registerTickHandler(this.gameTickHandler); TickRegistry.registerTickHandler(this.guiTickHandler); - WorldRegistry.registerWorldGenerator(this.mod); + GameRegistry.registerWorldGenerator(this.mod); } catch (Exception e) { diff --git a/fml/common/cpw/mods/fml/common/registry/BlockProxy.java b/fml/common/cpw/mods/fml/common/registry/BlockProxy.java new file mode 100644 index 000000000..99d3a912b --- /dev/null +++ b/fml/common/cpw/mods/fml/common/registry/BlockProxy.java @@ -0,0 +1,6 @@ +package cpw.mods.fml.common.registry; + +public interface BlockProxy +{ + +} diff --git a/fml/common/cpw/mods/fml/common/registry/FMLRegistry.java b/fml/common/cpw/mods/fml/common/registry/FMLRegistry.java index b535a8fe4..7700068f2 100644 --- a/fml/common/cpw/mods/fml/common/registry/FMLRegistry.java +++ b/fml/common/cpw/mods/fml/common/registry/FMLRegistry.java @@ -60,6 +60,7 @@ public class FMLRegistry public static void registerBlock(Block block) { + GameRegistry.registerBlock((BlockProxy)block); instance.registerBlock(block); } diff --git a/fml/common/cpw/mods/fml/common/registry/WorldRegistry.java b/fml/common/cpw/mods/fml/common/registry/GameRegistry.java similarity index 54% rename from fml/common/cpw/mods/fml/common/registry/WorldRegistry.java rename to fml/common/cpw/mods/fml/common/registry/GameRegistry.java index 9ca974d49..5320fcb05 100644 --- a/fml/common/cpw/mods/fml/common/registry/WorldRegistry.java +++ b/fml/common/cpw/mods/fml/common/registry/GameRegistry.java @@ -4,11 +4,17 @@ import java.util.HashSet; import java.util.Random; import java.util.Set; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; + import cpw.mods.fml.common.IWorldGenerator; +import cpw.mods.fml.common.Mod.Block; +import cpw.mods.fml.common.ModContainer; -public class WorldRegistry +public class GameRegistry { - + private static Multimap blockRegistry = ArrayListMultimap.create(); + private static Multimap itemRegistry = ArrayListMultimap.create(); private static Set worldGenerators = new HashSet(); public static void registerWorldGenerator(IWorldGenerator generator) @@ -30,4 +36,16 @@ public class WorldRegistry } + public static Object buildBlock(ModContainer container, Class type, Block annotation) throws Exception + { + Object o = type.getConstructor(int.class).newInstance(250); + registerBlock((BlockProxy)o); + return o; + } + + public static void registerBlock(BlockProxy block) + { + + } + } diff --git a/fml/common/cpw/mods/fml/common/registry/ItemProxy.java b/fml/common/cpw/mods/fml/common/registry/ItemProxy.java new file mode 100644 index 000000000..ffb3b5f2d --- /dev/null +++ b/fml/common/cpw/mods/fml/common/registry/ItemProxy.java @@ -0,0 +1,6 @@ +package cpw.mods.fml.common.registry; + +public interface ItemProxy +{ + +}