Commit e13e19ac4972f7bae1a25a94e104efa7b027527f
Backport all 1.12+ changes to 1.11.2
Showing
25 changed files
with
720 additions
and
343 deletions
build.gradle
@@ -60,8 +60,8 @@ archivesBaseName = "liteloader" | @@ -60,8 +60,8 @@ archivesBaseName = "liteloader" | ||
60 | version = buildVersion + (project.isReleaseBuild ? '' : '-' + project.classifier) | 60 | version = buildVersion + (project.isReleaseBuild ? '' : '-' + project.classifier) |
61 | 61 | ||
62 | // Minimum version of Java required | 62 | // Minimum version of Java required |
63 | -sourceCompatibility = '1.6' | ||
64 | -targetCompatibility = '1.6' | 63 | +sourceCompatibility = '1.8' |
64 | +targetCompatibility = '1.8' | ||
65 | 65 | ||
66 | repositories { | 66 | repositories { |
67 | mavenLocal() | 67 | mavenLocal() |
@@ -72,7 +72,7 @@ repositories { | @@ -72,7 +72,7 @@ repositories { | ||
72 | } | 72 | } |
73 | 73 | ||
74 | dependencies { | 74 | dependencies { |
75 | - compile('org.spongepowered:mixin:0.6.8-SNAPSHOT') { | 75 | + compile('org.spongepowered:mixin:0.7.1-SNAPSHOT') { |
76 | exclude module: 'asm-commons' | 76 | exclude module: 'asm-commons' |
77 | exclude module: 'asm-tree' | 77 | exclude module: 'asm-tree' |
78 | exclude module: 'launchwrapper' | 78 | exclude module: 'launchwrapper' |
@@ -89,11 +89,11 @@ minecraft { | @@ -89,11 +89,11 @@ minecraft { | ||
89 | 89 | ||
90 | sourceSets { | 90 | sourceSets { |
91 | main { | 91 | main { |
92 | - refMap = "mixins.liteloader.core.refmap.json" | 92 | + ext.refMap = "mixins.liteloader.core.refmap.json" |
93 | } | 93 | } |
94 | client { | 94 | client { |
95 | compileClasspath += main.compileClasspath + main.output | 95 | compileClasspath += main.compileClasspath + main.output |
96 | - refMap = "mixins.liteloader.client.refmap.json" | 96 | + ext.refMap = "mixins.liteloader.client.refmap.json" |
97 | } | 97 | } |
98 | debug { | 98 | debug { |
99 | compileClasspath += client.compileClasspath + client.output | 99 | compileClasspath += client.compileClasspath + client.output |
@@ -123,7 +123,7 @@ javadoc { | @@ -123,7 +123,7 @@ javadoc { | ||
123 | afterEvaluate { | 123 | afterEvaluate { |
124 | logger.lifecycle '=================================================' | 124 | logger.lifecycle '=================================================' |
125 | logger.lifecycle ' LiteLoader' | 125 | logger.lifecycle ' LiteLoader' |
126 | - logger.lifecycle ' Copyright (C) 2011-2016 Adam Mummery-Smith' | 126 | + logger.lifecycle ' Copyright (C) 2011-2017 Adam Mummery-Smith' |
127 | logger.lifecycle ' Running in {} mode', (project.isReleaseBuild ? "RELEASE" : "SNAPSHOT") | 127 | logger.lifecycle ' Running in {} mode', (project.isReleaseBuild ? "RELEASE" : "SNAPSHOT") |
128 | logger.lifecycle '=================================================' | 128 | logger.lifecycle '=================================================' |
129 | 129 |
gradle.properties
@@ -7,4 +7,4 @@ organization=LiteLoader | @@ -7,4 +7,4 @@ organization=LiteLoader | ||
7 | buildType=SNAPSHOT | 7 | buildType=SNAPSHOT |
8 | buildVersion=1.11.2 | 8 | buildVersion=1.11.2 |
9 | mcVersion=1.11.2 | 9 | mcVersion=1.11.2 |
10 | -mcMappings=snapshot_20161224 | ||
11 | \ No newline at end of file | 10 | \ No newline at end of file |
11 | +mcMappings=snapshot_20161224 |
src/client/java/com/mumfrey/liteloader/client/LiteLoaderEventBrokerClient.java
@@ -9,24 +9,9 @@ import org.lwjgl.input.Mouse; | @@ -9,24 +9,9 @@ import org.lwjgl.input.Mouse; | ||
9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; |
10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; | 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; |
11 | 11 | ||
12 | -import com.mumfrey.liteloader.ChatRenderListener; | ||
13 | -import com.mumfrey.liteloader.EntityRenderListener; | ||
14 | -import com.mumfrey.liteloader.FrameBufferListener; | ||
15 | -import com.mumfrey.liteloader.GameLoopListener; | ||
16 | -import com.mumfrey.liteloader.HUDRenderListener; | ||
17 | -import com.mumfrey.liteloader.InitCompleteListener; | ||
18 | -import com.mumfrey.liteloader.OutboundChatFilter; | ||
19 | -import com.mumfrey.liteloader.OutboundChatListener; | ||
20 | -import com.mumfrey.liteloader.PlayerClickListener; | 12 | +import com.mumfrey.liteloader.*; |
21 | import com.mumfrey.liteloader.PlayerInteractionListener.MouseButton; | 13 | import com.mumfrey.liteloader.PlayerInteractionListener.MouseButton; |
22 | -import com.mumfrey.liteloader.PostRenderListener; | ||
23 | -import com.mumfrey.liteloader.PreRenderListener; | ||
24 | -import com.mumfrey.liteloader.RenderListener; | ||
25 | -import com.mumfrey.liteloader.ScreenshotListener; | ||
26 | -import com.mumfrey.liteloader.Tickable; | ||
27 | -import com.mumfrey.liteloader.ViewportListener; | ||
28 | import com.mumfrey.liteloader.client.overlays.IEntityRenderer; | 14 | import com.mumfrey.liteloader.client.overlays.IEntityRenderer; |
29 | -import com.mumfrey.liteloader.client.overlays.IMinecraft; | ||
30 | import com.mumfrey.liteloader.common.LoadingProgress; | 15 | import com.mumfrey.liteloader.common.LoadingProgress; |
31 | import com.mumfrey.liteloader.core.InterfaceRegistrationDelegate; | 16 | import com.mumfrey.liteloader.core.InterfaceRegistrationDelegate; |
32 | import com.mumfrey.liteloader.core.LiteLoader; | 17 | import com.mumfrey.liteloader.core.LiteLoader; |
@@ -51,7 +36,6 @@ import net.minecraft.client.shader.Framebuffer; | @@ -51,7 +36,6 @@ import net.minecraft.client.shader.Framebuffer; | ||
51 | import net.minecraft.entity.Entity; | 36 | import net.minecraft.entity.Entity; |
52 | import net.minecraft.network.play.client.CPacketChatMessage; | 37 | import net.minecraft.network.play.client.CPacketChatMessage; |
53 | import net.minecraft.server.integrated.IntegratedServer; | 38 | import net.minecraft.server.integrated.IntegratedServer; |
54 | -import net.minecraft.util.Timer; | ||
55 | import net.minecraft.util.text.ITextComponent; | 39 | import net.minecraft.util.text.ITextComponent; |
56 | 40 | ||
57 | public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft, IntegratedServer> implements IResourceManagerReloadListener | 41 | public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft, IntegratedServer> implements IResourceManagerReloadListener |
@@ -427,14 +411,9 @@ public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft | @@ -427,14 +411,9 @@ public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft | ||
427 | /** | 411 | /** |
428 | * Callback from the tick hook, ticks all tickable mods | 412 | * Callback from the tick hook, ticks all tickable mods |
429 | */ | 413 | */ |
430 | - public void onTick() | 414 | + public void onTick(boolean clock, float partialTicks) |
431 | { | 415 | { |
432 | this.profiler.endStartSection("litemods"); | 416 | this.profiler.endStartSection("litemods"); |
433 | - | ||
434 | - Timer minecraftTimer = ((IMinecraft)this.engine.getClient()).getTimer(); | ||
435 | - float partialTicks = minecraftTimer.renderPartialTicks; | ||
436 | - boolean clock = minecraftTimer.elapsedTicks > 0; | ||
437 | - | ||
438 | Minecraft minecraft = this.engine.getClient(); | 417 | Minecraft minecraft = this.engine.getClient(); |
439 | 418 | ||
440 | // Flag indicates whether we are in game at the moment | 419 | // Flag indicates whether we are in game at the moment |
@@ -548,7 +527,7 @@ public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft | @@ -548,7 +527,7 @@ public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft | ||
548 | } | 527 | } |
549 | 528 | ||
550 | /** | 529 | /** |
551 | - * @param e | 530 | + * @param ci |
552 | * @param name | 531 | * @param name |
553 | * @param width | 532 | * @param width |
554 | * @param height | 533 | * @param height |
src/client/java/com/mumfrey/liteloader/client/LiteLoaderPanelManager.java
@@ -9,6 +9,7 @@ import org.lwjgl.input.Keyboard; | @@ -9,6 +9,7 @@ import org.lwjgl.input.Keyboard; | ||
9 | 9 | ||
10 | import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel; | 10 | import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel; |
11 | import com.mumfrey.liteloader.common.GameEngine; | 11 | import com.mumfrey.liteloader.common.GameEngine; |
12 | +import com.mumfrey.liteloader.core.LiteLoader; | ||
12 | import com.mumfrey.liteloader.core.LiteLoaderMods; | 13 | import com.mumfrey.liteloader.core.LiteLoaderMods; |
13 | import com.mumfrey.liteloader.core.LiteLoaderUpdateSite; | 14 | import com.mumfrey.liteloader.core.LiteLoaderUpdateSite; |
14 | import com.mumfrey.liteloader.core.LiteLoaderVersion; | 15 | import com.mumfrey.liteloader.core.LiteLoaderVersion; |
@@ -32,6 +33,13 @@ import net.minecraft.client.resources.I18n; | @@ -32,6 +33,13 @@ import net.minecraft.client.resources.I18n; | ||
32 | */ | 33 | */ |
33 | public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | 34 | public class LiteLoaderPanelManager implements PanelManager<GuiScreen> |
34 | { | 35 | { |
36 | + /** | ||
37 | + * Number of launches required before an update check is forced when the | ||
38 | + * "force update check" option is enabled. For snapshot versions this is | ||
39 | + * ignored and an update check is always performed. | ||
40 | + */ | ||
41 | + private static final int UPDATE_CHECK_INTERVAL = 10; | ||
42 | + | ||
35 | private final LoaderEnvironment environment; | 43 | private final LoaderEnvironment environment; |
36 | 44 | ||
37 | /** | 45 | /** |
@@ -87,14 +95,14 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | @@ -87,14 +95,14 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | ||
87 | this.displayModInfoScreenTab = this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_MOD_INFO_SCREEN, true); | 95 | this.displayModInfoScreenTab = this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_MOD_INFO_SCREEN, true); |
88 | this.tabAlwaysExpanded = this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_NO_HIDE_TAB, false); | 96 | this.tabAlwaysExpanded = this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_NO_HIDE_TAB, false); |
89 | 97 | ||
90 | - if (this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_FORCE_UPDATE, false)) | 98 | + if (this.shouldCheckForUpdates()) |
91 | { | 99 | { |
92 | int updateCheckInterval = this.properties.getIntegerProperty(LoaderProperties.OPTION_UPDATE_CHECK_INTR) + 1; | 100 | int updateCheckInterval = this.properties.getIntegerProperty(LoaderProperties.OPTION_UPDATE_CHECK_INTR) + 1; |
93 | - LiteLoaderLogger.debug("Force update is TRUE, updateCheckInterval = %d", updateCheckInterval); | 101 | + LiteLoaderLogger.debug("Regular update check enabled, updateCheckInterval = %d", updateCheckInterval); |
94 | 102 | ||
95 | - if (updateCheckInterval > 10) | 103 | + if (LiteLoader.isSnapshot() || updateCheckInterval > LiteLoaderPanelManager.UPDATE_CHECK_INTERVAL) |
96 | { | 104 | { |
97 | - LiteLoaderLogger.debug("Forcing update check!"); | 105 | + LiteLoaderLogger.debug("Checking for updates..."); |
98 | this.checkForUpdate = true; | 106 | this.checkForUpdate = true; |
99 | updateCheckInterval = 0; | 107 | updateCheckInterval = 0; |
100 | } | 108 | } |
@@ -104,6 +112,16 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | @@ -104,6 +112,16 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | ||
104 | } | 112 | } |
105 | } | 113 | } |
106 | 114 | ||
115 | + private boolean shouldCheckForUpdates() | ||
116 | + { | ||
117 | + if (LiteLoader.isSnapshot() && this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_CHECK_SNAPSHOTS, true)) | ||
118 | + { | ||
119 | + return true; | ||
120 | + } | ||
121 | + | ||
122 | + return this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_FORCE_UPDATE, false); | ||
123 | + } | ||
124 | + | ||
107 | @Override | 125 | @Override |
108 | public void init(LiteLoaderMods mods, ConfigManager configManager) | 126 | public void init(LiteLoaderMods mods, ConfigManager configManager) |
109 | { | 127 | { |
@@ -141,7 +159,8 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | @@ -141,7 +159,8 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | ||
141 | this.checkForUpdate = false; | 159 | this.checkForUpdate = false; |
142 | if (updateSite.isCheckSucceess() && updateSite.isUpdateAvailable()) | 160 | if (updateSite.isCheckSucceess() && updateSite.isUpdateAvailable()) |
143 | { | 161 | { |
144 | - this.setNotification(I18n.format("gui.notifications.updateavailable")); | 162 | + this.setNotification(I18n.format("gui.notifications." + (LiteLoader.isSnapshot() ? "newsnapshotavailable" : "updateavailable"), |
163 | + updateSite.getAvailableVersion(), updateSite.getAvailableVersionDate())); | ||
145 | } | 164 | } |
146 | } | 165 | } |
147 | } | 166 | } |
@@ -251,6 +270,19 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | @@ -251,6 +270,19 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> | ||
251 | { | 270 | { |
252 | return this.properties.getBooleanProperty(LoaderProperties.OPTION_FORCE_UPDATE); | 271 | return this.properties.getBooleanProperty(LoaderProperties.OPTION_FORCE_UPDATE); |
253 | } | 272 | } |
273 | + | ||
274 | + @Override | ||
275 | + public void setCheckForSnapshotsEnabled(boolean checkForSnapshots) | ||
276 | + { | ||
277 | + this.properties.setBooleanProperty(LoaderProperties.OPTION_CHECK_SNAPSHOTS, checkForSnapshots); | ||
278 | + this.properties.writeProperties(); | ||
279 | + } | ||
280 | + | ||
281 | + @Override | ||
282 | + public boolean isCheckForSnapshotsEnabled() | ||
283 | + { | ||
284 | + return this.properties.getBooleanProperty(LoaderProperties.OPTION_CHECK_SNAPSHOTS); | ||
285 | + } | ||
254 | 286 | ||
255 | /** | 287 | /** |
256 | * Display the liteloader panel over the specified GUI | 288 | * Display the liteloader panel over the specified GUI |
src/client/java/com/mumfrey/liteloader/client/api/LiteLoaderCoreAPIClient.java
@@ -42,7 +42,6 @@ public class LiteLoaderCoreAPIClient extends LiteLoaderCoreAPI | @@ -42,7 +42,6 @@ public class LiteLoaderCoreAPIClient extends LiteLoaderCoreAPI | ||
42 | 42 | ||
43 | private static final String[] requiredDownstreamTransformers = { | 43 | private static final String[] requiredDownstreamTransformers = { |
44 | LiteLoaderCoreAPI.PKG_LITELOADER_COMMON + ".transformers.LiteLoaderPacketTransformer", | 44 | LiteLoaderCoreAPI.PKG_LITELOADER_COMMON + ".transformers.LiteLoaderPacketTransformer", |
45 | - LiteLoaderCoreAPIClient.PKG_LITELOADER_CLIENT + ".transformers.MinecraftTransformer", | ||
46 | LiteLoaderCoreAPI.PKG_LITELOADER + ".transformers.event.json.ModEventInjectionTransformer" | 45 | LiteLoaderCoreAPI.PKG_LITELOADER + ".transformers.event.json.ModEventInjectionTransformer" |
47 | }; | 46 | }; |
48 | 47 |
src/client/java/com/mumfrey/liteloader/client/gui/GuiLiteLoaderPanel.java
@@ -177,11 +177,10 @@ public class GuiLiteLoaderPanel extends GuiScreen | @@ -177,11 +177,10 @@ public class GuiLiteLoaderPanel extends GuiScreen | ||
177 | this.startupErrorCount = mods.getStartupErrorCount(); | 177 | this.startupErrorCount = mods.getStartupErrorCount(); |
178 | this.criticalErrorCount = mods.getCriticalErrorCount(); | 178 | this.criticalErrorCount = mods.getCriticalErrorCount(); |
179 | 179 | ||
180 | - String branding = LiteLoader.getBranding(); | ||
181 | - if (branding != null && branding.contains("SNAPSHOT")) | 180 | + this.isSnapshot = LiteLoader.isSnapshot(); |
181 | + if (this.isSnapshot) | ||
182 | { | 182 | { |
183 | - this.isSnapshot = true; | ||
184 | - this.versionText = "\247c" + branding; | 183 | + this.versionText = "\247c" + LiteLoader.getBranding(); |
185 | } | 184 | } |
186 | } | 185 | } |
187 | 186 | ||
@@ -524,6 +523,7 @@ public class GuiLiteLoaderPanel extends GuiScreen | @@ -524,6 +523,7 @@ public class GuiLiteLoaderPanel extends GuiScreen | ||
524 | 523 | ||
525 | if (annoyingTip) | 524 | if (annoyingTip) |
526 | { | 525 | { |
526 | + GuiLiteLoaderPanel.displayErrorToolTip = false; | ||
527 | this.drawNotificationTooltip(mouseX, mouseY - 13); | 527 | this.drawNotificationTooltip(mouseX, mouseY - 13); |
528 | } | 528 | } |
529 | } | 529 | } |
@@ -542,8 +542,11 @@ public class GuiLiteLoaderPanel extends GuiScreen | @@ -542,8 +542,11 @@ public class GuiLiteLoaderPanel extends GuiScreen | ||
542 | } | 542 | } |
543 | else if (this.notification != null) | 543 | else if (this.notification != null) |
544 | { | 544 | { |
545 | - GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, this.notification, left, top, this.width, this.height, | ||
546 | - GuiLiteLoaderPanel.NOTIFICATION_TOOLTIP_FOREGROUND, GuiLiteLoaderPanel.NOTIFICATION_TOOLTIP_BACKGROUND); | 545 | + boolean isCritical = this.notification.startsWith("!!"); |
546 | + String text = isCritical ? this.notification.substring(2) : this.notification; | ||
547 | + int bgColour = isCritical ? GuiLiteLoaderPanel.ERROR_TOOLTIP_BACKGROUND : GuiLiteLoaderPanel.NOTIFICATION_TOOLTIP_BACKGROUND; | ||
548 | + GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, text, left, top, this.width, this.height, | ||
549 | + GuiLiteLoaderPanel.NOTIFICATION_TOOLTIP_FOREGROUND, bgColour); | ||
547 | } | 550 | } |
548 | } | 551 | } |
549 | 552 | ||
@@ -739,21 +742,32 @@ public class GuiLiteLoaderPanel extends GuiScreen | @@ -739,21 +742,32 @@ public class GuiLiteLoaderPanel extends GuiScreen | ||
739 | * | 742 | * |
740 | * @param fontRenderer | 743 | * @param fontRenderer |
741 | * @param tooltipText | 744 | * @param tooltipText |
742 | - * @param mouseX | ||
743 | - * @param mouseY | 745 | + * @param left |
746 | + * @param top | ||
744 | * @param screenWidth | 747 | * @param screenWidth |
745 | * @param screenHeight | 748 | * @param screenHeight |
746 | * @param colour | 749 | * @param colour |
747 | * @param backgroundColour | 750 | * @param backgroundColour |
748 | */ | 751 | */ |
749 | - public static void drawTooltip(FontRenderer fontRenderer, String tooltipText, int mouseX, int mouseY, int screenWidth, int screenHeight, | 752 | + public static void drawTooltip(FontRenderer fontRenderer, String text, int left, int top, int screenWidth, int screenHeight, |
750 | int colour, int backgroundColour) | 753 | int colour, int backgroundColour) |
751 | { | 754 | { |
752 | - int textSize = fontRenderer.getStringWidth(tooltipText); | ||
753 | - mouseX = Math.max(0, Math.min(screenWidth - 4, mouseX - 4)); | ||
754 | - mouseY = Math.max(0, Math.min(screenHeight - 16, mouseY)); | ||
755 | - drawRect(mouseX - textSize - 2, mouseY, mouseX + 2, mouseY + 12, backgroundColour); | ||
756 | - fontRenderer.drawStringWithShadow(tooltipText, mouseX - textSize, mouseY + 2, colour); | 755 | + String[] lines = text.trim().split("\\r?\\n"); |
756 | + int textWidth = 0; | ||
757 | + int textHeight = 9 * lines.length; | ||
758 | + for (String line : lines) | ||
759 | + { | ||
760 | + textWidth = Math.max(textWidth, fontRenderer.getStringWidth(line)); | ||
761 | + top -= 9; | ||
762 | + } | ||
763 | + | ||
764 | + left = Math.max(0, Math.min(screenWidth - 4, left - 4)); | ||
765 | + top = Math.max(0, Math.min(screenHeight - 16, top + 9)); | ||
766 | + drawRect(left - textWidth - 2, top, left + 2, top + textHeight + 2, backgroundColour); | ||
767 | + for (String line : lines) | ||
768 | + { | ||
769 | + fontRenderer.drawStringWithShadow(line, left - textWidth, (top += 9) - 7, colour); | ||
770 | + } | ||
757 | } | 771 | } |
758 | 772 | ||
759 | 773 |
src/client/java/com/mumfrey/liteloader/client/gui/GuiPanelError.java
@@ -12,10 +12,12 @@ import java.util.List; | @@ -12,10 +12,12 @@ import java.util.List; | ||
12 | 12 | ||
13 | import org.lwjgl.input.Keyboard; | 13 | import org.lwjgl.input.Keyboard; |
14 | 14 | ||
15 | +import com.google.common.base.Joiner; | ||
15 | import com.mumfrey.liteloader.core.ModInfo; | 16 | import com.mumfrey.liteloader.core.ModInfo; |
16 | 17 | ||
17 | import net.minecraft.client.Minecraft; | 18 | import net.minecraft.client.Minecraft; |
18 | import net.minecraft.client.gui.GuiButton; | 19 | import net.minecraft.client.gui.GuiButton; |
20 | +import net.minecraft.client.gui.GuiScreen; | ||
19 | import net.minecraft.client.resources.I18n; | 21 | import net.minecraft.client.resources.I18n; |
20 | 22 | ||
21 | public class GuiPanelError extends GuiPanel implements ScrollPanelContent | 23 | public class GuiPanelError extends GuiPanel implements ScrollPanelContent |
@@ -98,6 +100,7 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent | @@ -98,6 +100,7 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent | ||
98 | 100 | ||
99 | this.scrollPane.setSizeAndPosition(MARGIN, TOP, this.width - (MARGIN * 2), this.height - TOP - BOTTOM); | 101 | this.scrollPane.setSizeAndPosition(MARGIN, TOP, this.width - (MARGIN * 2), this.height - TOP - BOTTOM); |
100 | this.controls.add(new GuiButton(0, this.width - 59 - MARGIN, this.height - BOTTOM + 9, 60, 20, I18n.format("gui.done"))); | 102 | this.controls.add(new GuiButton(0, this.width - 59 - MARGIN, this.height - BOTTOM + 9, 60, 20, I18n.format("gui.done"))); |
103 | + this.controls.add(new GuiButton(1, this.width - 204 - MARGIN, this.height - BOTTOM + 9, 140, 20, I18n.format("gui.error.copytoclipboard"))); | ||
101 | } | 104 | } |
102 | 105 | ||
103 | @Override | 106 | @Override |
@@ -131,7 +134,10 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent | @@ -131,7 +134,10 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent | ||
131 | @Override | 134 | @Override |
132 | void keyPressed(char keyChar, int keyCode) | 135 | void keyPressed(char keyChar, int keyCode) |
133 | { | 136 | { |
134 | - if (keyCode == Keyboard.KEY_ESCAPE) this.close(); | 137 | + if (keyCode == Keyboard.KEY_ESCAPE) |
138 | + { | ||
139 | + this.close(); | ||
140 | + } | ||
135 | } | 141 | } |
136 | 142 | ||
137 | @Override | 143 | @Override |
@@ -161,6 +167,14 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent | @@ -161,6 +167,14 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent | ||
161 | @Override | 167 | @Override |
162 | void actionPerformed(GuiButton control) | 168 | void actionPerformed(GuiButton control) |
163 | { | 169 | { |
164 | - if (control.id == 0) this.close(); | 170 | + if (control.id == 0) |
171 | + { | ||
172 | + this.close(); | ||
173 | + } | ||
174 | + | ||
175 | + if (control.id == 1) | ||
176 | + { | ||
177 | + GuiScreen.setClipboardString(Joiner.on('\n').join(this.scrollPaneContent)); | ||
178 | + } | ||
165 | } | 179 | } |
166 | } | 180 | } |
src/client/java/com/mumfrey/liteloader/client/gui/GuiPanelSettings.java
@@ -17,25 +17,29 @@ import net.minecraft.client.resources.I18n; | @@ -17,25 +17,29 @@ import net.minecraft.client.resources.I18n; | ||
17 | 17 | ||
18 | class GuiPanelSettings extends GuiPanel | 18 | class GuiPanelSettings extends GuiPanel |
19 | { | 19 | { |
20 | - private GuiLiteLoaderPanel parentScreen; | 20 | + private final GuiLiteLoaderPanel parentScreen; |
21 | + | ||
22 | + private final boolean isSnapshot; | ||
21 | 23 | ||
22 | - private GuiCheckbox chkShowTab, chkNoHide, chkForceUpdate; | 24 | + private GuiCheckbox chkShowTab, chkNoHide, chkForceUpdate, chkCheckForSnapshots; |
23 | 25 | ||
24 | private boolean hide; | 26 | private boolean hide; |
25 | 27 | ||
26 | private String[] helpText = new String[5]; | 28 | private String[] helpText = new String[5]; |
27 | - | 29 | + |
28 | GuiPanelSettings(GuiLiteLoaderPanel parentScreen, Minecraft minecraft) | 30 | GuiPanelSettings(GuiLiteLoaderPanel parentScreen, Minecraft minecraft) |
29 | { | 31 | { |
30 | super(minecraft); | 32 | super(minecraft); |
31 | 33 | ||
32 | this.parentScreen = parentScreen; | 34 | this.parentScreen = parentScreen; |
35 | + this.isSnapshot = LiteLoader.isSnapshot(); | ||
33 | 36 | ||
37 | + String helpKey = this.isSnapshot ? "checkforsnapshots" : "forceupdate"; | ||
34 | this.helpText[0] = I18n.format("gui.settings.showtab.help1"); | 38 | this.helpText[0] = I18n.format("gui.settings.showtab.help1"); |
35 | this.helpText[1] = I18n.format("gui.settings.showtab.help2"); | 39 | this.helpText[1] = I18n.format("gui.settings.showtab.help2"); |
36 | this.helpText[2] = I18n.format("gui.settings.notabhide.help1"); | 40 | this.helpText[2] = I18n.format("gui.settings.notabhide.help1"); |
37 | - this.helpText[3] = I18n.format("gui.settings.forceupdate.help1"); | ||
38 | - this.helpText[4] = I18n.format("gui.settings.forceupdate.help2"); | 41 | + this.helpText[3] = I18n.format("gui.settings." + helpKey + ".help1"); |
42 | + this.helpText[4] = I18n.format("gui.settings." + helpKey + ".help2"); | ||
39 | } | 43 | } |
40 | 44 | ||
41 | @Override | 45 | @Override |
@@ -61,6 +65,10 @@ class GuiPanelSettings extends GuiPanel | @@ -61,6 +65,10 @@ class GuiPanelSettings extends GuiPanel | ||
61 | this.controls.add(this.chkShowTab = new GuiCheckbox(0, 34, 90, I18n.format("gui.settings.showtab.label"))); | 65 | this.controls.add(this.chkShowTab = new GuiCheckbox(0, 34, 90, I18n.format("gui.settings.showtab.label"))); |
62 | this.controls.add(this.chkNoHide = new GuiCheckbox(1, 34, 128, I18n.format("gui.settings.notabhide.label"))); | 66 | this.controls.add(this.chkNoHide = new GuiCheckbox(1, 34, 128, I18n.format("gui.settings.notabhide.label"))); |
63 | this.controls.add(this.chkForceUpdate = new GuiCheckbox(2, 34, 158, I18n.format("gui.settings.forceupdate.label"))); | 67 | this.controls.add(this.chkForceUpdate = new GuiCheckbox(2, 34, 158, I18n.format("gui.settings.forceupdate.label"))); |
68 | + this.controls.add(this.chkCheckForSnapshots = new GuiCheckbox(2, 34, 158, I18n.format("gui.settings.checkforsnapshots.label"))); | ||
69 | + | ||
70 | + this.chkForceUpdate.visible = !this.isSnapshot; | ||
71 | + this.chkCheckForSnapshots.visible = this.isSnapshot; | ||
64 | 72 | ||
65 | this.updateCheckBoxes(); | 73 | this.updateCheckBoxes(); |
66 | } | 74 | } |
@@ -72,6 +80,7 @@ class GuiPanelSettings extends GuiPanel | @@ -72,6 +80,7 @@ class GuiPanelSettings extends GuiPanel | ||
72 | this.chkShowTab.checked = panelManager.isTabVisible(); | 80 | this.chkShowTab.checked = panelManager.isTabVisible(); |
73 | this.chkNoHide.checked = panelManager.isTabAlwaysExpanded(); | 81 | this.chkNoHide.checked = panelManager.isTabAlwaysExpanded(); |
74 | this.chkForceUpdate.checked = panelManager.isForceUpdateEnabled(); | 82 | this.chkForceUpdate.checked = panelManager.isForceUpdateEnabled(); |
83 | + this.chkCheckForSnapshots.checked = panelManager.isCheckForSnapshotsEnabled(); | ||
75 | } | 84 | } |
76 | 85 | ||
77 | private void updateSettings() | 86 | private void updateSettings() |
@@ -81,6 +90,7 @@ class GuiPanelSettings extends GuiPanel | @@ -81,6 +90,7 @@ class GuiPanelSettings extends GuiPanel | ||
81 | panelManager.setTabVisible(this.chkShowTab.checked); | 90 | panelManager.setTabVisible(this.chkShowTab.checked); |
82 | panelManager.setTabAlwaysExpanded(this.chkNoHide.checked); | 91 | panelManager.setTabAlwaysExpanded(this.chkNoHide.checked); |
83 | panelManager.setForceUpdateEnabled(this.chkForceUpdate.checked); | 92 | panelManager.setForceUpdateEnabled(this.chkForceUpdate.checked); |
93 | + panelManager.setCheckForSnapshotsEnabled(this.chkCheckForSnapshots.checked); | ||
84 | } | 94 | } |
85 | 95 | ||
86 | @Override | 96 | @Override |
src/client/java/com/mumfrey/liteloader/client/gui/modlist/ModList.java
@@ -15,6 +15,7 @@ import org.lwjgl.input.Keyboard; | @@ -15,6 +15,7 @@ import org.lwjgl.input.Keyboard; | ||
15 | import com.mumfrey.liteloader.LiteMod; | 15 | import com.mumfrey.liteloader.LiteMod; |
16 | import com.mumfrey.liteloader.api.ModInfoDecorator; | 16 | import com.mumfrey.liteloader.api.ModInfoDecorator; |
17 | import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel; | 17 | import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel; |
18 | +import com.mumfrey.liteloader.core.EnabledModsList.Enabled; | ||
18 | import com.mumfrey.liteloader.core.LiteLoaderMods; | 19 | import com.mumfrey.liteloader.core.LiteLoaderMods; |
19 | import com.mumfrey.liteloader.core.ModInfo; | 20 | import com.mumfrey.liteloader.core.ModInfo; |
20 | import com.mumfrey.liteloader.interfaces.Loadable; | 21 | import com.mumfrey.liteloader.interfaces.Loadable; |
@@ -75,9 +76,12 @@ public class ModList | @@ -75,9 +76,12 @@ public class ModList | ||
75 | // Disabled mods | 76 | // Disabled mods |
76 | for (ModInfo<?> disabledMod : mods.getDisabledMods()) | 77 | for (ModInfo<?> disabledMod : mods.getDisabledMods()) |
77 | { | 78 | { |
78 | - ModListEntry modListEntry = new ModListEntry(this, mods, environment, minecraft.fontRendererObj, brandColour, decorators, disabledMod); | 79 | + if (environment.getEnabledModsList().getEnabled(environment.getProfile(), disabledMod.getIdentifier()) != Enabled.FILTERED) |
80 | + { | ||
81 | + ModListEntry modListEntry = new ModListEntry(this, mods, environment, minecraft.fontRendererObj, brandColour, decorators, disabledMod); | ||
79 | sortedMods.put(modListEntry.getKey(), modListEntry); | 82 | sortedMods.put(modListEntry.getKey(), modListEntry); |
80 | } | 83 | } |
84 | + } | ||
81 | 85 | ||
82 | // Show bad containers if no other containers are found, should help users realise they have the wrong mod version! | 86 | // Show bad containers if no other containers are found, should help users realise they have the wrong mod version! |
83 | if (sortedMods.size() == 0) | 87 | if (sortedMods.size() == 0) |
src/client/java/com/mumfrey/liteloader/client/mixin/MixinMinecraft.java
@@ -19,7 +19,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | @@ -19,7 +19,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||
19 | import com.mumfrey.liteloader.PlayerInteractionListener.MouseButton; | 19 | import com.mumfrey.liteloader.PlayerInteractionListener.MouseButton; |
20 | import com.mumfrey.liteloader.client.LiteLoaderEventBrokerClient; | 20 | import com.mumfrey.liteloader.client.LiteLoaderEventBrokerClient; |
21 | import com.mumfrey.liteloader.client.ducks.IFramebuffer; | 21 | import com.mumfrey.liteloader.client.ducks.IFramebuffer; |
22 | +import com.mumfrey.liteloader.client.gui.startup.LoadingBar; | ||
22 | import com.mumfrey.liteloader.client.overlays.IMinecraft; | 23 | import com.mumfrey.liteloader.client.overlays.IMinecraft; |
24 | +import com.mumfrey.liteloader.launch.LiteLoaderTweaker; | ||
23 | 25 | ||
24 | import net.minecraft.client.Minecraft; | 26 | import net.minecraft.client.Minecraft; |
25 | import net.minecraft.client.renderer.OpenGlHelper; | 27 | import net.minecraft.client.renderer.OpenGlHelper; |
@@ -35,6 +37,7 @@ public abstract class MixinMinecraft implements IMinecraft | @@ -35,6 +37,7 @@ public abstract class MixinMinecraft implements IMinecraft | ||
35 | @Shadow @Final private List<IResourcePack> defaultResourcePacks; | 37 | @Shadow @Final private List<IResourcePack> defaultResourcePacks; |
36 | @Shadow private String serverName; | 38 | @Shadow private String serverName; |
37 | @Shadow private int serverPort; | 39 | @Shadow private int serverPort; |
40 | + @Shadow private boolean isGamePaused; | ||
38 | 41 | ||
39 | @Shadow abstract void resize(int width, int height); | 42 | @Shadow abstract void resize(int width, int height); |
40 | @Shadow private void clickMouse() {} | 43 | @Shadow private void clickMouse() {} |
@@ -43,6 +46,25 @@ public abstract class MixinMinecraft implements IMinecraft | @@ -43,6 +46,25 @@ public abstract class MixinMinecraft implements IMinecraft | ||
43 | 46 | ||
44 | private LiteLoaderEventBrokerClient broker; | 47 | private LiteLoaderEventBrokerClient broker; |
45 | 48 | ||
49 | + @Inject(method = "init()V", at = @At(value = "NEW", target = "net/minecraft/client/renderer/EntityRenderer")) | ||
50 | + private void init(CallbackInfo ci) | ||
51 | + { | ||
52 | + LiteLoaderTweaker.init(); | ||
53 | + LiteLoaderTweaker.postInit(); | ||
54 | + } | ||
55 | + | ||
56 | + @Inject(method = "init()V", at = @At(value = "NEW", target = "net/minecraft/client/renderer/texture/TextureMap")) | ||
57 | + private void initTextures(CallbackInfo ci) | ||
58 | + { | ||
59 | + LoadingBar.initTextures(); | ||
60 | + } | ||
61 | + | ||
62 | + @Inject(method = "init()V", at = @At("INVOKE")) | ||
63 | + private void progress(CallbackInfo ci) | ||
64 | + { | ||
65 | + LoadingBar.incrementProgress(); | ||
66 | + } | ||
67 | + | ||
46 | @Inject(method = "init()V", at = @At("RETURN")) | 68 | @Inject(method = "init()V", at = @At("RETURN")) |
47 | private void onStartupComplete(CallbackInfo ci) | 69 | private void onStartupComplete(CallbackInfo ci) |
48 | { | 70 | { |
@@ -79,7 +101,9 @@ public abstract class MixinMinecraft implements IMinecraft | @@ -79,7 +101,9 @@ public abstract class MixinMinecraft implements IMinecraft | ||
79 | )) | 101 | )) |
80 | private void onTick(CallbackInfo ci) | 102 | private void onTick(CallbackInfo ci) |
81 | { | 103 | { |
82 | - this.broker.onTick(); | 104 | + boolean clock = this.timer.elapsedTicks > 0; |
105 | + float partialTicks = this.timer.renderPartialTicks; | ||
106 | + this.broker.onTick(clock, partialTicks); | ||
83 | } | 107 | } |
84 | 108 | ||
85 | @Redirect(method = "runGameLoop()V", at = @At( | 109 | @Redirect(method = "runGameLoop()V", at = @At( |
src/client/java/com/mumfrey/liteloader/client/transformers/MinecraftTransformer.java deleted
100644 → 0
1 | -/* | ||
2 | - * This file is part of LiteLoader. | ||
3 | - * Copyright (C) 2012-16 Adam Mummery-Smith | ||
4 | - * All Rights Reserved. | ||
5 | - */ | ||
6 | -package com.mumfrey.liteloader.client.transformers; | ||
7 | - | ||
8 | -import java.util.Iterator; | ||
9 | - | ||
10 | -import org.objectweb.asm.Opcodes; | ||
11 | -import org.objectweb.asm.tree.AbstractInsnNode; | ||
12 | -import org.objectweb.asm.tree.ClassNode; | ||
13 | -import org.objectweb.asm.tree.InsnList; | ||
14 | -import org.objectweb.asm.tree.LdcInsnNode; | ||
15 | -import org.objectweb.asm.tree.MethodInsnNode; | ||
16 | -import org.objectweb.asm.tree.MethodNode; | ||
17 | -import org.objectweb.asm.tree.TypeInsnNode; | ||
18 | - | ||
19 | -import com.mumfrey.liteloader.core.runtime.Obf; | ||
20 | -import com.mumfrey.liteloader.launch.LiteLoaderTweaker; | ||
21 | -import com.mumfrey.liteloader.transformers.ClassTransformer; | ||
22 | -import com.mumfrey.liteloader.util.log.LiteLoaderLogger; | ||
23 | - | ||
24 | -public class MinecraftTransformer extends ClassTransformer | ||
25 | -{ | ||
26 | - private static final String TWEAKCLASS = LiteLoaderTweaker.class.getName().replace('.', '/'); | ||
27 | - | ||
28 | - @Override | ||
29 | - public byte[] transform(String name, String transformedName, byte[] basicClass) | ||
30 | - { | ||
31 | - if ((Obf.Minecraft.name.equals(transformedName) || Obf.Minecraft.obf.equals(transformedName))) | ||
32 | - { | ||
33 | - ClassNode classNode = this.readClass(basicClass, true); | ||
34 | - for (MethodNode method : classNode.methods) | ||
35 | - { | ||
36 | - if (Obf.startGame.obf.equals(method.name) || Obf.startGame.srg.equals(method.name) || Obf.startGame.name.equals(method.name)) | ||
37 | - { | ||
38 | - this.transformStartGame(method); | ||
39 | - } | ||
40 | - } | ||
41 | - return this.writeClass(classNode); | ||
42 | - } | ||
43 | - return basicClass; | ||
44 | - } | ||
45 | - | ||
46 | - | ||
47 | - private void transformStartGame(MethodNode method) | ||
48 | - { | ||
49 | - InsnList insns = new InsnList(); | ||
50 | - | ||
51 | - boolean loadingBarEnabled = LiteLoaderTweaker.loadingBarEnabled(); | ||
52 | - boolean found = false; | ||
53 | - | ||
54 | - Iterator<AbstractInsnNode> iter = method.instructions.iterator(); | ||
55 | - while (iter.hasNext()) | ||
56 | - { | ||
57 | - AbstractInsnNode insn = iter.next(); | ||
58 | - if (loadingBarEnabled && insn instanceof MethodInsnNode) | ||
59 | - { | ||
60 | - insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Obf.LoadingBar.ref, "incrementProgress", "()V", false)); | ||
61 | - } | ||
62 | - | ||
63 | - insns.add(insn); | ||
64 | - | ||
65 | - if (insn instanceof TypeInsnNode && insn.getOpcode() == Opcodes.NEW && insns.getLast() != null) | ||
66 | - { | ||
67 | - TypeInsnNode typeNode = (TypeInsnNode)insn; | ||
68 | - if (!found && (Obf.EntityRenderer.obf.equals(typeNode.desc) || Obf.EntityRenderer.ref.equals(typeNode.desc))) | ||
69 | - { | ||
70 | - LiteLoaderLogger.info("MinecraftTransformer found INIT injection point, this is good."); | ||
71 | - found = true; | ||
72 | - | ||
73 | - insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, MinecraftTransformer.TWEAKCLASS, Obf.init.name, "()V", false)); | ||
74 | - insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, MinecraftTransformer.TWEAKCLASS, Obf.postInit.name, "()V", false)); | ||
75 | - } | ||
76 | - } | ||
77 | - | ||
78 | - if (loadingBarEnabled && insn instanceof LdcInsnNode) | ||
79 | - { | ||
80 | - LdcInsnNode ldcInsn = (LdcInsnNode)insn; | ||
81 | - if ("textures/blocks".equals(ldcInsn.cst)) | ||
82 | - { | ||
83 | - insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Obf.LoadingBar.ref, "initTextures", "()V", false)); | ||
84 | - } | ||
85 | - } | ||
86 | - } | ||
87 | - | ||
88 | - method.instructions = insns; | ||
89 | - | ||
90 | - if (!found) LiteLoaderLogger.severe("MinecraftTransformer failed to find INIT injection point, the game will probably crash pretty soon."); | ||
91 | - } | ||
92 | -} |
src/client/java/com/mumfrey/liteloader/modconfig/AbstractConfigPanel.java
@@ -7,15 +7,21 @@ package com.mumfrey.liteloader.modconfig; | @@ -7,15 +7,21 @@ package com.mumfrey.liteloader.modconfig; | ||
7 | 7 | ||
8 | import java.util.ArrayList; | 8 | import java.util.ArrayList; |
9 | import java.util.List; | 9 | import java.util.List; |
10 | +import java.util.regex.Pattern; | ||
10 | 11 | ||
11 | import org.lwjgl.input.Keyboard; | 12 | import org.lwjgl.input.Keyboard; |
12 | 13 | ||
14 | +import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel; | ||
13 | import com.mumfrey.liteloader.client.mixin.IGuiButton; | 15 | import com.mumfrey.liteloader.client.mixin.IGuiButton; |
14 | 16 | ||
15 | import net.minecraft.client.Minecraft; | 17 | import net.minecraft.client.Minecraft; |
18 | +import net.minecraft.client.gui.FontRenderer; | ||
16 | import net.minecraft.client.gui.GuiButton; | 19 | import net.minecraft.client.gui.GuiButton; |
17 | import net.minecraft.client.gui.GuiLabel; | 20 | import net.minecraft.client.gui.GuiLabel; |
18 | import net.minecraft.client.gui.GuiScreen; | 21 | import net.minecraft.client.gui.GuiScreen; |
22 | +import net.minecraft.client.gui.GuiTextField; | ||
23 | +import net.minecraft.client.renderer.RenderHelper; | ||
24 | +import net.minecraft.client.resources.I18n; | ||
19 | 25 | ||
20 | /** | 26 | /** |
21 | * A general-purpose base class for mod config panels which implements a lot of | 27 | * A general-purpose base class for mod config panels which implements a lot of |
@@ -42,74 +48,361 @@ public abstract class AbstractConfigPanel implements ConfigPanel | @@ -42,74 +48,361 @@ public abstract class AbstractConfigPanel implements ConfigPanel | ||
42 | } | 48 | } |
43 | 49 | ||
44 | /** | 50 | /** |
45 | - * Struct which keeps a control together with its callback object | 51 | + * A handle to an option text field, used to get and retrieve text and set |
52 | + * the max length. It is possible to obtain the native text field as well, | ||
53 | + * however caution should be used when doing so to avoid breaking the | ||
54 | + * contract of the text field wrapper used in the config panel itself. | ||
55 | + */ | ||
56 | + public interface ConfigTextField | ||
57 | + { | ||
58 | + /** | ||
59 | + * Get the inner text field | ||
60 | + */ | ||
61 | + public abstract GuiTextField getNativeTextField(); | ||
62 | + | ||
63 | + /** | ||
64 | + * Get the text field's text | ||
65 | + */ | ||
66 | + public abstract String getText(); | ||
67 | + | ||
68 | + /** | ||
69 | + * Set the text field's text | ||
70 | + * | ||
71 | + * @param text text to set | ||
72 | + * @return fluent interface | ||
73 | + */ | ||
74 | + public abstract ConfigTextField setText(String text); | ||
75 | + | ||
76 | + /** | ||
77 | + * Set a validation regex for this text box. | ||
78 | + * | ||
79 | + * @param regex Validation regex to use for this text field | ||
80 | + * @param force If set to <tt>false</tt>, invalid values will only cause | ||
81 | + * the text field to display an error when invalid text is present. | ||
82 | + * If set to <tt>true</tt>, invalid values will be forcibly | ||
83 | + * prohibited from being entered. | ||
84 | + * @return fluent interfaces | ||
85 | + */ | ||
86 | + public abstract ConfigTextField setRegex(String regex, boolean force); | ||
87 | + | ||
88 | + /** | ||
89 | + * If the validation regex is not set, always returns true. Otherwise | ||
90 | + * returns true if the current text value matches the validation regex. | ||
91 | + * | ||
92 | + * @return validation state of the current text value | ||
93 | + */ | ||
94 | + public abstract boolean isValid(); | ||
95 | + | ||
96 | + /** | ||
97 | + * Set the max allowed string length, defaults to 32 | ||
46 | * | 98 | * |
47 | - * @param <T> control type | 99 | + * @param maxLength max string length to use |
100 | + * @return fluent interface | ||
101 | + */ | ||
102 | + public abstract ConfigTextField setMaxLength(int maxLength); | ||
103 | + } | ||
104 | + | ||
105 | + /** | ||
106 | + * Base for config option handle structs | ||
48 | */ | 107 | */ |
49 | - class ConfigOption<T extends GuiButton> | 108 | + static abstract class ConfigOption |
50 | { | 109 | { |
51 | - final GuiLabel label; | ||
52 | - final T control; | ||
53 | - final ConfigOptionListener<T> listener; | 110 | + void onTick() |
111 | + { | ||
112 | + } | ||
113 | + | ||
114 | + abstract void draw(Minecraft minecraft, int mouseX, int mouseY, float partialTicks); | ||
115 | + | ||
116 | + void mouseReleased(Minecraft minecraft, int mouseX, int mouseY) | ||
117 | + { | ||
118 | + } | ||
119 | + | ||
120 | + boolean mousePressed(Minecraft minecraft, int mouseX, int mouseY) | ||
121 | + { | ||
122 | + return false; | ||
123 | + } | ||
54 | 124 | ||
55 | - ConfigOption(GuiLabel label) | 125 | + boolean keyPressed(Minecraft minecraft, char keyChar, int keyCode) |
126 | + { | ||
127 | + return false; | ||
128 | + } | ||
129 | + } | ||
130 | + | ||
131 | + /** | ||
132 | + * Struct for labels | ||
133 | + */ | ||
134 | + static class ConfigOptionLabel extends ConfigOption | ||
135 | + { | ||
136 | + private final GuiLabel label; | ||
137 | + | ||
138 | + ConfigOptionLabel(GuiLabel label) | ||
56 | { | 139 | { |
57 | this.label = label; | 140 | this.label = label; |
58 | - this.control = null; | ||
59 | - this.listener = null; | ||
60 | } | 141 | } |
61 | 142 | ||
62 | - ConfigOption(T control, ConfigOptionListener<T> listener) | 143 | + @Override |
144 | + void draw(Minecraft minecraft, int mouseX, int mouseY, float partialTicks) | ||
145 | + { | ||
146 | + this.label.drawLabel(minecraft, mouseX, mouseY); | ||
147 | + } | ||
148 | + } | ||
149 | + | ||
150 | + /** | ||
151 | + * Struct which keeps a control together with its callback object | ||
152 | + * | ||
153 | + * @param <T> control type | ||
154 | + */ | ||
155 | + static class ConfigOptionButton<T extends GuiButton> extends ConfigOption | ||
156 | + { | ||
157 | + private final T control; | ||
158 | + private final ConfigOptionListener<T> listener; | ||
159 | + | ||
160 | + ConfigOptionButton(T control, ConfigOptionListener<T> listener) | ||
63 | { | 161 | { |
64 | - this.label = null; | ||
65 | this.control = control; | 162 | this.control = control; |
66 | this.listener = listener; | 163 | this.listener = listener; |
67 | } | 164 | } |
68 | 165 | ||
166 | + @Override | ||
69 | void draw(Minecraft minecraft, int mouseX, int mouseY, float partialTicks) | 167 | void draw(Minecraft minecraft, int mouseX, int mouseY, float partialTicks) |
70 | { | 168 | { |
71 | - if (this.label != null) | 169 | + this.control.drawButton(minecraft, mouseX, mouseY); |
170 | + } | ||
171 | + | ||
172 | + @Override | ||
173 | + boolean mousePressed(Minecraft minecraft, int mouseX, int mouseY) | ||
174 | + { | ||
175 | + if (this.control.mousePressed(minecraft, mouseX, mouseY)) | ||
176 | + { | ||
177 | + this.control.playPressSound(minecraft.getSoundHandler()); | ||
178 | + if (this.listener != null) | ||
179 | + { | ||
180 | + this.listener.actionPerformed(this.control); | ||
181 | + } | ||
182 | + return true; | ||
183 | + } | ||
184 | + | ||
185 | + return false; | ||
186 | + } | ||
187 | + | ||
188 | + @Override | ||
189 | + void mouseReleased(Minecraft minecraft, int mouseX, int mouseY) | ||
190 | + { | ||
191 | + this.control.mouseReleased(mouseX, mouseY); | ||
192 | + } | ||
193 | + } | ||
194 | + | ||
195 | + /** | ||
196 | + * Struct for text fields | ||
197 | + */ | ||
198 | + class ConfigOptionTextField extends ConfigOption implements ConfigTextField | ||
199 | + { | ||
200 | + /** | ||
201 | + * List for accessing via tab order | ||
202 | + */ | ||
203 | + private final List<GuiConfigTextField> tabOrder; | ||
204 | + | ||
205 | + /** | ||
206 | + * Tab index | ||
207 | + */ | ||
208 | + private final int tabIndex; | ||
209 | + | ||
210 | + /** | ||
211 | + * Inner text field | ||
212 | + */ | ||
213 | + private final GuiConfigTextField textField; | ||
214 | + | ||
215 | + ConfigOptionTextField(List<GuiConfigTextField> tabOrder, GuiConfigTextField textField) | ||
216 | + { | ||
217 | + this.tabOrder = tabOrder; | ||
218 | + this.tabIndex = tabOrder.indexOf(textField); | ||
219 | + this.textField = textField; | ||
220 | + | ||
221 | + if (this.tabIndex == 0) | ||
72 | { | 222 | { |
73 | - this.label.drawLabel(minecraft, mouseX, mouseY); | 223 | + textField.setFocused(true); |
224 | + } | ||
74 | } | 225 | } |
75 | 226 | ||
76 | - if (this.control != null) | 227 | + @Override |
228 | + void onTick() | ||
77 | { | 229 | { |
78 | - this.control.drawButton(minecraft, mouseX, mouseY); | 230 | + this.textField.updateCursorCounter(); |
79 | } | 231 | } |
232 | + | ||
233 | + @Override | ||
234 | + void draw(Minecraft minecraft, int mouseX, int mouseY, float partialTicks) | ||
235 | + { | ||
236 | + this.textField.drawTextBox(mouseX, mouseY); | ||
80 | } | 237 | } |
81 | 238 | ||
239 | + @Override | ||
82 | boolean mousePressed(Minecraft minecraft, int mouseX, int mouseY) | 240 | boolean mousePressed(Minecraft minecraft, int mouseX, int mouseY) |
83 | { | 241 | { |
84 | - if (this.control != null && this.control.mousePressed(minecraft, mouseX, mouseY)) | 242 | + this.textField.mouseClicked(mouseX, mouseY, 0); |
243 | + if (this.textField.isFocused()) | ||
85 | { | 244 | { |
86 | - this.control.playPressSound(minecraft.getSoundHandler()); | ||
87 | - if (this.listener != null) | 245 | + // Unfocus all other text fields |
246 | + for (GuiTextField textField : this.tabOrder) | ||
88 | { | 247 | { |
89 | - this.listener.actionPerformed(this.control); | 248 | + if (textField != this.textField) |
249 | + { | ||
250 | + textField.setFocused(false); | ||
251 | + } | ||
90 | } | 252 | } |
253 | + } | ||
254 | + | ||
255 | + return false; | ||
256 | + } | ||
257 | + | ||
258 | + @Override | ||
259 | + boolean keyPressed(Minecraft minecraft, char keyChar, int keyCode) | ||
260 | + { | ||
261 | + if (!this.textField.isFocused()) | ||
262 | + { | ||
263 | + return false; | ||
264 | + } | ||
265 | + | ||
266 | + if (keyCode == Keyboard.KEY_TAB) | ||
267 | + { | ||
268 | + this.textField.setFocused(false); | ||
269 | + int tabOrderSize = this.tabOrder.size(); | ||
270 | + this.tabOrder.get((this.tabIndex + (GuiScreen.isShiftKeyDown() ? -1 : 1) + tabOrderSize) % tabOrderSize).setFocused(true); | ||
91 | return true; | 271 | return true; |
92 | } | 272 | } |
93 | 273 | ||
274 | + return this.textField.textboxKeyTyped(keyChar, keyCode); | ||
275 | + } | ||
276 | + | ||
277 | + @Override | ||
278 | + public GuiTextField getNativeTextField() | ||
279 | + { | ||
280 | + return this.textField; | ||
281 | + } | ||
282 | + | ||
283 | + @Override | ||
284 | + public String getText() | ||
285 | + { | ||
286 | + return this.textField.getText(); | ||
287 | + } | ||
288 | + | ||
289 | + @Override | ||
290 | + public ConfigTextField setText(String text) | ||
291 | + { | ||
292 | + this.textField.setText(text); | ||
293 | + return this; | ||
294 | + } | ||
295 | + | ||
296 | + @Override | ||
297 | + public ConfigTextField setMaxLength(int maxLength) | ||
298 | + { | ||
299 | + this.textField.setMaxStringLength(maxLength); | ||
300 | + return this; | ||
301 | + } | ||
302 | + | ||
303 | + @Override | ||
304 | + public ConfigTextField setRegex(String regex, boolean force) | ||
305 | + { | ||
306 | + this.textField.setRegex(Pattern.compile(regex), force);; | ||
307 | + return this; | ||
308 | + } | ||
309 | + | ||
310 | + @Override | ||
311 | + public boolean isValid() | ||
312 | + { | ||
313 | + return this.textField.isValid(); | ||
314 | + } | ||
315 | + } | ||
316 | + | ||
317 | + /** | ||
318 | + * Custom text field which supports "soft" validation by regex (draws red | ||
319 | + * border and error message when invalid) | ||
320 | + */ | ||
321 | + class GuiConfigTextField extends GuiTextField | ||
322 | + { | ||
323 | + private final FontRenderer fontRenderer; | ||
324 | + private final int width, height; | ||
325 | + private Pattern regex; | ||
326 | + private boolean valid, drawing; | ||
327 | + | ||
328 | + GuiConfigTextField(int id, FontRenderer fontRenderer, int x, int y, int width, int height) | ||
329 | + { | ||
330 | + super(id, fontRenderer, x, y, width, height); | ||
331 | + this.fontRenderer = fontRenderer; | ||
332 | + this.width = width; | ||
333 | + this.height = height; | ||
334 | + this.setRegex(null, false); | ||
335 | + } | ||
336 | + | ||
337 | + void setRegex(Pattern regex, boolean restrict) | ||
338 | + { | ||
339 | + if (restrict && regex != null) | ||
340 | + { | ||
341 | + this.setValidator((text) -> regex.matcher(text).matches()); | ||
342 | + this.regex = null; | ||
343 | + } | ||
344 | + else | ||
345 | + { | ||
346 | + this.setValidator((text) -> { | ||
347 | + this.validate(text); | ||
348 | + return true; | ||
349 | + }); | ||
350 | + this.regex = regex; | ||
351 | + this.validate(this.getText()); | ||
352 | + } | ||
353 | + } | ||
354 | + | ||
355 | + private boolean validate(String text) | ||
356 | + { | ||
357 | + this.valid = (this.regex == null || this.regex.matcher(text).matches()); | ||
358 | + return true; | ||
359 | + } | ||
360 | + | ||
361 | + boolean isValid() | ||
362 | + { | ||
363 | + return this.valid; | ||
364 | + } | ||
365 | + | ||
366 | + @Override | ||
367 | + public boolean getEnableBackgroundDrawing() | ||
368 | + { | ||
369 | + boolean bg = super.getEnableBackgroundDrawing(); | ||
370 | + if (bg && this.drawing && !this.isValid()) | ||
371 | + { | ||
372 | + drawRect(this.xPosition - 1, this.yPosition - 1, this.xPosition + this.width + 1, this.yPosition + this.height + 1, 0xFFFF5555); | ||
373 | + drawRect(this.xPosition, this.yPosition, this.xPosition + this.width, this.yPosition + this.height, 0xFF000000); | ||
94 | return false; | 374 | return false; |
95 | } | 375 | } |
96 | 376 | ||
97 | - void mouseReleased(Minecraft mc, int mouseX, int mouseY) | 377 | + return bg; |
378 | + } | ||
379 | + | ||
380 | + public void drawTextBox(int mouseX, int mouseY) | ||
98 | { | 381 | { |
99 | - if (this.control != null) | 382 | + this.drawing = true; |
383 | + super.drawTextBox(); | ||
384 | + if (!this.isValid()) | ||
385 | + { | ||
386 | + drawRect(this.xPosition + this.width - 10, this.yPosition, this.xPosition + this.width, this.yPosition + this.height, 0x66000000); | ||
387 | + this.fontRenderer.drawString("\247l!", this.xPosition + this.width - 6, this.yPosition + (this.height / 2) - 4, 0xFFFF5555); | ||
388 | + if (mouseX >= this.xPosition && mouseX < this.xPosition + this.width && mouseY >= this.yPosition && mouseY < this.yPosition + this.height) | ||
100 | { | 389 | { |
101 | - this.control.mouseReleased(mouseX, mouseY); | 390 | + AbstractConfigPanel.this.drawHoveringText(I18n.format("gui.invalidvalue"), mouseX, mouseY); |
391 | + } | ||
102 | } | 392 | } |
393 | + this.drawing = false; | ||
103 | } | 394 | } |
104 | } | 395 | } |
105 | 396 | ||
106 | protected final Minecraft mc; | 397 | protected final Minecraft mc; |
107 | 398 | ||
108 | - private final List<ConfigOption<?>> options = new ArrayList<ConfigOption<?>>(); | 399 | + private final List<ConfigOption> options = new ArrayList<ConfigOption>(); |
400 | + | ||
401 | + private final List<GuiConfigTextField> textFields = new ArrayList<GuiConfigTextField>(); | ||
109 | 402 | ||
110 | private int contentHeight = 0; | 403 | private int contentHeight = 0; |
111 | 404 | ||
112 | - private ConfigOption<?> selected; | 405 | + private ConfigOption selected; |
113 | 406 | ||
114 | public AbstractConfigPanel() | 407 | public AbstractConfigPanel() |
115 | { | 408 | { |
@@ -170,7 +463,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel | @@ -170,7 +463,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel | ||
170 | label.addLine(line); | 463 | label.addLine(line); |
171 | } | 464 | } |
172 | this.contentHeight = Math.max(y + height, this.contentHeight); | 465 | this.contentHeight = Math.max(y + height, this.contentHeight); |
173 | - this.options.add(new ConfigOption<GuiButton>(label)); | 466 | + this.options.add(new ConfigOptionLabel(label)); |
174 | } | 467 | } |
175 | 468 | ||
176 | /** | 469 | /** |
@@ -185,12 +478,33 @@ public abstract class AbstractConfigPanel implements ConfigPanel | @@ -185,12 +478,33 @@ public abstract class AbstractConfigPanel implements ConfigPanel | ||
185 | if (control != null) | 478 | if (control != null) |
186 | { | 479 | { |
187 | this.contentHeight = Math.max(control.yPosition + ((IGuiButton)control).getButtonHeight(), this.contentHeight); | 480 | this.contentHeight = Math.max(control.yPosition + ((IGuiButton)control).getButtonHeight(), this.contentHeight); |
188 | - this.options.add(new ConfigOption<T>(control, listener)); | 481 | + this.options.add(new ConfigOptionButton<T>(control, listener)); |
189 | } | 482 | } |
190 | 483 | ||
191 | return control; | 484 | return control; |
192 | } | 485 | } |
193 | 486 | ||
487 | + /** | ||
488 | + * Add a text field to the panel, returns a handle through which the created | ||
489 | + * text field can be accessed | ||
490 | + * | ||
491 | + * @param id control id | ||
492 | + * @param x text field x position | ||
493 | + * @param y text field y position | ||
494 | + * @param width text field width | ||
495 | + * @param height text field height | ||
496 | + * @return text field handle | ||
497 | + */ | ||
498 | + protected ConfigTextField addTextField(int id, int x, int y, int width, int height) | ||
499 | + { | ||
500 | + GuiConfigTextField textField = new GuiConfigTextField(id, this.mc.fontRendererObj, x + 2, y, width, height); | ||
501 | + this.textFields.add(textField); | ||
502 | + | ||
503 | + ConfigOptionTextField configOption = new ConfigOptionTextField(this.textFields, textField); | ||
504 | + this.options.add(configOption); | ||
505 | + return configOption; | ||
506 | + } | ||
507 | + | ||
194 | @Override | 508 | @Override |
195 | public void onPanelResize(ConfigPanelHost host) | 509 | public void onPanelResize(ConfigPanelHost host) |
196 | { | 510 | { |
@@ -199,12 +513,16 @@ public abstract class AbstractConfigPanel implements ConfigPanel | @@ -199,12 +513,16 @@ public abstract class AbstractConfigPanel implements ConfigPanel | ||
199 | @Override | 513 | @Override |
200 | public void onTick(ConfigPanelHost host) | 514 | public void onTick(ConfigPanelHost host) |
201 | { | 515 | { |
516 | + for (ConfigOption configOption : this.options) | ||
517 | + { | ||
518 | + configOption.onTick(); | ||
519 | + } | ||
202 | } | 520 | } |
203 | 521 | ||
204 | @Override | 522 | @Override |
205 | public void drawPanel(ConfigPanelHost host, int mouseX, int mouseY, float partialTicks) | 523 | public void drawPanel(ConfigPanelHost host, int mouseX, int mouseY, float partialTicks) |
206 | { | 524 | { |
207 | - for (ConfigOption<?> configOption : this.options) | 525 | + for (ConfigOption configOption : this.options) |
208 | { | 526 | { |
209 | configOption.draw(this.mc, mouseX, mouseY, partialTicks); | 527 | configOption.draw(this.mc, mouseX, mouseY, partialTicks); |
210 | } | 528 | } |
@@ -219,7 +537,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel | @@ -219,7 +537,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel | ||
219 | return; | 537 | return; |
220 | } | 538 | } |
221 | 539 | ||
222 | - for (ConfigOption<?> configOption : this.options) | 540 | + for (ConfigOption configOption : this.options) |
223 | { | 541 | { |
224 | if (configOption.mousePressed(this.mc, mouseX, mouseY)) | 542 | if (configOption.mousePressed(this.mc, mouseX, mouseY)) |
225 | { | 543 | { |
@@ -251,5 +569,22 @@ public abstract class AbstractConfigPanel implements ConfigPanel | @@ -251,5 +569,22 @@ public abstract class AbstractConfigPanel implements ConfigPanel | ||
251 | host.close(); | 569 | host.close(); |
252 | return; | 570 | return; |
253 | } | 571 | } |
572 | + | ||
573 | + for (ConfigOption configOption : this.options) | ||
574 | + { | ||
575 | + if (configOption.keyPressed(this.mc, keyChar, keyCode)) | ||
576 | + { | ||
577 | + break; | ||
578 | + } | ||
579 | + } | ||
580 | + } | ||
581 | + | ||
582 | + protected final void drawHoveringText(String text, int x, int y) | ||
583 | + { | ||
584 | + if (this.mc.currentScreen != null) | ||
585 | + { | ||
586 | + GuiLiteLoaderPanel.drawTooltip(this.mc.fontRendererObj, text, x, y, Integer.MAX_VALUE, Integer.MAX_VALUE, 0xFFFF5555, 0xB0000000); | ||
587 | + RenderHelper.disableStandardItemLighting(); | ||
588 | + } | ||
254 | } | 589 | } |
255 | } | 590 | } |
src/client/resources/mixins.liteloader.client.json
1 | { | 1 | { |
2 | "required": true, | 2 | "required": true, |
3 | - "minVersion": "0.6", | 3 | + "minVersion": "0.7", |
4 | + "compatibilityLevel": "JAVA_8", | ||
4 | "target": "@env(DEFAULT)", | 5 | "target": "@env(DEFAULT)", |
5 | "package": "com.mumfrey.liteloader.client.mixin", | 6 | "package": "com.mumfrey.liteloader.client.mixin", |
6 | "refmap": "mixins.liteloader.client.refmap.json", | 7 | "refmap": "mixins.liteloader.client.refmap.json", |
src/main/java/com/mumfrey/liteloader/core/EnabledModsList.java
@@ -24,6 +24,34 @@ import com.google.gson.GsonBuilder; | @@ -24,6 +24,34 @@ import com.google.gson.GsonBuilder; | ||
24 | */ | 24 | */ |
25 | public final class EnabledModsList | 25 | public final class EnabledModsList |
26 | { | 26 | { |
27 | + /** | ||
28 | + * Tristate for enablement which allows us to determine whether mod is | ||
29 | + * forcibly disabled by user or passively disabled by mod name filter | ||
30 | + */ | ||
31 | + public enum Enabled | ||
32 | + { | ||
33 | + ENABLED(true), | ||
34 | + DISABLED(false), | ||
35 | + FILTERED(false); | ||
36 | + | ||
37 | + private final boolean value; | ||
38 | + | ||
39 | + private Enabled(boolean value) | ||
40 | + { | ||
41 | + this.value = value; | ||
42 | + } | ||
43 | + | ||
44 | + public boolean booleanValue() | ||
45 | + { | ||
46 | + return this.value; | ||
47 | + } | ||
48 | + | ||
49 | + public static Enabled of(Boolean value) | ||
50 | + { | ||
51 | + return value == null ? Enabled.FILTERED : (value ? Enabled.ENABLED : Enabled.DISABLED); | ||
52 | + } | ||
53 | + } | ||
54 | + | ||
27 | @SuppressWarnings("unused") | 55 | @SuppressWarnings("unused") |
28 | private static final transient long serialVersionUID = -6449451105617763769L; | 56 | private static final transient long serialVersionUID = -6449451105617763769L; |
29 | 57 | ||
@@ -45,7 +73,7 @@ public final class EnabledModsList | @@ -45,7 +73,7 @@ public final class EnabledModsList | ||
45 | * the mods list because the command line is supposed to be an override | 73 | * the mods list because the command line is supposed to be an override |
46 | * rather than a new mask. These two values provide this behaviour. | 74 | * rather than a new mask. These two values provide this behaviour. |
47 | */ | 75 | */ |
48 | - private transient Boolean defaultEnabledValue = Boolean.TRUE; | 76 | + private transient Enabled defaultEnabledValue = Enabled.ENABLED; |
49 | private transient boolean allowSave = true; | 77 | private transient boolean allowSave = true; |
50 | 78 | ||
51 | /** | 79 | /** |
@@ -59,22 +87,27 @@ public final class EnabledModsList | @@ -59,22 +87,27 @@ public final class EnabledModsList | ||
59 | } | 87 | } |
60 | 88 | ||
61 | /** | 89 | /** |
62 | - * Check whether a particular mod is enabled | 90 | + * Check whether a particular container is enabled |
63 | * | 91 | * |
64 | * @param profileName | 92 | * @param profileName |
65 | * @param identifier | 93 | * @param identifier |
66 | */ | 94 | */ |
67 | public boolean isEnabled(String profileName, String identifier) | 95 | public boolean isEnabled(String profileName, String identifier) |
68 | { | 96 | { |
97 | + return this.getEnabled(profileName, identifier).booleanValue(); | ||
98 | + } | ||
99 | + | ||
100 | + public Enabled getEnabled(String profileName, String identifier) | ||
101 | + { | ||
69 | Map<String, Boolean> profile = this.getProfile(profileName); | 102 | Map<String, Boolean> profile = this.getProfile(profileName); |
70 | identifier = identifier.toLowerCase().trim(); | 103 | identifier = identifier.toLowerCase().trim(); |
71 | 104 | ||
72 | - if (!profile.containsKey(identifier)) | 105 | + if (!profile.containsKey(identifier) && this.defaultEnabledValue != Enabled.FILTERED) |
73 | { | 106 | { |
74 | - profile.put(identifier, this.defaultEnabledValue); | 107 | + profile.put(identifier, this.defaultEnabledValue.booleanValue()); |
75 | } | 108 | } |
76 | 109 | ||
77 | - return profile.get(identifier); | 110 | + return Enabled.of(profile.get(identifier)); |
78 | } | 111 | } |
79 | 112 | ||
80 | /** | 113 | /** |
@@ -87,7 +120,7 @@ public final class EnabledModsList | @@ -87,7 +120,7 @@ public final class EnabledModsList | ||
87 | public void setEnabled(String profileName, String identifier, boolean enabled) | 120 | public void setEnabled(String profileName, String identifier, boolean enabled) |
88 | { | 121 | { |
89 | Map<String, Boolean> profile = this.getProfile(profileName); | 122 | Map<String, Boolean> profile = this.getProfile(profileName); |
90 | - profile.put(identifier.toLowerCase().trim(), Boolean.valueOf(enabled)); | 123 | + profile.put(identifier.toLowerCase().trim(), enabled ? Boolean.TRUE : Boolean.FALSE); |
91 | 124 | ||
92 | this.allowSave = true; | 125 | this.allowSave = true; |
93 | } | 126 | } |
@@ -106,12 +139,9 @@ public final class EnabledModsList | @@ -106,12 +139,9 @@ public final class EnabledModsList | ||
106 | { | 139 | { |
107 | if (modNameFilter != null) | 140 | if (modNameFilter != null) |
108 | { | 141 | { |
109 | - for (String modName : profile.keySet()) | ||
110 | - { | ||
111 | - profile.put(modName, Boolean.FALSE); | ||
112 | - } | 142 | + profile.clear(); |
113 | 143 | ||
114 | - this.defaultEnabledValue = Boolean.FALSE; | 144 | + this.defaultEnabledValue = Enabled.FILTERED; |
115 | this.allowSave = false; | 145 | this.allowSave = false; |
116 | 146 | ||
117 | for (String filterEntry : modNameFilter) | 147 | for (String filterEntry : modNameFilter) |
@@ -122,8 +152,8 @@ public final class EnabledModsList | @@ -122,8 +152,8 @@ public final class EnabledModsList | ||
122 | } | 152 | } |
123 | catch (Exception ex) | 153 | catch (Exception ex) |
124 | { | 154 | { |
125 | - this.defaultEnabledValue = Boolean.TRUE; | ||
126 | - this.allowSave = true; | 155 | + this.defaultEnabledValue = Enabled.ENABLED; |
156 | +// this.allowSave = true; | ||
127 | } | 157 | } |
128 | } | 158 | } |
129 | 159 | ||
@@ -135,7 +165,7 @@ public final class EnabledModsList | @@ -135,7 +165,7 @@ public final class EnabledModsList | ||
135 | private Map<String, Boolean> getProfile(String profileName) | 165 | private Map<String, Boolean> getProfile(String profileName) |
136 | { | 166 | { |
137 | if (profileName == null) profileName = "default"; | 167 | if (profileName == null) profileName = "default"; |
138 | - if (this.mods == null) this.mods = new TreeMap<String, TreeMap<String,Boolean>>(); | 168 | + if (this.mods == null) this.mods = new TreeMap<String, TreeMap<String, Boolean>>(); |
139 | 169 | ||
140 | if (!this.mods.containsKey(profileName)) | 170 | if (!this.mods.containsKey(profileName)) |
141 | { | 171 | { |
src/main/java/com/mumfrey/liteloader/core/LiteLoader.java
@@ -532,6 +532,15 @@ public final class LiteLoader | @@ -532,6 +532,15 @@ public final class LiteLoader | ||
532 | { | 532 | { |
533 | return "true".equals(System.getProperty("mcpenv")); | 533 | return "true".equals(System.getProperty("mcpenv")); |
534 | } | 534 | } |
535 | + | ||
536 | + /** | ||
537 | + * Get whether the current running version is a snapshot build | ||
538 | + */ | ||
539 | + public static boolean isSnapshot() | ||
540 | + { | ||
541 | + String branding = LiteLoader.getBranding(); | ||
542 | + return branding != null && branding.contains("SNAPSHOT"); | ||
543 | + } | ||
535 | 544 | ||
536 | /** | 545 | /** |
537 | * Dump debugging information to the console | 546 | * Dump debugging information to the console |
src/main/java/com/mumfrey/liteloader/core/LiteLoaderUpdateSite.java
@@ -8,6 +8,10 @@ package com.mumfrey.liteloader.core; | @@ -8,6 +8,10 @@ package com.mumfrey.liteloader.core; | ||
8 | import java.io.File; | 8 | import java.io.File; |
9 | import java.io.IOException; | 9 | import java.io.IOException; |
10 | import java.io.InputStream; | 10 | import java.io.InputStream; |
11 | +import java.util.Date; | ||
12 | +import java.util.Map; | ||
13 | +import java.util.regex.Matcher; | ||
14 | +import java.util.regex.Pattern; | ||
11 | 15 | ||
12 | import com.google.common.io.ByteSink; | 16 | import com.google.common.io.ByteSink; |
13 | import com.google.common.io.Files; | 17 | import com.google.common.io.Files; |
@@ -21,6 +25,8 @@ public class LiteLoaderUpdateSite extends UpdateSite | @@ -21,6 +25,8 @@ public class LiteLoaderUpdateSite extends UpdateSite | ||
21 | private static final String UPDATE_SITE_URL = "http://dl.liteloader.com/versions/"; | 25 | private static final String UPDATE_SITE_URL = "http://dl.liteloader.com/versions/"; |
22 | private static final String UPDATE_SITE_VERSIONS_JSON = "versions.json"; | 26 | private static final String UPDATE_SITE_VERSIONS_JSON = "versions.json"; |
23 | private static final String UPDATE_SITE_ARTEFACT_NAME = "com.mumfrey:liteloader"; | 27 | private static final String UPDATE_SITE_ARTEFACT_NAME = "com.mumfrey:liteloader"; |
28 | + | ||
29 | + private static final Pattern SNAPSHOT_REGEX = Pattern.compile("^([0-9\\._]+)-SNAPSHOT-(r[0-9a-z]+)-(b([0-9]+))-(.*)$", Pattern.CASE_INSENSITIVE); | ||
24 | 30 | ||
25 | private String mcVersion; | 31 | private String mcVersion; |
26 | 32 | ||
@@ -28,6 +34,10 @@ public class LiteLoaderUpdateSite extends UpdateSite | @@ -28,6 +34,10 @@ public class LiteLoaderUpdateSite extends UpdateSite | ||
28 | private File jarFile = null; | 34 | private File jarFile = null; |
29 | 35 | ||
30 | private boolean updateForced = false; | 36 | private boolean updateForced = false; |
37 | + private boolean isSnapshot = false; | ||
38 | + | ||
39 | + private int currentBuild, availableBuild; | ||
40 | + private String snapshotDate = null; | ||
31 | 41 | ||
32 | public LiteLoaderUpdateSite(String targetVersion, long currentTimeStamp) | 42 | public LiteLoaderUpdateSite(String targetVersion, long currentTimeStamp) |
33 | { | 43 | { |
@@ -36,6 +46,64 @@ public class LiteLoaderUpdateSite extends UpdateSite | @@ -36,6 +46,64 @@ public class LiteLoaderUpdateSite extends UpdateSite | ||
36 | 46 | ||
37 | this.mcVersion = targetVersion; | 47 | this.mcVersion = targetVersion; |
38 | } | 48 | } |
49 | + | ||
50 | + @Override | ||
51 | + public void beginUpdateCheck() | ||
52 | + { | ||
53 | + this.isSnapshot = LiteLoader.isSnapshot(); | ||
54 | + super.beginUpdateCheck(); | ||
55 | + } | ||
56 | + | ||
57 | + @Override | ||
58 | + public boolean isSnapshot() | ||
59 | + { | ||
60 | + return this.isSnapshot; | ||
61 | + } | ||
62 | + | ||
63 | + @Override | ||
64 | + public String getAvailableVersion() | ||
65 | + { | ||
66 | + if (this.isSnapshot() && this.availableBuild > 0) | ||
67 | + { | ||
68 | + return String.valueOf(this.availableBuild); | ||
69 | + } | ||
70 | + | ||
71 | + return super.getAvailableVersion(); | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public String getAvailableVersionDate() | ||
76 | + { | ||
77 | + if (this.snapshotDate != null) | ||
78 | + { | ||
79 | + return this.snapshotDate; | ||
80 | + } | ||
81 | + | ||
82 | + return super.getAvailableVersionDate(); | ||
83 | + } | ||
84 | + | ||
85 | + @Override | ||
86 | + protected boolean compareArtefact(Map<?, ?> artefact, long bestTimeStamp, Long remoteTimeStamp) | ||
87 | + { | ||
88 | + if (this.isSnapshot()) | ||
89 | + { | ||
90 | + String remoteBuild = artefact.get("build").toString(); | ||
91 | + String myBuild = LiteLoader.getBranding(); | ||
92 | + | ||
93 | + Matcher remoteMatcher = LiteLoaderUpdateSite.SNAPSHOT_REGEX.matcher(remoteBuild); | ||
94 | + Matcher myMatcher = LiteLoaderUpdateSite.SNAPSHOT_REGEX.matcher(myBuild); | ||
95 | + | ||
96 | + if (remoteMatcher.matches() && myMatcher.matches()) | ||
97 | + { | ||
98 | + this.currentBuild = Integer.parseInt(myMatcher.group(4)); | ||
99 | + this.availableBuild = Integer.parseInt(remoteMatcher.group(4)); | ||
100 | + this.snapshotDate = String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM", new Date(remoteTimeStamp * 1000L)); | ||
101 | + return this.availableBuild > this.currentBuild; | ||
102 | + } | ||
103 | + } | ||
104 | + | ||
105 | + return super.compareArtefact(artefact, bestTimeStamp, remoteTimeStamp); | ||
106 | + } | ||
39 | 107 | ||
40 | public boolean canForceUpdate(LoaderProperties properties) | 108 | public boolean canForceUpdate(LoaderProperties properties) |
41 | { | 109 | { |
src/main/java/com/mumfrey/liteloader/core/runtime/Obf.java
@@ -26,14 +26,11 @@ public class Obf | @@ -26,14 +26,11 @@ public class Obf | ||
26 | public static final Obf BakedProfilingHandlerList = new Obf("com.mumfrey.liteloader.core.event.ProfilingHandlerList$BakedList" ); | 26 | public static final Obf BakedProfilingHandlerList = new Obf("com.mumfrey.liteloader.core.event.ProfilingHandlerList$BakedList" ); |
27 | public static final Obf PacketEvents = new Obf("com.mumfrey.liteloader.core.PacketEvents" ); | 27 | public static final Obf PacketEvents = new Obf("com.mumfrey.liteloader.core.PacketEvents" ); |
28 | public static final Obf PacketEventsClient = new Obf("com.mumfrey.liteloader.client.PacketEventsClient" ); | 28 | public static final Obf PacketEventsClient = new Obf("com.mumfrey.liteloader.client.PacketEventsClient" ); |
29 | - public static final Obf LoadingBar = new Obf("com.mumfrey.liteloader.client.gui.startup.LoadingBar" ); | ||
30 | public static final Obf GameProfile = new Obf("com.mojang.authlib.GameProfile" ); | 29 | public static final Obf GameProfile = new Obf("com.mojang.authlib.GameProfile" ); |
31 | public static final Obf MinecraftMain = new Obf("net.minecraft.client.main.Main" ); | 30 | public static final Obf MinecraftMain = new Obf("net.minecraft.client.main.Main" ); |
32 | public static final Obf MinecraftServer = new Obf("net.minecraft.server.MinecraftServer" ); | 31 | public static final Obf MinecraftServer = new Obf("net.minecraft.server.MinecraftServer" ); |
33 | public static final Obf GL11 = new Obf("org.lwjgl.opengl.GL11" ); | 32 | public static final Obf GL11 = new Obf("org.lwjgl.opengl.GL11" ); |
34 | public static final Obf RealmsMainScreen = new Obf("com.mojang.realmsclient.RealmsMainScreen" ); | 33 | public static final Obf RealmsMainScreen = new Obf("com.mojang.realmsclient.RealmsMainScreen" ); |
35 | - public static final Obf init = new Obf("init" ); | ||
36 | - public static final Obf postInit = new Obf("postInit" ); | ||
37 | public static final Obf constructor = new Obf("<init>" ); | 34 | public static final Obf constructor = new Obf("<init>" ); |
38 | 35 | ||
39 | // CHECKSTYLE:OFF | 36 | // CHECKSTYLE:OFF |
src/main/java/com/mumfrey/liteloader/core/runtime/Packets.java
@@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
5 | */ | 5 | */ |
6 | package com.mumfrey.liteloader.core.runtime; | 6 | package com.mumfrey.liteloader.core.runtime; |
7 | 7 | ||
8 | +import java.lang.reflect.Field; | ||
8 | import java.util.HashMap; | 9 | import java.util.HashMap; |
9 | import java.util.Map; | 10 | import java.util.Map; |
10 | 11 | ||
@@ -157,125 +158,7 @@ public final class Packets extends Obf | @@ -157,125 +158,7 @@ public final class Packets extends Obf | ||
157 | 158 | ||
158 | // CHECKSTYLE:ON | 159 | // CHECKSTYLE:ON |
159 | 160 | ||
160 | - public static final Packets[] packets = new Packets[] { | ||
161 | - CPacketEncryptionResponse, | ||
162 | - CPacketLoginStart, | ||
163 | - SPacketDisconnectLogin, | ||
164 | - SPacketEnableCompression, | ||
165 | - SPacketEncryptionRequest, | ||
166 | - SPacketLoginSuccess, | ||
167 | - CPacketAnimation, | ||
168 | - CPacketChatMessage, | ||
169 | - CPacketClickWindow, | ||
170 | - CPacketClientSettings, | ||
171 | - CPacketClientStatus, | ||
172 | - CPacketCloseWindow, | ||
173 | - CPacketConfirmTeleport, | ||
174 | - CPacketConfirmTransaction, | ||
175 | - CPacketCreativeInventoryAction, | ||
176 | - CPacketCustomPayload, | ||
177 | - CPacketEnchantItem, | ||
178 | - CPacketEntityAction, | ||
179 | - CPacketHeldItemChange, | ||
180 | - CPacketInput, | ||
181 | - C00Handshake, | ||
182 | - CPacketKeepAlive, | ||
183 | - CPacketPlayer, | ||
184 | - CPacketPlayerPosition, | ||
185 | - CPacketPlayerPositionRotation, | ||
186 | - CPacketPlayerRotation, | ||
187 | - CPacketPlayerAbilities, | ||
188 | - CPacketPlayerDigging, | ||
189 | - CPacketPlayerTryUseItem, | ||
190 | - CPacketPlayerTryUseItemOnBlock, | ||
191 | - CPacketResourcePackStatus, | ||
192 | - CPacketSpectate, | ||
193 | - CPacketSteerBoat, | ||
194 | - CPacketTabComplete, | ||
195 | - CPacketUpdateSign, | ||
196 | - CPacketUseEntity, | ||
197 | - CPacketVehicleMove, | ||
198 | - SPacketAnimation, | ||
199 | - SPacketBlockAction, | ||
200 | - SPacketBlockBreakAnim, | ||
201 | - SPacketBlockChange, | ||
202 | - SPacketCamera, | ||
203 | - SPacketChangeGameState, | ||
204 | - SPacketChat, | ||
205 | - SPacketChunkData, | ||
206 | - SPacketCloseWindow, | ||
207 | - SPacketCollectItem, | ||
208 | - SPacketCombatEvent, | ||
209 | - SPacketConfirmTransaction, | ||
210 | - SPacketCooldown, | ||
211 | - SPacketCustomPayload, | ||
212 | - SPacketCustomSound, | ||
213 | - SPacketDestroyEntities, | ||
214 | - SPacketDisconnect, | ||
215 | - SPacketDisplayObjective, | ||
216 | - SPacketEffect, | ||
217 | - SPacketEntity, | ||
218 | - S15PacketEntityRelMove, | ||
219 | - S16PacketEntityLook, | ||
220 | - S17PacketEntityLookMove, | ||
221 | - SPacketEntityAttach, | ||
222 | - SPacketEntityEffect, | ||
223 | - SPacketEntityEquipment, | ||
224 | - SPacketEntityHeadLook, | ||
225 | - SPacketEntityMetadata, | ||
226 | - SPacketEntityProperties, | ||
227 | - SPacketEntityStatus, | ||
228 | - SPacketEntityTeleport, | ||
229 | - SPacketEntityVelocity, | ||
230 | - SPacketExplosion, | ||
231 | - SPacketHeldItemChange, | ||
232 | - SPacketJoinGame, | ||
233 | - SPacketKeepAlive, | ||
234 | - SPacketMaps, | ||
235 | - SPacketMoveVehicle, | ||
236 | - SPacketMultiBlockChange, | ||
237 | - SPacketOpenWindow, | ||
238 | - SPacketParticles, | ||
239 | - SPacketPlayerAbilities, | ||
240 | - SPacketPlayerListHeaderFooter, | ||
241 | - SPacketPlayerListItem, | ||
242 | - SPacketPlayerPosLook, | ||
243 | - SPacketRemoveEntityEffect, | ||
244 | - SPacketResourcePackSend, | ||
245 | - SPacketRespawn, | ||
246 | - SPacketScoreboardObjective, | ||
247 | - SPacketServerDifficulty, | ||
248 | - SPacketSetExperience, | ||
249 | - SPacketSetPassengers, | ||
250 | - SPacketSetSlot, | ||
251 | - SPacketSignEditorOpen, | ||
252 | - SPacketSoundEffect, | ||
253 | - SPacketSpawnExperienceOrb, | ||
254 | - SPacketSpawnGlobalEntity, | ||
255 | - SPacketSpawnMob, | ||
256 | - SPacketSpawnObject, | ||
257 | - SPacketSpawnPainting, | ||
258 | - SPacketSpawnPlayer, | ||
259 | - SPacketSpawnPosition, | ||
260 | - SPacketStatistics, | ||
261 | - SPacketTabComplete, | ||
262 | - SPacketTeams, | ||
263 | - SPacketTimeUpdate, | ||
264 | - SPacketTitle, | ||
265 | - SPacketUnloadChunk, | ||
266 | - SPacketUpdateBossInfo, | ||
267 | - SPacketUpdateHealth, | ||
268 | - SPacketUpdateScore, | ||
269 | - SPacketUpdateTileEntity, | ||
270 | - SPacketUseBed, | ||
271 | - SPacketWindowItems, | ||
272 | - SPacketWindowProperty, | ||
273 | - SPacketWorldBorder, | ||
274 | - CPacketPing, | ||
275 | - CPacketServerQuery, | ||
276 | - SPacketPong, | ||
277 | - SPacketServerInfo | ||
278 | - }; | 161 | + public static final Packets[] packets = Packets.toArray(); |
279 | 162 | ||
280 | private static int nextPacketIndex; | 163 | private static int nextPacketIndex; |
281 | 164 | ||
@@ -295,6 +178,24 @@ public final class Packets extends Obf | @@ -295,6 +178,24 @@ public final class Packets extends Obf | ||
295 | this.context = context; | 178 | this.context = context; |
296 | } | 179 | } |
297 | 180 | ||
181 | + private static Packets[] toArray() | ||
182 | + { | ||
183 | + Field[] fields = Packets.class.getFields(); | ||
184 | + Packets[] packets = new Packets[Packets.nextPacketIndex]; | ||
185 | + for (int index = 0; index < Packets.nextPacketIndex; index++) | ||
186 | + { | ||
187 | + try | ||
188 | + { | ||
189 | + packets[index] = (Packets)fields[index].get(null); | ||
190 | + } | ||
191 | + catch (Exception ex) | ||
192 | + { | ||
193 | + throw new RuntimeException(ex); | ||
194 | + } | ||
195 | + } | ||
196 | + return packets; | ||
197 | + } | ||
198 | + | ||
298 | public int getIndex() | 199 | public int getIndex() |
299 | { | 200 | { |
300 | return this.index; | 201 | return this.index; |
src/main/java/com/mumfrey/liteloader/interfaces/PanelManager.java
@@ -88,4 +88,14 @@ public interface PanelManager<TParentScreen> extends TickObserver, PostRenderObs | @@ -88,4 +88,14 @@ public interface PanelManager<TParentScreen> extends TickObserver, PostRenderObs | ||
88 | * Get whether "force update" is enabled | 88 | * Get whether "force update" is enabled |
89 | */ | 89 | */ |
90 | public abstract boolean isForceUpdateEnabled(); | 90 | public abstract boolean isForceUpdateEnabled(); |
91 | + | ||
92 | + /** | ||
93 | + * Set whether "check for new snapshots" is enabled | ||
94 | + */ | ||
95 | + public abstract void setCheckForSnapshotsEnabled(boolean checkForSnapshots); | ||
96 | + | ||
97 | + /** | ||
98 | + * Get whether "check for new snapshots" is enabled | ||
99 | + */ | ||
100 | + public abstract boolean isCheckForSnapshotsEnabled(); | ||
91 | } | 101 | } |
src/main/java/com/mumfrey/liteloader/launch/LoaderProperties.java
@@ -99,6 +99,7 @@ public interface LoaderProperties | @@ -99,6 +99,7 @@ public interface LoaderProperties | ||
99 | public static final String OPTION_FORCE_UPDATE = "allowForceUpdate"; | 99 | public static final String OPTION_FORCE_UPDATE = "allowForceUpdate"; |
100 | public static final String OPTION_UPDATE_CHECK_INTR = "updateCheckInterval"; | 100 | public static final String OPTION_UPDATE_CHECK_INTR = "updateCheckInterval"; |
101 | public static final String OPTION_JINPUT_DISABLE = "disableJInput"; | 101 | public static final String OPTION_JINPUT_DISABLE = "disableJInput"; |
102 | + public static final String OPTION_CHECK_SNAPSHOTS = "checkForNewSnapshots"; | ||
102 | 103 | ||
103 | // Enumerator properties | 104 | // Enumerator properties |
104 | public static final String OPTION_SEARCH_MODS = "search.mods"; | 105 | public static final String OPTION_SEARCH_MODS = "search.mods"; |
src/main/java/com/mumfrey/liteloader/modconfig/ConfigManager.java
@@ -17,6 +17,7 @@ import com.google.common.collect.Maps; | @@ -17,6 +17,7 @@ import com.google.common.collect.Maps; | ||
17 | import com.google.common.io.Files; | 17 | import com.google.common.io.Files; |
18 | import com.mumfrey.liteloader.Configurable; | 18 | import com.mumfrey.liteloader.Configurable; |
19 | import com.mumfrey.liteloader.LiteMod; | 19 | import com.mumfrey.liteloader.LiteMod; |
20 | +import com.mumfrey.liteloader.util.log.LiteLoaderLogger; | ||
20 | 21 | ||
21 | /** | 22 | /** |
22 | * Registry where we keep the mod config panel classes and config file writers | 23 | * Registry where we keep the mod config panel classes and config file writers |
@@ -165,6 +166,10 @@ public class ConfigManager | @@ -165,6 +166,10 @@ public class ConfigManager | ||
165 | } | 166 | } |
166 | catch (InstantiationException ex) {} | 167 | catch (InstantiationException ex) {} |
167 | catch (IllegalAccessException ex) {} | 168 | catch (IllegalAccessException ex) {} |
169 | + catch (Exception ex) | ||
170 | + { | ||
171 | + LiteLoaderLogger.severe("Error creating mod configuration panel <%s> for mod %s", this.configPanels.get(modClass), modClass); | ||
172 | + } | ||
168 | 173 | ||
169 | // If instantiation fails, remove the panel | 174 | // If instantiation fails, remove the panel |
170 | this.configPanels.remove(modClass); | 175 | this.configPanels.remove(modClass); |
src/main/java/com/mumfrey/liteloader/permissions/PermissionsManagerClient.java
@@ -47,37 +47,37 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | @@ -47,37 +47,37 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | ||
47 | * Permissions permissible which is a proxy for permissions that are common | 47 | * Permissions permissible which is a proxy for permissions that are common |
48 | * to all mods. | 48 | * to all mods. |
49 | */ | 49 | */ |
50 | - private static Permissible allMods = new PermissibleAllMods(); | ||
51 | - | ||
52 | - /** | ||
53 | - * Minecraft instance | ||
54 | - */ | ||
55 | - private GameEngine<?, ?> engine; | 50 | + private final static Permissible allMods = new PermissibleAllMods(); |
56 | 51 | ||
57 | /** | 52 | /** |
58 | * List of registered client mods supporting permissions | 53 | * List of registered client mods supporting permissions |
59 | */ | 54 | */ |
60 | - private Map<String, Permissible> registeredClientMods = new HashMap<String, Permissible>(); | 55 | + private final Map<String, Permissible> registeredClientMods = new HashMap<String, Permissible>(); |
61 | 56 | ||
62 | /** | 57 | /** |
63 | * List of registered client permissions, grouped by mod | 58 | * List of registered client permissions, grouped by mod |
64 | */ | 59 | */ |
65 | - private Map<Permissible, TreeSet<String>> registeredClientPermissions = new HashMap<Permissible, TreeSet<String>>(); | 60 | + private final Map<Permissible, TreeSet<String>> registeredClientPermissions = new HashMap<Permissible, TreeSet<String>>(); |
66 | 61 | ||
67 | /** | 62 | /** |
68 | * Objects which listen to events generated by this object | 63 | * Objects which listen to events generated by this object |
69 | */ | 64 | */ |
70 | - private Set<Permissible> permissibles = new HashSet<Permissible>(); | 65 | + private final Set<Permissible> permissibles = new HashSet<Permissible>(); |
71 | 66 | ||
72 | /** | 67 | /** |
73 | * Local permissions, used when server permissions are not available | 68 | * Local permissions, used when server permissions are not available |
74 | */ | 69 | */ |
75 | - private LocalPermissions localPermissions = new LocalPermissions(); | 70 | + private final LocalPermissions localPermissions = new LocalPermissions(); |
76 | 71 | ||
77 | /** | 72 | /** |
78 | * Server permissions, indexed by mod | 73 | * Server permissions, indexed by mod |
79 | */ | 74 | */ |
80 | - private Map<String, ServerPermissions> serverPermissions = new HashMap<String, ServerPermissions>(); | 75 | + private final Map<String, ServerPermissions> serverPermissions = new HashMap<String, ServerPermissions>(); |
76 | + | ||
77 | + /** | ||
78 | + * Minecraft instance | ||
79 | + */ | ||
80 | + private GameEngine<?, ?> engine; | ||
81 | 81 | ||
82 | /** | 82 | /** |
83 | * Last time onTick was called, used to detect tamper condition if no ticks | 83 | * Last time onTick was called, used to detect tamper condition if no ticks |
@@ -124,8 +124,11 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | @@ -124,8 +124,11 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | ||
124 | if (mod == null) mod = allMods; | 124 | if (mod == null) mod = allMods; |
125 | String modName = mod.getPermissibleModName(); | 125 | String modName = mod.getPermissibleModName(); |
126 | 126 | ||
127 | - ServerPermissions modPermissions = this.serverPermissions.get(modName); | ||
128 | - return modPermissions != null ? modPermissions : this.localPermissions; | 127 | + synchronized (this.serverPermissions) |
128 | + { | ||
129 | + ServerPermissions modPermissions = this.serverPermissions.get(modName); | ||
130 | + return modPermissions != null ? modPermissions : this.localPermissions; | ||
131 | + } | ||
129 | } | 132 | } |
130 | 133 | ||
131 | /* (non-Javadoc) | 134 | /* (non-Javadoc) |
@@ -138,8 +141,11 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | @@ -138,8 +141,11 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | ||
138 | if (mod == null) mod = allMods; | 141 | if (mod == null) mod = allMods; |
139 | String modName = mod.getPermissibleModName(); | 142 | String modName = mod.getPermissibleModName(); |
140 | 143 | ||
141 | - ServerPermissions modPermissions = this.serverPermissions.get(modName); | ||
142 | - return modPermissions != null ? modPermissions.getReplicationTime() : 0; | 144 | + synchronized (this.serverPermissions) |
145 | + { | ||
146 | + ServerPermissions modPermissions = this.serverPermissions.get(modName); | ||
147 | + return modPermissions != null ? modPermissions.getReplicationTime() : 0; | ||
148 | + } | ||
143 | } | 149 | } |
144 | 150 | ||
145 | /** | 151 | /** |
@@ -208,7 +214,10 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | @@ -208,7 +214,10 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | ||
208 | */ | 214 | */ |
209 | protected void clearServerPermissions() | 215 | protected void clearServerPermissions() |
210 | { | 216 | { |
211 | - this.serverPermissions.clear(); | 217 | + synchronized (this.serverPermissions) |
218 | + { | ||
219 | + this.serverPermissions.clear(); | ||
220 | + } | ||
212 | 221 | ||
213 | for (Permissible permissible : this.permissibles) | 222 | for (Permissible permissible : this.permissibles) |
214 | { | 223 | { |
@@ -264,7 +273,10 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | @@ -264,7 +273,10 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | ||
264 | } | 273 | } |
265 | else | 274 | else |
266 | { | 275 | { |
267 | - this.serverPermissions.remove(modName); | 276 | + synchronized (this.serverPermissions) |
277 | + { | ||
278 | + this.serverPermissions.remove(modName); | ||
279 | + } | ||
268 | } | 280 | } |
269 | } | 281 | } |
270 | 282 | ||
@@ -289,12 +301,15 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | @@ -289,12 +301,15 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | ||
289 | } | 301 | } |
290 | } | 302 | } |
291 | 303 | ||
292 | - for (Map.Entry<String, ServerPermissions> modPermissions : this.serverPermissions.entrySet()) | 304 | + synchronized (this.serverPermissions) |
293 | { | 305 | { |
294 | - if (!modPermissions.getValue().isValid()) | 306 | + for (Map.Entry<String, ServerPermissions> modPermissions : this.serverPermissions.entrySet()) |
295 | { | 307 | { |
296 | - modPermissions.getValue().notifyRefreshPending(); | ||
297 | - this.sendPermissionQuery(this.registeredClientMods.get(modPermissions.getKey())); | 308 | + if (!modPermissions.getValue().isValid()) |
309 | + { | ||
310 | + modPermissions.getValue().notifyRefreshPending(); | ||
311 | + this.sendPermissionQuery(this.registeredClientMods.get(modPermissions.getKey())); | ||
312 | + } | ||
298 | } | 313 | } |
299 | } | 314 | } |
300 | 315 | ||
@@ -336,7 +351,10 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | @@ -336,7 +351,10 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi | ||
336 | 351 | ||
337 | if (modPermissions != null && modPermissions.getModName() != null) | 352 | if (modPermissions != null && modPermissions.getModName() != null) |
338 | { | 353 | { |
339 | - this.serverPermissions.put(modPermissions.getModName(), modPermissions); | 354 | + synchronized (this.serverPermissions) |
355 | + { | ||
356 | + this.serverPermissions.put(modPermissions.getModName(), modPermissions); | ||
357 | + } | ||
340 | 358 | ||
341 | Permissible permissible = this.registeredClientMods.get(modPermissions.getModName()); | 359 | Permissible permissible = this.registeredClientMods.get(modPermissions.getModName()); |
342 | if (permissible != null) permissible.onPermissionsChanged(this); | 360 | if (permissible != null) permissible.onPermissionsChanged(this); |
src/main/java/com/mumfrey/liteloader/update/UpdateSite.java
@@ -160,6 +160,11 @@ public class UpdateSite implements Comparator<Long> | @@ -160,6 +160,11 @@ public class UpdateSite implements Comparator<Long> | ||
160 | } | 160 | } |
161 | } | 161 | } |
162 | } | 162 | } |
163 | + | ||
164 | + public boolean isSnapshot() | ||
165 | + { | ||
166 | + return false; | ||
167 | + } | ||
163 | 168 | ||
164 | /** | 169 | /** |
165 | * Gets whether a check is in progress | 170 | * Gets whether a check is in progress |
@@ -319,7 +324,7 @@ public class UpdateSite implements Comparator<Long> | @@ -319,7 +324,7 @@ public class UpdateSite implements Comparator<Long> | ||
319 | */ | 324 | */ |
320 | private void handleVersionData(Object key, Map<?, ?> value) | 325 | private void handleVersionData(Object key, Map<?, ?> value) |
321 | { | 326 | { |
322 | - if ("artefacts".equals(key)) | 327 | + if ((this.isSnapshot() && "snapshots".equals(key)) || (!this.isSnapshot() && "artefacts".equals(key))) |
323 | { | 328 | { |
324 | if (value.containsKey(this.artefact)) | 329 | if (value.containsKey(this.artefact)) |
325 | { | 330 | { |
@@ -387,7 +392,7 @@ public class UpdateSite implements Comparator<Long> | @@ -387,7 +392,7 @@ public class UpdateSite implements Comparator<Long> | ||
387 | this.availableVersion = artefact.get("version").toString(); | 392 | this.availableVersion = artefact.get("version").toString(); |
388 | this.availableVersionDate = DateFormat.getDateTimeInstance().format(new Date(remoteTimeStamp * 1000L)); | 393 | this.availableVersionDate = DateFormat.getDateTimeInstance().format(new Date(remoteTimeStamp * 1000L)); |
389 | this.availableVersionURL = this.createArtefactURL(artefact.get("file").toString()); | 394 | this.availableVersionURL = this.createArtefactURL(artefact.get("file").toString()); |
390 | - this.updateAvailable = this.compareTimeStamps(bestTimeStamp, remoteTimeStamp); | 395 | + this.updateAvailable = this.compareArtefact(artefact, bestTimeStamp, remoteTimeStamp); |
391 | 396 | ||
392 | return true; | 397 | return true; |
393 | } | 398 | } |
@@ -395,6 +400,11 @@ public class UpdateSite implements Comparator<Long> | @@ -395,6 +400,11 @@ public class UpdateSite implements Comparator<Long> | ||
395 | return false; | 400 | return false; |
396 | } | 401 | } |
397 | 402 | ||
403 | + protected boolean compareArtefact(Map<?, ?> artefact, long bestTimeStamp, Long remoteTimeStamp) | ||
404 | + { | ||
405 | + return this.compareTimeStamps(bestTimeStamp, remoteTimeStamp); | ||
406 | + } | ||
407 | + | ||
398 | /** | 408 | /** |
399 | * @param bestTimeStamp | 409 | * @param bestTimeStamp |
400 | * @param remoteTimeStamp | 410 | * @param remoteTimeStamp |
src/main/resources/assets/liteloader/lang/en_us.lang
@@ -16,6 +16,9 @@ gui.settings.notabhide.help1=Only applies if the above option is also checked | @@ -16,6 +16,9 @@ gui.settings.notabhide.help1=Only applies if the above option is also checked | ||
16 | gui.settings.forceupdate.label=Periodically Check For Updates | 16 | gui.settings.forceupdate.label=Periodically Check For Updates |
17 | gui.settings.forceupdate.help1=This option is §cexperimental§r and may not work properly | 17 | gui.settings.forceupdate.help1=This option is §cexperimental§r and may not work properly |
18 | gui.settings.forceupdate.help2=yet, it also enables the "force update" capability. | 18 | gui.settings.forceupdate.help2=yet, it also enables the "force update" capability. |
19 | +gui.settings.checkforsnapshots.label=Check For New Snapshots | ||
20 | +gui.settings.checkforsnapshots.help1=If this option is enabled, LiteLoader will check | ||
21 | +gui.settings.checkforsnapshots.help2=for new SNAPSHOT releases each time it it launched | ||
19 | 22 | ||
20 | gui.about.taboptions=§nLiteLoader Panel Options | 23 | gui.about.taboptions=§nLiteLoader Panel Options |
21 | 24 | ||
@@ -83,7 +86,11 @@ gui.log.uploadsuccess=Upload succeeded, log available at | @@ -83,7 +86,11 @@ gui.log.uploadsuccess=Upload succeeded, log available at | ||
83 | gui.log.closedialog=Close | 86 | gui.log.closedialog=Close |
84 | 87 | ||
85 | gui.error.title=Startup errors for %s | 88 | gui.error.title=Startup errors for %s |
89 | +gui.error.copytoclipboard=Copy error to clipboard | ||
86 | 90 | ||
87 | gui.error.tooltip=%d mod startup error(s) detected (%d critical) | 91 | gui.error.tooltip=%d mod startup error(s) detected (%d critical) |
88 | 92 | ||
89 | -gui.notifications.updateavailable=LiteLoader Update Available! | ||
90 | \ No newline at end of file | 93 | \ No newline at end of file |
94 | +gui.notifications.updateavailable=LiteLoader Update Available! | ||
95 | +gui.notifications.newsnapshotavailable=!!New Snapshot Available:%nBuild #%s (%s) | ||
96 | + | ||
97 | +gui.invalidvalue=§cInvalid value! | ||
91 | \ No newline at end of file | 98 | \ No newline at end of file |
src/main/resources/mixins.liteloader.core.json
1 | { | 1 | { |
2 | "required": true, | 2 | "required": true, |
3 | - "minVersion": "0.5.3", | 3 | + "minVersion": "0.7", |
4 | + "compatibilityLevel": "JAVA_8", | ||
4 | "target": "@env(DEFAULT)", | 5 | "target": "@env(DEFAULT)", |
5 | "package": "com.mumfrey.liteloader.common.mixin", | 6 | "package": "com.mumfrey.liteloader.common.mixin", |
6 | "refmap": "mixins.liteloader.core.refmap.json", | 7 | "refmap": "mixins.liteloader.core.refmap.json", |