From 28b0c48ce79ac5562e402a0f5b1b856630c4c9c0 Mon Sep 17 00:00:00 2001
From: My-Name-Is-Jeff <37018278+My-Name-Is-Jeff@users.noreply.github.com>
Date: Sun, 30 May 2021 18:40:22 -0400
Subject: [PATCH] Failing downloads no longer suspend the updater + added a
 summary screen

---
 .../skyblockclientupdater/gui/UpdateScreen.kt | 40 +++++++++----------
 .../gui/UpdateSummaryScreen.kt                | 31 ++++++++++++++
 .../skyblockclientupdater/utils/TickTask.kt   | 40 +++++++++++++++++++
 3 files changed, 91 insertions(+), 20 deletions(-)
 create mode 100644 src/main/kotlin/mynameisjeff/skyblockclientupdater/gui/UpdateSummaryScreen.kt
 create mode 100644 src/main/kotlin/mynameisjeff/skyblockclientupdater/utils/TickTask.kt

diff --git a/src/main/kotlin/mynameisjeff/skyblockclientupdater/gui/UpdateScreen.kt b/src/main/kotlin/mynameisjeff/skyblockclientupdater/gui/UpdateScreen.kt
index 5db19c2..8afecc6 100644
--- a/src/main/kotlin/mynameisjeff/skyblockclientupdater/gui/UpdateScreen.kt
+++ b/src/main/kotlin/mynameisjeff/skyblockclientupdater/gui/UpdateScreen.kt
@@ -1,10 +1,10 @@
 package mynameisjeff.skyblockclientupdater.gui
 
 import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.job
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import mynameisjeff.skyblockclientupdater.SkyClientUpdater
+import mynameisjeff.skyblockclientupdater.utils.TickTask
 import mynameisjeff.skyblockclientupdater.utils.UpdateChecker
 import net.minecraft.client.gui.GuiButton
 import net.minecraft.client.gui.GuiScreen
@@ -22,13 +22,13 @@ import kotlin.concurrent.thread
  * https://github.com/Skytils/SkytilsMod/blob/1.x/LICENSE
  */
 class UpdateScreen(private val updatingMods: List<Triple<File, String, String>>) : GuiScreen() {
-    private var failed = false
     private var complete = false
     private var exited = false
     private var backButton: GuiButton = GuiButton(0, 0, 0, 200, 20, "")
     private var progress = 0f
 
-    private var completedDownloads = 0
+    private var downloadedMods = arrayListOf<File>()
+    private var failedDownloadingMods = arrayListOf<File>()
 
     override fun initGui() {
         backButton.xPosition = width / 2 - 100
@@ -47,12 +47,12 @@ class UpdateScreen(private val updatingMods: List<Triple<File, String, String>>)
                         launch(Dispatchers.IO) {
                             val jarName = update.second
                             val url = update.third
-                            downloadUpdate(url, File(directory, jarName))
-                            if (!failed) {
+                            val file = File(directory, jarName)
+                            downloadUpdate(url, file)
+                            if (!failedDownloadingMods.contains(file)) {
+                                downloadedMods.add(file)
                                 UpdateChecker.deleteFileOnShutdown(update.first, jarName)
                             }
-                        }.invokeOnCompletion {
-                            completedDownloads++
                         }
                     }
                 } catch (ex: Exception) {
@@ -63,7 +63,7 @@ class UpdateScreen(private val updatingMods: List<Triple<File, String, String>>)
     }
 
     private fun updateText() {
-        backButton.displayString = if (failed || complete) "Back" else "Cancel"
+        backButton.displayString = if (exited || complete) "Back" else "Cancel"
     }
 
     private fun downloadUpdate(url: String, location: File) {
@@ -75,14 +75,14 @@ class UpdateScreen(private val updatingMods: List<Triple<File, String, String>>)
             )
             st.connect()
             if (st.responseCode != HttpURLConnection.HTTP_OK) {
-                failed = true
+                failedDownloadingMods.add(location)
                 updateText()
                 println(url + " returned status code " + st.responseCode)
                 return
             }
             location.parentFile.mkdirs()
             if (!location.exists() && !location.createNewFile()) {
-                failed = true
+                failedDownloadingMods.add(location)
                 updateText()
                 println("Couldn't create update file directory")
                 return
@@ -98,7 +98,6 @@ class UpdateScreen(private val updatingMods: List<Triple<File, String, String>>)
                     // Cancelled
                     fos.close()
                     fis.close()
-                    failed = true
                     return
                 }
                 total += count.toLong()
@@ -109,12 +108,11 @@ class UpdateScreen(private val updatingMods: List<Triple<File, String, String>>)
             fos.close()
             fis.close()
             if (exited) {
-                failed = true
                 return
             }
         } catch (ex: Exception) {
             ex.printStackTrace()
-            failed = true
+            failedDownloadingMods.add(location)
             updateText()
         }
     }
