New logging stuff, also the early plugin api for forge
This commit is contained in:
parent
50ed44359d
commit
ba28161f16
|
@ -239,7 +239,7 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
// }
|
||||
// Mark this as a "first tick"
|
||||
KeyBindingRegistry.uploadKeyBindingsToGame(client.field_6304_y);
|
||||
|
||||
|
||||
firstTick = true;
|
||||
}
|
||||
|
||||
|
@ -497,7 +497,7 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
{
|
||||
networkManager.func_972_a(packet);
|
||||
}
|
||||
|
||||
|
||||
// TODO
|
||||
// for (ModContainer mod : Loader.getModList()) {
|
||||
// mod.getNetworkHandler().onServerLogin(handler);
|
||||
|
@ -518,7 +518,7 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
return;
|
||||
}
|
||||
// TODO
|
||||
|
||||
|
||||
// ModContainer mod = FMLCommonHandler.instance().getModForChannel(packet.field_44012_a);
|
||||
//
|
||||
// if (mod != null)
|
||||
|
@ -961,7 +961,7 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log.warning("Texture FX %s has failed to animate. Likely caused by a texture pack change that they did not respond correctly to", name);
|
||||
FMLLog.warning("Texture FX %s has failed to animate. Likely caused by a texture pack change that they did not respond correctly to", name);
|
||||
if (ifx != null)
|
||||
{
|
||||
ifx.setErrored(true);
|
||||
|
@ -977,7 +977,7 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
int target = ((dim.width >> 4) * (dim.height >> 4)) << 2;
|
||||
if (effect.field_1127_a.length != target)
|
||||
{
|
||||
FMLLog.log.warning("Detected a texture FX sizing discrepancy in %s (%d, %d)", name, effect.field_1127_a.length, target);
|
||||
FMLLog.warning("Detected a texture FX sizing discrepancy in %s (%d, %d)", name, effect.field_1127_a.length, target);
|
||||
ifx.setErrored(true);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class SpriteHelper
|
|||
private static HashMap<String, BitSet> spriteInfo = new HashMap<String, BitSet>();
|
||||
|
||||
private static void initMCSpriteMaps() {
|
||||
BitSet slots =
|
||||
BitSet slots =
|
||||
SpriteHelper.toBitSet(
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
|
@ -51,7 +51,7 @@ public class SpriteHelper
|
|||
"0000000111111000" +
|
||||
"0000000000000000");
|
||||
spriteInfo.put("/terrain.png", slots);
|
||||
|
||||
|
||||
slots = SpriteHelper.toBitSet(
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
|
@ -74,8 +74,8 @@ public class SpriteHelper
|
|||
/**
|
||||
* Register a sprite map for ModTextureStatic, to allow for other mods to override
|
||||
* your sprite page.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static void registerSpriteMapForFile(String file, String spriteMap) {
|
||||
if (spriteInfo.size() == 0) {
|
||||
|
@ -87,20 +87,20 @@ public class SpriteHelper
|
|||
}
|
||||
spriteInfo.put(file, toBitSet(spriteMap));
|
||||
}
|
||||
|
||||
|
||||
public static int getUniqueSpriteIndex(String path)
|
||||
{
|
||||
if (!spriteInfo.containsKey("/terrain.png"))
|
||||
{
|
||||
initMCSpriteMaps();
|
||||
}
|
||||
|
||||
|
||||
BitSet slots = spriteInfo.get(path);
|
||||
|
||||
|
||||
if (slots == null)
|
||||
{
|
||||
Exception ex = new Exception(String.format("Invalid getUniqueSpriteIndex call for texture: %s", path));
|
||||
FMLLog.log.log(Level.SEVERE, ex, "A critical error has been detected with sprite overrides");
|
||||
FMLLog.log(Level.SEVERE, ex, "A critical error has been detected with sprite overrides");
|
||||
FMLCommonHandler.instance().raiseException(ex,"Invalid request to getUniqueSpriteIndex",true);
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ public class SpriteHelper
|
|||
if (ret == -1)
|
||||
{
|
||||
Exception ex = new Exception(String.format("No more sprite indicies left for: %s", path));
|
||||
FMLLog.log.log(Level.SEVERE, ex, "There are no sprite indicies left for %s", path);
|
||||
FMLLog.log(Level.SEVERE, ex, "There are no sprite indicies left for %s", path);
|
||||
FMLCommonHandler.instance().raiseException(ex,"No more sprite indicies left", true);
|
||||
}
|
||||
return ret;
|
||||
|
|
|
@ -271,7 +271,7 @@ public class FMLCommonHandler
|
|||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
FMLLog.log.log(Level.WARNING, e, "Error building registration list");
|
||||
FMLLog.log(Level.WARNING, e, "Error building registration list");
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ public class FMLCommonHandler
|
|||
*/
|
||||
public Logger getFMLLogger()
|
||||
{
|
||||
return FMLLog.log.getLogger();
|
||||
return FMLLog.getLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,78 +1,22 @@
|
|||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class FMLLog
|
||||
{
|
||||
private static cpw.mods.fml.relauncher.FMLLog coreLog = cpw.mods.fml.relauncher.FMLLog.log;
|
||||
|
||||
/**
|
||||
* Our special logger for logging issues to. We copy various assets from the
|
||||
* Minecraft logger to acheive a similar appearance.
|
||||
*/
|
||||
public static FMLLog log = new FMLLog();
|
||||
|
||||
private static File minecraftHome;
|
||||
private static boolean configured;
|
||||
private Logger myLog;
|
||||
|
||||
private FMLLog()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Configure the FML logger
|
||||
*/
|
||||
private static void configureLogging()
|
||||
{
|
||||
LogManager.getLogManager().reset();
|
||||
Logger globalLogger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||
globalLogger.setLevel(Level.OFF);
|
||||
|
||||
log.myLog = Logger.getLogger("ForgeModLoader");
|
||||
FMLLogFormatter formatter = new FMLLogFormatter();
|
||||
ConsoleHandler ch = new ConsoleHandler();
|
||||
log.myLog.setUseParentHandlers(false);
|
||||
log.myLog.addHandler(ch);
|
||||
ch.setFormatter(formatter);
|
||||
log.myLog.setLevel(Level.ALL);
|
||||
try
|
||||
{
|
||||
File logPath = new File(minecraftHome, "ForgeModLoader-%g.log");
|
||||
FileHandler fileHandler = new FileHandler(logPath.getPath(), 0, 3);
|
||||
fileHandler.setFormatter(new FMLLogFormatter());
|
||||
fileHandler.setLevel(Level.ALL);
|
||||
log.myLog.addHandler(fileHandler);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
// Reset global logging to shut up other logging sources (thanks guava!)
|
||||
configured = true;
|
||||
}
|
||||
|
||||
public static void log(Level level, String format, Object... data)
|
||||
{
|
||||
if (!configured)
|
||||
{
|
||||
configureLogging();
|
||||
}
|
||||
log.myLog.log(level, String.format(format, data));
|
||||
coreLog.log(level, String.format(format, data));
|
||||
}
|
||||
|
||||
public static void log(Level level, Throwable ex, String format, Object... data)
|
||||
{
|
||||
if (!configured)
|
||||
{
|
||||
configureLogging();
|
||||
}
|
||||
log.myLog.log(level, String.format(format, data), ex);
|
||||
coreLog.log(level, String.format(format, data), ex);
|
||||
}
|
||||
|
||||
|
||||
public static void severe(String format, Object... data)
|
||||
{
|
||||
log(Level.SEVERE, format, data);
|
||||
|
@ -102,8 +46,8 @@ public class FMLLog
|
|||
{
|
||||
log(Level.FINEST, format, data);
|
||||
}
|
||||
public Logger getLogger()
|
||||
public static Logger getLogger()
|
||||
{
|
||||
return myLog;
|
||||
return coreLog.getLogger();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,12 +52,12 @@ import cpw.mods.fml.common.toposort.TopologicalSort;
|
|||
|
||||
/**
|
||||
* The loader class performs the actual loading of the mod code from disk.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* There are several {@link LoaderState}s to mod loading, triggered in two
|
||||
* different stages from the FML handler code's hooks into the minecraft code.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <ol>
|
||||
* <li>LOADING. Scanning the filesystem for mod containers to load (zips, jars,
|
||||
* directories), adding them to the {@link #modClassLoader} Scanning, the loaded
|
||||
|
@ -74,12 +74,12 @@ import cpw.mods.fml.common.toposort.TopologicalSort;
|
|||
* but it attempts to continue loading before abandoning and giving a fatal
|
||||
* error.</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* Phase 1 code triggers the LOADING and PREINIT states. Phase 2 code triggers
|
||||
* the INIT and POSTINIT states.
|
||||
*
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class Loader
|
||||
{
|
||||
|
@ -153,7 +153,7 @@ public class Loader
|
|||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
FMLLog.log.log(Level.SEVERE, "Could not get FML version information - corrupted installation detected!", ex);
|
||||
FMLLog.log(Level.SEVERE, "Could not get FML version information - corrupted installation detected!", ex);
|
||||
throw new LoaderException(ex);
|
||||
}
|
||||
}
|
||||
|
@ -164,9 +164,9 @@ public class Loader
|
|||
build = properties.getProperty("fmlbuild.build.number", "missing");
|
||||
mccversion = properties.getProperty("fmlbuild.mcclientversion", "missing");
|
||||
mcsversion = properties.getProperty("fmlbuild.mcserverversion", "missing");
|
||||
|
||||
FMLLog.log.info("Forge Mod Loader version %s.%s.%s.%s for Minecraft client:%s, server:%s loading", major, minor, rev, build, mccversion, mcsversion);
|
||||
|
||||
|
||||
FMLLog.info("Forge Mod Loader version %s.%s.%s.%s for Minecraft client:%s, server:%s loading", major, minor, rev, build, mccversion, mcsversion);
|
||||
|
||||
modClassLoader = new ModClassLoader(getClass().getClassLoader());
|
||||
}
|
||||
|
||||
|
@ -177,47 +177,47 @@ public class Loader
|
|||
*/
|
||||
private void sortModList()
|
||||
{
|
||||
FMLLog.log.fine("Verifying mod requirements are satisfied");
|
||||
FMLLog.fine("Verifying mod requirements are satisfied");
|
||||
try
|
||||
{
|
||||
for (ModContainer mod : mods)
|
||||
{
|
||||
if (!namedMods.keySet().containsAll(mod.getRequirements()))
|
||||
{
|
||||
FMLLog.log.log(Level.SEVERE, "The mod %s (%s) requires mods %s to be available, one or more are not", mod.getModId(), mod.getName(), mod.getRequirements());
|
||||
FMLLog.log(Level.SEVERE, "The mod %s (%s) requires mods %s to be available, one or more are not", mod.getModId(), mod.getName(), mod.getRequirements());
|
||||
throw new LoaderException();
|
||||
}
|
||||
}
|
||||
|
||||
FMLLog.log.fine("All mod requirements are satisfied");
|
||||
|
||||
FMLLog.fine("All mod requirements are satisfied");
|
||||
|
||||
ModSorter sorter = new ModSorter(mods, namedMods);
|
||||
|
||||
try
|
||||
{
|
||||
FMLLog.log.fine("Sorting mods into an ordered list");
|
||||
FMLLog.fine("Sorting mods into an ordered list");
|
||||
mods = sorter.sort();
|
||||
FMLLog.log.fine("Mod sorting completed successfully");
|
||||
FMLLog.fine("Mod sorting completed successfully");
|
||||
}
|
||||
catch (ModSortingException sortException)
|
||||
{
|
||||
FMLLog.log.severe("A dependency cycle was detected in the input mod set so an ordering cannot be determined");
|
||||
FMLLog.log.severe("The visited mod list is %s", sortException.getExceptionData().getVisitedNodes());
|
||||
FMLLog.log.severe("The first mod in the cycle is %s", sortException.getExceptionData().getFirstBadNode());
|
||||
FMLLog.log.log(Level.SEVERE, sortException, "The full error");
|
||||
FMLLog.severe("A dependency cycle was detected in the input mod set so an ordering cannot be determined");
|
||||
FMLLog.severe("The visited mod list is %s", sortException.getExceptionData().getVisitedNodes());
|
||||
FMLLog.severe("The first mod in the cycle is %s", sortException.getExceptionData().getFirstBadNode());
|
||||
FMLLog.log(Level.SEVERE, sortException, "The full error");
|
||||
throw new LoaderException(sortException);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
FMLLog.log.fine("Mod sorting data:");
|
||||
FMLLog.fine("Mod sorting data:");
|
||||
for (ModContainer mod : mods)
|
||||
{
|
||||
FMLLog.log.fine("\t%s(%s): %s (%s)", mod.getModId(), mod.getName(), mod.getSource().getName(), mod.getSortingRules());
|
||||
FMLLog.fine("\t%s(%s): %s (%s)", mod.getModId(), mod.getName(), mod.getSource().getName(), mod.getSortingRules());
|
||||
}
|
||||
if (mods.size()==0)
|
||||
{
|
||||
FMLLog.log.fine("No mods found to sort");
|
||||
{
|
||||
FMLLog.fine("No mods found to sort");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,38 +225,38 @@ public class Loader
|
|||
|
||||
/**
|
||||
* The primary loading code
|
||||
*
|
||||
*
|
||||
* This is visited during first initialization by Minecraft to scan and load
|
||||
* the mods from all sources 1. The minecraft jar itself (for loading of in
|
||||
* jar mods- I would like to remove this if possible but forge depends on it
|
||||
* at present) 2. The mods directory with expanded subdirs, searching for
|
||||
* mods named mod_*.class 3. The mods directory for zip and jar files,
|
||||
* searching for mod classes named mod_*.class again
|
||||
*
|
||||
*
|
||||
* The found resources are first loaded into the {@link #modClassLoader}
|
||||
* (always) then scanned for class resources matching the specification
|
||||
* above.
|
||||
*
|
||||
*
|
||||
* If they provide the {@link Mod} annotation, they will be loaded as
|
||||
* "FML mods", which currently is effectively a NO-OP. If they are
|
||||
* determined to be {@link BaseMod} subclasses they are loaded as such.
|
||||
*
|
||||
*
|
||||
* Finally, if they are successfully loaded as classes, they are then added
|
||||
* to the available mod list.
|
||||
*/
|
||||
private void identifyMods()
|
||||
{
|
||||
ModDiscoverer discoverer = new ModDiscoverer();
|
||||
FMLLog.log.fine("Attempting to load mods contained in the minecraft jar file and associated classes");
|
||||
FMLLog.fine("Attempting to load mods contained in the minecraft jar file and associated classes");
|
||||
discoverer.findClasspathMods(modClassLoader);
|
||||
FMLLog.log.fine("Minecraft jar mods loaded successfully");
|
||||
FMLLog.fine("Minecraft jar mods loaded successfully");
|
||||
|
||||
FMLLog.log.info("Searching %s for mods", canonicalModsDir.getAbsolutePath());
|
||||
FMLLog.info("Searching %s for mods", canonicalModsDir.getAbsolutePath());
|
||||
discoverer.findModDirMods(canonicalModsDir);
|
||||
|
||||
mods = discoverer.identifyMods();
|
||||
namedMods = Maps.uniqueIndex(mods, new ModIdFunction());
|
||||
FMLLog.log.info("Forge Mod Loader has identified %d mod%s to load", mods.size(), mods.size() != 1 ? "s" : "");
|
||||
FMLLog.info("Forge Mod Loader has identified %d mod%s to load", mods.size(), mods.size() != 1 ? "s" : "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -280,7 +280,7 @@ public class Loader
|
|||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
FMLLog.log.log(Level.SEVERE,
|
||||
FMLLog.log(Level.SEVERE,
|
||||
String.format("Failed to resolve loader directories: mods : %s ; config %s", canonicalModsDir.getAbsolutePath(),
|
||||
configDir.getAbsolutePath()), ioe);
|
||||
throw new LoaderException(ioe);
|
||||
|
@ -288,37 +288,37 @@ public class Loader
|
|||
|
||||
if (!canonicalModsDir.exists())
|
||||
{
|
||||
FMLLog.log.info("No mod directory found, creating one: %s", canonicalModsPath);
|
||||
FMLLog.info("No mod directory found, creating one: %s", canonicalModsPath);
|
||||
boolean dirMade = canonicalModsDir.mkdir();
|
||||
if (!dirMade)
|
||||
{
|
||||
FMLLog.log.severe("Unable to create the mod directory %s", canonicalModsPath);
|
||||
FMLLog.severe("Unable to create the mod directory %s", canonicalModsPath);
|
||||
throw new LoaderException();
|
||||
}
|
||||
FMLLog.log.info("Mod directory created successfully");
|
||||
FMLLog.info("Mod directory created successfully");
|
||||
}
|
||||
|
||||
if (!canonicalConfigDir.exists())
|
||||
{
|
||||
FMLLog.log.fine("No config directory found, creating one: %s", canonicalConfigPath);
|
||||
FMLLog.fine("No config directory found, creating one: %s", canonicalConfigPath);
|
||||
boolean dirMade = canonicalConfigDir.mkdir();
|
||||
if (!dirMade)
|
||||
{
|
||||
FMLLog.log.severe("Unable to create the config directory %s", canonicalConfigPath);
|
||||
FMLLog.severe("Unable to create the config directory %s", canonicalConfigPath);
|
||||
throw new LoaderException();
|
||||
}
|
||||
FMLLog.log.info("Config directory created successfully");
|
||||
FMLLog.info("Config directory created successfully");
|
||||
}
|
||||
|
||||
if (!canonicalModsDir.isDirectory())
|
||||
{
|
||||
FMLLog.log.severe("Attempting to load mods from %s, which is not a directory", canonicalModsPath);
|
||||
FMLLog.severe("Attempting to load mods from %s, which is not a directory", canonicalModsPath);
|
||||
throw new LoaderException();
|
||||
}
|
||||
|
||||
if (!configDir.isDirectory())
|
||||
{
|
||||
FMLLog.log.severe("Attempting to load configuration from %s, which is not a directory", canonicalConfigPath);
|
||||
FMLLog.severe("Attempting to load configuration from %s, which is not a directory", canonicalConfigPath);
|
||||
throw new LoaderException();
|
||||
}
|
||||
}
|
||||
|
@ -354,31 +354,31 @@ public class Loader
|
|||
private void disableRequestedMods()
|
||||
{
|
||||
String disabledModList = System.getProperty("fml.disabledMods", "");
|
||||
FMLLog.log.fine("Received a system property request \'%s\'",disabledModList);
|
||||
FMLLog.fine("Received a system property request \'%s\'",disabledModList);
|
||||
Map<String, String> sysPropertyStateList = Splitter.on(CharMatcher.anyOf(";:"))
|
||||
.omitEmptyStrings().trimResults().withKeyValueSeparator("=")
|
||||
.split(disabledModList);
|
||||
FMLLog.log.fine("System property request managing the state of %d mods", sysPropertyStateList.size());
|
||||
FMLLog.fine("System property request managing the state of %d mods", sysPropertyStateList.size());
|
||||
Map<String, String> modStates = Maps.newHashMap();
|
||||
|
||||
|
||||
File disabledModFile = new File(canonicalConfigDir, "fmlModState.properties");
|
||||
Properties disabledModListProperties = new Properties();
|
||||
if (disabledModFile.exists() && disabledModFile.isFile())
|
||||
{
|
||||
FMLLog.log.fine("Found a mod state file %s", disabledModFile.getName());
|
||||
FMLLog.fine("Found a mod state file %s", disabledModFile.getName());
|
||||
try
|
||||
{
|
||||
disabledModListProperties.load(new FileReader(disabledModFile));
|
||||
FMLLog.log.fine("Loaded states for %d mods from file", disabledModListProperties.size());
|
||||
FMLLog.fine("Loaded states for %d mods from file", disabledModListProperties.size());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log.log(Level.INFO, e, "An error occurred reading the fmlModState.properties file");
|
||||
FMLLog.log(Level.INFO, e, "An error occurred reading the fmlModState.properties file");
|
||||
}
|
||||
}
|
||||
modStates.putAll(Maps.fromProperties(disabledModListProperties));
|
||||
modStates.putAll(sysPropertyStateList);
|
||||
FMLLog.log.fine("After merging, found state information for %d mods", modStates.size());
|
||||
FMLLog.fine("After merging, found state information for %d mods", modStates.size());
|
||||
|
||||
Map<String, Boolean> isEnabled = Maps.transformValues(modStates, new Function<String, Boolean>()
|
||||
{
|
||||
|
@ -387,12 +387,12 @@ public class Loader
|
|||
return !Boolean.parseBoolean(input);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for (Map.Entry<String, Boolean> entry : isEnabled.entrySet())
|
||||
{
|
||||
if (namedMods.containsKey(entry.getKey()))
|
||||
{
|
||||
FMLLog.log.info("Setting mod %s to enabled state %b", entry.getKey(), entry.getValue());
|
||||
FMLLog.info("Setting mod %s to enabled state %b", entry.getKey(), entry.getValue());
|
||||
namedMods.get(entry.getKey()).setEnabledState(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ public class Loader
|
|||
|
||||
/**
|
||||
* Query if we know of a mod named modname
|
||||
*
|
||||
*
|
||||
* @param modname
|
||||
* @return
|
||||
*/
|
||||
|
@ -421,7 +421,7 @@ public class Loader
|
|||
{
|
||||
StringBuilder ret = new StringBuilder();
|
||||
List<String> branding = FMLCommonHandler.instance().getBrandings();
|
||||
|
||||
|
||||
Joiner.on(' ').skipNulls().appendTo(ret, branding.subList(1, branding.size()));
|
||||
if (modController!=null)
|
||||
{
|
||||
|
@ -452,9 +452,9 @@ public class Loader
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
boolean parseFailure=false;
|
||||
|
||||
|
||||
for (String dep : DEPENDENCYSPLITTER.split(dependencyString))
|
||||
{
|
||||
List<String> depparts = Lists.newArrayList(DEPENDENCYPARTSPLITTER.split(dep));
|
||||
|
@ -467,7 +467,7 @@ public class Loader
|
|||
String target = depparts.get(1);
|
||||
boolean targetIsAll = target.equals("*");
|
||||
// If we don't have two parts to each substring, this is an invalid dependency string
|
||||
|
||||
|
||||
// If this is a required element, add it to the required list
|
||||
if ("required-before".equals(instruction) || "required-after".equals(instruction))
|
||||
{
|
||||
|
@ -482,7 +482,7 @@ public class Loader
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// before elements are things we are loaded before (so they are our dependants)
|
||||
if ("required-before".equals(instruction) || "before".equals(instruction))
|
||||
{
|
||||
|
@ -498,7 +498,7 @@ public class Loader
|
|||
parseFailure=true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (parseFailure)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, "Unable to parse dependency string %s", dependencyString);
|
||||
|
|
|
@ -37,7 +37,7 @@ import cpw.mods.fml.relauncher.RelaunchClassLoader;
|
|||
*/
|
||||
public class ModClassLoader extends URLClassLoader
|
||||
{
|
||||
private static final List<String> STANDARD_LIBRARIES = ImmutableList.of("jinput.jar", "lwjgl.jar", "lwjgl_util.jar", "argo-2.25.jar", "asm-all-4.0.jar", "guava-12.0.jar");
|
||||
private static final List<String> STANDARD_LIBRARIES = ImmutableList.of("jinput.jar", "lwjgl.jar", "lwjgl_util.jar");
|
||||
private RelaunchClassLoader mainClassLoader;
|
||||
|
||||
public ModClassLoader(ClassLoader parent) {
|
||||
|
@ -70,7 +70,7 @@ public class ModClassLoader extends URLClassLoader
|
|||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
FMLLog.log.log(Level.SEVERE, "Unable to process our input to locate the minecraft code", e);
|
||||
FMLLog.log(Level.SEVERE, "Unable to process our input to locate the minecraft code", e);
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,11 +34,11 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
|||
public List<ModContainer> discover(ModCandidate candidate)
|
||||
{
|
||||
List<ModContainer> found = Lists.newArrayList();
|
||||
FMLLog.log.fine("Examining directory %s for potential mods", candidate.getModContainer().getName());
|
||||
FMLLog.fine("Examining directory %s for potential mods", candidate.getModContainer().getName());
|
||||
exploreFileSystem("", candidate.getModContainer(), found, candidate, null);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
public void exploreFileSystem(String path, File modDir, List<ModContainer> harvestedMods, ModCandidate candidate, MetadataCollection mc)
|
||||
{
|
||||
if (path.length() == 0)
|
||||
|
@ -55,7 +55,7 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
|||
mc = MetadataCollection.from(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File[] content = modDir.listFiles(new ClassFilter());
|
||||
|
||||
// Always sort our content
|
||||
|
@ -64,12 +64,12 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
|||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
FMLLog.log.finest("Recursing into package %s", path + file.getName());
|
||||
FMLLog.finest("Recursing into package %s", path + file.getName());
|
||||
exploreFileSystem(path + file.getName() + ".", file, harvestedMods, candidate, mc);
|
||||
continue;
|
||||
}
|
||||
Matcher match = classFile.matcher(file.getName());
|
||||
|
||||
|
||||
if (match.matches())
|
||||
{
|
||||
ASMModParser modParser = null;
|
||||
|
@ -83,7 +83,7 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
|||
{
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
|
||||
|
||||
modParser.validate();
|
||||
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer());
|
||||
if (container!=null)
|
||||
|
@ -92,8 +92,8 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
|||
container.bindMetadata(mc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ public class JarDiscoverer implements ITypeDiscoverer
|
|||
public List<ModContainer> discover(ModCandidate candidate)
|
||||
{
|
||||
List<ModContainer> foundMods = Lists.newArrayList();
|
||||
FMLLog.log.fine("Examining file %s for potential mods", candidate.getModContainer().getName());
|
||||
FMLLog.fine("Examining file %s for potential mods", candidate.getModContainer().getName());
|
||||
ZipFile jar = null;
|
||||
try
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ public class JarDiscoverer implements ITypeDiscoverer
|
|||
MetadataCollection mc = null;
|
||||
if (modInfo != null)
|
||||
{
|
||||
FMLLog.log.finer("Located mcmod.info file in file %s", candidate.getModContainer().getName());
|
||||
FMLLog.finer("Located mcmod.info file in file %s", candidate.getModContainer().getName());
|
||||
mc = MetadataCollection.from(jar.getInputStream(modInfo));
|
||||
}
|
||||
for (ZipEntry ze : Collections.list(jar.entries()))
|
||||
|
@ -52,7 +52,7 @@ public class JarDiscoverer implements ITypeDiscoverer
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log.warning("Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName());
|
||||
FMLLog.warning("Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -26,12 +26,14 @@ import org.objectweb.asm.FieldVisitor;
|
|||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.LoaderException;
|
||||
import cpw.mods.fml.common.ModClassLoader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.relauncher.RelaunchLibraryManager;
|
||||
|
||||
public class ModDiscoverer
|
||||
{
|
||||
|
@ -41,10 +43,11 @@ public class ModDiscoverer
|
|||
|
||||
public void findClasspathMods(ModClassLoader modClassLoader)
|
||||
{
|
||||
List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries()).addAll(RelaunchLibraryManager.getLibraries()).build();
|
||||
File[] minecraftSources = modClassLoader.getParentSources();
|
||||
if (minecraftSources.length == 1 && minecraftSources[0].isFile())
|
||||
{
|
||||
FMLLog.log.fine("Minecraft is a file at %s, loading", minecraftSources[0].getAbsolutePath());
|
||||
FMLLog.fine("Minecraft is a file at %s, loading", minecraftSources[0].getAbsolutePath());
|
||||
candidates.add(new ModCandidate(minecraftSources[0], minecraftSources[0], ContainerType.JAR));
|
||||
}
|
||||
else
|
||||
|
@ -53,19 +56,19 @@ public class ModDiscoverer
|
|||
{
|
||||
if (minecraftSources[i].isFile())
|
||||
{
|
||||
if (modClassLoader.getDefaultLibraries().contains(minecraftSources[i].getName()))
|
||||
if (knownLibraries.contains(minecraftSources[i].getName()))
|
||||
{
|
||||
FMLLog.log.fine("Skipping known library file %s", minecraftSources[i].getAbsolutePath());
|
||||
}
|
||||
FMLLog.fine("Skipping known library file %s", minecraftSources[i].getAbsolutePath());
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.log.fine("Found a minecraft related file at %s, examining for mod candidates", minecraftSources[i].getAbsolutePath());
|
||||
FMLLog.fine("Found a minecraft related file at %s, examining for mod candidates", minecraftSources[i].getAbsolutePath());
|
||||
candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.JAR, true));
|
||||
}
|
||||
}
|
||||
else if (minecraftSources[i].isDirectory())
|
||||
{
|
||||
FMLLog.log.fine("Found a minecraft related directory at %s, examining for mod candidates", minecraftSources[i].getAbsolutePath());
|
||||
FMLLog.fine("Found a minecraft related directory at %s, examining for mod candidates", minecraftSources[i].getAbsolutePath());
|
||||
candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.DIR, true));
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +86,7 @@ public class ModDiscoverer
|
|||
{
|
||||
if (modFile.isDirectory())
|
||||
{
|
||||
FMLLog.log.fine("Found a candidate mod directory %s", modFile.getName());
|
||||
FMLLog.fine("Found a candidate mod directory %s", modFile.getName());
|
||||
candidates.add(new ModCandidate(modFile, modFile, ContainerType.DIR));
|
||||
}
|
||||
else
|
||||
|
@ -92,12 +95,12 @@ public class ModDiscoverer
|
|||
|
||||
if (matcher.matches())
|
||||
{
|
||||
FMLLog.log.fine("Found a candidate zip or jar file %s", matcher.group(0));
|
||||
FMLLog.fine("Found a candidate zip or jar file %s", matcher.group(0));
|
||||
candidates.add(new ModCandidate(modFile, modFile, ContainerType.JAR));
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.log.fine("Ignoring unknown file %s in mods directory", modFile.getName());
|
||||
FMLLog.fine("Ignoring unknown file %s in mods directory", modFile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +109,7 @@ public class ModDiscoverer
|
|||
public List<ModContainer> identifyMods()
|
||||
{
|
||||
List<ModContainer> modList = Lists.newArrayList();
|
||||
|
||||
|
||||
for (ModCandidate candidate : candidates)
|
||||
{
|
||||
try
|
||||
|
@ -123,7 +126,7 @@ public class ModDiscoverer
|
|||
Throwables.propagate(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return modList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ public class ModLoaderModContainer implements ModContainer
|
|||
this.gameTickHandler = new BaseModTicker(instance, false);
|
||||
this.guiTickHandler = new BaseModTicker(instance, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -122,14 +122,14 @@ public class ModLoaderModContainer implements ModContainer
|
|||
{
|
||||
try
|
||||
{
|
||||
FMLLog.log.fine("Reading existing configuration file for %s : %s", modClazzName, modConfig.getName());
|
||||
FMLLog.fine("Reading existing configuration file for %s : %s", modClazzName, modConfig.getName());
|
||||
FileReader configReader = new FileReader(modConfig);
|
||||
props.load(configReader);
|
||||
configReader.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log.log(Level.SEVERE, e, "Error occured reading mod configuration file %s", modConfig.getName());
|
||||
FMLLog.log(Level.SEVERE, e, "Error occured reading mod configuration file %s", modConfig.getName());
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
existingConfigFound = true;
|
||||
|
@ -161,17 +161,17 @@ public class ModLoaderModContainer implements ModContainer
|
|||
defaultValue = f.get(null);
|
||||
propertyValue = props.getProperty(propertyName, extractValue(defaultValue));
|
||||
Object currentValue = parseValue(propertyValue, property, f.getType(), propertyName, modClazzName);
|
||||
FMLLog.log.finest("Configuration for %s.%s found values default: %s, configured: %s, interpreted: %s", modClazzName, propertyName, defaultValue, propertyValue, currentValue);
|
||||
FMLLog.finest("Configuration for %s.%s found values default: %s, configured: %s, interpreted: %s", modClazzName, propertyName, defaultValue, propertyValue, currentValue);
|
||||
|
||||
if (currentValue != null && !currentValue.equals(defaultValue))
|
||||
{
|
||||
FMLLog.log.finest("Configuration for %s.%s value set to: %s", modClazzName, propertyName, currentValue);
|
||||
FMLLog.finest("Configuration for %s.%s value set to: %s", modClazzName, propertyName, currentValue);
|
||||
f.set(null, currentValue);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log.log(Level.SEVERE, e, "Invalid configuration found for %s in %s", propertyName, modConfig.getName());
|
||||
FMLLog.log(Level.SEVERE, e, "Invalid configuration found for %s in %s", propertyName, modConfig.getName());
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
finally
|
||||
|
@ -208,22 +208,22 @@ public class ModLoaderModContainer implements ModContainer
|
|||
{
|
||||
if (!mlPropFound && !existingConfigFound)
|
||||
{
|
||||
FMLLog.log.fine("No MLProp configuration for %s found or required. No file written", modClazzName);
|
||||
FMLLog.fine("No MLProp configuration for %s found or required. No file written", modClazzName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mlPropFound && existingConfigFound)
|
||||
{
|
||||
File mlPropBackup = new File(modConfig.getParent(),modConfig.getName()+".bak");
|
||||
FMLLog.log.fine("MLProp configuration file for %s found but not required. Attempting to rename file to %s", modClazzName, mlPropBackup.getName());
|
||||
FMLLog.fine("MLProp configuration file for %s found but not required. Attempting to rename file to %s", modClazzName, mlPropBackup.getName());
|
||||
boolean renamed = modConfig.renameTo(mlPropBackup);
|
||||
if (renamed)
|
||||
{
|
||||
FMLLog.log.fine("Unused MLProp configuration file for %s renamed successfully to %s", modClazzName, mlPropBackup.getName());
|
||||
FMLLog.fine("Unused MLProp configuration file for %s renamed successfully to %s", modClazzName, mlPropBackup.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.log.fine("Unused MLProp configuration file for %s renamed UNSUCCESSFULLY to %s", modClazzName, mlPropBackup.getName());
|
||||
FMLLog.fine("Unused MLProp configuration file for %s renamed UNSUCCESSFULLY to %s", modClazzName, mlPropBackup.getName());
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -233,11 +233,11 @@ public class ModLoaderModContainer implements ModContainer
|
|||
FileWriter configWriter = new FileWriter(modConfig);
|
||||
props.store(configWriter, comments.toString());
|
||||
configWriter.close();
|
||||
FMLLog.log.fine("Configuration for %s written to %s", modClazzName, modConfig.getName());
|
||||
FMLLog.fine("Configuration for %s written to %s", modClazzName, modConfig.getName());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
FMLLog.log.log(Level.SEVERE, e, "Error trying to write the config file %s", modConfig.getName());
|
||||
FMLLog.log(Level.SEVERE, e, "Error trying to write the config file %s", modConfig.getName());
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ public class ModLoaderModContainer implements ModContainer
|
|||
|
||||
if (n.doubleValue() < property.min() || n.doubleValue() > property.max())
|
||||
{
|
||||
FMLLog.log.warning("Configuration for %s.%s found value %s outside acceptable range %s,%s", modConfigName,propertyName, n, property.min(), property.max());
|
||||
FMLLog.warning("Configuration for %s.%s found value %s outside acceptable range %s,%s", modConfigName,propertyName, n, property.min(), property.max());
|
||||
return null;
|
||||
}
|
||||
else
|
||||
|
@ -332,7 +332,7 @@ public class ModLoaderModContainer implements ModContainer
|
|||
{
|
||||
return sortingProperties;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(Object mod)
|
||||
{
|
||||
|
@ -477,11 +477,11 @@ public class ModLoaderModContainer implements ModContainer
|
|||
}
|
||||
|
||||
// Lifecycle mod events
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void constructMod(FMLConstructionEvent event)
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
ModClassLoader modClassLoader = event.getModClassLoader();
|
||||
modClassLoader.addFile(modSource);
|
||||
|
@ -516,8 +516,8 @@ public class ModLoaderModContainer implements ModContainer
|
|||
Throwables.propagateIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void init(FMLInitializationEvent event)
|
||||
{
|
||||
|
@ -531,7 +531,7 @@ public class ModLoaderModContainer implements ModContainer
|
|||
Throwables.propagateIfPossible(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void postInit(FMLPostInitializationEvent event)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package cpw.mods.fml.relauncher;
|
||||
|
||||
public class CoreFMLLibraries implements ILibrarySet
|
||||
{
|
||||
private static String[] libraries = { "argo-2.25.jar","guava-12.0.1.jar","asm-all-4.0.jar" };
|
||||
private static String[] checksums = { "bb672829fde76cb163004752b86b0484bd0a7f4b", "b8e78b9af7bf45900e14c6f958486b6ca682195f", "98308890597acb64047f7e896638e0d98753ae82" };
|
||||
|
||||
@Override
|
||||
public String[] getLibraries()
|
||||
{
|
||||
return libraries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getHashes()
|
||||
{
|
||||
return checksums;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRootURL()
|
||||
{
|
||||
return "http://cloud.github.com/downloads/cpw/FML/%s";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package cpw.mods.fml.relauncher;
|
||||
|
||||
public class FMLCorePlugin implements IFMLLoadingPlugin
|
||||
{
|
||||
@Override
|
||||
public String[] getLibraryRequestClass()
|
||||
{
|
||||
return new String[] {"cpw.mods.fml.relauncher.CoreFMLLibraries"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass()
|
||||
{
|
||||
return new String[] {"cpw.mods.fml.common.asm.ASMTransformer"};
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ public class FMLEmbeddingRelauncher
|
|||
if (INSTANCE == null)
|
||||
{
|
||||
INSTANCE = new FMLEmbeddingRelauncher();
|
||||
System.out.println("FML relaunch active");
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
@ -47,8 +46,6 @@ public class FMLEmbeddingRelauncher
|
|||
// Now we re-inject the home into the "new" minecraft under our control
|
||||
Class<? super Object> client = ReflectionHelper.getClass(clientLoader, "net.minecraft.client.Minecraft");
|
||||
ReflectionHelper.setPrivateValue(client, null, minecraftHome, "field_6275_Z", "ap", "minecraftDir");
|
||||
Class<? super Object> log = ReflectionHelper.getClass(clientLoader, "cpw.mods.fml.common.FMLLog");
|
||||
ReflectionHelper.setPrivateValue(log, null, minecraftHome, "minecraftHome");
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -75,6 +72,8 @@ public class FMLEmbeddingRelauncher
|
|||
// Hmmm
|
||||
}
|
||||
File minecraftHome = ReflectionHelper.getPrivateValue(mcMaster, null, "field_6275_Z", "ap", "minecraftDir");
|
||||
FMLLog.minecraftHome = minecraftHome;
|
||||
FMLLog.info("FML relaunch active");
|
||||
|
||||
RelaunchLibraryManager.handleLaunch(minecraftHome, clientLoader);
|
||||
return minecraftHome;
|
||||
|
@ -119,7 +118,7 @@ public class FMLEmbeddingRelauncher
|
|||
}
|
||||
else
|
||||
{
|
||||
System.out.printf("Found unknown applet parent %s, unable to inject!\n", launcherClass);
|
||||
FMLLog.severe("Found unknown applet parent %s, unable to inject!\n", launcherClass);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
package cpw.mods.fml.relauncher;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import cpw.mods.fml.relauncher.FMLLogFormatter;
|
||||
|
||||
public class FMLLog
|
||||
{
|
||||
|
||||
private static class LoggingOutStream extends ByteArrayOutputStream
|
||||
{
|
||||
private Logger log;
|
||||
private StringBuilder currentMessage;
|
||||
|
||||
public LoggingOutStream(Logger log)
|
||||
{
|
||||
this.log = log;
|
||||
this.currentMessage = new StringBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
String record;
|
||||
synchronized(this)
|
||||
{
|
||||
super.flush();
|
||||
record = this.toString();
|
||||
super.reset();
|
||||
|
||||
currentMessage.append(record);
|
||||
if (currentMessage.lastIndexOf(FMLLogFormatter.LINE_SEPARATOR)>=0)
|
||||
{
|
||||
// Are we longer than just the line separator?
|
||||
if (currentMessage.length()>FMLLogFormatter.LINE_SEPARATOR.length())
|
||||
{
|
||||
// Trim the line separator
|
||||
currentMessage.setLength(currentMessage.length()-FMLLogFormatter.LINE_SEPARATOR.length());
|
||||
log.log(Level.INFO, currentMessage.toString());
|
||||
}
|
||||
currentMessage.setLength(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Our special logger for logging issues to. We copy various assets from the
|
||||
* Minecraft logger to acheive a similar appearance.
|
||||
*/
|
||||
public static FMLLog log = new FMLLog();
|
||||
|
||||
static File minecraftHome;
|
||||
private static boolean configured;
|
||||
private Logger myLog;
|
||||
|
||||
private FMLLog()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Configure the FML logger
|
||||
*/
|
||||
private static void configureLogging()
|
||||
{
|
||||
LogManager.getLogManager().reset();
|
||||
Logger globalLogger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||
globalLogger.setLevel(Level.OFF);
|
||||
|
||||
log.myLog = Logger.getLogger("ForgeModLoader");
|
||||
|
||||
Logger stdOut = Logger.getLogger("STDOUT");
|
||||
stdOut.setParent(log.myLog);
|
||||
Logger stdErr = Logger.getLogger("STDERR");
|
||||
stdErr.setParent(log.myLog);
|
||||
FMLLogFormatter formatter = new FMLLogFormatter();
|
||||
|
||||
// Console handler captures the normal stderr before it gets replaced
|
||||
ConsoleHandler ch = new ConsoleHandler();
|
||||
ch.setLevel(Level.parse(System.getProperty("fml.log.level","INFO")));
|
||||
log.myLog.setUseParentHandlers(false);
|
||||
log.myLog.addHandler(ch);
|
||||
ch.setFormatter(formatter);
|
||||
log.myLog.setLevel(Level.ALL);
|
||||
try
|
||||
{
|
||||
File logPath = new File(minecraftHome, "ForgeModLoader-%g.log");
|
||||
FileHandler fileHandler = new FileHandler(logPath.getPath(), 0, 3);
|
||||
fileHandler.setFormatter(formatter);
|
||||
fileHandler.setLevel(Level.ALL);
|
||||
log.myLog.addHandler(fileHandler);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
// Set system out to a log stream
|
||||
System.setOut(new PrintStream(new LoggingOutStream(stdOut), true));
|
||||
System.setErr(new PrintStream(new LoggingOutStream(stdErr), true));
|
||||
|
||||
// Reset global logging to shut up other logging sources (thanks guava!)
|
||||
configured = true;
|
||||
}
|
||||
|
||||
public static void log(Level level, String format, Object... data)
|
||||
{
|
||||
if (!configured)
|
||||
{
|
||||
configureLogging();
|
||||
}
|
||||
log.myLog.log(level, String.format(format, data));
|
||||
}
|
||||
|
||||
public static void log(Level level, Throwable ex, String format, Object... data)
|
||||
{
|
||||
if (!configured)
|
||||
{
|
||||
configureLogging();
|
||||
}
|
||||
log.myLog.log(level, String.format(format, data), ex);
|
||||
}
|
||||
|
||||
public static void severe(String format, Object... data)
|
||||
{
|
||||
log(Level.SEVERE, format, data);
|
||||
}
|
||||
|
||||
public static void warning(String format, Object... data)
|
||||
{
|
||||
log(Level.WARNING, format, data);
|
||||
}
|
||||
|
||||
public static void info(String format, Object... data)
|
||||
{
|
||||
log(Level.INFO, format, data);
|
||||
}
|
||||
|
||||
public static void fine(String format, Object... data)
|
||||
{
|
||||
log(Level.FINE, format, data);
|
||||
}
|
||||
|
||||
public static void finer(String format, Object... data)
|
||||
{
|
||||
log(Level.FINER, format, data);
|
||||
}
|
||||
|
||||
public static void finest(String format, Object... data)
|
||||
{
|
||||
log(Level.FINEST, format, data);
|
||||
}
|
||||
public Logger getLogger()
|
||||
{
|
||||
return myLog;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package cpw.mods.fml.common;
|
||||
package cpw.mods.fml.relauncher;
|
||||
|
||||
/**
|
||||
* Copied from ConsoleLogFormatter for shared use on the client
|
||||
*
|
||||
*
|
||||
*/
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
@ -13,6 +13,7 @@ import java.util.logging.LogRecord;
|
|||
|
||||
final class FMLLogFormatter extends Formatter
|
||||
{
|
||||
static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public String format(LogRecord record)
|
||||
|
@ -50,8 +51,16 @@ final class FMLLogFormatter extends Formatter
|
|||
msg.append(" [" + lvl.getLocalizedName() + "] ");
|
||||
}
|
||||
|
||||
if (record.getLoggerName() != null)
|
||||
{
|
||||
msg.append("["+record.getLoggerName()+"] ");
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.append("[] ");
|
||||
}
|
||||
msg.append(record.getMessage());
|
||||
msg.append(System.getProperty("line.separator"));
|
||||
msg.append(LINE_SEPARATOR);
|
||||
Throwable thr = record.getThrown();
|
||||
|
||||
if (thr != null)
|
|
@ -0,0 +1,23 @@
|
|||
package cpw.mods.fml.relauncher;
|
||||
|
||||
/**
|
||||
* The base plugin that provides class name meta information to FML to
|
||||
* enhance the classloading lifecycle for mods in FML
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface IFMLLoadingPlugin
|
||||
{
|
||||
/**
|
||||
* Return a list of classes that implement the ILibrarySet interface
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String[] getLibraryRequestClass();
|
||||
/**
|
||||
* Return a list of classes that implements the IClassTransformer interface
|
||||
* @return
|
||||
*/
|
||||
String[] getASMTransformerClass();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package cpw.mods.fml.relauncher;
|
||||
|
||||
/**
|
||||
* Interface for certain core plugins to register libraries to
|
||||
* be loaded in by the FML class loader at launch time
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface ILibrarySet
|
||||
{
|
||||
/**
|
||||
* Return a list of libraries available from a common location
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String[] getLibraries();
|
||||
/**
|
||||
* Return the string encoded sha1 hash for each library in the returned list
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String[] getHashes();
|
||||
/**
|
||||
* Return the root URL format string from which this library set can be obtained
|
||||
* There needs to be a single %s string substitution which is the library name
|
||||
* @return
|
||||
*/
|
||||
String getRootURL();
|
||||
}
|
|
@ -19,17 +19,165 @@ import java.nio.channels.ReadableByteChannel;
|
|||
import java.nio.channels.FileChannel.MapMode;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import cpw.mods.fml.common.discovery.ModCandidate;
|
||||
|
||||
public class RelaunchLibraryManager
|
||||
{
|
||||
private static String[] libraries = { "argo-2.25.jar","guava-12.0.jar","asm-all-4.0.jar" };
|
||||
private static String[] checksums = { "bb672829fde76cb163004752b86b0484bd0a7f4b", "5bc66dd95b79db1e437eb08adba124a3e4088dc0", "98308890597acb64047f7e896638e0d98753ae82" };
|
||||
private static String[] plugins = { "cpw.mods.fml.relauncher.FMLCorePlugin" , "net.minecraftforge.classloading.FMLForgePlugin" };
|
||||
private static final String HEXES = "0123456789abcdef";
|
||||
private static List<String> loadedLibraries = new ArrayList<String>();
|
||||
public static void handleLaunch(File mcDir, RelaunchClassLoader actualClassLoader)
|
||||
{
|
||||
List<IFMLLoadingPlugin> loadPlugins = new ArrayList<IFMLLoadingPlugin>();
|
||||
List<ILibrarySet> libraries = new ArrayList<ILibrarySet>();
|
||||
for (String s : plugins)
|
||||
{
|
||||
try
|
||||
{
|
||||
IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) Class.forName(s, true, actualClassLoader).newInstance();
|
||||
loadPlugins.add(plugin);
|
||||
for (String libName : plugin.getLibraryRequestClass())
|
||||
{
|
||||
libraries.add((ILibrarySet) Class.forName(libName, true, actualClassLoader).newInstance());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// HMMM
|
||||
}
|
||||
}
|
||||
|
||||
if (loadPlugins.isEmpty())
|
||||
{
|
||||
throw new RuntimeException("A fatal error has occured - no valid fml load plugin was found - this is a completely corrupt FML installation.");
|
||||
}
|
||||
|
||||
List<Throwable> caughtErrors = new ArrayList<Throwable>();
|
||||
try
|
||||
{
|
||||
File libDir;
|
||||
try
|
||||
{
|
||||
libDir = setupLibDir(mcDir);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
caughtErrors.add(e);
|
||||
return;
|
||||
}
|
||||
|
||||
for (ILibrarySet lib : libraries)
|
||||
{
|
||||
for (int i=0; i<lib.getLibraries().length; i++)
|
||||
{
|
||||
boolean download = false;
|
||||
String libName = lib.getLibraries()[i];
|
||||
String checksum = lib.getHashes()[i];
|
||||
File libFile = new File(libDir, libName);
|
||||
if (!libFile.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
downloadFile(libFile, lib.getRootURL());
|
||||
download = true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
caughtErrors.add(e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (libFile.exists() && !libFile.isFile())
|
||||
{
|
||||
caughtErrors.add(new RuntimeException(String.format("Found a file %s that is not a normal file - you should clear this out of the way", libName)));
|
||||
continue;
|
||||
}
|
||||
|
||||
String fileChecksum = generateChecksum(libFile);
|
||||
if (!checksum.equals(fileChecksum))
|
||||
{
|
||||
caughtErrors.add(new RuntimeException(String.format("The file %s has an invalid checksum %s (expecting %s) - delete it and try again.", libName, fileChecksum, checksum)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!download)
|
||||
{
|
||||
System.out.printf("Found library file %s present and correct in lib dir\n", libName);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.printf("Library file %s was downloaded and verified successfully", libName);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
actualClassLoader.addURL(libFile.toURI().toURL());
|
||||
loadedLibraries.add(libName);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
caughtErrors.add(new RuntimeException(String.format("Should never happen - %s is broken - probably a somehow corrupted download. Delete it and try again.", libFile.getName()), e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!caughtErrors.isEmpty())
|
||||
{
|
||||
FMLLog.severe("There were errors during initial FML setup. " +
|
||||
"Some files failed to download or were otherwise corrupted. " +
|
||||
"You will need to manually obtain the following files from " +
|
||||
"these download links and ensure your lib directory is clean. ");
|
||||
for (ILibrarySet set : libraries)
|
||||
{
|
||||
for (String file : set.getLibraries())
|
||||
{
|
||||
FMLLog.severe("*** Download "+set.getRootURL(), file);
|
||||
}
|
||||
}
|
||||
FMLLog.severe("<===========>");
|
||||
FMLLog.severe("The following is the errors that caused the setup to fail. " +
|
||||
"They may help you diagnose and resolve the issue");
|
||||
for (Throwable t : caughtErrors)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, t, "Fatal error");
|
||||
}
|
||||
throw new RuntimeException("A fatal error occured and FML cannot continue");
|
||||
}
|
||||
}
|
||||
|
||||
for (IFMLLoadingPlugin plug : loadPlugins)
|
||||
{
|
||||
for (String xformClass : plug.getASMTransformerClass())
|
||||
{
|
||||
actualClassLoader.registerTransformer(xformClass);
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
Class<?> loaderClazz = Class.forName("cpw.mods.fml.common.Loader", true, actualClassLoader);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Load in the Loader, make sure he's ready to roll - this will initialize most of the rest of minecraft here
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mcDir
|
||||
* @return
|
||||
*/
|
||||
private static File setupLibDir(File mcDir)
|
||||
{
|
||||
File libDir = new File(mcDir,"lib");
|
||||
try
|
||||
|
@ -48,51 +196,7 @@ public class RelaunchLibraryManager
|
|||
{
|
||||
throw new RuntimeException(String.format("Found a lib file in %s that's not a directory", mcDir.getName()));
|
||||
}
|
||||
|
||||
for (int i=0; i<libraries.length; i++)
|
||||
{
|
||||
String libName = libraries[i];
|
||||
String checksum = checksums[i];
|
||||
File libFile = new File(libDir, libName);
|
||||
if (!libFile.exists())
|
||||
{
|
||||
downloadFile(libFile);
|
||||
}
|
||||
|
||||
if (libFile.exists() && !libFile.isFile())
|
||||
{
|
||||
throw new RuntimeException(String.format("Found a file %s that is not a normal file", libName));
|
||||
}
|
||||
|
||||
String fileChecksum = generateChecksum(libFile);
|
||||
if (!checksum.equals(fileChecksum))
|
||||
{
|
||||
throw new RuntimeException(String.format("The file %s has an invalid checksum %s (expecting %s)", libName, fileChecksum, checksum));
|
||||
}
|
||||
try
|
||||
{
|
||||
actualClassLoader.addURL(libFile.toURI().toURL());
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
// Register our class loading transformer now we have everything we need
|
||||
actualClassLoader.registerTransformer("cpw.mods.fml.common.asm.ASMTransformer");
|
||||
// Register the forge class loading transformer now we have everything we need
|
||||
actualClassLoader.registerTransformer("net.minecraftforge.asm.ASMTransformer");
|
||||
|
||||
try
|
||||
{
|
||||
Class<?> loaderClazz = Class.forName("cpw.mods.fml.common.Loader", true, actualClassLoader);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Load in the Loader, make sure he's ready to roll
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return libDir;
|
||||
}
|
||||
|
||||
private static String generateChecksum(File file)
|
||||
|
@ -119,20 +223,12 @@ public class RelaunchLibraryManager
|
|||
return null;
|
||||
}
|
||||
}
|
||||
private static void downloadFile(File libFile)
|
||||
private static void downloadFile(File libFile, String rootUrl)
|
||||
{
|
||||
// try
|
||||
// {
|
||||
// JOptionPane.showMessageDialog(null, String.format("Downloading required FML library %s from github.com",libName));
|
||||
// }
|
||||
// catch (HeadlessException he)
|
||||
// {
|
||||
// // Ignore
|
||||
// }
|
||||
try
|
||||
{
|
||||
URL libDownload = new URL(String.format("http://cloud.github.com/downloads/cpw/FML/%s",libFile.getName()));
|
||||
System.out.printf("Downloading %s..", libDownload.toString());
|
||||
URL libDownload = new URL(String.format(rootUrl,libFile.getName()));
|
||||
FMLLog.info("Downloading %s", libDownload.toString());
|
||||
InputStream urlConn = libDownload.openStream();
|
||||
ReadableByteChannel urlChannel = Channels.newChannel(urlConn);
|
||||
FileOutputStream libFileStream = new FileOutputStream(libFile);
|
||||
|
@ -142,11 +238,19 @@ public class RelaunchLibraryManager
|
|||
libFileStream.close();
|
||||
urlChannel.close();
|
||||
urlConn.close();
|
||||
System.out.println("download successful");
|
||||
FMLLog.info("Download complete");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
FMLLog.severe("There was a problem downloading the file %s automatically. Perhaps you" +
|
||||
"have an environment without internet access. You will need to download " +
|
||||
"the file manually\n", libFile.getName());
|
||||
throw new RuntimeException("A download error occured", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getLibraries()
|
||||
{
|
||||
return loadedLibraries;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue