Commit 1782552f6e30982177b67f95efe69326c79614a5

Authored by Mumfrey
1 parent 634b0659

wrap mod instances for better handling for startup errors, report startup errors to the user

Showing 27 changed files with 1261 additions and 322 deletions
java/client/com/mumfrey/liteloader/client/ClientEvents.java
@@ -480,6 +480,7 @@ public class ClientEvents extends Events<Minecraft, IntegratedServer> @@ -480,6 +480,7 @@ public class ClientEvents extends Events<Minecraft, IntegratedServer>
480 } 480 }
481 catch (Throwable th) 481 catch (Throwable th)
482 { 482 {
  483 + this.mods.onLateInitFailed(initMod, th);
483 LiteLoaderLogger.warning(th, "Error initialising mod %s", initMod.getName()); 484 LiteLoaderLogger.warning(th, "Error initialising mod %s", initMod.getName());
484 } 485 }
485 } 486 }
java/client/com/mumfrey/liteloader/client/LiteLoaderPanelManager.java
@@ -185,6 +185,12 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> @@ -185,6 +185,12 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen>
185 this.minecraft.displayGuiScreen(this.panelHost); 185 this.minecraft.displayGuiScreen(this.panelHost);
186 } 186 }
187 } 187 }
  188 +
  189 + @Override
  190 + public int getStartupErrorCount()
  191 + {
  192 + return this.mods.getStartupErrorCount();
  193 + }
188 194
189 private boolean isPanelSupportedOnScreen(GuiScreen guiScreen) 195 private boolean isPanelSupportedOnScreen(GuiScreen guiScreen)
190 { 196 {
java/client/com/mumfrey/liteloader/client/api/LiteLoaderCoreAPIClient.java
@@ -82,7 +82,8 @@ public class LiteLoaderCoreAPIClient extends LiteLoaderCoreAPI @@ -82,7 +82,8 @@ public class LiteLoaderCoreAPIClient extends LiteLoaderCoreAPI
82 { 82 {
83 return ImmutableList.<CustomisationProvider>of 83 return ImmutableList.<CustomisationProvider>of
84 ( 84 (
85 - new LiteLoaderBrandingProvider() 85 + new LiteLoaderBrandingProvider(),
  86 + new LiteLoaderModInfoDecorator()
86 ); 87 );
87 } 88 }
88 89
java/client/com/mumfrey/liteloader/client/api/LiteLoaderModInfoDecorator.java 0 → 100644
  1 +package com.mumfrey.liteloader.client.api;
  2 +
  3 +import java.util.List;
  4 +
  5 +import net.minecraft.client.resources.I18n;
  6 +
  7 +import com.mumfrey.liteloader.api.ModInfoDecorator;
  8 +import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel;
  9 +import com.mumfrey.liteloader.client.util.render.IconAbsolute;
  10 +import com.mumfrey.liteloader.client.util.render.IconAbsoluteClickable;
  11 +import com.mumfrey.liteloader.core.ModInfo;
  12 +import com.mumfrey.liteloader.util.render.IconTextured;
  13 +
  14 +/**
  15 + * ModInfo decorator
  16 + *
  17 + * @author Adam Mummery-Smith
  18 + */
  19 +public class LiteLoaderModInfoDecorator implements ModInfoDecorator
  20 +{
  21 + /* (non-Javadoc)
  22 + * @see com.mumfrey.liteloader.api.ModInfoDecorator#addIcons(com.mumfrey.liteloader.core.ModInfo, java.util.List)
  23 + */
  24 + @Override
  25 + public void addIcons(final ModInfo<?> mod, List<IconTextured> icons)
  26 + {
  27 + if (mod.hasTweakClass())
  28 + {
  29 + icons.add(new IconAbsolute(LiteLoaderBrandingProvider.ABOUT_TEXTURE, I18n.format("gui.mod.providestweak"), 12, 12, 158, 80, 170, 92));
  30 + }
  31 +
  32 + if (mod.hasClassTransformers())
  33 + {
  34 + icons.add(new IconAbsolute(LiteLoaderBrandingProvider.ABOUT_TEXTURE, I18n.format("gui.mod.providestransformer"), 12, 12, 170, 80, 182, 92));
  35 + }
  36 +
  37 + if (mod.usesAPI())
  38 + {
  39 + icons.add(new IconAbsolute(LiteLoaderBrandingProvider.ABOUT_TEXTURE, I18n.format("gui.mod.usingapi"), 12, 12, 122, 92, 134, 104));
  40 + }
  41 +
  42 + List<Throwable> startupErrors = mod.getStartupErrors();
  43 + if (startupErrors != null && startupErrors.size() > 0)
  44 + {
  45 + icons.add(new IconAbsoluteClickable(LiteLoaderBrandingProvider.ABOUT_TEXTURE, I18n.format("gui.mod.startuperror", startupErrors.size()), 12, 12, 134, 92, 146, 104){
  46 + @Override
  47 + public void onClicked(Object source, Object container)
  48 + {
  49 + if (source instanceof GuiLiteLoaderPanel)
  50 + {
  51 + ((GuiLiteLoaderPanel)source).showErrorPanel(mod);
  52 + }
  53 + }
  54 + });
  55 + }
  56 + }
  57 +}
java/client/com/mumfrey/liteloader/client/gui/GuiLiteLoaderPanel.java
@@ -3,10 +3,13 @@ package com.mumfrey.liteloader.client.gui; @@ -3,10 +3,13 @@ package com.mumfrey.liteloader.client.gui;
3 import static org.lwjgl.opengl.GL11.*; 3 import static org.lwjgl.opengl.GL11.*;
4 4
5 import java.nio.DoubleBuffer; 5 import java.nio.DoubleBuffer;
  6 +import java.util.ArrayList;
  7 +import java.util.List;
6 8
7 import net.minecraft.client.Minecraft; 9 import net.minecraft.client.Minecraft;
8 import net.minecraft.client.gui.FontRenderer; 10 import net.minecraft.client.gui.FontRenderer;
9 import net.minecraft.client.gui.GuiButton; 11 import net.minecraft.client.gui.GuiButton;
  12 +import net.minecraft.client.gui.GuiMainMenu;
10 import net.minecraft.client.gui.GuiScreen; 13 import net.minecraft.client.gui.GuiScreen;
11 import net.minecraft.client.renderer.Tessellator; 14 import net.minecraft.client.renderer.Tessellator;
12 import net.minecraft.client.resources.I18n; 15 import net.minecraft.client.resources.I18n;
@@ -20,10 +23,12 @@ import org.lwjgl.input.Mouse; @@ -20,10 +23,12 @@ import org.lwjgl.input.Mouse;
20 import com.mumfrey.liteloader.LiteMod; 23 import com.mumfrey.liteloader.LiteMod;
21 import com.mumfrey.liteloader.api.LiteAPI; 24 import com.mumfrey.liteloader.api.LiteAPI;
22 import com.mumfrey.liteloader.api.BrandingProvider; 25 import com.mumfrey.liteloader.api.BrandingProvider;
  26 +import com.mumfrey.liteloader.api.ModInfoDecorator;
23 import com.mumfrey.liteloader.client.api.LiteLoaderBrandingProvider; 27 import com.mumfrey.liteloader.client.api.LiteLoaderBrandingProvider;
24 import com.mumfrey.liteloader.core.LiteLoader; 28 import com.mumfrey.liteloader.core.LiteLoader;
25 import com.mumfrey.liteloader.core.LiteLoaderVersion; 29 import com.mumfrey.liteloader.core.LiteLoaderVersion;
26 import com.mumfrey.liteloader.core.LiteLoaderMods; 30 import com.mumfrey.liteloader.core.LiteLoaderMods;
  31 +import com.mumfrey.liteloader.core.ModInfo;
27 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI; 32 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI;
28 import com.mumfrey.liteloader.launch.LoaderEnvironment; 33 import com.mumfrey.liteloader.launch.LoaderEnvironment;
29 import com.mumfrey.liteloader.modconfig.ConfigManager; 34 import com.mumfrey.liteloader.modconfig.ConfigManager;
@@ -55,6 +60,10 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -55,6 +60,10 @@ public class GuiLiteLoaderPanel extends GuiScreen
55 */ 60 */
56 private static DoubleBuffer doubleBuffer = BufferUtils.createByteBuffer(64).asDoubleBuffer(); 61 private static DoubleBuffer doubleBuffer = BufferUtils.createByteBuffer(64).asDoubleBuffer();
57 62
  63 + private static int clippingPlaneFlags = 0;
  64 +
  65 + private static boolean displayErrorToolTip = true;
  66 +
58 /** 67 /**
59 * Reference to the main menu which this screen is either overlaying or using as its background 68 * Reference to the main menu which this screen is either overlaying or using as its background
60 */ 69 */
@@ -108,8 +117,12 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -108,8 +117,12 @@ public class GuiLiteLoaderPanel extends GuiScreen
108 private ResourceLocation iconResource = LiteLoaderBrandingProvider.ABOUT_TEXTURE; 117 private ResourceLocation iconResource = LiteLoaderBrandingProvider.ABOUT_TEXTURE;
109 private IIcon iconCoords = LiteLoaderBrandingProvider.ICON_COORDS; 118 private IIcon iconCoords = LiteLoaderBrandingProvider.ICON_COORDS;
110 119
  120 + private List<ModInfoDecorator> modInfoDecorators = new ArrayList<ModInfoDecorator>();
  121 +
111 private boolean mouseOverLogo = false; 122 private boolean mouseOverLogo = false;
112 123
  124 + private int startupErrorCount = 0;
  125 +
113 /** 126 /**
114 * @param minecraft 127 * @param minecraft
115 * @param parentScreen 128 * @param parentScreen
@@ -127,8 +140,10 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -127,8 +140,10 @@ public class GuiLiteLoaderPanel extends GuiScreen
127 140
128 this.initBranding(); 141 this.initBranding();
129 142
130 - this.currentPanel = this.modsPanel = new GuiPanelMods(this, minecraft, mods, environment, configManager, this.brandColour); 143 + this.currentPanel = this.modsPanel = new GuiPanelMods(this, minecraft, mods, environment, configManager, this.brandColour, this.modInfoDecorators);
131 this.settingsPanel = new GuiPanelSettings(this, minecraft); 144 this.settingsPanel = new GuiPanelSettings(this, minecraft);
  145 +
  146 + this.startupErrorCount = mods.getStartupErrorCount();
132 } 147 }
133 148
134 /** 149 /**
@@ -145,31 +160,38 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -145,31 +160,38 @@ public class GuiLiteLoaderPanel extends GuiScreen
145 for (LiteAPI api : LiteLoader.getAPIs()) 160 for (LiteAPI api : LiteLoader.getAPIs())
146 { 161 {
147 BrandingProvider brandingProvider = LiteLoader.getCustomisationProvider(api, BrandingProvider.class); 162 BrandingProvider brandingProvider = LiteLoader.getCustomisationProvider(api, BrandingProvider.class);
148 - if (brandingProvider == null) continue;  
149 -  
150 - if (brandingProvider.getBrandingColour() != 0 && brandingProvider.getPriority() > brandingColourProviderPriority) 163 + if (brandingProvider != null)
151 { 164 {
152 - brandingColourProviderPriority = brandingProvider.getPriority();  
153 - this.brandColour = 0xFF000000 | brandingProvider.getBrandingColour(); 165 + if (brandingProvider.getBrandingColour() != 0 && brandingProvider.getPriority() > brandingColourProviderPriority)
  166 + {
  167 + brandingColourProviderPriority = brandingProvider.getPriority();
  168 + this.brandColour = 0xFF000000 | brandingProvider.getBrandingColour();
  169 + }
  170 +
  171 + ResourceLocation logoResource = brandingProvider.getLogoResource();
  172 + IIcon logoCoords = brandingProvider.getLogoCoords();
  173 + if (logoResource != null && logoCoords != null && brandingProvider.getPriority() > logoProviderPriority)
  174 + {
  175 + logoProvider = api;
  176 + logoProviderPriority = brandingProvider.getPriority();
  177 + this.logoResource = logoResource;
  178 + this.logoCoords = logoCoords;
  179 + }
  180 +
  181 + ResourceLocation iconResource = brandingProvider.getIconResource();
  182 + IIcon iconCoords = brandingProvider.getIconCoords();
  183 + if (iconResource != null && iconCoords != null && brandingProvider.getPriority() > iconProviderPriority)
  184 + {
  185 + iconProviderPriority = brandingProvider.getPriority();
  186 + this.iconResource = iconResource;
  187 + this.iconCoords = iconCoords;
  188 + }
154 } 189 }
155 190
156 - ResourceLocation logoResource = brandingProvider.getLogoResource();  
157 - IIcon logoCoords = brandingProvider.getLogoCoords();  
158 - if (logoResource != null && logoCoords != null && brandingProvider.getPriority() > logoProviderPriority) 191 + ModInfoDecorator modInfoDecorator = LiteLoader.getCustomisationProvider(api, ModInfoDecorator.class);
  192 + if (modInfoDecorator != null)
159 { 193 {
160 - logoProvider = api;  
161 - logoProviderPriority = brandingProvider.getPriority();  
162 - this.logoResource = logoResource;  
163 - this.logoCoords = logoCoords;  
164 - }  
165 -  
166 - ResourceLocation iconResource = brandingProvider.getIconResource();  
167 - IIcon iconCoords = brandingProvider.getIconCoords();  
168 - if (iconResource != null && iconCoords != null && brandingProvider.getPriority() > iconProviderPriority)  
169 - {  
170 - iconProviderPriority = brandingProvider.getPriority();  
171 - this.iconResource = iconResource;  
172 - this.iconCoords = iconCoords; 194 + this.modInfoDecorators.add(modInfoDecorator);
173 } 195 }
174 } 196 }
175 197
@@ -218,6 +240,9 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -218,6 +240,9 @@ public class GuiLiteLoaderPanel extends GuiScreen
218 @Override 240 @Override
219 public void initGui() 241 public void initGui()
220 { 242 {
  243 + // Hide the tooltip once the user opens the panel
  244 + GuiLiteLoaderPanel.displayErrorToolTip = false;
  245 +
221 this.currentPanel.setSize(this.width - LEFT_EDGE, this.height); 246 this.currentPanel.setSize(this.width - LEFT_EDGE, this.height);
222 247
223 this.buttonList.add(new GuiHoverLabel(2, LEFT_EDGE + MARGIN, this.height - PANEL_BOTTOM + 9, this.fontRendererObj, I18n.format("gui.about.taboptions"), this.brandColour)); 248 this.buttonList.add(new GuiHoverLabel(2, LEFT_EDGE + MARGIN, this.height - PANEL_BOTTOM + 9, this.fontRendererObj, I18n.format("gui.about.taboptions"), this.brandColour));
@@ -312,16 +337,11 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -312,16 +337,11 @@ public class GuiLiteLoaderPanel extends GuiScreen
312 this.handleMouseClick(offsetMouseX, mouseY, partialTicks, active, mouseOverTab); 337 this.handleMouseClick(offsetMouseX, mouseY, partialTicks, active, mouseOverTab);
313 338
314 // Calculate the tab opacity, not framerate adjusted because we don't really care 339 // Calculate the tab opacity, not framerate adjusted because we don't really care
315 - this.tabOpacity = mouseOverTab || alwaysExpandTab || this.isOpen() ? 0.5F : Math.max(0.0F, this.tabOpacity - partialTicks * 0.1F); 340 + this.tabOpacity = mouseOverTab || alwaysExpandTab || this.startupErrorCount > 0 || this.isOpen() ? 0.5F : Math.max(0.0F, this.tabOpacity - partialTicks * 0.1F);
316 341
317 // Draw the panel contents 342 // Draw the panel contents
318 this.drawPanel(offsetMouseX, mouseY, partialTicks, active, xOffset); 343 this.drawPanel(offsetMouseX, mouseY, partialTicks, active, xOffset);
319 -  
320 - if (mouseOverTab && this.tweenAmount < 0.01)  
321 - {  
322 - GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, LiteLoader.getVersionDisplayString(), mouseX, mouseY, this.width, this.height, 0xFFFFFF, 0xB0000000);  
323 - GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, this.activeModText, mouseX, mouseY + 13, this.width, this.height, 0xCCCCCC, 0xB0000000);  
324 - } 344 + this.drawTooltips(mouseX, mouseY, partialTicks, active, xOffset, mouseOverTab);
325 } 345 }
326 346
327 /** 347 /**
@@ -348,6 +368,10 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -348,6 +368,10 @@ public class GuiLiteLoaderPanel extends GuiScreen
348 368
349 this.mc.getTextureManager().bindTexture(LiteLoaderBrandingProvider.ABOUT_TEXTURE); 369 this.mc.getTextureManager().bindTexture(LiteLoaderBrandingProvider.ABOUT_TEXTURE);
350 glDrawTexturedRect(LEFT_EDGE - TAB_WIDTH, TAB_TOP, TAB_WIDTH + 1, TAB_HEIGHT, 80, 80, 122, 160, 0.5F + this.tabOpacity); 370 glDrawTexturedRect(LEFT_EDGE - TAB_WIDTH, TAB_TOP, TAB_WIDTH + 1, TAB_HEIGHT, 80, 80, 122, 160, 0.5F + this.tabOpacity);
  371 + if (this.startupErrorCount > 0)
  372 + {
  373 + glDrawTexturedRect(LEFT_EDGE - TAB_WIDTH + 7, TAB_TOP + 2, 12, 12, 134, 92, 134 + 12, 92 + 12, 0.5F + this.tabOpacity);
  374 + }
351 } 375 }
352 else 376 else
353 { 377 {
@@ -420,7 +444,30 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -420,7 +444,30 @@ public class GuiLiteLoaderPanel extends GuiScreen
420 this.mouseOverLogo = (mouseY > MARGIN && mouseY < MARGIN + this.logoCoords.getIconHeight() && mouseX > left && mouseX < left + this.logoCoords.getIconWidth()); 444 this.mouseOverLogo = (mouseY > MARGIN && mouseY < MARGIN + this.logoCoords.getIconHeight() && mouseX > left && mouseX < left + this.logoCoords.getIconWidth());
421 return this.mouseOverLogo; 445 return this.mouseOverLogo;
422 } 446 }
423 - 447 +
  448 + private void drawTooltips(int mouseX, int mouseY, float partialTicks, boolean active, float xOffset, boolean mouseOverTab)
  449 + {
  450 + if (mouseOverTab && this.tweenAmount < 0.01)
  451 + {
  452 + GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, LiteLoader.getVersionDisplayString(), mouseX, mouseY, this.width, this.height, 0xFFFFFF, 0xB0000000);
  453 + GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, this.activeModText, mouseX, mouseY + 13, this.width, this.height, 0xCCCCCC, 0xB0000000);
  454 +
  455 + if (this.startupErrorCount > 0)
  456 + {
  457 + this.drawErrorTooltip(mouseX, mouseY - 13);
  458 + }
  459 + }
  460 + else if (GuiLiteLoaderPanel.displayErrorToolTip && this.startupErrorCount > 0 && !active && this.parentScreen instanceof GuiMainMenu)
  461 + {
  462 + this.drawErrorTooltip((int)xOffset + LEFT_EDGE - 12, TAB_TOP + 2);
  463 + }
  464 + }
  465 +
  466 + private void drawErrorTooltip(int left, int top)
  467 + {
  468 + GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, I18n.format("gui.error.tooltip", this.startupErrorCount), left, top, this.width, this.height, 0xFF5555, 0xB0330000);
  469 + }
  470 +
424 /* (non-Javadoc) 471 /* (non-Javadoc)
425 * @see net.minecraft.client.gui.GuiScreen#actionPerformed(net.minecraft.client.gui.GuiButton) 472 * @see net.minecraft.client.gui.GuiScreen#actionPerformed(net.minecraft.client.gui.GuiButton)
426 */ 473 */
@@ -463,6 +510,11 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -463,6 +510,11 @@ public class GuiLiteLoaderPanel extends GuiScreen
463 this.setCurrentPanel(new GuiPanelAbout(this.mc, this)); 510 this.setCurrentPanel(new GuiPanelAbout(this.mc, this));
464 } 511 }
465 512
  513 + public void showErrorPanel(ModInfo<?> mod)
  514 + {
  515 + this.setCurrentPanel(new GuiPanelError(this.mc, this, mod));
  516 + }
  517 +
