Commit 1782552f6e30982177b67f95efe69326c79614a5
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<TClient, TServer extends MinecraftServer> 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<TClient, TServer extends MinecraftServer> 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<TParentScreen> 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