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 | 60 | version = buildVersion + (project.isReleaseBuild ? '' : '-' + project.classifier) |
61 | 61 | |
62 | 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 | 66 | repositories { |
67 | 67 | mavenLocal() |
... | ... | @@ -72,7 +72,7 @@ repositories { |
72 | 72 | } |
73 | 73 | |
74 | 74 | dependencies { |
75 | - compile('org.spongepowered:mixin:0.6.8-SNAPSHOT') { | |
75 | + compile('org.spongepowered:mixin:0.7.1-SNAPSHOT') { | |
76 | 76 | exclude module: 'asm-commons' |
77 | 77 | exclude module: 'asm-tree' |
78 | 78 | exclude module: 'launchwrapper' |
... | ... | @@ -89,11 +89,11 @@ minecraft { |
89 | 89 | |
90 | 90 | sourceSets { |
91 | 91 | main { |
92 | - refMap = "mixins.liteloader.core.refmap.json" | |
92 | + ext.refMap = "mixins.liteloader.core.refmap.json" | |
93 | 93 | } |
94 | 94 | client { |
95 | 95 | compileClasspath += main.compileClasspath + main.output |
96 | - refMap = "mixins.liteloader.client.refmap.json" | |
96 | + ext.refMap = "mixins.liteloader.client.refmap.json" | |
97 | 97 | } |
98 | 98 | debug { |
99 | 99 | compileClasspath += client.compileClasspath + client.output |
... | ... | @@ -123,7 +123,7 @@ javadoc { |
123 | 123 | afterEvaluate { |
124 | 124 | logger.lifecycle '=================================================' |
125 | 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 | 127 | logger.lifecycle ' Running in {} mode', (project.isReleaseBuild ? "RELEASE" : "SNAPSHOT") |
128 | 128 | logger.lifecycle '=================================================' |
129 | 129 | ... | ... |
gradle.properties
src/client/java/com/mumfrey/liteloader/client/LiteLoaderEventBrokerClient.java
... | ... | @@ -9,24 +9,9 @@ import org.lwjgl.input.Mouse; |
9 | 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; |
10 | 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 | 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 | 14 | import com.mumfrey.liteloader.client.overlays.IEntityRenderer; |
29 | -import com.mumfrey.liteloader.client.overlays.IMinecraft; | |
30 | 15 | import com.mumfrey.liteloader.common.LoadingProgress; |
31 | 16 | import com.mumfrey.liteloader.core.InterfaceRegistrationDelegate; |
32 | 17 | import com.mumfrey.liteloader.core.LiteLoader; |
... | ... | @@ -51,7 +36,6 @@ import net.minecraft.client.shader.Framebuffer; |
51 | 36 | import net.minecraft.entity.Entity; |
52 | 37 | import net.minecraft.network.play.client.CPacketChatMessage; |
53 | 38 | import net.minecraft.server.integrated.IntegratedServer; |
54 | -import net.minecraft.util.Timer; | |
55 | 39 | import net.minecraft.util.text.ITextComponent; |
56 | 40 | |
57 | 41 | public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft, IntegratedServer> implements IResourceManagerReloadListener |
... | ... | @@ -427,14 +411,9 @@ public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft |
427 | 411 | /** |
428 | 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 | 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 | 417 | Minecraft minecraft = this.engine.getClient(); |
439 | 418 | |
440 | 419 | // Flag indicates whether we are in game at the moment |
... | ... | @@ -548,7 +527,7 @@ public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft |
548 | 527 | } |
549 | 528 | |
550 | 529 | /** |
551 | - * @param e | |
530 | + * @param ci | |
552 | 531 | * @param name |
553 | 532 | * @param width |
554 | 533 | * @param height | ... | ... |
src/client/java/com/mumfrey/liteloader/client/LiteLoaderPanelManager.java
... | ... | @@ -9,6 +9,7 @@ import org.lwjgl.input.Keyboard; |
9 | 9 | |
10 | 10 | import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel; |
11 | 11 | import com.mumfrey.liteloader.common.GameEngine; |
12 | +import com.mumfrey.liteloader.core.LiteLoader; | |
12 | 13 | import com.mumfrey.liteloader.core.LiteLoaderMods; |
13 | 14 | import com.mumfrey.liteloader.core.LiteLoaderUpdateSite; |
14 | 15 | import com.mumfrey.liteloader.core.LiteLoaderVersion; |
... | ... | @@ -32,6 +33,13 @@ import net.minecraft.client.resources.I18n; |
32 | 33 | */ |
33 | 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 | 43 | private final LoaderEnvironment environment; |
36 | 44 | |
37 | 45 | /** |
... | ... | @@ -87,14 +95,14 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> |
87 | 95 | this.displayModInfoScreenTab = this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_MOD_INFO_SCREEN, true); |
88 | 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 | 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 | 106 | this.checkForUpdate = true; |
99 | 107 | updateCheckInterval = 0; |
100 | 108 | } |
... | ... | @@ -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 | 125 | @Override |
108 | 126 | public void init(LiteLoaderMods mods, ConfigManager configManager) |
109 | 127 | { |
... | ... | @@ -141,7 +159,8 @@ public class LiteLoaderPanelManager implements PanelManager<GuiScreen> |
141 | 159 | this.checkForUpdate = false; |
142 | 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 | 270 | { |
252 | 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 | 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 | 42 | |
43 | 43 | private static final String[] requiredDownstreamTransformers = { |
44 | 44 | LiteLoaderCoreAPI.PKG_LITELOADER_COMMON + ".transformers.LiteLoaderPacketTransformer", |
45 | - LiteLoaderCoreAPIClient.PKG_LITELOADER_CLIENT + ".transformers.MinecraftTransformer", | |
46 | 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 | 177 | this.startupErrorCount = mods.getStartupErrorCount(); |
178 | 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 | 523 | |
525 | 524 | if (annoyingTip) |
526 | 525 | { |
526 | + GuiLiteLoaderPanel.displayErrorToolTip = false; | |
527 | 527 | this.drawNotificationTooltip(mouseX, mouseY - 13); |
528 | 528 | } |
529 | 529 | } |
... | ... | @@ -542,8 +542,11 @@ public class GuiLiteLoaderPanel extends GuiScreen |
542 | 542 | } |
543 | 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 | 742 | * |
740 | 743 | * @param fontRenderer |
741 | 744 | * @param tooltipText |
742 | - * @param mouseX | |
743 | - * @param mouseY | |
745 | + * @param left | |
746 | + * @param top | |
744 | 747 | * @param screenWidth |
745 | 748 | * @param screenHeight |
746 | 749 | * @param colour |
747 | 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 | 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 | 12 | |
13 | 13 | import org.lwjgl.input.Keyboard; |
14 | 14 | |
15 | +import com.google.common.base.Joiner; | |
15 | 16 | import com.mumfrey.liteloader.core.ModInfo; |
16 | 17 | |
17 | 18 | import net.minecraft.client.Minecraft; |
18 | 19 | import net.minecraft.client.gui.GuiButton; |
20 | +import net.minecraft.client.gui.GuiScreen; | |
19 | 21 | import net.minecraft.client.resources.I18n; |
20 | 22 | |
21 | 23 | public class GuiPanelError extends GuiPanel implements ScrollPanelContent |
... | ... | @@ -98,6 +100,7 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent |
98 | 100 | |
99 | 101 | this.scrollPane.setSizeAndPosition(MARGIN, TOP, this.width - (MARGIN * 2), this.height - TOP - BOTTOM); |
100 | 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 | 106 | @Override |
... | ... | @@ -131,7 +134,10 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent |
131 | 134 | @Override |
132 | 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 | 143 | @Override |
... | ... | @@ -161,6 +167,14 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent |
161 | 167 | @Override |
162 | 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 | 17 | |
18 | 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 | 26 | private boolean hide; |
25 | 27 | |
26 | 28 | private String[] helpText = new String[5]; |
27 | - | |
29 | + | |
28 | 30 | GuiPanelSettings(GuiLiteLoaderPanel parentScreen, Minecraft minecraft) |
29 | 31 | { |
30 | 32 | super(minecraft); |
31 | 33 | |
32 | 34 | this.parentScreen = parentScreen; |
35 | + this.isSnapshot = LiteLoader.isSnapshot(); | |
33 | 36 | |
37 | + String helpKey = this.isSnapshot ? "checkforsnapshots" : "forceupdate"; | |
34 | 38 | this.helpText[0] = I18n.format("gui.settings.showtab.help1"); |
35 | 39 | this.helpText[1] = I18n.format("gui.settings.showtab.help2"); |
36 | 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 | 45 | @Override |
... | ... | @@ -61,6 +65,10 @@ class GuiPanelSettings extends GuiPanel |
61 | 65 | this.controls.add(this.chkShowTab = new GuiCheckbox(0, 34, 90, I18n.format("gui.settings.showtab.label"))); |
62 | 66 | this.controls.add(this.chkNoHide = new GuiCheckbox(1, 34, 128, I18n.format("gui.settings.notabhide.label"))); |
63 | 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 | 73 | this.updateCheckBoxes(); |
66 | 74 | } |
... | ... | @@ -72,6 +80,7 @@ class GuiPanelSettings extends GuiPanel |
72 | 80 | this.chkShowTab.checked = panelManager.isTabVisible(); |
73 | 81 | this.chkNoHide.checked = panelManager.isTabAlwaysExpanded(); |
74 | 82 | this.chkForceUpdate.checked = panelManager.isForceUpdateEnabled(); |
83 | + this.chkCheckForSnapshots.checked = panelManager.isCheckForSnapshotsEnabled(); | |
75 | 84 | } |
76 | 85 | |
77 | 86 | private void updateSettings() |
... | ... | @@ -81,6 +90,7 @@ class GuiPanelSettings extends GuiPanel |
81 | 90 | panelManager.setTabVisible(this.chkShowTab.checked); |
82 | 91 | panelManager.setTabAlwaysExpanded(this.chkNoHide.checked); |
83 | 92 | panelManager.setForceUpdateEnabled(this.chkForceUpdate.checked); |
93 | + panelManager.setCheckForSnapshotsEnabled(this.chkCheckForSnapshots.checked); | |
84 | 94 | } |
85 | 95 | |
86 | 96 | @Override | ... | ... |
src/client/java/com/mumfrey/liteloader/client/gui/modlist/ModList.java
... | ... | @@ -15,6 +15,7 @@ import org.lwjgl.input.Keyboard; |
15 | 15 | import com.mumfrey.liteloader.LiteMod; |
16 | 16 | import com.mumfrey.liteloader.api.ModInfoDecorator; |
17 | 17 | import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel; |
18 | +import com.mumfrey.liteloader.core.EnabledModsList.Enabled; | |
18 | 19 | import com.mumfrey.liteloader.core.LiteLoaderMods; |
19 | 20 | import com.mumfrey.liteloader.core.ModInfo; |
20 | 21 | import com.mumfrey.liteloader.interfaces.Loadable; |
... | ... | @@ -75,9 +76,12 @@ public class ModList |
75 | 76 | // Disabled mods |
76 | 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 | 82 | sortedMods.put(modListEntry.getKey(), modListEntry); |
80 | 83 | } |
84 | + } | |
81 | 85 | |
82 | 86 | // Show bad containers if no other containers are found, should help users realise they have the wrong mod version! |
83 | 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 | 19 | import com.mumfrey.liteloader.PlayerInteractionListener.MouseButton; |
20 | 20 | import com.mumfrey.liteloader.client.LiteLoaderEventBrokerClient; |
21 | 21 | import com.mumfrey.liteloader.client.ducks.IFramebuffer; |
22 | +import com.mumfrey.liteloader.client.gui.startup.LoadingBar; | |
22 | 23 | import com.mumfrey.liteloader.client.overlays.IMinecraft; |
24 | +import com.mumfrey.liteloader.launch.LiteLoaderTweaker; | |
23 | 25 | |
24 | 26 | import net.minecraft.client.Minecraft; |
25 | 27 | import net.minecraft.client.renderer.OpenGlHelper; |
... | ... | @@ -35,6 +37,7 @@ public abstract class MixinMinecraft implements IMinecraft |
35 | 37 | @Shadow @Final private List<IResourcePack> defaultResourcePacks; |
36 | 38 | @Shadow private String serverName; |
37 | 39 | @Shadow private int serverPort; |
40 | + @Shadow private boolean isGamePaused; | |
38 | 41 | |
39 | 42 | @Shadow abstract void resize(int width, int height); |
40 | 43 | @Shadow private void clickMouse() {} |
... | ... | @@ -43,6 +46,25 @@ public abstract class MixinMinecraft implements IMinecraft |
43 | 46 | |
44 | 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 | 68 | @Inject(method = "init()V", at = @At("RETURN")) |
47 | 69 | private void onStartupComplete(CallbackInfo ci) |
48 | 70 | { |
... | ... | @@ -79,7 +101,9 @@ public abstract class MixinMinecraft implements IMinecraft |
79 | 101 | )) |
80 | 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 | 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 | 7 | |
8 | 8 | import java.util.ArrayList; |
9 | 9 | import java.util.List; |
10 | +import java.util.regex.Pattern; | |
10 | 11 | |
11 | 12 | import org.lwjgl.input.Keyboard; |
12 | 13 | |
14 | +import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel; | |
13 | 15 | import com.mumfrey.liteloader.client.mixin.IGuiButton; |
14 | 16 | |
15 | 17 | import net.minecraft.client.Minecraft; |
18 | +import net.minecraft.client.gui.FontRenderer; | |
16 | 19 | import net.minecraft.client.gui.GuiButton; |
17 | 20 | import net.minecraft.client.gui.GuiLabel; |
18 | 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 | 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 | 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 | 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 | 162 | this.control = control; |
66 | 163 | this.listener = listener; |
67 | 164 | } |
68 | 165 | |
166 | + @Override | |
69 | 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 | 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 | 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 | 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 | 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 | 403 | private int contentHeight = 0; |
111 | 404 | |
112 | - private ConfigOption<?> selected; | |
405 | + private ConfigOption selected; | |
113 | 406 | |
114 | 407 | public AbstractConfigPanel() |
115 | 408 | { |
... | ... | @@ -170,7 +463,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel |
170 | 463 | label.addLine(line); |
171 | 464 | } |
172 | 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 | 478 | if (control != null) |
186 | 479 | { |
187 | 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 | 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 | 508 | @Override |
195 | 509 | public void onPanelResize(ConfigPanelHost host) |
196 | 510 | { |
... | ... | @@ -199,12 +513,16 @@ public abstract class AbstractConfigPanel implements ConfigPanel |
199 | 513 | @Override |
200 | 514 | public void onTick(ConfigPanelHost host) |
201 | 515 | { |
516 | + for (ConfigOption configOption : this.options) | |
517 | + { | |
518 | + configOption.onTick(); | |
519 | + } | |
202 | 520 | } |
203 | 521 | |
204 | 522 | @Override |
205 | 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 | 527 | configOption.draw(this.mc, mouseX, mouseY, partialTicks); |
210 | 528 | } |
... | ... | @@ -219,7 +537,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel |
219 | 537 | return; |
220 | 538 | } |
221 | 539 | |
222 | - for (ConfigOption<?> configOption : this.options) | |
540 | + for (ConfigOption configOption : this.options) | |
223 | 541 | { |
224 | 542 | if (configOption.mousePressed(this.mc, mouseX, mouseY)) |
225 | 543 | { |
... | ... | @@ -251,5 +569,22 @@ public abstract class AbstractConfigPanel implements ConfigPanel |
251 | 569 | host.close(); |
252 | 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
src/main/java/com/mumfrey/liteloader/core/EnabledModsList.java
... | ... | @@ -24,6 +24,34 @@ import com.google.gson.GsonBuilder; |
24 | 24 | */ |
25 | 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 | 55 | @SuppressWarnings("unused") |
28 | 56 | private static final transient long serialVersionUID = -6449451105617763769L; |
29 | 57 | |
... | ... | @@ -45,7 +73,7 @@ public final class EnabledModsList |
45 | 73 | * the mods list because the command line is supposed to be an override |
46 | 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 | 77 | private transient boolean allowSave = true; |
50 | 78 | |
51 | 79 | /** |
... | ... | @@ -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 | 92 | * @param profileName |
65 | 93 | * @param identifier |
66 | 94 | */ |
67 | 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 | 102 | Map<String, Boolean> profile = this.getProfile(profileName); |
70 | 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 | 120 | public void setEnabled(String profileName, String identifier, boolean enabled) |
88 | 121 | { |
89 | 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 | 125 | this.allowSave = true; |
93 | 126 | } |
... | ... | @@ -106,12 +139,9 @@ public final class EnabledModsList |
106 | 139 | { |
107 | 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 | 145 | this.allowSave = false; |
116 | 146 | |
117 | 147 | for (String filterEntry : modNameFilter) |
... | ... | @@ -122,8 +152,8 @@ public final class EnabledModsList |
122 | 152 | } |
123 | 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 | 165 | private Map<String, Boolean> getProfile(String profileName) |
136 | 166 | { |
137 | 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 | 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 | 532 | { |
533 | 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 | 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 | 8 | import java.io.File; |
9 | 9 | import java.io.IOException; |
10 | 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 | 16 | import com.google.common.io.ByteSink; |
13 | 17 | import com.google.common.io.Files; |
... | ... | @@ -21,6 +25,8 @@ public class LiteLoaderUpdateSite extends UpdateSite |
21 | 25 | private static final String UPDATE_SITE_URL = "http://dl.liteloader.com/versions/"; |
22 | 26 | private static final String UPDATE_SITE_VERSIONS_JSON = "versions.json"; |
23 | 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 | 31 | private String mcVersion; |
26 | 32 | |
... | ... | @@ -28,6 +34,10 @@ public class LiteLoaderUpdateSite extends UpdateSite |
28 | 34 | private File jarFile = null; |
29 | 35 | |
30 | 36 | private boolean updateForced = false; |
37 | + private boolean isSnapshot = false; | |
38 | + | |
39 | + private int currentBuild, availableBuild; | |
40 | + private String snapshotDate = null; | |
31 | 41 | |
32 | 42 | public LiteLoaderUpdateSite(String targetVersion, long currentTimeStamp) |
33 | 43 | { |
... | ... | @@ -36,6 +46,64 @@ public class LiteLoaderUpdateSite extends UpdateSite |
36 | 46 | |
37 | 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 | 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 | 26 | public static final Obf BakedProfilingHandlerList = new Obf("com.mumfrey.liteloader.core.event.ProfilingHandlerList$BakedList" ); |
27 | 27 | public static final Obf PacketEvents = new Obf("com.mumfrey.liteloader.core.PacketEvents" ); |
28 | 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 | 29 | public static final Obf GameProfile = new Obf("com.mojang.authlib.GameProfile" ); |
31 | 30 | public static final Obf MinecraftMain = new Obf("net.minecraft.client.main.Main" ); |
32 | 31 | public static final Obf MinecraftServer = new Obf("net.minecraft.server.MinecraftServer" ); |
33 | 32 | public static final Obf GL11 = new Obf("org.lwjgl.opengl.GL11" ); |
34 | 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 | 34 | public static final Obf constructor = new Obf("<init>" ); |
38 | 35 | |
39 | 36 | // CHECKSTYLE:OFF | ... | ... |
src/main/java/com/mumfrey/liteloader/core/runtime/Packets.java
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | */ |
6 | 6 | package com.mumfrey.liteloader.core.runtime; |
7 | 7 | |
8 | +import java.lang.reflect.Field; | |
8 | 9 | import java.util.HashMap; |
9 | 10 | import java.util.Map; |
10 | 11 | |
... | ... | @@ -157,125 +158,7 @@ public final class Packets extends Obf |
157 | 158 | |
158 | 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 | 163 | private static int nextPacketIndex; |
281 | 164 | |
... | ... | @@ -295,6 +178,24 @@ public final class Packets extends Obf |
295 | 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 | 199 | public int getIndex() |
299 | 200 | { |
300 | 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 | 88 | * Get whether "force update" is enabled |
89 | 89 | */ |
90 | 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 | 99 | public static final String OPTION_FORCE_UPDATE = "allowForceUpdate"; |
100 | 100 | public static final String OPTION_UPDATE_CHECK_INTR = "updateCheckInterval"; |
101 | 101 | public static final String OPTION_JINPUT_DISABLE = "disableJInput"; |
102 | + public static final String OPTION_CHECK_SNAPSHOTS = "checkForNewSnapshots"; | |
102 | 103 | |
103 | 104 | // Enumerator properties |
104 | 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 | 17 | import com.google.common.io.Files; |
18 | 18 | import com.mumfrey.liteloader.Configurable; |
19 | 19 | import com.mumfrey.liteloader.LiteMod; |
20 | +import com.mumfrey.liteloader.util.log.LiteLoaderLogger; | |
20 | 21 | |
21 | 22 | /** |
22 | 23 | * Registry where we keep the mod config panel classes and config file writers |
... | ... | @@ -165,6 +166,10 @@ public class ConfigManager |
165 | 166 | } |
166 | 167 | catch (InstantiationException ex) {} |
167 | 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 | 174 | // If instantiation fails, remove the panel |
170 | 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 | 47 | * Permissions permissible which is a proxy for permissions that are common |
48 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 124 | if (mod == null) mod = allMods; |
125 | 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 | 134 | /* (non-Javadoc) |
... | ... | @@ -138,8 +141,11 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi |
138 | 141 | if (mod == null) mod = allMods; |
139 | 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 | 214 | */ |
209 | 215 | protected void clearServerPermissions() |
210 | 216 | { |
211 | - this.serverPermissions.clear(); | |
217 | + synchronized (this.serverPermissions) | |
218 | + { | |
219 | + this.serverPermissions.clear(); | |
220 | + } | |
212 | 221 | |
213 | 222 | for (Permissible permissible : this.permissibles) |
214 | 223 | { |
... | ... | @@ -264,7 +273,10 @@ public final class PermissionsManagerClient implements PermissionsManager, Plugi |
264 | 273 | } |
265 | 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 | 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 | 351 | |
337 | 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 | 359 | Permissible permissible = this.registeredClientMods.get(modPermissions.getModName()); |
342 | 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 | 160 | } |
161 | 161 | } |
162 | 162 | } |
163 | + | |
164 | + public boolean isSnapshot() | |
165 | + { | |
166 | + return false; | |
167 | + } | |
163 | 168 | |
164 | 169 | /** |
165 | 170 | * Gets whether a check is in progress |
... | ... | @@ -319,7 +324,7 @@ public class UpdateSite implements Comparator<Long> |
319 | 324 | */ |
320 | 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 | 329 | if (value.containsKey(this.artefact)) |
325 | 330 | { |
... | ... | @@ -387,7 +392,7 @@ public class UpdateSite implements Comparator<Long> |
387 | 392 | this.availableVersion = artefact.get("version").toString(); |
388 | 393 | this.availableVersionDate = DateFormat.getDateTimeInstance().format(new Date(remoteTimeStamp * 1000L)); |
389 | 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 | 397 | return true; |
393 | 398 | } |
... | ... | @@ -395,6 +400,11 @@ public class UpdateSite implements Comparator<Long> |
395 | 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 | 409 | * @param bestTimeStamp |
400 | 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 | 16 | gui.settings.forceupdate.label=Periodically Check For Updates |
17 | 17 | gui.settings.forceupdate.help1=This option is §cexperimental§r and may not work properly |
18 | 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 | 23 | gui.about.taboptions=§nLiteLoader Panel Options |
21 | 24 | |
... | ... | @@ -83,7 +86,11 @@ gui.log.uploadsuccess=Upload succeeded, log available at |
83 | 86 | gui.log.closedialog=Close |
84 | 87 | |
85 | 88 | gui.error.title=Startup errors for %s |
89 | +gui.error.copytoclipboard=Copy error to clipboard | |
86 | 90 | |
87 | 91 | gui.error.tooltip=%d mod startup error(s) detected (%d critical) |
88 | 92 | |
89 | -gui.notifications.updateavailable=LiteLoader Update Available! | |
90 | 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 | 98 | \ No newline at end of file | ... | ... |
src/main/resources/mixins.liteloader.core.json