466 /* (non-Javadoc) 518 /* (non-Javadoc)
467 * @see net.minecraft.client.gui.GuiScreen#mouseClicked(int, int, int) 519 * @see net.minecraft.client.gui.GuiScreen#mouseClicked(int, int, int)
468 */ 520 */
@@ -688,6 +740,8 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -688,6 +740,8 @@ public class GuiLiteLoaderPanel extends GuiScreen
688 */ 740 */
689 final static void glEnableClipping(int xLeft, int xRight, int yTop, int yBottom) 741 final static void glEnableClipping(int xLeft, int xRight, int yTop, int yBottom)
690 { 742 {
  743 + clippingPlaneFlags = 0;
  744 +
691 // Apply left edge clipping if specified 745 // Apply left edge clipping if specified
692 if (xLeft != -1) 746 if (xLeft != -1)
693 { 747 {
@@ -695,6 +749,7 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -695,6 +749,7 @@ public class GuiLiteLoaderPanel extends GuiScreen
695 doubleBuffer.put(1).put(0).put(0).put(-xLeft).flip(); 749 doubleBuffer.put(1).put(0).put(0).put(-xLeft).flip();
696 glClipPlane(GL_CLIP_PLANE2, doubleBuffer); 750 glClipPlane(GL_CLIP_PLANE2, doubleBuffer);
697 glEnable(GL_CLIP_PLANE2); 751 glEnable(GL_CLIP_PLANE2);
  752 + clippingPlaneFlags |= GL_CLIP_PLANE2;
698 } 753 }
699 754
700 // Apply right edge clipping if specified 755 // Apply right edge clipping if specified
@@ -704,6 +759,7 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -704,6 +759,7 @@ public class GuiLiteLoaderPanel extends GuiScreen
704 doubleBuffer.put(-1).put(0).put(0).put(xRight).flip(); 759 doubleBuffer.put(-1).put(0).put(0).put(xRight).flip();
705 glClipPlane(GL_CLIP_PLANE3, doubleBuffer); 760 glClipPlane(GL_CLIP_PLANE3, doubleBuffer);
706 glEnable(GL_CLIP_PLANE3); 761 glEnable(GL_CLIP_PLANE3);
  762 + clippingPlaneFlags |= GL_CLIP_PLANE3;
707 } 763 }
708 764
709 // Apply top edge clipping if specified 765 // Apply top edge clipping if specified
@@ -713,6 +769,7 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -713,6 +769,7 @@ public class GuiLiteLoaderPanel extends GuiScreen
713 doubleBuffer.put(0).put(1).put(0).put(-yTop).flip(); 769 doubleBuffer.put(0).put(1).put(0).put(-yTop).flip();
714 glClipPlane(GL_CLIP_PLANE4, doubleBuffer); 770 glClipPlane(GL_CLIP_PLANE4, doubleBuffer);
715 glEnable(GL_CLIP_PLANE4); 771 glEnable(GL_CLIP_PLANE4);
  772 + clippingPlaneFlags |= GL_CLIP_PLANE4;
716 } 773 }
717 774
718 // Apply bottom edge clipping if specified 775 // Apply bottom edge clipping if specified
@@ -722,10 +779,22 @@ public class GuiLiteLoaderPanel extends GuiScreen @@ -722,10 +779,22 @@ public class GuiLiteLoaderPanel extends GuiScreen
722 doubleBuffer.put(0).put(-1).put(0).put(yBottom).flip(); 779 doubleBuffer.put(0).put(-1).put(0).put(yBottom).flip();
723 glClipPlane(GL_CLIP_PLANE5, doubleBuffer); 780 glClipPlane(GL_CLIP_PLANE5, doubleBuffer);
724 glEnable(GL_CLIP_PLANE5); 781 glEnable(GL_CLIP_PLANE5);
  782 + clippingPlaneFlags |= GL_CLIP_PLANE5;
725 } 783 }
726 } 784 }
727 785
728 /** 786 /**
  787 + * Enable clipping planes which were previously enabled
  788 + */
  789 + final static void glEnableClipping()
  790 + {
  791 + if ((clippingPlaneFlags & GL_CLIP_PLANE2) == GL_CLIP_PLANE2) glEnable(GL_CLIP_PLANE2);
  792 + if ((clippingPlaneFlags & GL_CLIP_PLANE3) == GL_CLIP_PLANE3) glEnable(GL_CLIP_PLANE3);
  793 + if ((clippingPlaneFlags & GL_CLIP_PLANE4) == GL_CLIP_PLANE4) glEnable(GL_CLIP_PLANE4);
  794 + if ((clippingPlaneFlags & GL_CLIP_PLANE5) == GL_CLIP_PLANE5) glEnable(GL_CLIP_PLANE5);
  795 + }
  796 +
  797 + /**
729 * Disable OpenGL clipping planes (uses planes 2, 3, 4 and 5) 798 * Disable OpenGL clipping planes (uses planes 2, 3, 4 and 5)
730 */ 799 */
731 final static void glDisableClipping() 800 final static void glDisableClipping()
java/client/com/mumfrey/liteloader/client/gui/GuiModListEntry.java
@@ -11,16 +11,16 @@ import net.minecraft.client.gui.FontRenderer; @@ -11,16 +11,16 @@ import net.minecraft.client.gui.FontRenderer;
11 import net.minecraft.client.gui.Gui; 11 import net.minecraft.client.gui.Gui;
12 import net.minecraft.client.resources.I18n; 12 import net.minecraft.client.resources.I18n;
13 13
14 -import com.google.common.collect.ImmutableSet; 14 +import com.google.common.base.Strings;
15 import com.mumfrey.liteloader.LiteMod; 15 import com.mumfrey.liteloader.LiteMod;
16 -import com.mumfrey.liteloader.client.api.LiteLoaderBrandingProvider;  
17 -import com.mumfrey.liteloader.client.util.render.IconAbsolute;  
18 -import com.mumfrey.liteloader.core.LiteLoaderEnumerator; 16 +import com.mumfrey.liteloader.api.ModInfoDecorator;
19 import com.mumfrey.liteloader.core.LiteLoaderMods; 17 import com.mumfrey.liteloader.core.LiteLoaderMods;
  18 +import com.mumfrey.liteloader.core.ModInfo;
20 import com.mumfrey.liteloader.interfaces.Loadable; 19 import com.mumfrey.liteloader.interfaces.Loadable;
21 import com.mumfrey.liteloader.interfaces.LoadableMod; 20 import com.mumfrey.liteloader.interfaces.LoadableMod;
22 -import com.mumfrey.liteloader.interfaces.TweakContainer;  
23 import com.mumfrey.liteloader.launch.LoaderEnvironment; 21 import com.mumfrey.liteloader.launch.LoaderEnvironment;
  22 +import com.mumfrey.liteloader.util.render.IconClickable;
  23 +import com.mumfrey.liteloader.util.render.IconTextured;
24 24
25 /** 25 /**
26 * Represents a mod in the mod info screen, keeps track of mod information and provides methods 26 * Represents a mod in the mod info screen, keeps track of mod information and provides methods
@@ -41,6 +41,9 @@ public class GuiModListEntry extends Gui @@ -41,6 +41,9 @@ public class GuiModListEntry extends Gui
41 private static final int API_COLOUR = 0xFFAA00AA; 41 private static final int API_COLOUR = 0xFFAA00AA;
42 private static final int EXTERNAL_ENTRY_COLOUR = 0xFF47D1AA; 42 private static final int EXTERNAL_ENTRY_COLOUR = 0xFF47D1AA;
43 private static final int MISSING_DEPENDENCY_COLOUR = 0xFFFFAA00; 43 private static final int MISSING_DEPENDENCY_COLOUR = 0xFFFFAA00;
  44 + private static final int ERROR_COLOUR = 0xFFFF5555;
  45 + private static final int ERROR_GRADIENT_COLOUR = 0xFFAA0000;
  46 + private static final int ERROR_GRADIENT_COLOUR2 = 0xFF550000;
44 47
45 private static final int TITLE_COLOUR = GuiModListEntry.WHITE; 48 private static final int TITLE_COLOUR = GuiModListEntry.WHITE;
46 private static final int VERSION_TEXT_COLOUR = GuiModListEntry.GREY; 49 private static final int VERSION_TEXT_COLOUR = GuiModListEntry.GREY;
@@ -54,8 +57,6 @@ public class GuiModListEntry extends Gui @@ -54,8 +57,6 @@ public class GuiModListEntry extends Gui
54 private static final int PANEL_HEIGHT = 32; 57 private static final int PANEL_HEIGHT = 32;
55 private static final int PANEL_SPACING = 4; 58 private static final int PANEL_SPACING = 4;
56 59
57 - private static final Set<String> BUILT_IN_APIS = ImmutableSet.of("liteloader");  
58 -  
59 /** 60 /**
60 * For text display 61 * For text display
61 */ 62 */
@@ -63,12 +64,12 @@ public class GuiModListEntry extends Gui @@ -63,12 +64,12 @@ public class GuiModListEntry extends Gui
63 64
64 private final int brandColour; 65 private final int brandColour;
65 66
  67 + private final List<ModInfoDecorator> decorators;
  68 +
66 private final LiteLoaderMods mods; 69 private final LiteLoaderMods mods;
67 70
68 - private LiteMod modInstance; 71 + private ModInfo<?> modInfo;
69 72
70 - private Class<? extends LiteMod> modClass;  
71 -  
72 /** 73 /**
73 * The identifier of the mod, used as the enablement/disablement key 74 * The identifier of the mod, used as the enablement/disablement key
74 */ 75 */
@@ -108,6 +109,8 @@ public class GuiModListEntry extends Gui @@ -108,6 +109,8 @@ public class GuiModListEntry extends Gui
108 109
109 private boolean isMissingAPIs; 110 private boolean isMissingAPIs;
110 111
  112 + private boolean isErrored;
  113 +
111 /** 114 /**
112 * True if the mod is missing a dependency which has caused it not to load 115 * True if the mod is missing a dependency which has caused it not to load
113 */ 116 */
@@ -134,12 +137,14 @@ public class GuiModListEntry extends Gui @@ -134,12 +137,14 @@ public class GuiModListEntry extends Gui
134 */ 137 */
135 private boolean mouseOverListEntry, mouseOverInfo, mouseOverScrollBar; 138 private boolean mouseOverListEntry, mouseOverInfo, mouseOverScrollBar;
136 139
  140 + private IconClickable mouseOverIcon = null;
  141 +
