diff --git a/src/main/kotlin/Checksum.kt b/src/main/kotlin/Checksum.kt index dbfb944..43be22b 100644 --- a/src/main/kotlin/Checksum.kt +++ b/src/main/kotlin/Checksum.kt @@ -2,6 +2,7 @@ import java.io.File import java.io.FileInputStream import java.io.IOException import java.io.InputStream +import java.net.URI import java.net.URL import java.security.MessageDigest import java.security.NoSuchAlgorithmException @@ -21,7 +22,7 @@ object Checksum { return null } - fun getLocalChecksum(file: String?): String { + fun getLocalChecksum(file: URI?): String { val local = File(file!!) if(!local.exists()) return "" else FileInputStream(local).use { fis -> return calculateMd5(fis) } diff --git a/src/main/kotlin/Globals.kt b/src/main/kotlin/Globals.kt index 0199ad3..18d020c 100644 --- a/src/main/kotlin/Globals.kt +++ b/src/main/kotlin/Globals.kt @@ -1,3 +1,4 @@ +import settingseditor.SettingsWindow import java.awt.Component import java.io.File import kotlin.system.exitProcess @@ -10,9 +11,9 @@ fun Component.placeAt(x: Int, y: Int, width: Int, height: Int){ fun launchClient() { println("Launching client now.") var proc = Runtime.getRuntime().exec("java -jar " + Settings.SAVE_NAME, null, File(System.getProperty("user.home"))) - if(proc.isAlive){ + if(proc.isAlive && SettingsWindow.closeLauncherOnLaunch.isToggled){ exitProcess(0) - } else { + } else if(SettingsWindow.closeLauncherOnLaunch.isToggled) { MainWindow.loadingLabel.text = "Error starting the client." } } \ No newline at end of file diff --git a/src/main/kotlin/MainWindow.kt b/src/main/kotlin/MainWindow.kt index f2f5a38..4757dfa 100644 --- a/src/main/kotlin/MainWindow.kt +++ b/src/main/kotlin/MainWindow.kt @@ -1,4 +1,6 @@ import com.sun.java.accessibility.util.AWTEventMonitor +import launcherupdate.LauncherUpdateNotification +import settingseditor.Json import settingseditor.SettingsWindow import java.awt.* import java.awt.event.MouseAdapter @@ -37,6 +39,7 @@ object MainWindow : JFrame("2009scape Launcher") { isVisible = true isEnabled = true pack() + //SettingsWindow //<-- initialize all this shit haha hacks go weeee } private fun constructTopBar(){ @@ -85,30 +88,33 @@ object MainWindow : JFrame("2009scape Launcher") { val loadingFrame = JLabel(ImageIcon(javaClass.getResource("/loadingFrame.png"))) playButton.isEnabled = true playButton.onClick { - val t = Thread { - val oldText = loadingLabel.text - loadingLabel.text = "Checking for updates" - playButton.isEnabled = false - var counter = 0 - var dotCounter = 0 - while(Updater.status == Updater.UpdateStatus.CHECKING){ - if(counter++ % 5 == 0){ - dotCounter++ - loadingLabel.text = "Checking for updates${".".repeat((dotCounter % 4) + 1)}" + if(!Settings.HAS_UPDATED) { + val t = Thread { + val oldText = loadingLabel.text + loadingLabel.text = "Checking for updates" + playButton.isEnabled = false + var counter = 0 + var dotCounter = 0 + while (Updater.status == Updater.UpdateStatus.CHECKING) { + if (counter++ % 5 == 0) { + dotCounter++ + loadingLabel.text = "Checking for updates${".".repeat((dotCounter % 4) + 1)}" + } + Thread.sleep(50L) } - Thread.sleep(50L) - } - if(Updater.remoteMD5 != "-1" && Updater.remoteMD5 != Updater.localMD5){ - println("Update required, running update...") - loadingLabel.text = oldText - Updater.runUpdate() - } else { - loadingLabel.text = oldText - playButton.isEnabled = true - launchClient() - } - }.start() - Thread { Updater.checkUpdate() }.start() + Settings.HAS_UPDATED = true + if (Updater.remoteMD5 != "-1" && Updater.remoteMD5 != Updater.localMD5) { + println("Update required, running update...") + loadingLabel.text = oldText + Updater.runUpdate() + } else { + loadingLabel.text = oldText + playButton.isEnabled = true + launchClient() + } + }.start() + Thread { Updater.checkUpdate() }.start() + } else launchClient() } loadingFrame.placeAt(96,MainWindow.height - 35, 704, 35) loadingBar.placeAt(103, MainWindow.height - 33, 695, 31) @@ -199,7 +205,7 @@ object MainWindow : JFrame("2009scape Launcher") { button.onClick { SettingsWindow.open() } - button.placeAt(panel.width - 75, 6, 30, 30) + button.placeAt(panel.width - 80, 1, 40, 40) panel.add(button) } @@ -220,6 +226,18 @@ object MainWindow : JFrame("2009scape Launcher") { @JvmStatic fun main(args: Array) { - + Json.parse() + val t = Thread { + if(Settings.CHECK_FOR_UPDATES) { + Updater.checkLauncherUpdate() + while (Updater.launcherStatus == Updater.UpdateStatus.CHECKING) { + Thread.sleep(100L) + } + if (Updater.launcherLocalMD5 != Updater.launcherRemoteMD5) { + System.out.println("Trying to open") + LauncherUpdateNotification.open() + } + } + }.start() } } \ No newline at end of file diff --git a/src/main/kotlin/Settings.kt b/src/main/kotlin/Settings.kt index 4633f68..3751b1c 100644 --- a/src/main/kotlin/Settings.kt +++ b/src/main/kotlin/Settings.kt @@ -2,4 +2,11 @@ object Settings { val SAVE_DIR = System.getProperty("user.home") val SAVE_NAME = "2009scape.jar" val DOWNLOAD_URL = "http://play.2009scape.org/2009scape.jar" + val LAUNCHER_URL = "https://gitlab.com/2009scape/09launcher/-/jobs/artifacts/master/raw/build/libs/2009scape.jar?job=build" + var HAS_UPDATED = false + var CHECK_FOR_UPDATES = true + set(value) { + field = value + println(value) + } } \ No newline at end of file diff --git a/src/main/kotlin/Updater.kt b/src/main/kotlin/Updater.kt index 1a578ae..6ace6a4 100644 --- a/src/main/kotlin/Updater.kt +++ b/src/main/kotlin/Updater.kt @@ -1,6 +1,7 @@ import java.awt.Image import java.io.File import java.io.RandomAccessFile +import java.net.URI import java.net.URL import java.util.concurrent.Executors import javax.swing.ImageIcon @@ -10,15 +11,26 @@ object Updater { var status = UpdateStatus.CHECKING var localMD5 = "-1" var remoteMD5 = "-1" + var launcherRemoteMD5 = "-1" + var launcherLocalMD5 = "-1" + var launcherStatus = UpdateStatus.CHECKING fun checkUpdate(){ status = UpdateStatus.CHECKING - localMD5 = Checksum.getLocalChecksum(Settings.SAVE_DIR + File.separator + Settings.SAVE_NAME) + localMD5 = Checksum.getLocalChecksum(URI.create("file://" + Settings.SAVE_DIR + File.separator + Settings.SAVE_NAME)) remoteMD5 = Checksum.getRemoteChecksum(Settings.DOWNLOAD_URL) ?: "-1" println("Local: $localMD5 || Remote: $remoteMD5") status = UpdateStatus.COMPLETE } + fun checkLauncherUpdate(){ + launcherStatus = UpdateStatus.CHECKING + launcherLocalMD5 = Checksum.getLocalChecksum(javaClass.protectionDomain.codeSource.location.toURI()) + launcherRemoteMD5 = Checksum.getRemoteChecksum(Settings.LAUNCHER_URL) ?: "-1" + println("Launcher Local: $launcherLocalMD5 || Launcher Remote: $launcherRemoteMD5") + launcherStatus = UpdateStatus.COMPLETE + } + fun runUpdate(){ val t = Thread() { var oldText = MainWindow.loadingLabel.text diff --git a/src/main/kotlin/launcherupdate/LauncherUpdateNotification.kt b/src/main/kotlin/launcherupdate/LauncherUpdateNotification.kt new file mode 100644 index 0000000..1891b0a --- /dev/null +++ b/src/main/kotlin/launcherupdate/LauncherUpdateNotification.kt @@ -0,0 +1,104 @@ +package launcherupdate + +import BackgroundPanel +import Checkbox +import ImgButton +import placeAt +import settingseditor.Json +import settingseditor.SettingsWindow +import java.awt.* +import java.net.URI +import javax.imageio.ImageIO +import javax.swing.JFrame +import javax.swing.JLabel +import javax.swing.JPanel +import javax.swing.JSeparator +import javax.swing.border.Border +import kotlin.system.exitProcess + +object LauncherUpdateNotification : JFrame() { + init { + isUndecorated = true + isVisible = false + isResizable = false + defaultCloseOperation = HIDE_ON_CLOSE + isAutoRequestFocus = true + isAlwaysOnTop = true + preferredSize = Dimension(250,150) + size = Dimension(250,150) + layout = BorderLayout() + setLocationRelativeTo(null) + + val textArea = getDarkPanel(BorderLayout()) + val label = getLabel("
A new launcher update is available!
Would you like to download it now?
") + textArea.add(label, BorderLayout.NORTH) + + val interiorPanel = getDarkPanel(BorderLayout()) + val checkBoxLabel = getLabel("Notify me of future updates") + val checkBox = Checkbox() + checkBox.isToggled = Settings.CHECK_FOR_UPDATES + checkBox.onClick { + checkBox.isToggled = !checkBox.isToggled + Settings.CHECK_FOR_UPDATES = checkBox.isToggled + } + interiorPanel.add(checkBoxLabel, BorderLayout.WEST) + interiorPanel.add(checkBox, BorderLayout.EAST) + textArea.add(interiorPanel,BorderLayout.SOUTH) + add(textArea, BorderLayout.CENTER) + + + + val buttons = getThemedPanel(BorderLayout()) + val yesButton = ImgButton("/save_hi.png") + yesButton.onClick { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Desktop.getDesktop().browse(URI(Settings.LAUNCHER_URL)); + } + Json.save() + exitProcess(0) + } + + val noButton = ImgButton("/update_no.png") + noButton.onClick { + Json.save() + isVisible = false + MainWindow.isEnabled = true + } + + buttons.add(getSeparator(), BorderLayout.NORTH) + buttons.add(yesButton,BorderLayout.WEST) + buttons.add(noButton,BorderLayout.EAST) + add(buttons, BorderLayout.SOUTH) + pack() + } + + fun getThemedPanel(layout: LayoutManager? = null): JPanel { + val panel = if(layout == null) JPanel() else JPanel(layout) + panel.background = Color(102,90,69) + return panel + } + + fun getDarkPanel(layout: LayoutManager? = null): JPanel { + val panel = if(layout == null) JPanel() else JPanel(layout) + panel.background = Color(82,73,51) + return panel + } + + fun getSeparator(): JSeparator { + val sep = JSeparator(JSeparator.HORIZONTAL) + sep.background = Color(57,49,39) + sep.foreground = Color(57,49,39) + return sep + } + + fun getLabel(text: String): JLabel { + val label = JLabel(text) + label.foreground = Color(227,208,179) + return label + } + + fun open() { + isVisible = true + MainWindow.isEnabled = false + } +} \ No newline at end of file diff --git a/src/main/kotlin/settingseditor/Json.kt b/src/main/kotlin/settingseditor/Json.kt index 0b98d28..5c5f936 100644 --- a/src/main/kotlin/settingseditor/Json.kt +++ b/src/main/kotlin/settingseditor/Json.kt @@ -18,6 +18,7 @@ object Json { val slayer = customization["slayer"] as JSONObject val rcm = customization["right_click_menu"] as JSONObject val styles = rcm["styles"] as JSONObject + val launcher = customization.getOrPut("launcher") { JSONObject() } as JSONObject val background = rcm["background"] as JSONObject val title_bar = rcm["title_bar"] as JSONObject @@ -42,6 +43,8 @@ object Json { slayer["color"] = SettingsWindow.slayerColor.text slayer["opacity"] = SettingsWindow.slayerOpacity.text customization["login_theme"] = SettingsWindow.loginTheme.text + launcher["closeOnClientLaunch"] = SettingsWindow.closeLauncherOnLaunch.isToggled + launcher["notifyUpdates"] = Settings.CHECK_FOR_UPDATES FileWriter(CONF).use { writer -> writer.write(data.toJSONString()) @@ -64,6 +67,7 @@ object Json { } val customization = data["customization"] as JSONObject + val launcher = customization.getOrPut("launcher") {JSONObject()} as JSONObject val xpDrops = customization["xpdrops"] as JSONObject val slayer = customization["slayer"] as JSONObject val rcm = customization["right_click_menu"] as JSONObject @@ -95,6 +99,9 @@ object Json { SettingsWindow.slayerColor.text = slayer.getOrDefault("color", "#635a38").toString() SettingsWindow.slayerOpacity.text = slayer.getOrDefault("opacity","180").toString() SettingsWindow.loginTheme.text = customization.getOrDefault("login_theme","scape main").toString() + + SettingsWindow.closeLauncherOnLaunch.isToggled = launcher.getOrDefault("closeOnClientLaunch", true) as Boolean + Settings.CHECK_FOR_UPDATES = launcher.getOrDefault("notifyUpdates", true) as Boolean } catch (e: Exception) { println("error parsing settings, replacing with defaults...") e.printStackTrace() diff --git a/src/main/kotlin/settingseditor/SettingsWindow.kt b/src/main/kotlin/settingseditor/SettingsWindow.kt index 185724e..e3be77a 100644 --- a/src/main/kotlin/settingseditor/SettingsWindow.kt +++ b/src/main/kotlin/settingseditor/SettingsWindow.kt @@ -40,6 +40,8 @@ object SettingsWindow : JFrame("Client Settings") { val slayerColor = JTextField() val slayerOpacity = JTextField() val slayerEnabled = Checkbox() + val closeLauncherOnLaunch = Checkbox() + val checkForLauncherUpdates = Checkbox() init { isUndecorated = true @@ -56,6 +58,7 @@ object SettingsWindow : JFrame("Client Settings") { addDebugTab() addRightClickTab() addMiscTab() + addLauncherSettingsTab() val saveButton = ImgButton("/save_hi.png","/save_lo.png") saveButton.onClick { @@ -64,6 +67,14 @@ object SettingsWindow : JFrame("Client Settings") { } saveButton.placeAt(width - 30, height - 30, 30, 30) add(saveButton) + + val closeButton = ImgButton("/close_hi.png", "/close_dark.png") + closeButton.onClick { + isVisible = false + Json.parse() + } + closeButton.placeAt(width - 25, 5, 20, 20) + add(closeButton) } fun addMiscTab() { @@ -71,13 +82,6 @@ object SettingsWindow : JFrame("Client Settings") { pane.layout = BoxLayout(pane, BoxLayout.PAGE_AXIS) val button = ImgButton("/misc.png", "/misc.png", false) - val label = BackgroundLabel("/messageBox.png", "Misc
Settings") - label.placeAt(40, 30, 90, 56) - add(label) - - button.onMouseEnter { label.isVisible = true } - button.onMouseExit { label.isVisible = false } - val xpTogglePanel = getThemedPanel(BorderLayout()) val xpDropPanel = getThemedPanel(BorderLayout()) val xpTrackPanel = getThemedPanel(BorderLayout()) @@ -131,20 +135,13 @@ object SettingsWindow : JFrame("Client Settings") { slayerOpacityPanel.add(slayerOpacity, BorderLayout.EAST) pane.add(slayerOpacityPanel) - addTab(pane, button, getLabel("Theme: all lowercase")) + addTab(pane, button, getLabel("Misc Settings")) } fun addDebugTab(){ val pane = getThemedPanel() pane.layout = BoxLayout(pane, BoxLayout.PAGE_AXIS) - val button = ImgButton("/settings.png", "/settings.png", false) - - val label = BackgroundLabel("/messageBox.png", "Debug
Settings") - label.placeAt(0,30, 90, 56) - add(label) - - button.onMouseEnter { label.isVisible = true } - button.onMouseExit { label.isVisible = false } + val button = ImgButton("/debug_settings.png", "/debug_settings.png", false) val itemDebug = getThemedPanel(BorderLayout()) val itemDebugLabel = getLabel("Item IDs Visible") @@ -166,7 +163,7 @@ object SettingsWindow : JFrame("Client Settings") { npcDebug.add(npcDebugCheckbox, BorderLayout.EAST) pane.add(npcDebug) - addTab(pane, button) + addTab(pane, button, getLabel("Debug Settings")) } fun addRightClickTab() { @@ -174,13 +171,6 @@ object SettingsWindow : JFrame("Client Settings") { pane.layout = BoxLayout(pane, BoxLayout.PAGE_AXIS) val button = ImgButton("/rightClick.png", "/rightClick.png", false) - val label = BackgroundLabel("/messageBox.png", "Rightclick
Settings") - label.placeAt(5,30, 90, 56) - add(label) - - button.onMouseEnter { label.isVisible = true } - button.onMouseExit { label.isVisible = false } - val rs3BorderPanel = getThemedPanel(BorderLayout()) val bgColorPanel = getThemedPanel(BorderLayout()) val bgOpacityPanel = getThemedPanel(BorderLayout()) @@ -241,7 +231,34 @@ object SettingsWindow : JFrame("Client Settings") { borderOpacityPanel.add(borderOpacity, BorderLayout.EAST) pane.add(borderOpacityPanel) - addTab(pane, button, getLabel("Color: HEX || Opacity: 0-255")) + addTab(pane, button, getLabel("Rightclick Settings")) + } + + fun addLauncherSettingsTab(){ + val pane = getThemedPanel() + pane.layout = BoxLayout(pane, BoxLayout.PAGE_AXIS) + val button = ImgButton("/launcher_settings.png", "/launcher_settings.png", false) + + val closeLauncherOnLaunchPanel = getThemedPanel(BorderLayout()) + val closeLauncherOnLaunchLabel = getLabel("Close launcher when client starts") + val checkForUpdatePanel = getThemedPanel(BorderLayout()) + val checkForUpdateLabel = getLabel("Notify me of launcher updates") + + checkForLauncherUpdates.onClick { + checkForLauncherUpdates.isToggled = !checkForLauncherUpdates.isToggled + Settings.CHECK_FOR_UPDATES = checkForLauncherUpdates.isToggled + } + + closeLauncherOnLaunchPanel.add(closeLauncherOnLaunchLabel, BorderLayout.WEST) + closeLauncherOnLaunchPanel.add(closeLauncherOnLaunch, BorderLayout.EAST) + pane.add(closeLauncherOnLaunchPanel) + pane.add(getSeparator()) + + checkForUpdatePanel.add(checkForUpdateLabel, BorderLayout.WEST) + checkForUpdatePanel.add(checkForLauncherUpdates, BorderLayout.EAST) + pane.add(checkForUpdatePanel) + + addTab(pane, button, getLabel("Launcher Settings")) } fun addTab(content: JPanel, button: ImgButton, tabNote: JLabel = getLabel("")){ @@ -251,7 +268,7 @@ object SettingsWindow : JFrame("Client Settings") { content.isVisible = false button.placeAt(buttonSpacer, 0, 30, 30) button.onClick { activeTab = buttons.indexOf(button); updateVisibleTab() } - buttonSpacer += 35 + buttonSpacer += 40 add(button) button.isEnabled = false buttons.add(button) @@ -265,6 +282,7 @@ object SettingsWindow : JFrame("Client Settings") { activeTab = 0 updateVisibleTab() Json.parse() + checkForLauncherUpdates.isToggled = Settings.CHECK_FOR_UPDATES isVisible = true } diff --git a/src/main/resources/debug_settings.png b/src/main/resources/debug_settings.png new file mode 100644 index 0000000..5b9f947 Binary files /dev/null and b/src/main/resources/debug_settings.png differ diff --git a/src/main/resources/launcher_settings.png b/src/main/resources/launcher_settings.png new file mode 100644 index 0000000..989ed51 Binary files /dev/null and b/src/main/resources/launcher_settings.png differ diff --git a/src/main/resources/settings.png b/src/main/resources/settings.png index 5b9f947..b8800b6 100644 Binary files a/src/main/resources/settings.png and b/src/main/resources/settings.png differ diff --git a/src/main/resources/update_no.png b/src/main/resources/update_no.png new file mode 100644 index 0000000..9737aeb Binary files /dev/null and b/src/main/resources/update_no.png differ