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 480 }
481 481 catch (Throwable th)
482 482 {
  483 + this.mods.onLateInitFailed(initMod, th);
483 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 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 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 82 {
83 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 3 import static org.lwjgl.opengl.GL11.*;
4 4  
5 5 import java.nio.DoubleBuffer;
  6 +import java.util.ArrayList;
  7 +import java.util.List;
6 8  
7 9 import net.minecraft.client.Minecraft;
8 10 import net.minecraft.client.gui.FontRenderer;
9 11 import net.minecraft.client.gui.GuiButton;
  12 +import net.minecraft.client.gui.GuiMainMenu;
10 13 import net.minecraft.client.gui.GuiScreen;
11 14 import net.minecraft.client.renderer.Tessellator;
12 15 import net.minecraft.client.resources.I18n;
... ... @@ -20,10 +23,12 @@ import org.lwjgl.input.Mouse;
20 23 import com.mumfrey.liteloader.LiteMod;
21 24 import com.mumfrey.liteloader.api.LiteAPI;
22 25 import com.mumfrey.liteloader.api.BrandingProvider;
  26 +import com.mumfrey.liteloader.api.ModInfoDecorator;
23 27 import com.mumfrey.liteloader.client.api.LiteLoaderBrandingProvider;
24 28 import com.mumfrey.liteloader.core.LiteLoader;
25 29 import com.mumfrey.liteloader.core.LiteLoaderVersion;
26 30 import com.mumfrey.liteloader.core.LiteLoaderMods;
  31 +import com.mumfrey.liteloader.core.ModInfo;
27 32 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI;
28 33 import com.mumfrey.liteloader.launch.LoaderEnvironment;
29 34 import com.mumfrey.liteloader.modconfig.ConfigManager;
... ... @@ -55,6 +60,10 @@ public class GuiLiteLoaderPanel extends GuiScreen
55 60 */
56 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 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 117 private ResourceLocation iconResource = LiteLoaderBrandingProvider.ABOUT_TEXTURE;
109 118 private IIcon iconCoords = LiteLoaderBrandingProvider.ICON_COORDS;
110 119  
  120 + private List<ModInfoDecorator> modInfoDecorators = new ArrayList<ModInfoDecorator>();
  121 +
111 122 private boolean mouseOverLogo = false;
112 123  
  124 + private int startupErrorCount = 0;
  125 +
113 126 /**
114 127 * @param minecraft
115 128 * @param parentScreen
... ... @@ -127,8 +140,10 @@ public class GuiLiteLoaderPanel extends GuiScreen
127 140  
128 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 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 160 for (LiteAPI api : LiteLoader.getAPIs())
146 161 {
147 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 240 @Override
219 241 public void initGui()
220 242 {
  243 + // Hide the tooltip once the user opens the panel
  244 + GuiLiteLoaderPanel.displayErrorToolTip = false;
  245 +
221 246 this.currentPanel.setSize(this.width - LEFT_EDGE, this.height);
222 247  
223 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 337 this.handleMouseClick(offsetMouseX, mouseY, partialTicks, active, mouseOverTab);
313 338  
314 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 342 // Draw the panel contents
318 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 368  
349 369 this.mc.getTextureManager().bindTexture(LiteLoaderBrandingProvider.ABOUT_TEXTURE);
350 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 376 else
353 377 {
... ... @@ -420,7 +444,30 @@ public class GuiLiteLoaderPanel extends GuiScreen
420 444 this.mouseOverLogo = (mouseY > MARGIN && mouseY < MARGIN + this.logoCoords.getIconHeight() && mouseX > left && mouseX < left + this.logoCoords.getIconWidth());
421 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 471 /* (non-Javadoc)
425 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 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 518 /* (non-Javadoc)
467 519 * @see net.minecraft.client.gui.GuiScreen#mouseClicked(int, int, int)
468 520 */
... ... @@ -688,6 +740,8 @@ public class GuiLiteLoaderPanel extends GuiScreen
688 740 */
689 741 final static void glEnableClipping(int xLeft, int xRight, int yTop, int yBottom)
690 742 {
  743 + clippingPlaneFlags = 0;
  744 +
691 745 // Apply left edge clipping if specified
692 746 if (xLeft != -1)
693 747 {
... ... @@ -695,6 +749,7 @@ public class GuiLiteLoaderPanel extends GuiScreen
695 749 doubleBuffer.put(1).put(0).put(0).put(-xLeft).flip();
696 750 glClipPlane(GL_CLIP_PLANE2, doubleBuffer);
697 751 glEnable(GL_CLIP_PLANE2);
  752 + clippingPlaneFlags |= GL_CLIP_PLANE2;
698 753 }
699 754  
700 755 // Apply right edge clipping if specified
... ... @@ -704,6 +759,7 @@ public class GuiLiteLoaderPanel extends GuiScreen
704 759 doubleBuffer.put(-1).put(0).put(0).put(xRight).flip();
705 760 glClipPlane(GL_CLIP_PLANE3, doubleBuffer);
706 761 glEnable(GL_CLIP_PLANE3);
  762 + clippingPlaneFlags |= GL_CLIP_PLANE3;
707 763 }
708 764  
709 765 // Apply top edge clipping if specified
... ... @@ -713,6 +769,7 @@ public class GuiLiteLoaderPanel extends GuiScreen
713 769 doubleBuffer.put(0).put(1).put(0).put(-yTop).flip();
714 770 glClipPlane(GL_CLIP_PLANE4, doubleBuffer);
715 771 glEnable(GL_CLIP_PLANE4);
  772 + clippingPlaneFlags |= GL_CLIP_PLANE4;
716 773 }
717 774  
718 775 // Apply bottom edge clipping if specified
... ... @@ -722,10 +779,22 @@ public class GuiLiteLoaderPanel extends GuiScreen
722 779 doubleBuffer.put(0).put(-1).put(0).put(yBottom).flip();
723 780 glClipPlane(GL_CLIP_PLANE5, doubleBuffer);
724 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 798 * Disable OpenGL clipping planes (uses planes 2, 3, 4 and 5)
730 799 */
731 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 11 import net.minecraft.client.gui.Gui;
12 12 import net.minecraft.client.resources.I18n;
13 13  
14   -import com.google.common.collect.ImmutableSet;
  14 +import com.google.common.base.Strings;
15 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 17 import com.mumfrey.liteloader.core.LiteLoaderMods;
  18 +import com.mumfrey.liteloader.core.ModInfo;
20 19 import com.mumfrey.liteloader.interfaces.Loadable;
21 20 import com.mumfrey.liteloader.interfaces.LoadableMod;
22   -import com.mumfrey.liteloader.interfaces.TweakContainer;
23 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 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 41 private static final int API_COLOUR = 0xFFAA00AA;
42 42 private static final int EXTERNAL_ENTRY_COLOUR = 0xFF47D1AA;
43 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 48 private static final int TITLE_COLOUR = GuiModListEntry.WHITE;
46 49 private static final int VERSION_TEXT_COLOUR = GuiModListEntry.GREY;
... ... @@ -54,8 +57,6 @@ public class GuiModListEntry extends Gui
54 57 private static final int PANEL_HEIGHT = 32;
55 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 61 * For text display
61 62 */
... ... @@ -63,12 +64,12 @@ public class GuiModListEntry extends Gui
63 64  
64 65 private final int brandColour;
65 66  
  67 + private final List<ModInfoDecorator> decorators;
  68 +
66 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 74 * The identifier of the mod, used as the enablement/disablement key
74 75 */
... ... @@ -108,6 +109,8 @@ public class GuiModListEntry extends Gui
108 109  
109 110 private boolean isMissingAPIs;
110 111  
  112 + private boolean isErrored;
  113 +
111 114 /**
112 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 137 */
135 138 private boolean mouseOverListEntry, mouseOverInfo, mouseOverScrollBar;
136 139  
  140 + private IconClickable mouseOverIcon = null;
  141 +
137 142 /**
138 143 * True if this is not a mod but an external jar
139 144 */
140 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 150 * Scroll bar control for the mod info
... ... @@ -149,125 +154,49 @@ public class GuiModListEntry extends Gui
149 154 /**
150 155 * Mod list entry for an ACTIVE mod
151 156 * @param fontRenderer
152   - * @param modInstance
  157 + * @param modInfo
153 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 234 xPosition += (width - 14);
306 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 241 xPosition = this.drawPropertyIcon(xPosition, yPosition, icon, mouseX, mouseY);
311 242 }
... ... @@ -313,7 +244,7 @@ public class GuiModListEntry extends Gui
313 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 249 glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
319 250 Minecraft.getMinecraft().getTextureManager().bindTexture(icon.getTextureResource());
... ... @@ -324,7 +255,15 @@ public class GuiModListEntry extends Gui
324 255  
325 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 269 return xPosition - 14;
... ... @@ -353,7 +292,7 @@ public class GuiModListEntry extends Gui
353 292 drawRect(xPosition + 5, yPos, xPosition + width, yPos + 1, GuiModListEntry.DIVIDER_COLOUR); yPos += 4; // divider
354 293  
355 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 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 362 */
424 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 376 {
438 377 if (this.isMissingDependencies) return GuiModListEntry.MISSING_DEPENDENCY_COLOUR;
439 378 if (this.isMissingAPIs) return GuiModListEntry.API_COLOUR;
  379 + if (this.isErrored) return GuiModListEntry.ERROR_COLOUR;
440 380 if (!this.enabled) return GuiModListEntry.GREY;
441 381 return this.external ? GuiModListEntry.EXTERNAL_ENTRY_COLOUR : GuiModListEntry.WHITE;
442 382 }
... ... @@ -497,17 +437,17 @@ public class GuiModListEntry extends Gui
497 437  
498 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 443 public LiteMod getModInstance()
504 444 {
505   - return this.modInstance;
  445 + return this.modInfo.getMod();
506 446 }
507 447  
508 448 public Class<? extends LiteMod> getModClass()
509 449 {
510   - return this.modClass;
  450 + return this.modInfo.getModClass();
511 451 }
512 452  
513 453 public String getName()
... ... @@ -545,11 +485,24 @@ public class GuiModListEntry extends Gui
545 485 return this.willBeEnabled;
546 486 }
547 487  
  488 + public boolean isMouseOverIcon()
  489 + {
  490 + return this.mouseOverListEntry && this.mouseOverIcon != null;
  491 + }
  492 +