137 /** 142 /**
138 * True if this is not a mod but an external jar 143 * True if this is not a mod but an external jar
139 */ 144 */
140 private boolean external; 145 private boolean external;
141 146
142 - private List<IconAbsolute> modIcons = new ArrayList<IconAbsolute>(); 147 + private List<IconTextured> modIcons = new ArrayList<IconTextured>();
143 148
144 /** 149 /**
145 * Scroll bar control for the mod info 150 * Scroll bar control for the mod info
@@ -149,125 +154,49 @@ public class GuiModListEntry extends Gui @@ -149,125 +154,49 @@ public class GuiModListEntry extends Gui
149 /** 154 /**
150 * Mod list entry for an ACTIVE mod 155 * Mod list entry for an ACTIVE mod
151 * @param fontRenderer 156 * @param fontRenderer
152 - * @param modInstance 157 + * @param modInfo
153 * @param enabledMods 158 * @param enabledMods
154 */ 159 */
155 - GuiModListEntry(LiteLoaderMods mods, LoaderEnvironment environment, FontRenderer fontRenderer, int brandColour, LiteMod modInstance) 160 + GuiModListEntry(LiteLoaderMods mods, LoaderEnvironment environment, FontRenderer fontRenderer, int brandColour, List<ModInfoDecorator> decorators, ModInfo<?> modInfo)
156 { 161 {
157 - this.mods = mods;  
158 - this.fontRenderer = fontRenderer;  
159 - this.brandColour = brandColour;  
160 -  
161 - this.modInstance = modInstance;  
162 - this.modClass = modInstance.getClass();  
163 - this.identifier = mods.getModIdentifier(this.modClass);  
164 - this.name = modInstance.getName();  
165 - this.version = modInstance.getVersion();  
166 - this.enabled = true;  
167 - this.canBeToggled = this.identifier != null && mods.getEnabledModsList().saveAllowed();  
168 - this.willBeEnabled = this.identifier == null || mods.isModEnabled(this.identifier);;  
169 -  
170 - LoadableMod<?> modContainer = mods.getModContainer(this.modClass); 162 + this.mods = mods;
  163 + this.fontRenderer = fontRenderer;
  164 + this.brandColour = brandColour;
  165 + this.decorators = decorators;
  166 + this.modInfo = modInfo;
171 167
172 - this.author = modContainer.getAuthor();  
173 - this.url = modContainer.getMetaValue("url", null);  
174 - this.description = modContainer.getDescription(LiteLoaderEnumerator.getModClassName(modInstance)); 168 + this.identifier = modInfo.getIdentifier();
  169 + this.name = modInfo.getDisplayName();
  170 + this.version = modInfo.getVersion();
  171 + this.author = modInfo.getAuthor();
  172 + this.enabled = modInfo.isActive();
  173 + this.canBeToggled = modInfo.isToggleable() && mods.getEnabledModsList().saveAllowed();
  174 + this.willBeEnabled = mods.isModEnabled(this.identifier);;
  175 + this.external = modInfo.getContainer().isExternalJar();
  176 + this.description = modInfo.getDescription();
  177 + this.url = modInfo.getURL();
  178 + this.isErrored = modInfo.getStartupErrors() != null && modInfo.getStartupErrors().size() > 0;
175 179
176 - boolean providesTweak = false;  
177 - boolean providesTransformer = false;  
178 - boolean usingAPI = this.checkUsingAPI(modContainer);  
179 -  
180 - if (modContainer instanceof TweakContainer) 180 + if (!modInfo.isActive())
181 { 181 {
182 - providesTweak = ((TweakContainer<?>)modContainer).hasTweakClass();  
183 - providesTransformer = ((TweakContainer<?>)modContainer).hasClassTransformers(); 182 + this.enabled = modInfo.getContainer().isEnabled(environment);
  183 +
  184 + Loadable<?> modContainer = modInfo.getContainer();
  185 + if (modContainer instanceof LoadableMod<?>)
  186 + {
  187 + LoadableMod<?> loadableMod = (LoadableMod<?>)modContainer;
  188 +
  189 + this.missingDependencies = loadableMod.getMissingDependencies();
  190 + this.missingAPIs = loadableMod.getMissingAPIs();
  191 + this.isMissingDependencies = this.missingDependencies.size() > 0;
  192 + this.isMissingAPIs = this.missingAPIs.size() > 0;
  193 + }
184 } 194 }
185 -  
186 - this.initIcons(providesTweak, providesTransformer, usingAPI);  
187 - }  
188 -  
189 - /**  
190 - * Mod list entry for a currently disabled mod  
191 - * @param mods  
192 - * @param fontRenderer  
193 - * @param modContainer  
194 - */  
195 - GuiModListEntry(LiteLoaderMods mods, LoaderEnvironment environment, FontRenderer fontRenderer, int brandColour, Loadable<?> modContainer)  
196 - {  
197 - this.mods = mods;  
198 - this.fontRenderer = fontRenderer;  
199 - this.brandColour = brandColour;  
200 -  
201 - this.identifier = modContainer.getIdentifier().toLowerCase();  
202 - this.name = modContainer.getDisplayName();  
203 - this.version = modContainer.getVersion();  
204 - this.author = modContainer.getAuthor();  
205 - this.enabled = modContainer.isEnabled(environment);  
206 - this.canBeToggled = modContainer.isToggleable() && mods.getEnabledModsList().saveAllowed();  
207 - this.willBeEnabled = mods.isModEnabled(this.identifier);  
208 - this.external = modContainer.isExternalJar();  
209 - this.description = modContainer.getDescription(null);  
210 -  
211 - boolean providesTweak = false;  
212 - boolean providesTransformer = false;  
213 - boolean usingAPI = false;  
214 195
215 - if (modContainer instanceof LoadableMod<?>) 196 + for (ModInfoDecorator decorator : this.decorators)
216 { 197 {
217 - LoadableMod<?> loadableMod = (LoadableMod<?>)modContainer;  
218 -  
219 - this.url = loadableMod.getMetaValue("url", null);  
220 - this.missingDependencies = loadableMod.getMissingDependencies();  
221 - this.missingAPIs = loadableMod.getMissingAPIs();  
222 - this.isMissingDependencies = this.missingDependencies.size() > 0;  
223 - this.isMissingAPIs = this.missingAPIs.size() > 0;  
224 -  
225 - usingAPI = this.checkUsingAPI(loadableMod); 198 + decorator.addIcons(modInfo, this.modIcons);
226 } 199 }
227 -  
228 - if (modContainer instanceof TweakContainer)  
229 - {  
230 - TweakContainer<?> tweakContainer = (TweakContainer<?>)modContainer;  
231 -  
232 - providesTweak = tweakContainer.hasTweakClass();  
233 - providesTransformer = tweakContainer.hasClassTransformers();  
234 - }  
235 -  
236 - this.initIcons(providesTweak, providesTransformer, usingAPI);  
237 - }  
238 -  
239 - /**  
240 - * @param providesTweak  
241 - * @param providesTransformer  
242 - * @param usingAPI  
243 - */  
244 - protected void initIcons(boolean providesTweak, boolean providesTransformer, boolean usingAPI)  
245 - {  
246 - if (providesTweak)  
247 - {  
248 - this.modIcons.add(new IconAbsolute(LiteLoaderBrandingProvider.ABOUT_TEXTURE, I18n.format("gui.mod.providestweak"), 12, 12, 158, 80, 158 + 12, 80 + 12));  
249 - }  
250 -  
251 - if (providesTransformer)  
252 - {  
253 - this.modIcons.add(new IconAbsolute(LiteLoaderBrandingProvider.ABOUT_TEXTURE, I18n.format("gui.mod.providestransformer"), 12, 12, 170, 80, 170 + 12, 80 + 12));  
254 - }  
255 -  
256 - if (usingAPI)  
257 - {  
258 - this.modIcons.add(new IconAbsolute(LiteLoaderBrandingProvider.ABOUT_TEXTURE, I18n.format("gui.mod.usingapi"), 12, 12, 122, 92, 122 + 12, 92 + 12));  
259 - }  
260 - }  
261 -  
262 - private boolean checkUsingAPI(LoadableMod<?> loadableMod)  
263 - {  
264 - for (String requiredAPI : loadableMod.getRequiredAPIs())  
265 - {  
266 - if (!GuiModListEntry.BUILT_IN_APIS.contains(requiredAPI))  
267 - return true;  
268 - }  
269 -  
270 - return false;  
271 } 200 }
272 201
273 /** 202 /**
@@ -305,7 +234,9 @@ public class GuiModListEntry extends Gui @@ -305,7 +234,9 @@ public class GuiModListEntry extends Gui
305 xPosition += (width - 14); 234 xPosition += (width - 14);
306 yPosition += (GuiModListEntry.PANEL_HEIGHT - 14); 235 yPosition += (GuiModListEntry.PANEL_HEIGHT - 14);
307 236
308 - for (IconAbsolute icon : this.modIcons) 237 + this.mouseOverIcon = null;
  238 +
  239 + for (IconTextured icon : this.modIcons)
309 { 240 {
310 xPosition = this.drawPropertyIcon(xPosition, yPosition, icon, mouseX, mouseY); 241 xPosition = this.drawPropertyIcon(xPosition, yPosition, icon, mouseX, mouseY);
311 } 242 }
@@ -313,7 +244,7 @@ public class GuiModListEntry extends Gui @@ -313,7 +244,7 @@ public class GuiModListEntry extends Gui
313 return GuiModListEntry.PANEL_HEIGHT + GuiModListEntry.PANEL_SPACING; 244 return GuiModListEntry.PANEL_HEIGHT + GuiModListEntry.PANEL_SPACING;
314 } 245 }
315 246
316 - protected int drawPropertyIcon(int xPosition, int yPosition, IconAbsolute icon, int mouseX, int mouseY) 247 + protected int drawPropertyIcon(int xPosition, int yPosition, IconTextured icon, int mouseX, int mouseY)
317 { 248 {
318 glColor4f(1.0F, 1.0F, 1.0F, 1.0F); 249 glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
319 Minecraft.getMinecraft().getTextureManager().bindTexture(icon.getTextureResource()); 250 Minecraft.getMinecraft().getTextureManager().bindTexture(icon.getTextureResource());
@@ -324,7 +255,15 @@ public class GuiModListEntry extends Gui @@ -324,7 +255,15 @@ public class GuiModListEntry extends Gui
324 255
325 if (mouseX >= xPosition && mouseX <= xPosition + 12 && mouseY >= yPosition && mouseY <= yPosition + 12) 256 if (mouseX >= xPosition && mouseX <= xPosition + 12 && mouseY >= yPosition && mouseY <= yPosition + 12)
326 { 257 {
327 - GuiLiteLoaderPanel.drawTooltip(this.fontRenderer, icon.getIconName(), mouseX, mouseY, 4096, 4096, GuiModListEntry.WHITE, GuiModListEntry.BLEND_HALF & GuiModListEntry.BLACK); 258 + String tooltipText = icon.getDisplayText();
  259 + if (tooltipText != null)
  260 + {
  261 + GuiLiteLoaderPanel.glDisableClipping();
  262 + GuiLiteLoaderPanel.drawTooltip(this.fontRenderer, tooltipText, mouseX, mouseY, 4096, 4096, GuiModListEntry.WHITE, GuiModListEntry.BLEND_HALF & GuiModListEntry.BLACK);
  263 + GuiLiteLoaderPanel.glEnableClipping();
  264 + }
  265 +
  266 + if (icon instanceof IconClickable) this.mouseOverIcon = (IconClickable)icon;
328 } 267 }
329 268
330 return xPosition - 14; 269 return xPosition - 14;
@@ -353,7 +292,7 @@ public class GuiModListEntry extends Gui @@ -353,7 +292,7 @@ public class GuiModListEntry extends Gui
353 drawRect(xPosition + 5, yPos, xPosition + width, yPos + 1, GuiModListEntry.DIVIDER_COLOUR); yPos += 4; // divider 292 drawRect(xPosition + 5, yPos, xPosition + width, yPos + 1, GuiModListEntry.DIVIDER_COLOUR); yPos += 4; // divider
354 293
355 this.fontRenderer.drawString(I18n.format("gui.about.authors") + ": \2477" + this.author, xPosition + 5, yPos, GuiModListEntry.AUTHORS_COLOUR); yPos += 10; 294 this.fontRenderer.drawString(I18n.format("gui.about.authors") + ": \2477" + this.author, xPosition + 5, yPos, GuiModListEntry.AUTHORS_COLOUR); yPos += 10;
356 - if (this.url != null) 295 + if (!Strings.isNullOrEmpty(this.url))
357 { 296 {
358 this.fontRenderer.drawString(this.url, xPosition + 5, yPos, GuiModListEntry.BLEND_2THRDS & this.brandColour); yPos += 10; 297 this.fontRenderer.drawString(this.url, xPosition + 5, yPos, GuiModListEntry.BLEND_2THRDS & this.brandColour); yPos += 10;
359 } 298 }
@@ -423,7 +362,7 @@ public class GuiModListEntry extends Gui @@ -423,7 +362,7 @@ public class GuiModListEntry extends Gui
423 */ 362 */
424 protected int getGradientColour(boolean selected) 363 protected int getGradientColour(boolean selected)
425 { 364 {
426 - return GuiModListEntry.BLEND_2THRDS & (selected ? (this.external ? GuiModListEntry.EXTERNAL_ENTRY_COLOUR : this.brandColour) : GuiModListEntry.BLACK); 365 + return GuiModListEntry.BLEND_2THRDS & (this.isErrored ? (selected ? GuiModListEntry.ERROR_GRADIENT_COLOUR : GuiModListEntry.ERROR_GRADIENT_COLOUR2) : (selected ? (this.external ? GuiModListEntry.EXTERNAL_ENTRY_COLOUR : this.brandColour) : GuiModListEntry.BLACK));
427 } 366 }
428 367
429 /** 368 /**
@@ -437,6 +376,7 @@ public class GuiModListEntry extends Gui @@ -437,6 +376,7 @@ public class GuiModListEntry extends Gui
437 { 376 {
438 if (this.isMissingDependencies) return GuiModListEntry.MISSING_DEPENDENCY_COLOUR; 377 if (this.isMissingDependencies) return GuiModListEntry.MISSING_DEPENDENCY_COLOUR;
439 if (this.isMissingAPIs) return GuiModListEntry.API_COLOUR; 378 if (this.isMissingAPIs) return GuiModListEntry.API_COLOUR;
  379 + if (this.isErrored) return GuiModListEntry.ERROR_COLOUR;
440 if (!this.enabled) return GuiModListEntry.GREY; 380 if (!this.enabled) return GuiModListEntry.GREY;
441 return this.external ? GuiModListEntry.EXTERNAL_ENTRY_COLOUR : GuiModListEntry.WHITE; 381 return this.external ? GuiModListEntry.EXTERNAL_ENTRY_COLOUR : GuiModListEntry.WHITE;
442 } 382 }
@@ -497,17 +437,17 @@ public class GuiModListEntry extends Gui @@ -497,17 +437,17 @@ public class GuiModListEntry extends Gui
497 437
498 public String getKey() 438 public String getKey()
499 { 439 {
500 - return this.identifier + Integer.toHexString(this.hashCode()); 440 + return (this.isErrored ? "0000" : "") + this.identifier + Integer.toHexString(this.hashCode());
501 } 441 }
502 442
503 public LiteMod getModInstance() 443 public LiteMod getModInstance()
504 { 444 {
505 - return this.modInstance; 445 + return this.modInfo.getMod();
506 } 446 }
507 447
508 public Class<? extends LiteMod> getModClass() 448 public Class<? extends LiteMod> getModClass()
509 { 449 {
510 - return this.modClass; 450 + return this.modInfo.getModClass();
511 } 451 }
512 452
513 public String getName() 453 public String getName()
@@ -545,11 +485,24 @@ public class GuiModListEntry extends Gui @@ -545,11 +485,24 @@ public class GuiModListEntry extends Gui
545 return this.willBeEnabled; 485 return this.willBeEnabled;
546 } 486 }
547 487
  488 + public boolean isMouseOverIcon()
  489 + {
  490 + return this.mouseOverListEntry && this.mouseOverIcon != null;
  491 + }
  492 +
548 public boolean isMouseOver() 493 public boolean isMouseOver()
549 { 494 {
550 return this.mouseOverListEntry; 495 return this.mouseOverListEntry;
551 } 496 }
552 - 497 +
  498 + public void iconClick(Object source)
  499 + {
  500 + if (this.mouseOverIcon != null)
  501 + {
  502 + this.mouseOverIcon.onClicked(source, this);
  503 + }
  504 + }
  505 +
553 public boolean mouseWheelScrolled(int mouseWheelDelta) 506 public boolean mouseWheelScrolled(int mouseWheelDelta)
554 { 507 {
555 if (this.mouseOverInfo) 508 if (this.mouseOverInfo)
java/client/com/mumfrey/liteloader/client/gui/GuiPanelConfigContainer.java
@@ -109,7 +109,14 @@ class GuiPanelConfigContainer extends GuiPanel implements ConfigPanelHost @@ -109,7 +109,14 @@ class GuiPanelConfigContainer extends GuiPanel implements ConfigPanelHost
109 @Override 109 @Override
110 void onShown() 110 void onShown()
111 { 111 {
112 - this.panel.onPanelShown(this); 112 + try
  113 + {
  114 + this.panel.onPanelShown(this);
  115 + }
  116 + catch (Exception ex)
  117 + {
  118 + ex.printStackTrace();
  119 + }
113 } 120 }
114 121
115 /** 122 /**
@@ -118,7 +125,14 @@ class GuiPanelConfigContainer extends GuiPanel implements ConfigPanelHost @@ -118,7 +125,14 @@ class GuiPanelConfigContainer extends GuiPanel implements ConfigPanelHost
118 @Override 125 @Override
119 void onHidden() 126 void onHidden()
120 { 127 {
121 - this.panel.onPanelHidden(); 128 + try
  129 + {
  130 + this.panel.onPanelHidden();
  131 + }
  132 + catch (Exception ex)
  133 + {
  134 + ex.printStackTrace();
  135 + }
122 } 136 }
123 137
124 /** 138 /**
java/client/com/mumfrey/liteloader/client/gui/GuiPanelError.java 0 → 100644
  1 +package com.mumfrey.liteloader.client.gui;
  2 +
  3 +import java.io.PrintWriter;
  4 +import java.io.StringWriter;
  5 +import java.util.ArrayList;
  6 +import java.util.List;
  7 +
  8 +import org.lwjgl.input.Keyboard;
  9 +
  10 +import com.mumfrey.liteloader.core.ModInfo;
  11 +
  12 +import net.minecraft.client.Minecraft;
  13 +import net.minecraft.client.gui.GuiButton;
  14 +import net.minecraft.client.resources.I18n;
  15 +
  16 +public class GuiPanelError extends GuiPanel implements ScrollPanelContent
  17 +{
  18 + private final ModInfo<?> mod;
  19 +
  20 + private GuiScrollPanel scrollPane;
  21 +
  22 + private List<String> scrollPaneContent = new ArrayList<String>();
  23 +
  24 + public GuiPanelError(Minecraft minecraft, GuiLiteLoaderPanel parent, ModInfo<?> mod)
  25 + {
  26 + super(minecraft);
  27 +
  28 + this.mod = mod;
  29 + this.scrollPane = new GuiScrollPanel(minecraft, this, MARGIN, TOP, this.width - (MARGIN * 2), this.height - TOP - BOTTOM);
  30 +
  31 + this.populateScrollPaneContent();
  32 + }
  33 +
  34 + private void populateScrollPaneContent()
  35 + {
  36 + for (Throwable th : this.mod.getStartupErrors())
  37 + {
  38 + StringWriter sw = new StringWriter();
  39 + th.printStackTrace(new PrintWriter(sw, true));
  40 + for (String line : sw.toString().split("\\r?\\n"))
  41 + {
  42 + this.scrollPaneContent.add(line.replace("\t", " "));
  43 + }
  44 +
  45 + this.scrollPaneContent.add("!");
  46 + }
  47 +
  48 + this.scrollPaneContent.remove(this.scrollPaneContent.size() - 1);
  49 + }
  50 +
  51 + @Override
  52 + public int getScrollPanelContentHeight(GuiScrollPanel source)
  53 + {
  54 + return this.scrollPaneContent.size() * 10;
  55 + }
  56 +
  57 + @Override
  58 + public void drawScrollPanelContent(GuiScrollPanel source, int mouseX, int mouseY, float partialTicks, int scrollAmount, int visibleHeight)
  59 + {
  60 + int yPos = -10;
  61 +
  62 + for (String line : this.scrollPaneContent)
  63 + {
  64 + if ("!".equals(line))
  65 + {
  66 + yPos += 10;
  67 + drawRect(0, yPos + 4, this.width, yPos + 5, 0xFF555555);
  68 + }
  69 + else
  70 + {
  71 + boolean indented = line.startsWith(" ");
  72 + line = line.replaceAll("\\((.+?\\.java:[0-9]+)\\)", "(\247f$1\247r)");
  73 + line = line.replaceAll("at ([^\\(]+)\\(", "at \2476$1\247r(");
  74 + this.mc.fontRendererObj.drawString(line, 2, yPos += 10, indented ? 0xFF999999 : 0xFFFF5555);
  75 + }
  76 + }
  77 + }
  78 +
  79 + @Override
  80 + public void scrollPanelActionPerformed(GuiScrollPanel source, GuiButton control)
  81 + {
  82 + }
  83 +
  84 + @Override
  85 + public void scrollPanelMousePressed(GuiScrollPanel source, int mouseX, int mouseY, int mouseButton)
  86 + {
  87 + }
  88 +
  89 + @Override
  90 + void setSize(int width, int height)
  91 + {
  92 + super.setSize(width, height);
  93 +
  94 + this.scrollPane.setSizeAndPosition(MARGIN, TOP, this.width - (MARGIN * 2), this.height - TOP - BOTTOM);
  95 + this.controls.add(new GuiButton(0, this.width - 59 - MARGIN, this.height - BOTTOM + 9, 60, 20, I18n.format("gui.done")));
  96 + }
  97 +
  98 + @Override
  99 + void draw(int mouseX, int mouseY, float partialTicks)
  100 + {
  101 + this.mc.fontRendererObj.drawString(I18n.format("gui.error.title", this.mod.getDisplayName()), MARGIN, TOP - 14, 0xFFFFFFFF);
  102 +
  103 + drawRect(MARGIN, TOP - 4, this.width - MARGIN, TOP - 3, 0xFF999999);
  104 + drawRect(MARGIN, this.height - BOTTOM + 2, this.width - MARGIN, this.height - BOTTOM + 3, 0xFF999999);
  105 +
  106 + this.scrollPane.draw(mouseX, mouseY, partialTicks);
  107 +
  108 + super.draw(mouseX, mouseY, partialTicks);
  109 + }
  110 +
  111 + @Override
  112 + void onTick()
  113 + {
  114 + }
  115 +
  116 + @Override
  117 + void onHidden()
  118 + {
  119 + }
  120 +
  121 + @Override
  122 + void onShown()
  123 + {
  124 + }
  125 +
  126 + @Override
  127 + void keyPressed(char keyChar, int keyCode)
  128 + {
  129 + if (keyCode == Keyboard.KEY_ESCAPE) this.close();
  130 + }
  131 +
  132 + @Override
  133 + void mousePressed(int mouseX, int mouseY, int mouseButton)
  134 + {
  135 + this.scrollPane.mousePressed(mouseX, mouseY, mouseButton);
  136 + super.mousePressed(mouseX, mouseY, mouseButton);
  137 + }
  138 +
  139 + @Override
  140 + void mouseMoved(int mouseX, int mouseY)
  141 + {
  142 + }
  143 +
  144 + @Override
  145 + void mouseReleased(int mouseX, int mouseY, int mouseButton)
  146 + {
  147 + this.scrollPane.mouseReleased(mouseX, mouseY, mouseButton);
  148 + }
  149 +
  150 + @Override
  151 + void mouseWheelScrolled(int mouseWheelDelta)
  152 + {
  153 + this.scrollPane.mouseWheelScrolled(mouseWheelDelta);
  154 + }
  155 +
  156 + @Override
  157 + void actionPerformed(GuiButton control)
  158 + {
  159 + if (control.id == 0) this.close();
  160 + }
  161 +}
java/client/com/mumfrey/liteloader/client/gui/GuiPanelMods.java
@@ -10,8 +10,11 @@ import java.util.TreeMap; @@ -10,8 +10,11 @@ import java.util.TreeMap;
10 import org.lwjgl.input.Keyboard; 10 import org.lwjgl.input.Keyboard;
11 11
12 import com.mumfrey.liteloader.LiteMod; 12 import com.mumfrey.liteloader.LiteMod;
  13 +import com.mumfrey.liteloader.api.ModInfoDecorator;
13 import com.mumfrey.liteloader.core.LiteLoaderMods; 14 import com.mumfrey.liteloader.core.LiteLoaderMods;
  15 +import com.mumfrey.liteloader.core.ModInfo;
14 import com.mumfrey.liteloader.interfaces.Loadable; 16 import com.mumfrey.liteloader.interfaces.Loadable;
  17 +import com.mumfrey.liteloader.interfaces.LoadableMod;
15 import com.mumfrey.liteloader.launch.LoaderEnvironment; 18 import com.mumfrey.liteloader.launch.LoaderEnvironment;
16 import com.mumfrey.liteloader.modconfig.ConfigManager; 19 import com.mumfrey.liteloader.modconfig.ConfigManager;
17 import com.mumfrey.liteloader.modconfig.ConfigPanel; 20 import com.mumfrey.liteloader.modconfig.ConfigPanel;
@@ -70,7 +73,7 @@ public class GuiPanelMods extends GuiPanel @@ -70,7 +73,7 @@ public class GuiPanelMods extends GuiPanel
70 73
71 private int brandColour; 74 private int brandColour;
72 75
73 - public GuiPanelMods(GuiLiteLoaderPanel parentScreen, Minecraft minecraft, LiteLoaderMods mods, LoaderEnvironment environment, ConfigManager configManager, int brandColour) 76 + public GuiPanelMods(GuiLiteLoaderPanel parentScreen, Minecraft minecraft, LiteLoaderMods mods, LoaderEnvironment environment, ConfigManager configManager, int brandColour, List<ModInfoDecorator> decorators)
74 { 77 {
75 super(minecraft); 78 super(minecraft);
76 79
@@ -78,7 +81,7 @@ public class GuiPanelMods extends GuiPanel @@ -78,7 +81,7 @@ public class GuiPanelMods extends GuiPanel
78 this.configManager = configManager; 81 this.configManager = configManager;
79 this.brandColour = brandColour; 82 this.brandColour = brandColour;
80 83
81 - this.populateModList(mods, environment); 84 + this.populateModList(mods, environment, decorators);
82 } 85 }
83 86
84 /** 87 /**
@@ -87,29 +90,29 @@ public class GuiPanelMods extends GuiPanel @@ -87,29 +90,29 @@ public class GuiPanelMods extends GuiPanel
87 * @param mods 90 * @param mods
88 * @param environment 91 * @param environment
89 */ 92 */
90 - private void populateModList(LiteLoaderMods mods, LoaderEnvironment environment) 93 + private void populateModList(LiteLoaderMods mods, LoaderEnvironment environment, List<ModInfoDecorator> decorators)
91 { 94 {
92 // Add mods to this treeset first, in order to sort them 95 // Add mods to this treeset first, in order to sort them
93 Map<String, GuiModListEntry> sortedMods = new TreeMap<String, GuiModListEntry>(); 96 Map<String, GuiModListEntry> sortedMods = new TreeMap<String, GuiModListEntry>();
94 97
95 // Active mods 98 // Active mods
96 - for (LiteMod mod : mods.getLoadedMods()) 99 + for (ModInfo<LoadableMod<?>> mod : mods.getLoadedMods())
97 { 100 {
98 - GuiModListEntry modListEntry = new GuiModListEntry(mods, environment, this.mc.fontRendererObj, this.brandColour, mod); 101 + GuiModListEntry modListEntry = new GuiModListEntry(mods, environment, this.mc.fontRendererObj, this.brandColour, decorators, mod);
99 sortedMods.put(modListEntry.getKey(), modListEntry); 102 sortedMods.put(modListEntry.getKey(), modListEntry);
100 } 103 }
101 104
102 // Disabled mods 105 // Disabled mods
103 - for (Loadable<?> disabledMod : mods.getDisabledMods()) 106 + for (ModInfo<Loadable<?>> disabledMod : mods.getDisabledMods())
104 { 107 {
105 - GuiModListEntry modListEntry = new GuiModListEntry(mods, environment, this.mc.fontRendererObj, this.brandColour, disabledMod); 108 + GuiModListEntry modListEntry = new GuiModListEntry(mods, environment, this.mc.fontRendererObj, this.brandColour, decorators, disabledMod);
106 sortedMods.put(modListEntry.getKey(), modListEntry); 109 sortedMods.put(modListEntry.getKey(), modListEntry);
107 } 110 }
108 111
109 // Injected tweaks 112 // Injected tweaks
110 - for (Loadable<?> injectedTweak : mods.getInjectedTweaks()) 113 + for (ModInfo<Loadable<?>> injectedTweak : mods.getInjectedTweaks())
111 { 114 {
112 - GuiModListEntry modListEntry = new GuiModListEntry(mods, environment, this.mc.fontRendererObj, this.brandColour, injectedTweak); 115 + GuiModListEntry modListEntry = new GuiModListEntry(mods, environment, this.mc.fontRendererObj, this.brandColour, decorators, injectedTweak);
113 sortedMods.put(modListEntry.getKey(), modListEntry); 116 sortedMods.put(modListEntry.getKey(), modListEntry);
114 } 117 }
115 118
@@ -178,10 +181,17 @@ public class GuiPanelMods extends GuiPanel @@ -178,10 +181,17 @@ public class GuiPanelMods extends GuiPanel
178 { 181 {
179 this.selectMod(mod); 182 this.selectMod(mod);
180 183
181 - // handle double-click  
182 - if (mod == lastSelectedMod && this.doubleClickTime > 0 && this.btnConfig.visible) 184 + if (mod.isMouseOverIcon())
183 { 185 {
184 - this.actionPerformed(this.btnConfig); 186 + mod.iconClick(this.parentScreen);
  187 + }
  188 + else
  189 + {
  190 + // handle double-click
  191 + if (mod == lastSelectedMod && this.doubleClickTime > 0 && this.btnConfig.visible)
  192 + {
  193 + this.actionPerformed(this.btnConfig);
  194 + }
185 } 195 }
186 196
187 this.doubleClickTime = 5; 197 this.doubleClickTime = 5;
java/client/com/mumfrey/liteloader/client/util/render/IconAbsolute.java
1 package com.mumfrey.liteloader.client.util.render; 1 package com.mumfrey.liteloader.client.util.render;
2 2
3 -import net.minecraft.util.IIcon; 3 +import com.mumfrey.liteloader.util.render.IconTextured;
  4 +
4 import net.minecraft.util.ResourceLocation; 5 import net.minecraft.util.ResourceLocation;
5 6
6 -public class IconAbsolute implements IIcon 7 +public class IconAbsolute implements IconTextured
7 { 8 {
8 private ResourceLocation textureResource; 9 private ResourceLocation textureResource;
9 10
10 - private String name; 11 + private String displayText;
11 12
12 private int texMapSize = 256; 13 private int texMapSize = 256;
13 14
@@ -21,15 +22,15 @@ public class IconAbsolute implements IIcon @@ -21,15 +22,15 @@ public class IconAbsolute implements IIcon
21 private float vCoord; 22 private float vCoord;
22 private float vCoord2; 23 private float vCoord2;
23 24
24 - public IconAbsolute(ResourceLocation textureResource, String name, int width, int height, float uCoord, float vCoord, float uCoord2, float vCoord2) 25 + public IconAbsolute(ResourceLocation textureResource, String displayText, int width, int height, float uCoord, float vCoord, float uCoord2, float vCoord2)
25 { 26 {
26 - this(textureResource, name, width, height, uCoord, vCoord, uCoord2, vCoord2, 256); 27 + this(textureResource, displayText, width, height, uCoord, vCoord, uCoord2, vCoord2, 256);
27 } 28 }
28 29
29 - public IconAbsolute(ResourceLocation textureResource, String name, int width, int height, float uCoord, float vCoord, float uCoord2, float vCoord2, int texMapSize) 30 + public IconAbsolute(ResourceLocation textureResource, String displayText, int width, int height, float uCoord, float vCoord, float uCoord2, float vCoord2, int texMapSize)
30 { 31 {
31 this.textureResource = textureResource; 32 this.textureResource = textureResource;
32 - this.name = name; 33 + this.displayText = displayText;
33 this.width = width; 34 this.width = width;
34 this.height = height; 35 this.height = height;
35 36
@@ -42,7 +43,14 @@ public class IconAbsolute implements IIcon @@ -42,7 +43,14 @@ public class IconAbsolute implements IIcon
42 this.vCoord = vCoord / this.texMapSize; 43 this.vCoord = vCoord / this.texMapSize;
43 this.vCoord2 = vCoord2 / this.texMapSize; 44 this.vCoord2 = vCoord2 / this.texMapSize;
44 } 45 }
  46 +
  47 + @Override
  48 + public String getDisplayText()
  49 + {
  50 + return this.displayText;
  51 + }
45 52
  53 + @Override
46 public ResourceLocation getTextureResource() 54 public ResourceLocation getTextureResource()
47 { 55 {
48 return this.textureResource; 56 return this.textureResource;
@@ -60,11 +68,13 @@ public class IconAbsolute implements IIcon @@ -60,11 +68,13 @@ public class IconAbsolute implements IIcon
60 return this.height; 68 return this.height;
61 } 69 }
62 70
  71 + @Override
63 public int getUPos() 72 public int getUPos()
64 { 73 {
65 return this.uPos; 74 return this.uPos;
66 } 75 }
67 76
  77 + @Override
68 public int getVPos() 78 public int getVPos()
69 { 79 {
70 return this.vPos; 80 return this.vPos;
@@ -111,6 +121,6 @@ public class IconAbsolute implements IIcon @@ -111,6 +121,6 @@ public class IconAbsolute implements IIcon
111 @Override 121 @Override
112 public String getIconName() 122 public String getIconName()
113 { 123 {
114 - return this.name; 124 + return this.displayText;
115 } 125 }
116 } 126 }
java/client/com/mumfrey/liteloader/client/util/render/IconAbsoluteClickable.java 0 → 100644
  1 +package com.mumfrey.liteloader.client.util.render;
  2 +
  3 +import net.minecraft.util.ResourceLocation;
  4 +
  5 +import com.mumfrey.liteloader.util.render.IconClickable;
  6 +
  7 +public abstract class IconAbsoluteClickable extends IconAbsolute implements IconClickable
  8 +{
  9 + public IconAbsoluteClickable(ResourceLocation textureResource, String displayText, int width, int height, float uCoord, float vCoord, float uCoord2, float vCoord2)
  10 + {
  11 + super(textureResource, displayText, width, height, uCoord, vCoord, uCoord2, vCoord2);
  12 + }
  13 +
  14 + public IconAbsoluteClickable(ResourceLocation textureResource, String displayText, int width, int height, float uCoord, float vCoord, float uCoord2, float vCoord2, int texMapSize)
  15 + {
  16 + super(textureResource, displayText, width, height, uCoord, vCoord, uCoord2, vCoord2, texMapSize);
  17 + }
  18 +}
java/common/com/mumfrey/liteloader/api/ModInfoDecorator.java 0 → 100644
  1 +package com.mumfrey.liteloader.api;
  2 +
  3 +import java.util.List;
  4 +
  5 +import com.mumfrey.liteloader.core.ModInfo;
  6 +import com.mumfrey.liteloader.util.render.IconTextured;
  7 +
  8 +/**
  9 + * LiteLoader Extensible API - Branding Provider
  10 + *
  11 + * Decorator for ModInfo classes, to alter the appearance of ModInfo entries in the mod list
  12 + *
  13 + * @author Adam Mummery-Smith
  14 + */
  15 +public interface ModInfoDecorator extends CustomisationProvider
  16 +{
  17 + /**
  18 + * Add icons to the mod list entry for this mod
  19 + *
  20 + * @param mod
  21 + * @param icons
  22 + */
  23 + public abstract void addIcons(ModInfo<?> mod, List<IconTextured> icons);
  24 +}
java/common/com/mumfrey/liteloader/core/Events.java
@@ -55,7 +55,8 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -55,7 +55,8 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
55 * Profiler 55 * Profiler
56 */ 56 */
57 protected final Profiler profiler; 57 protected final Profiler profiler;
58 - 58 +
  59 + protected LiteLoaderMods mods;
59 60
60 /** 61 /**
61 * List of mods which can filter server chat 62 * List of mods which can filter server chat
@@ -84,6 +85,14 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -84,6 +85,14 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
84 this.engine = engine; 85 this.engine = engine;
85 this.profiler = engine.getProfiler(); 86 this.profiler = engine.getProfiler();
86 } 87 }
  88 +
  89 + /**
  90 + * @param mods
  91 + */
  92 + void setMods(LiteLoaderMods mods)
  93 + {
  94 + this.mods = mods;
  95 + }
87 96
88 /** 97 /**
89 * 98 *
java/common/com/mumfrey/liteloader/core/LiteLoader.java
@@ -2,6 +2,7 @@ package com.mumfrey.liteloader.core; @@ -2,6 +2,7 @@ package com.mumfrey.liteloader.core;
2 2
3 import java.io.File; 3 import java.io.File;
4 import java.io.PrintStream; 4 import java.io.PrintStream;
  5 +import java.util.ArrayList;
5 import java.util.Collection; 6 import java.util.Collection;
6 import java.util.LinkedList; 7 import java.util.LinkedList;
7 import java.util.List; 8 import java.util.List;
@@ -602,7 +603,14 @@ public final class LiteLoader @@ -602,7 +603,14 @@ public final class LiteLoader
602 */ 603 */
603 public List<LiteMod> getLoadedMods() 604 public List<LiteMod> getLoadedMods()
604 { 605 {
605 - return this.mods.getLoadedMods(); 606 + List<LiteMod> loadedMods = new ArrayList<LiteMod>();
  607 +
  608 + for (ModInfo<LoadableMod<?>> loadedMod : this.mods.getLoadedMods())
  609 + {
  610 + loadedMods.add(loadedMod.getMod());
  611 + }
  612 +
  613 + return loadedMods;
606 } 614 }
607 615
608 /** 616 /**
@@ -610,15 +618,30 @@ public final class LiteLoader @@ -610,15 +618,30 @@ public final class LiteLoader
610 */ 618 */
611 public List<Loadable<?>> getDisabledMods() 619 public List<Loadable<?>> getDisabledMods()
612 { 620 {
613 - return this.mods.getDisabledMods(); 621 + List<Loadable<?>> disabledMods = new ArrayList<Loadable<?>>();
  622 +
  623 + for (ModInfo<Loadable<?>> disabledMod : this.mods.getDisabledMods())
  624 + {
  625 + disabledMods.add(disabledMod.getContainer());
  626 + }
  627 +
  628 + return disabledMods;
614 } 629 }
615 630
616 /** 631 /**
617 * Get the list of injected tweak containers 632 * Get the list of injected tweak containers
618 */ 633 */
  634 + @SuppressWarnings("unchecked")
619 public Collection<Loadable<File>> getInjectedTweaks() 635 public Collection<Loadable<File>> getInjectedTweaks()
620 { 636 {
621 - return this.mods.getInjectedTweaks(); 637 + Collection<Loadable<File>> tweaks = new ArrayList<Loadable<File>>();
  638 +
  639 + for (ModInfo<Loadable<?>> tweak : this.mods.getInjectedTweaks())
  640 + {
  641 + tweaks.add((Loadable<File>)tweak.getContainer());
  642 + }
  643 +
  644 + return tweaks;
622 } 645 }
623 646
624 /** 647 /**
@@ -840,6 +863,10 @@ public final class LiteLoader @@ -840,6 +863,10 @@ public final class LiteLoader
840 863
841 // Create the event broker 864 // Create the event broker
842 this.events = this.objectFactory.getEventBroker(); 865 this.events = this.objectFactory.getEventBroker();
  866 + if (this.events != null)
  867 + {
  868 + this.events.setMods(this.mods);
  869 + }
843 870
844 // Get the mod panel manager 871 // Get the mod panel manager
845 this.modPanelManager = this.objectFactory.getModPanelManager(); 872 this.modPanelManager = this.objectFactory.getModPanelManager();
java/common/com/mumfrey/liteloader/core/LiteLoaderEnumerator.java
@@ -5,8 +5,10 @@ import java.net.MalformedURLException; @@ -5,8 +5,10 @@ import java.net.MalformedURLException;
5 import java.net.URL; 5 import java.net.URL;
6 import java.util.ArrayList; 6 import java.util.ArrayList;
7 import java.util.Collection; 7 import java.util.Collection;
  8 +import java.util.Collections;
8 import java.util.HashMap; 9 import java.util.HashMap;
9 import java.util.HashSet; 10 import java.util.HashSet;
  11 +import java.util.LinkedHashSet;
10 import java.util.LinkedList; 12 import java.util.LinkedList;
11 import java.util.List; 13 import java.util.List;
12 import java.util.Map; 14 import java.util.Map;
@@ -76,17 +78,17 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -76,17 +78,17 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
76 /** 78 /**
77 * Classes to load, mapped by class name 79 * Classes to load, mapped by class name
78 */ 80 */
79 - private final Map<String, Class<? extends LiteMod>> modsToLoad = new HashMap<String, Class<? extends LiteMod>>(); 81 + private final Set<ModInfo<LoadableMod<?>>> modsToLoad = new LinkedHashSet<ModInfo<LoadableMod<?>>>();
80 82
81 /** 83 /**
82 * Mod containers which are disabled 84 * Mod containers which are disabled
83 */ 85 */
84 - private final Map<String, LoadableMod<?>> disabledContainers = new HashMap<String, LoadableMod<?>>(); 86 + private final Map<String, ModInfo<Loadable<?>>> disabledContainers = new HashMap<String, ModInfo<Loadable<?>>>();
85 87
86 /** 88 /**
87 * Mapping of identifiers to mod containers 89 * Mapping of identifiers to mod containers
88 */ 90 */
89 - private final Map<String, LoadableMod<?>> containers = new HashMap<String, LoadableMod<?>>(); 91 + private final Map<String, LoadableMod<?>> enabledContainers = new HashMap<String, LoadableMod<?>>();
90 92
91 /** 93 /**
92 * Containers which have already been checked for potential mod candidates 94 * Containers which have already been checked for potential mod candidates
@@ -94,11 +96,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -94,11 +96,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
94 private final Set<LoadableMod<?>> enumeratedContainers = new HashSet<LoadableMod<?>>(); 96 private final Set<LoadableMod<?>> enumeratedContainers = new HashSet<LoadableMod<?>>();
95 97
96 /** 98 /**
97 - * Mapping of mods to mod containers  
98 - */  
99 - private final Map<String, LoadableMod<?>> modContainers = new HashMap<String, LoadableMod<?>>();  
100 -  
101 - /**  
102 * Tweaks to inject 99 * Tweaks to inject
103 */ 100 */
104 private final List<TweakContainer<File>> tweakContainers = new ArrayList<TweakContainer<File>>(); 101 private final List<TweakContainer<File>> tweakContainers = new ArrayList<TweakContainer<File>>();
@@ -106,7 +103,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -106,7 +103,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
106 /** 103 /**
107 * Other tweak-containing jars which we have injected 104 * Other tweak-containing jars which we have injected
108 */ 105 */
109 - private final List<Loadable<File>> injectedTweaks = new ArrayList<Loadable<File>>(); 106 + private final List<ModInfo<Loadable<?>>> injectedTweaks = new ArrayList<ModInfo<Loadable<?>>>();
110 107
111 /** 108 /**
112 * 109 *
@@ -236,18 +233,18 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -236,18 +233,18 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
236 * Get the list of all enumerated mod classes to load 233 * Get the list of all enumerated mod classes to load
237 */ 234 */
238 @Override 235 @Override
239 - public Collection<Class<? extends LiteMod>> getModsToLoad() 236 + public Collection<? extends ModInfo<LoadableMod<?>>> getModsToLoad()
240 { 237 {
241 this.checkState(EnumeratorState.FINALISED, "getModsToLoad"); 238 this.checkState(EnumeratorState.FINALISED, "getModsToLoad");
242 239
243 - return this.modsToLoad.values(); 240 + return Collections.unmodifiableSet(this.modsToLoad);
244 } 241 }
245 242
246 /** 243 /**
247 * @return 244 * @return
248 */ 245 */
249 @Override 246 @Override
250 - public Collection<LoadableMod<?>> getDisabledContainers() 247 + public Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers()
251 { 248 {
252 this.checkState(EnumeratorState.FINALISED, "getDisabledContainers"); 249 this.checkState(EnumeratorState.FINALISED, "getDisabledContainers");
253 250
@@ -258,7 +255,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -258,7 +255,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
258 * Get the list of injected tweak containers 255 * Get the list of injected tweak containers
259 */ 256 */
260 @Override 257 @Override
261 - public List<Loadable<File>> getInjectedTweaks() 258 + public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
262 { 259 {
263 this.checkState(EnumeratorState.FINALISED, "getInjectedTweaks"); 260 this.checkState(EnumeratorState.FINALISED, "getInjectedTweaks");
264 261
@@ -299,7 +296,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -299,7 +296,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
299 { 296 {
300 this.checkState(EnumeratorState.FINALISED, "getContainer"); 297 this.checkState(EnumeratorState.FINALISED, "getContainer");
301 298
302 - return this.containers.get(identifier); 299 + return this.enabledContainers.get(identifier);
303 } 300 }
304 301
305 /** 302 /**
@@ -311,7 +308,13 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -311,7 +308,13 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
311 { 308 {
312 this.checkState(EnumeratorState.FINALISED, "getContainer"); 309 this.checkState(EnumeratorState.FINALISED, "getContainer");
313 310
314 - return this.modContainers.containsKey(modClass.getSimpleName()) ? this.modContainers.get(modClass.getSimpleName()) : LoadableMod.NONE; 311 + for (ModInfo<LoadableMod<?>> mod : this.modsToLoad)
  312 + {
  313 + if (modClass.equals(mod.getModClass()))
  314 + return mod.getContainer();
  315 + }
  316 +
  317 + return LoadableMod.NONE;
315 } 318 }
316 319
317 /** 320 /**
@@ -324,8 +327,14 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -324,8 +327,14 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
324 public String getIdentifier(Class<? extends LiteMod> modClass) 327 public String getIdentifier(Class<? extends LiteMod> modClass)
325 { 328 {
326 String modClassName = modClass.getSimpleName(); 329 String modClassName = modClass.getSimpleName();
327 - if (!this.modContainers.containsKey(modClassName)) return LiteLoaderEnumerator.getModClassName(modClass);  
328 - return this.modContainers.get(modClassName).getIdentifier(); 330 +
  331 + for (ModInfo<LoadableMod<?>> mod : this.modsToLoad)
  332 + {
  333 + if (modClassName.equals(mod.getModClassSimpleName()))
  334 + return mod.getIdentifier();
  335 + }
  336 +
  337 + return LiteLoaderEnumerator.getModClassName(modClass);
329 } 338 }
330 339
331 @Override 340 @Override
@@ -447,7 +456,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -447,7 +456,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
447 this.checkState(EnumeratorState.DISCOVER, "registerEnabledContainer"); 456 this.checkState(EnumeratorState.DISCOVER, "registerEnabledContainer");
448 457
449 this.disabledContainers.remove(container.getIdentifier()); 458 this.disabledContainers.remove(container.getIdentifier());
450 - this.containers.put(container.getIdentifier(), container); 459 + this.enabledContainers.put(container.getIdentifier(), container);
451 } 460 }
452 461
453 /** 462 /**
@@ -457,8 +466,8 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -457,8 +466,8 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
457 { 466 {
458 this.checkState(EnumeratorState.DISCOVER, "registerDisabledContainer"); 467 this.checkState(EnumeratorState.DISCOVER, "registerDisabledContainer");
459 468
460 - this.containers.remove(container.getIdentifier());  
461 - this.disabledContainers.put(container.getIdentifier(), container); 469 + this.enabledContainers.remove(container.getIdentifier());
  470 + this.disabledContainers.put(container.getIdentifier(), new NonMod(container, false));
462 } 471 }
463 472
464 /* (non-Javadoc) 473 /* (non-Javadoc)
@@ -514,7 +523,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -514,7 +523,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
514 523
515 if (container.isExternalJar()) 524 if (container.isExternalJar())
516 { 525 {
517 - this.injectedTweaks.add(container); 526 + this.injectedTweaks.add(new NonMod(container, true));
518 } 527 }
519 528
520 String[] classPathEntries = container.getClassPathEntries(); 529 String[] classPathEntries = container.getClassPathEntries();
@@ -582,9 +591,10 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -582,9 +591,10 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
582 this.enumeratedContainers.add(container); 591 this.enumeratedContainers.add(container);
583 592
584 LinkedList<Class<? extends LiteMod>> modClasses = LiteLoaderEnumerator.<LiteMod>getSubclassesFor(container, this.classLoader, LiteMod.class, this.supportedPrefixes); 593 LinkedList<Class<? extends LiteMod>> modClasses = LiteLoaderEnumerator.<LiteMod>getSubclassesFor(container, this.classLoader, LiteMod.class, this.supportedPrefixes);
585 - for (Class<? extends LiteMod> mod : modClasses) 594 + for (Class<? extends LiteMod> modClass : modClasses)
586 { 595 {
587 - this.registerMod(mod, registerContainer ? container : null); 596 + Mod mod = new Mod(container, modClass);
  597 + this.registerMod(mod);
588 } 598 }
589 599
590 if (modClasses.size() > 0) 600 if (modClasses.size() > 0)
@@ -592,29 +602,24 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -592,29 +602,24 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
592 LiteLoaderLogger.info("Found %d potential matches", modClasses.size()); 602 LiteLoaderLogger.info("Found %d potential matches", modClasses.size());
593 603
594 this.disabledContainers.remove(container.getIdentifier()); 604 this.disabledContainers.remove(container.getIdentifier());
595 - this.containers.put(container.getIdentifier(), container); 605 + this.enabledContainers.put(container.getIdentifier(), container);
596 } 606 }
597 } 607 }
598 608
599 /* (non-Javadoc) 609 /* (non-Javadoc)
600 - * @see com.mumfrey.liteloader.core.PluggableEnumerator#addMod(java.lang.Class, com.mumfrey.liteloader.core.LoadableMod) 610 + * @see com.mumfrey.liteloader.interfaces.ModularEnumerator#registerMod(com.mumfrey.liteloader.interfaces.ModInfo)
601 */ 611 */
602 @Override 612 @Override
603 - public void registerMod(Class<? extends LiteMod> mod, LoadableMod<?> container) 613 + public void registerMod(ModInfo<LoadableMod<?>> mod)
604 { 614 {
605 this.checkState(EnumeratorState.REGISTER, "registerMod"); 615 this.checkState(EnumeratorState.REGISTER, "registerMod");
606 616
607 - if (this.modsToLoad.containsKey(mod.getSimpleName())) 617 + if (this.modsToLoad.contains(mod))
608 { 618 {
609 - LiteLoaderLogger.warning("Mod name collision for mod with class '%s', maybe you have more than one copy?", mod.getSimpleName()); 619 + LiteLoaderLogger.warning("Mod name collision for mod with class '%s', maybe you have more than one copy?", mod.getModClassSimpleName());
610 } 620 }
611 621
612 - this.modsToLoad.put(mod.getSimpleName(), mod);  
613 - if (container != null)  
614 - {  
615 - this.modContainers.put(mod.getSimpleName(), container);  
616 - container.addContainedMod(LiteLoaderEnumerator.getModClassName(mod));  
617 - } 622 + this.modsToLoad.add(mod);
618 } 623 }
619 624
620 /** 625 /**
java/common/com/mumfrey/liteloader/core/LiteLoaderMods.java
@@ -71,22 +71,24 @@ public class LiteLoaderMods @@ -71,22 +71,24 @@ public class LiteLoaderMods
71 /** 71 /**
72 * Global list of mods which we can load 72 * Global list of mods which we can load
73 */ 73 */
74 - protected final LinkedList<LiteMod> allMods = new LinkedList<LiteMod>(); 74 + protected final LinkedList<Mod> allMods = new LinkedList<Mod>();
75 75
76 /** 76 /**
77 * Global list of mods which are still waiting for initialisiation 77 * Global list of mods which are still waiting for initialisiation
78 */ 78 */
79 - protected final LinkedList<LiteMod> initMods = new LinkedList<LiteMod>(); 79 + protected final LinkedList<Mod> initMods = new LinkedList<Mod>();
80 80
81 /** 81 /**
82 * Global list of mods which we have loaded 82 * Global list of mods which we have loaded
83 */ 83 */
84 - protected final LinkedList<LiteMod> loadedMods = new LinkedList<LiteMod>(); 84 + protected final LinkedList<Mod> loadedMods = new LinkedList<Mod>();
85 85
86 /** 86 /**
87 * Mods which are loaded but disabled 87 * Mods which are loaded but disabled
88 */ 88 */
89 - protected final LinkedList<Loadable<?>> disabledMods = new LinkedList<Loadable<?>>(); 89 + protected final LinkedList<NonMod> disabledMods = new LinkedList<NonMod>();
  90 +
  91 + private int startupErrorCount;
90 92
91 LiteLoaderMods(LiteLoader loader, LoaderEnvironment environment, LoaderProperties properties, ConfigManager configManager) 93 LiteLoaderMods(LiteLoader loader, LoaderEnvironment environment, LoaderProperties properties, ConfigManager configManager)
92 { 94 {
@@ -97,12 +99,13 @@ public class LiteLoaderMods @@ -97,12 +99,13 @@ public class LiteLoaderMods
97 this.configManager = configManager; 99 this.configManager = configManager;
98 } 100 }
99 101
  102 + @SuppressWarnings("unchecked")
100 void init(List<ModLoadObserver> observers) 103 void init(List<ModLoadObserver> observers)
101 { 104 {
102 this.observers = observers; 105 this.observers = observers;
103 - this.disabledMods.addAll(this.enumerator.getDisabledContainers()); 106 + this.disabledMods.addAll((Collection<? extends NonMod>)this.enumerator.getDisabledContainers());
104 } 107 }
105 - 108 +
106 void onPostInit() 109 void onPostInit()
107 { 110 {
108 this.updateSharedModList(); 111 this.updateSharedModList();
@@ -115,9 +118,9 @@ public class LiteLoaderMods @@ -115,9 +118,9 @@ public class LiteLoaderMods
115 return this.environment.getEnabledModsList(); 118 return this.environment.getEnabledModsList();
116 } 119 }
117 120
118 - public LinkedList<LiteMod> getAllMods() 121 + public List<Mod> getAllMods()
119 { 122 {
120 - return this.allMods; 123 + return Collections.unmodifiableList(this.allMods);
121 } 124 }
122 125
123 /** 126 /**
@@ -133,25 +136,41 @@ public class LiteLoaderMods @@ -133,25 +136,41 @@ public class LiteLoaderMods
133 /** 136 /**
134 * Get a list containing all loaded mods 137 * Get a list containing all loaded mods
135 */ 138 */
136 - public List<LiteMod> getLoadedMods() 139 + public List<? extends ModInfo<LoadableMod<?>>> getLoadedMods()
137 { 140 {
138 - return Collections.unmodifiableList(this.loadedMods); 141 + return this.loadedMods;
139 } 142 }
140 143
141 /** 144 /**
142 * Get a list containing all mod files which were NOT loaded 145 * Get a list containing all mod files which were NOT loaded
143 */ 146 */
144 - public List<Loadable<?>> getDisabledMods() 147 + public List<? extends ModInfo<Loadable<?>>> getDisabledMods()
145 { 148 {
146 - return Collections.unmodifiableList(this.disabledMods); 149 + return this.disabledMods;
147 } 150 }
148 151
149 /** 152 /**
150 * Get the list of injected tweak containers 153 * Get the list of injected tweak containers
151 */ 154 */
152 - public Collection<Loadable<File>> getInjectedTweaks() 155 + public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
  156 + {
  157 + return this.enumerator.getInjectedTweaks();
  158 + }
  159 +
  160 + public int getStartupErrorCount()
153 { 161 {
154 - return Collections.unmodifiableCollection(this.enumerator.getInjectedTweaks()); 162 + return this.startupErrorCount;
  163 + }
  164 +
  165 + public ModInfo<?> getModInfo(LiteMod instance)
  166 + {
  167 + for (Mod mod : this.allMods)
  168 + {
  169 + if (instance == mod.getMod())
  170 + return mod;
  171 + }
  172 +
  173 + return null;
155 } 174 }
156 175
157 /** 176 /**
@@ -186,13 +205,10 @@ public class LiteLoaderMods @@ -186,13 +205,10 @@ public class LiteLoaderMods
186 throw new IllegalArgumentException("Attempted to get a reference to a mod without specifying a mod name"); 205 throw new IllegalArgumentException("Attempted to get a reference to a mod without specifying a mod name");
187 } 206 }
188 207
189 - for (LiteMod mod : this.allMods) 208 + for (Mod mod : this.allMods)
190 { 209 {
191 - Class<? extends LiteMod> modClass = mod.getClass();  
192 - String modId = this.enumerator.getIdentifier(modClass);  
193 -  
194 - if (modName.equalsIgnoreCase(mod.getName()) || modName.equalsIgnoreCase(modId) || modName.equalsIgnoreCase(modClass.getSimpleName()))  
195 - return (T)mod; 210 + if (mod.matchesName(modName))
  211 + return (T)mod.getMod();
196 } 212 }
197 213
198 return null; 214 return null;
@@ -207,9 +223,9 @@ public class LiteLoaderMods @@ -207,9 +223,9 @@ public class LiteLoaderMods
207 @SuppressWarnings("unchecked") 223 @SuppressWarnings("unchecked")
208 public <T extends LiteMod> T getMod(Class<T> modClass) 224 public <T extends LiteMod> T getMod(Class<T> modClass)
209 { 225 {
210 - for (LiteMod mod : this.allMods) 226 + for (Mod mod : this.allMods)
211 { 227 {
212 - if (mod.getClass().equals(modClass)) 228 + if (mod.getModClass().equals(modClass))
213 return (T)mod; 229 return (T)mod;
214 } 230 }
215 231
@@ -226,12 +242,10 @@ public class LiteLoaderMods @@ -226,12 +242,10 @@ public class LiteLoaderMods
226 { 242 {
227 if (identifier == null) return null; 243 if (identifier == null) return null;
228 244
229 - for (LiteMod mod : this.allMods) 245 + for (Mod mod : this.allMods)
230 { 246 {
231 - if (identifier.equalsIgnoreCase(this.enumerator.getIdentifier(mod.getClass())))  
232 - {  
233 - return mod.getClass();  
234 - } 247 + if (mod.matchesIdentifier(identifier))
  248 + return mod.getModClass();
235 } 249 }
236 250
237 return null; 251 return null;
@@ -368,16 +382,14 @@ public class LiteLoaderMods @@ -368,16 +382,14 @@ public class LiteLoaderMods
368 * @param modName 382 * @param modName
369 * @return 383 * @return
370 */ 384 */
371 - public boolean isModActive(String modName) 385 + public boolean isModActive(String identifier)
372 { 386 {
373 - if (modName == null) return false; 387 + if (identifier == null) return false;
374 388
375 - for (LiteMod mod : this.loadedMods) 389 + for (Mod mod : this.loadedMods)
376 { 390 {
377 - if (modName.equalsIgnoreCase(this.enumerator.getIdentifier(mod.getClass())))  
378 - { 391 + if (mod.matchesIdentifier(identifier))
379 return true; 392 return true;
380 - }  
381 } 393 }
382 394
383 return false; 395 return false;
@@ -392,14 +404,14 @@ public class LiteLoaderMods @@ -392,14 +404,14 @@ public class LiteLoaderMods
392 { 404 {
393 LoadingProgress.incTotalLiteLoaderProgress(this.enumerator.getModsToLoad().size()); 405 LoadingProgress.incTotalLiteLoaderProgress(this.enumerator.getModsToLoad().size());
394 406
395 - for (Class<? extends LiteMod> mod : this.enumerator.getModsToLoad()) 407 + for (ModInfo<LoadableMod<?>> mod : this.enumerator.getModsToLoad())
396 { 408 {
397 - LoadingProgress.incLiteLoaderProgress("Loading mod from %s...", mod.getName());  
398 - LoadableMod<?> container = this.enumerator.getContainer(mod); 409 + LoadingProgress.incLiteLoaderProgress("Loading mod from %s...", mod.getModClassSimpleName());
  410 + LoadableMod<?> container = mod.getContainer();
399 411
400 try 412 try
401 { 413 {
402 - String identifier = this.enumerator.getIdentifier(mod); 414 + String identifier = mod.getIdentifier();
403 if (identifier == null || this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), identifier)) 415 if (identifier == null || this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), identifier))
404 { 416 {
405 if (!this.enumerator.checkDependencies(container)) 417 if (!this.enumerator.checkDependencies(container))
@@ -408,7 +420,14 @@ public class LiteLoaderMods @@ -408,7 +420,14 @@ public class LiteLoaderMods
408 continue; 420 continue;
409 } 421 }
410 422
411 - this.loadMod(identifier, mod, container); 423 + if (mod instanceof Mod)
  424 + {
  425 + this.loadMod((Mod)mod);
  426 + }
  427 + else
  428 + {
  429 + this.loadMod(identifier, mod.getModClass(), container);
  430 + }
412 } 431 }
413 else 432 else
414 { 433 {
@@ -417,33 +436,44 @@ public class LiteLoaderMods @@ -417,33 +436,44 @@ public class LiteLoaderMods
417 } 436 }
418 catch (Throwable th) 437 catch (Throwable th)
419 { 438 {
420 - this.onModLoadFailed(container, mod.getName(), "an error occurred", th); 439 + this.onModLoadFailed(container, mod.getModClassName(), "an error occurred", th);
421 } 440 }
422 } 441 }
423 } 442 }
424 443
425 /** 444 /**
426 * @param identifier 445 * @param identifier
427 - * @param mod 446 + * @param modClass
428 * @param container 447 * @param container
429 * @throws InstantiationException 448 * @throws InstantiationException
430 * @throws IllegalAccessException 449 * @throws IllegalAccessException
431 */ 450 */
432 - void loadMod(String identifier, Class<? extends LiteMod> mod, LoadableMod<?> container) throws InstantiationException, IllegalAccessException 451 + void loadMod(String identifier, Class<? extends LiteMod> modClass, LoadableMod<?> container) throws InstantiationException, IllegalAccessException
433 { 452 {
434 - LiteLoaderLogger.info("Loading mod from %s", mod.getName()); 453 + Mod mod = new Mod(container, modClass, identifier);
  454 + this.loadMod(mod);
  455 + }
  456 +
  457 + /**
  458 + * @param mod
  459 + * @throws InstantiationException
  460 + * @throws IllegalAccessException
  461 + */
  462 + void loadMod(Mod mod) throws InstantiationException, IllegalAccessException
  463 + {
  464 + LiteLoaderLogger.info("Loading mod from %s", mod.getModClassName());
435 465
436 LiteMod newMod = mod.newInstance(); 466 LiteMod newMod = mod.newInstance();
437 467
438 - this.onModLoaded(newMod); 468 + this.onModLoaded(mod);
439 469
440 - String modName = newMod.getName();  
441 - if (modName == null && identifier != null) modName = identifier; 470 + String modName = mod.getDisplayName();
442 LiteLoaderLogger.info("Successfully added mod %s version %s", modName, newMod.getVersion()); 471 LiteLoaderLogger.info("Successfully added mod %s version %s", modName, newMod.getVersion());
443 472
444 // Register the mod as a resource pack if the container exists 473 // Register the mod as a resource pack if the container exists
445 - if (container != null) 474 + if (mod.hasContainer())
446 { 475 {
  476 + LoadableMod<?> container = mod.getContainer();
447 LiteLoaderLogger.info("Adding \"%s\" to active resource pack set", container.getLocation()); 477 LiteLoaderLogger.info("Adding \"%s\" to active resource pack set", container.getLocation());
448 if (modName != null) 478 if (modName != null)
449 { 479 {
@@ -460,11 +490,11 @@ public class LiteLoaderMods @@ -460,11 +490,11 @@ public class LiteLoaderMods
460 /** 490 /**
461 * @param mod 491 * @param mod
462 */ 492 */
463 - void onModLoaded(LiteMod mod) 493 + void onModLoaded(Mod mod)
464 { 494 {
465 for (ModLoadObserver observer : this.observers) 495 for (ModLoadObserver observer : this.observers)
466 { 496 {
467 - observer.onModLoaded(mod); 497 + observer.onModLoaded(mod.getMod());
468 } 498 }
469 499
470 this.allMods.add(mod); 500 this.allMods.add(mod);
@@ -485,7 +515,7 @@ public class LiteLoaderMods @@ -485,7 +515,7 @@ public class LiteLoaderMods
485 515
486 if (container != LoadableMod.NONE && !this.disabledMods.contains(container)) 516 if (container != LoadableMod.NONE && !this.disabledMods.contains(container))
487 { 517 {
488 - this.disabledMods.add(container); 518 + this.disabledMods.add(new NonMod(container, false));
489 } 519 }
490 520
491 for (ModLoadObserver observer : this.observers) 521 for (ModLoadObserver observer : this.observers)
@@ -504,7 +534,7 @@ public class LiteLoaderMods @@ -504,7 +534,7 @@ public class LiteLoaderMods
504 534
505 while (this.initMods.size() > 0) 535 while (this.initMods.size() > 0)
506 { 536 {
507 - LiteMod mod = this.initMods.removeFirst(); 537 + Mod mod = this.initMods.removeFirst();
508 538
509 try 539 try
510 { 540 {
@@ -513,8 +543,8 @@ public class LiteLoaderMods @@ -513,8 +543,8 @@ public class LiteLoaderMods
513 } 543 }
514 catch (Throwable th) 544 catch (Throwable th)
515 { 545 {
516 - LiteLoaderLogger.warning(th, "Error initialising mod '%s'", mod.getName());  
517 - this.allMods.remove(mod); 546 + this.registerModStartupError(mod, th);
  547 + LiteLoaderLogger.warning(th, "Error initialising mod '%s'", mod.getDisplayName());
518 } 548 }
519 } 549 }
520 550
@@ -524,70 +554,73 @@ public class LiteLoaderMods @@ -524,70 +554,73 @@ public class LiteLoaderMods
524 /** 554 /**
525 * @param mod 555 * @param mod
526 */ 556 */
527 - private void initMod(LiteMod mod) 557 + private void initMod(Mod mod)
528 { 558 {
529 - LiteLoaderLogger.info("Initialising mod %s version %s", mod.getName(), mod.getVersion());  
530 - LoadingProgress.incLiteLoaderProgress("Initialising mod %s version %s...", mod.getName(), mod.getVersion()); 559 + LiteMod instance = mod.getMod();
531 560
532 - this.onPreInitMod(mod); 561 + LiteLoaderLogger.info("Initialising mod %s version %s", instance.getName(), instance.getVersion());
  562 + LoadingProgress.incLiteLoaderProgress("Initialising mod %s version %s...", instance.getName(), instance.getVersion());
  563 +
  564 + this.onPreInitMod(instance);
533 565
534 // initialise the mod 566 // initialise the mod
535 - mod.init(LiteLoader.getCommonConfigFolder()); 567 + instance.init(LiteLoader.getCommonConfigFolder());
  568 +
  569 + this.onPostInitMod(instance);
536 570
537 - this.onPostInitMod(mod); 571 + this.loadedMods.add(mod);
  572 + this.loadedModsList += String.format("\n - %s version %s", mod.getDisplayName(), mod.getVersion());
538 } 573 }
539 574
540 /** 575 /**
541 - * @param mod 576 + * @param instance
542 */ 577 */
543 - private void onPreInitMod(LiteMod mod) 578 + private void onPreInitMod(LiteMod instance)
544 { 579 {
545 for (ModLoadObserver observer : this.observers) 580 for (ModLoadObserver observer : this.observers)
546 { 581 {
547 - observer.onPreInitMod(mod); 582 + observer.onPreInitMod(instance);
548 } 583 }
549 584
550 // register mod config panel if configurable 585 // register mod config panel if configurable
551 - this.configManager.registerMod(mod); 586 + this.configManager.registerMod(instance);
552 587
553 try 588 try
554 { 589 {
555 - this.handleModVersionUpgrade(mod); 590 + this.handleModVersionUpgrade(instance);
556 } 591 }
557 catch (Throwable th) 592 catch (Throwable th)
558 { 593 {
559 - LiteLoaderLogger.warning("Error performing settings upgrade for %s. Settings may not be properly migrated", mod.getName()); 594 + LiteLoaderLogger.warning("Error performing settings upgrade for %s. Settings may not be properly migrated", instance.getName());
560 } 595 }
561 596
562 // Init mod config if there is any 597 // Init mod config if there is any
563 - this.configManager.initConfig(mod); 598 + this.configManager.initConfig(instance);
564 } 599 }
565 600
566 /** 601 /**
567 - * @param mod 602 + * @param instance
568 */ 603 */
569 - private void onPostInitMod(LiteMod mod) 604 + private void onPostInitMod(LiteMod instance)
570 { 605 {
  606 + System.err.println("on post init mod " + instance.getName());
571 for (ModLoadObserver observer : this.observers) 607 for (ModLoadObserver observer : this.observers)
572 { 608 {
573 - observer.onPostInitMod(mod); 609 + observer.onPostInitMod(instance);
574 } 610 }
575 611
576 // add the mod to all relevant listener queues 612 // add the mod to all relevant listener queues
577 - LiteLoader.getInterfaceManager().offer(mod); 613 + LiteLoader.getInterfaceManager().offer(instance);
578 614
579 - this.loader.onPostInitMod(mod);  
580 -  
581 - this.loadedMods.add(mod);  
582 - this.loadedModsList += String.format("\n - %s version %s", mod.getName(), mod.getVersion()); 615 + this.loader.onPostInitMod(instance);
583 } 616 }
584 617
585 /** 618 /**
586 - * @param mod 619 + * @param instance
587 */ 620 */
588 - private void handleModVersionUpgrade(LiteMod mod) 621 + private void handleModVersionUpgrade(LiteMod instance)
589 { 622 {
590 - String modKey = this.getModNameForConfig(mod.getClass(), mod.getName()); 623 + String modKey = this.getModNameForConfig(instance.getClass(), instance.getName());
591 624
592 int currentRevision = LiteLoaderVersion.CURRENT.getLoaderRevision(); 625 int currentRevision = LiteLoaderVersion.CURRENT.getLoaderRevision();
593 int lastKnownRevision = this.properties.getLastKnownModRevision(modKey); 626 int lastKnownRevision = this.properties.getLastKnownModRevision(modKey);
@@ -598,25 +631,25 @@ public class LiteLoaderMods @@ -598,25 +631,25 @@ public class LiteLoaderMods
598 File newConfigPath = LiteLoader.getConfigFolder(); 631 File newConfigPath = LiteLoader.getConfigFolder();
599 File oldConfigPath = this.environment.inflectVersionedConfigPath(lastModVersion); 632 File oldConfigPath = this.environment.inflectVersionedConfigPath(lastModVersion);
600 633
601 - LiteLoaderLogger.info("Performing config upgrade for mod %s. Upgrading %s to %s...", mod.getName(), lastModVersion, LiteLoaderVersion.CURRENT); 634 + LiteLoaderLogger.info("Performing config upgrade for mod %s. Upgrading %s to %s...", instance.getName(), lastModVersion, LiteLoaderVersion.CURRENT);
602 635
603 for (ModLoadObserver observer : this.observers) 636 for (ModLoadObserver observer : this.observers)
604 { 637 {
605 - observer.onMigrateModConfig(mod, newConfigPath, oldConfigPath); 638 + observer.onMigrateModConfig(instance, newConfigPath, oldConfigPath);
606 } 639 }
607 640
608 // Migrate versioned config if any is present 641 // Migrate versioned config if any is present
609 - this.configManager.migrateModConfig(mod, newConfigPath, oldConfigPath); 642 + this.configManager.migrateModConfig(instance, newConfigPath, oldConfigPath);
610 643
611 // Let the mod upgrade 644 // Let the mod upgrade
612 - mod.upgradeSettings(LiteLoaderVersion.CURRENT.getMinecraftVersion(), newConfigPath, oldConfigPath); 645 + instance.upgradeSettings(LiteLoaderVersion.CURRENT.getMinecraftVersion(), newConfigPath, oldConfigPath);
613 646
614 this.properties.storeLastKnownModRevision(modKey); 647 this.properties.storeLastKnownModRevision(modKey);
615 - LiteLoaderLogger.info("Config upgrade succeeded for mod %s", mod.getName()); 648 + LiteLoaderLogger.info("Config upgrade succeeded for mod %s", instance.getName());
616 } 649 }
617 - else if (currentRevision < lastKnownRevision && ConfigManager.getConfigStrategy(mod) == ConfigStrategy.Unversioned) 650 + else if (currentRevision < lastKnownRevision && ConfigManager.getConfigStrategy(instance) == ConfigStrategy.Unversioned)
618 { 651 {
619 - LiteLoaderLogger.warning("Mod %s has config from unknown loader revision %d. This may cause unexpected behaviour.", mod.getName(), lastKnownRevision); 652 + LiteLoaderLogger.warning("Mod %s has config from unknown loader revision %d. This may cause unexpected behaviour.", instance.getName(), lastKnownRevision);
620 } 653 }
621 } 654 }
622 655
@@ -637,30 +670,49 @@ public class LiteLoaderMods @@ -637,30 +670,49 @@ public class LiteLoaderMods
637 return String.format("version.%s", modName.toLowerCase().replaceAll("[^a-z0-9_\\-\\.]", "")); 670 return String.format("version.%s", modName.toLowerCase().replaceAll("[^a-z0-9_\\-\\.]", ""));
638 } 671 }
639 672
  673 + /**
  674 + * @param instance
  675 + * @param th
  676 + */
  677 + public void onLateInitFailed(LiteMod instance, Throwable th)
  678 + {
  679 + ModInfo<?> mod = this.getModInfo(instance);
  680 + if (mod != null)
  681 + {
  682 + this.registerModStartupError(mod, th);
  683 + this.registerModStartupError(mod, th);
  684 + }
  685 + }
  686 +
  687 + private void registerModStartupError(ModInfo<?> mod, Throwable th)
  688 + {
  689 + this.startupErrorCount++;
  690 + mod.registerStartupError(th);
  691 + }
  692 +
640 void updateSharedModList() 693 void updateSharedModList()
641 { 694 {
642 Map<String, Map<String, String>> modList = this.enumerator.getSharedModList(); 695 Map<String, Map<String, String>> modList = this.enumerator.getSharedModList();
643 if (modList == null) return; 696 if (modList == null) return;
644 697
645 - for (LiteMod mod : this.allMods) 698 + for (Mod mod : this.allMods)
646 { 699 {
647 - String modKey = String.format("%s:%s", LiteLoaderMods.MOD_SYSTEM, this.loader.getModIdentifier(mod)); 700 + String modKey = String.format("%s:%s", LiteLoaderMods.MOD_SYSTEM, mod.getIdentifier());
648 modList.put(modKey, this.packModInfoToMap(mod)); 701 modList.put(modKey, this.packModInfoToMap(mod));
649 } 702 }
650 } 703 }
651 704
652 - private Map<String, String> packModInfoToMap(LiteMod mod) 705 + private Map<String, String> packModInfoToMap(Mod mod)
653 { 706 {
654 Map<String, String> modInfo = new HashMap<String, String>(); 707 Map<String, String> modInfo = new HashMap<String, String>();
655 - LoadableMod<?> container = this.loader.getModContainer(mod);  
656 708
657 modInfo.put("modsystem", LiteLoaderMods.MOD_SYSTEM); 709 modInfo.put("modsystem", LiteLoaderMods.MOD_SYSTEM);
658 - modInfo.put("id", this.loader.getModIdentifier(mod)); 710 + modInfo.put("id", mod.getIdentifier());
659 modInfo.put("version", mod.getVersion()); 711 modInfo.put("version", mod.getVersion());
660 - modInfo.put("name", mod.getName());  
661 - modInfo.put("url", container.getMetaValue("url", ""));  
662 - modInfo.put("authors", container.getAuthor());  
663 - modInfo.put("description", container.getDescription(LiteLoaderEnumerator.getModClassName(mod))); 712 + modInfo.put("name", mod.getDisplayName());
  713 + modInfo.put("url", mod.getURL());
  714 + modInfo.put("authors", mod.getAuthor());
  715 + modInfo.put("description", mod.getDescription());
664 716
665 return modInfo; 717 return modInfo;
666 } 718 }
java/common/com/mumfrey/liteloader/core/LiteLoaderVersion.java
@@ -9,7 +9,7 @@ import com.mumfrey.liteloader.update.UpdateSite; @@ -9,7 +9,7 @@ import com.mumfrey.liteloader.update.UpdateSite;
9 * LiteLoader version table 9 * LiteLoader version table
10 * 10 *
11 * @author Adam Mummery-Smith 11 * @author Adam Mummery-Smith
12 - * @version 1.7.10_02 12 + * @version 1.7.10_03
13 */ 13 */
14 public enum LiteLoaderVersion 14 public enum LiteLoaderVersion
15 { 15 {
@@ -37,7 +37,8 @@ public enum LiteLoaderVersion @@ -37,7 +37,8 @@ public enum LiteLoaderVersion
37 MC_1_7_2_R6(26, 0, "1.7.2", "1.7.2_06", "1.7.2_06"), 37 MC_1_7_2_R6(26, 0, "1.7.2", "1.7.2_06", "1.7.2_06"),
38 MC_1_7_10_R0(27, 1404330030, "1.7.10", "1.7.10", "1.7.10"), 38 MC_1_7_10_R0(27, 1404330030, "1.7.10", "1.7.10", "1.7.10"),
39 MC_1_7_10_R1(28, 1404673785, "1.7.10", "1.7.10_01", "1.7.10"), 39 MC_1_7_10_R1(28, 1404673785, "1.7.10", "1.7.10_01", "1.7.10"),
40 - MC_1_7_10_R2(29, 1405369406, "1.7.10", "1.7.10_02", "1.7.10"); 40 + MC_1_7_10_R2(29, 1405369406, "1.7.10", "1.7.10_02", "1.7.10"),
  41 + MC_1_7_10_R3(30, 0, "1.7.10", "1.7.10_03", "1.7.10");
41 42
42 /** 43 /**
43 * Current loader version 44 * Current loader version
java/common/com/mumfrey/liteloader/core/Mod.java 0 → 100644
  1 +package com.mumfrey.liteloader.core;
  2 +
  3 +import com.mumfrey.liteloader.LiteMod;
  4 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  5 +
  6 +/**
  7 + * ModInfo for an active mod instance
  8 + *
  9 + * @author Adam Mummery-Smith
  10 + */
  11 +class Mod extends ModInfo<LoadableMod<?>>
  12 +{
  13 + /**
  14 + * Mod class
  15 + */
  16 + private final Class<? extends LiteMod> modClass;
  17 +
  18 + /**
  19 + * Mod's key identifier, usually the class simplename
  20 + */
  21 + private final String key;
  22 +
  23 + /**
  24 + * Mod's identifier (from metadata)
  25 + */
  26 + private final String identifier;
  27 +
  28 + /**
  29 + * Mod instance
  30 + */
  31 + private LiteMod instance;
  32 +
  33 + /**
  34 + * Mod display name, initially read from metadata then replaced with real name once instanced
  35 + */
  36 + private String name;
  37 +
  38 + /**
  39 + * Mod display name, initially read from version then replaced with real version once instanced
  40 + */
  41 + private String version;
  42 +
  43 + /**
  44 + * @param container
  45 + * @param modClass
  46 + */
  47 + public Mod(LoadableMod<?> container, Class<? extends LiteMod> modClass)
  48 + {
  49 + this(container, modClass, container != null ? container.getIdentifier() : LiteLoaderEnumerator.getModClassName(modClass));
  50 + }
  51 +
  52 + /**
  53 + * @param container
  54 + * @param modClass
  55 + * @param identifier
  56 + */
  57 + public Mod(LoadableMod<?> container, Class<? extends LiteMod> modClass, String identifier)
  58 + {
  59 + super(container != null ? container : LoadableMod.NONE, true);
  60 +
  61 + this.modClass = modClass;
  62 + this.key = modClass.getSimpleName();
  63 + this.identifier = identifier.toLowerCase();
  64 + this.name = this.container.getDisplayName();
  65 + this.version = this.container.getVersion();
  66 + }
  67 +
  68 + /**
  69 + * Called by the mod manager to instance the mod
  70 + *
  71 + * @return
  72 + * @throws InstantiationException
  73 + * @throws IllegalAccessException
  74 + */
  75 + LiteMod newInstance() throws InstantiationException, IllegalAccessException
  76 + {
  77 + if (this.instance != null)
  78 + {
  79 + throw new InstantiationException("Attempted to create an instance of " + this.key + " but the instance was already created");
  80 + }
  81 +
  82 + this.instance = this.modClass.newInstance();
  83 +
  84 + String name = this.instance.getName();
  85 + if (name != null) this.name = name;
  86 +
  87 + String version = this.instance.getVersion();
  88 + if (version != null) this.version = version;
  89 +
  90 + return this.instance;
  91 + }
  92 +
  93 + /* (non-Javadoc)
  94 + * @see com.mumfrey.liteloader.core.ModInfo#isToggleable()
  95 + */
  96 + @Override
  97 + public boolean isToggleable()
  98 + {
  99 + return true;
  100 + }
  101 +
  102 + /* (non-Javadoc)
  103 + * @see com.mumfrey.liteloader.core.ModInfo#getMod()
  104 + */
  105 + @Override
  106 + public LiteMod getMod()
  107 + {
  108 + return this.instance;
  109 + }
  110 +
  111 + /* (non-Javadoc)
  112 + * @see com.mumfrey.liteloader.core.ModInfo#getModClass()
  113 + */
  114 + @Override
  115 + public Class<? extends LiteMod> getModClass()
  116 + {
  117 + return this.modClass;
  118 + }
  119 +
  120 + /* (non-Javadoc)
  121 + * @see com.mumfrey.liteloader.core.ModInfo#getDisplayName()
  122 + */
  123 + @Override
  124 + public String getDisplayName()
  125 + {
  126 + return this.name;
  127 + }
  128 +
  129 + /* (non-Javadoc)
  130 + * @see com.mumfrey.liteloader.core.ModInfo#getVersion()
  131 + */
  132 + @Override
  133 + public String getVersion()
  134 + {
  135 + return this.version;
  136 + }
  137 +
  138 + /* (non-Javadoc)
  139 + * @see com.mumfrey.liteloader.core.ModInfo#getModClassName()
  140 + */
  141 + @Override
  142 + public String getModClassName()
  143 + {
  144 + return this.modClass.getName();
  145 + }
  146 +
  147 + /* (non-Javadoc)
  148 + * @see com.mumfrey.liteloader.core.ModInfo#getModClassSimpleName()
  149 + */
  150 + @Override
  151 + public String getModClassSimpleName()
  152 + {
  153 + return this.key;
  154 + }
  155 +
  156 + /* (non-Javadoc)
  157 + * @see com.mumfrey.liteloader.core.ModInfo#getIdentifier()
  158 + */
  159 + @Override
  160 + public String getIdentifier()
  161 + {
  162 + return this.identifier;
  163 + }
  164 +
  165 + /**
  166 + * Get whether any of the valid identifiers match the supplied name
  167 + *
  168 + * @param name
  169 + * @return
  170 + */
  171 + public boolean matchesName(String name)
  172 + {
  173 + return (name.equalsIgnoreCase(this.instance.getName()) || name.equalsIgnoreCase(this.identifier) || name.equalsIgnoreCase(this.key));
  174 + }
  175 +
  176 + /**
  177 + * Get whether ths mod identifier matches the supplied identifier
  178 + *
  179 + * @param identifier
  180 + * @return
  181 + */
  182 + public boolean matchesIdentifier(String identifier)
  183 + {
  184 + return identifier.equalsIgnoreCase(this.identifier);
  185 + }
  186 +
  187 + /* (non-Javadoc)
  188 + * @see java.lang.Object#equals(java.lang.Object)
  189 + */
  190 + @Override
  191 + public boolean equals(Object other)
  192 + {
  193 + if (other == null) return false;
  194 + if (!(other instanceof Mod)) return false;
  195 + return ((Mod)other).key.equals(this.key);
  196 + }
  197 +
  198 + /* (non-Javadoc)
  199 + * @see java.lang.Object#hashCode()
  200 + */
  201 + @Override
  202 + public int hashCode()
  203 + {
  204 + return this.key.hashCode();
  205 + }
  206 +}
java/common/com/mumfrey/liteloader/core/ModInfo.java 0 → 100644
  1 +package com.mumfrey.liteloader.core;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.Collections;
  5 +import java.util.List;
  6 +import java.util.Set;
  7 +
  8 +import com.google.common.collect.ImmutableSet;
  9 +import com.mumfrey.liteloader.LiteMod;
  10 +import com.mumfrey.liteloader.interfaces.Loadable;
  11 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  12 +import com.mumfrey.liteloader.interfaces.TweakContainer;
  13 +
  14 +/**
  15 + * ModInfo is used to keep runtime information about a mod (or other injectable) together with relevant
  16 + * environmental information (such as startup errors) and its container.
  17 + *
  18 + * @author Adam Mummery-Smith
  19 + *
  20 + * @param <TContainer> type of container
  21 + */
  22 +public abstract class ModInfo<TContainer extends Loadable<?>>
  23 +{
  24 + /**
  25 + * List of built-in APIs, used to filter for 3rd-party APIs
  26 + */
  27 + protected static final Set<String> BUILT_IN_APIS = ImmutableSet.of("liteloader");
  28 +
  29 + /**
  30 + * Container instance
  31 + */
  32 + protected final TContainer container;
  33 +
  34 + /**
  35 + * True if this mod is active/injected or not active/errored
  36 + */
  37 + protected final boolean active;
  38 +
  39 + /**
  40 + * Startup errors encountered whilst loading this mod
  41 + */
  42 + private final List<Throwable> startupErrors = new ArrayList<Throwable>();
  43 +
  44 + /**
  45 + * @param container
  46 + * @param active
  47 + */
  48 + protected ModInfo(TContainer container, boolean active)
  49 + {
  50 + this.container = container;
  51 + this.active = active;
  52 + }
  53 +
  54 + /**
  55 + * Get whether this mod is currently active
  56 + */
  57 + public final boolean isActive()
  58 + {
  59 + return this.active;
  60 + }
  61 +
  62 + /**
  63 + * Get whether this mod can be toggled
  64 + */
  65 + public boolean isToggleable()
  66 + {
  67 + return this.container.isToggleable();
  68 + }
  69 +
  70 + /**
  71 + * Get whether this mod has a container
  72 + */
  73 + public final boolean hasContainer()
  74 + {
  75 + return this.container != LoadableMod.NONE;
  76 + }
  77 +
  78 + /**
  79 + * Get the container for this mod
  80 + */
  81 + public final TContainer getContainer()
  82 + {
  83 + return this.container;
  84 + }
  85 +
  86 + /**
  87 + * Callback to allow the mod manager to register a startup error
  88 + */
  89 + void registerStartupError(Throwable th)
  90 + {
  91 + this.startupErrors.add(th);
  92 + }
  93 +
  94 + /**
  95 + * Get startup errors for this instance
  96 + */
  97 + public List<Throwable> getStartupErrors()
  98 + {
  99 + return Collections.unmodifiableList(this.startupErrors);
  100 + }
  101 +
  102 + /**
  103 + * Get the display name for this mod
  104 + */
  105 + public String getDisplayName()
  106 + {
  107 + return this.container.getDisplayName();
  108 + }
  109 +
  110 + /**
  111 + * Get the mod version
  112 + */
  113 + public String getVersion()
  114 + {
  115 + return this.container.getVersion();
  116 + }
  117 +
  118 + /**
  119 + * Get the nod identifier
  120 + */
  121 + public String getIdentifier()
  122 + {
  123 + return this.container.getIdentifier();
  124 + }
  125 +
  126 + /**
  127 + * Get the mod URL
  128 + */
  129 + public String getURL()
  130 + {
  131 + return this.container instanceof LoadableMod<?> ? ((LoadableMod<?>)this.container).getMetaValue("url", "") : null;
  132 + }
  133 +
  134 + /**
  135 + * Get the mod author(s)
  136 + */
  137 + public String getAuthor()
  138 + {
  139 + return this.container.getAuthor();
  140 + }
  141 +
  142 + /**
  143 + * Get the mod description
  144 + */
  145 + public String getDescription()
  146 + {
  147 + return this.container.getDescription(null);
  148 + }
  149 +
  150 + /**
  151 + * If this container has a tweak
  152 + */
  153 + public boolean hasTweakClass()
  154 + {
  155 + return (this.container instanceof TweakContainer && ((TweakContainer<?>)this.container).hasTweakClass());
  156 + }
  157 +
  158 + /**
  159 + * If this has transformers (NOT robots in disguise, the other kind)
  160 + */
  161 + public boolean hasClassTransformers()
  162 + {
  163 + return (this.container instanceof TweakContainer && ((TweakContainer<?>)this.container).hasClassTransformers());
  164 + }
  165 +
  166 + /**
  167 + * Get whether this mod uses external (3rd-party) API
  168 + */
  169 + public boolean usesAPI()
  170 + {
  171 + if (this.container instanceof LoadableMod<?>)
  172 + {
  173 + for (String requiredAPI : ((LoadableMod<?>)this.container).getRequiredAPIs())
  174 + {
  175 + if (!ModInfo.BUILT_IN_APIS.contains(requiredAPI))
  176 + return true;
  177 + }
  178 + }
  179 +
  180 + return false;
  181 + }
  182 +
  183 + /**
  184 + * Get the mod instance
  185 + */
  186 + public abstract LiteMod getMod();
  187 +
  188 + /**
  189 + * Get the mod class
  190 + */
  191 + public abstract Class<? extends LiteMod> getModClass();
  192 +
  193 + /**
  194 + * Get the mod class full name
  195 + */
  196 + public abstract String getModClassName();
  197 +
  198 + /**
  199 + * Get the mod class simple name
  200 + */
  201 + public abstract String getModClassSimpleName();
  202 +}
java/common/com/mumfrey/liteloader/core/NonMod.java 0 → 100644
  1 +package com.mumfrey.liteloader.core;
  2 +
  3 +import com.mumfrey.liteloader.LiteMod;
  4 +import com.mumfrey.liteloader.interfaces.Loadable;
  5 +
  6 +/**
  7 + * ModInfo for unloaded containers and injected tweaks
  8 + *
  9 + * @author Adam Mummery-Smith
  10 + */
  11 +public class NonMod extends ModInfo<Loadable<?>>
  12 +{
  13 + /**
  14 + * @param container
  15 + * @param active
  16 + */
  17 + public NonMod(Loadable<?> container, boolean active)
  18 + {
  19 + super(container, active);
  20 + }
  21 +
  22 + /* (non-Javadoc)
  23 + * @see com.mumfrey.liteloader.core.ModInfo#getMod()
  24 + */
  25 + @Override
  26 + public LiteMod getMod()
  27 + {
  28 + return null;
  29 + }
  30 +
  31 + /* (non-Javadoc)
  32 + * @see com.mumfrey.liteloader.core.ModInfo#getModClass()
  33 + */
  34 + @Override
  35 + public Class<? extends LiteMod> getModClass()
  36 + {
  37 + return null;
  38 + }
  39 +
  40 + /* (non-Javadoc)
  41 + * @see com.mumfrey.liteloader.core.ModInfo#getModClassName()
  42 + */
  43 + @Override
  44 + public String getModClassName()
  45 + {
  46 + return null;
  47 + }
  48 +
  49 + /* (non-Javadoc)
  50 + * @see com.mumfrey.liteloader.core.ModInfo#getModClassSimpleName()
  51 + */
  52 + @Override
  53 + public String getModClassSimpleName()
  54 + {
  55 + return null;
  56 + }
  57 +}
java/common/com/mumfrey/liteloader/interfaces/LoaderEnumerator.java
1 package com.mumfrey.liteloader.interfaces; 1 package com.mumfrey.liteloader.interfaces;
2 2
3 -import java.io.File;  
4 import java.util.Collection; 3 import java.util.Collection;
5 import java.util.List; 4 import java.util.List;
6 import java.util.Map; 5 import java.util.Map;
7 6
8 import com.mumfrey.liteloader.LiteMod; 7 import com.mumfrey.liteloader.LiteMod;
  8 +import com.mumfrey.liteloader.core.ModInfo;
9 9
10 /** 10 /**
11 * Interface for the enumerator 11 * Interface for the enumerator
@@ -69,7 +69,7 @@ public interface LoaderEnumerator extends ModularEnumerator @@ -69,7 +69,7 @@ public interface LoaderEnumerator extends ModularEnumerator
69 * 69 *
70 * @return 70 * @return
71 */ 71 */
72 - public abstract Collection<LoadableMod<?>> getDisabledContainers(); 72 + public abstract Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers();
73 73
74 /** 74 /**
75 * @param modClass 75 * @param modClass
@@ -87,12 +87,12 @@ public interface LoaderEnumerator extends ModularEnumerator @@ -87,12 +87,12 @@ public interface LoaderEnumerator extends ModularEnumerator
87 /** 87 /**
88 * @return 88 * @return
89 */ 89 */
90 - public abstract Collection<Class<? extends LiteMod>> getModsToLoad(); 90 + public abstract Collection<? extends ModInfo<LoadableMod<?>>> getModsToLoad();
91 91
92 /** 92 /**
93 * @return 93 * @return
94 */ 94 */
95 - public abstract List<Loadable<File>> getInjectedTweaks(); 95 + public abstract List<? extends ModInfo<Loadable<?>>> getInjectedTweaks();
96 96
97 /** 97 /**
98 * @return 98 * @return
java/common/com/mumfrey/liteloader/interfaces/ModularEnumerator.java
@@ -2,8 +2,8 @@ package com.mumfrey.liteloader.interfaces; @@ -2,8 +2,8 @@ package com.mumfrey.liteloader.interfaces;
2 2
3 import java.io.File; 3 import java.io.File;
4 4
5 -import com.mumfrey.liteloader.LiteMod;  
6 import com.mumfrey.liteloader.api.EnumeratorModule; 5 import com.mumfrey.liteloader.api.EnumeratorModule;
  6 +import com.mumfrey.liteloader.core.ModInfo;
7 7
8 /** 8 /**
9 * Interface for the mod enumerator 9 * Interface for the mod enumerator
@@ -39,7 +39,6 @@ public interface ModularEnumerator @@ -39,7 +39,6 @@ public interface ModularEnumerator
39 39
40 /** 40 /**
41 * @param mod 41 * @param mod
42 - * @param container  
43 */ 42 */
44 - public abstract void registerMod(Class<? extends LiteMod> mod, LoadableMod<?> container); 43 + public abstract void registerMod(ModInfo<LoadableMod<?>> mod);
45 } 44 }
46 \ No newline at end of file 45 \ No newline at end of file
java/common/com/mumfrey/liteloader/interfaces/PanelManager.java
@@ -49,4 +49,9 @@ public interface PanelManager&lt;TParentScreen&gt; extends TickObserver, PostRenderObs @@ -49,4 +49,9 @@ public interface PanelManager&lt;TParentScreen&gt; extends TickObserver, PostRenderObs
49 * @param parentScreen 49 * @param parentScreen
50 */ 50 */
51 public abstract void displayLiteLoaderPanel(TParentScreen parentScreen); 51 public abstract void displayLiteLoaderPanel(TParentScreen parentScreen);
  52 +
  53 + /**
  54 + * @return
  55 + */
  56 + public abstract int getStartupErrorCount();
52 } 57 }
java/common/com/mumfrey/liteloader/util/render/IconClickable.java 0 → 100644
  1 +package com.mumfrey.liteloader.util.render;
  2 +
  3 +/**
  4 + * Icon with an onClicked handler
  5 + *
  6 + * @author Adam Mummery-Smith
  7 + */
  8 +public interface IconClickable extends IconTextured
  9 +{
  10 + /**
  11 + * @param source Source of the event, usually the outermost gui screen
  12 + * @param container Container of this icon, the actual component hosting the icon
  13 + */
  14 + public void onClicked(Object source, Object container);
  15 +}
java/common/com/mumfrey/liteloader/util/render/IconTextured.java 0 → 100644
  1 +package com.mumfrey.liteloader.util.render;
  2 +
  3 +import net.minecraft.util.IIcon;
  4 +import net.minecraft.util.ResourceLocation;
  5 +
  6 +/**
  7 + * Icon with a texture and tooltip allocated to it
  8 + *
  9 + * @author Adam Mummery-Smith
  10 + */
  11 +public interface IconTextured extends IIcon
  12 +{
  13 + /**
  14 + * Get tooltip text, return null for no tooltip
  15 + */
  16 + public abstract String getDisplayText();
  17 +
  18 + /**
  19 + * Get the texture resource for this icon
  20 + */
  21 + public abstract ResourceLocation getTextureResource();
  22 +
  23 + /**
  24 + * Get the U coordinate on the texture for this icon
  25 + */
  26 + public abstract int getUPos();
  27 +
  28 + /**
  29 + * Get the V coordinate on the texture for this icon
  30 + */
  31 + public abstract int getVPos();
  32 +}
resources/assets/liteloader/lang/en_US.lang
@@ -37,6 +37,7 @@ gui.description.missingapis=Missing APIs: %s @@ -37,6 +37,7 @@ gui.description.missingapis=Missing APIs: %s
37 gui.mod.providestweak=Provides Tweak 37 gui.mod.providestweak=Provides Tweak
38 gui.mod.providestransformer=Provides Transformer 38 gui.mod.providestransformer=Provides Transformer
39 gui.mod.usingapi=Uses additional API 39 gui.mod.usingapi=Uses additional API
  40 +gui.mod.startuperror=%d startup error(s)
40 41
41 gui.settings.title=%s Settings 42 gui.settings.title=%s Settings
42 gui.saveandclose=Save & Close 43 gui.saveandclose=Save & Close
@@ -64,4 +65,8 @@ gui.log.postlog=Upload Log @@ -64,4 +65,8 @@ gui.log.postlog=Upload Log
64 gui.log.uploading=Uploading log to pastebin... 65 gui.log.uploading=Uploading log to pastebin...
65 gui.log.uploadfailed=Upload failed 66 gui.log.uploadfailed=Upload failed
66 gui.log.uploadsuccess=Upload succeeded, log available at 67 gui.log.uploadsuccess=Upload succeeded, log available at
67 -gui.log.closedialog=Close  
68 \ No newline at end of file 68 \ No newline at end of file
  69 +gui.log.closedialog=Close
  70 +
  71 +gui.error.title=Startup errors for %s
  72 +
  73 +gui.error.tooltip=%d mod startup error(s) detected
69 \ No newline at end of file 74 \ No newline at end of file
resources/assets/liteloader/textures/gui/about.png

41.7 KB | W: | H:

42 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin