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