diff --git a/build.gradle b/build.gradle index 1348b03..3eec34d 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ repositories { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib" implementation 'org.jsoup:jsoup:1.14.1' + implementation files("libs/json-simple-1.1.1.jar") } jar { diff --git a/src/main/kotlin/Checkbox.kt b/src/main/kotlin/Checkbox.kt new file mode 100644 index 0000000..ef7c47f --- /dev/null +++ b/src/main/kotlin/Checkbox.kt @@ -0,0 +1,19 @@ +class Checkbox : ImgButton("/toggleOn.png","toggleOff.png", false) { + + var isToggled = false + set(value) { + field = value + isEnabled = value + } + + init { + isEnabled = false + + onClick { + isToggled = !isToggled + } + + onMouseEnter { } + onMouseExit { } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ImgButton.kt b/src/main/kotlin/ImgButton.kt index c049094..d0ea171 100644 --- a/src/main/kotlin/ImgButton.kt +++ b/src/main/kotlin/ImgButton.kt @@ -5,7 +5,7 @@ import javax.swing.Icon import javax.swing.ImageIcon import javax.swing.JLabel -class ImgButton(enabledURL: String, disabledURL: String = enabledURL, val autoHandleMouse: Boolean = true) : JLabel() { +open class ImgButton(enabledURL: String, disabledURL: String = enabledURL, val autoHandleMouse: Boolean = true) : JLabel() { private var hoverMethod: (MouseEvent) -> Unit = {} private var mouseLeaveMethod: (MouseEvent) -> Unit = {} diff --git a/src/main/kotlin/MainWindow.kt b/src/main/kotlin/MainWindow.kt index 48b706f..2f02fcd 100644 --- a/src/main/kotlin/MainWindow.kt +++ b/src/main/kotlin/MainWindow.kt @@ -1,4 +1,5 @@ import com.sun.java.accessibility.util.AWTEventMonitor +import settingseditor.SettingsWindow import java.awt.* import java.awt.event.MouseAdapter import java.awt.event.MouseEvent @@ -74,6 +75,7 @@ object MainWindow : JFrame("2009scape Launcher") { addBugReportButton(panel) addHighscoreButton(panel) addDiscordButton(panel) + addSettingsbutton(panel) addLogo(panel) add(panel) } @@ -185,6 +187,21 @@ object MainWindow : JFrame("2009scape Launcher") { panel.add(button) } + private fun addSettingsbutton(panel: BackgroundPanel){ + val button = ImgButton("/settings.png") + val label = BackgroundLabel("/messageBox.png", "Client
Settings") + add(label) + + label.placeAt(panel.width - 100, 40, 90, 56) + button.onMouseEnter { label.isVisible = true } + button.onMouseExit { label.isVisible = false } + button.onClick { + SettingsWindow.open() + } + button.placeAt(panel.width - 75, 6, 30, 30) + panel.add(button) + } + private fun addCloseButton(panel: BackgroundPanel){ val button = ImgButton("/close_hi.png","/close_dark.png") button.onClick { exitProcess(0) } diff --git a/src/main/kotlin/settingseditor/Json.kt b/src/main/kotlin/settingseditor/Json.kt new file mode 100644 index 0000000..82837f2 --- /dev/null +++ b/src/main/kotlin/settingseditor/Json.kt @@ -0,0 +1,112 @@ +package settingseditor + +import org.json.simple.JSONObject +import org.json.simple.parser.JSONParser +import java.io.File +import java.io.FileReader +import java.io.FileWriter + +object Json { + + val HOME = System.getProperty("user.home") + val CONF = HOME + File.separator + "config.json" + var data: JSONObject = JSONObject() + + fun save(){ + val customization = data["customization"] as JSONObject + val xpDrops = customization["xpdrops"] as JSONObject + val slayer = customization["slayer"] as JSONObject + val rcm = customization["right_click_menu"] as JSONObject + val styles = rcm["styles"] as JSONObject + + val background = rcm["background"] as JSONObject + val title_bar = rcm["title_bar"] as JSONObject + val border = rcm["border"] as JSONObject + val debug = data["debug"] as JSONObject + + background["color"] = SettingsWindow.bgColorField.text + background["opacity"] = SettingsWindow.bgOpacityField.text + title_bar["color"] = SettingsWindow.titleColorField.text + title_bar["opacity"] = SettingsWindow.titleOpacityField.text + title_bar["font_color"] = SettingsWindow.titleFontColor.text + border["color"] = SettingsWindow.borderColor.text + border["opacity"] = SettingsWindow.borderOpacity.text + styles["rs3border"] = SettingsWindow.rs3Border.isToggled + debug["item_debug"] = SettingsWindow.itemDebugCheckbox.isToggled + debug["object_debug"] = SettingsWindow.objectDebugCheckbox.isToggled + debug["npc_debug"] = SettingsWindow.npcDebugCheckbox.isToggled + xpDrops["enabled"] = SettingsWindow.xpDropsEnabled.isToggled + xpDrops["drop_mode"] = SettingsWindow.xpDropMode.selectedIndex + xpDrops["track_mode"] = SettingsWindow.xpTrackMode.selectedIndex + slayer["enabled"] = SettingsWindow.slayerEnabled.isToggled + slayer["color"] = SettingsWindow.slayerColor.text + slayer["opacity"] = SettingsWindow.slayerOpacity.text + customization["login_theme"] = SettingsWindow.loginTheme.text + + FileWriter(CONF).use { writer -> + writer.write(data.toJSONString()) + writer.flush() + } + } + + fun parse(){ + try { + if(!File(CONF).exists()){ + FileReader(javaClass.getResource("/config.json")!!.file).use { reader -> + val writer = FileWriter(CONF) + reader.copyTo(writer, 1024) + writer.flush() + writer.close() + } + } + data = FileReader(CONF).use { reader -> + val parser = JSONParser() + parser.parse(reader) as JSONObject + } + + val customization = data["customization"] as JSONObject + val xpDrops = customization["xpdrops"] as JSONObject + val slayer = customization["slayer"] as JSONObject + val rcm = customization["right_click_menu"] as JSONObject + val styles = rcm["styles"] as JSONObject + + val background = rcm["background"] as JSONObject + val title_bar = rcm["title_bar"] as JSONObject + val border = rcm["border"] as JSONObject + val debug = data["debug"] as JSONObject + + SettingsWindow.itemDebugCheckbox.isToggled = debug["item_debug"] as Boolean + SettingsWindow.objectDebugCheckbox.isToggled = debug["object_debug"] as Boolean + SettingsWindow.npcDebugCheckbox.isToggled = debug["npc_debug"] as Boolean + + SettingsWindow.rs3Border.isToggled = styles["rs3border"] as Boolean + SettingsWindow.bgColorField.text = background["color"].toString() + SettingsWindow.bgOpacityField.text = background["opacity"].toString() + SettingsWindow.titleColorField.text = title_bar["color"].toString() + SettingsWindow.titleOpacityField.text = title_bar["opacity"].toString() + SettingsWindow.titleFontColor.text = title_bar["font_color"].toString() + SettingsWindow.borderColor.text = border["color"].toString() + SettingsWindow.borderOpacity.text = border["opacity"].toString() + + SettingsWindow.xpDropsEnabled.isToggled = xpDrops.getOrDefault("enabled",true) as Boolean + SettingsWindow.xpDropMode.selectedIndex = xpDrops.getOrDefault("drop_mode",0).toString().toInt() + SettingsWindow.xpTrackMode.selectedIndex = xpDrops.getOrDefault("track_mode",0).toString().toInt() + + SettingsWindow.slayerEnabled.isToggled = slayer.getOrDefault("enabled",true) as Boolean + 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() + } catch (e: Exception) { + println("error parsing settings, replacing with defaults...") + e.printStackTrace() + File(CONF).delete() + FileReader(javaClass.getResource("/config.json")!!.file).use { reader -> + val writer = FileWriter(CONF) + reader.copyTo(writer, 1024) + writer.flush() + writer.close() + } + parse() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/settingseditor/SettingsWindow.kt b/src/main/kotlin/settingseditor/SettingsWindow.kt new file mode 100644 index 0000000..185724e --- /dev/null +++ b/src/main/kotlin/settingseditor/SettingsWindow.kt @@ -0,0 +1,303 @@ +package settingseditor + +import BackgroundLabel +import BackgroundPanel +import Checkbox +import ImgButton +import placeAt +import java.awt.BorderLayout +import java.awt.Color +import java.awt.Dimension +import java.awt.LayoutManager +import javax.imageio.ImageIO +import javax.swing.* + +object SettingsWindow : JFrame("Client Settings") { + + val xpDropModeOptions = arrayOf("instant","incremental") + val xpTrackModeOptions = arrayOf("total xp","recent skill") + + var tabs = ArrayList() + var buttons = ArrayList() + var tabNotes = ArrayList() + var activeTab = 0 + var buttonSpacer = 0 + val itemDebugCheckbox = Checkbox() + val objectDebugCheckbox = Checkbox() + val npcDebugCheckbox = Checkbox() + val rs3Border = Checkbox() + val bgColorField = JTextField() + val bgOpacityField = JTextField() + val titleColorField = JTextField() + val titleOpacityField = JTextField() + val titleFontColor = JTextField() + val borderColor = JTextField() + val borderOpacity = JTextField() + val loginTheme = JTextField() + val xpDropsEnabled = Checkbox() + val xpDropMode = JComboBox(xpDropModeOptions) + val xpTrackMode = JComboBox(xpTrackModeOptions) + val slayerColor = JTextField() + val slayerOpacity = JTextField() + val slayerEnabled = Checkbox() + + init { + isUndecorated = true + isVisible = false + isResizable = false + defaultCloseOperation = HIDE_ON_CLOSE + preferredSize = Dimension(400,300) + size = Dimension(400,300) + val tileBG = BackgroundPanel(ImageIO.read(javaClass.getResource("/topBar.png"))) + contentPane = tileBG + layout = null + setLocationRelativeTo(null) + + addDebugTab() + addRightClickTab() + addMiscTab() + + val saveButton = ImgButton("/save_hi.png","/save_lo.png") + saveButton.onClick { + Json.save() + isVisible = false + } + saveButton.placeAt(width - 30, height - 30, 30, 30) + add(saveButton) + } + + fun addMiscTab() { + val pane = getThemedPanel() + 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()) + val slayerTogglePanel = getThemedPanel(BorderLayout()) + val slayerColorPanel = getThemedPanel(BorderLayout()) + val slayerOpacityPanel = getThemedPanel(BorderLayout()) + val loginThemePanel = getThemedPanel(BorderLayout()) + val xpToggleLabel = getLabel("XP Drops Enabled") + val xpDropLabel = getLabel("XP Drop Mode") + val xpTrackLabel = getLabel("XP Track Mode") + val slayerToggleLabel = getLabel("Slayer Tracker Enabled") + val slayerColorLabel = getLabel("Slayer Tracker Color") + val slayerOpacityLabel = getLabel("Slayer Tracker Opacity") + val loginThemeLabel = getLabel("Login Theme") + + for(field in arrayOf(loginTheme, xpDropMode, xpTrackMode, slayerColor, slayerOpacity)) + { + field.size = Dimension(200,10) + field.minimumSize = Dimension(200,10) + field.maximumSize = Dimension(200,10) + field.preferredSize = Dimension(200,10) + } + + loginThemePanel.add(loginThemeLabel, BorderLayout.WEST) + loginThemePanel.add(loginTheme, BorderLayout.EAST) + pane.add(loginThemePanel) + pane.add(getSeparator()) + + xpTogglePanel.add(xpToggleLabel, BorderLayout.WEST) + xpTogglePanel.add(xpDropsEnabled, BorderLayout.EAST) + pane.add(xpTogglePanel) + + xpDropPanel.add(xpDropLabel, BorderLayout.WEST) + xpDropPanel.add(xpDropMode, BorderLayout.EAST) + pane.add(xpDropPanel) + + xpTrackPanel.add(xpTrackLabel, BorderLayout.WEST) + xpTrackPanel.add(xpTrackMode, BorderLayout.EAST) + pane.add(xpTrackPanel) + pane.add(getSeparator()) + + slayerTogglePanel.add(slayerToggleLabel, BorderLayout.WEST) + slayerTogglePanel.add(slayerEnabled, BorderLayout.EAST) + pane.add(slayerTogglePanel) + + slayerColorPanel.add(slayerColorLabel, BorderLayout.WEST) + slayerColorPanel.add(slayerColor, BorderLayout.EAST) + pane.add(slayerColorPanel) + + slayerOpacityPanel.add(slayerOpacityLabel, BorderLayout.WEST) + slayerOpacityPanel.add(slayerOpacity, BorderLayout.EAST) + pane.add(slayerOpacityPanel) + + addTab(pane, button, getLabel("Theme: all lowercase")) + } + + 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 itemDebug = getThemedPanel(BorderLayout()) + val itemDebugLabel = getLabel("Item IDs Visible") + itemDebug.add(itemDebugLabel, BorderLayout.WEST) + itemDebug.add(itemDebugCheckbox, BorderLayout.EAST) + pane.add(itemDebug) + pane.add(getSeparator()) + + val objectDebug = getThemedPanel(BorderLayout()) + val objectDebugLabel = getLabel("Object IDs Visible") + objectDebug.add(objectDebugLabel, BorderLayout.WEST) + objectDebug.add(objectDebugCheckbox, BorderLayout.EAST) + pane.add(objectDebug) + pane.add(getSeparator()) + + val npcDebug = getThemedPanel(BorderLayout()) + val npcDebugLabel = getLabel("NPC IDs Visible") + npcDebug.add(npcDebugLabel, BorderLayout.WEST) + npcDebug.add(npcDebugCheckbox, BorderLayout.EAST) + pane.add(npcDebug) + + addTab(pane, button) + } + + fun addRightClickTab() { + val pane = getThemedPanel() + 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()) + val titleColorPanel = getThemedPanel(BorderLayout()) + val titleOpacityPanel = getThemedPanel(BorderLayout()) + val titleFontPanel = getThemedPanel(BorderLayout()) + val borderColorPanel = getThemedPanel(BorderLayout()) + val borderOpacityPanel = getThemedPanel(BorderLayout()) + val rs3BorderLabel = getLabel("Use RS3-Style Menu Border") + val bgColorLabel = getLabel("Background Color") + val bgOpacityLabel = getLabel("Background Opacity") + val titleColorLabel = getLabel("Title Bar Color") + val titleOpacityLabel = getLabel("Title Bar Opacity") + val titleFontLabel = getLabel("Title Bar Font Color") + val borderColorLabel = getLabel("Border Color") + val borderOpacityLabel = getLabel("Border Opacity") + + for(field in arrayOf(bgColorField, bgOpacityField, titleColorField, titleOpacityField, titleFontColor, borderColor, borderOpacity)) + { + field.size = Dimension(100,10) + field.minimumSize = Dimension(100,10) + field.maximumSize = Dimension(100,10) + field.preferredSize = Dimension(100,10) + } + + rs3BorderPanel.add(rs3BorderLabel, BorderLayout.WEST) + rs3BorderPanel.add(rs3Border, BorderLayout.EAST) + pane.add(rs3BorderPanel) + pane.add(getSeparator()) + + bgColorPanel.add(bgColorLabel, BorderLayout.WEST) + bgColorPanel.add(bgColorField, BorderLayout.EAST) + pane.add(bgColorPanel) + + bgOpacityPanel.add(bgOpacityLabel, BorderLayout.WEST) + bgOpacityPanel.add(bgOpacityField, BorderLayout.EAST) + pane.add(bgOpacityPanel) + pane.add(getSeparator()) + + titleColorPanel.add(titleColorLabel, BorderLayout.WEST) + titleColorPanel.add(titleColorField, BorderLayout.EAST) + pane.add(titleColorPanel) + + titleFontPanel.add(titleFontLabel, BorderLayout.WEST) + titleFontPanel.add(titleFontColor, BorderLayout.EAST) + pane.add(titleFontPanel) + + titleOpacityPanel.add(titleOpacityLabel, BorderLayout.WEST) + titleOpacityPanel.add(titleOpacityField, BorderLayout.EAST) + pane.add(titleOpacityPanel) + pane.add(getSeparator()) + + borderColorPanel.add(borderColorLabel, BorderLayout.WEST) + borderColorPanel.add(borderColor, BorderLayout.EAST) + pane.add(borderColorPanel) + + borderOpacityPanel.add(borderOpacityLabel, BorderLayout.WEST) + borderOpacityPanel.add(borderOpacity, BorderLayout.EAST) + pane.add(borderOpacityPanel) + + addTab(pane, button, getLabel("Color: HEX || Opacity: 0-255")) + } + + fun addTab(content: JPanel, button: ImgButton, tabNote: JLabel = getLabel("")){ + content.placeAt(0,30,width,height - 60) + add(content) + tabs.add(content) + content.isVisible = false + button.placeAt(buttonSpacer, 0, 30, 30) + button.onClick { activeTab = buttons.indexOf(button); updateVisibleTab() } + buttonSpacer += 35 + add(button) + button.isEnabled = false + buttons.add(button) + tabNote.placeAt(5, 275, width / 2, 20) + tabNote.isVisible = true + add(tabNote) + tabNotes.add(tabNote) + } + + fun open(){ + activeTab = 0 + updateVisibleTab() + Json.parse() + isVisible = true + } + + fun updateVisibleTab(){ + for(i in 0 until tabs.size){ + if(i != activeTab){ + tabs[i].isVisible = false + tabNotes[i].isVisible = false + } + else { + tabs[i].isVisible = true + tabNotes[i].isVisible = true + } + } + repaint() + } + + fun getThemedPanel(layout: LayoutManager? = null): JPanel{ + val panel = if(layout == null) JPanel() else JPanel(layout) + panel.background = Color(102,90,69) + 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 + } +} \ No newline at end of file diff --git a/src/main/resources/config.json b/src/main/resources/config.json new file mode 100644 index 0000000..19c0684 --- /dev/null +++ b/src/main/resources/config.json @@ -0,0 +1,61 @@ +{ + "ip_address": "play.2009scape.org", + "ip_management" : "play.2009scape.org", + "server_port": 43594, + "wl_port": 5555, + "js5_port": 43593, + "world": 1, + + "customization": { + "login_theme": "scape main", + + "right_click_menu": { + "background": { + "color": "#5D5447", + "opacity": "255" + }, + "title_bar": { + "color": "#000000", + "opacity": "255", + "font_color": "#FFFFFF" + }, + "border": { + "color": "#FFFFFF", + "opacity": "255" + }, + "styles": { + "Presets provide default customizations.": "rs3, classic, or custom. custom allows you to define your own values above. Classic is standard 2009.", + "presets": "custom", + "rs3border": false + } + }, + "xpdrops": { + "enabled": true, + "drop_mode": 0, + "track_mode": 0 + }, + "slayer": { + "enabled": true, + "color": "#635a38", + "opacity": "180" + }, + "rendering_options": { + "technical": { + "render_distance_increase": true + }, + "skybox": { + "skybox_color" : "Coming in a future update..." + } + } + }, + + "debug": { + "item_debug": false, + "object_debug": false, + "npc_debug": false, + "hd_login_region_debug": false, + "hd_login_region_debug_verbose": false, + "cache_debug": false, + "world_map_debug": false + } +} diff --git a/src/main/resources/misc.png b/src/main/resources/misc.png new file mode 100644 index 0000000..92ffdd0 Binary files /dev/null and b/src/main/resources/misc.png differ diff --git a/src/main/resources/rightClick.png b/src/main/resources/rightClick.png new file mode 100644 index 0000000..8020708 Binary files /dev/null and b/src/main/resources/rightClick.png differ diff --git a/src/main/resources/save_hi.png b/src/main/resources/save_hi.png new file mode 100644 index 0000000..4c42bc1 Binary files /dev/null and b/src/main/resources/save_hi.png differ diff --git a/src/main/resources/save_lo.png b/src/main/resources/save_lo.png new file mode 100644 index 0000000..c3587e9 Binary files /dev/null and b/src/main/resources/save_lo.png differ diff --git a/src/main/resources/settings.png b/src/main/resources/settings.png new file mode 100644 index 0000000..5b9f947 Binary files /dev/null and b/src/main/resources/settings.png differ diff --git a/src/main/resources/toggleOff.png b/src/main/resources/toggleOff.png new file mode 100644 index 0000000..51158f5 Binary files /dev/null and b/src/main/resources/toggleOff.png differ diff --git a/src/main/resources/toggleOn.png b/src/main/resources/toggleOn.png new file mode 100644 index 0000000..5042fd4 Binary files /dev/null and b/src/main/resources/toggleOn.png differ