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 this.currentList = null; 066 FMLLog.finest("Attempting to deliver %d IMC messages to mod %s", modMessages.get(activeContainer.getModId()).size(), activeContainer.getModId()); 067 } 068 069 private ImmutableList<IMCMessage> currentList; 070 071 public ImmutableList<IMCMessage> getMessages() 072 { 073 if (currentList == null) 074 { 075 currentList = ImmutableList.copyOf(modMessages.removeAll(activeContainer.getModId())); 076 } 077 return currentList; 078 } 079 } 080 081 /** 082 * You will receive an instance of this for each message sent 083 * 084 * @author cpw 085 * 086 */ 087 public static final class IMCMessage { 088 /** 089 * This is the modid of the mod that sent you the message 090 */ 091 private String sender; 092 /** 093 * This field, and {@link #value} are both at the mod's discretion 094 */ 095 public final String key; 096 /** 097 * This field, and {@link #key} are both at the mod's discretion 098 */ 099 private Object value; 100 101 private IMCMessage(String key, Object value) 102 { 103 this.key = key; 104 this.value = value; 105 } 106 107 @Override 108 public String toString() 109 { 110 return sender; 111 } 112 113 public String getSender() 114 { 115 return this.sender; 116 } 117 118 void setSender(ModContainer activeModContainer) 119 { 120 this.sender = activeModContainer.getModId(); 121 } 122 123 public String getStringValue() 124 { 125 return (String) value; 126 } 127 128 public NBTTagCompound getNBTValue() 129 { 130 return (NBTTagCompound) value; 131 } 132 133 public ItemStack getItemStackValue() 134 { 135 return (ItemStack) value; 136 } 137 138 public Class<?> getMessageType() 139 { 140 return value.getClass(); 141 } 142 143 public boolean isStringMessage() 144 { 145 return String.class.isAssignableFrom(getMessageType()); 146 } 147 148 public boolean isItemStackMessage() 149 { 150 return ItemStack.class.isAssignableFrom(getMessageType()); 151 } 152 153 public boolean isNBTMessage() 154 { 155 return NBTTagCompound.class.isAssignableFrom(getMessageType()); 156 } 157 } 158 159 public static boolean sendMessage(String modId, String key, NBTTagCompound value) 160 { 161 return enqueueStartupMessage(modId, new IMCMessage(key, value)); 162 } 163 public static boolean sendMessage(String modId, String key, ItemStack value) 164 { 165 return enqueueStartupMessage(modId, new IMCMessage(key, value)); 166 } 167 public static boolean sendMessage(String modId, String key, String value) 168 { 169 return enqueueStartupMessage(modId, new IMCMessage(key, value)); 170 } 171 172 public static void sendRuntimeMessage(Object sourceMod, String modId, String key, NBTTagCompound value) 173 { 174 enqueueMessage(sourceMod, modId, new IMCMessage(key, value)); 175 } 176 177 public static void sendRuntimeMessage(Object sourceMod, String modId, String key, ItemStack value) 178 { 179 enqueueMessage(sourceMod, modId, new IMCMessage(key, value)); 180 } 181 182 public static void sendRuntimeMessage(Object sourceMod, String modId, String key, String value) 183 { 184 enqueueMessage(sourceMod, modId, new IMCMessage(key, value)); 185 } 186 187 private static boolean enqueueStartupMessage(String modTarget, IMCMessage message) 188 { 189 if (Loader.instance().activeModContainer() == null) 190 { 191 return false; 192 } 193 enqueueMessage(Loader.instance().activeModContainer(), modTarget, message); 194 return Loader.isModLoaded(modTarget) && !Loader.instance().hasReachedState(LoaderState.POSTINITIALIZATION); 195 196 } 197 private static void enqueueMessage(Object sourceMod, String modTarget, IMCMessage message) 198 { 199 ModContainer mc; 200 if (sourceMod instanceof ModContainer) { 201 mc = (ModContainer) sourceMod; 202 } 203 else 204 { 205 mc = FMLCommonHandler.instance().findContainerFor(sourceMod); 206 } 207 if (mc != null && Loader.isModLoaded(modTarget)) 208 { 209 message.setSender(mc); 210 modMessages.put(modTarget, message); 211 } 212 } 213 214 /** 215 * Retrieve any pending runtime messages for the mod 216 * @param forMod The {@link Instance} of the Mod to fetch messages for 217 * @return any messages - the collection will never be null 218 */ 219 public static ImmutableList<IMCMessage> fetchRuntimeMessages(Object forMod) 220 { 221 ModContainer mc = FMLCommonHandler.instance().findContainerFor(forMod); 222 if (mc != null) 223 { 224 return ImmutableList.copyOf(modMessages.removeAll(mc.getModId())); 225 } 226 else 227 { 228 return emptyIMCList; 229 } 230 } 231}