Simple InterMod comms. Send a message using FMLInterModComms.sendMessage(). Receive messages through an @IMCCallback

This commit is contained in:
Christian 2012-10-24 16:39:55 -04:00
parent 39d6ef64c2
commit a72f6b1eff
8 changed files with 154 additions and 22 deletions

View file

@ -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<? extends FMLStateEvent>, Class<? extends Annotation>> modAnnotationTypes = ImmutableBiMap.<Class<? extends FMLStateEvent>, Class<? extends Annotation>>builder()
private static final BiMap<Class<? extends FMLEvent>, Class<? extends Annotation>> modAnnotationTypes = ImmutableBiMap.<Class<? extends FMLEvent>, Class<? extends Annotation>>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<? extends Annotation>, Class<? extends FMLStateEvent>> modTypeAnnotations = modAnnotationTypes.inverse();
private static final BiMap<Class<? extends Annotation>, Class<? extends FMLEvent>> 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<? extends Annotation> annotation = modAnnotationTypes.get(event.getClass());
if (annotation == null)

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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)

View file

@ -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

View file

@ -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
}
}

View file

@ -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<String, IMCMessage> 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<IMCMessage> messages)
{
this.messages = Multimaps.index(messages, new Function<IMCMessage, String>() {
public String apply(IMCMessage msg) { return msg.sender; };
});
}
@Override
public void applyModContainer(ModContainer activeContainer) {
currentList = messages.get(activeContainer.getModId());
}
private final ImmutableListMultimap<String, IMCMessage> messages;
private ImmutableList<IMCMessage> currentList;
public ImmutableList<IMCMessage> 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);
}
}

View file

@ -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();