From 7cc91cfb0c3e1ceebf0778f80ced044c27358f13 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 24 Oct 2012 16:39:55 -0400 Subject: [PATCH] Simple InterMod comms. Send a message using FMLInterModComms.sendMessage(). Receive messages through an @IMCCallback --- .../cpw/mods/fml/common/FMLModContainer.java | 9 +- .../cpw/mods/fml/common/LoadController.java | 26 +++-- common/cpw/mods/fml/common/Loader.java | 6 ++ common/cpw/mods/fml/common/LoaderState.java | 5 +- common/cpw/mods/fml/common/Mod.java | 16 ++- .../cpw/mods/fml/common/event/FMLEvent.java | 6 ++ .../fml/common/event/FMLInterModComms.java | 102 ++++++++++++++++++ .../mods/fml/common/event/FMLStateEvent.java | 6 -- 8 files changed, 154 insertions(+), 22 deletions(-) create mode 100644 common/cpw/mods/fml/common/event/FMLInterModComms.java diff --git a/common/cpw/mods/fml/common/FMLModContainer.java b/common/cpw/mods/fml/common/FMLModContainer.java index d580ec18a1..ed6be8ce5d 100644 --- a/common/cpw/mods/fml/common/FMLModContainer.java +++ b/common/cpw/mods/fml/common/FMLModContainer.java @@ -46,7 +46,9 @@ 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.FMLEvent; import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLInterModComms.IMCEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLServerStartedEvent; @@ -76,15 +78,16 @@ public class FMLModContainer implements ModContainer private DefaultArtifactVersion processedVersion; private boolean isNetworkMod; - private static final BiMap, Class> modAnnotationTypes = ImmutableBiMap., Class>builder() + private static final BiMap, Class> modAnnotationTypes = ImmutableBiMap., Class>builder() .put(FMLPreInitializationEvent.class, Mod.PreInit.class) .put(FMLInitializationEvent.class, Mod.Init.class) .put(FMLPostInitializationEvent.class, Mod.PostInit.class) .put(FMLServerStartingEvent.class, Mod.ServerStarting.class) .put(FMLServerStartedEvent.class, Mod.ServerStarted.class) .put(FMLServerStoppingEvent.class, Mod.ServerStopping.class) + .put(IMCEvent.class,Mod.IMCCallback.class) .build(); - private static final BiMap, Class> modTypeAnnotations = modAnnotationTypes.inverse(); + private static final BiMap, Class> modTypeAnnotations = modAnnotationTypes.inverse(); private String annotationDependencies; private VersionRange minecraftAccepted; @@ -422,7 +425,7 @@ public class FMLModContainer implements ModContainer } @Subscribe - public void handleModStateEvent(FMLStateEvent event) + public void handleModStateEvent(FMLEvent event) { Class annotation = modAnnotationTypes.get(event.getClass()); if (annotation == null) diff --git a/common/cpw/mods/fml/common/LoadController.java b/common/cpw/mods/fml/common/LoadController.java index c4dbb51321..4e869c53f0 100644 --- a/common/cpw/mods/fml/common/LoadController.java +++ b/common/cpw/mods/fml/common/LoadController.java @@ -19,6 +19,7 @@ import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import cpw.mods.fml.common.LoaderState.ModState; +import cpw.mods.fml.common.event.FMLEvent; import cpw.mods.fml.common.event.FMLLoadEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLStateEvent; @@ -124,7 +125,7 @@ public class LoadController } @Subscribe - public void propogateStateMessage(FMLStateEvent stateEvent) + public void propogateStateMessage(FMLEvent stateEvent) { if (stateEvent instanceof FMLPreInitializationEvent) { @@ -135,17 +136,20 @@ public class LoadController activeContainer = mc; String modId = mc.getModId(); stateEvent.applyModContainer(activeContainer()); - FMLLog.finer("Posting state event %s to mod %s", stateEvent.getEventType(), modId); + FMLLog.finer("Sending event %s to mod %s", stateEvent.getEventType(), modId); eventChannels.get(modId).post(stateEvent); - FMLLog.finer("State event %s delivered to mod %s", stateEvent.getEventType(), modId); + FMLLog.finer("Sent event %s to mod %s", stateEvent.getEventType(), modId); activeContainer = null; - if (!errors.containsKey(modId)) + if (stateEvent instanceof FMLStateEvent) { - modStates.put(modId, stateEvent.getModState()); - } - else - { - modStates.put(modId, ModState.ERRORED); + if (!errors.containsKey(modId)) + { + modStates.put(modId, ((FMLStateEvent)stateEvent).getModState()); + } + else + { + modStates.put(modId, ModState.ERRORED); + } } } } @@ -229,4 +233,8 @@ public class LoadController { return this.state == state; } + + boolean hasReachedState(LoaderState state) { + return this.state.ordinal()>=state.ordinal() && this.state!=LoaderState.ERRORED; + } } diff --git a/common/cpw/mods/fml/common/Loader.java b/common/cpw/mods/fml/common/Loader.java index 392655376f..90b89656b7 100644 --- a/common/cpw/mods/fml/common/Loader.java +++ b/common/cpw/mods/fml/common/Loader.java @@ -52,6 +52,7 @@ import com.google.common.collect.TreeMultimap; import cpw.mods.fml.common.LoaderState.ModState; import cpw.mods.fml.common.discovery.ModDiscoverer; +import cpw.mods.fml.common.event.FMLInterModComms; import cpw.mods.fml.common.event.FMLLoadEvent; import cpw.mods.fml.common.functions.ModIdFunction; import cpw.mods.fml.common.modloader.BaseModProxy; @@ -645,6 +646,7 @@ public class Loader // Mod controller should be in the initialization state here modController.distributeStateMessage(LoaderState.INITIALIZATION); modController.transition(LoaderState.POSTINITIALIZATION); + modController.distributeStateMessage(FMLInterModComms.IMCEvent.class); modController.distributeStateMessage(LoaderState.POSTINITIALIZATION); modController.transition(LoaderState.AVAILABLE); modController.distributeStateMessage(LoaderState.AVAILABLE); @@ -727,4 +729,8 @@ public class Loader { return minecraft; } + + public boolean hasReachedState(LoaderState state) { + return modController.hasReachedState(state); + } } diff --git a/common/cpw/mods/fml/common/LoaderState.java b/common/cpw/mods/fml/common/LoaderState.java index d59720b924..731e2a4e75 100644 --- a/common/cpw/mods/fml/common/LoaderState.java +++ b/common/cpw/mods/fml/common/LoaderState.java @@ -3,6 +3,7 @@ package cpw.mods.fml.common; import com.google.common.base.Throwables; import cpw.mods.fml.common.event.FMLConstructionEvent; +import cpw.mods.fml.common.event.FMLEvent; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLLoadCompleteEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; @@ -59,7 +60,7 @@ public enum LoaderState { return eventClass != null; } - + public FMLStateEvent getEvent(Object... eventData) { try @@ -87,7 +88,7 @@ public enum LoaderState AVAILABLE("Available"), DISABLED("Disabled"), ERRORED("Errored"); - + private String label; private ModState(String label) diff --git a/common/cpw/mods/fml/common/Mod.java b/common/cpw/mods/fml/common/Mod.java index d2d086dd26..a608fc7fcd 100644 --- a/common/cpw/mods/fml/common/Mod.java +++ b/common/cpw/mods/fml/common/Mod.java @@ -18,6 +18,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import cpw.mods.fml.common.event.FMLInterModComms; +import cpw.mods.fml.common.event.FMLInterModComms.IMCMessage; + import net.minecraft.src.ItemBlock; /** @@ -99,7 +102,7 @@ public @interface Mod @Target(ElementType.METHOD) public @interface ServerStarting {} /** - * Mark the designated method as being called at the "post-initialization" phase + * Mark the designated method as being called at the "server-started" phase * @author cpw * */ @@ -107,13 +110,22 @@ public @interface Mod @Target(ElementType.METHOD) public @interface ServerStarted {} /** - * Mark the designated method as being called at the "post-initialization" phase + * Mark the designated method as being called at the "server-stopping" phase * @author cpw * */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ServerStopping {} + /** + * Mark the designated method as the receiver for {@link FMLInterModComms} messages + * Called between {@link Init} and {@link PostInit} + * @author cpw + * + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface IMCCallback {} /** * Populate the annotated field with the mod instance. * @author cpw diff --git a/common/cpw/mods/fml/common/event/FMLEvent.java b/common/cpw/mods/fml/common/event/FMLEvent.java index 4014f7c7e3..5443715b6a 100644 --- a/common/cpw/mods/fml/common/event/FMLEvent.java +++ b/common/cpw/mods/fml/common/event/FMLEvent.java @@ -1,9 +1,15 @@ package cpw.mods.fml.common.event; +import cpw.mods.fml.common.ModContainer; + public class FMLEvent { public final String getEventType() { return getClass().getSimpleName(); } + + public void applyModContainer(ModContainer activeContainer) { + // NO OP + } } diff --git a/common/cpw/mods/fml/common/event/FMLInterModComms.java b/common/cpw/mods/fml/common/event/FMLInterModComms.java new file mode 100644 index 0000000000..5fe271b379 --- /dev/null +++ b/common/cpw/mods/fml/common/event/FMLInterModComms.java @@ -0,0 +1,102 @@ +package cpw.mods.fml.common.event; + +import java.util.List; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimaps; + +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.LoaderState; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.Mod.Init; +import cpw.mods.fml.common.Mod.PostInit; + + +/** + * Simple intermod communications to receive simple messages directed at you from + * other mods + * + * @author cpw + * + */ +public class FMLInterModComms { + private static ArrayListMultimap modMessages = ArrayListMultimap.create(); + /** + * Subscribe to this event to receive your messages (they are sent between {@link Init} and {@link PostInit}) + * + * @author cpw + * + */ + public static class IMCEvent extends FMLEvent { + private IMCEvent(List messages) + { + this.messages = Multimaps.index(messages, new Function() { + public String apply(IMCMessage msg) { return msg.sender; }; + }); + } + + @Override + public void applyModContainer(ModContainer activeContainer) { + currentList = messages.get(activeContainer.getModId()); + } + + private final ImmutableListMultimap messages; + + private ImmutableList currentList; + + public ImmutableList getMessages() + { + return currentList; + } + } + + /** + * You will receive an instance of this for each message sent + * @author cpw + * + */ + public static final class IMCMessage { + /** + * This is the modid of the mod that sent you the message + */ + public final String sender; + + /** + * This field, and {@link #value} are both at the mod's discretion + */ + public final String key; + /** + * This field, and {@link #key} are both at the mod's discretion + */ + public final String value; + + private IMCMessage(String sender, String key, String value) + { + this.key = key; + this.value = value; + this.sender = sender; + } + @Override + public String toString() { + return sender; + } + } + + public static boolean sendMessage(String modId, String key, String value) + { + if (Loader.instance().activeModContainer()==null) + { + return false; + } + modMessages.put(modId, new IMCMessage(Loader.instance().activeModContainer().getModId(), key, value)); + return Loader.isModLoaded(modId) && !Loader.instance().hasReachedState(LoaderState.POSTINITIALIZATION); + } +} diff --git a/common/cpw/mods/fml/common/event/FMLStateEvent.java b/common/cpw/mods/fml/common/event/FMLStateEvent.java index 0f1a3decd3..04540b323c 100644 --- a/common/cpw/mods/fml/common/event/FMLStateEvent.java +++ b/common/cpw/mods/fml/common/event/FMLStateEvent.java @@ -2,7 +2,6 @@ package cpw.mods.fml.common.event; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.LoaderState.ModState; -import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.Side; public abstract class FMLStateEvent extends FMLEvent @@ -14,11 +13,6 @@ public abstract class FMLStateEvent extends FMLEvent public abstract ModState getModState(); - public void applyModContainer(ModContainer activeContainer) - { - // NO OP - } - public Side getSide() { return FMLCommonHandler.instance().getSide();