Commit 3c957d788ff474d8a80aad15c5c096c01eb2c9e2
1 parent
bd15e763
check for mod transformer injection errors and treat as critical errors
Showing
8 changed files
with
217 additions
and
24 deletions
java/client/com/mumfrey/liteloader/client/ClientEvents.java
@@ -481,7 +481,7 @@ public class ClientEvents extends Events<Minecraft, IntegratedServer> | @@ -481,7 +481,7 @@ public class ClientEvents extends Events<Minecraft, IntegratedServer> | ||
481 | catch (Throwable th) | 481 | catch (Throwable th) |
482 | { | 482 | { |
483 | this.mods.onLateInitFailed(initMod, th); | 483 | this.mods.onLateInitFailed(initMod, th); |
484 | - LiteLoaderLogger.warning(th, "Error initialising mod %s", initMod.getName()); | 484 | + LiteLoaderLogger.warning(th, "Error calling late init for mod %s", initMod.getName()); |
485 | } | 485 | } |
486 | } | 486 | } |
487 | } | 487 | } |
java/client/com/mumfrey/liteloader/client/LiteLoaderPanelManager.java
@@ -191,6 +191,12 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | @@ -191,6 +191,12 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | ||
191 | { | 191 | { |
192 | return this.mods.getStartupErrorCount(); | 192 | return this.mods.getStartupErrorCount(); |
193 | } | 193 | } |
194 | + | ||
195 | + @Override | ||
196 | + public int getCriticalErrorCount() | ||
197 | + { | ||
198 | + return this.mods.getCriticalErrorCount(); | ||
199 | + } | ||
194 | 200 | ||
195 | private boolean isPanelSupportedOnScreen(GuiScreen guiScreen) | 201 | private boolean isPanelSupportedOnScreen(GuiScreen guiScreen) |
196 | { | 202 | { |
java/client/com/mumfrey/liteloader/client/gui/GuiLiteLoaderPanel.java
@@ -121,7 +121,7 @@ public class GuiLiteLoaderPanel extends GuiScreen | @@ -121,7 +121,7 @@ public class GuiLiteLoaderPanel extends GuiScreen | ||
121 | 121 | ||
122 | private boolean mouseOverLogo = false; | 122 | private boolean mouseOverLogo = false; |
123 | 123 | ||
124 | - private int startupErrorCount = 0; | 124 | + private int startupErrorCount = 0, criticalErrorCount = 0; |
125 | 125 | ||
126 | /** | 126 | /** |
127 | * @param minecraft | 127 | * @param minecraft |
@@ -144,6 +144,7 @@ public class GuiLiteLoaderPanel extends GuiScreen | @@ -144,6 +144,7 @@ public class GuiLiteLoaderPanel extends GuiScreen | ||
144 | this.settingsPanel = new GuiPanelSettings(this, minecraft); | 144 | this.settingsPanel = new GuiPanelSettings(this, minecraft); |
145 | 145 | ||
146 | this.startupErrorCount = mods.getStartupErrorCount(); | 146 | this.startupErrorCount = mods.getStartupErrorCount(); |
147 | + this.criticalErrorCount = mods.getCriticalErrorCount(); | ||
147 | } | 148 | } |
148 | 149 | ||
149 | /** | 150 | /** |
@@ -465,7 +466,7 @@ public class GuiLiteLoaderPanel extends GuiScreen | @@ -465,7 +466,7 @@ public class GuiLiteLoaderPanel extends GuiScreen | ||
465 | 466 | ||
466 | private void drawErrorTooltip(int left, int top) | 467 | private void drawErrorTooltip(int left, int top) |
467 | { | 468 | { |
468 | - GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, I18n.format("gui.error.tooltip", this.startupErrorCount), left, top, this.width, this.height, 0xFF5555, 0xB0330000); | 469 | + GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, I18n.format("gui.error.tooltip", this.startupErrorCount, this.criticalErrorCount), left, top, this.width, this.height, 0xFF5555, 0xB0330000); |
469 | } | 470 | } |
470 | 471 | ||
471 | /* (non-Javadoc) | 472 | /* (non-Javadoc) |
java/common/com/mumfrey/liteloader/core/Events.java
@@ -99,6 +99,9 @@ public abstract class Events<TClient, TServer extends MinecraftServer> implement | @@ -99,6 +99,9 @@ public abstract class Events<TClient, TServer extends MinecraftServer> implement | ||
99 | */ | 99 | */ |
100 | protected void onStartupComplete() | 100 | protected void onStartupComplete() |
101 | { | 101 | { |
102 | + LoadingProgress.setMessage("Checking mods..."); | ||
103 | + this.mods.onStartupComplete(); | ||
104 | + | ||
102 | LoadingProgress.setMessage("Initialising CoreProviders..."); | 105 | LoadingProgress.setMessage("Initialising CoreProviders..."); |
103 | this.loader.onStartupComplete(); | 106 | this.loader.onStartupComplete(); |
104 | 107 |
java/common/com/mumfrey/liteloader/core/LiteLoaderMods.java
@@ -7,6 +7,7 @@ import java.util.HashMap; | @@ -7,6 +7,7 @@ import java.util.HashMap; | ||
7 | import java.util.LinkedList; | 7 | import java.util.LinkedList; |
8 | import java.util.List; | 8 | import java.util.List; |
9 | import java.util.Map; | 9 | import java.util.Map; |
10 | +import java.util.Set; | ||
10 | 11 | ||
11 | import javax.activity.InvalidActivityException; | 12 | import javax.activity.InvalidActivityException; |
12 | 13 | ||
@@ -18,6 +19,9 @@ import com.mumfrey.liteloader.common.LoadingProgress; | @@ -18,6 +19,9 @@ import com.mumfrey.liteloader.common.LoadingProgress; | ||
18 | import com.mumfrey.liteloader.interfaces.LoaderEnumerator; | 19 | import com.mumfrey.liteloader.interfaces.LoaderEnumerator; |
19 | import com.mumfrey.liteloader.interfaces.Loadable; | 20 | import com.mumfrey.liteloader.interfaces.Loadable; |
20 | import com.mumfrey.liteloader.interfaces.LoadableMod; | 21 | import com.mumfrey.liteloader.interfaces.LoadableMod; |
22 | +import com.mumfrey.liteloader.interfaces.TweakContainer; | ||
23 | +import com.mumfrey.liteloader.launch.ClassTransformerManager; | ||
24 | +import com.mumfrey.liteloader.launch.LiteLoaderTweaker; | ||
21 | import com.mumfrey.liteloader.launch.LoaderEnvironment; | 25 | import com.mumfrey.liteloader.launch.LoaderEnvironment; |
22 | import com.mumfrey.liteloader.launch.LoaderProperties; | 26 | import com.mumfrey.liteloader.launch.LoaderProperties; |
23 | import com.mumfrey.liteloader.modconfig.ConfigManager; | 27 | import com.mumfrey.liteloader.modconfig.ConfigManager; |
@@ -88,7 +92,7 @@ public class LiteLoaderMods | @@ -88,7 +92,7 @@ public class LiteLoaderMods | ||
88 | */ | 92 | */ |
89 | protected final LinkedList<NonMod> disabledMods = new LinkedList<NonMod>(); | 93 | protected final LinkedList<NonMod> disabledMods = new LinkedList<NonMod>(); |
90 | 94 | ||
91 | - private int startupErrorCount; | 95 | + private int startupErrorCount, criticalErrorCount; |
92 | 96 | ||
93 | LiteLoaderMods(LiteLoader loader, LoaderEnvironment environment, LoaderProperties properties, ConfigManager configManager) | 97 | LiteLoaderMods(LiteLoader loader, LoaderEnvironment environment, LoaderProperties properties, ConfigManager configManager) |
94 | { | 98 | { |
@@ -162,6 +166,11 @@ public class LiteLoaderMods | @@ -162,6 +166,11 @@ public class LiteLoaderMods | ||
162 | return this.startupErrorCount; | 166 | return this.startupErrorCount; |
163 | } | 167 | } |
164 | 168 | ||
169 | + public int getCriticalErrorCount() | ||
170 | + { | ||
171 | + return this.criticalErrorCount; | ||
172 | + } | ||
173 | + | ||
165 | public ModInfo<?> getModInfo(LiteMod instance) | 174 | public ModInfo<?> getModInfo(LiteMod instance) |
166 | { | 175 | { |
167 | for (Mod mod : this.allMods) | 176 | for (Mod mod : this.allMods) |
@@ -670,6 +679,47 @@ public class LiteLoaderMods | @@ -670,6 +679,47 @@ public class LiteLoaderMods | ||
670 | return String.format("version.%s", modName.toLowerCase().replaceAll("[^a-z0-9_\\-\\.]", "")); | 679 | return String.format("version.%s", modName.toLowerCase().replaceAll("[^a-z0-9_\\-\\.]", "")); |
671 | } | 680 | } |
672 | 681 | ||
682 | + void onStartupComplete() | ||
683 | + { | ||
684 | + this.validateModTransformers(); | ||
685 | + } | ||
686 | + | ||
687 | + /** | ||
688 | + * Check that all specified mod transformers were injected successfully, tag mods with failed transformers | ||
689 | + * as critically errored | ||
690 | + */ | ||
691 | + private void validateModTransformers() | ||
692 | + { | ||
693 | + ClassTransformerManager transformerManager = LiteLoaderTweaker.getTransformerManager(); | ||
694 | + Set<String> injectedTransformers = transformerManager.getInjectedTransformers(); | ||
695 | + | ||
696 | + for (Mod mod : this.loadedMods) | ||
697 | + { | ||
698 | + if (mod.hasClassTransformers()) | ||
699 | + { | ||
700 | + List<String> modTransformers = ((TweakContainer<?>)mod.getContainer()).getClassTransformerClassNames(); | ||
701 | + for (String modTransformer : modTransformers) | ||
702 | + { | ||
703 | + if (!injectedTransformers.contains(modTransformer)) | ||
704 | + { | ||
705 | + List<Throwable> throwables = transformerManager.getTransformerStartupErrors(modTransformer); | ||
706 | + if (throwables != null) | ||
707 | + { | ||
708 | + for (Throwable th : throwables) | ||
709 | + { | ||
710 | + this.registerModStartupError(mod, th, true); | ||
711 | + } | ||
712 | + } | ||
713 | + else | ||
714 | + { | ||
715 | + this.registerModStartupError(mod, new RuntimeException("Missing class transformer " + modTransformer), true); | ||
716 | + } | ||
717 | + } | ||
718 | + } | ||
719 | + } | ||
720 | + } | ||
721 | + } | ||
722 | + | ||
673 | /** | 723 | /** |
674 | * @param instance | 724 | * @param instance |
675 | * @param th | 725 | * @param th |
@@ -685,7 +735,33 @@ public class LiteLoaderMods | @@ -685,7 +735,33 @@ public class LiteLoaderMods | ||
685 | 735 | ||
686 | private void registerModStartupError(ModInfo<?> mod, Throwable th) | 736 | private void registerModStartupError(ModInfo<?> mod, Throwable th) |
687 | { | 737 | { |
738 | + // This is a critical error if a mod has already injected a transformer, since it may have injected | ||
739 | + // callbacks which it is not in a position to handle! | ||
740 | + boolean critical = this.hasModInjectedTransformers(mod); | ||
741 | + | ||
742 | + this.registerModStartupError(mod, th, critical); | ||
743 | + } | ||
744 | + | ||
745 | + private boolean hasModInjectedTransformers(ModInfo<?> mod) | ||
746 | + { | ||
747 | + if (!mod.hasClassTransformers()) return false; | ||
748 | + | ||
749 | + Set<String> injectedTransformers = LiteLoaderTweaker.getTransformerManager().getInjectedTransformers(); | ||
750 | + List<String> modTransformers = ((TweakContainer<?>)mod.getContainer()).getClassTransformerClassNames(); | ||
751 | + | ||
752 | + for (String modTransformer : modTransformers) | ||
753 | + { | ||
754 | + if (injectedTransformers.contains(modTransformer)) | ||
755 | + return true; | ||
756 | + } | ||
757 | + | ||
758 | + return false; | ||
759 | + } | ||
760 | + | ||
761 | + private void registerModStartupError(ModInfo<?> mod, Throwable th, boolean critical) | ||
762 | + { | ||
688 | this.startupErrorCount++; | 763 | this.startupErrorCount++; |
764 | + if (critical) this.criticalErrorCount++; | ||
689 | mod.registerStartupError(th); | 765 | mod.registerStartupError(th); |
690 | } | 766 | } |
691 | 767 |
java/common/com/mumfrey/liteloader/interfaces/PanelManager.java
@@ -54,4 +54,9 @@ public interface PanelManager<TParentScreen> extends TickObserver, PostRenderObs | @@ -54,4 +54,9 @@ public interface PanelManager<TParentScreen> extends TickObserver, PostRenderObs | ||
54 | * @return | 54 | * @return |
55 | */ | 55 | */ |
56 | public abstract int getStartupErrorCount(); | 56 | public abstract int getStartupErrorCount(); |
57 | + | ||
58 | + /** | ||
59 | + * @return | ||
60 | + */ | ||
61 | + public abstract int getCriticalErrorCount(); | ||
57 | } | 62 | } |
java/common/com/mumfrey/liteloader/launch/ClassTransformerManager.java
1 | package com.mumfrey.liteloader.launch; | 1 | package com.mumfrey.liteloader.launch; |
2 | 2 | ||
3 | -import java.util.Arrays; | ||
4 | -import java.util.Collection; | ||
5 | -import java.util.HashMap; | ||
6 | -import java.util.HashSet; | ||
7 | -import java.util.Iterator; | ||
8 | -import java.util.List; | ||
9 | -import java.util.Map; | ||
10 | -import java.util.Set; | ||
11 | -import java.util.TreeSet; | 3 | +import java.lang.reflect.Field; |
4 | +import java.util.*; | ||
12 | import java.util.Map.Entry; | 5 | import java.util.Map.Entry; |
13 | 6 | ||
7 | +import org.apache.logging.log4j.Logger; | ||
8 | +import org.apache.logging.log4j.core.LogEvent; | ||
9 | +import org.apache.logging.log4j.core.appender.AbstractAppender; | ||
10 | + | ||
14 | import net.minecraft.launchwrapper.IClassTransformer; | 11 | import net.minecraft.launchwrapper.IClassTransformer; |
15 | import net.minecraft.launchwrapper.LaunchClassLoader; | 12 | import net.minecraft.launchwrapper.LaunchClassLoader; |
13 | +import net.minecraft.launchwrapper.LogWrapper; | ||
16 | 14 | ||
17 | import com.mumfrey.liteloader.transformers.PacketTransformer; | 15 | import com.mumfrey.liteloader.transformers.PacketTransformer; |
18 | import com.mumfrey.liteloader.util.SortableValue; | 16 | import com.mumfrey.liteloader.util.SortableValue; |
@@ -33,7 +31,7 @@ public class ClassTransformerManager | @@ -33,7 +31,7 @@ public class ClassTransformerManager | ||
33 | /** | 31 | /** |
34 | * Transformers to inject | 32 | * Transformers to inject |
35 | */ | 33 | */ |
36 | - private Set<String> injectedTransformers = new HashSet<String>(); | 34 | + private Set<String> pendingTransformers = new HashSet<String>(); |
37 | 35 | ||
38 | /** | 36 | /** |
39 | * Transformers to inject after preInit but before the game starts, necessary for anything that needs to be downstream of forge | 37 | * Transformers to inject after preInit but before the game starts, necessary for anything that needs to be downstream of forge |
@@ -51,11 +49,60 @@ public class ClassTransformerManager | @@ -51,11 +49,60 @@ public class ClassTransformerManager | ||
51 | private final List<String> requiredTransformers; | 49 | private final List<String> requiredTransformers; |
52 | 50 | ||
53 | /** | 51 | /** |
52 | + * Transformers successfully injected by us | ||
53 | + */ | ||
54 | + private final Set<String> injectedTransformers = new HashSet<String>(); | ||
55 | + | ||
56 | + /** | ||
57 | + * Catalogue of transformer startup failures | ||
58 | + */ | ||
59 | + private final Map<String, List<Throwable>> transformerStartupErrors = new HashMap<String, List<Throwable>>(); | ||
60 | + | ||
61 | + private Logger attachedLog; | ||
62 | + | ||
63 | + private String pendingTransformer; | ||
64 | + | ||
65 | + class ThrowableObserver extends AbstractAppender | ||
66 | + { | ||
67 | + public ThrowableObserver() | ||
68 | + { | ||
69 | + super("Throwable Observer", null, null); | ||
70 | + this.start(); | ||
71 | + } | ||
72 | + | ||
73 | + @Override | ||
74 | + public void append(LogEvent event) | ||
75 | + { | ||
76 | + ClassTransformerManager.this.observeThrowable(event.getThrown()); | ||
77 | + } | ||
78 | + } | ||
79 | + | ||
80 | + /** | ||
54 | * @param requiredTransformers | 81 | * @param requiredTransformers |
55 | */ | 82 | */ |
56 | public ClassTransformerManager(List<String> requiredTransformers) | 83 | public ClassTransformerManager(List<String> requiredTransformers) |
57 | { | 84 | { |
58 | this.requiredTransformers = requiredTransformers; | 85 | this.requiredTransformers = requiredTransformers; |
86 | + | ||
87 | + this.appendObserver(); | ||
88 | + } | ||
89 | + | ||
90 | + private void appendObserver() | ||
91 | + { | ||
92 | + try | ||
93 | + { | ||
94 | + Field fLogger = LogWrapper.class.getDeclaredField("myLog"); | ||
95 | + fLogger.setAccessible(true); | ||
96 | + this.attachedLog = (Logger)fLogger.get(LogWrapper.log); | ||
97 | + if (this.attachedLog instanceof org.apache.logging.log4j.core.Logger) | ||
98 | + { | ||
99 | + ((org.apache.logging.log4j.core.Logger)this.attachedLog).addAppender(new ThrowableObserver()); | ||
100 | + } | ||
101 | + } | ||
102 | + catch (Exception ex) | ||
103 | + { | ||
104 | + LiteLoaderLogger.warning("Failed to append ThrowableObserver to LogWrapper, transformer startup exceptions may not be logged"); | ||
105 | + } | ||
59 | } | 106 | } |
60 | 107 | ||
61 | /** | 108 | /** |
@@ -66,7 +113,7 @@ public class ClassTransformerManager | @@ -66,7 +113,7 @@ public class ClassTransformerManager | ||
66 | { | 113 | { |
67 | if (!this.gameStarted) | 114 | if (!this.gameStarted) |
68 | { | 115 | { |
69 | - this.injectedTransformers.add(transformerClass); | 116 | + this.pendingTransformers.add(transformerClass); |
70 | return true; | 117 | return true; |
71 | } | 118 | } |
72 | 119 | ||
@@ -81,7 +128,7 @@ public class ClassTransformerManager | @@ -81,7 +128,7 @@ public class ClassTransformerManager | ||
81 | { | 128 | { |
82 | if (!this.gameStarted) | 129 | if (!this.gameStarted) |
83 | { | 130 | { |
84 | - this.injectedTransformers.addAll(transformerClasses); | 131 | + this.pendingTransformers.addAll(transformerClasses); |
85 | return true; | 132 | return true; |
86 | } | 133 | } |
87 | 134 | ||
@@ -96,7 +143,7 @@ public class ClassTransformerManager | @@ -96,7 +143,7 @@ public class ClassTransformerManager | ||
96 | { | 143 | { |
97 | if (!this.gameStarted) | 144 | if (!this.gameStarted) |
98 | { | 145 | { |
99 | - this.injectedTransformers.addAll(Arrays.asList(transformerClasses)); | 146 | + this.pendingTransformers.addAll(Arrays.asList(transformerClasses)); |
100 | return true; | 147 | return true; |
101 | } | 148 | } |
102 | 149 | ||
@@ -108,12 +155,12 @@ public class ClassTransformerManager | @@ -108,12 +155,12 @@ public class ClassTransformerManager | ||
108 | */ | 155 | */ |
109 | void injectUpstreamTransformers(LaunchClassLoader classLoader) | 156 | void injectUpstreamTransformers(LaunchClassLoader classLoader) |
110 | { | 157 | { |
111 | - this.sieveAndSortPacketTransformers(classLoader, this.injectedTransformers); | 158 | + this.sieveAndSortPacketTransformers(classLoader, this.pendingTransformers); |
112 | 159 | ||
113 | for (String requiredTransformerClassName : this.requiredTransformers) | 160 | for (String requiredTransformerClassName : this.requiredTransformers) |
114 | { | 161 | { |
115 | LiteLoaderLogger.info("Injecting required class transformer '%s'", requiredTransformerClassName); | 162 | LiteLoaderLogger.info("Injecting required class transformer '%s'", requiredTransformerClassName); |
116 | - classLoader.registerTransformer(requiredTransformerClassName); | 163 | + this.injectTransformer(classLoader, requiredTransformerClassName); |
117 | } | 164 | } |
118 | 165 | ||
119 | for (Entry<String, TreeSet<SortableValue<String>>> packetClassTransformers : this.packetTransformers.entrySet()) | 166 | for (Entry<String, TreeSet<SortableValue<String>>> packetClassTransformers : this.packetTransformers.entrySet()) |
@@ -121,14 +168,15 @@ public class ClassTransformerManager | @@ -121,14 +168,15 @@ public class ClassTransformerManager | ||
121 | for (SortableValue<String> transformerInfo : packetClassTransformers.getValue()) | 168 | for (SortableValue<String> transformerInfo : packetClassTransformers.getValue()) |
122 | { | 169 | { |
123 | String packetClass = packetClassTransformers.getKey(); | 170 | String packetClass = packetClassTransformers.getKey(); |
171 | + String transformerClassName = transformerInfo.getValue(); | ||
124 | if (packetClass.lastIndexOf('.') != -1) packetClass = packetClass.substring(packetClass.lastIndexOf('.') + 1); | 172 | if (packetClass.lastIndexOf('.') != -1) packetClass = packetClass.substring(packetClass.lastIndexOf('.') + 1); |
125 | - LiteLoaderLogger.info("Injecting packet class transformer '%s' for packet class '%s' with priority %d", transformerInfo.getValue(), packetClass, transformerInfo.getPriority()); | ||
126 | - classLoader.registerTransformer(transformerInfo.getValue()); | 173 | + LiteLoaderLogger.info("Injecting packet class transformer '%s' for packet class '%s' with priority %d", transformerClassName, packetClass, transformerInfo.getPriority()); |
174 | + this.injectTransformer(classLoader, transformerClassName); | ||
127 | } | 175 | } |
128 | } | 176 | } |
129 | 177 | ||
130 | // inject any transformers received after this point directly into the downstreamTransformers set | 178 | // inject any transformers received after this point directly into the downstreamTransformers set |
131 | - this.injectedTransformers = this.downstreamTransformers; | 179 | + this.pendingTransformers = this.downstreamTransformers; |
132 | } | 180 | } |
133 | 181 | ||
134 | /** | 182 | /** |
@@ -142,7 +190,7 @@ public class ClassTransformerManager | @@ -142,7 +190,7 @@ public class ClassTransformerManager | ||
142 | for (String transformerClassName : this.downstreamTransformers) | 190 | for (String transformerClassName : this.downstreamTransformers) |
143 | { | 191 | { |
144 | LiteLoaderLogger.info("Injecting additional class transformer class '%s'", transformerClassName); | 192 | LiteLoaderLogger.info("Injecting additional class transformer class '%s'", transformerClassName); |
145 | - classLoader.registerTransformer(transformerClassName); | 193 | + this.injectTransformer(classLoader, transformerClassName); |
146 | } | 194 | } |
147 | 195 | ||
148 | this.downstreamTransformers.clear(); | 196 | this.downstreamTransformers.clear(); |
@@ -211,4 +259,58 @@ public class ClassTransformerManager | @@ -211,4 +259,58 @@ public class ClassTransformerManager | ||
211 | 259 | ||
212 | LiteLoaderLogger.info("Added %d packet transformer classes to the transformer list", registeredTransformers); | 260 | LiteLoaderLogger.info("Added %d packet transformer classes to the transformer list", registeredTransformers); |
213 | } | 261 | } |
262 | + | ||
263 | + private synchronized void injectTransformer(LaunchClassLoader classLoader, String transformerClassName) | ||
264 | + { | ||
265 | + // Assign pendingTransformer so that logged errors during transformer init can be put in the map | ||
266 | + this.pendingTransformer = transformerClassName; | ||
267 | + | ||
268 | + // Register the transformer | ||
269 | + classLoader.registerTransformer(transformerClassName); | ||
270 | + | ||
271 | + // Unassign pending transformer now init is completed | ||
272 | + this.pendingTransformer = null; | ||
273 | + | ||
274 | + // Check whether the transformer was successfully injected, look for it in the transformer list | ||
275 | + if (this.findTransformer(classLoader, transformerClassName) != null) | ||
276 | + { | ||
277 | + this.injectedTransformers.add(transformerClassName); | ||
278 | + } | ||
279 | + } | ||
280 | + | ||
281 | + public void observeThrowable(Throwable th) | ||
282 | + { | ||
283 | + if (th != null && this.pendingTransformer != null) | ||
284 | + { | ||
285 | + List<Throwable> transformerErrors = this.transformerStartupErrors.get(this.pendingTransformer); | ||
286 | + if (transformerErrors == null) | ||
287 | + { | ||
288 | + transformerErrors = new ArrayList<Throwable>(); | ||
289 | + this.transformerStartupErrors.put(this.pendingTransformer, transformerErrors); | ||
290 | + } | ||
291 | + transformerErrors.add(th); | ||
292 | + } | ||
293 | + } | ||
294 | + | ||
295 | + private IClassTransformer findTransformer(LaunchClassLoader classLoader, String transformerClassName) | ||
296 | + { | ||
297 | + for (IClassTransformer transformer : classLoader.getTransformers()) | ||
298 | + { | ||
299 | + if (transformer.getClass().getName().equals(transformerClassName)) | ||
300 | + return transformer; | ||
301 | + } | ||
302 | + | ||
303 | + return null; | ||
304 | + } | ||
305 | + | ||
306 | + public Set<String> getInjectedTransformers() | ||
307 | + { | ||
308 | + return Collections.unmodifiableSet(this.injectedTransformers); | ||
309 | + } | ||
310 | + | ||
311 | + public List<Throwable> getTransformerStartupErrors(String transformerClassName) | ||
312 | + { | ||
313 | + List<Throwable> errorList = this.transformerStartupErrors.get(transformerClassName); | ||
314 | + return errorList != null ? Collections.unmodifiableList(errorList) : null; | ||
315 | + } | ||
214 | } | 316 | } |
resources/assets/liteloader/lang/en_US.lang
@@ -70,4 +70,4 @@ gui.log.closedialog=Close | @@ -70,4 +70,4 @@ gui.log.closedialog=Close | ||
70 | 70 | ||
71 | gui.error.title=Startup errors for %s | 71 | gui.error.title=Startup errors for %s |
72 | 72 | ||
73 | -gui.error.tooltip=%d mod startup error(s) detected | ||
74 | \ No newline at end of file | 73 | \ No newline at end of file |
74 | +gui.error.tooltip=%d mod startup error(s) detected (%d critical) | ||
75 | \ No newline at end of file | 75 | \ No newline at end of file |