From dee36e793b0ce433e73245ec14cd51b520d63ffa Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 15 Jul 2021 19:28:03 -0500 Subject: [PATCH] Initial push --- .idea/.gitignore | 0 build.gradle | 22 ++++ gradle.properties | 1 + settings.gradle | 2 + src/main/kotlin/BackgroundLabel.kt | 15 +++ src/main/kotlin/BackgroundPanel.kt | 40 ++++++ src/main/kotlin/Checksum.kt | 98 ++++++++++++++ src/main/kotlin/Extensions.kt | 6 + src/main/kotlin/ImgButton.kt | 55 ++++++++ src/main/kotlin/LatestUpdatePane.kt | 71 ++++++++++ src/main/kotlin/MainWindow.kt | 153 ++++++++++++++++++++++ src/main/kotlin/Settings.kt | 5 + src/main/kotlin/Updater.kt | 86 ++++++++++++ src/main/resources/close_dark.png | Bin 0 -> 295 bytes src/main/resources/close_hi.png | Bin 0 -> 316 bytes src/main/resources/highScores.png | Bin 0 -> 382 bytes src/main/resources/joinDiscord.png | Bin 0 -> 435 bytes src/main/resources/loadingBar.png | Bin 0 -> 676 bytes src/main/resources/loadingFrame.png | Bin 0 -> 731 bytes src/main/resources/logo.png | Bin 0 -> 15809 bytes src/main/resources/messageBox.png | Bin 0 -> 1040 bytes src/main/resources/news.png | Bin 0 -> 1967 bytes src/main/resources/playButton.png | Bin 0 -> 11625 bytes src/main/resources/playButtonDisabled.png | Bin 0 -> 10737 bytes src/main/resources/reportBug.png | Bin 0 -> 880 bytes src/main/resources/tile.png | Bin 0 -> 652 bytes src/main/resources/topBar.png | Bin 0 -> 366 bytes 27 files changed, 554 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 settings.gradle create mode 100644 src/main/kotlin/BackgroundLabel.kt create mode 100644 src/main/kotlin/BackgroundPanel.kt create mode 100644 src/main/kotlin/Checksum.kt create mode 100644 src/main/kotlin/Extensions.kt create mode 100644 src/main/kotlin/ImgButton.kt create mode 100644 src/main/kotlin/LatestUpdatePane.kt create mode 100644 src/main/kotlin/MainWindow.kt create mode 100644 src/main/kotlin/Settings.kt create mode 100644 src/main/kotlin/Updater.kt create mode 100644 src/main/resources/close_dark.png create mode 100644 src/main/resources/close_hi.png create mode 100644 src/main/resources/highScores.png create mode 100644 src/main/resources/joinDiscord.png create mode 100644 src/main/resources/loadingBar.png create mode 100644 src/main/resources/loadingFrame.png create mode 100644 src/main/resources/logo.png create mode 100644 src/main/resources/messageBox.png create mode 100644 src/main/resources/news.png create mode 100644 src/main/resources/playButton.png create mode 100644 src/main/resources/playButtonDisabled.png create mode 100644 src/main/resources/reportBug.png create mode 100644 src/main/resources/tile.png create mode 100644 src/main/resources/topBar.png diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..f45880c --- /dev/null +++ b/build.gradle @@ -0,0 +1,22 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' version '1.4.32' +} + +group 'org.rs09' +version '1.0' + +repositories { + mavenCentral() +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib" + implementation 'org.jsoup:jsoup:1.14.1' +} + +jar { + manifest { + attributes 'Main-Class': 'MainWindow' + } + from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..29e08e8 --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +kotlin.code.style=official \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..b8d02f1 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'rs09launcher' + diff --git a/src/main/kotlin/BackgroundLabel.kt b/src/main/kotlin/BackgroundLabel.kt new file mode 100644 index 0000000..555ddb8 --- /dev/null +++ b/src/main/kotlin/BackgroundLabel.kt @@ -0,0 +1,15 @@ +import java.awt.BorderLayout +import java.awt.Color +import java.awt.GridBagLayout +import javax.swing.JLabel + +class BackgroundLabel(url: String, text: String) : BackgroundPanel(url) { + val textLabel = JLabel("
$text
return calculateMd5(fis) } + } catch (e: Exception) { + e.printStackTrace() + MainWindow.loadingLabel.text = e.message + MainWindow.loadingLabel.repaint() + } + return null + } + + fun getLocalChecksum(file: String?): String { + val local = File(file!!) + if(!local.exists()) return "" + else FileInputStream(local).use { fis -> return calculateMd5(fis) } + } + + val remoteChecksum: String? + get() { + try { + URL(Settings.DOWNLOAD_URL).openStream().use { stream -> return calculateMd5(stream) } + } catch (e: Exception) { + e.printStackTrace() + MainWindow.loadingLabel.text = e.message + MainWindow.loadingLabel.repaint() + return null + } + } + + fun getRemoteChecksum(url: String?): String? { + try { + URL(url).openStream().use { stream -> return calculateMd5(stream) } + } catch (e: Exception) { + e.printStackTrace() + MainWindow.loadingLabel.text = e.message + MainWindow.loadingLabel.repaint() + return null + } + } + + fun calculateMd5(instream: InputStream): String { + return calculateDigest(instream, "MD5") + } + + private fun calculateDigest(instream: InputStream, algorithm: String): String { + val buffer = ByteArray(4096) + val messageDigest = getMessageDigest(algorithm) + messageDigest!!.reset() + var bytesRead: Int + try { + while (instream.read(buffer).also { bytesRead = it } != -1) { + messageDigest.update(buffer, 0, bytesRead) + } + } catch (e: IOException) { + System.err.println("Error making a '$algorithm' digest on the inputstream") + } + return toHex(messageDigest.digest()) + } + + fun toHex(ba: ByteArray): String { + val baLen = ba.size + val hexchars = CharArray(baLen * 2) + var cIdx = 0 + for (i in 0 until baLen) { + hexchars[cIdx++] = hexdigit[(ba[i].toInt() shr 4) and 0x0F] + hexchars[cIdx++] = hexdigit[(ba[i] and 0x0F).toInt()] + } + return String(hexchars) + } + + fun getMessageDigest(algorithm: String): MessageDigest? { + var messageDigest: MessageDigest? = null + try { + messageDigest = MessageDigest.getInstance(algorithm) + } catch (e: NoSuchAlgorithmException) { + System.err.println("The '$algorithm' algorithm is not available") + } + return messageDigest + } + + private val hexdigit = charArrayOf( + '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f' + ) +} \ No newline at end of file diff --git a/src/main/kotlin/Extensions.kt b/src/main/kotlin/Extensions.kt new file mode 100644 index 0000000..bcbb469 --- /dev/null +++ b/src/main/kotlin/Extensions.kt @@ -0,0 +1,6 @@ +import java.awt.Component + +fun Component.placeAt(x: Int, y: Int, width: Int, height: Int){ + this.setBounds(x,y,width,height) + if(this is ImgButton) this.scale(width,height) +} \ No newline at end of file diff --git a/src/main/kotlin/ImgButton.kt b/src/main/kotlin/ImgButton.kt new file mode 100644 index 0000000..c049094 --- /dev/null +++ b/src/main/kotlin/ImgButton.kt @@ -0,0 +1,55 @@ +import java.awt.Image +import java.awt.event.MouseEvent +import java.awt.event.MouseListener +import javax.swing.Icon +import javax.swing.ImageIcon +import javax.swing.JLabel + +class ImgButton(enabledURL: String, disabledURL: String = enabledURL, val autoHandleMouse: Boolean = true) : JLabel() { + + private var hoverMethod: (MouseEvent) -> Unit = {} + private var mouseLeaveMethod: (MouseEvent) -> Unit = {} + private var onClickMethod: (MouseEvent) -> Unit = {} + + init { + isEnabled = false + icon = ImageIcon(javaClass.getResource(enabledURL)) + disabledIcon = ImageIcon(javaClass.getResource(disabledURL)) + addMouseListener(object : MouseListener { + override fun mouseClicked(p0: MouseEvent) { + onClickMethod.invoke(p0) + } + + override fun mousePressed(p0: MouseEvent?) {} + + override fun mouseReleased(p0: MouseEvent?) {} + + override fun mouseEntered(p0: MouseEvent) { + if(autoHandleMouse) isEnabled = true + hoverMethod.invoke(p0) + } + + override fun mouseExited(p0: MouseEvent) { + if(autoHandleMouse) isEnabled = false + mouseLeaveMethod.invoke(p0) + } + }) + } + + fun onClick(handler: (event: MouseEvent) -> Unit){ + onClickMethod = handler + } + + fun onMouseEnter(handler: (event: MouseEvent) -> Unit){ + hoverMethod = handler + } + + fun onMouseExit(handler: (event: MouseEvent) -> Unit){ + mouseLeaveMethod = handler + } + + fun scale(width: Int, height: Int){ + icon = ImageIcon((icon as ImageIcon).image.getScaledInstance(width,height, Image.SCALE_SMOOTH)) + disabledIcon = ImageIcon((disabledIcon as ImageIcon).image.getScaledInstance(width, height, Image.SCALE_SMOOTH)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/LatestUpdatePane.kt b/src/main/kotlin/LatestUpdatePane.kt new file mode 100644 index 0000000..8073551 --- /dev/null +++ b/src/main/kotlin/LatestUpdatePane.kt @@ -0,0 +1,71 @@ +import org.jsoup.Jsoup +import org.jsoup.nodes.Element +import org.jsoup.nodes.Node +import java.awt.Color +import java.awt.Dimension +import java.awt.Graphics +import java.awt.Rectangle +import javax.swing.JButton +import javax.swing.JComponent +import javax.swing.JScrollPane +import javax.swing.JTextPane +import javax.swing.plaf.basic.BasicScrollBarUI + +class LatestUpdatePane(url: String) : JScrollPane() { + val texPane = JTextPane() + init { + texPane.contentType = "text/html" + + texPane.putClientProperty(JTextPane.HONOR_DISPLAY_PROPERTIES, true) + border = null + + val doc = Jsoup.connect(url).get() + doc.getElementsByTag("img").remove() + removeComments(doc) + val postBody = doc.select(".rightpanel").select(".msgcontents") + texPane.text = postBody.toString() + setViewportView(texPane) + + getViewport().background = Color(153,132,104) + texPane.background = Color(153,132,104) + background = Color(153,132,104) + + getVerticalScrollBar().ui = object : BasicScrollBarUI() { + override fun configureScrollBarColors() { + this.thumbColor = Color(75,69,53) + } + + override fun paintTrack(p0: Graphics?, p1: JComponent?, p2: Rectangle?) {} + + override fun createDecreaseButton(p0: Int): JButton { + return object : JButton() { + override fun getPreferredSize(): Dimension { + return Dimension() + } + } + } + + override fun createIncreaseButton(p0: Int): JButton { + return object : JButton() { + override fun getPreferredSize(): Dimension { + return Dimension() + } + } + } + } + + getVerticalScrollBar().background = Color(49,45,37) + } + + private fun removeComments(node: Node) { + var i = 0 + while (i < node.childNodeSize()) { + val child = node.childNode(i) + if (child.nodeName() == "#comment") child.remove() + else { + removeComments(child) + i++ + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/MainWindow.kt b/src/main/kotlin/MainWindow.kt new file mode 100644 index 0000000..076e7a9 --- /dev/null +++ b/src/main/kotlin/MainWindow.kt @@ -0,0 +1,153 @@ +import java.awt.Desktop +import java.awt.Dimension +import java.awt.Image +import java.io.File +import java.net.URI +import javax.imageio.ImageIO +import javax.swing.* +import kotlin.system.exitProcess + + +object MainWindow : JFrame("2009scape Launcher") { + + val loadingLabel = JLabel("Press Launch to play 2009scape!") + val loadingBar = JLabel(ImageIcon(javaClass.getResource("/loadingBar.png"))) + val playButton = ImgButton("/playButton.png","/playButtonDisabled.png", false) + + + init { + defaultCloseOperation = EXIT_ON_CLOSE + preferredSize = Dimension(1366,768) + size = Dimension(800,500) + val tileBG = BackgroundPanel(ImageIO.read(javaClass.getResource("/tile.png"))) + contentPane = tileBG + layout = null + + constructTopBar() + val updatePane = LatestUpdatePane("https://2009scape.org/services/m=news/archives/2021-07-12.html") + updatePane.placeAt(4, 45, MainWindow.width - 8, MainWindow.height - 85) + add(updatePane) + addPlayButton() + + setLocationRelativeTo(null) + isUndecorated = true + isVisible = true + } + + private fun constructTopBar(){ + val panel = BackgroundPanel(ImageIO.read(javaClass.getResource("/topBar.png"))) + panel.placeAt(0,0,MainWindow.width, 40) + addCloseButton(panel) + addNewsButton(panel) + addBugReportButton(panel) + addHighscoreButton(panel) + addDiscordButton(panel) + addLogo(panel) + add(panel) + } + + private fun addPlayButton(){ + val loadingFrame = JLabel(ImageIcon(javaClass.getResource("/loadingFrame.png"))) + playButton.isEnabled = true + playButton.onClick { + if(Updater.checkUpdate()) Updater.runUpdate() + else Runtime.getRuntime().exec("java -jar " + Settings.SAVE_DIR + File.separator + Settings.SAVE_NAME, null, File(System.getProperty("user.home"))).also { exitProcess(0) } + } + loadingFrame.placeAt(96,MainWindow.height - 35, 704, 35) + loadingBar.placeAt(103, MainWindow.height - 33, 695, 31) + playButton.placeAt(0,MainWindow.height - 35,100,35) + loadingLabel.placeAt(300, MainWindow.height - 24, 300, 15) + add(loadingLabel) + add(loadingBar) + add(loadingFrame) + add(playButton) + } + + private fun addNewsButton(panel: JPanel){ + val label = BackgroundLabel("/messageBox.png", "Latest
Update") + label.placeAt(0, 40, 90, 56) + add(label) + + val button = ImgButton("/news.png") + button.onMouseEnter { label.isVisible = true } + button.onMouseExit { label.isVisible = false } + button.onClick { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Desktop.getDesktop().browse(URI("https://2009scape.org/services/m=news/archives/2021-07-12.html")); + } + } + button.placeAt(5,4,35,35) + panel.add(button) + } + + private fun addBugReportButton(panel: JPanel){ + val label = BackgroundLabel("/messageBox.png", "Report
Bug") + label.placeAt(25, 40, 90, 56) + add(label) + + val button = ImgButton("/reportBug.png") + button.onMouseEnter { label.isVisible = true } + button.onMouseExit { label.isVisible = false } + button.onClick { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Desktop.getDesktop().browse(URI("https://gitlab.com/2009scape/2009scape/-/issues")); + } + } + button.placeAt(50, 4, 35, 35) + panel.add(button) + } + + private fun addHighscoreButton(panel: JPanel){ + val label = BackgroundLabel("/messageBox.png", "Leader
Boards") + label.placeAt(70, 40, 90, 56) + add(label) + + val button = ImgButton("/highScores.png") + button.onMouseEnter { label.isVisible = true } + button.onMouseExit { label.isVisible = false } + button.onClick { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Desktop.getDesktop().browse(URI("https://2009scape.org/services/m=hiscore/hiscores.html?world=2")); + } + } + button.placeAt(90, 2, 38, 38) + panel.add(button) + } + + private fun addDiscordButton(panel: JPanel){ + val label = BackgroundLabel("/messageBox.png", "Join
Discord") + label.placeAt(110, 40, 90, 56) + add(label) + + val button = ImgButton("/joinDiscord.png") + button.onMouseEnter { label.isVisible = true } + button.onMouseExit { label.isVisible = false } + button.onClick { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Desktop.getDesktop().browse(URI("https://discord.gg/YY7WSttN7H")); + } + } + button.placeAt(135, 4, 35, 35) + panel.add(button) + } + + private fun addCloseButton(panel: BackgroundPanel){ + val button = ImgButton("/close_hi.png","/close_dark.png") + button.onClick { exitProcess(0) } + button.placeAt(panel.width - 35, 7, 25, 25) + button.isOpaque = false + panel.add(button) + } + + private fun addLogo(panel: JPanel){ + val logo = JLabel(ImageIcon(javaClass.getResource("/logo.png"))) + logo.icon = ImageIcon((logo.icon as ImageIcon).image.getScaledInstance(179,40, Image.SCALE_SMOOTH)) + logo.placeAt(311, 0, 179, 40) + panel.add(logo) + } + + @JvmStatic + fun main(args: Array) { + + } +} \ No newline at end of file diff --git a/src/main/kotlin/Settings.kt b/src/main/kotlin/Settings.kt new file mode 100644 index 0000000..4633f68 --- /dev/null +++ b/src/main/kotlin/Settings.kt @@ -0,0 +1,5 @@ +object Settings { + val SAVE_DIR = System.getProperty("user.home") + val SAVE_NAME = "2009scape.jar" + val DOWNLOAD_URL = "http://play.2009scape.org/2009scape.jar" +} \ No newline at end of file diff --git a/src/main/kotlin/Updater.kt b/src/main/kotlin/Updater.kt new file mode 100644 index 0000000..f036681 --- /dev/null +++ b/src/main/kotlin/Updater.kt @@ -0,0 +1,86 @@ +import java.awt.Image +import java.io.File +import java.io.RandomAccessFile +import java.net.URL +import java.util.concurrent.Executors +import javax.swing.ImageIcon + +object Updater { + + private var status = UpdateStatus.DOWNLOADING + + fun checkUpdate(): Boolean{ + val localMD5 = Checksum.getLocalChecksum(Settings.SAVE_DIR + File.separator + Settings.SAVE_NAME) + val remoteMD5 = Checksum.getRemoteChecksum(Settings.DOWNLOAD_URL) + + return localMD5 != remoteMD5 + } + + fun runUpdate(){ + val t = Thread() { + var oldText = MainWindow.loadingLabel.text + MainWindow.loadingLabel.text = "Updating client..." + MainWindow.playButton.isEnabled = false + var downloaded = 0 + var lastBarUpdate = 0 + + val connection = URL(Settings.DOWNLOAD_URL).openConnection() + connection.connect() + + val length = connection.contentLength + + if (!File(Settings.SAVE_DIR).exists()) { + File(Settings.SAVE_DIR).mkdir() + } + if (File(Settings.SAVE_DIR + File.separator + Settings.SAVE_NAME).exists()) { + File(Settings.SAVE_DIR + File.separator + Settings.SAVE_NAME).delete() + } + + File(Settings.SAVE_DIR + File.separator + Settings.SAVE_NAME).createNewFile() + + val file = RandomAccessFile(Settings.SAVE_DIR + File.separator + Settings.SAVE_NAME, "rw") + + val stream = connection.getInputStream() + + while(status == UpdateStatus.DOWNLOADING){ + val buffer = if(length - downloaded > 1024){ + ByteArray(1024) + } else { + ByteArray(length - downloaded) + } + + val read = stream.read(buffer) + + if(read == -1) break + + val progress = ((downloaded / length.toFloat()) * 100).toInt() + val barLength = 1 + ((progress / 100.0) * 695.0).toInt() + + MainWindow.loadingLabel.text = "Updating client... $progress%" + + if(barLength - lastBarUpdate > 5){ + MainWindow.loadingBar.icon = ImageIcon((MainWindow.loadingBar.icon as ImageIcon).image.getScaledInstance(barLength, 31, Image.SCALE_FAST)) + MainWindow.loadingBar.placeAt(103, MainWindow.height - 33, barLength, 31) + lastBarUpdate = barLength + } + + file.write(buffer, 0, read) + downloaded += read + + if(downloaded >= length){ + MainWindow.loadingLabel.text = oldText + MainWindow.playButton.isEnabled = true + file.close() + status = UpdateStatus.COMPLETE + } + } + MainWindow.loadingBar.icon = ImageIcon((MainWindow.loadingBar.icon as ImageIcon).image.getScaledInstance(695, 31, Image.SCALE_FAST)) + MainWindow.loadingBar.placeAt(103, MainWindow.height - 33, 695, 31) + }.start() + } + + internal enum class UpdateStatus{ + DOWNLOADING, + COMPLETE + } +} \ No newline at end of file diff --git a/src/main/resources/close_dark.png b/src/main/resources/close_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..470ce7482c84f0d2bff7a751ed47527bffbb6f38 GIT binary patch literal 295 zcmV+?0oeYDP)-85m(=Sq5r50PwaC@qS36b&P4AgH@me1IVFVSi?z7pacWJ(+p$2<^naa z7SmxM2P2l+{48M4PPT936I@&b7ssv+E;>3msfeq8;o#>)uI0i_nxsi-;g;9D+(Vnb z_p0xGYJF7&SJ02!>o9S&oR4fSFz99Cyf*f@8vm68rjH)@TTmoE&xL*0vrcfQM>jmS zjS!zUCJ5$!4+%+ literal 0 HcmV?d00001 diff --git a/src/main/resources/highScores.png b/src/main/resources/highScores.png new file mode 100644 index 0000000000000000000000000000000000000000..13333fe0a360f70e4fca2173a911f1feb2991c27 GIT binary patch literal 382 zcmV-^0fGLBP)>TX>(J@sVAR{C5pBT%FR#l@6_oDb^tLRAQ%F;3;|gHvJ4%AET^gi2>Biv4;lv;Ragy-17>bn47QwV4nR)H z*s>bU9RN#&Aj3|ENBrMnZwtpDF<5-Va8KVv>N@~r5VFM}3~~%U2dHM~P|pD%%h2&c zU0s|G09j5|2VnF4BxOy!4v>tHr;YDQ=j*c-31~~xI!ouIs!EgXAFwrF>%%!xzqrHw% cFba?X0J^HrA!GxrxBvhE07*qoM6N<$g4F4fi2wiq literal 0 HcmV?d00001 diff --git a/src/main/resources/joinDiscord.png b/src/main/resources/joinDiscord.png new file mode 100644 index 0000000000000000000000000000000000000000..7db79ea3f582e3924d4193facc546ecf2b9574bf GIT binary patch literal 435 zcmV;k0ZjghP)(?<{WT%7)%pr*fGT#Q zt6pst2;@{k7=T#C?M^&C^ir|-Tk;xp_3rHu04C#cV*uO+p$p{z6q5G4E56oiKR_~> zIW-UpfSm7(xlRY@LJT3IlZf5-=Q$^ftAtor3&kT>+pf)xXqgtmwqd93%X6>+$-ll&?=mnjwq!ax2Y5O=D-;yvr)B1( zGB9XNtet4!Lp``jxUvo>x*9SY~-@mhccaPC&?-`TT*)kVOZu_V{ zN>bac#TGBh;E*=WP~FqBL?-_GhmT+Nj%~J@|GW6hD$8z0yNMOkB$xT_akSZ+ zDLv-_)N_wU~NX|ix!kOm)1oXqoN7LIpJy|W(I$Xok8X8B;x9A0%g zekHT<{3X|;qP}o&$u>JK|7`6X zJBG|xT9wQ)GE9qEPsP3e@b2BWd;e@Nzj@Ct_Nb^SXYXwRV6?C$dAqwX{0G4WdzViJ zif|TqL>4nJa0`PlBg3pY5H=O_NVOp!Wya>>fJy&hJ~Ikjv*Dd-d-~lWH8`h z*ccT5HHiJkd23^X8ylYzkim!Lp``jxUvo>x*9SY~-@mhccaPC&?-`TT*)kVOZu_V{ zN>bac#TGBh;E*=WP~FqBL?-_GhmT+Nj%~J@|GW6hD$8z0yNMOkB$xT_akSZ+ zDLv-_)N_wU~NX|ix!kOm)1oXqoN7LIpJy|W(I$Xok8X8B;x9A0%g zekHT<{3X|;qP}o&$u>JK|7`6X zJBG|xT9wQ)GE9qEPsP3e@b2BWd;e@Nzj@Ct_Nb^SXYXwRV6?C$dAqwX{0G4WdzViJ zif|TqL>4nJa0`PlBg3pY5H=O_NVOp!Wt|pezSdnLN`2J978H@y}hweu)#pU zB~b6_lAae+x|i|X;?y$c&`P);ygdBx&RL7sGczzaU9oF1U|t<8 literal 0 HcmV?d00001 diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2b3e05477fc4d5e0169a8a6ba913f4fed99b7ee6 GIT binary patch literal 15809 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 CjL!oA literal 0 HcmV?d00001 diff --git a/src/main/resources/messageBox.png b/src/main/resources/messageBox.png new file mode 100644 index 0000000000000000000000000000000000000000..17e6869be05ab34d7842b52e4e5d4686b1f301fe GIT binary patch literal 1040 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 B|9AiZ literal 0 HcmV?d00001 diff --git a/src/main/resources/playButtonDisabled.png b/src/main/resources/playButtonDisabled.png new file mode 100644 index 0000000000000000000000000000000000000000..f50b9609dfb25d8e3da6aa02d22c616b03930907 GIT binary patch literal 10737 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