ForgePatch/fml/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java

486 lines
14 KiB
Java
Raw Normal View History

2012-03-30 14:11:13 +00:00
/*
* Forge Mod Loader
* Copyright (c) 2012-2013 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* cpw - implementation
2012-03-30 14:11:13 +00:00
*/
package cpw.mods.fml.common;
import java.util.EnumSet;
2012-05-07 05:39:55 +00:00
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
2012-07-24 01:20:37 +00:00
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
2012-07-24 01:20:37 +00:00
2012-07-23 19:03:17 +00:00
import cpw.mods.fml.common.registry.TickRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.server.FMLServerHandler;
2012-07-22 14:26:38 +00:00
2012-05-07 05:39:55 +00:00
/**
* The main class for non-obfuscated hook handling code
*
* Anything that doesn't require obfuscated or client/server specific code should
* go in this handler
*
* It also contains a reference to the sided handler instance that is valid
* allowing for common code to access specific properties from the obfuscated world
* without a direct dependency
*
* @author cpw
*
*/
public class FMLCommonHandler
{
/**
* The singleton
*/
private static final FMLCommonHandler INSTANCE = new FMLCommonHandler();
/**
* The delegate for side specific data and functions
*/
private IFMLSidedHandler sidedDelegate;
private List<IScheduledTickHandler> scheduledClientTicks = Lists.newArrayList();
private List<IScheduledTickHandler> scheduledServerTicks = Lists.newArrayList();
private Class<?> forge;
private boolean noForge;
private List<String> brandings;
private List<String> brandingsNoMC;
private List<ICrashCallable> crashCallables = Lists.newArrayList(Loader.instance().getCallableCrashInformation());
private Set<SaveHandler> handlerSet = Sets.newSetFromMap(new MapMaker().weakKeys().<SaveHandler,Boolean>makeMap());
public void beginLoading(IFMLSidedHandler handler)
{
sidedDelegate = handler;
FMLLog.log("MinecraftForge", Level.INFO, "Attempting early MinecraftForge initialization");
callForgeMethod("initialize");
callForgeMethod("registerCrashCallable");
FMLLog.log("MinecraftForge", Level.INFO, "Completed early MinecraftForge initialization");
}
public void rescheduleTicks(Side side)
{
TickRegistry.updateTickQueue(side.isClient() ? scheduledClientTicks : scheduledServerTicks, side);
}
public void tickStart(EnumSet<TickType> ticks, Side side, Object ... data)
{
List<IScheduledTickHandler> scheduledTicks = side.isClient() ? scheduledClientTicks : scheduledServerTicks;
if (scheduledTicks.size()==0)
{
return;
}
for (IScheduledTickHandler ticker : scheduledTicks)
{
EnumSet<TickType> ticksToRun = EnumSet.copyOf(Objects.firstNonNull(ticker.ticks(), EnumSet.noneOf(TickType.class)));
ticksToRun.retainAll(ticks);
if (!ticksToRun.isEmpty())
{
ticker.tickStart(ticksToRun, data);
}
}
2012-05-07 05:39:55 +00:00
}
public void tickEnd(EnumSet<TickType> ticks, Side side, Object ... data)
2012-05-07 05:39:55 +00:00
{
List<IScheduledTickHandler> scheduledTicks = side.isClient() ? scheduledClientTicks : scheduledServerTicks;
if (scheduledTicks.size()==0)
{
return;
}
for (IScheduledTickHandler ticker : scheduledTicks)
{
EnumSet<TickType> ticksToRun = EnumSet.copyOf(Objects.firstNonNull(ticker.ticks(), EnumSet.noneOf(TickType.class)));
ticksToRun.retainAll(ticks);
if (!ticksToRun.isEmpty())
{
ticker.tickEnd(ticksToRun, data);
}
}
}
/**
* @return the instance
*/
public static FMLCommonHandler instance()
{
return INSTANCE;
2012-03-30 14:11:13 +00:00
}
/**
* Find the container that associates with the supplied mod object
* @param mod
*/
public ModContainer findContainerFor(Object mod)
{
return Loader.instance().getReversedModObjectList().get(mod);
}
/**
* Get the forge mod loader logging instance (goes to the forgemodloader log file)
2012-10-25 20:18:42 +00:00
* @return The log instance for the FML log file
*/
public Logger getFMLLogger()
{
return FMLLog.getLogger();
}
public Side getSide()
2012-05-07 04:54:18 +00:00
{
return sidedDelegate.getSide();
2012-05-07 04:54:18 +00:00
}
/**
* Return the effective side for the context in the game. This is dependent
* on thread analysis to try and determine whether the code is running in the
* server or not. Use at your own risk
*/
public Side getEffectiveSide()
{
Thread thr = Thread.currentThread();
if ((thr.getName().equals("Server thread")))
{
return Side.SERVER;
}
return Side.CLIENT;
}
/**
* Raise an exception
*/
public void raiseException(Throwable exception, String message, boolean stopGame)
2012-05-07 05:39:55 +00:00
{
FMLLog.log(Level.SEVERE, exception, "Something raised an exception. The message was '%s'. 'stopGame' is %b", message, stopGame);
if (stopGame)
{
getSidedDelegate().haltGame(message,exception);
}
2012-05-07 05:39:55 +00:00
}
private Class<?> findMinecraftForge()
{
if (forge==null && !noForge)
{
try {
forge = Class.forName("net.minecraftforge.common.MinecraftForge");
} catch (Exception ex) {
noForge = true;
}
}
return forge;
}
private Object callForgeMethod(String method)
{
if (noForge)
return null;
try
{
return findMinecraftForge().getMethod(method).invoke(null);
}
catch (Exception e)
{
// No Forge installation
return null;
}
}
2012-07-24 01:20:37 +00:00
public void computeBranding()
{
2012-07-24 01:20:37 +00:00
if (brandings == null)
{
Builder<String> brd = ImmutableList.<String>builder();
2012-07-31 02:31:07 +00:00
brd.add(Loader.instance().getMCVersionString());
brd.add(Loader.instance().getMCPVersionString());
brd.add("FML v"+Loader.instance().getFMLVersionString());
2012-08-16 17:01:48 +00:00
String forgeBranding = (String) callForgeMethod("getBrandingVersion");
if (!Strings.isNullOrEmpty(forgeBranding))
{
brd.add(forgeBranding);
}
if (sidedDelegate!=null)
{
brd.addAll(sidedDelegate.getAdditionalBrandingInformation());
}
if (Loader.instance().getFMLBrandingProperties().containsKey("fmlbranding"))
{
brd.add(Loader.instance().getFMLBrandingProperties().get("fmlbranding"));
2012-07-24 01:20:37 +00:00
}
int tModCount = Loader.instance().getModList().size();
int aModCount = Loader.instance().getActiveModList().size();
brd.add(String.format("%d mod%s loaded, %d mod%s active", tModCount, tModCount!=1 ? "s" :"", aModCount, aModCount!=1 ? "s" :"" ));
brandings = brd.build();
brandingsNoMC = brandings.subList(1, brandings.size());
}
2012-07-24 01:20:37 +00:00
}
public List<String> getBrandings(boolean includeMC)
2012-07-24 01:20:37 +00:00
{
if (brandings == null)
{
computeBranding();
}
return includeMC ? ImmutableList.copyOf(brandings) : ImmutableList.copyOf(brandingsNoMC);
}
2012-06-01 02:09:45 +00:00
public IFMLSidedHandler getSidedDelegate()
{
return sidedDelegate;
}
2012-07-06 14:29:17 +00:00
public void onPostServerTick()
{
tickEnd(EnumSet.of(TickType.SERVER), Side.SERVER);
2012-07-06 14:29:17 +00:00
}
/**
* Every tick just after world and other ticks occur
*/
public void onPostWorldTick(Object world)
{
tickEnd(EnumSet.of(TickType.WORLD), Side.SERVER, world);
2012-07-06 14:29:17 +00:00
}
public void onPreServerTick()
{
tickStart(EnumSet.of(TickType.SERVER), Side.SERVER);
2012-07-06 14:29:17 +00:00
}
/**
* Every tick just before world and other ticks occur
*/
public void onPreWorldTick(Object world)
{
tickStart(EnumSet.of(TickType.WORLD), Side.SERVER, world);
2012-07-06 14:29:17 +00:00
}
public void onWorldLoadTick(World[] worlds)
2012-07-06 02:31:46 +00:00
{
rescheduleTicks(Side.SERVER);
for (World w : worlds)
{
tickStart(EnumSet.of(TickType.WORLDLOAD), Side.SERVER, w);
}
2012-07-06 02:31:46 +00:00
}
public boolean handleServerAboutToStart(MinecraftServer server)
{
return Loader.instance().serverAboutToStart(server);
}
public boolean handleServerStarting(MinecraftServer server)
{
return Loader.instance().serverStarting(server);
}
public void handleServerStarted()
{
Loader.instance().serverStarted();
}
public void handleServerStopping()
{
Loader.instance().serverStopping();
}
2012-08-02 19:20:30 +00:00
public MinecraftServer getMinecraftServerInstance()
{
return sidedDelegate.getServer();
2012-08-02 19:20:30 +00:00
}
2012-08-08 04:31:24 +00:00
public void showGuiScreen(Object clientGuiElement)
{
sidedDelegate.showGuiScreen(clientGuiElement);
}
2012-08-09 05:58:14 +00:00
public void onServerStart(MinecraftServer dedicatedServer)
{
FMLServerHandler.instance();
sidedDelegate.beginServerLoading(dedicatedServer);
}
public void onServerStarted()
{
sidedDelegate.finishServerLoading();
}
public void onPreClientTick()
{
tickStart(EnumSet.of(TickType.CLIENT), Side.CLIENT);
}
public void onPostClientTick()
{
tickEnd(EnumSet.of(TickType.CLIENT), Side.CLIENT);
}
public void onRenderTickStart(float timer)
{
tickStart(EnumSet.of(TickType.RENDER), Side.CLIENT, timer);
}
public void onRenderTickEnd(float timer)
{
tickEnd(EnumSet.of(TickType.RENDER), Side.CLIENT, timer);
}
public void onPlayerPreTick(EntityPlayer player)
{
Side side = player instanceof EntityPlayerMP ? Side.SERVER : Side.CLIENT;
tickStart(EnumSet.of(TickType.PLAYER), side, player);
}
public void onPlayerPostTick(EntityPlayer player)
{
Side side = player instanceof EntityPlayerMP ? Side.SERVER : Side.CLIENT;
tickEnd(EnumSet.of(TickType.PLAYER), side, player);
}
public void registerCrashCallable(ICrashCallable callable)
{
crashCallables.add(callable);
}
2012-11-02 03:53:13 +00:00
public void enhanceCrashReport(CrashReport crashReport, CrashReportCategory category)
{
for (ICrashCallable call: crashCallables)
{
2012-11-02 03:53:13 +00:00
category.func_71500_a(call.getLabel(), call);
}
}
2012-09-06 14:03:30 +00:00
public void handleWorldDataSave(SaveHandler handler, WorldInfo worldInfo, NBTTagCompound tagCompound)
{
for (ModContainer mc : Loader.instance().getModList())
{
if (mc instanceof InjectedModContainer)
{
WorldAccessContainer wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
if (wac != null)
{
NBTTagCompound dataForWriting = wac.getDataForWriting(handler, worldInfo);
tagCompound.func_74782_a(mc.getModId(), dataForWriting);
}
}
}
}
public void handleWorldDataLoad(SaveHandler handler, WorldInfo worldInfo, NBTTagCompound tagCompound)
{
if (getEffectiveSide()!=Side.SERVER)
{
return;
}
if (handlerSet.contains(handler))
{
return;
}
handlerSet.add(handler);
Map<String,NBTBase> additionalProperties = Maps.newHashMap();
// worldInfo.setAdditionalProperties(additionalProperties);
for (ModContainer mc : Loader.instance().getModList())
{
if (mc instanceof InjectedModContainer)
{
WorldAccessContainer wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
if (wac != null)
{
wac.readData(handler, worldInfo, additionalProperties, tagCompound.func_74775_l(mc.getModId()));
}
}
}
}
public boolean shouldServerBeKilledQuietly()
{
if (sidedDelegate == null)
{
return false;
}
return sidedDelegate.shouldServerShouldBeKilledQuietly();
}
2012-12-31 04:52:38 +00:00
public void handleServerStopped()
{
sidedDelegate.serverStopped();
MinecraftServer server = getMinecraftServerInstance();
2012-12-31 04:52:38 +00:00
Loader.instance().serverStopped();
// FORCE the internal server to stop: hello optifine workaround!
if (server!=null) ObfuscationReflectionHelper.setPrivateValue(MinecraftServer.class, server, false, "field_71316"+"_v", "u", "serverStopped");
2012-12-31 04:52:38 +00:00
}
public String getModName()
{
List<String> modNames = Lists.newArrayListWithExpectedSize(3);
modNames.add("fml");
if (!noForge)
{
modNames.add("forge");
}
if (Loader.instance().getFMLBrandingProperties().containsKey("snooperbranding"))
{
modNames.add(Loader.instance().getFMLBrandingProperties().get("snooperbranding"));
}
return Joiner.on(',').join(modNames);
}
public void addModToResourcePack(ModContainer container)
{
sidedDelegate.addModAsResource(container);
}
public void updateResourcePackList()
{
sidedDelegate.updateResourcePackList();
}
public String getCurrentLanguage()
{
return sidedDelegate.getCurrentLanguage();
}
public void bootstrap()
{
}
public NetworkManager getClientToServerNetworkManager()
{
return sidedDelegate.getClientToServerNetworkManager();
}
2012-03-30 14:11:13 +00:00
}