ForgePatch/fml/common/cpw/mods/fml/common/LoadController.java

211 lines
7.0 KiB
Java
Raw Normal View History

package cpw.mods.fml.common;
2012-07-24 01:20:37 +00:00
import java.util.List;
2012-07-22 14:26:38 +00:00
import java.util.Map;
2012-07-23 19:03:17 +00:00
import java.util.Map.Entry;
2012-07-22 14:26:38 +00:00
import java.util.logging.Level;
import com.google.common.base.Joiner;
2012-07-23 19:03:17 +00:00
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
2012-07-22 14:26:38 +00:00
import com.google.common.collect.ImmutableMap;
2012-08-17 13:24:38 +00:00
import com.google.common.collect.ImmutableMap.Builder;
2012-07-24 01:20:37 +00:00
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
2012-07-22 14:26:38 +00:00
import com.google.common.collect.Multimap;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
2012-07-22 14:26:38 +00:00
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.event.FMLLoadEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLStateEvent;
public class LoadController
{
2012-07-22 14:26:38 +00:00
private Loader loader;
private EventBus masterChannel;
private ImmutableMap<String,EventBus> eventChannels;
private LoaderState state;
2012-07-23 19:03:17 +00:00
private Multimap<String, ModState> modStates = ArrayListMultimap.create();
private Multimap<String, Throwable> errors = ArrayListMultimap.create();
2012-07-22 14:26:38 +00:00
private Map<String, ModContainer> modList;
2012-07-24 01:20:37 +00:00
private List<ModContainer> activeModList = Lists.newArrayList();
private String activeContainer;
private BiMap<ModContainer, Object> modObjectList;
2012-07-22 14:26:38 +00:00
public LoadController(Loader loader)
{
this.loader = loader;
this.masterChannel = new EventBus("FMLMainChannel");
this.masterChannel.register(this);
state = LoaderState.NOINIT;
}
@Subscribe
public void buildModList(FMLLoadEvent event)
{
this.modList = loader.getIndexedModList();
2012-07-22 14:26:38 +00:00
Builder<String, EventBus> eventBus = ImmutableMap.builder();
2012-07-24 01:20:37 +00:00
for (ModContainer mod : loader.getModList())
2012-07-22 14:26:38 +00:00
{
EventBus bus = new EventBus(mod.getModId());
boolean isActive = mod.registerBus(bus, this);
if (isActive)
{
2012-07-23 19:03:17 +00:00
FMLLog.fine("Activating mod %s", mod.getModId());
2012-07-24 01:20:37 +00:00
activeModList.add(mod);
2012-07-22 14:26:38 +00:00
modStates.put(mod.getModId(), ModState.UNLOADED);
eventBus.put(mod.getModId(), bus);
}
else
{
2012-07-23 19:03:17 +00:00
FMLLog.warning("Mod %s has been disabled through configuration", mod.getModId());
2012-07-22 14:26:38 +00:00
modStates.put(mod.getModId(), ModState.UNLOADED);
modStates.put(mod.getModId(), ModState.DISABLED);
}
}
2012-07-22 14:26:38 +00:00
eventChannels = eventBus.build();
}
public void distributeStateMessage(LoaderState state, Object... eventData)
2012-07-22 14:26:38 +00:00
{
if (state.hasEvent())
{
masterChannel.post(state.getEvent(eventData));
}
}
2012-07-23 19:03:17 +00:00
public void transition(LoaderState desiredState)
2012-07-22 14:26:38 +00:00
{
2012-07-23 19:03:17 +00:00
LoaderState oldState = state;
2012-07-22 14:26:38 +00:00
state = state.transition(!errors.isEmpty());
2012-07-23 19:03:17 +00:00
if (state != desiredState)
{
FMLLog.severe("Fatal errors were detected during the transition from %s to %s. Loading cannot continue", oldState, desiredState);
StringBuilder sb = new StringBuilder();
printModStates(sb);
FMLLog.severe(sb.toString());
FMLLog.severe("The following problems were captured during this phase");
for (Entry<String, Throwable> error : errors.entries())
{
FMLLog.log(Level.SEVERE, error.getValue(), "Caught exception from %s", error.getKey());
}
2012-07-24 01:20:37 +00:00
// Throw embedding the first error (usually the only one)
throw new LoaderException(errors.values().iterator().next());
2012-07-23 19:03:17 +00:00
}
2012-07-22 14:26:38 +00:00
}
2012-07-24 01:20:37 +00:00
public ModContainer activeContainer()
{
return activeContainer!=null ? modList.get(activeContainer) : null;
}
@Subscribe
2012-07-23 19:03:17 +00:00
public void propogateStateMessage(FMLStateEvent stateEvent)
2012-07-22 14:26:38 +00:00
{
if (stateEvent instanceof FMLPreInitializationEvent)
{
modObjectList = buildModObjectList();
}
2012-07-22 14:26:38 +00:00
for (Map.Entry<String,EventBus> entry : eventChannels.entrySet())
{
2012-07-24 01:20:37 +00:00
activeContainer = entry.getKey();
stateEvent.applyModContainer(activeContainer());
FMLLog.finer("Posting state event %s to mod %s", stateEvent, entry.getKey());
2012-07-22 14:26:38 +00:00
entry.getValue().post(stateEvent);
FMLLog.finer("State event %s delivered to mod %s", stateEvent, entry.getKey());
2012-07-24 01:20:37 +00:00
activeContainer = null;
2012-07-23 19:03:17 +00:00
if (!errors.containsKey(entry.getKey()))
2012-07-22 14:26:38 +00:00
{
modStates.put(entry.getKey(), stateEvent.getModState());
}
else
{
modStates.put(entry.getKey(), ModState.ERRORED);
}
}
}
public ImmutableBiMap<ModContainer, Object> buildModObjectList()
{
ImmutableBiMap.Builder<ModContainer, Object> builder = ImmutableBiMap.<ModContainer, Object>builder();
for (ModContainer mc : activeModList)
{
if (!mc.isImmutable() && mc.getMod()!=null)
{
builder.put(mc, mc.getMod());
}
if (mc.getMod()==null && !mc.isImmutable() && state!=LoaderState.CONSTRUCTING)
{
FMLLog.severe("There is a severe problem with %s - it appears not to have constructed correctly", mc.getModId());
if (state != LoaderState.CONSTRUCTING)
{
this.errorOccurred(mc, new RuntimeException());
}
}
}
return builder.build();
}
2012-07-22 14:26:38 +00:00
public void errorOccurred(ModContainer modContainer, Throwable exception)
{
2012-07-23 19:03:17 +00:00
errors.put(modContainer.getModId(), exception);
2012-07-22 14:26:38 +00:00
}
public void printModStates(StringBuilder ret)
{
for (String modId : modStates.keySet())
{
ModContainer mod = modList.get(modId);
ret.append("\n\t").append(mod.getName()).append(" (").append(mod.getSource().getName()).append(") ");
Joiner.on("->"). appendTo(ret, modStates.get(modId));
}
}
2012-07-24 01:20:37 +00:00
public List<ModContainer> getActiveModList()
{
return activeModList;
}
public ModState getModState(ModContainer selectedMod)
{
return Iterables.getLast(modStates.get(selectedMod.getModId()), ModState.AVAILABLE);
}
public void distributeStateMessage(Class<?> customEvent)
{
try
{
masterChannel.post(customEvent.newInstance());
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "An unexpected exception");
throw new LoaderException(e);
}
}
public BiMap<ModContainer, Object> getModObjectList()
{
if (modObjectList == null)
{
FMLLog.severe("Detected an attempt by a mod %s to perform game activity during mod construction. This is a serious programming error.", activeContainer);
return buildModObjectList();
}
return ImmutableBiMap.copyOf(modObjectList);
}
public boolean isInState(LoaderState state)
{
return this.state == state;
}
}