diff --git a/src/main/kotlin/NPCSpawnPanel.kt b/src/main/kotlin/NPCSpawnPanel.kt new file mode 100644 index 0000000..fb9ca72 --- /dev/null +++ b/src/main/kotlin/NPCSpawnPanel.kt @@ -0,0 +1,102 @@ +import cacheops.cache.definition.decoder.NPC +import misc.ImgButton +import java.awt.Color +import java.awt.Dimension +import java.awt.FlowLayout +import java.awt.event.MouseAdapter +import java.awt.event.MouseEvent +import javax.swing.BoxLayout +import javax.swing.JLabel +import javax.swing.JPanel +import javax.swing.border.MatteBorder + +class NPCSpawnPanel : JPanel() { + val rowBorder = MatteBorder(1, 1, 1, 1, Color.WHITE) + init { + layout = BoxLayout(this, BoxLayout.PAGE_AXIS) + + add(NPCSpawnerPanel()) + + Rs2MapEditor.npcs.forEach { + val row = NPCRow(it, this) + row.border = rowBorder + Rs2MapEditor.npcRows.add(row) + add(row) + } + } + + fun redrawRows() { + Rs2MapEditor.npcRows.forEach { + remove(it) + } + Rs2MapEditor.npcRows.clear() + Rs2MapEditor.npcs.forEach { + val row = NPCRow(it, this) + row.border = rowBorder + Rs2MapEditor.npcRows.add(row) + add(row) + } + repaint() + } + + class NPCSpawnerPanel : JPanel() { + init { + val addButton = ImgButton("/add_hi.png", "/add_dark.png") + addButton.onClick { + Rs2MapEditor.state = EditorState.ADD_NPC + } + Rs2MapEditor.npcIdInput.minimumSize = Dimension(200, 25) + Rs2MapEditor.npcIdInput.maximumSize = Dimension(200, 25) + Rs2MapEditor.npcIdInput.preferredSize = Dimension(200, 25) + minimumSize = Dimension(300, 60) + preferredSize = Dimension(300, 60) + maximumSize = Dimension(300, 60) + + layout = FlowLayout() + add(Rs2MapEditor.npcIdInput) + add(addButton) + border = MatteBorder(1, 1, 1, 1, Color.GREEN) + } + } + + class NPCRow(val npc: NPC, val parent: JPanel) : JPanel(){ + init { + layout = FlowLayout() + add(JLabel("${npc.definition.name} (LVL ${npc.definition.combat}) [${npc.x} | ${npc.y} | ${npc.plane}]")) + val deleteButton = ImgButton("/trash_hi.png", "/trash_dark.png") + add(deleteButton) + minimumSize = Dimension(300, 40) + preferredSize = Dimension(300, 40) + maximumSize = Dimension(300, 40) + deleteButton.onClick { + Rs2MapEditor.npcs.remove(npc) + parent.remove(this) + parent.repaint() + Rs2MapEditor.npcRows.remove(this) + if(Rs2MapEditor.npcs.filter { it.x == npc.x && it.y == npc.y }.isEmpty()){ + Rs2MapEditor.componentPointMap.filter { it.key.x == npc.x && it.key.y == npc.y }.forEach { (_,cell) -> + cell.components.forEach { c -> + if(c is JLabel) cell.remove(c) + } + cell.repaint() + Rs2MapEditor.npcsUpdated = true + } + } + } + + addMouseListener(object : MouseAdapter(){ + val border = MatteBorder(1, 1, 1, 1, Color.YELLOW) + val defaultBorder = MatteBorder(1, 1, 1, 1, Color.GRAY) + override fun mouseEntered(e: MouseEvent?) { + super.mouseEntered(e) + Rs2MapEditor.componentPointMap.filter { it.key.x == npc.x && it.key.y == npc.y }.forEach { it.value.border = border } + } + + override fun mouseExited(e: MouseEvent?) { + super.mouseExited(e) + Rs2MapEditor.componentPointMap.filter { it.key.x == npc.x && it.key.y == npc.y }.forEach{ it.value.border = defaultBorder } + } + }) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/Rs2MapEditor.kt b/src/main/kotlin/Rs2MapEditor.kt index c15a672..9e47c50 100644 --- a/src/main/kotlin/Rs2MapEditor.kt +++ b/src/main/kotlin/Rs2MapEditor.kt @@ -8,6 +8,8 @@ import com.displee.cache.CacheLibrary import com.formdev.flatlaf.FlatDarculaLaf import const.Image.RED_DOT import const.Image.YELLOW_DOT +import misc.CustomEventQueue +import misc.ImgButton import java.awt.* import java.awt.event.KeyEvent import java.awt.event.MouseAdapter @@ -18,13 +20,16 @@ import kotlin.system.exitProcess object Rs2MapEditor { - val library = CacheLibrary.create("K:\\RSPSDev\\2-009Scape-578\\Server\\data\\cache") + val library = CacheLibrary.create("/home/ceikry/IdeaProjects/rs09-remake/Server/data/cache/") var region = 12850 var npcs = NPCSpawnParser.parseNPCSpawns(region) var items = GroundItemSpawnParser.parseItemSpawns(region) val npcRows = ArrayList() + var npcsUpdated = false + var tileDataUpdated = false lateinit var mapPanel: MapPane lateinit var npcPanel: NPCSpawnPanel + lateinit var infoPane: InfoPane @JvmStatic fun main(args: Array) { @@ -61,7 +66,7 @@ object Rs2MapEditor { var infoLabel = JLabel() var underlayInfo = JLabel("Right click a tile to get more information") var underlayLabel = JLabel() - val npcIdInput = JTextField() + lateinit var npcIdInput: JTextField var state = EditorState.NONE class MainFrame : JFrame("Praesecho Map Editor v0.3") { @@ -80,17 +85,18 @@ object Rs2MapEditor { defaultCloseOperation = EXIT_ON_CLOSE jMenuBar = MenuBar() mapPanel = MapPane() + npcIdInput = JTextField() npcPanel = NPCSpawnPanel() - add(SettingsPane(), BorderLayout.PAGE_START) + infoPane = InfoPane() add(ScrollPane(), BorderLayout.CENTER) add(ScrollPane2(), BorderLayout.EAST) add(statusBar, BorderLayout.SOUTH) infoLabel.text = "Information" statusLabel.text = "-" - //frame.pack() setLocationRelativeTo(null) isResizable = false isVisible = true + CustomEventQueue.install() } } @@ -126,7 +132,7 @@ object Rs2MapEditor { if (overlayID == 0) { mapCell.background = underlayMap[MapTileParser.definition.getTile(column, flippedY, 0).underlayId]!!.getRGB() } else { - mapCell.background = Color(overlayMap[overlayID]!!.color) + mapCell.background = overlayMap[overlayID]!!.getRGB() } mapCell.border = border @@ -297,6 +303,7 @@ object Rs2MapEditor { println("${selectedPointX} : ${selectedPointY}") string.append("
") underlayInfo.text = String.format("%s", string.toString()) + infoPane.selectedIndex = 0 } } }) @@ -307,8 +314,9 @@ object Rs2MapEditor { init { // Scroll bar val scrollFrame = JScrollPane(mapPanel) - scrollFrame.maximumSize = Dimension(1300, 700) - scrollFrame.preferredSize = Dimension(1300, 700) + scrollFrame.maximumSize = Dimension(1300, 750) + scrollFrame.preferredSize = Dimension(1300, 750) + scrollFrame.verticalScrollBar.unitIncrement = 20 add(scrollFrame, BorderLayout.CENTER) } } @@ -317,8 +325,9 @@ object Rs2MapEditor { init { // Scroll bar layout = BorderLayout() - val scrollFrame = JScrollPane(InfoPane()) + val scrollFrame = JScrollPane(infoPane) scrollFrame.preferredSize = Dimension(255, 980) + scrollFrame.verticalScrollBar.unitIncrement = 20 add(scrollFrame, BorderLayout.CENTER) } } @@ -380,96 +389,6 @@ object Rs2MapEditor { } } - class NPCSpawnPanel : JPanel() { - val rowBorder = MatteBorder(1,1,1,1,Color.WHITE) - init { - layout = BoxLayout(this, BoxLayout.PAGE_AXIS) - - add(NPCSpawnerPanel()) - - npcs.forEach { - val row = NPCRow(it, this) - row.border = rowBorder - npcRows.add(row) - add(row) - } - } - - fun redrawRows() { - npcRows.forEach { - remove(it) - } - npcRows.clear() - npcs.forEach { - val row = NPCRow(it, this) - row.border = rowBorder - npcRows.add(row) - add(row) - } - repaint() - } - - class NPCSpawnerPanel : JPanel() { - init { - val addButton = ImgButton("add_hi.png","add_dark.png") - addButton.onClick { - state = EditorState.ADD_NPC - } - npcIdInput.minimumSize = Dimension(200,25) - npcIdInput.maximumSize = Dimension(200,25) - npcIdInput.preferredSize = Dimension(200,25) - minimumSize = Dimension(300, 60) - preferredSize = Dimension(300, 60) - maximumSize = Dimension(300, 60) - - layout = FlowLayout() - add(npcIdInput) - add(addButton) - border = MatteBorder(1,1,1,1, Color.GREEN) - } - } - - class NPCRow(val npc: NPC, val parent: JPanel) : JPanel(){ - init { - layout = FlowLayout() - add(JLabel("${npc.definition.name} (LVL ${npc.definition.combat}) [${npc.x} | ${npc.y} | ${npc.plane}]")) - val deleteButton = ImgButton("trash_hi.png","trash_dark.png") - add(deleteButton) - minimumSize = Dimension(300, 40) - preferredSize = Dimension(300, 40) - maximumSize = Dimension(300, 40) - deleteButton.onClick { - npcs.remove(npc) - parent.remove(this) - parent.repaint() - npcRows.remove(this) - if(npcs.filter { it.x == npc.x && it.y == npc.y }.isEmpty()){ - componentPointMap.filter { it.key.x == npc.x && it.key.y == npc.y }.forEach { (_,cell) -> - cell.components.forEach { c -> - if(c is JLabel) cell.remove(c) - } - cell.repaint() - } - } - } - - addMouseListener(object : MouseAdapter(){ - val border = MatteBorder(1,1,1,1,Color.YELLOW) - val defaultBorder = MatteBorder(1,1,1,1, Color.GRAY) - override fun mouseEntered(e: MouseEvent?) { - super.mouseEntered(e) - componentPointMap.filter { it.key.x == npc.x && it.key.y == npc.y }.forEach { it.value.border = border } - } - - override fun mouseExited(e: MouseEvent?) { - super.mouseExited(e) - componentPointMap.filter { it.key.x == npc.x && it.key.y == npc.y }.forEach{ it.value.border = defaultBorder } - } - }) - } - } - } - class UnderlaySquarePanel(color: Color, size: Int, val id: Any) : JPanel() { init { when (id) { diff --git a/src/main/kotlin/cacheops/cache/definition/encoder/NPCSpawnEncoder.kt b/src/main/kotlin/cacheops/cache/definition/encoder/NPCSpawnEncoder.kt index 0620b86..1d1de66 100644 --- a/src/main/kotlin/cacheops/cache/definition/encoder/NPCSpawnEncoder.kt +++ b/src/main/kotlin/cacheops/cache/definition/encoder/NPCSpawnEncoder.kt @@ -4,6 +4,7 @@ import Rs2MapEditor import cacheops.cache.definition.decoder.NPC import const.Indices import java.nio.ByteBuffer +import javax.swing.JOptionPane object NPCSpawnEncoder { @@ -25,6 +26,8 @@ object NPCSpawnEncoder { if (dataArray != null) { Rs2MapEditor.library.put(Indices.LANDSCAPES, "n${x}_${y}", dataArray, intArrayOf(0,0,0,0)) Rs2MapEditor.library.update() + JOptionPane.showMessageDialog(Rs2MapEditor.mapPanel, "NPCs written to cache. [✓]") + Rs2MapEditor.npcsUpdated = false } else { System.err.println("Panic! Something went VERY wrong!") } diff --git a/src/main/kotlin/const/Misc.kt b/src/main/kotlin/const/Misc.kt index d22748c..376b131 100644 --- a/src/main/kotlin/const/Misc.kt +++ b/src/main/kotlin/const/Misc.kt @@ -3,4 +3,4 @@ package const import cacheops.cache.Cache import cacheops.cache.CacheDelegate -val cache: Cache = CacheDelegate("K:\\RSPSDev\\2-009Scape-578\\Server\\data\\cache") +val cache: Cache = CacheDelegate("/home/ceikry/IdeaProjects/rs09-remake/Server/data/cache/") diff --git a/src/main/kotlin/ext/JagexTypes.kt b/src/main/kotlin/ext/JagexTypes.kt index 72cb882..9fd676f 100644 --- a/src/main/kotlin/ext/JagexTypes.kt +++ b/src/main/kotlin/ext/JagexTypes.kt @@ -3,7 +3,7 @@ package ext import java.nio.ByteBuffer fun ByteBuffer.medium(): Int { - return ((get().toInt() shl 16 and 0xff0000) + (get().toInt() shl 8 and 0xff00) + (get().toInt() and 0xff)) + return (((get().toInt() shl 16) and 0xff0000) + ((get().toInt() shl 8) and 0xff00) + (get().toInt() and 0xff)) // return ((get().toInt() and 0xff) + (get().toInt() shl 8 and 0xff00) + ) } diff --git a/src/main/kotlin/misc/CustomEventQueue.kt b/src/main/kotlin/misc/CustomEventQueue.kt new file mode 100644 index 0000000..249e210 --- /dev/null +++ b/src/main/kotlin/misc/CustomEventQueue.kt @@ -0,0 +1,22 @@ +package misc + +import java.awt.AWTEvent +import java.awt.Event +import java.awt.EventQueue +import java.awt.Toolkit +import java.awt.event.KeyEvent + +class CustomEventQueue : EventQueue() { + override fun dispatchEvent(event: AWTEvent?) { + if(event is KeyEvent){ + GlobalKeybinds.handle(event) + } + super.dispatchEvent(event) + } + + companion object { + fun install() { + Toolkit.getDefaultToolkit().systemEventQueue.push(CustomEventQueue()) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/misc/GlobalKeybinds.kt b/src/main/kotlin/misc/GlobalKeybinds.kt new file mode 100644 index 0000000..792b09e --- /dev/null +++ b/src/main/kotlin/misc/GlobalKeybinds.kt @@ -0,0 +1,42 @@ +package misc + +import cacheops.cache.definition.encoder.NPCSpawnEncoder +import java.awt.Event +import java.awt.event.KeyEvent + +var ctrlPressed = false + +object GlobalKeybinds{ + fun handle(event: KeyEvent){ + if(event.id == Event.KEY_PRESS){ + if(event.keyCode == KeyEvent.VK_CONTROL) { + ctrlPressed = true + } + return + } + if(event.id == Event.KEY_RELEASE){ + if(event.keyCode == KeyEvent.VK_CONTROL) { + ctrlPressed = false + return + } + } + + if(ctrlPressed){ //Handle keybinds that rely on control being pressed + when(event.keyCode){ + + + KeyEvent.VK_S -> { //CTRL+S + if(Rs2MapEditor.npcsUpdated){ + NPCSpawnEncoder.write(Rs2MapEditor.npcs) + } + } + + + } + } + + else when(event.keyCode){ + KeyEvent.VK_ESCAPE -> Rs2MapEditor.state = EditorState.NONE + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ImgButton.kt b/src/main/kotlin/misc/ImgButton.kt similarity index 99% rename from src/main/kotlin/ImgButton.kt rename to src/main/kotlin/misc/ImgButton.kt index 882a253..94c44b7 100644 --- a/src/main/kotlin/ImgButton.kt +++ b/src/main/kotlin/misc/ImgButton.kt @@ -1,3 +1,5 @@ +package misc + import java.awt.Image import java.awt.event.MouseEvent import java.awt.event.MouseListener