@@ -128,9 +126,9 @@ class UpdateScreen(private val updatingMods: List<Triple<File, String, String>>)
     override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) {
         drawDefaultBackground()
         when {
-            failed -> drawCenteredString(
+            exited -> drawCenteredString(
                 mc.fontRendererObj,
-                EnumChatFormatting.RED.toString() + "Update download failed",
+                EnumChatFormatting.RED.toString() + "Update download exited",
                 width / 2,
                 height / 2,
                 -0x1
@@ -142,13 +140,15 @@ class UpdateScreen(private val updatingMods: List<Triple<File, String, String>>)
                 height / 2,
                 0xFFFFFF
             )
+            downloadedMods.size + failedDownloadingMods.size == updatingMods.size -> {
+                complete = true
+                updateText()
+                TickTask(1) {
+                    mc.displayGuiScreen(UpdateSummaryScreen(downloadedMods, failedDownloadingMods))
+                }
+            }
             else -> {
                 drawCenteredString(mc.fontRendererObj,"Downloading... ${UpdateChecker.needsDelete.size} / ${updatingMods.size}", width / 2, height / 2, 0xFFFFFF)
-                if (!failed && completedDownloads == updatingMods.size) {
-                    mc.shutdown()
-                    complete = true
-                    updateText()
-                }
             }
         }
         super.drawScreen(mouseX, mouseY, partialTicks)
diff --git a/src/main/kotlin/mynameisjeff/skyblockclientupdater/gui/UpdateSummaryScreen.kt b/src/main/kotlin/mynameisjeff/skyblockclientupdater/gui/UpdateSummaryScreen.kt
new file mode 100644
index 0000000..5bd3ebb
--- /dev/null
+++ b/src/main/kotlin/mynameisjeff/skyblockclientupdater/gui/UpdateSummaryScreen.kt
@@ -0,0 +1,31 @@
+package mynameisjeff.skyblockclientupdater.gui
+
+import net.minecraft.client.gui.GuiButton
+import net.minecraft.client.gui.GuiScreen
+import java.awt.Color
+import java.io.File
+
+class UpdateSummaryScreen(val downloadedMods: ArrayList<File>, val failedDownloadingMods: ArrayList<File>) : GuiScreen() {
+
+    override fun initGui() {
+        buttonList.add(GuiButton(0, width / 2 - 100, height - 75, 200, 20, "Quit Game"))
+    }
+
+    override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) {
+        drawDefaultBackground()
+
+        drawCenteredString(fontRendererObj, "${downloadedMods.size + failedDownloadingMods.size} updates requested", width / 2, 20, 0xFFFFFF)
+        drawCenteredString(fontRendererObj, "${downloadedMods.size} updates successful", width / 4, 30, Color.GREEN.rgb)
+        drawCenteredString(fontRendererObj, "${failedDownloadingMods.size} updates failed", 3 * (width / 4), 30, Color.RED.rgb)
+
+        for (i in 0 until downloadedMods.size) drawCenteredString(fontRendererObj,
+            downloadedMods[i].name, width / 4, 30 + i.inc() * fontRendererObj.FONT_HEIGHT, Color.GREEN.rgb)
+        for (i in 0 until failedDownloadingMods.size) drawCenteredString(fontRendererObj,
+            failedDownloadingMods[i].name, 3 * (width / 4), 30 + i.inc() * fontRendererObj.FONT_HEIGHT, Color.RED.rgb)
+        super.drawScreen(mouseX, mouseY, partialTicks)
+    }
+
+    override fun actionPerformed(button: GuiButton) {
+        mc.shutdown()
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/mynameisjeff/skyblockclientupdater/utils/TickTask.kt b/src/main/kotlin/mynameisjeff/skyblockclientupdater/utils/TickTask.kt
new file mode 100644
index 0000000..054f0cf
--- /dev/null
+++ b/src/main/kotlin/mynameisjeff/skyblockclientupdater/utils/TickTask.kt
@@ -0,0 +1,40 @@
+/*
+ * Skytils - Hypixel Skyblock Quality of Life Mod
+ * Copyright (C) 2021 Skytils
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package mynameisjeff.skyblockclientupdater.utils
+
+import net.minecraftforge.common.MinecraftForge
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent
+
+class TickTask(private var ticks: Int = 0, private val task: () -> Unit) {
+
+    @SubscribeEvent
+    fun onTick(event: TickEvent.ClientTickEvent) {
+        if (event.phase != TickEvent.Phase.START) return
+        if (ticks <= 0) {
+            task()
+            MinecraftForge.EVENT_BUS.unregister(this)
+        }
+        ticks--
+    }
+
+    init {
+        MinecraftForge.EVENT_BUS.register(this)
+    }
+}
\ No newline at end of file