548 493 public boolean isMouseOver()
549 494 {
550 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 506 public boolean mouseWheelScrolled(int mouseWheelDelta)
554 507 {
555 508 if (this.mouseOverInfo)
... ...
java/client/com/mumfrey/liteloader/client/gui/GuiPanelConfigContainer.java
... ... @@ -109,7 +109,14 @@ class GuiPanelConfigContainer extends GuiPanel implements ConfigPanelHost
109 109 @Override
110 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 125 @Override
119 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 10 import org.lwjgl.input.Keyboard;
11 11  
12 12 import com.mumfrey.liteloader.LiteMod;
  13 +import com.mumfrey.liteloader.api.ModInfoDecorator;
13 14 import com.mumfrey.liteloader.core.LiteLoaderMods;
  15 +import com.mumfrey.liteloader.core.ModInfo;
14 16 import com.mumfrey.liteloader.interfaces.Loadable;
  17 +import com.mumfrey.liteloader.interfaces.LoadableMod;
15 18 import com.mumfrey.liteloader.launch.LoaderEnvironment;
16 19 import com.mumfrey.liteloader.modconfig.ConfigManager;
17 20 import com.mumfrey.liteloader.modconfig.ConfigPanel;
... ... @@ -70,7 +73,7 @@ public class GuiPanelMods extends GuiPanel
70 73  
71 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 78 super(minecraft);
76 79  
... ... @@ -78,7 +81,7 @@ public class GuiPanelMods extends GuiPanel
78 81 this.configManager = configManager;
79 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 90 * @param mods
88 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 95 // Add mods to this treeset first, in order to sort them
93 96 Map<String, GuiModListEntry> sortedMods = new TreeMap<String, GuiModListEntry>();
94 97  
95 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 102 sortedMods.put(modListEntry.getKey(), modListEntry);
100 103 }
101 104  
102 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 109 sortedMods.put(modListEntry.getKey(), modListEntry);
107 110 }
108 111  
109 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 116 sortedMods.put(modListEntry.getKey(), modListEntry);
114 117 }
115 118  
... ... @@ -178,10 +181,17 @@ public class GuiPanelMods extends GuiPanel
178 181 {
179 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 197 this.doubleClickTime = 5;
... ...
java/client/com/mumfrey/liteloader/client/util/render/IconAbsolute.java
1 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 5 import net.minecraft.util.ResourceLocation;
5 6  
6   -public class IconAbsolute implements IIcon
  7 +public class IconAbsolute implements IconTextured
7 8 {
8 9 private ResourceLocation textureResource;
9 10  
10   - private String name;
  11 + private String displayText;
11 12  
12 13 private int texMapSize = 256;
13 14  
... ... @@ -21,15 +22,15 @@ public class IconAbsolute implements IIcon
21 22 private float vCoord;
22 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 32 this.textureResource = textureResource;
32   - this.name = name;
  33 + this.displayText = displayText;
33 34 this.width = width;
34 35 this.height = height;
35 36  
... ... @@ -42,7 +43,14 @@ public class IconAbsolute implements IIcon
42 43 this.vCoord = vCoord / this.texMapSize;
43 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 54 public ResourceLocation getTextureResource()
47 55 {
48 56 return this.textureResource;
... ... @@ -60,11 +68,13 @@ public class IconAbsolute implements IIcon
60 68 return this.height;
61 69 }
62 70  
  71 + @Override
63 72 public int getUPos()
64 73 {
65 74 return this.uPos;
66 75 }
67 76  
  77 + @Override
68 78 public int getVPos()
69 79 {
70 80 return this.vPos;
... ... @@ -111,6 +121,6 @@ public class IconAbsolute implements IIcon
111 121 @Override
112 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 55 * Profiler
56 56 */
57 57 protected final Profiler profiler;
58   -
  58 +
  59 + protected LiteLoaderMods mods;
59 60  
60 61 /**
61 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 85 this.engine = engine;
85 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 2  
3 3 import java.io.File;
4 4 import java.io.PrintStream;
  5 +import java.util.ArrayList;
5 6 import java.util.Collection;
6 7 import java.util.LinkedList;
7 8 import java.util.List;
... ... @@ -602,7 +603,14 @@ public final class LiteLoader
602 603 */
603 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 618 */
611 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 632 * Get the list of injected tweak containers
618 633 */
  634 + @SuppressWarnings("unchecked")
619 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 863  
841 864 // Create the event broker
842 865 this.events = this.objectFactory.getEventBroker();
  866 + if (this.events != null)
  867 + {
  868 + this.events.setMods(this.mods);
  869 + }
843 870  
844 871 // Get the mod panel manager
845 872 this.modPanelManager = this.objectFactory.getModPanelManager();
... ...
java/common/com/mumfrey/liteloader/core/LiteLoaderEnumerator.java
... ... @@ -5,8 +5,10 @@ import java.net.MalformedURLException;
5 5 import java.net.URL;
6 6 import java.util.ArrayList;
7 7 import java.util.Collection;
  8 +import java.util.Collections;
8 9 import java.util.HashMap;
9 10 import java.util.HashSet;
  11 +import java.util.LinkedHashSet;
10 12 import java.util.LinkedList;
11 13 import java.util.List;
12 14 import java.util.Map;
... ... @@ -76,17 +78,17 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
76 78 /**
77 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 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 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 94 * Containers which have already been checked for potential mod candidates
... ... @@ -94,11 +96,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
94 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 99 * Tweaks to inject
103 100 */
104 101 private final List<TweakContainer<File>> tweakContainers = new ArrayList<TweakContainer<File>>();
... ... @@ -106,7 +103,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
106 103 /**
107 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 233 * Get the list of all enumerated mod classes to load
237 234 */
238 235 @Override
239   - public Collection<Class<? extends LiteMod>> getModsToLoad()
  236 + public Collection<? extends ModInfo<LoadableMod<?>>> getModsToLoad()
240 237 {
241 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 244 * @return
248 245 */
249 246 @Override
250   - public Collection<LoadableMod<?>> getDisabledContainers()
  247 + public Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers()
251 248 {
252 249 this.checkState(EnumeratorState.FINALISED, "getDisabledContainers");
253 250  
... ... @@ -258,7 +255,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
258 255 * Get the list of injected tweak containers
259 256 */
260 257 @Override
261   - public List<Loadable<File>> getInjectedTweaks()
  258 + public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
262 259 {
263 260 this.checkState(EnumeratorState.FINALISED, "getInjectedTweaks");
264 261  
... ... @@ -299,7 +296,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
299 296 {
300 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 308 {
312 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 327 public String getIdentifier(Class<? extends LiteMod> modClass)
325 328 {
326 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 340 @Override
... ... @@ -447,7 +456,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
447 456 this.checkState(EnumeratorState.DISCOVER, "registerEnabledContainer");
448 457  
449 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 466 {
458 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 473 /* (non-Javadoc)
... ... @@ -514,7 +523,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
514 523  
515 524 if (container.isExternalJar())
516 525 {
517   - this.injectedTweaks.add(container);
  526 + this.injectedTweaks.add(new NonMod(container, true));
518 527 }
519 528  
520 529 String[] classPathEntries = container.getClassPathEntries();
... ... @@ -582,9 +591,10 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
582 591 this.enumeratedContainers.add(container);
583 592  
584 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 600 if (modClasses.size() > 0)
... ... @@ -592,29 +602,24 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
592 602 LiteLoaderLogger.info("Found %d potential matches", modClasses.size());
593 603  
594 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 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 612 @Override
603   - public void registerMod(Class<? extends LiteMod> mod, LoadableMod<?> container)
  613 + public void registerMod(ModInfo<LoadableMod<?>> mod)
604 614 {
605 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 71 /**
72 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 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 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 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 93 LiteLoaderMods(LiteLoader loader, LoaderEnvironment environment, LoaderProperties properties, ConfigManager configManager)
92 94 {
... ... @@ -97,12 +99,13 @@ public class LiteLoaderMods
97 99 this.configManager = configManager;
98 100 }
99 101  
  102 + @SuppressWarnings("unchecked")
100 103 void init(List<ModLoadObserver> observers)
101 104 {
102 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 109 void onPostInit()
107 110 {
108 111 this.updateSharedModList();
... ... @@ -115,9 +118,9 @@ public class LiteLoaderMods
115 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 136 /**
134 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 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 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 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 214 return null;
... ... @@ -207,9 +223,9 @@ public class LiteLoaderMods
207 223 @SuppressWarnings("unchecked")
208 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 229 return (T)mod;
214 230 }
215 231  
... ... @@ -226,12 +242,10 @@ public class LiteLoaderMods
226 242 {
227 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 251 return null;
... ... @@ -368,16 +382,14 @@ public class LiteLoaderMods
368 382 * @param modName
369 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 392 return true;
380   - }
381 393 }
382 394  
383 395 return false;
... ... @@ -392,14 +404,14 @@ public class LiteLoaderMods
392 404 {
393 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 412 try
401 413 {
402   - String identifier = this.enumerator.getIdentifier(mod);
  414 + String identifier = mod.getIdentifier();
403 415 if (identifier == null || this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), identifier))
404 416 {
405 417 if (!this.enumerator.checkDependencies(container))
... ... @@ -408,7 +420,14 @@ public class LiteLoaderMods
408 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 432 else
414 433 {
... ... @@ -417,33 +436,44 @@ public class LiteLoaderMods
417 436 }
418 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 445 * @param identifier
427   - * @param mod
  446 + * @param modClass
428 447 * @param container
429 448 * @throws InstantiationException
430 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 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 471 LiteLoaderLogger.info("Successfully added mod %s version %s", modName, newMod.getVersion());
443 472  
444 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 477 LiteLoaderLogger.info("Adding \"%s\" to active resource pack set", container.getLocation());
448 478 if (modName != null)
449 479 {
... ... @@ -460,11 +490,11 @@ public class LiteLoaderMods
460 490 /**
461 491 * @param mod
462 492 */
463   - void onModLoaded(LiteMod mod)
  493 + void onModLoaded(Mod mod)
464 494 {
465 495 for (ModLoadObserver observer : this.observers)
466 496 {
467   - observer.onModLoaded(mod);
  497 + observer.onModLoaded(mod.getMod());
468 498 }
469 499  
470 500 this.allMods.add(mod);
... ... @@ -485,7 +515,7 @@ public class LiteLoaderMods
485 515  
486 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 521 for (ModLoadObserver observer : this.observers)
... ... @@ -504,7 +534,7 @@ public class LiteLoaderMods
504 534  
505 535 while (this.initMods.size() > 0)
506 536 {
507   - LiteMod mod = this.initMods.removeFirst();
  537 + Mod mod = this.initMods.removeFirst();
508 538  
509 539 try
510 540 {
... ... @@ -513,8 +543,8 @@ public class LiteLoaderMods
513 543 }
514 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 554 /**
525 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 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 580 for (ModLoadObserver observer : this.observers)
546 581 {
547   - observer.onPreInitMod(mod);
  582 + observer.onPreInitMod(instance);
548 583 }
549 584  
550 585 // register mod config panel if configurable
551   - this.configManager.registerMod(mod);
  586 + this.configManager.registerMod(instance);
552 587  
553 588 try
554 589 {
555   - this.handleModVersionUpgrade(mod);
  590 + this.handleModVersionUpgrade(instance);
556 591 }
557 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 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 607 for (ModLoadObserver observer : this.observers)
572 608 {
573   - observer.onPostInitMod(mod);
  609 + observer.onPostInitMod(instance);
574 610 }
575 611  
576 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 625 int currentRevision = LiteLoaderVersion.CURRENT.getLoaderRevision();
593 626 int lastKnownRevision = this.properties.getLastKnownModRevision(modKey);
... ... @@ -598,25 +631,25 @@ public class LiteLoaderMods
598 631 File newConfigPath = LiteLoader.getConfigFolder();
599 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 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 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 644 // Let the mod upgrade
612   - mod.upgradeSettings(LiteLoaderVersion.CURRENT.getMinecraftVersion(), newConfigPath, oldConfigPath);
  645 + instance.upgradeSettings(LiteLoaderVersion.CURRENT.getMinecraftVersion(), newConfigPath, oldConfigPath);
613 646  
614 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 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 693 void updateSharedModList()
641 694 {
642 695 Map<String, Map<String, String>> modList = this.enumerator.getSharedModList();
643 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 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 707 Map<String, String> modInfo = new HashMap<String, String>();
655   - LoadableMod<?> container = this.loader.getModContainer(mod);
656 708  
657 709 modInfo.put("modsystem", LiteLoaderMods.MOD_SYSTEM);
658   - modInfo.put("id", this.loader.getModIdentifier(mod));
  710 + modInfo.put("id", mod.getIdentifier());
659 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 717 return modInfo;
666 718 }
... ...
java/common/com/mumfrey/liteloader/core/LiteLoaderVersion.java
... ... @@ -9,7 +9,7 @@ import com.mumfrey.liteloader.update.UpdateSite;
9 9 * LiteLoader version table
10 10 *
11 11 * @author Adam Mummery-Smith
12   - * @version 1.7.10_02
  12 + * @version 1.7.10_03
13 13 */
14 14 public enum LiteLoaderVersion
15 15 {
... ... @@ -37,7 +37,8 @@ public enum LiteLoaderVersion
37 37 MC_1_7_2_R6(26, 0, "1.7.2", "1.7.2_06", "1.7.2_06"),
38 38 MC_1_7_10_R0(27, 1404330030, "1.7.10", "1.7.10", "1.7.10"),
39 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 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 1 package com.mumfrey.liteloader.interfaces;
2 2  
3   -import java.io.File;
4 3 import java.util.Collection;
5 4 import java.util.List;
6 5 import java.util.Map;
7 6  
8 7 import com.mumfrey.liteloader.LiteMod;
  8 +import com.mumfrey.liteloader.core.ModInfo;
9 9  
10 10 /**
11 11 * Interface for the enumerator
... ... @@ -69,7 +69,7 @@ public interface LoaderEnumerator extends ModularEnumerator
69 69 *
70 70 * @return
71 71 */
72   - public abstract Collection<LoadableMod<?>> getDisabledContainers();
  72 + public abstract Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers();
73 73  
74 74 /**
75 75 * @param modClass
... ... @@ -87,12 +87,12 @@ public interface LoaderEnumerator extends ModularEnumerator
87 87 /**
88 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 93 * @return
94 94 */
95   - public abstract List<Loadable<File>> getInjectedTweaks();
  95 + public abstract List<? extends ModInfo<Loadable<?>>> getInjectedTweaks();
96 96  
97 97 /**
98 98 * @return
... ...
java/common/com/mumfrey/liteloader/interfaces/ModularEnumerator.java
... ... @@ -2,8 +2,8 @@ package com.mumfrey.liteloader.interfaces;
2 2  
3 3 import java.io.File;
4 4  
5   -import com.mumfrey.liteloader.LiteMod;
6 5 import com.mumfrey.liteloader.api.EnumeratorModule;
  6 +import com.mumfrey.liteloader.core.ModInfo;
7 7  
8 8 /**
9 9 * Interface for the mod enumerator
... ... @@ -39,7 +39,6 @@ public interface ModularEnumerator
39 39  
40 40 /**
41 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 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 49 * @param parentScreen
50 50 */
51 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 37 gui.mod.providestweak=Provides Tweak
38 38 gui.mod.providestransformer=Provides Transformer
39 39 gui.mod.usingapi=Uses additional API
  40 +gui.mod.startuperror=%d startup error(s)
40 41  
41 42 gui.settings.title=%s Settings
42 43 gui.saveandclose=Save & Close
... ... @@ -64,4 +65,8 @@ gui.log.postlog=Upload Log
64 65 gui.log.uploading=Uploading log to pastebin...
65 66 gui.log.uploadfailed=Upload failed
66 67 gui.log.uploadsuccess=Upload succeeded, log available at
67   -gui.log.closedialog=Close
68 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 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