mirror of
https://gitlab.com/2009scape/tools/2009scape-map-viewer.git
synced 2026-08-01 14:39:25 -06:00
NPC map stuff
This commit is contained in:
parent
9c67d6d9da
commit
1a14bd7dbc
12 changed files with 349 additions and 58 deletions
54
src/main/kotlin/ImgButton.kt
Normal file
54
src/main/kotlin/ImgButton.kt
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import java.awt.Image
|
||||
import java.awt.event.MouseEvent
|
||||
import java.awt.event.MouseListener
|
||||
import javax.swing.ImageIcon
|
||||
import javax.swing.JLabel
|
||||
|
||||
open 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))
|
||||
}
|
||||
}
|
||||
|
|
@ -3,21 +3,29 @@ import cacheops.cache.definition.data.MapTile
|
|||
import cacheops.cache.definition.data.UnderlayDefinition
|
||||
import cacheops.cache.definition.decoder.FloorUnderlayConfiguration
|
||||
import cacheops.cache.definition.decoder.MapTileParser
|
||||
import cacheops.cache.definition.decoder.NPC
|
||||
import cacheops.cache.definition.decoder.NPCSpawnParser
|
||||
import cacheops.cache.definition.encoder.MapTileWriter
|
||||
import com.displee.cache.CacheLibrary
|
||||
import com.formdev.flatlaf.FlatDarculaLaf
|
||||
import const.Image.YELLOW_DOT
|
||||
import java.awt.*
|
||||
import java.awt.event.KeyEvent
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import java.lang.StringBuilder
|
||||
import javax.swing.*
|
||||
import javax.swing.border.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
object Rs2MapEditor {
|
||||
|
||||
val library = CacheLibrary.create("K:\\RSPSDev\\2-009Scape-578\\Server\\data\\cache")
|
||||
var region = 12850 // Lumbridge
|
||||
val library = CacheLibrary.create("/home/ceikry/IdeaProjects/rs09-remake/Server/data/cache/")
|
||||
var region = 7474 // Lumbridge
|
||||
var npcs = NPCSpawnParser.parseNPCSpawns(region)
|
||||
val npcRows = ArrayList<NPCSpawnPanel.NPCRow>()
|
||||
lateinit var mapPanel: MapPane
|
||||
lateinit var npcPanel: NPCSpawnPanel
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
|
|
@ -40,7 +48,7 @@ object Rs2MapEditor {
|
|||
// Stores the underlay ID for each point
|
||||
var colorPointMap: HashMap<Point, Int> = hashMapOf()
|
||||
|
||||
val componentPointMap = hashMapOf<Point, CellPane>()
|
||||
val componentPointMap = hashMapOf<Point, MapCell>()
|
||||
|
||||
// Stores the underlay ID with the Underlay Definition
|
||||
lateinit var underlayMap: HashMap<Int, UnderlayDefinition>
|
||||
|
|
@ -51,6 +59,8 @@ object Rs2MapEditor {
|
|||
var infoLabel = JLabel()
|
||||
var underlayInfo = JLabel("Right click a tile to get more information")
|
||||
var underlayLabel = JLabel()
|
||||
val npcIdInput = JTextField()
|
||||
var state = EditorState.NONE
|
||||
|
||||
class MainFrame : JFrame("Praesecho Map Editor v0.3") {
|
||||
init {
|
||||
|
|
@ -67,6 +77,8 @@ object Rs2MapEditor {
|
|||
maximumSize = Dimension(1567, 1100)
|
||||
defaultCloseOperation = EXIT_ON_CLOSE
|
||||
jMenuBar = MenuBar()
|
||||
mapPanel = MapPane()
|
||||
npcPanel = NPCSpawnPanel()
|
||||
add(SettingsPane(), BorderLayout.PAGE_START)
|
||||
add(ScrollPane(), BorderLayout.CENTER)
|
||||
add(ScrollPane2(), BorderLayout.EAST)
|
||||
|
|
@ -80,38 +92,82 @@ object Rs2MapEditor {
|
|||
}
|
||||
}
|
||||
|
||||
class GridPane : JPanel() {
|
||||
class MapPane : JPanel() {
|
||||
val gbc = GridBagConstraints()
|
||||
val mapHeight = 64
|
||||
val mapWidth = 64
|
||||
init {
|
||||
layout = GridBagLayout()
|
||||
val gbc = GridBagConstraints()
|
||||
val height = 64
|
||||
val width = 64
|
||||
gbc.fill = GridBagConstraints.NONE
|
||||
gbc.weightx = 1.0
|
||||
for (row in 0 until height) {
|
||||
for (column in 0 until width) {
|
||||
SwingUtilities.invokeLater {
|
||||
for (row in 0 until mapHeight) {
|
||||
for (column in 0 until mapWidth) {
|
||||
gbc.gridx = column
|
||||
gbc.gridy = row
|
||||
val border: Border =
|
||||
MatteBorder(
|
||||
1,
|
||||
1,
|
||||
if (row == mapHeight) 1 else 0,
|
||||
if (column == mapWidth) 1 else 0,
|
||||
Color.GRAY
|
||||
)
|
||||
val flippedY = (64 - row) - 1
|
||||
val point = Point(column, flippedY)
|
||||
colorPointMap[point] = MapTileParser.definition.getTile(column, flippedY, 0).underlayId
|
||||
val mapCell = MapCell()
|
||||
mapCell.background =
|
||||
underlayMap[MapTileParser.definition.getTile(column, flippedY, 0).underlayId]!!.getRGB()
|
||||
mapCell.border = border
|
||||
val npcsHere = npcs.filter { it.x == column && it.y == flippedY && it.plane == 0 }.toList()
|
||||
if (npcsHere.isNotEmpty()) {
|
||||
mapCell.layout = BorderLayout()
|
||||
mapCell.add(JLabel(YELLOW_DOT))
|
||||
}
|
||||
componentPointMap[point] = mapCell
|
||||
add(mapCell, gbc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun repaintMap() {
|
||||
colorPointMap.clear()
|
||||
componentPointMap.clear()
|
||||
this.removeAll()
|
||||
for (row in 0 until mapHeight) {
|
||||
for (column in 0 until mapWidth) {
|
||||
gbc.gridx = column
|
||||
gbc.gridy = row
|
||||
val border: Border = MatteBorder(1, 1, if (row == height) 1 else 0, if (column == width) 1 else 0, Color.GRAY)
|
||||
val border: Border =
|
||||
MatteBorder(1, 1, if (row == mapHeight) 1 else 0, if (column == mapWidth) 1 else 0, Color.GRAY)
|
||||
val flippedY = (64 - row) - 1
|
||||
val point = Point(column, flippedY)
|
||||
colorPointMap[point] = MapTileParser.definition.getTile(column, flippedY, 0).underlayId
|
||||
val cellPane = CellPane()
|
||||
cellPane.background = underlayMap[MapTileParser.definition.getTile(column, flippedY, 0).underlayId]!!.getRGB()
|
||||
cellPane.border = border
|
||||
componentPointMap[point] = cellPane
|
||||
add(cellPane, gbc)
|
||||
val mapCell = MapCell()
|
||||
mapCell.background =
|
||||
underlayMap[MapTileParser.definition.getTile(column, flippedY, 0).underlayId]!!.getRGB()
|
||||
mapCell.border = border
|
||||
val npcsHere = npcs.filter { it.x == column && it.y == flippedY && it.plane == 0 }.toList()
|
||||
if (npcsHere.isNotEmpty()) {
|
||||
mapCell.layout = BorderLayout()
|
||||
mapCell.add(JLabel(YELLOW_DOT))
|
||||
}
|
||||
componentPointMap[point] = mapCell
|
||||
add(mapCell, gbc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CellPane : JPanel() {
|
||||
class MapCell : JPanel() {
|
||||
var defaultBackground: Color = background
|
||||
override fun getPreferredSize(): Dimension {
|
||||
return Dimension(cellX, cellY)
|
||||
}
|
||||
init {
|
||||
|
||||
//add(underlayLabel)
|
||||
addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseEntered(e: MouseEvent) {
|
||||
|
|
@ -124,7 +180,11 @@ object Rs2MapEditor {
|
|||
"Viewing Underlay: ${MapTileParser.definition.getTile(selectedPointX, selectedPointY, 0).underlayId} | " +
|
||||
"Selected Underlay: ${if (selectedUnderlayId == null) "<font color='red'>No underlay selected!</font>" else "$selectedUnderlayId"}</html>"
|
||||
defaultBackground = background
|
||||
background = Color.BLUE
|
||||
if(state == EditorState.SET_UNDERLAY || state == EditorState.NONE) {
|
||||
background = Color.BLUE
|
||||
} else if (state == EditorState.ADD_NPC || state == EditorState.ADD_GROUNDITEM){
|
||||
background = Color.YELLOW
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseExited(e: MouseEvent) {
|
||||
|
|
@ -133,7 +193,7 @@ object Rs2MapEditor {
|
|||
|
||||
override fun mouseClicked(e: MouseEvent) {
|
||||
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||
if (selectedUnderlayId != null) {
|
||||
if (selectedUnderlayId != null && state == EditorState.SET_UNDERLAY) {
|
||||
val originalTile = MapTileParser.definition.getTile(selectedPointX, selectedPointY, 0)
|
||||
val underlayID = selectedUnderlayId
|
||||
val point = Point(selectedPointX, selectedPointY)
|
||||
|
|
@ -146,29 +206,65 @@ object Rs2MapEditor {
|
|||
// Update map tile cacheops.definitions with new tile information
|
||||
MapTileParser.definition.setTile(point.x, point.y, 0, MapTile(originalTile.height, originalTile.attrOpcode, originalTile.overlayId, originalTile.overlayPath, originalTile.overlayRotation, originalTile.settings, underlayID))
|
||||
}
|
||||
else if (npcIdInput.text.isNotEmpty() && state == EditorState.ADD_NPC){
|
||||
val id = npcIdInput.text.toIntOrNull()
|
||||
if(id == null){
|
||||
state = EditorState.NONE
|
||||
return
|
||||
}
|
||||
|
||||
val npc = NPC(id, selectedPointX, selectedPointY, 0)
|
||||
npcs.add(npc)
|
||||
componentPointMap.filter { it.key.x == selectedPointX && it.key.y == selectedPointY }.forEach {(_, cell) ->
|
||||
var hasLabel = false
|
||||
cell.components.forEach { if(it is JLabel) hasLabel = true }
|
||||
cell.layout = BorderLayout()
|
||||
if(!hasLabel) cell.add(JLabel(YELLOW_DOT))
|
||||
cell.repaint()
|
||||
}
|
||||
npcPanel.redrawRows()
|
||||
}
|
||||
} else if (SwingUtilities.isRightMouseButton(e)) {
|
||||
val point = Point(selectedPointX, selectedPointY)
|
||||
val def = MapTileParser.definition.getTile(point.x, point.y, 0)
|
||||
underlayInfo.text =
|
||||
String.format("<html><body style=\"text-align: center;\">%s</body></html>",
|
||||
"<h2><b>Tile [${point.x}, ${point.y}] Information</b></h2><br>" +
|
||||
"<hr width=\"250px\"><br>" +
|
||||
"<table style=\"border:1px solid gray;margin-left:auto;margin-right:auto;>" +
|
||||
"<thead>" +
|
||||
"<tr style=\"text-align:center\">" +
|
||||
"<th>UnderlayID</th>" +
|
||||
"<th>Height</th>" +
|
||||
"<th>Settings</th>" +
|
||||
"</tr>" +
|
||||
"</thead>" +
|
||||
"<tbody>" +
|
||||
"<tr style=\"text-align:center\">" +
|
||||
"<td>${def.underlayId}</td>" +
|
||||
"<td>${def.height}</td>" +
|
||||
"<td>${def.settings}</td>" +
|
||||
"</tr>" +
|
||||
"</tbody>" +
|
||||
"</table>")
|
||||
val string = StringBuilder()
|
||||
.append("<h2><b>Tile [${point.x}, ${point.y}] Information</b></h2><br>")
|
||||
.append("<hr width=\"250px\"><br>")
|
||||
.append("<table style=\"border:1px solid gray;margin-left:auto;margin-right:auto;>")
|
||||
.append("<thead>")
|
||||
.append("<tr style=\"text-align:center\">")
|
||||
.append("<th>UnderlayID</th>")
|
||||
.append("<th>Height</th>")
|
||||
.append("<th>Settings</th>")
|
||||
.append("</tr>")
|
||||
.append("</thead>")
|
||||
.append("<tbody>")
|
||||
.append("<tr style=\"text-align:center\">")
|
||||
.append("<td>${def.underlayId}</td>")
|
||||
.append("<td>${def.height}</td>")
|
||||
.append("<td>${def.settings}</td>")
|
||||
.append("</tr>")
|
||||
.append("</tbody>")
|
||||
.append("</table>")
|
||||
.append("<br/>")
|
||||
.append("<table style=\"border:1px solid gray;margin-left:auto;margin-right:auto;>")
|
||||
.append("<thead>")
|
||||
.append("<tr style=\"text-align:center\">")
|
||||
.append("<th>NPC ID</th>")
|
||||
.append("<th>Name</th>")
|
||||
.append("</tr>")
|
||||
.append("</thead>")
|
||||
.append("<tbody>")
|
||||
val npcsHere = npcs.filter { println(it.definition.name + " ${it.x}:${it.y}:${it.plane}"); it.x == selectedPointX && it.y == selectedPointY && it.plane == 0 }.toList()
|
||||
for(npc in npcsHere){
|
||||
string.append("<tr style=\"text-align:center\">")
|
||||
string.append("<td>${npc.id}</td>")
|
||||
string.append("<td>${npc.definition.name}(${npc.definition.combat})</td>")
|
||||
string.append("</tr>")
|
||||
}
|
||||
println("${selectedPointX} : ${selectedPointY}")
|
||||
string.append("</tbody></table><br/>")
|
||||
underlayInfo.text = String.format("<html><body style=\"text-align: center;\">%s</body></html>", string.toString())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -178,7 +274,7 @@ object Rs2MapEditor {
|
|||
class ScrollPane : JPanel() {
|
||||
init {
|
||||
// Scroll bar
|
||||
val scrollFrame = JScrollPane(GridPane())
|
||||
val scrollFrame = JScrollPane(mapPanel)
|
||||
scrollFrame.maximumSize = Dimension(1300, 980)
|
||||
scrollFrame.preferredSize = Dimension(1300, 980)
|
||||
add(scrollFrame, BorderLayout.CENTER)
|
||||
|
|
@ -201,17 +297,16 @@ object Rs2MapEditor {
|
|||
val underlayComponent: JComponent = FLUGridPanel()
|
||||
val panel3: JComponent = makeTextPanel("Howdy Ho! I'm an overlay panel, or soon will be that is!")
|
||||
|
||||
preferredSize = Dimension(230, 980)
|
||||
preferredSize = Dimension(230, 4000)
|
||||
border = CompoundBorder(LineBorder(Color.DARK_GRAY), EmptyBorder(0, 0, 0, 0))
|
||||
|
||||
|
||||
|
||||
addTab("Information", informationComponent)
|
||||
setMnemonicAt(0, KeyEvent.VK_1)
|
||||
add("Underlays", underlayComponent)
|
||||
setMnemonicAt(1, KeyEvent.VK_2)
|
||||
addTab("Overlays", panel3)
|
||||
setMnemonicAt(2, KeyEvent.VK_3)
|
||||
add("NPC Spawn", npcPanel)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +348,96 @@ 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) {
|
||||
|
|
@ -291,7 +476,12 @@ object Rs2MapEditor {
|
|||
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||
when (id) {
|
||||
is Int -> {
|
||||
selectedUnderlayId = id
|
||||
if(selectedUnderlayId == id){
|
||||
state = EditorState.NONE
|
||||
} else {
|
||||
state = EditorState.SET_UNDERLAY
|
||||
selectedUnderlayId = id
|
||||
}
|
||||
statusLabel.text = "<html>Region: $region | " +
|
||||
"Local Coordinates: [$selectedPointX, $selectedPointY] | " +
|
||||
"Global Coordinates: [${MapTileParser.coordinateX(selectedPointX)}, ${MapTileParser.coordinateX(selectedPointY)}] | " +
|
||||
|
|
@ -417,3 +607,13 @@ object Rs2MapEditor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class EditorState{
|
||||
NONE,
|
||||
SET_UNDERLAY,
|
||||
SET_OVERLAY,
|
||||
ADD_NPC,
|
||||
ADD_GROUNDITEM,
|
||||
DEL_NPC,
|
||||
DEL_GROUNDITEM
|
||||
}
|
||||
|
|
@ -8,12 +8,27 @@ import const.Indices
|
|||
|
||||
class NPCDecoder(cache: Cache, val member: Boolean) : DefinitionDecoder<NPCDefinition>(cache, Indices.CONFIGURATION_NPCS) {
|
||||
|
||||
companion object {
|
||||
val DEFINITIONS = HashMap<Int, NPCDefinition>()
|
||||
}
|
||||
|
||||
override fun create() = NPCDefinition()
|
||||
|
||||
override fun getFile(id: Int) = id and 0x7f
|
||||
|
||||
override fun getArchive(id: Int) = id ushr 7
|
||||
|
||||
override fun readData(id: Int): NPCDefinition? {
|
||||
return super.readData(id)
|
||||
}
|
||||
|
||||
fun forId(id : Int): NPCDefinition {
|
||||
if(DEFINITIONS[id] != null) return DEFINITIONS[id]!!
|
||||
val def = readData(id)
|
||||
DEFINITIONS[id] = def!!
|
||||
return def
|
||||
}
|
||||
|
||||
override fun NPCDefinition.read(opcode: Int, buffer: Reader) {
|
||||
when (opcode) {
|
||||
1 -> {
|
||||
|
|
|
|||
|
|
@ -1,42 +1,49 @@
|
|||
package cacheops.cache.definition.decoder
|
||||
|
||||
import Rs2MapEditor
|
||||
import cacheops.cache.definition.data.NPCDefinition
|
||||
import const.Image
|
||||
import const.cache
|
||||
import ext.unsignedShort
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
val decoder = NPCDecoder(cache, true)
|
||||
|
||||
class NPCSpawnDecoder {
|
||||
|
||||
fun decode(data: ByteArray) {
|
||||
fun decode(data: ByteArray): ArrayList<NPC> {
|
||||
|
||||
val buffer = ByteBuffer.wrap(data)
|
||||
val list = ArrayList<NPC>()
|
||||
|
||||
while (buffer.hasRemaining()) {
|
||||
val coords = buffer.unsignedShort()
|
||||
|
||||
val lz = coords shr 14
|
||||
val ly = (coords shr 7) and 0x3f
|
||||
val lx = coords and 0x3f
|
||||
val lx = (coords shr 7) and 0x3f
|
||||
val ly = coords and 0x3f
|
||||
|
||||
val npcID = buffer.unsignedShort()
|
||||
println("Npc: $npcID | Spawn: [$lx, $ly, $lz]")
|
||||
list.add(NPC(npcID, lx, ly, lz))
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
object NPCSpawnParser {
|
||||
|
||||
fun parseNPCSpawns() {
|
||||
// Meh 18000 is good enough for now and covers all of our regions
|
||||
for (regionIDs in 0..18000) {
|
||||
val x = (regionIDs shr 8) and 0xFF
|
||||
val y = regionIDs and 0xFF
|
||||
val npcSpawnData = Rs2MapEditor.library.data(5, "n${x}_${y}")
|
||||
fun parseNPCSpawns(regionId: Int): ArrayList<NPC> {
|
||||
val x = (regionId shr 8) and 0xFF
|
||||
val y = regionId and 0xFF
|
||||
val npcSpawnData = Rs2MapEditor.library.data(5, "n${x}_${y}")
|
||||
|
||||
if (npcSpawnData != null && npcSpawnData.isNotEmpty()) {
|
||||
println("NPC DATA FOR $regionIDs")
|
||||
NPCSpawnDecoder().decode(npcSpawnData)
|
||||
println("\n")
|
||||
}
|
||||
if (npcSpawnData != null && npcSpawnData.isNotEmpty()) {
|
||||
return NPCSpawnDecoder().decode(npcSpawnData)
|
||||
}
|
||||
return ArrayList()
|
||||
}
|
||||
}
|
||||
|
||||
class NPC(val id: Int, val x: Int, val y: Int, val plane: Int) {
|
||||
val definition: NPCDefinition = decoder.forId(id)
|
||||
}
|
||||
9
src/main/kotlin/const/Image.kt
Normal file
9
src/main/kotlin/const/Image.kt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package const
|
||||
|
||||
import javax.imageio.ImageIO
|
||||
import javax.swing.ImageIcon
|
||||
|
||||
object Image {
|
||||
val RED_DOT = ImageIcon(ImageIO.read(javaClass.getResource("/dot_red.png")))
|
||||
val YELLOW_DOT = ImageIcon(ImageIO.read(javaClass.getResource("/dot_yellow.png")))
|
||||
}
|
||||
6
src/main/kotlin/const/Misc.kt
Normal file
6
src/main/kotlin/const/Misc.kt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package const
|
||||
|
||||
import cacheops.cache.Cache
|
||||
import cacheops.cache.CacheDelegate
|
||||
|
||||
val cache: Cache = CacheDelegate("/home/ceikry/IdeaProjects/rs09-remake/Server/data/cache/")
|
||||
BIN
src/main/resources/add_dark.png
Normal file
BIN
src/main/resources/add_dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 356 B |
BIN
src/main/resources/add_hi.png
Normal file
BIN
src/main/resources/add_hi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 337 B |
BIN
src/main/resources/dot_red.png
Normal file
BIN
src/main/resources/dot_red.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 114 B |
BIN
src/main/resources/dot_yellow.png
Normal file
BIN
src/main/resources/dot_yellow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 115 B |
BIN
src/main/resources/trash_dark.png
Normal file
BIN
src/main/resources/trash_dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 330 B |
BIN
src/main/resources/trash_hi.png
Normal file
BIN
src/main/resources/trash_hi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 323 B |
Loading…
Add table
Add a link
Reference in a new issue