    001    package cpw.mods.fml.common.event;
    002
    003    import java.util.List;
    004
    005    import net.minecraft.item.ItemStack;
    006    import net.minecraft.nbt.NBTTagCompound;
    007
    008    import com.google.common.base.Function;
    009    import com.google.common.base.Functions;
    010    import com.google.common.base.Predicate;
    011    import com.google.common.base.Predicates;
    012    import com.google.common.collect.ArrayListMultimap;
    013    import com.google.common.collect.FluentIterable;
    014    import com.google.common.collect.ImmutableList;
    015    import com.google.common.collect.ImmutableListMultimap;
    016    import com.google.common.collect.Maps;
    017    import com.google.common.collect.Multimaps;
    018
    019    import cpw.mods.fml.common.FMLCommonHandler;
    020    import cpw.mods.fml.common.FMLLog;
    021    import cpw.mods.fml.common.Loader;
    022    import cpw.mods.fml.common.LoaderState;
    023    import cpw.mods.fml.common.Mod.Instance;
    024    import cpw.mods.fml.common.ModContainer;
    025    import cpw.mods.fml.common.Mod.Init;
    026    import cpw.mods.fml.common.Mod.PostInit;
    027
    028    /**
    029     * Simple intermod communications to receive simple messages directed at you
    030     * from other mods
    031     *
    032     * @author cpw
    033     *
    034     */
    035    public class FMLInterModComms {
    036        private static final ImmutableList<IMCMessage> emptyIMCList = ImmutableList.<IMCMessage>of();
    037        private static ArrayListMultimap<String, IMCMessage> modMessages = ArrayListMultimap.create();
    038
    039        /**
    040         * Subscribe to this event to receive your messages (they are sent between
    041         * {@link Init} and {@link PostInit})
    042         *
    043         * @author cpw
    044         *
    045         */
    046        public static class IMCEvent extends FMLEvent {
    047            @Override
    048            public void applyModContainer(ModContainer activeContainer)
    049            {
    050                currentList = ImmutableList.copyOf(modMessages.removeAll(activeContainer.getModId()));
    051                FMLLog.finest("Attempting to deliver %d IMC messages to mod %s", currentList.size(), activeContainer.getModId());
    052            }
    053
    054            private ImmutableList<IMCMessage> currentList;
    055
    056            public ImmutableList<IMCMessage> getMessages()
    057            {
    058                return currentList;
    059            }
    060        }
    061
    062        /**
    063         * You will receive an instance of this for each message sent
    064         *
    065         * @author cpw
    066         *
    067         */
    068        public static final class IMCMessage {
    069            /**
    070             * This is the modid of the mod that sent you the message
    071             */
    072            private String sender;
    073            /**
    074             * This field, and {@link #value} are both at the mod's discretion
    075             */
    076            public final String key;
    077            /**
    078             * This field, and {@link #key} are both at the mod's discretion
    079             */
    080            private Object value;
    081
    082            private IMCMessage(String key, Object value)
    083            {
    084                this.key = key;
    085                this.value = value;
    086            }
    087
    088            @Override
    089            public String toString()
    090            {
    091                return sender;
    092            }
    093
    094            public String getSender()
    095            {
    096                return this.sender;
    097            }
    098
    099            void setSender(ModContainer activeModContainer)
    100            {
    101                this.sender = activeModContainer.getModId();
    102            }
    103
    104            public String getStringValue()
    105            {
    106                return (String) value;
    107            }
    108
    109            public NBTTagCompound getNBTValue()
    110            {
    111                return (NBTTagCompound) value;
    112            }
    113
    114            public ItemStack getItemStackValue()
    115            {
    116                return (ItemStack) value;
    117            }
    118
    119            public Class<?> getMessageType()
    120            {
    121                return value.getClass();
    122            }
    123
    124            public boolean isStringMessage()
    125            {
    126                return String.class.isAssignableFrom(getMessageType());
    127            }
    128
    129            public boolean isItemStackMessage()
    130            {
    131                return ItemStack.class.isAssignableFrom(getMessageType());
    132            }
    133
    134            public boolean isNBTMessage()
    135            {
    136                return NBTTagCompound.class.isAssignableFrom(getMessageType());
    137            }
    138        }
    139
    140        public static boolean sendMessage(String modId, String key, NBTTagCompound value)
    141        {
    142            return enqueueStartupMessage(modId, new IMCMessage(key, value));
    143        }
    144        public static boolean sendMessage(String modId, String key, ItemStack value)
    145        {
    146            return enqueueStartupMessage(modId, new IMCMessage(key, value));
    147        }
    148        public static boolean sendMessage(String modId, String key, String value)
    149        {
    150            return enqueueStartupMessage(modId, new IMCMessage(key, value));
    151        }
    152
    153        public static void sendRuntimeMessage(Object sourceMod, String modId, String key, NBTTagCompound value)
    154        {
    155            enqueueMessage(sourceMod, modId, new IMCMessage(key, value));
    156        }
    157
    158        public static void sendRuntimeMessage(Object sourceMod, String modId, String key, ItemStack value)
    159        {
    160            enqueueMessage(sourceMod, modId, new IMCMessage(key, value));
    161        }
    162
    163        public static void sendRuntimeMessage(Object sourceMod, String modId, String key, String value)
    164        {
    165            enqueueMessage(sourceMod, modId, new IMCMessage(key, value));
    166        }
    167
    168        private static boolean enqueueStartupMessage(String modTarget, IMCMessage message)
    169        {
    170            if (Loader.instance().activeModContainer() == null)
    171            {
    172                return false;
    173            }
    174            enqueueMessage(Loader.instance().activeModContainer(), modTarget, message);
    175            return Loader.isModLoaded(modTarget) && !Loader.instance().hasReachedState(LoaderState.POSTINITIALIZATION);
    176
    177        }
    178        private static void enqueueMessage(Object sourceMod, String modTarget, IMCMessage message)
    179        {
    180            ModContainer mc;
    181            if (sourceMod instanceof ModContainer) {
    182                mc = (ModContainer) sourceMod;
    183            }
    184            else
    185            {
    186                mc = FMLCommonHandler.instance().findContainerFor(sourceMod);
    187            }
    188            if (mc != null && Loader.isModLoaded(modTarget))
    189            {
    190                message.setSender(mc);
    191                modMessages.put(modTarget, message);
    192            }
    193        }
    194
    195        /**
    196         * Retrieve any pending runtime messages for the mod
    197         * @param forMod The {@link Instance} of the Mod to fetch messages for
    198         * @return any messages - the collection will never be null
    199         */
    200        public static ImmutableList<IMCMessage> fetchRuntimeMessages(Object forMod)
    201        {
    202            ModContainer mc = FMLCommonHandler.instance().findContainerFor(forMod);
    203            if (mc != null)
    204            {
    205                return ImmutableList.copyOf(modMessages.removeAll(mc));
    206            }
    207            else
    208            {
    209                return emptyIMCList;
    210            }
    211        }
    212    }