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