diff --git a/conf/build.gradle.forge b/conf/build.gradle.forge index 46df073..940c0d9 100644 --- a/conf/build.gradle.forge +++ b/conf/build.gradle.forge @@ -26,7 +26,7 @@ dependencies { - compile 'net.minecraft:launchwrapper:1.11' + compile 'net.minecraft:launchwrapper:1.12' compile 'com.google.code.findbugs:jsr305:1.3.9' compile 'org.ow2.asm:asm-debug-all:5.0.3' compile 'com.typesafe.akka:akka-actor_2.11:2.3.3' diff --git a/src/main/java/cpw/mods/fml/client/FMLClientHandler.java b/src/main/java/cpw/mods/fml/client/FMLClientHandler.java index 0cddcff..80411e9 100644 --- a/src/main/java/cpw/mods/fml/client/FMLClientHandler.java +++ b/src/main/java/cpw/mods/fml/client/FMLClientHandler.java @@ -58,6 +58,7 @@ import net.minecraft.network.ServerStatusResponse; import net.minecraft.server.MinecraftServer; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StringUtils; import net.minecraft.world.WorldSettings; import net.minecraft.world.storage.SaveFormatOld; @@ -68,6 +69,7 @@ import org.lwjgl.input.Mouse; import org.lwjgl.opengl.Display; +import com.google.common.base.CharMatcher; import com.google.common.base.Strings; import com.google.common.base.Throwables; import com.google.common.collect.BiMap; @@ -1003,9 +1005,19 @@ public void processWindowMessages() { // workaround for windows requiring messages being processed on the main thread - if(LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_WINDOWS) - { - Display.processMessages(); - } + if (LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_WINDOWS) return; + // If we can't grab the mutex, the update call is blocked, probably in native code, just skip it and carry on + // We'll get another go next time + if (!SplashProgress.mutex.tryAcquire()) return; + Display.processMessages(); + SplashProgress.mutex.release(); + } + // From FontRenderer.renderCharAtPos + private static final String ALLOWED_CHARS = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000"; + @Override + public String stripSpecialChars(String message) + { + // We can't handle many unicode points in the splash renderer + return CharMatcher.anyOf(ALLOWED_CHARS).retainFrom(StringUtils.stripControlCodes(message)); } } \ No newline at end of file diff --git a/src/main/java/cpw/mods/fml/client/SplashProgress.java b/src/main/java/cpw/mods/fml/client/SplashProgress.java index ef510b2..f058a3b 100644 --- a/src/main/java/cpw/mods/fml/client/SplashProgress.java +++ b/src/main/java/cpw/mods/fml/client/SplashProgress.java @@ -9,10 +9,13 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.io.PrintStream; +import java.io.PrintWriter; import java.lang.Thread.UncaughtExceptionHandler; import java.nio.IntBuffer; import java.util.Iterator; import java.util.Properties; +import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -40,6 +43,7 @@ import org.lwjgl.opengl.SharedDrawable; import org.lwjgl.util.glu.GLU; +import cpw.mods.fml.common.EnhancedRuntimeException; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.ICrashCallable; @@ -81,6 +85,7 @@ private static int barBorderColor; private static int barColor; private static int barBackgroundColor; + static final Semaphore mutex = new Semaphore(1); private static String getString(String name, String def) { @@ -174,7 +179,12 @@ return "GL info"; } }); - CrashReport report = CrashReport.makeCrashReport(new Throwable(), "Loading screen debug info"); + CrashReport report = CrashReport.makeCrashReport(new Throwable() + { + @Override public String getMessage(){ return "This is just a prompt for computer specs to be printed. THIS IS NOT A ERROR"; } + @Override public void printStackTrace(final PrintWriter s){ s.println(getMessage()); } + @Override public void printStackTrace(final PrintStream s) { s.println(getMessage()); } + }, "Loading screen debug info"); System.out.println(report.getCompleteReport()); try @@ -270,8 +280,8 @@ // forge logo setColor(backgroundColor); - float fw = (float)forgeTexture.getWidth() / 2; - float fh = (float)forgeTexture.getHeight() / 2; + float fw = (float)forgeTexture.getWidth() / 2 / 2; + float fh = (float)forgeTexture.getHeight() / 2 / 2; if(rotate) { float sh = Math.max(fw, fh); @@ -297,7 +307,16 @@ glEnd(); glDisable(GL_TEXTURE_2D); + // We use mutex to indicate safely to the main thread that we're taking the display global lock + // So the main thread can skip processing messages while we're updating. + // There are system setups where this call can pause for a while, because the GL implementation + // is trying to impose a framerate or other thing is occurring. Without the mutex, the main + // thread would delay waiting for the same global display lock + mutex.acquireUninterruptibly(); Display.update(); + // As soon as we're done, we release the mutex. The other thread can now ping the processmessages + // call as often as it wants until we get get back here again + mutex.release(); if(pause) { clearGL(); @@ -344,7 +363,7 @@ drawBox(barWidth - 2, barHeight - 2); // slidy part setColor(barColor); - drawBox((barWidth - 2) * b.getStep() / b.getSteps(), barHeight - 2); + drawBox((barWidth - 2) * (b.getStep() + 1) / (b.getSteps() + 1), barHeight - 2); // Step can sometimes be 0. // progress text String progress = "" + b.getStep() + "/" + b.getSteps(); glTranslatef(((float)barWidth - 2) / 2 - fontRenderer.getStringWidth(progress), 2, 0); @@ -469,9 +488,9 @@ public static void finish() { if(!enabled) return; - checkThreadState(); try { + checkThreadState(); done = true; thread.join(); d.releaseContext(); @@ -483,10 +502,66 @@ catch (Exception e) { e.printStackTrace(); - throw new RuntimeException(e); + if (disableSplash()) + { + throw new EnhancedRuntimeException(e) + { + @Override + protected void printStackTrace(WrappedPrintStream stream) + { + stream.println("SplashProgress has detected a error loading Minecraft."); + stream.println("This can sometimes be caused by bad video drivers."); + stream.println("We have automatically disabeled the new Splash Screen in config/splash.properties."); + stream.println("Try reloading minecraft before reporting any errors."); + } + }; + } + else + { + throw new EnhancedRuntimeException(e) + { + @Override + protected void printStackTrace(WrappedPrintStream stream) + { + stream.println("SplashProgress has detected a error loading Minecraft."); + stream.println("This can sometimes be caused by bad video drivers."); + stream.println("Please try disabeling the new Splash Screen in config/splash.properties."); + stream.println("After doing so, try reloading minecraft before reporting any errors."); + } + }; + } } } + private static boolean disableSplash() + { + File configFile = new File(Minecraft.getMinecraft().mcDataDir, "config/splash.properties"); + File parent = configFile.getParentFile(); + if (!parent.exists()) + parent.mkdirs(); + + FileReader r = null; + enabled = false; + config.setProperty("enabled", "false"); + + FileWriter w = null; + try + { + w = new FileWriter(configFile); + config.store(w, "Splash screen properties"); + } + catch(IOException e) + { + FMLLog.log(Level.ERROR, e, "Could not save the splash.properties file"); + return false; + } + finally + { + IOUtils.closeQuietly(w); + } + return true; + } + private static IResourcePack createResourcePack(File file) { if(file.isDirectory()) diff --git a/src/main/java/cpw/mods/fml/common/EnhancedRuntimeException.java b/src/main/java/cpw/mods/fml/common/EnhancedRuntimeException.java index 13b3157..e5d90ff 100644 --- a/src/main/java/cpw/mods/fml/common/EnhancedRuntimeException.java +++ b/src/main/java/cpw/mods/fml/common/EnhancedRuntimeException.java @@ -44,7 +44,7 @@ this.printStackTrace(new WrappedPrintStream() { @Override - void println(String line) + public void println(String line) { buf.append(line).append('\n'); } @@ -60,7 +60,7 @@ printStackTrace(new WrappedPrintStream() { @Override - void println(String line) + public void println(String line) { s.println(line); } @@ -72,7 +72,7 @@ printStackTrace(new WrappedPrintStream() { @Override - void println(String line) + public void println(String line) { s.println(line); } @@ -84,6 +84,6 @@ public static abstract class WrappedPrintStream { - abstract void println(String line); + public abstract void println(String line); } } \ No newline at end of file diff --git a/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java b/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java index 90e8ff7..05f0a1f 100644 --- a/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java +++ b/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java @@ -643,4 +643,9 @@ Runtime.getRuntime().exit(exitCode); } } + + public String stripSpecialChars(String message) + { + return sidedDelegate != null ? sidedDelegate.stripSpecialChars(message) : message; + } } diff --git a/src/main/java/cpw/mods/fml/common/IFMLSidedHandler.java b/src/main/java/cpw/mods/fml/common/IFMLSidedHandler.java index 0672762..7461554 100644 --- a/src/main/java/cpw/mods/fml/common/IFMLSidedHandler.java +++ b/src/main/java/cpw/mods/fml/common/IFMLSidedHandler.java @@ -63,4 +63,6 @@ void allowLogins(); void processWindowMessages(); + + String stripSpecialChars(String message); } \ No newline at end of file diff --git a/src/main/java/cpw/mods/fml/common/LoadController.java b/src/main/java/cpw/mods/fml/common/LoadController.java index 9a4d43a..c27e5d6 100644 --- a/src/main/java/cpw/mods/fml/common/LoadController.java +++ b/src/main/java/cpw/mods/fml/common/LoadController.java @@ -183,7 +183,7 @@ { modObjectList = buildModObjectList(); } - ProgressBar bar = ProgressManager.push(stateEvent.description(), activeModList.size()); + ProgressBar bar = ProgressManager.push(stateEvent.description(), activeModList.size(), true); for (ModContainer mc : activeModList) { bar.step(mc.getName()); @@ -266,10 +266,17 @@ public void printModStates(StringBuilder ret) { + ret.append("\n\tStates:"); + for (ModState state : ModState.values()) + ret.append(" '").append(state.getMarker()).append("' = ").append(state.toString()); + for (ModContainer mc : loader.getModList()) { - ret.append("\n\t").append(mc.getModId()).append("{").append(mc.getVersion()).append("} [").append(mc.getName()).append("] (").append(mc.getSource().getName()).append(") "); - Joiner.on("->"). appendTo(ret, modStates.get(mc.getModId())); + ret.append("\n\t"); + for (ModState state : modStates.get(mc.getModId())) + ret.append(state.getMarker()); + + ret.append("\t").append(mc.getModId()).append("{").append(mc.getVersion()).append("} [").append(mc.getName()).append("] (").append(mc.getSource().getName()).append(") "); } } diff --git a/src/main/java/cpw/mods/fml/common/Loader.java b/src/main/java/cpw/mods/fml/common/Loader.java index 9641322..d98edb1 100644 --- a/src/main/java/cpw/mods/fml/common/Loader.java +++ b/src/main/java/cpw/mods/fml/common/Loader.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedHashMap; @@ -75,6 +76,7 @@ import cpw.mods.fml.common.functions.ModIdFunction; import cpw.mods.fml.common.registry.GameData; import cpw.mods.fml.common.registry.GameRegistry.Type; +import cpw.mods.fml.common.registry.ItemStackHolderInjector; import cpw.mods.fml.common.registry.ObjectHolderRegistry; import cpw.mods.fml.common.toposort.ModSorter; import cpw.mods.fml.common.toposort.ModSortingException; @@ -509,10 +511,30 @@ } modController.transition(LoaderState.CONSTRUCTING, false); modController.distributeStateMessage(LoaderState.CONSTRUCTING, modClassLoader, discoverer.getASMTable(), reverseDependencies); + + List mods = Lists.newArrayList(); + mods.addAll(getActiveModList()); + Collections.sort(mods, new Comparator() + { + @Override + public int compare(ModContainer o1, ModContainer o2) + { + return o1.getModId().compareTo(o2.getModId()); + } + }); + FMLLog.fine("Mod signature data"); + FMLLog.fine(" \tValid Signatures:"); for (ModContainer mod : getActiveModList()) { - FMLLog.fine("\t%s(%s:%s): %s (%s)", mod.getModId(), mod.getName(), mod.getVersion(), mod.getSource().getName(), CertificateHelper.getFingerprint(mod.getSigningCertificate())); + if (mod.getSigningCertificate() != null) + FMLLog.fine("\t\t(%s) %s\t(%s\t%s)\t%s", CertificateHelper.getFingerprint(mod.getSigningCertificate()), mod.getModId(), mod.getName(), mod.getVersion(), mod.getSource().getName()); + } + FMLLog.fine(" \tMissing Signatures:"); + for (ModContainer mod : getActiveModList()) + { + if (mod.getSigningCertificate() == null) + FMLLog.fine("\t\t%s\t(%s\t%s)\t%s", mod.getModId(), mod.getName(), mod.getVersion(), mod.getSource().getName()); } if (getActiveModList().isEmpty()) { @@ -530,8 +552,10 @@ return; } ObjectHolderRegistry.INSTANCE.findObjectHolders(discoverer.getASMTable()); + ItemStackHolderInjector.INSTANCE.findHolders(discoverer.getASMTable()); modController.distributeStateMessage(LoaderState.PREINITIALIZATION, discoverer.getASMTable(), canonicalConfigDir); ObjectHolderRegistry.INSTANCE.applyObjectHolders(); + ItemStackHolderInjector.INSTANCE.inject(); modController.transition(LoaderState.INITIALIZATION, false); progressBar.step("Initializing Minecraft Engine"); } @@ -620,7 +644,7 @@ public String getFMLVersionString() { - return String.format("%s.%s.%s.%s", major, minor, rev, build); + return "7.10.99.99"; } public ClassLoader getModClassLoader() @@ -714,6 +738,7 @@ progressBar.step("Initializing mods Phase 3"); modController.transition(LoaderState.POSTINITIALIZATION, false); modController.distributeStateMessage(FMLInterModComms.IMCEvent.class); + ItemStackHolderInjector.INSTANCE.inject(); modController.distributeStateMessage(LoaderState.POSTINITIALIZATION); progressBar.step("Finishing up"); modController.transition(LoaderState.AVAILABLE, false); diff --git a/src/main/java/cpw/mods/fml/common/LoaderState.java b/src/main/java/cpw/mods/fml/common/LoaderState.java index ca4b44f..7eb4cb9 100644 --- a/src/main/java/cpw/mods/fml/common/LoaderState.java +++ b/src/main/java/cpw/mods/fml/common/LoaderState.java @@ -95,21 +95,23 @@ } public enum ModState { - UNLOADED("Unloaded"), - LOADED("Loaded"), - CONSTRUCTED("Constructed"), - PREINITIALIZED("Pre-initialized"), - INITIALIZED("Initialized"), - POSTINITIALIZED("Post-initialized"), - AVAILABLE("Available"), - DISABLED("Disabled"), - ERRORED("Errored"); + UNLOADED ("Unloaded", "U"), + LOADED ("Loaded", "L"), + CONSTRUCTED ("Constructed", "C"), + PREINITIALIZED ("Pre-initialized", "H"), + INITIALIZED ("Initialized", "I"), + POSTINITIALIZED("Post-initialized", "J"), + AVAILABLE ("Available", "A"), + DISABLED ("Disabled", "D"), + ERRORED ("Errored", "E"); private String label; + private String marker; - private ModState(String label) + private ModState(String label, String marker) { this.label = label; + this.marker = marker; } @Override @@ -117,5 +119,10 @@ { return this.label; } + + public String getMarker() + { + return this.marker; + } } } \ No newline at end of file diff --git a/src/main/java/cpw/mods/fml/common/MinecraftDummyContainer.java b/src/main/java/cpw/mods/fml/common/MinecraftDummyContainer.java index fba4f55..c05642c 100644 --- a/src/main/java/cpw/mods/fml/common/MinecraftDummyContainer.java +++ b/src/main/java/cpw/mods/fml/common/MinecraftDummyContainer.java @@ -12,8 +12,12 @@ package cpw.mods.fml.common; +import java.security.cert.Certificate; + import cpw.mods.fml.common.versioning.VersionParser; import cpw.mods.fml.common.versioning.VersionRange; +import cpw.mods.fml.relauncher.FMLLaunchHandler; +import cpw.mods.fml.relauncher.Side; public class MinecraftDummyContainer extends DummyModContainer { @@ -33,4 +37,20 @@ { return staticRange; } + + @Override + public Certificate getSigningCertificate() + { + if (FMLLaunchHandler.side() != Side.CLIENT) + return null; + + try + { + Class cbr = Class.forName("net.minecraft.client.ClientBrandRetriever", false, getClass().getClassLoader()); + Certificate[] certificates = cbr.getProtectionDomain().getCodeSource().getCertificates(); + return certificates != null ? certificates[0] : null; + } + catch (Exception e){} // Errors don't matter just return null. + return null; + } } \ No newline at end of file diff --git a/src/main/java/cpw/mods/fml/common/ProgressManager.java b/src/main/java/cpw/mods/fml/common/ProgressManager.java index 38ffead..1ba6857 100644 --- a/src/main/java/cpw/mods/fml/common/ProgressManager.java +++ b/src/main/java/cpw/mods/fml/common/ProgressManager.java @@ -20,8 +20,20 @@ @Deprecated public static ProgressBar push(String title, int steps) { + return push(title, steps, false); + } + /** + * @deprecated not a stable API, will break, don't use this yet + */ + @Deprecated + public static ProgressBar push(String title, int steps, boolean timeEachStep) + { ProgressBar bar = new ProgressBar(title, steps); bars.add(bar); + if (timeEachStep) + { + bar.timeEachStep(); + } FMLCommonHandler.instance().processWindowMessages(); return bar; } @@ -34,6 +46,16 @@ { if(bar.getSteps() != bar.getStep()) throw new IllegalStateException("can't pop unfinished ProgressBar " + bar.getTitle()); bars.remove(bar); + if (bar.getSteps() != 0) + { + long newTime = System.nanoTime(); + if (bar.timeEachStep) + FMLLog.fine("Bar Step: %s - %s took %.3fs", bar.getTitle(), bar.getMessage(), ((float)(newTime - bar.lastTime) / 1000000 / 1000)); + if (bar.getSteps() == 1) + FMLLog.fine("Bar Finished: %s - %s took %.3fs", bar.getTitle(), bar.getMessage(), ((float)(newTime - bar.startTime) / 1000000 / 1000)); + else + FMLLog.fine("Bar Finished: %s took %.3fs", bar.getTitle(), ((float)(newTime - bar.startTime) / 1000000 / 1000)); + } FMLCommonHandler.instance().processWindowMessages(); } @@ -55,6 +77,9 @@ private final int steps; private volatile int step = 0; private volatile String message = ""; + private boolean timeEachStep = false; + private long startTime = System.nanoTime(); + private long lastTime = startTime; private ProgressBar(String title, int steps) { @@ -70,8 +95,14 @@ public void step(String message) { if(step >= steps) throw new IllegalStateException("too much steps for ProgressBar " + title); + if (timeEachStep && step != 0) + { + long newTime = System.nanoTime(); + FMLLog.fine("Bar Step: %s - %s took %.3fs", getTitle(), getMessage(), ((float)(newTime - lastTime) / 1000000 / 1000)); + lastTime = newTime; + } step++; - this.message = message; + this.message = FMLCommonHandler.instance().stripSpecialChars(message); FMLCommonHandler.instance().processWindowMessages(); } @@ -94,5 +125,10 @@ { return message; } + + public void timeEachStep() + { + this.timeEachStep = true; + } } } \ No newline at end of file diff --git a/src/main/java/cpw/mods/fml/common/asm/transformers/AccessTransformer.java b/src/main/java/cpw/mods/fml/common/asm/transformers/AccessTransformer.java index deaa7e0..04b7475 100644 --- a/src/main/java/cpw/mods/fml/common/asm/transformers/AccessTransformer.java +++ b/src/main/java/cpw/mods/fml/common/asm/transformers/AccessTransformer.java @@ -118,7 +118,7 @@ rulesResource = Resources.getResource(rulesFile); } processATFile(Resources.asCharSource(rulesResource, Charsets.UTF_8)); - FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer config file %s\n", modifiers.size(), rulesFile); + FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer config file %s", modifiers.size(), rulesFile); } protected void processATFile(CharSource rulesResource) throws IOException { diff --git a/src/main/java/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java b/src/main/java/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java index 5ae8986..bd5f5c7 100644 --- a/src/main/java/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java +++ b/src/main/java/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java @@ -65,7 +65,7 @@ { if (buildEvents(classNode)) { - ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); + ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); classNode.accept(cw); return cw.toByteArray(); } diff --git a/src/main/java/cpw/mods/fml/common/asm/transformers/ModAPITransformer.java b/src/main/java/cpw/mods/fml/common/asm/transformers/ModAPITransformer.java index 0e5abdb..85c1e35 100644 --- a/src/main/java/cpw/mods/fml/common/asm/transformers/ModAPITransformer.java +++ b/src/main/java/cpw/mods/fml/common/asm/transformers/ModAPITransformer.java @@ -25,7 +25,7 @@ public class ModAPITransformer implements IClassTransformer { - private static final boolean logDebugInfo = Boolean.valueOf(System.getProperty("fml.debugAPITransformer", "true")); + private static final boolean logDebugInfo = Boolean.valueOf(System.getProperty("fml.debugAPITransformer", "false")); private ListMultimap optionals; @Override diff --git a/src/main/java/cpw/mods/fml/common/patcher/ClassPatchManager.java b/src/main/java/cpw/mods/fml/common/patcher/ClassPatchManager.java index a2e1082..373d6ce 100644 --- a/src/main/java/cpw/mods/fml/common/patcher/ClassPatchManager.java +++ b/src/main/java/cpw/mods/fml/common/patcher/ClassPatchManager.java @@ -38,6 +38,7 @@ public static final ClassPatchManager INSTANCE = new ClassPatchManager(); public static final boolean dumpPatched = Boolean.parseBoolean(System.getProperty("fml.dumpPatchedClasses", "false")); + public static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("fml.debugClassPatchManager", "false")); private GDiffPatcher patcher = new GDiffPatcher(); private ListMultimap patches; @@ -75,7 +76,8 @@ return inputData; } boolean ignoredError = false; - FMLRelaunchLog.fine("Runtime patching class %s (input size %d), found %d patch%s", mappedName, (inputData == null ? 0 : inputData.length), list.size(), list.size()!=1 ? "es" : ""); + if (DEBUG) + FMLRelaunchLog.fine("Runtime patching class %s (input size %d), found %d patch%s", mappedName, (inputData == null ? 0 : inputData.length), list.size(), list.size()!=1 ? "es" : ""); for (ClassPatch patch: list) { if (!patch.targetClassName.equals(mappedName) && !patch.sourceClassName.equals(name)) @@ -122,7 +124,7 @@ } } } - if (!ignoredError) + if (!ignoredError && DEBUG) { FMLRelaunchLog.fine("Successfully applied runtime patches for %s (new size %d)", mappedName, inputData.length); } @@ -194,13 +196,15 @@ } } while (true); FMLRelaunchLog.fine("Read %d binary patches", patches.size()); - FMLRelaunchLog.fine("Patch list :\n\t%s", Joiner.on("\t\n").join(patches.asMap().entrySet())); + if (DEBUG) + FMLRelaunchLog.fine("Patch list :\n\t%s", Joiner.on("\t\n").join(patches.asMap().entrySet())); patchedClasses.clear(); } private ClassPatch readPatch(JarEntry patchEntry, JarInputStream jis) { - FMLRelaunchLog.finer("Reading patch data from %s", patchEntry.getName()); + if (DEBUG) + FMLRelaunchLog.finer("Reading patch data from %s", patchEntry.getName()); ByteArrayDataInput input; try { diff --git a/src/main/java/cpw/mods/fml/common/registry/FMLControlledNamespacedRegistry.java b/src/main/java/cpw/mods/fml/common/registry/FMLControlledNamespacedRegistry.java index 335de20..d3b32d5 100644 --- a/src/main/java/cpw/mods/fml/common/registry/FMLControlledNamespacedRegistry.java +++ b/src/main/java/cpw/mods/fml/common/registry/FMLControlledNamespacedRegistry.java @@ -23,6 +23,7 @@ import cpw.mods.fml.common.functions.GenericIterableFactory; public class FMLControlledNamespacedRegistry extends RegistryNamespaced { + public static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("fml.debugRegistryEntries", "false")); private final Class superType; private String optionalDefaultName; private I optionalDefaultObject; @@ -396,14 +397,16 @@ } addObjectRaw(idToUse, name, thing); - FMLLog.finer("Registry add: %s %d %s (req. id %d)", name, idToUse, thing, id); + if (DEBUG) + FMLLog.finer("Registry add: %s %d %s (req. id %d)", name, idToUse, thing, id); return idToUse; } void addAlias(String from, String to) { aliases.put(from, to); - FMLLog.finer("Registry alias: %s -> %s", from, to); + if (DEBUG) + FMLLog.finer("Registry alias: %s -> %s", from, to); } Map getEntriesNotIn(FMLControlledNamespacedRegistry registry) @@ -426,6 +429,9 @@ void dump() { + if (!DEBUG) + return; + List ids = new ArrayList(); for (I thing : this.typeSafeIterable()) @@ -439,7 +445,7 @@ for (int id : ids) { I thing = getRaw(id); - FMLLog.finer("Registry: %s %d %s", getNameForObject(thing), id, thing); + FMLLog.finer("Registry: %d %s %s", id, getNameForObject(thing), thing); } } diff --git a/src/main/java/cpw/mods/fml/common/registry/GameData.java b/src/main/java/cpw/mods/fml/common/registry/GameData.java index 2016884..c7a3c93 100644 --- a/src/main/java/cpw/mods/fml/common/registry/GameData.java +++ b/src/main/java/cpw/mods/fml/common/registry/GameData.java @@ -834,7 +834,8 @@ } else // ItemBlock after its Block { - FMLLog.fine("Found matching Block %s for ItemBlock %s at id %d, original id requested: %d", block, item, id, idHint); + if (FMLControlledNamespacedRegistry.DEBUG) + FMLLog.fine("Found matching Block %s for ItemBlock %s at id %d, original id requested: %d", block, item, id, idHint); freeSlot(id, item); // temporarily free the slot occupied by the Block for the item registration } diff --git a/src/main/java/cpw/mods/fml/common/registry/GameRegistry.java b/src/main/java/cpw/mods/fml/common/registry/GameRegistry.java index d68144e..466cd82 100644 --- a/src/main/java/cpw/mods/fml/common/registry/GameRegistry.java +++ b/src/main/java/cpw/mods/fml/common/registry/GameRegistry.java @@ -32,6 +32,10 @@ import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.item.crafting.IRecipe; +import net.minecraft.nbt.JsonToNBT; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTException; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; @@ -40,6 +44,8 @@ import org.ultramine.server.chunk.WrappedModGenerator; import com.google.common.base.Objects; +import com.google.common.base.Strings; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -478,4 +484,70 @@ */ String value(); } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface ItemStackHolder + { + /** + * The registry name of the item being looked up. + * @return The registry name + */ + public String value(); + + /** + * The metadata or damage value for the itemstack, defaults to 0. + * @return the metadata value + */ + public int meta() default 0; + + /** + * The string serialized nbt value for the itemstack. Defaults to empty for no nbt. + * + * @return a nbt string + */ + public String nbt() default ""; + } + + /** + * Makes an {@link ItemStack} based on the itemName reference, with supplied meta, stackSize and nbt, if possible + * + * Will return null if the item doesn't exist (because it's not from a loaded mod for example) + * Will throw a {@link RuntimeException} if the nbtString is invalid for use in an {@link ItemStack} + * + * @param itemName a registry name reference + * @param meta the meta + * @param stackSize the stack size + * @param nbtString an nbt stack as a string, will be processed by {@link JsonToNBT} + * @return a new itemstack + */ + public static ItemStack makeItemStack(String itemName, int meta, int stackSize, String nbtString) + { + if (itemName == null) throw new IllegalArgumentException("The itemName cannot be null"); + Item item = GameData.getItemRegistry().getObject(itemName); + if (item == null) { + FMLLog.getLogger().log(Level.TRACE, "Unable to find item with name {}", itemName); + return null; + } + ItemStack is = new ItemStack(item,1,meta); + if (!Strings.isNullOrEmpty(nbtString)) { + NBTBase nbttag = null; + try + { + nbttag = JsonToNBT.func_150315_a(nbtString); + } catch (NBTException e) + { + FMLLog.getLogger().log(Level.WARN, "Encountered an exception parsing ItemStack NBT string {}", nbtString, e); + throw Throwables.propagate(e); + } + if (!(nbttag instanceof NBTTagCompound)) { + FMLLog.getLogger().log(Level.WARN, "Unexpected NBT string - multiple values {}", nbtString); + throw new RuntimeException("Invalid NBT JSON"); + } else { + is.setTagCompound((NBTTagCompound) nbttag); + } + } + return is; + } + } diff --git a/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderInjector.java b/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderInjector.java new file mode 100644 index 0000000..76d0e0d --- /dev/null +++ b/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderInjector.java @@ -0,0 +1,80 @@ +package cpw.mods.fml.common.registry; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.logging.log4j.Level; + +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.discovery.ASMDataTable; +import cpw.mods.fml.common.discovery.ASMDataTable.ASMData; + +public enum ItemStackHolderInjector +{ + INSTANCE; + + private List itemStackHolders = Lists.newArrayList(); + + public void inject() { + FMLLog.getLogger().log(Level.INFO, "Injecting itemstacks"); + for (ItemStackHolderRef ishr: itemStackHolders) { + ishr.apply(); + } + FMLLog.getLogger().log(Level.INFO, "Itemstack injection complete"); + } + + public void findHolders(ASMDataTable table) { + FMLLog.info("Identifying ItemStackHolder annotations"); + Set allItemStackHolders = table.getAll(GameRegistry.ItemStackHolder.class.getName()); + Map> classCache = Maps.newHashMap(); + for (ASMData data : allItemStackHolders) + { + String className = data.getClassName(); + String annotationTarget = data.getObjectName(); + String value = (String) data.getAnnotationInfo().get("value"); + int meta = data.getAnnotationInfo().containsKey("meta") ? (Integer) data.getAnnotationInfo().get("meta") : 0; + String nbt = data.getAnnotationInfo().containsKey("nbt") ? (String) data.getAnnotationInfo().get("nbt") : ""; + addHolder(classCache, className, annotationTarget, value, meta, nbt); + } + FMLLog.info("Found %d ItemStackHolder annotations", allItemStackHolders.size()); + + } + + private void addHolder(Map> classCache, String className, String annotationTarget, String value, Integer meta, String nbt) + { + Class clazz; + if (classCache.containsKey(className)) + { + clazz = classCache.get(className); + } + else + { + try + { + clazz = Class.forName(className, true, getClass().getClassLoader()); + classCache.put(className, clazz); + } + catch (Exception ex) + { + // unpossible? + throw Throwables.propagate(ex); + } + } + try + { + Field f = clazz.getField(annotationTarget); + itemStackHolders.add(new ItemStackHolderRef(f, value, meta, nbt)); + } + catch (Exception ex) + { + // unpossible? + throw Throwables.propagate(ex); + } + } +} \ No newline at end of file diff --git a/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderRef.java b/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderRef.java new file mode 100644 index 0000000..4d0014c --- /dev/null +++ b/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderRef.java @@ -0,0 +1,84 @@ +package cpw.mods.fml.common.registry; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import net.minecraft.item.ItemStack; + +import org.apache.logging.log4j.Level; + +import com.google.common.base.Throwables; + +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.registry.GameRegistry.ItemStackHolder; + + +/** + * Internal class used in tracking {@link ItemStackHolder} references + * + * @author cpw + * + */ +class ItemStackHolderRef { + private Field field; + private String itemName; + private int meta; + private String serializednbt; + + + ItemStackHolderRef(Field field, String itemName, int meta, String serializednbt) + { + this.field = field; + this.itemName = itemName; + this.meta = meta; + this.serializednbt = serializednbt; + makeWritable(field); + } + + private static Field modifiersField; + private static Object reflectionFactory; + private static Method newFieldAccessor; + private static Method fieldAccessorSet; + private static void makeWritable(Field f) + { + try + { + if (modifiersField == null) + { + Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); + reflectionFactory = getReflectionFactory.invoke(null); + newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); + fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); + modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + } + modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); + } catch (Exception e) + { + throw Throwables.propagate(e); + } + } + + public void apply() + { + ItemStack is; + try + { + is = GameRegistry.makeItemStack(itemName, meta, 1, serializednbt); + } catch (RuntimeException e) + { + FMLLog.getLogger().log(Level.ERROR, "Caught exception processing itemstack {},{},{} in annotation at {}.{}", itemName, meta, serializednbt,field.getClass().getName(),field.getName()); + throw e; + } + try + { + Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); + fieldAccessorSet.invoke(fieldAccessor, null, is); + } + catch (Exception e) + { + FMLLog.getLogger().log(Level.WARN, "Unable to set {} with value {},{},{}", this.field, this.itemName, this.meta, this.serializednbt); + } + } +} \ No newline at end of file diff --git a/src/main/java/cpw/mods/fml/common/registry/LanguageRegistry.java b/src/main/java/cpw/mods/fml/common/registry/LanguageRegistry.java index 50ee2c3..dc5f782 100644 --- a/src/main/java/cpw/mods/fml/common/registry/LanguageRegistry.java +++ b/src/main/java/cpw/mods/fml/common/registry/LanguageRegistry.java @@ -20,6 +20,7 @@ import java.net.URL; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; @@ -35,6 +36,8 @@ import net.minecraft.util.StringTranslate; import com.google.common.base.Charsets; +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.FMLLog; @@ -273,13 +276,15 @@ private void searchZipForLanguages(File source, Side side) throws IOException { ZipFile zf = new ZipFile(source); + List added = Lists.newArrayList(); for (ZipEntry ze : Collections.list(zf.entries())) { Matcher matcher = assetENUSLang.matcher(ze.getName()); if (matcher.matches()) { String lang = matcher.group(2); - FMLLog.fine("Injecting found translation data for lang %s in zip file %s at %s into language system", lang, source.getName(), ze.getName()); + //FMLLog.fine("Injecting found translation data for lang %s in zip file %s at %s into language system", lang, source.getName(), ze.getName()); + added.add(lang); LanguageRegistry.instance().injectLanguage(lang, StringTranslate.parseLangFile(zf.getInputStream(ze))); // Ensure en_US is available to StringTranslate on the server if ("en_US".equals(lang) && side == Side.SERVER) @@ -288,6 +293,8 @@ } } } + if (added.size() > 0) + FMLLog.fine("Found translations in %s [%s]", source.getName(), Joiner.on(", ").join(added)); zf.close(); } diff --git a/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java b/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java index 90f61bf..deb055e 100644 --- a/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java +++ b/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java @@ -13,24 +13,30 @@ package cpw.mods.fml.relauncher; import java.io.File; +import java.io.FileFilter; import java.io.FilenameFilter; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.JarFile; + import net.minecraft.launchwrapper.ITweaker; import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; + import org.apache.logging.log4j.Level; + import com.google.common.base.Strings; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; @@ -38,6 +44,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.ObjectArrays; import com.google.common.primitives.Ints; + import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.asm.transformers.ModAccessTransformer; import cpw.mods.fml.common.launcher.FMLInjectionAndSortingTweaker; @@ -243,6 +250,42 @@ FMLRelaunchLog.severe("Problem file : %s", f.getName()); } } + FileFilter derpdirfilter = new FileFilter() { + @Override + public boolean accept(File pathname) + { + return pathname.isDirectory() && new File(pathname,"META-INF").isDirectory(); + } + + }; + File[] derpdirlist = coreMods.listFiles(derpdirfilter); + if (derpdirlist != null && derpdirlist.length > 0) + { + FMLRelaunchLog.log.getLogger().log(Level.FATAL, "There appear to be jars extracted into the mods directory. This is VERY BAD and will almost NEVER WORK WELL"); + FMLRelaunchLog.log.getLogger().log(Level.FATAL, "You should place original jars only in the mods directory. NEVER extract them to the mods directory."); + FMLRelaunchLog.log.getLogger().log(Level.FATAL, "The directories below appear to be extracted jar files. Fix this before you continue."); + + for (File f : derpdirlist) + { + FMLRelaunchLog.log.getLogger().log(Level.FATAL, "Directory {} contains {}", f.getName(), Arrays.asList(new File(f,"META-INF").list())); + } + + RuntimeException re = new RuntimeException("Extracted mod jars found, loading will NOT continue"); + // We're generating a crash report for the launcher to show to the user here + try + { + Class crashreportclass = classLoader.loadClass("b"); + Object crashreport = crashreportclass.getMethod("a", Throwable.class, String.class).invoke(null, re, "FML has discovered extracted jar files in the mods directory.\nThis breaks mod loading functionality completely.\nRemove the directories and replace with the jar files originally provided."); + File crashreportfile = new File(new File(coreMods.getParentFile(),"crash-reports"),String.format("fml-crash-%1$tY-%1$tm-%1$td_%1$tT.txt",Calendar.getInstance())); + crashreportclass.getMethod("a",File.class).invoke(crashreport, crashreportfile); + System.out.println("#@!@# FML has crashed the game deliberately. Crash report saved to: #@!@# " + crashreportfile.getAbsolutePath()); + } catch (Exception e) + { + e.printStackTrace(); + // NOOP - hopefully + } + throw re; + } File[] coreModList = coreMods.listFiles(ff); File versionedModDir = new File(coreMods, FMLInjectionData.mccversion); if (versionedModDir.isDirectory()) diff --git a/src/main/java/cpw/mods/fml/server/FMLServerHandler.java b/src/main/java/cpw/mods/fml/server/FMLServerHandler.java index 114ce4a..c563a6f 100644 --- a/src/main/java/cpw/mods/fml/server/FMLServerHandler.java +++ b/src/main/java/cpw/mods/fml/server/FMLServerHandler.java @@ -259,7 +259,7 @@ { return DedicatedServer.allowPlayerLogins; } - + @Override public void allowLogins() { DedicatedServer.allowPlayerLogins = true; @@ -270,4 +270,10 @@ { // NOOP } + + @Override + public String stripSpecialChars(String message) + { + return message; + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/Minecraft.java b/src/main/java/net/minecraft/client/Minecraft.java index 64cec6e..71caf67 100644 --- a/src/main/java/net/minecraft/client/Minecraft.java +++ b/src/main/java/net/minecraft/client/Minecraft.java @@ -498,7 +498,7 @@ this.mcResourceManager.registerReloadListener(this.standardGalacticFontRenderer); this.mcResourceManager.registerReloadListener(new GrassColorReloadListener()); this.mcResourceManager.registerReloadListener(new FoliageColorReloadListener()); - cpw.mods.fml.common.ProgressManager.ProgressBar bar= cpw.mods.fml.common.ProgressManager.push("Rendering Setup", 9); + cpw.mods.fml.common.ProgressManager.ProgressBar bar= cpw.mods.fml.common.ProgressManager.push("Rendering Setup", 9, true); bar.step("Loading Render Manager"); RenderManager.instance.itemRenderer = new ItemRenderer(this); bar.step("Loading Entity Renderer"); @@ -537,14 +537,14 @@ bar.step("Render Global instance"); this.renderGlobal = new RenderGlobal(this); bar.step("Building Blocks Texture"); - this.textureMapBlocks = new TextureMap(0, "textures/blocks"); + this.textureMapBlocks = new TextureMap(0, "textures/blocks", true); bar.step("Anisotropy and Mipmaps"); this.textureMapBlocks.setAnisotropicFiltering(this.gameSettings.anisotropicFiltering); this.textureMapBlocks.setMipmapLevels(this.gameSettings.mipmapLevels); bar.step("Loading Blocks Texture"); this.renderEngine.loadTextureMap(TextureMap.locationBlocksTexture, this.textureMapBlocks); bar.step("Loading Items Texture"); - this.renderEngine.loadTextureMap(TextureMap.locationItemsTexture, new TextureMap(1, "textures/items")); + this.renderEngine.loadTextureMap(TextureMap.locationItemsTexture, new TextureMap(1, "textures/items", true)); bar.step("Viewport"); GL11.glViewport(0, 0, this.displayWidth, this.displayHeight); this.effectRenderer = new EffectRenderer(this.theWorld, this.renderEngine); @@ -566,12 +566,12 @@ this.field_152354_ay = null; this.loadingScreen = new LoadingScreenRenderer(this); + FMLClientHandler.instance().onInitializationComplete(); if (this.gameSettings.fullScreen && !this.fullscreen) { this.toggleFullscreen(); } - FMLClientHandler.instance().onInitializationComplete(); try { Display.setVSyncEnabled(this.gameSettings.enableVsync); diff --git a/src/main/java/net/minecraft/client/network/NetHandlerPlayClient.java b/src/main/java/net/minecraft/client/network/NetHandlerPlayClient.java index 386a09c..b483a3f 100644 --- a/src/main/java/net/minecraft/client/network/NetHandlerPlayClient.java +++ b/src/main/java/net/minecraft/client/network/NetHandlerPlayClient.java @@ -742,6 +742,11 @@ float f = (float)(p_147281_1_.func_149028_l() * 360) / 256.0F; float f1 = (float)(p_147281_1_.func_149030_m() * 360) / 256.0F; EntityLivingBase entitylivingbase = (EntityLivingBase)EntityList.createEntityByID(p_147281_1_.func_149025_e(), this.gameController.theWorld); + if (entitylivingbase == null) + { + cpw.mods.fml.common.FMLLog.info("Server attempted to spawn an unknown entity using ID: {0} at ({1}, {2}, {3}) Skipping!", p_147281_1_.func_149025_e(), d0, d1, d2); + return; + } entitylivingbase.serverPosX = p_147281_1_.func_149023_f(); entitylivingbase.serverPosY = p_147281_1_.func_149034_g(); entitylivingbase.serverPosZ = p_147281_1_.func_149029_h(); diff --git a/src/main/java/net/minecraft/client/renderer/texture/Stitcher.java b/src/main/java/net/minecraft/client/renderer/texture/Stitcher.java index 5c7d2a8..1f6acc2 100644 --- a/src/main/java/net/minecraft/client/renderer/texture/Stitcher.java +++ b/src/main/java/net/minecraft/client/renderer/texture/Stitcher.java @@ -60,6 +60,7 @@ public void doStitch() { Stitcher.Holder[] aholder = (Stitcher.Holder[])this.setStitchHolders.toArray(new Stitcher.Holder[this.setStitchHolders.size()]); + cpw.mods.fml.common.ProgressManager.ProgressBar bar = cpw.mods.fml.common.ProgressManager.push("Texture stitching", aholder.length); Arrays.sort(aholder); Stitcher.Holder[] aholder1 = aholder; int i = aholder.length; @@ -67,6 +68,7 @@ for (int j = 0; j < i; ++j) { Stitcher.Holder holder = aholder1[j]; + bar.step(holder.getAtlasSprite().getIconName()); if (!this.allocateSlot(holder)) { @@ -80,6 +82,7 @@ this.currentWidth = MathHelper.roundUpToPowerOfTwo(this.currentWidth); this.currentHeight = MathHelper.roundUpToPowerOfTwo(this.currentHeight); } + cpw.mods.fml.common.ProgressManager.pop(bar); } public List getStichSlots() diff --git a/src/main/java/net/minecraft/client/renderer/texture/TextureManager.java b/src/main/java/net/minecraft/client/renderer/texture/TextureManager.java index c1f161c..8b1fedb 100644 --- a/src/main/java/net/minecraft/client/renderer/texture/TextureManager.java +++ b/src/main/java/net/minecraft/client/renderer/texture/TextureManager.java @@ -162,12 +162,15 @@ public void onResourceManagerReload(IResourceManager p_110549_1_) { + cpw.mods.fml.common.ProgressManager.ProgressBar bar = cpw.mods.fml.common.ProgressManager.push("Reloading Texture Manager", this.mapTextureObjects.keySet().size(), true); Iterator iterator = this.mapTextureObjects.entrySet().iterator(); while (iterator.hasNext()) { Entry entry = (Entry)iterator.next(); + bar.step(entry.getKey().toString()); this.loadTexture((ResourceLocation)entry.getKey(), (ITextureObject)entry.getValue()); } + cpw.mods.fml.common.ProgressManager.pop(bar); } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/renderer/texture/TextureMap.java b/src/main/java/net/minecraft/client/renderer/texture/TextureMap.java index a94488a..3264047 100644 --- a/src/main/java/net/minecraft/client/renderer/texture/TextureMap.java +++ b/src/main/java/net/minecraft/client/renderer/texture/TextureMap.java @@ -36,6 +36,7 @@ @SideOnly(Side.CLIENT) public class TextureMap extends AbstractTexture implements ITickableTextureObject, IIconRegister { + private static final boolean ENABLE_SKIP = Boolean.parseBoolean(System.getProperty("fml.skipFirstTextureLoad", "true")); private static final Logger logger = LogManager.getLogger(); public static final ResourceLocation locationBlocksTexture = new ResourceLocation("textures/atlas/blocks.png"); public static final ResourceLocation locationItemsTexture = new ResourceLocation("textures/atlas/items.png"); @@ -48,12 +49,18 @@ private int anisotropicFiltering = 1; private final TextureAtlasSprite missingImage = new TextureAtlasSprite("missingno"); private static final String __OBFID = "CL_00001058"; + private boolean skipFirst = false; public TextureMap(int p_i1281_1_, String p_i1281_2_) { + this(p_i1281_1_, p_i1281_2_, false); + } + public TextureMap(int p_i1281_1_, String p_i1281_2_, boolean skipFirst) + { this.textureType = p_i1281_1_; this.basePath = p_i1281_2_; this.registerIcons(); + this.skipFirst = skipFirst && ENABLE_SKIP; } private void initMissingImage() @@ -100,11 +107,11 @@ this.listAnimatedSprites.clear(); int j = Integer.MAX_VALUE; ForgeHooksClient.onTextureStitchedPre(this); - cpw.mods.fml.common.ProgressManager.ProgressBar bar = cpw.mods.fml.common.ProgressManager.push("Texture stitching", this.mapRegisteredSprites.size()); + cpw.mods.fml.common.ProgressManager.ProgressBar bar = cpw.mods.fml.common.ProgressManager.push("Texture Loading", skipFirst ? 0 : this.mapRegisteredSprites.size()); Iterator iterator = this.mapRegisteredSprites.entrySet().iterator(); TextureAtlasSprite textureatlassprite; - while (iterator.hasNext()) + while (!skipFirst && iterator.hasNext()) { Entry entry = (Entry)iterator.next(); ResourceLocation resourcelocation = new ResourceLocation((String)entry.getKey()); @@ -197,9 +204,9 @@ } Iterator iterator1 = this.mapRegisteredSprites.values().iterator(); - bar = cpw.mods.fml.common.ProgressManager.push("Mipmap generation", this.mapRegisteredSprites.size()); + bar = cpw.mods.fml.common.ProgressManager.push("Mipmap generation", skipFirst ? 0 : this.mapRegisteredSprites.size()); - while (iterator1.hasNext()) + while (!skipFirst && iterator1.hasNext()) { final TextureAtlasSprite textureatlassprite1 = (TextureAtlasSprite)iterator1.next(); bar.step(textureatlassprite1.getIconName()); @@ -244,6 +251,7 @@ this.missingImage.generateMipmaps(this.mipmapLevels); stitcher.addSprite(this.missingImage); cpw.mods.fml.common.ProgressManager.pop(bar); + skipFirst = false; bar = cpw.mods.fml.common.ProgressManager.push("Texture creation", 3); try diff --git a/src/main/java/net/minecraft/client/resources/SimpleReloadableResourceManager.java b/src/main/java/net/minecraft/client/resources/SimpleReloadableResourceManager.java index ef96434..a197440 100644 --- a/src/main/java/net/minecraft/client/resources/SimpleReloadableResourceManager.java +++ b/src/main/java/net/minecraft/client/resources/SimpleReloadableResourceManager.java @@ -95,7 +95,7 @@ public void reloadResources(List p_110541_1_) { this.clearResources(); - cpw.mods.fml.common.ProgressManager.ProgressBar resReload = cpw.mods.fml.common.ProgressManager.push("Loading Resources", p_110541_1_.size()+1); + cpw.mods.fml.common.ProgressManager.ProgressBar resReload = cpw.mods.fml.common.ProgressManager.push("Loading Resources", p_110541_1_.size()+1, true); logger.info("Reloading ResourceManager: " + joinerResourcePacks.join(Iterables.transform(p_110541_1_, new Function() { private static final String __OBFID = "CL_00001092"; diff --git a/src/main/java/net/minecraft/entity/EntityList.java b/src/main/java/net/minecraft/entity/EntityList.java index 8902165..c6b902f 100644 --- a/src/main/java/net/minecraft/entity/EntityList.java +++ b/src/main/java/net/minecraft/entity/EntityList.java @@ -84,6 +84,7 @@ public static void addMapping(Class p_75618_0_, String p_75618_1_, int p_75618_2_) { + if (p_75618_2_ < 0 || p_75618_2_ > 255) throw new IllegalArgumentException("Attempted to register a entity with invalid ID: " + p_75618_2_ + " Name: " + p_75618_1_ + " Class: " + p_75618_0_); if (stringToClassMapping.containsKey(p_75618_1_)) { throw new IllegalArgumentException("ID is already registered: " + p_75618_1_); @@ -321,4 +322,4 @@ this.field_151513_e = StatList.func_151176_b(this); } } -} \ No newline at end of file +} diff --git a/src/main/java/net/minecraftforge/client/model/obj/WavefrontObject.java b/src/main/java/net/minecraftforge/client/model/obj/WavefrontObject.java index 8476f30..665d7c8 100644 --- a/src/main/java/net/minecraftforge/client/model/obj/WavefrontObject.java +++ b/src/main/java/net/minecraftforge/client/model/obj/WavefrontObject.java @@ -26,9 +26,9 @@ */ public class WavefrontObject implements IModelCustom { - private static Pattern vertexPattern = Pattern.compile("(v( (\\-){0,1}\\d+\\.\\d+){3,4} *\\n)|(v( (\\-){0,1}\\d+\\.\\d+){3,4} *$)"); - private static Pattern vertexNormalPattern = Pattern.compile("(vn( (\\-){0,1}\\d+\\.\\d+){3,4} *\\n)|(vn( (\\-){0,1}\\d+\\.\\d+){3,4} *$)"); - private static Pattern textureCoordinatePattern = Pattern.compile("(vt( (\\-){0,1}\\d+\\.\\d+){2,3} *\\n)|(vt( (\\-){0,1}\\d+\\.\\d+){2,3} *$)"); + private static Pattern vertexPattern = Pattern.compile("(v( (\\-){0,1}\\d+(\\.\\d+)?){3,4} *\\n)|(v( (\\-){0,1}\\d+(\\.\\d+)?){3,4} *$)"); + private static Pattern vertexNormalPattern = Pattern.compile("(vn( (\\-){0,1}\\d+(\\.\\d+)?){3,4} *\\n)|(vn( (\\-){0,1}\\d+(\\.\\d+)?){3,4} *$)"); + private static Pattern textureCoordinatePattern = Pattern.compile("(vt( (\\-){0,1}\\d+\\.\\d+){2,3} *\\n)|(vt( (\\-){0,1}\\d+(\\.\\d+)?){2,3} *$)"); private static Pattern face_V_VT_VN_Pattern = Pattern.compile("(f( \\d+/\\d+/\\d+){3,4} *\\n)|(f( \\d+/\\d+/\\d+){3,4} *$)"); private static Pattern face_V_VT_Pattern = Pattern.compile("(f( \\d+/\\d+){3,4} *\\n)|(f( \\d+/\\d+){3,4} *$)"); private static Pattern face_V_VN_Pattern = Pattern.compile("(f( \\d+//\\d+){3,4} *\\n)|(f( \\d+//\\d+){3,4} *$)"); @@ -49,7 +49,7 @@ public WavefrontObject(ResourceLocation resource) throws ModelFormatException { this.fileName = resource.toString(); - + try { IResource res = Minecraft.getMinecraft().getResourceManager().getResource(resource); @@ -60,7 +60,7 @@ throw new ModelFormatException("IO Exception reading model format", e); } } - + public WavefrontObject(String filename, InputStream inputStream) throws ModelFormatException { this.fileName = filename; diff --git a/src/main/java/net/minecraftforge/common/ForgeModContainer.java b/src/main/java/net/minecraftforge/common/ForgeModContainer.java index c0c9b74..eaa31e6 100644 --- a/src/main/java/net/minecraftforge/common/ForgeModContainer.java +++ b/src/main/java/net/minecraftforge/common/ForgeModContainer.java @@ -12,6 +12,7 @@ import static net.minecraftforge.common.config.Configuration.CATEGORY_GENERAL; import java.io.File; +import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -381,4 +382,13 @@ "net.minecraftforge.transformers" ); } + + + + @Override + public Certificate getSigningCertificate() + { + Certificate[] certificates = getClass().getProtectionDomain().getCodeSource().getCertificates(); + return certificates != null ? certificates[0] : null; + } } diff --git a/src/main/java/net/minecraftforge/common/ForgeVersion.java b/src/main/java/net/minecraftforge/common/ForgeVersion.java index a18b35e..4081068 100644 --- a/src/main/java/net/minecraftforge/common/ForgeVersion.java +++ b/src/main/java/net/minecraftforge/common/ForgeVersion.java @@ -23,7 +23,7 @@ //This number is incremented every minecraft release, never reset public static final int minorVersion = 13; //This number is incremented every time a interface changes or new major feature is added, and reset every Minecraft version - public static final int revisionVersion = 3; + public static final int revisionVersion = 4; //This number is incremented every time Jenkins builds Forge, and never reset. Should always be 0 in the repo code. public static final int buildVersion = 1403; diff --git a/src/main/java/net/minecraftforge/common/MinecraftForge.java b/src/main/java/net/minecraftforge/common/MinecraftForge.java index 1744040..7c43ac9 100644 --- a/src/main/java/net/minecraftforge/common/MinecraftForge.java +++ b/src/main/java/net/minecraftforge/common/MinecraftForge.java @@ -140,16 +140,16 @@ else handlers = ObjectArrays.concat(handlers, server, String.class); - FMLLog.info("Preloading CrashReport classes", ForgeVersion.getVersion()); + //FMLLog.info("Preloading CrashReport classes", ForgeVersion.getVersion()); for (String s : handlers) { - FMLLog.info("\t" + s); + //FMLLog.info("\t" + s); try { Class cls = Class.forName(s, false, MinecraftForge.class.getClassLoader()); if (cls != null && !Callable.class.isAssignableFrom(cls)) { - FMLLog.info("\t% s is not a instance of callable!", s); + //FMLLog.info("\t% s is not a instance of callable!", s); } } catch (Exception e){} diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index d4a7f57..a127b8c 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -79,25 +79,21 @@ public static void initFluidIDs(BiMap newfluidIDs, Set defaultNames) { maxID = newfluidIDs.size(); - fluidIDs.clear(); - fluidIDs.putAll(newfluidIDs); - fluidNames.clear(); - for (Entry e : fluidIDs.entrySet()) { - fluidNames.put(e.getValue(), e.getKey().getName()); - } - loadFluidDefaults(defaultNames); + loadFluidDefaults(newfluidIDs, defaultNames); } /** * Called by forge to load default fluid IDs from the world or from server -> client for syncing * DO NOT call this and expect useful behaviour. + * @param newfluidIDs */ - private static void loadFluidDefaults(Set defaultNames) + private static void loadFluidDefaults(BiMap localFluidIDs, Set defaultNames) { // If there's an empty set of default names, use the defaults as defined locally if (defaultNames.isEmpty()) { defaultNames.addAll(defaultFluidName.values()); } + BiMap localFluids = HashBiMap.create(fluids); for (String defaultName : defaultNames) { Fluid fluid = masterFluidReference.get(defaultName); @@ -112,10 +108,17 @@ FMLLog.getLogger().log(Level.ERROR, "The fluid {} specified as default is not present - it will be reverted to default {}", defaultName, localDefault); } FMLLog.getLogger().log(Level.DEBUG, "The fluid {} has been selected as the default fluid for {}", defaultName, fluid.getName()); - Fluid oldFluid = fluids.put(fluid.getName(), fluid); - Integer id = fluidIDs.remove(oldFluid); - fluidIDs.put(fluid, id); + Fluid oldFluid = localFluids.put(fluid.getName(), fluid); + Integer id = localFluidIDs.remove(oldFluid); + localFluidIDs.put(fluid, id); } + BiMap localFluidNames = fluidNames; + for (Entry e : localFluidIDs.entrySet()) { + localFluidNames.put(e.getValue(), e.getKey().getName()); + } + fluidIDs = localFluidIDs; + fluids = localFluids; + fluidNames = localFluidNames; fluidBlocks = null; for (FluidDelegate fd : delegates.values()) { @@ -312,7 +315,7 @@ { FMLLog.getLogger().log(Level.DEBUG, "World is missing persistent fluid defaults - using local defaults"); } - loadFluidDefaults(defaults); + loadFluidDefaults(HashBiMap.create(fluidIDs), defaults); } public static void writeDefaultFluidList(NBTTagCompound forgeData)