From 8bef5128032546533a395d94bd7e5b523aab83f6 Mon Sep 17 00:00:00 2001 From: Christian Date: Sun, 26 Aug 2012 10:45:00 -0400 Subject: [PATCH] Versions now have two flavours: the @Mod(version) which is the "programmatic version" and is used for all version relationship calculation. The "display version" as sourced from mcmod.info is used for display purposes only and can be literally anything. Note: they fall back to one another when they're missing, and to "1.0" if both are absent. Also, changed @Instance. Now, you can inject *other* mods using @Instance as long as you depend on them as a "before" or "dependency" relationship. Classes containing @Instance will only be loaded if the Mod the @Instance refers is present. So you don't have to worry about runtime class resolution. --- client/cpw/mods/fml/client/GuiModList.java | 2 +- .../cpw/mods/fml/client/GuiSlotModList.java | 4 +- .../mods/fml/common/DummyModContainer.java | 6 + .../cpw/mods/fml/common/FMLModContainer.java | 118 +++++++++++++----- .../mods/fml/common/InjectedModContainer.java | 6 + common/cpw/mods/fml/common/ModContainer.java | 2 + .../modloader/ModLoaderModContainer.java | 8 +- .../src/cpw/mods/mockmod/MockBlock.java | 4 + .../src/cpw/mods/mockmod/MockMod.java | 4 +- .../src/net/minecraft/src/mod_testMod.java | 4 +- 10 files changed, 122 insertions(+), 36 deletions(-) diff --git a/client/cpw/mods/fml/client/GuiModList.java b/client/cpw/mods/fml/client/GuiModList.java index 324bf0aee3..805e7e4929 100644 --- a/client/cpw/mods/fml/client/GuiModList.java +++ b/client/cpw/mods/fml/client/GuiModList.java @@ -123,7 +123,7 @@ public class GuiModList extends GuiScreen this.field_73886_k.func_78261_a(selectedMod.getMetadata().name, offset, shifty, 0xFFFFFF); shifty += 12; - shifty = drawLine(String.format("Version: %s (%s)", selectedMod.getMetadata().version, selectedMod.getVersion()), offset, shifty); + shifty = drawLine(String.format("Version: %s (%s)", selectedMod.getDisplayVersion(), 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); diff --git a/client/cpw/mods/fml/client/GuiSlotModList.java b/client/cpw/mods/fml/client/GuiSlotModList.java index f45eafeaef..bccb26a41d 100644 --- a/client/cpw/mods/fml/client/GuiSlotModList.java +++ b/client/cpw/mods/fml/client/GuiSlotModList.java @@ -74,13 +74,13 @@ public class GuiSlotModList extends GuiScrollingList if (Loader.instance().getModState(mc)==ModState.DISABLED) { this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getName(), listWidth - 10), this.left + 3 , var3 + 2, 0xFF2222); - this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getVersion(), listWidth - 10), this.left + 3 , var3 + 12, 0xFF2222); + this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getDisplayVersion(), listWidth - 10), this.left + 3 , var3 + 12, 0xFF2222); this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a("DISABLED", listWidth - 10), this.left + 3 , var3 + 22, 0xFF2222); } else { this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getName(), listWidth - 10), this.left + 3 , var3 + 2, 0xFFFFFF); - this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getVersion(), listWidth - 10), this.left + 3 , var3 + 12, 0xCCCCCC); + this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getDisplayVersion(), listWidth - 10), this.left + 3 , var3 + 12, 0xCCCCCC); this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getMetadata() !=null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 10), this.left + 3 , var3 + 22, 0xCCCCCC); } } diff --git a/common/cpw/mods/fml/common/DummyModContainer.java b/common/cpw/mods/fml/common/DummyModContainer.java index 3a375ddedc..4f2584c048 100644 --- a/common/cpw/mods/fml/common/DummyModContainer.java +++ b/common/cpw/mods/fml/common/DummyModContainer.java @@ -126,4 +126,10 @@ public class DummyModContainer implements ModContainer { return false; } + + @Override + public String getDisplayVersion() + { + return md.version; + } } diff --git a/common/cpw/mods/fml/common/FMLModContainer.java b/common/cpw/mods/fml/common/FMLModContainer.java index 5bbbc0d82d..f1b420bb08 100644 --- a/common/cpw/mods/fml/common/FMLModContainer.java +++ b/common/cpw/mods/fml/common/FMLModContainer.java @@ -16,11 +16,14 @@ import java.io.File; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Level; +import com.google.common.base.Function; import com.google.common.base.Strings; import com.google.common.base.Throwables; import com.google.common.collect.ArrayListMultimap; @@ -28,6 +31,7 @@ import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; +import com.google.common.collect.SetMultimap; import com.google.common.collect.Sets; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; @@ -35,6 +39,7 @@ import com.google.common.eventbus.Subscribe; import cpw.mods.fml.common.Mod.Instance; import cpw.mods.fml.common.Mod.Metadata; import cpw.mods.fml.common.discovery.ASMDataTable; +import cpw.mods.fml.common.discovery.ASMDataTable.ASMData; import cpw.mods.fml.common.event.FMLConstructionEvent; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; @@ -56,9 +61,7 @@ public class FMLModContainer implements ModContainer private String className; private Map descriptor; private boolean enabled = true; - private List requirements; - private List dependencies; - private List dependants; + private String internalVersion; private boolean overridesMetadata; private EventBus eventBus; private LoadController controller; @@ -100,7 +103,7 @@ public class FMLModContainer implements ModContainer @Override public String getVersion() { - return modMetadata.version; + return internalVersion; } @Override @@ -146,10 +149,16 @@ public class FMLModContainer implements ModContainer FMLLog.info("Mod %s is missing the required element 'name'. Substituting %s", getModId(), getModId()); modMetadata.name = getModId(); } - if (Strings.isNullOrEmpty(modMetadata.version)) + internalVersion = (String) descriptor.get("version"); + if (Strings.isNullOrEmpty(internalVersion) && !Strings.isNullOrEmpty(modMetadata.version)) { - FMLLog.warning("Mod %s is missing the required element 'version'. Substituting 1", getModId()); - modMetadata.version = "1"; + FMLLog.warning("Mod %s is missing the required element 'version'. Falling back to metadata version %s", getModId(), modMetadata.version); + modMetadata.version = internalVersion; + } + if (Strings.isNullOrEmpty(internalVersion)) + { + FMLLog.warning("Mod %s is missing the required element 'version' and no fallback can be found. Substituting '1.0'.", getModId()); + modMetadata.version = internalVersion = "1.0"; } } @@ -216,15 +225,6 @@ public class FMLModContainer implements ModContainer { Multimap,Object> anns = ArrayListMultimap.create(); - for (Field f : clazz.getDeclaredFields()) - { - for (Annotation a : f.getAnnotations()) - { - f.setAccessible(true); - anns.put(a.annotationType(), f); - } - } - for (Method m : clazz.getDeclaredMethods()) { for (Annotation a : m.getAnnotations()) @@ -248,20 +248,25 @@ public class FMLModContainer implements ModContainer return anns; } - private void processFieldAnnotations() throws Exception + private void processFieldAnnotations(ASMDataTable asmDataTable) throws Exception { - // Instance annotation - for (Object o : annotations.get(Instance.class)) - { - Field f = (Field) o; - f.set(modInstance, modInstance); - } + SetMultimap annotations = asmDataTable.getAnnotationsFor(this); - for (Object o : annotations.get(Metadata.class)) + parseSimpleFieldAnnotation(annotations, Instance.class.getName(), new Function() { - Field f = (Field) o; - f.set(modInstance, modMetadata); - } + public Object apply(ModContainer mc) + { + return mc.getMod(); + } + }); + parseSimpleFieldAnnotation(annotations, Metadata.class.getName(), new Function() + { + public Object apply(ModContainer mc) + { + return mc.getMetadata(); + } + }); + //TODO // for (Object o : annotations.get(Block.class)) // { @@ -270,6 +275,57 @@ public class FMLModContainer implements ModContainer // } } + private void parseSimpleFieldAnnotation(SetMultimap annotations, String annotationClassName, Function retreiver) throws IllegalAccessException + { + System.out.println(annotationClassName); + String[] annName = annotationClassName.split("\\."); + System.out.println(Arrays.toString(annName)); + String annotationName = annName[annName.length - 1]; + for (ASMData targets : annotations.get(annotationClassName)) + { + String targetMod = (String) targets.getAnnotationInfo().get("value"); + Field f = null; + Object injectedMod = null; + ModContainer mc = this; + boolean isStatic = false; + Class clz = modInstance.getClass(); + if (!Strings.isNullOrEmpty(targetMod)) + { + mc = Loader.instance().getIndexedModList().get(targetMod); + } + if (mc != null) + { + try + { + clz = Class.forName(targets.getClassName(), true, Loader.instance().getModClassLoader()); + f = clz.getDeclaredField(targets.getObjectName()); + f.setAccessible(true); + isStatic = Modifier.isStatic(f.getModifiers()); + injectedMod = retreiver.apply(mc); + } + catch (Exception e) + { + Throwables.propagateIfPossible(e); + FMLLog.log(Level.WARNING, e, "Attempting to load @%s in class %s for %s and failing", annotationName, targets.getClassName(), mc.getModId()); + } + } + if (f != null) + { + Object target = null; + if (!isStatic) + { + target = modInstance; + if (!modInstance.getClass().equals(clz)) + { + FMLLog.warning("Unable to inject @%s in non-static field %s.%s for %s as it is NOT the primary mod instance", annotationName, targets.getClassName(), targets.getObjectName(), mc.getModId()); + continue; + } + } + f.set(target, injectedMod); + } + } + } + @Subscribe public void constructMod(FMLConstructionEvent event) { @@ -285,7 +341,7 @@ public class FMLModContainer implements ModContainer isNetworkMod = FMLNetworkHandler.instance().registerNetworkMod(this, clazz, event.getASMHarvestedData()); modInstance = clazz.newInstance(); ProxyInjector.inject(this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide()); - processFieldAnnotations(); + processFieldAnnotations(event.getASMHarvestedData()); } catch (Throwable e) { @@ -337,4 +393,10 @@ public class FMLModContainer implements ModContainer { return isNetworkMod; } + + @Override + public String getDisplayVersion() + { + return modMetadata.version; + } } diff --git a/common/cpw/mods/fml/common/InjectedModContainer.java b/common/cpw/mods/fml/common/InjectedModContainer.java index aa64446cc6..104b01b35e 100644 --- a/common/cpw/mods/fml/common/InjectedModContainer.java +++ b/common/cpw/mods/fml/common/InjectedModContainer.java @@ -104,4 +104,10 @@ public class InjectedModContainer implements ModContainer { return true; } + + @Override + public String getDisplayVersion() + { + return wrappedContainer.getDisplayVersion(); + } } diff --git a/common/cpw/mods/fml/common/ModContainer.java b/common/cpw/mods/fml/common/ModContainer.java index c188a29d70..e45e67173d 100644 --- a/common/cpw/mods/fml/common/ModContainer.java +++ b/common/cpw/mods/fml/common/ModContainer.java @@ -150,4 +150,6 @@ public interface ModContainer boolean isImmutable(); boolean isNetworkMod(); + + String getDisplayVersion(); } diff --git a/common/cpw/mods/fml/common/modloader/ModLoaderModContainer.java b/common/cpw/mods/fml/common/modloader/ModLoaderModContainer.java index 4a550fc9b8..7dae23ab79 100644 --- a/common/cpw/mods/fml/common/modloader/ModLoaderModContainer.java +++ b/common/cpw/mods/fml/common/modloader/ModLoaderModContainer.java @@ -446,7 +446,7 @@ public class ModLoaderModContainer implements ModContainer @Override public void bindMetadata(MetadataCollection mc) { - Map dummyMetadata = ImmutableMap.builder().put("name", modId).put("version", "").build(); + Map dummyMetadata = ImmutableMap.builder().put("name", modId).put("version", "1.0").build(); this.metadata = mc.getMetadataForId(modId, dummyMetadata); Loader.instance().computeDependencies(sortingProperties, getRequirements(), getDependencies(), getDependants()); } @@ -585,4 +585,10 @@ public class ModLoaderModContainer implements ModContainer { return this.isNetworkMod; } + + @Override + public String getDisplayVersion() + { + return metadata!=null ? metadata.version : getVersion(); + } } diff --git a/eclipse/FML-MockMod/src/cpw/mods/mockmod/MockBlock.java b/eclipse/FML-MockMod/src/cpw/mods/mockmod/MockBlock.java index 67ae90c41e..c33ef24a15 100644 --- a/eclipse/FML-MockMod/src/cpw/mods/mockmod/MockBlock.java +++ b/eclipse/FML-MockMod/src/cpw/mods/mockmod/MockBlock.java @@ -1,10 +1,14 @@ package cpw.mods.mockmod; +import cpw.mods.fml.common.Mod.Instance; import net.minecraft.src.Block; import net.minecraft.src.Material; public class MockBlock extends Block { + @Instance("mod_testMod") + public static Object tstInstance; + public MockBlock(int id) { super(id,Material.field_76259_v); diff --git a/eclipse/FML-MockMod/src/cpw/mods/mockmod/MockMod.java b/eclipse/FML-MockMod/src/cpw/mods/mockmod/MockMod.java index 51eebb139c..9118933bb6 100644 --- a/eclipse/FML-MockMod/src/cpw/mods/mockmod/MockMod.java +++ b/eclipse/FML-MockMod/src/cpw/mods/mockmod/MockMod.java @@ -18,7 +18,7 @@ import cpw.mods.fml.common.network.NetworkMod; import cpw.mods.fml.common.network.Player; import cpw.mods.fml.common.ModMetadata; -@Mod(modid="MockMod", name="Mock Mod",version="1.2.3", dependencies="before:mod_testMod", useMetadata=true) +@Mod(modid="MockMod", name="Mock Mod",version="1.2.3", dependencies="after:mod_testMod", useMetadata=true) @NetworkMod(channels={"MockMod"},clientSideRequired=true,packetHandler=MockMod.PacketHandler.class) public class MockMod { @@ -58,6 +58,6 @@ public class MockMod @Init public void init(FMLInitializationEvent evt) { - System.out.printf("Hello from mockmod init : %s %s\n", myInstance, meta); + System.out.printf("Hello from mockmod init : %s %s %s\n", myInstance, meta, MockBlock.tstInstance); } } diff --git a/eclipse/simpletestmod/src/net/minecraft/src/mod_testMod.java b/eclipse/simpletestmod/src/net/minecraft/src/mod_testMod.java index 1b5b6162c3..a6ea4d6d25 100644 --- a/eclipse/simpletestmod/src/net/minecraft/src/mod_testMod.java +++ b/eclipse/simpletestmod/src/net/minecraft/src/mod_testMod.java @@ -19,7 +19,7 @@ import net.minecraft.client.Minecraft; @NetworkMod(channels={"mod_TestMod"},clientSideRequired=true,packetHandler=mod_testMod.PacketHandler.class) public class mod_testMod extends BaseMod { - + @MLProp public static int test = 0; public static class PacketHandler implements IPacketHandler @@ -116,6 +116,6 @@ public class mod_testMod extends BaseMod { @Override public String getPriorities() { - return "after:MockMod"; + return "before:MockMod"; } } \ No newline at end of file