mirror of
https://gitlab.com/2009scape/tools/rs09-thanos-tool.git
synced 2026-08-01 14:39:20 -06:00
Implemented NPC spawn editing and lots of UI improvements
This commit is contained in:
parent
5855afa6ca
commit
4b673c9063
98 changed files with 7040 additions and 3 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
build/
|
||||||
|
.idea/
|
||||||
|
.gradle/
|
||||||
10
build.gradle
10
build.gradle
|
|
@ -1,5 +1,6 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'org.jetbrains.kotlin.jvm' version '1.4.32'
|
id 'org.jetbrains.kotlin.jvm' version '1.4.32'
|
||||||
|
id 'application'
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'org.example'
|
group 'org.example'
|
||||||
|
|
@ -11,12 +12,21 @@ repositories {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClass = 'MainScreenKt'
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains:markdown-jvm:0.2.0"
|
implementation "org.jetbrains:markdown-jvm:0.2.0"
|
||||||
implementation "com.github.ajalt.mordant:mordant:2.0.0-alpha2"
|
implementation "com.github.ajalt.mordant:mordant:2.0.0-alpha2"
|
||||||
implementation "com.github.weisj:darklaf-core:2.5.5"
|
implementation "com.github.weisj:darklaf-core:2.5.5"
|
||||||
implementation "com.googlecode.json-simple:json-simple:1.1.1"
|
implementation "com.googlecode.json-simple:json-simple:1.1.1"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib"
|
||||||
|
// https://mvnrepository.com/artifact/com.displee/disio
|
||||||
|
implementation group: 'com.displee', name: 'disio', version: '2.2'
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/com.displee/rs-cache-library
|
||||||
|
implementation group: 'com.displee', name: 'rs-cache-library', version: '6.8.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
task buildJar(type: Jar) {
|
task buildJar(type: Jar) {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ object EditorConstants {
|
||||||
|
|
||||||
var CONFIG_PATH = ""
|
var CONFIG_PATH = ""
|
||||||
|
|
||||||
var VALID_FILES = arrayOf("drop_tables.json","npc_configs.json","item_configs.json", "shops.json", "object_configs.json")
|
var VALID_FILES = arrayOf("drop_tables.json","npc_configs.json","item_configs.json", "shops.json", "object_configs.json", "npc_spawns.json", "ground_item_spawns.json")
|
||||||
|
|
||||||
var CREDITS = arrayOf(
|
var CREDITS = arrayOf(
|
||||||
"weisJ - darklaf look and feel themes http://github.com/weisj",
|
"weisJ - darklaf look and feel themes http://github.com/weisj",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import org.json.simple.JSONArray
|
import org.json.simple.JSONArray
|
||||||
import org.json.simple.JSONObject
|
import org.json.simple.JSONObject
|
||||||
import org.json.simple.parser.JSONParser
|
import org.json.simple.parser.JSONParser
|
||||||
|
import tools.Util
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileReader
|
import java.io.FileReader
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
|
|
@ -254,6 +255,66 @@ enum class Editors(val data: EditorData) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
|
NPC_SPAWNS(object : EditorData("npc_spawns.json") {
|
||||||
|
override fun parse() {
|
||||||
|
Logger.logInfo("Parsing npc spawn data...")
|
||||||
|
val spawnMap = HashMap<Int, ArrayList<TableData.NPCSpawn>>()
|
||||||
|
configureParser()
|
||||||
|
data.forEach { spawnRaw ->
|
||||||
|
val spawn = spawnRaw as JSONObject
|
||||||
|
val id = spawn["npc_id"].toString().toInt()
|
||||||
|
val datas: Array<String> = spawn["loc_data"].toString().split("-".toRegex()).toTypedArray()
|
||||||
|
var tokens: Array<String>
|
||||||
|
for (d in datas) {
|
||||||
|
if(d.isEmpty()){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tokens = d.replace("{", "").replace("}", "").split(",".toRegex()).toTypedArray()
|
||||||
|
val isWalks = tokens[3].trim { it <= ' ' } == "1"
|
||||||
|
val spawnDirection = Integer.valueOf(tokens[4].trim { it <= ' ' })
|
||||||
|
val spawnCoords = intArrayOf(Integer.valueOf(tokens[0].trim { it <= ' ' }), Integer.valueOf(tokens[1].trim { it <= ' ' }), Integer.valueOf(tokens[2].trim { it <= ' ' }))
|
||||||
|
val npc = TableData.NPCSpawn(id, TableData.Location(spawnCoords[0], spawnCoords[1], spawnCoords[2]), isWalks, spawnDirection)
|
||||||
|
val regionId = Util.getRegionId(npc.location)
|
||||||
|
if (!spawnMap.containsKey(regionId))
|
||||||
|
spawnMap[regionId] = ArrayList()
|
||||||
|
spawnMap[regionId]!!.add(npc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TableData.npcSpawns = spawnMap
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun save() {
|
||||||
|
Logger.logInfo("Saving NPC spawn info...")
|
||||||
|
val spawnMap = HashMap<Int, StringBuilder>()
|
||||||
|
for ((_, spawns) in TableData.npcSpawns) {
|
||||||
|
for (spawn in spawns) {
|
||||||
|
if (!spawnMap.contains(spawn.id)) spawnMap[spawn.id] = StringBuilder()
|
||||||
|
spawnMap[spawn.id]!!.append("{${spawn.location.x},${spawn.location.y},${spawn.location.z},${if(spawn.canWalk) 1 else 0},${spawn.spawnDirection}}-")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val spawnsJsonArray = JSONArray()
|
||||||
|
for ((id, spawnString) in spawnMap.entries.sortedBy { it.key.toInt() }) {
|
||||||
|
val spawn = JSONObject()
|
||||||
|
spawn["npc_id"] = id.toString()
|
||||||
|
spawn["loc_data"] = spawnString.toString()
|
||||||
|
spawnsJsonArray.add(spawn)
|
||||||
|
}
|
||||||
|
val manager = ScriptEngineManager()
|
||||||
|
val scriptEngine = manager.getEngineByName("JavaScript")
|
||||||
|
scriptEngine.put("jsonString", spawnsJsonArray.toJSONString())
|
||||||
|
scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)")
|
||||||
|
val prettyPrintedJson = scriptEngine["result"] as String
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileWriter(EditorConstants.CONFIG_PATH + File.separator + fileName).use { file ->
|
||||||
|
file.write(prettyPrintedJson)
|
||||||
|
file.flush()
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ object MainScreen : JFrame("RS09 Thanos Tool ${EditorConstants.BUILD_NUMBER}") {
|
||||||
val openItem = JButton("Edit Item Configs")
|
val openItem = JButton("Edit Item Configs")
|
||||||
val openShops = JButton("Edit Shops")
|
val openShops = JButton("Edit Shops")
|
||||||
val openObjects = JButton("Edit Object Configs")
|
val openObjects = JButton("Edit Object Configs")
|
||||||
|
val openNpcItemSpawns = JButton("Edit NPC/Item Spawns")
|
||||||
var loadedModel = object : DefaultTableModel(){}
|
var loadedModel = object : DefaultTableModel(){}
|
||||||
val loadedTable = object : JTable(loadedModel){
|
val loadedTable = object : JTable(loadedModel){
|
||||||
override fun editCellAt(p0: Int, p1: Int): Boolean {
|
override fun editCellAt(p0: Int, p1: Int): Boolean {
|
||||||
|
|
@ -79,6 +80,10 @@ object MainScreen : JFrame("RS09 Thanos Tool ${EditorConstants.BUILD_NUMBER}") {
|
||||||
ShopList().open()
|
ShopList().open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openNpcItemSpawns.addActionListener {
|
||||||
|
Rs2MapEditor.main(arrayOf())
|
||||||
|
}
|
||||||
|
|
||||||
val showCredits = JButton("Show Credits")
|
val showCredits = JButton("Show Credits")
|
||||||
showCredits.addActionListener {
|
showCredits.addActionListener {
|
||||||
credits.isVisible = true
|
credits.isVisible = true
|
||||||
|
|
@ -87,8 +92,8 @@ object MainScreen : JFrame("RS09 Thanos Tool ${EditorConstants.BUILD_NUMBER}") {
|
||||||
val editorPanel = JPanel()
|
val editorPanel = JPanel()
|
||||||
val selectionPanel = JPanel()
|
val selectionPanel = JPanel()
|
||||||
|
|
||||||
editorPanel.layout = BoxLayout(editorPanel, BoxLayout.Y_AXIS)//BoxLayout(editorPanel, BoxLayout.PAGE_AXIS)
|
editorPanel.layout = BoxLayout(editorPanel, BoxLayout.Y_AXIS)
|
||||||
for(i in arrayOf(openDrops, openNPC, openItem, openObjects, openShops, showCredits)){
|
for(i in arrayOf(openDrops, openNPC, openItem, openObjects, openShops, openNpcItemSpawns, showCredits)){
|
||||||
i.preferredSize = Dimension(175,40)
|
i.preferredSize = Dimension(175,40)
|
||||||
i.maximumSize = Dimension(175,40)
|
i.maximumSize = Dimension(175,40)
|
||||||
i.isEnabled = i == showCredits
|
i.isEnabled = i == showCredits
|
||||||
|
|
@ -134,6 +139,7 @@ fun showLoaded(){
|
||||||
"item_configs" -> MainScreen.openItem.isEnabled = true.also { Editors.ITEM_CONFIGS.data.parse() }
|
"item_configs" -> MainScreen.openItem.isEnabled = true.also { Editors.ITEM_CONFIGS.data.parse() }
|
||||||
"shops" -> MainScreen.openShops.isEnabled = true.also { Editors.SHOPS.data.parse() }
|
"shops" -> MainScreen.openShops.isEnabled = true.also { Editors.SHOPS.data.parse() }
|
||||||
"object_configs" -> MainScreen.openObjects.isEnabled = true.also { Editors.OBJECT_CONFIGS.data.parse()}
|
"object_configs" -> MainScreen.openObjects.isEnabled = true.also { Editors.OBJECT_CONFIGS.data.parse()}
|
||||||
|
"npc_spawns" -> MainScreen.openNpcItemSpawns.isEnabled = true.also { Editors.NPC_SPAWNS.data.parse() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
97
src/main/kotlin/NPCMenu.kt
Normal file
97
src/main/kotlin/NPCMenu.kt
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
import java.awt.Dimension
|
||||||
|
import java.awt.event.KeyEvent
|
||||||
|
import java.awt.event.KeyListener
|
||||||
|
import java.awt.event.MouseEvent
|
||||||
|
import java.awt.event.MouseListener
|
||||||
|
import java.util.*
|
||||||
|
import java.util.regex.PatternSyntaxException
|
||||||
|
import javax.swing.*
|
||||||
|
import javax.swing.table.DefaultTableCellRenderer
|
||||||
|
import javax.swing.table.DefaultTableModel
|
||||||
|
import javax.swing.table.TableRowSorter
|
||||||
|
|
||||||
|
object NPCMenu : JFrame("NPC Selection Menu") {
|
||||||
|
var model = DefaultTableModel()
|
||||||
|
var searchField = JTextField()
|
||||||
|
var sorter = TableRowSorter(model)
|
||||||
|
var cellRenderer = DefaultTableCellRenderer()
|
||||||
|
var populated = false
|
||||||
|
var caller: ((Int,String) -> Unit)? = null
|
||||||
|
private fun filter() {
|
||||||
|
var rf: RowFilter<DefaultTableModel?, Any?>? = null
|
||||||
|
//If current expression doesn't parse, don't update.
|
||||||
|
rf = try {
|
||||||
|
RowFilter.regexFilter("(?i)${searchField.text}")
|
||||||
|
} catch (e: PatternSyntaxException) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sorter.rowFilter = rf
|
||||||
|
}
|
||||||
|
|
||||||
|
fun open() {
|
||||||
|
if (!populated) {
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
for ((id,name) in TableData.npcNames) {
|
||||||
|
model.addRow(arrayOf(id,name))
|
||||||
|
}
|
||||||
|
isVisible = true
|
||||||
|
populated = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
layout = BorderLayout()
|
||||||
|
cellRenderer.toolTipText = "Double-Click to select."
|
||||||
|
val searchPanel = JPanel()
|
||||||
|
val searchLabel = JLabel("Search for NPC:")
|
||||||
|
searchField.preferredSize = Dimension(100, 20)
|
||||||
|
searchPanel.add(searchLabel)
|
||||||
|
searchPanel.add(searchField)
|
||||||
|
add(searchPanel, BorderLayout.NORTH)
|
||||||
|
setLocationRelativeTo(null)
|
||||||
|
val npcTable: JTable = object : JTable(model) {
|
||||||
|
override fun editCellAt(i: Int, i1: Int, eventObject: EventObject): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.addColumn("ID")
|
||||||
|
model.addColumn("Name")
|
||||||
|
npcTable.rowSorter = sorter
|
||||||
|
npcTable.columnModel.getColumn(0).maxWidth = 55
|
||||||
|
npcTable.columnModel.getColumn(0).cellRenderer = cellRenderer
|
||||||
|
npcTable.columnModel.getColumn(1).cellRenderer = cellRenderer
|
||||||
|
npcTable.addMouseListener(object : MouseListener {
|
||||||
|
override fun mouseClicked(mouseEvent: MouseEvent) {
|
||||||
|
if (mouseEvent.clickCount == 2) {
|
||||||
|
val table = mouseEvent.source as JTable
|
||||||
|
val row = table.selectedRow
|
||||||
|
val selectedID = table.getValueAt(row,0).toString().toInt()
|
||||||
|
val selectedName = table.getValueAt(row,1).toString()
|
||||||
|
caller?.invoke(selectedID,selectedName)
|
||||||
|
isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mousePressed(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseReleased(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseEntered(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseExited(mouseEvent: MouseEvent) {}
|
||||||
|
})
|
||||||
|
searchField.addKeyListener(object : KeyListener {
|
||||||
|
override fun keyTyped(keyEvent: KeyEvent) {
|
||||||
|
filter()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyPressed(keyEvent: KeyEvent) {}
|
||||||
|
override fun keyReleased(keyEvent: KeyEvent) {}
|
||||||
|
})
|
||||||
|
val scrollPane = JScrollPane(npcTable)
|
||||||
|
add(scrollPane, BorderLayout.SOUTH)
|
||||||
|
pack()
|
||||||
|
isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
405
src/main/kotlin/Rs2MapEditor.kt
Normal file
405
src/main/kotlin/Rs2MapEditor.kt
Normal file
|
|
@ -0,0 +1,405 @@
|
||||||
|
|
||||||
|
import cacheops.cache.definition.data.OverlayDefinition
|
||||||
|
import cacheops.cache.definition.data.UnderlayDefinition
|
||||||
|
import cacheops.cache.definition.data.MapTile
|
||||||
|
import cacheops.cache.definition.decoder.*
|
||||||
|
import com.displee.cache.CacheLibrary
|
||||||
|
import const.Image.RED_DOT
|
||||||
|
import const.Image.YELLOW_DOT
|
||||||
|
import const.cachePath
|
||||||
|
import misc.CustomEventQueue
|
||||||
|
import tools.ItemSearchTool
|
||||||
|
import tools.NPCSearchTool
|
||||||
|
import tools.Util
|
||||||
|
import ui.*
|
||||||
|
import java.awt.*
|
||||||
|
import java.awt.event.*
|
||||||
|
import javax.swing.*
|
||||||
|
import javax.swing.border.*
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
object Rs2MapEditor {
|
||||||
|
|
||||||
|
val library = CacheLibrary.create(cachePath)
|
||||||
|
var region = 12850
|
||||||
|
var npcs = TableData.npcSpawns[region]
|
||||||
|
var items = GroundItemSpawnParser.parseItemSpawns(region)
|
||||||
|
var sceneries = TileSceneryParser.parseRegion(region)
|
||||||
|
val npcRows = ArrayList<NPCSpawnPanel.NPCRow>()
|
||||||
|
val itemRows = ArrayList<ItemSpawnPanel.ItemRow>()
|
||||||
|
var npcsUpdated = false
|
||||||
|
var itemsUpdated = false
|
||||||
|
var tileDataUpdated = false
|
||||||
|
var plane = 0
|
||||||
|
var visualizeHeight = false
|
||||||
|
var drawGrid = true
|
||||||
|
var previousHeight = -1
|
||||||
|
lateinit var mapPanel: MapPane
|
||||||
|
lateinit var npcPanel: NPCSpawnPanel
|
||||||
|
lateinit var itemPanel: ItemSpawnPanel
|
||||||
|
lateinit var infoPane: InfoPane
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
FloorUnderlayConfiguration.init()
|
||||||
|
FloorOverlayConfiguration.init()
|
||||||
|
MapTileParser.init()
|
||||||
|
underlayMap = FloorUnderlayConfiguration.floorUnderlays
|
||||||
|
overlayMap = FloorOverlayConfiguration.floorOverlays
|
||||||
|
MainFrame()
|
||||||
|
}
|
||||||
|
|
||||||
|
var cellX = 20
|
||||||
|
var cellY = 20
|
||||||
|
|
||||||
|
// Formatted points
|
||||||
|
var selectedPointX = 0
|
||||||
|
|
||||||
|
var selectedPointY = 0
|
||||||
|
get() = (64 - field) - 1
|
||||||
|
|
||||||
|
// Stores the underlay ID for each point
|
||||||
|
var colorPointMap: HashMap<Point, Int> = hashMapOf()
|
||||||
|
|
||||||
|
val componentPointMap = hashMapOf<Point, MapCell>()
|
||||||
|
|
||||||
|
// Stores the underlay ID with the Underlay Definition
|
||||||
|
lateinit var underlayMap: HashMap<Int, UnderlayDefinition>
|
||||||
|
lateinit var overlayMap: HashMap<Int, OverlayDefinition>
|
||||||
|
|
||||||
|
var selectedUnderlayId: Int? = null
|
||||||
|
|
||||||
|
var statusLabel = JLabel()
|
||||||
|
var infoLabel = JLabel()
|
||||||
|
var underlayInfo = JLabel("Right click a tile to get more information")
|
||||||
|
var underlayLabel = JLabel()
|
||||||
|
lateinit var npcIdInput: JTextField
|
||||||
|
lateinit var npcCanWalkCheckbox: JCheckBox
|
||||||
|
lateinit var npcDirectionCheckboxes: Array<JCheckBox>
|
||||||
|
lateinit var directionalCheckboxPanel: JPanel
|
||||||
|
lateinit var itemIdInput: JTextField
|
||||||
|
lateinit var itemRespawnInput: JTextField
|
||||||
|
lateinit var itemAmountInput: JTextField
|
||||||
|
lateinit var infoScrollPane: ScrollPane2
|
||||||
|
var state = EditorState.NONE
|
||||||
|
|
||||||
|
class MainFrame : JFrame("2009scape Map Viewer v1.0") {
|
||||||
|
init {
|
||||||
|
val statusBar = JPanel(FlowLayout(FlowLayout.LEFT))
|
||||||
|
statusBar.border = CompoundBorder(
|
||||||
|
LineBorder(Color.DARK_GRAY),
|
||||||
|
EmptyBorder(2, 3, 2, 3)
|
||||||
|
)
|
||||||
|
statusLabel.foreground = Color.YELLOW
|
||||||
|
|
||||||
|
directionalCheckboxPanel = JPanel(GridLayout(3,3))
|
||||||
|
npcDirectionCheckboxes = Array<JCheckBox>(8) { JCheckBox().also { it.addItemListener(DirectionCheckboxOnClick) } }
|
||||||
|
var cbCounter = 0
|
||||||
|
for (i in 0 until 9) {
|
||||||
|
if (i == 0) npcDirectionCheckboxes[i].setSelected(true)
|
||||||
|
if (i != 4) {
|
||||||
|
directionalCheckboxPanel.add(npcDirectionCheckboxes[cbCounter++])
|
||||||
|
} else {
|
||||||
|
directionalCheckboxPanel.add(JLabel("↻", SwingConstants.CENTER))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusBar.add(statusLabel)
|
||||||
|
|
||||||
|
bounds = Rectangle(Dimension(1567, 850))
|
||||||
|
size.setSize(1567, 850)
|
||||||
|
maximumSize = Dimension(1567, 850)
|
||||||
|
defaultCloseOperation = HIDE_ON_CLOSE
|
||||||
|
jMenuBar = MenuBar()
|
||||||
|
mapPanel = MapPane()
|
||||||
|
npcIdInput = JTextField()
|
||||||
|
npcCanWalkCheckbox = JCheckBox()
|
||||||
|
itemIdInput = JTextField()
|
||||||
|
itemRespawnInput = JTextField()
|
||||||
|
itemAmountInput = JTextField()
|
||||||
|
npcPanel = NPCSpawnPanel()
|
||||||
|
itemPanel = ItemSpawnPanel()
|
||||||
|
infoPane = InfoPane()
|
||||||
|
infoScrollPane = ScrollPane2()
|
||||||
|
add(ScrollPane(), BorderLayout.CENTER)
|
||||||
|
add(infoScrollPane, BorderLayout.EAST)
|
||||||
|
add(statusBar, BorderLayout.SOUTH)
|
||||||
|
infoLabel.text = "Information"
|
||||||
|
statusLabel.text = "-"
|
||||||
|
setLocationRelativeTo(null)
|
||||||
|
isResizable = false
|
||||||
|
isVisible = true
|
||||||
|
|
||||||
|
CustomEventQueue.install()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapPane : JPanel() {
|
||||||
|
val gbc = GridBagConstraints()
|
||||||
|
val mapHeight = 64
|
||||||
|
val mapWidth = 64
|
||||||
|
init {
|
||||||
|
layout = GridBagLayout()
|
||||||
|
gbc.fill = GridBagConstraints.NONE
|
||||||
|
gbc.weightx = 1.0
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
repaintMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
var border: Border = MatteBorder(1, 1, if (row == mapHeight) 1 else 0, if (column == mapWidth) 1 else 0, Color(255,255,255,25))
|
||||||
|
val flippedY = (64 - row) - 1
|
||||||
|
val point = Point(column, flippedY)
|
||||||
|
colorPointMap[point] = MapTileParser.definition.getTile(column, flippedY, plane).underlayId - 1
|
||||||
|
val mapCell = MapCell()
|
||||||
|
|
||||||
|
val tileDef = MapTileParser.definition.getTile(column, flippedY, plane)
|
||||||
|
var overlayID = (MapTileParser.definition.getTile(column, flippedY, plane).overlayId - 1)
|
||||||
|
var underlayID = (MapTileParser.definition.getTile(column, flippedY, plane).underlayId - 1)
|
||||||
|
|
||||||
|
|
||||||
|
componentPointMap[point] = mapCell
|
||||||
|
add(mapCell, gbc)
|
||||||
|
|
||||||
|
if(overlayID < 0 && underlayID < 0){
|
||||||
|
mapCell.defaultBackground = Color(0,0,0,0)
|
||||||
|
mapCell.background = mapCell.defaultBackground
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (underlayID < 0) {
|
||||||
|
underlayID = 0
|
||||||
|
}
|
||||||
|
if (overlayID < 0) {
|
||||||
|
overlayID = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val fluDef = underlayMap[underlayID]
|
||||||
|
val floDef = overlayMap[overlayID]
|
||||||
|
|
||||||
|
if (overlayID == 0) {
|
||||||
|
mapCell.background = fluDef!!.getRGB()
|
||||||
|
} else if (floDef!!.blendColor != -1) {
|
||||||
|
mapCell.background = Color(floDef.blendColor)
|
||||||
|
} else {
|
||||||
|
mapCell.background = floDef.getRGB()
|
||||||
|
}
|
||||||
|
|
||||||
|
if(visualizeHeight){
|
||||||
|
val height = tileDef.height
|
||||||
|
val otherTiles: List<MapTile> = Pair(column, flippedY).getSurroundingTiles()
|
||||||
|
|
||||||
|
val borderSizes = intArrayOf(0,0,0,0)
|
||||||
|
var borderColor = Color(0,0,0,0)
|
||||||
|
|
||||||
|
for(tileIndex in otherTiles.indices){
|
||||||
|
val tile = otherTiles[tileIndex]
|
||||||
|
if(height > tile.height){
|
||||||
|
val tileDiff = height - tile.height
|
||||||
|
val alpha = Math.min(tileDiff * 8, 255)
|
||||||
|
val color: Color
|
||||||
|
try {
|
||||||
|
color = Color(0,0,0, alpha)
|
||||||
|
} catch (e: Exception){
|
||||||
|
println("Invalid alpha value: $alpha")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val borderIndex = when(tileIndex){
|
||||||
|
0 -> 0
|
||||||
|
3 -> 1
|
||||||
|
2 -> 2
|
||||||
|
1 -> 3
|
||||||
|
else -> -1
|
||||||
|
}
|
||||||
|
|
||||||
|
borderSizes[borderIndex] = 3
|
||||||
|
if(color.alpha > borderColor.alpha) borderColor = color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapCell.border = MatteBorder(borderSizes[0], borderSizes[1], borderSizes[2], borderSizes[3], borderColor)
|
||||||
|
} else if(drawGrid) {
|
||||||
|
mapCell.border = border
|
||||||
|
}
|
||||||
|
|
||||||
|
val sceneryHere = sceneries.filter { it.x == column && it.y == flippedY && it.plane == plane }.toList()
|
||||||
|
if(sceneryHere.isNotEmpty()){
|
||||||
|
sceneryHere.forEach(mapCell::flagScenery)
|
||||||
|
}
|
||||||
|
|
||||||
|
val thisAbsolute = Util.getAbsoluteCoordinates(region, column, flippedY, plane)
|
||||||
|
val npcsHere = npcs!!.filter { it.location == thisAbsolute }.toList()
|
||||||
|
if (npcsHere.isNotEmpty()) {
|
||||||
|
mapCell.layout = BorderLayout()
|
||||||
|
mapCell.add(JLabel(YELLOW_DOT))
|
||||||
|
}
|
||||||
|
val itemSpawnsHere = items.filter { it.x == column && it.y == flippedY && it.plane == plane }.toList()
|
||||||
|
if (itemSpawnsHere.isNotEmpty()) {
|
||||||
|
mapCell.layout = BorderLayout()
|
||||||
|
mapCell.add(JLabel(RED_DOT))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
this.repaint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScrollPane : JPanel() {
|
||||||
|
init {
|
||||||
|
// Scroll bar
|
||||||
|
val scrollFrame = JScrollPane(mapPanel)
|
||||||
|
scrollFrame.maximumSize = Dimension(1300, 750)
|
||||||
|
scrollFrame.preferredSize = Dimension(1300, 750)
|
||||||
|
scrollFrame.verticalScrollBar.unitIncrement = 20
|
||||||
|
add(scrollFrame, BorderLayout.CENTER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScrollPane2 : JPanel() {
|
||||||
|
lateinit var scrollFrame: JScrollPane
|
||||||
|
init {
|
||||||
|
// Scroll bar
|
||||||
|
layout = BorderLayout()
|
||||||
|
scrollFrame = JScrollPane(infoPane)
|
||||||
|
scrollFrame.preferredSize = Dimension(255, 980)
|
||||||
|
scrollFrame.verticalScrollBar.unitIncrement = 20
|
||||||
|
add(scrollFrame, BorderLayout.CENTER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun makeTextPanel(text: String?): JComponent {
|
||||||
|
val panel = JPanel(false)
|
||||||
|
val filler = JLabel(text)
|
||||||
|
filler.horizontalAlignment = JLabel.CENTER
|
||||||
|
panel.layout = GridLayout(1, 1)
|
||||||
|
panel.add(filler)
|
||||||
|
return panel
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuBar : JMenuBar() {
|
||||||
|
init {
|
||||||
|
add(GoMenuOption())
|
||||||
|
add(MoveRegionButton("NORTH", 0, 1))
|
||||||
|
add(MoveRegionButton("SOUTH", 0, -1))
|
||||||
|
add(MoveRegionButton("EAST", 1, 0))
|
||||||
|
add(MoveRegionButton("WEST", -1, 0))
|
||||||
|
add(JSeparator(JSeparator.VERTICAL))
|
||||||
|
add(JLabel("Plane: "))
|
||||||
|
add(PlaneButton(0))
|
||||||
|
add(PlaneButton(1))
|
||||||
|
add(PlaneButton(2))
|
||||||
|
add(PlaneButton(3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GoMenuOption : JMenu("Go..") {
|
||||||
|
init {
|
||||||
|
add(LoadRegionItem())
|
||||||
|
add(LoadByCoordinatesItem())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadRegionItem : JMenuItem("To Region") {
|
||||||
|
init {
|
||||||
|
addActionListener {
|
||||||
|
val region = JOptionPane.showInputDialog("Enter Desired Region ID")
|
||||||
|
val regionId = region.toIntOrNull() ?: JOptionPane.showInputDialog("Invalid Integer Entered").toIntOrNull() ?: return@addActionListener
|
||||||
|
|
||||||
|
Rs2MapEditor.loadRegion(regionId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadByCoordinatesItem : JMenuItem("To Coords") {
|
||||||
|
init {
|
||||||
|
addActionListener {
|
||||||
|
val coords = JOptionPane.showInputDialog("Enter Coords")
|
||||||
|
val components = coords.split(",").map { it.trim { it <= ' ' }.toInt() }.toIntArray()
|
||||||
|
val regionId = Util.getRegionId (TableData.Location(components[0], components[1], components[2]))
|
||||||
|
|
||||||
|
Rs2MapEditor.loadRegion(regionId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrefMenuOption : JMenu("Preferences") {
|
||||||
|
init {
|
||||||
|
add(visualizeHeightItem())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class visualizeHeightItem : JCheckBoxMenuItem("Visualize Heights", false) {
|
||||||
|
init {
|
||||||
|
addActionListener {
|
||||||
|
Rs2MapEditor.visualizeHeight = !Rs2MapEditor.visualizeHeight
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
mapPanel.repaintMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MoveRegionButton(symbol: String, val diffX: Int, val diffY: Int) : JButton(symbol) {
|
||||||
|
init {
|
||||||
|
this.addMouseListener (object : MouseAdapter() {
|
||||||
|
override fun mouseClicked (e: MouseEvent) {
|
||||||
|
var currentRegion = Rs2MapEditor.region
|
||||||
|
var newRegion = Util.getRegion(currentRegion, diffX, diffY)
|
||||||
|
Rs2MapEditor.loadRegion(newRegion)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var DirectionCheckboxOnClick = object : ItemListener {
|
||||||
|
override fun itemStateChanged (e: ItemEvent) {
|
||||||
|
var source = e.getItemSelectable()
|
||||||
|
if (source !is JCheckBox) return
|
||||||
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
|
for (checkbox in npcDirectionCheckboxes) { if (checkbox != source) checkbox.setSelected(false) }
|
||||||
|
} else {
|
||||||
|
var anySelected = false
|
||||||
|
for (checkbox in npcDirectionCheckboxes) { if (checkbox.isSelected) anySelected = true }
|
||||||
|
if (!anySelected) source.setSelected(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadRegion (regionId: Int) {
|
||||||
|
Rs2MapEditor.region = regionId
|
||||||
|
Rs2MapEditor.plane = 0
|
||||||
|
npcs = TableData.npcSpawns[regionId] ?: ArrayList<TableData.NPCSpawn>().also { TableData.npcSpawns[regionId] = it }
|
||||||
|
items = GroundItemSpawnParser.parseItemSpawns(regionId)
|
||||||
|
sceneries = TileSceneryParser.parseRegion(regionId)
|
||||||
|
npcPanel.redrawRows()
|
||||||
|
itemPanel.redrawRows()
|
||||||
|
try {
|
||||||
|
MapTileParser.init()
|
||||||
|
mapPanel.repaintMap()
|
||||||
|
} catch (e: Exception){
|
||||||
|
mapPanel.removeAll()
|
||||||
|
mapPanel.revalidate()
|
||||||
|
JOptionPane.showMessageDialog(null, "No Map Data for Region ID $regionId.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class EditorState{
|
||||||
|
NONE,
|
||||||
|
SET_UNDERLAY,
|
||||||
|
SET_OVERLAY,
|
||||||
|
ADD_NPC,
|
||||||
|
ADD_GROUNDITEM,
|
||||||
|
DEL_NPC,
|
||||||
|
DEL_GROUNDITEM
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import org.json.simple.JSONArray
|
import org.json.simple.JSONArray
|
||||||
import org.json.simple.JSONObject
|
import org.json.simple.JSONObject
|
||||||
|
import tools.Util
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
@ -8,11 +9,18 @@ import javax.script.ScriptEngineManager
|
||||||
|
|
||||||
object TableData {
|
object TableData {
|
||||||
class Shop(var id: Int,var title: String,var stock: ArrayList<Item>,var npcs: String,var currency: Int,var general_store: Boolean,var high_alch: Boolean,var forceShared: Boolean)
|
class Shop(var id: Int,var title: String,var stock: ArrayList<Item>,var npcs: String,var currency: Int,var general_store: Boolean,var high_alch: Boolean,var forceShared: Boolean)
|
||||||
|
data class NPCSpawn(var id: Int, var location: Location, var canWalk: Boolean, var spawnDirection: Int)
|
||||||
|
data class ItemSpawn(var id: Int, var location: Location, var respawnTicks: Int, var amount: Int)
|
||||||
|
data class Location(val x: Int, val y: Int, val z: Int) {
|
||||||
|
val localCoords = Util.getRegionCoordinates(this)
|
||||||
|
}
|
||||||
val tables = ArrayList<NPCDropTable>()
|
val tables = ArrayList<NPCDropTable>()
|
||||||
val itemNames = hashMapOf<Int,String>()
|
val itemNames = hashMapOf<Int,String>()
|
||||||
val npcNames = hashMapOf<Int,String>()
|
val npcNames = hashMapOf<Int,String>()
|
||||||
val npcConfigKeys = HashSet<String>()
|
val npcConfigKeys = HashSet<String>()
|
||||||
val npcConfigs = ArrayList<JSONObject>()
|
val npcConfigs = ArrayList<JSONObject>()
|
||||||
|
var npcSpawns = HashMap<Int, ArrayList<NPCSpawn>>()
|
||||||
|
val itemSpawns = HashMap<Int, ArrayList<ItemSpawn>>()
|
||||||
val objConfigKeys = HashSet<String>()
|
val objConfigKeys = HashSet<String>()
|
||||||
val objConfigs = ArrayList<JSONObject>()
|
val objConfigs = ArrayList<JSONObject>()
|
||||||
var itemConfigKeys = HashSet<String>()
|
var itemConfigKeys = HashSet<String>()
|
||||||
|
|
|
||||||
40
src/main/kotlin/cacheops/cache/Cache.kt
vendored
Normal file
40
src/main/kotlin/cacheops/cache/Cache.kt
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
package cacheops.cache
|
||||||
|
|
||||||
|
import com.displee.cache.index.Index255
|
||||||
|
import java.math.BigInteger
|
||||||
|
|
||||||
|
interface Cache {
|
||||||
|
|
||||||
|
var index255: Index255?
|
||||||
|
|
||||||
|
fun getFile(index: Int, archive: Int, file: Int = 0, xtea: IntArray? = null): ByteArray?
|
||||||
|
|
||||||
|
fun getFile(index: Int, name: String, xtea: IntArray? = null): ByteArray?
|
||||||
|
|
||||||
|
fun getArchive(indexId: Int, archiveId: Int): ByteArray?
|
||||||
|
|
||||||
|
fun generateOldVersionTable(): ByteArray
|
||||||
|
|
||||||
|
fun generateNewVersionTable(exponent: BigInteger, modulus: BigInteger): ByteArray
|
||||||
|
|
||||||
|
fun close()
|
||||||
|
|
||||||
|
fun getIndexCrc(indexId: Int): Int
|
||||||
|
|
||||||
|
fun archiveCount(indexId: Int, archiveId: Int): Int
|
||||||
|
|
||||||
|
fun lastFileId(indexId: Int, archive: Int): Int
|
||||||
|
|
||||||
|
fun lastArchiveId(indexId: Int): Int
|
||||||
|
|
||||||
|
fun getArchiveId(index: Int, name: String): Int
|
||||||
|
|
||||||
|
fun getArchiveId(index: Int, archive: Int): Int
|
||||||
|
|
||||||
|
fun getArchives(index: Int): IntArray
|
||||||
|
|
||||||
|
fun write(index: Int, archive: Int, file: Int, data: ByteArray, xteas: IntArray? = null)
|
||||||
|
|
||||||
|
fun update(): Boolean
|
||||||
|
|
||||||
|
}
|
||||||
88
src/main/kotlin/cacheops/cache/CacheDelegate.kt
vendored
Normal file
88
src/main/kotlin/cacheops/cache/CacheDelegate.kt
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
package cacheops.cache
|
||||||
|
|
||||||
|
import com.displee.cache.CacheLibrary
|
||||||
|
import com.displee.cache.index.Index255
|
||||||
|
import java.math.BigInteger
|
||||||
|
|
||||||
|
class CacheDelegate(directory: String) : Cache {
|
||||||
|
|
||||||
|
private val delegate = CacheLibrary(directory)
|
||||||
|
|
||||||
|
init {
|
||||||
|
println("Cache read from $directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
override var index255: Index255?
|
||||||
|
get() = delegate.index255
|
||||||
|
set(value) {
|
||||||
|
delegate.index255 = value
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun getFile(index: Int, archive: Int, file: Int, xtea: IntArray?) =
|
||||||
|
delegate.data(index, archive, file, xtea)
|
||||||
|
|
||||||
|
override fun getFile(index: Int, name: String, xtea: IntArray?) = delegate.data(index, name, xtea)
|
||||||
|
|
||||||
|
override fun getArchive(indexId: Int, archiveId: Int): ByteArray? {
|
||||||
|
val index = if (indexId == 255) index255 else delegate.index(indexId)
|
||||||
|
if (index == null) {
|
||||||
|
println("Unable to find valid index for file request [indexId=$indexId, archiveId=$archiveId]}")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val archiveSector = index.readArchiveSector(archiveId)
|
||||||
|
if (archiveSector == null) {
|
||||||
|
println("Unable to read archive sector $archiveId in index $indexId")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return archiveSector.data
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateOldVersionTable(): ByteArray = delegate.generateOldUkeys()
|
||||||
|
|
||||||
|
override fun generateNewVersionTable(exponent: BigInteger, modulus: BigInteger) = delegate.generateNewUkeys(exponent, modulus)
|
||||||
|
|
||||||
|
override fun close() = delegate.close()
|
||||||
|
|
||||||
|
override fun getIndexCrc(indexId: Int): Int {
|
||||||
|
return delegate.index(indexId).crc
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun archiveCount(indexId: Int, archiveId: Int): Int {
|
||||||
|
return delegate.index(indexId).archive(archiveId)?.fileIds()?.size ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun lastFileId(indexId: Int, archive: Int): Int {
|
||||||
|
return delegate.index(indexId).archive(archive)?.last()?.id ?: -1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun lastArchiveId(indexId: Int): Int {
|
||||||
|
return delegate.index(indexId).last()?.id ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getArchiveId(index: Int, name: String): Int {
|
||||||
|
return delegate.index(index).archiveId(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getArchiveId(index: Int, hash: Int): Int {
|
||||||
|
delegate.index(index).archives().forEach { archive ->
|
||||||
|
if(archive.hashName == hash) {
|
||||||
|
return archive.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getArchives(index: Int): IntArray {
|
||||||
|
return delegate.index(index).archiveIds()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(index: Int, archive: Int, file: Int, data: ByteArray, xteas: IntArray?) {
|
||||||
|
delegate.put(index, archive, file, data, xteas)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(): Boolean {
|
||||||
|
delegate.update()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/main/kotlin/cacheops/cache/Definition.kt
vendored
Normal file
5
src/main/kotlin/cacheops/cache/Definition.kt
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
package cacheops.cache
|
||||||
|
|
||||||
|
interface Definition {
|
||||||
|
var id: Int
|
||||||
|
}
|
||||||
131
src/main/kotlin/cacheops/cache/DefinitionDecoder.kt
vendored
Normal file
131
src/main/kotlin/cacheops/cache/DefinitionDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
package cacheops.cache
|
||||||
|
|
||||||
|
|
||||||
|
import cacheops.cache.buffer.read.BufferReader
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
abstract class DefinitionDecoder<T : Definition>(protected val cache: Cache, internal val index: Int) {
|
||||||
|
|
||||||
|
protected val dataCache = ConcurrentHashMap<Int, T>()
|
||||||
|
|
||||||
|
open val last: Int
|
||||||
|
get() = cache.lastArchiveId(index) * 256 + (cache.archiveCount(index, cache.lastArchiveId(index)))
|
||||||
|
|
||||||
|
val indices: IntRange
|
||||||
|
get() = 0..last
|
||||||
|
|
||||||
|
fun getOrNull(id: Int): T? {
|
||||||
|
var value = dataCache[id]
|
||||||
|
if (value == null) {
|
||||||
|
value = readData(id)
|
||||||
|
if (value != null) {
|
||||||
|
dataCache[id] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun get(id: Int) = getOrNull(id) ?: create()
|
||||||
|
|
||||||
|
protected abstract fun create(): T
|
||||||
|
|
||||||
|
protected open fun getData(archive: Int, file: Int): ByteArray? {
|
||||||
|
return cache.getFile(index, archive, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun readData(id: Int): T? {
|
||||||
|
val archive = getArchive(id)
|
||||||
|
val file = getFile(id)
|
||||||
|
val data = getData(archive, file)
|
||||||
|
if (data != null) {
|
||||||
|
val definition = create()
|
||||||
|
definition.id = id
|
||||||
|
readLoop(definition, BufferReader(data))
|
||||||
|
definition.changeValues()
|
||||||
|
return definition
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun readLoop(definition: T, buffer: Reader) {
|
||||||
|
while (true) {
|
||||||
|
val opcode = buffer.readUnsignedByte()
|
||||||
|
if (opcode == 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
definition.read(opcode, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getFile(id: Int) = id
|
||||||
|
|
||||||
|
open fun getArchive(id: Int) = id
|
||||||
|
|
||||||
|
protected abstract fun T.read(opcode: Int, buffer: Reader)
|
||||||
|
|
||||||
|
protected open fun T.changeValues() {
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun clear() {
|
||||||
|
dataCache.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forEach(function: (T) -> Unit) {
|
||||||
|
for (i in indices) {
|
||||||
|
val def = getOrNull(i) ?: continue
|
||||||
|
function.invoke(def)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun byteToChar(b: Byte): Char {
|
||||||
|
var i = 0xff and b.toInt()
|
||||||
|
require(i != 0) { "Non cp1252 character 0x" + i.toString(16) + " provided" }
|
||||||
|
if (i in 128..159) {
|
||||||
|
var char = UNICODE_TABLE[i - 128].toInt()
|
||||||
|
if (char == 0) {
|
||||||
|
char = 63
|
||||||
|
}
|
||||||
|
i = char
|
||||||
|
}
|
||||||
|
return i.toChar()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var UNICODE_TABLE = charArrayOf(
|
||||||
|
'\u20ac',
|
||||||
|
'\u0000',
|
||||||
|
'\u201a',
|
||||||
|
'\u0192',
|
||||||
|
'\u201e',
|
||||||
|
'\u2026',
|
||||||
|
'\u2020',
|
||||||
|
'\u2021',
|
||||||
|
'\u02c6',
|
||||||
|
'\u2030',
|
||||||
|
'\u0160',
|
||||||
|
'\u2039',
|
||||||
|
'\u0152',
|
||||||
|
'\u0000',
|
||||||
|
'\u017d',
|
||||||
|
'\u0000',
|
||||||
|
'\u0000',
|
||||||
|
'\u2018',
|
||||||
|
'\u2019',
|
||||||
|
'\u201c',
|
||||||
|
'\u201d',
|
||||||
|
'\u2022',
|
||||||
|
'\u2013',
|
||||||
|
'\u2014',
|
||||||
|
'\u02dc',
|
||||||
|
'\u2122',
|
||||||
|
'\u0161',
|
||||||
|
'\u203a',
|
||||||
|
'\u0153',
|
||||||
|
'\u0000',
|
||||||
|
'\u017e',
|
||||||
|
'\u0178'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/main/kotlin/cacheops/cache/DefinitionEncoder.kt
vendored
Normal file
7
src/main/kotlin/cacheops/cache/DefinitionEncoder.kt
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package cacheops.cache
|
||||||
|
|
||||||
|
import cacheops.cache.buffer.write.Writer
|
||||||
|
|
||||||
|
interface DefinitionEncoder<T : Definition> {
|
||||||
|
fun Writer.encode(definition: T)
|
||||||
|
}
|
||||||
223
src/main/kotlin/cacheops/cache/buffer/read/BufferReader.kt
vendored
Normal file
223
src/main/kotlin/cacheops/cache/buffer/read/BufferReader.kt
vendored
Normal file
|
|
@ -0,0 +1,223 @@
|
||||||
|
package cacheops.cache.buffer.read
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
class BufferReader(
|
||||||
|
val buffer: ByteBuffer
|
||||||
|
) : Reader {
|
||||||
|
|
||||||
|
constructor(array: ByteArray) : this(buffer = ByteBuffer.wrap(array))
|
||||||
|
|
||||||
|
override val length: Int = buffer.remaining()
|
||||||
|
private var bitIndex = 0
|
||||||
|
|
||||||
|
override fun readByte(): Int {
|
||||||
|
return buffer.get().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readByteAdd(): Int {
|
||||||
|
return (readByte() - 128).toByte().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readByteInverse(): Int {
|
||||||
|
return -readByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readByteSubtract(): Int {
|
||||||
|
return (readByteInverse() + 128).toByte().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readUnsignedByte(): Int {
|
||||||
|
return readByte() and 0xff
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readShort(): Int {
|
||||||
|
return (readByte() shl 8) or readUnsignedByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readShortAdd(): Int {
|
||||||
|
return (readByte() shl 8) or readUnsignedByteAdd()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readUnsignedShortAdd(): Int {
|
||||||
|
return (readByte() shl 8) or ((readByte() - 128) and 0xff)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readShortLittle(): Int {
|
||||||
|
return readUnsignedByte() or (readByte() shl 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readShortAddLittle(): Int {
|
||||||
|
return readUnsignedByteAdd() or (readByte() shl 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readUnsignedByteAdd(): Int {
|
||||||
|
return (readByte() - 128).toByte().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readUnsignedShort(): Int {
|
||||||
|
return (readUnsignedByte() shl 8) or readUnsignedByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readUnsignedShortLittle(): Int {
|
||||||
|
return readUnsignedByte() or (readUnsignedByte() shl 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readMedium(): Int {
|
||||||
|
return (readByte() shl 16) or (readByte() shl 8) or readUnsignedByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readUnsignedMedium(): Int {
|
||||||
|
return (readUnsignedByte() shl 16) or (readUnsignedByte() shl 8) or readUnsignedByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readInt(): Int {
|
||||||
|
return (readUnsignedByte() shl 24) or (readUnsignedByte() shl 16) or (readUnsignedByte() shl 8) or readUnsignedByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readIntInverseMiddle(): Int {
|
||||||
|
return (readByte() shl 16) or (readByte() shl 24) or readUnsignedByte() or (readByte() shl 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readIntLittle(): Int {
|
||||||
|
return readUnsignedByte() or (readByte() shl 8) or (readByte() shl 16) or (readByte() shl 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readUnsignedIntMiddle(): Int {
|
||||||
|
return (readUnsignedByte() shl 8) or readUnsignedByte() or (readUnsignedByte() shl 24) or (readUnsignedByte() shl 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readSmart(): Int {
|
||||||
|
val peek = readUnsignedByte()
|
||||||
|
return if (peek < 128) {
|
||||||
|
peek and 0xFF
|
||||||
|
} else {
|
||||||
|
(peek shl 8 or readUnsignedByte()) - 32768
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readBigSmart(): Int {
|
||||||
|
val peek = readByte()
|
||||||
|
return if (peek < 0) {
|
||||||
|
((peek shl 24) or (readUnsignedByte() shl 16) or (readUnsignedByte() shl 8) or readUnsignedByte()) and 0x7fffffff
|
||||||
|
} else {
|
||||||
|
val value = (peek shl 8) or readUnsignedByte()
|
||||||
|
if (value == 32767) -1 else value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readLargeSmart(): Int {
|
||||||
|
var baseValue = 0
|
||||||
|
var lastValue = readSmart()
|
||||||
|
while (lastValue == 32767) {
|
||||||
|
lastValue = readSmart()
|
||||||
|
baseValue += 32767
|
||||||
|
}
|
||||||
|
return baseValue + lastValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readLong(): Long {
|
||||||
|
val first = readInt().toLong() and 0xffffffffL
|
||||||
|
val second = readInt().toLong() and 0xffffffffL
|
||||||
|
return second + (first shl 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readString(): String {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
var b: Int
|
||||||
|
while (buffer.hasRemaining()) {
|
||||||
|
b = readByte()
|
||||||
|
if (b == 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sb.append(b.toChar())
|
||||||
|
}
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readBytes(value: ByteArray) {
|
||||||
|
buffer.get(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readBytes(array: ByteArray, offset: Int, length: Int) {
|
||||||
|
buffer.get(array, offset, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun skip(amount: Int) {
|
||||||
|
buffer.position(buffer.position() + amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun position(): Int {
|
||||||
|
return buffer.position()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun position(index: Int) {
|
||||||
|
buffer.position(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun array(): ByteArray {
|
||||||
|
return buffer.array()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readableBytes(): Int {
|
||||||
|
return buffer.remaining()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun startBitAccess(): Reader {
|
||||||
|
bitIndex = buffer.position() * 8
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun finishBitAccess(): Reader {
|
||||||
|
buffer.position((bitIndex + 7) / 8)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
override fun readBits(bitCount: Int): Int {
|
||||||
|
if (bitCount < 0 || bitCount > 32) {
|
||||||
|
throw IllegalArgumentException("Number of bits must be between 1 and 32 inclusive")
|
||||||
|
}
|
||||||
|
|
||||||
|
var bitCount = bitCount
|
||||||
|
var bytePos = bitIndex shr 3
|
||||||
|
var bitOffset = 8 - (bitIndex and 7)
|
||||||
|
var value = 0
|
||||||
|
bitIndex += bitCount
|
||||||
|
|
||||||
|
while (bitCount > bitOffset) {
|
||||||
|
value += buffer.get(bytePos++).toInt() and BIT_MASKS[bitOffset] shl bitCount - bitOffset
|
||||||
|
bitCount -= bitOffset
|
||||||
|
bitOffset = 8
|
||||||
|
}
|
||||||
|
value += if (bitCount == bitOffset) {
|
||||||
|
buffer.get(bytePos).toInt() and BIT_MASKS[bitOffset]
|
||||||
|
} else {
|
||||||
|
buffer.get(bytePos).toInt() shr bitOffset - bitCount and BIT_MASKS[bitCount]
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readIncrSmallSmart(): Int {
|
||||||
|
var var3: Int = readSmart()
|
||||||
|
var value = 0
|
||||||
|
while (32767 == var3) {
|
||||||
|
var3 = readSmart()
|
||||||
|
value += 32767
|
||||||
|
}
|
||||||
|
value += var3
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Bit masks for [readBits]
|
||||||
|
*/
|
||||||
|
private val BIT_MASKS = IntArray(32)
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (i in BIT_MASKS.indices)
|
||||||
|
BIT_MASKS[i] = (1 shl i) - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
116
src/main/kotlin/cacheops/cache/buffer/read/Reader.kt
vendored
Normal file
116
src/main/kotlin/cacheops/cache/buffer/read/Reader.kt
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
package cacheops.cache.buffer.read
|
||||||
|
|
||||||
|
interface Reader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starting length of the packet
|
||||||
|
*/
|
||||||
|
val length: Int
|
||||||
|
|
||||||
|
fun readBoolean() = readByte() == 1
|
||||||
|
|
||||||
|
fun readBooleanAdd() = readByteAdd() == 1
|
||||||
|
|
||||||
|
fun readBooleanInverse() = readByteInverse() == 1
|
||||||
|
|
||||||
|
fun readBooleanSubtract() = readByteSubtract() == 1
|
||||||
|
|
||||||
|
fun readUnsignedBoolean() = readUnsignedByte() == 1
|
||||||
|
|
||||||
|
fun readByte(): Int
|
||||||
|
|
||||||
|
fun readByteAdd(): Int
|
||||||
|
|
||||||
|
fun readByteInverse(): Int
|
||||||
|
|
||||||
|
fun readByteSubtract(): Int
|
||||||
|
|
||||||
|
fun readUnsignedByte(): Int
|
||||||
|
|
||||||
|
fun readUnsignedByteAdd(): Int
|
||||||
|
|
||||||
|
fun readShort(): Int
|
||||||
|
|
||||||
|
fun readShortAdd(): Int
|
||||||
|
|
||||||
|
fun readShortLittle(): Int
|
||||||
|
|
||||||
|
fun readShortAddLittle(): Int
|
||||||
|
|
||||||
|
fun readUnsignedShort(): Int
|
||||||
|
|
||||||
|
fun readUnsignedShortLittle(): Int
|
||||||
|
|
||||||
|
fun readUnsignedShortAdd(): Int
|
||||||
|
|
||||||
|
fun readMedium(): Int
|
||||||
|
|
||||||
|
fun readUnsignedMedium(): Int
|
||||||
|
|
||||||
|
fun readInt(): Int
|
||||||
|
|
||||||
|
fun readIntInverseMiddle(): Int
|
||||||
|
|
||||||
|
fun readIntLittle(): Int
|
||||||
|
|
||||||
|
fun readUnsignedIntMiddle(): Int
|
||||||
|
|
||||||
|
fun readSmart(): Int
|
||||||
|
|
||||||
|
fun readBigSmart(): Int
|
||||||
|
|
||||||
|
fun readLargeSmart(): Int
|
||||||
|
|
||||||
|
fun readLong(): Long
|
||||||
|
|
||||||
|
fun readString(): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads all bytes into [ByteArray]
|
||||||
|
* @param value The array to be written to.
|
||||||
|
*/
|
||||||
|
fun readBytes(value: ByteArray)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads [length] number of bytes starting at [offset] to [array].
|
||||||
|
* @param array The [ByteArray] to be written to
|
||||||
|
* @param offset Destination index
|
||||||
|
* @param length Number of bytes to read
|
||||||
|
*/
|
||||||
|
fun readBytes(array: ByteArray, offset: Int, length: Int = array.size)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips the [amount] bytes.
|
||||||
|
* @param amount Number of bytes to skip
|
||||||
|
*/
|
||||||
|
fun skip(amount: Int)
|
||||||
|
|
||||||
|
fun position(): Int
|
||||||
|
|
||||||
|
fun array(): ByteArray
|
||||||
|
|
||||||
|
fun position(index: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the remaining number of readable bytes.
|
||||||
|
* @return [Int]
|
||||||
|
*/
|
||||||
|
fun readableBytes(): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables individual decoded byte writing aka 'bit access'
|
||||||
|
*/
|
||||||
|
fun startBitAccess(): Reader
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables 'bit access'
|
||||||
|
*/
|
||||||
|
fun finishBitAccess(): Reader
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a bit during 'bit access'
|
||||||
|
* @param bitCount number of bits to be written
|
||||||
|
* @param value bit value to be set
|
||||||
|
*/
|
||||||
|
fun readBits(bitCount: Int): Int
|
||||||
|
}
|
||||||
206
src/main/kotlin/cacheops/cache/buffer/write/BufferWriter.kt
vendored
Normal file
206
src/main/kotlin/cacheops/cache/buffer/write/BufferWriter.kt
vendored
Normal file
|
|
@ -0,0 +1,206 @@
|
||||||
|
package cacheops.cache.buffer.write
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All functions relative to writing directly to a packet are done by this class
|
||||||
|
*/
|
||||||
|
class BufferWriter(
|
||||||
|
capacity: Int = 64,
|
||||||
|
private val buffer: ByteBuffer = ByteBuffer.allocate(capacity)
|
||||||
|
) : Writer {
|
||||||
|
|
||||||
|
private var bitIndex = 0
|
||||||
|
|
||||||
|
override fun writeByte(value: Int) {
|
||||||
|
buffer.put(value.toByte())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeByteAdd(value: Int) {
|
||||||
|
writeByte(value + 128)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeByteInverse(value: Int) {
|
||||||
|
writeByte(-value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeByteSubtract(value: Int) {
|
||||||
|
writeByte(-value + 128)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setByte(index: Int, value: Int) {
|
||||||
|
buffer.put(index, value.toByte())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeShort(value: Int) {
|
||||||
|
writeByte(value shr 8)
|
||||||
|
writeByte(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeShortAdd(value: Int) {
|
||||||
|
writeByte(value shr 8)
|
||||||
|
writeByteAdd(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeShortLittle(value: Int) {
|
||||||
|
writeByte(value)
|
||||||
|
writeByte(value shr 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeShortAddLittle(value: Int) {
|
||||||
|
writeByteAdd(value)
|
||||||
|
writeByte(value shr 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeMedium(value: Int) {
|
||||||
|
writeByte(value shr 16)
|
||||||
|
writeByte(value shr 8)
|
||||||
|
writeByte(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeInt(value: Int) {
|
||||||
|
writeByte(value shr 24)
|
||||||
|
writeByte(value shr 16)
|
||||||
|
writeByte(value shr 8)
|
||||||
|
writeByte(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeIntMiddle(value: Int) {
|
||||||
|
writeByte(value shr 8)
|
||||||
|
writeByte(value)
|
||||||
|
writeByte(value shr 24)
|
||||||
|
writeByte(value shr 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeIntInverse(value: Int) {
|
||||||
|
writeByte(value shr 8)
|
||||||
|
writeByte(value shr 24)
|
||||||
|
writeByte(value shr 16)
|
||||||
|
writeByteInverse(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeIntInverseMiddle(value: Int) {
|
||||||
|
writeByte(value shr 16)
|
||||||
|
writeByte(value shr 24)
|
||||||
|
writeByte(value)
|
||||||
|
writeByte(value shr 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeIntLittle(value: Int) {
|
||||||
|
writeByte(value)
|
||||||
|
writeByte(value shr 8)
|
||||||
|
writeByte(value shr 16)
|
||||||
|
writeByte(value shr 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeIntInverseLittle(value: Int) {
|
||||||
|
writeByteInverse(value)
|
||||||
|
writeByte(value shr 8)
|
||||||
|
writeByte(value shr 16)
|
||||||
|
writeByte(value shr 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeLong(value: Long) {
|
||||||
|
writeByte((value shr 56).toInt())
|
||||||
|
writeByte((value shr 48).toInt())
|
||||||
|
writeByte((value shr 40).toInt())
|
||||||
|
writeByte((value shr 32).toInt())
|
||||||
|
writeByte((value shr 24).toInt())
|
||||||
|
writeByte((value shr 16).toInt())
|
||||||
|
writeByte((value shr 8).toInt())
|
||||||
|
writeByte(value.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeBytes(value: ByteArray) {
|
||||||
|
buffer.put(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeBytes(data: ByteArray, offset: Int, length: Int) {
|
||||||
|
buffer.put(data, offset, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun startBitAccess() {
|
||||||
|
bitIndex = buffer.position() * 8
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun finishBitAccess() {
|
||||||
|
buffer.position((bitIndex + 7) / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeBits(bitCount: Int, value: Boolean) {
|
||||||
|
writeBits(bitCount, if (value) 1 else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeBits(bitCount: Int, value: Int) {
|
||||||
|
var numBits = bitCount
|
||||||
|
|
||||||
|
var byteIndex = bitIndex shr 3
|
||||||
|
var bitOffset = 8 - (bitIndex and 7)
|
||||||
|
bitIndex += numBits
|
||||||
|
|
||||||
|
var tmp: Int
|
||||||
|
var max: Int
|
||||||
|
while (numBits > bitOffset) {
|
||||||
|
tmp = buffer.get(byteIndex).toInt()
|
||||||
|
max = BIT_MASKS[bitOffset]
|
||||||
|
tmp = tmp and max.inv() or (value shr numBits - bitOffset and max)
|
||||||
|
buffer.put(byteIndex++, tmp.toByte())
|
||||||
|
numBits -= bitOffset
|
||||||
|
bitOffset = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = buffer.get(byteIndex).toInt()
|
||||||
|
max = BIT_MASKS[numBits]
|
||||||
|
if (numBits == bitOffset) {
|
||||||
|
tmp = tmp and max.inv() or (value and max)
|
||||||
|
} else {
|
||||||
|
tmp = tmp and (max shl bitOffset - numBits).inv()
|
||||||
|
tmp = tmp or (value and max shl bitOffset - numBits)
|
||||||
|
}
|
||||||
|
buffer.put(byteIndex, tmp.toByte())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun position(): Int {
|
||||||
|
return buffer.position()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun position(index: Int) {
|
||||||
|
buffer.position(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toArray(): ByteArray {
|
||||||
|
val data = ByteArray(position())
|
||||||
|
System.arraycopy(buffer.array(), 0, data, 0, data.size)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun array(): ByteArray {
|
||||||
|
return buffer.array()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
buffer.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remaining(): Int {
|
||||||
|
return buffer.remaining()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeIncrSmallSmart(value: Int) {
|
||||||
|
if (value < 128) {
|
||||||
|
writeByte(value)
|
||||||
|
} else {
|
||||||
|
writeShort(0x8000 or value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val BIT_MASKS = IntArray(32)
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (i in BIT_MASKS.indices) {
|
||||||
|
BIT_MASKS[i] = (1 shl i) - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/main/kotlin/cacheops/cache/buffer/write/Writer.kt
vendored
Normal file
101
src/main/kotlin/cacheops/cache/buffer/write/Writer.kt
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
package cacheops.cache.buffer.write
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All functions relative to writing directly to a packet are done by this class
|
||||||
|
*/
|
||||||
|
interface Writer {
|
||||||
|
|
||||||
|
fun setByte(index: Int, value: Int)
|
||||||
|
|
||||||
|
fun writeByte(value: Int)
|
||||||
|
|
||||||
|
fun writeByteAdd(value: Int)
|
||||||
|
|
||||||
|
fun writeByteInverse(value: Int)
|
||||||
|
|
||||||
|
fun writeByteSubtract(value: Int)
|
||||||
|
|
||||||
|
fun writeByte(value: Boolean) {
|
||||||
|
writeByte(if (value) 1 else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeShort(value: Int)
|
||||||
|
|
||||||
|
fun writeShortAdd(value: Int)
|
||||||
|
|
||||||
|
fun writeShortLittle(value: Int)
|
||||||
|
|
||||||
|
fun writeShortAddLittle(value: Int)
|
||||||
|
|
||||||
|
fun writeMedium(value: Int)
|
||||||
|
|
||||||
|
fun writeInt(value: Int)
|
||||||
|
|
||||||
|
fun writeIntMiddle(value: Int)
|
||||||
|
|
||||||
|
fun writeIntInverse(value: Int)
|
||||||
|
|
||||||
|
fun writeIntInverseMiddle(value: Int)
|
||||||
|
|
||||||
|
fun writeIntLittle(value: Int)
|
||||||
|
|
||||||
|
fun writeIntInverseLittle(value: Int)
|
||||||
|
|
||||||
|
fun writeLong(value: Long)
|
||||||
|
|
||||||
|
fun writeSmart(value: Int) {
|
||||||
|
if (value >= 128) {
|
||||||
|
writeShort(value + 32768)
|
||||||
|
} else {
|
||||||
|
writeByte(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeString(value: String?) {
|
||||||
|
if (value != null) {
|
||||||
|
writeBytes(value.toByteArray())
|
||||||
|
}
|
||||||
|
writeByte(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writePrefixedString(value: String) {
|
||||||
|
writeByte(0)
|
||||||
|
writeBytes(value.toByteArray())
|
||||||
|
writeByte(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeBytes(value: ByteArray)
|
||||||
|
|
||||||
|
fun writeBytes(data: ByteArray, offset: Int, length: Int)
|
||||||
|
|
||||||
|
fun startBitAccess()
|
||||||
|
|
||||||
|
fun finishBitAccess()
|
||||||
|
|
||||||
|
fun writeBits(bitCount: Int, value: Boolean) {
|
||||||
|
writeBits(bitCount, if (value) 1 else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeBits(bitCount: Int, value: Int)
|
||||||
|
|
||||||
|
fun skip(position: Int) {
|
||||||
|
for (i in 0 until position) {
|
||||||
|
writeByte(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun position(): Int
|
||||||
|
|
||||||
|
fun position(index: Int)
|
||||||
|
|
||||||
|
fun toArray(): ByteArray
|
||||||
|
|
||||||
|
fun array(): ByteArray
|
||||||
|
|
||||||
|
fun clear()
|
||||||
|
|
||||||
|
fun remaining(): Int
|
||||||
|
|
||||||
|
fun writeIncrSmallSmart(value: Int)
|
||||||
|
|
||||||
|
}
|
||||||
15
src/main/kotlin/cacheops/cache/definition/ColorPalette.kt
vendored
Normal file
15
src/main/kotlin/cacheops/cache/definition/ColorPalette.kt
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package cacheops.cache.definition
|
||||||
|
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
|
||||||
|
interface ColorPalette {
|
||||||
|
var recolourPalette: ByteArray?
|
||||||
|
|
||||||
|
fun readColourPalette(buffer: Reader) {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
recolourPalette = ByteArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
recolourPalette!![count] = buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/main/kotlin/cacheops/cache/definition/Extra.kt
vendored
Normal file
16
src/main/kotlin/cacheops/cache/definition/Extra.kt
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cacheops.cache.definition
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
interface Extra {
|
||||||
|
|
||||||
|
var extras: Map<String, Any>
|
||||||
|
|
||||||
|
operator fun <T: Any> get(key: String): T = extras.getValue(key) as T
|
||||||
|
|
||||||
|
fun has(key: String) = extras.containsKey(key)
|
||||||
|
|
||||||
|
fun getOrNull(key: String): Any? = extras[key]
|
||||||
|
|
||||||
|
operator fun <T : Any> get(key: String, defaultValue: T) = getOrNull(key) as? T ?: defaultValue
|
||||||
|
|
||||||
|
}
|
||||||
28
src/main/kotlin/cacheops/cache/definition/Parameterized.kt
vendored
Normal file
28
src/main/kotlin/cacheops/cache/definition/Parameterized.kt
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package cacheops.cache.definition
|
||||||
|
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
interface Parameterized {
|
||||||
|
|
||||||
|
var params: HashMap<Long, Any>?
|
||||||
|
|
||||||
|
fun <T : Any> getParam(key: Long) = params?.get(key) as T
|
||||||
|
|
||||||
|
fun <T : Any> getParamOrNull(key: Long) = params?.get(key) as? T
|
||||||
|
|
||||||
|
fun <T : Any> getParam(key: Long, default: T) = params?.get(key) as? T ?: default
|
||||||
|
|
||||||
|
fun readParameters(buffer: Reader) {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
if (length == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
params = HashMap()
|
||||||
|
repeat(length) {
|
||||||
|
val string = buffer.readUnsignedBoolean()
|
||||||
|
val id = buffer.readUnsignedMedium().toLong()
|
||||||
|
params!![id] = if (string) buffer.readString() else buffer.readInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/main/kotlin/cacheops/cache/definition/Recolourable.kt
vendored
Normal file
30
src/main/kotlin/cacheops/cache/definition/Recolourable.kt
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package cacheops.cache.definition
|
||||||
|
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
|
||||||
|
interface Recolourable {
|
||||||
|
var originalColours: ShortArray?
|
||||||
|
var modifiedColours: ShortArray?
|
||||||
|
var originalTextureColours: ShortArray?
|
||||||
|
var modifiedTextureColours: ShortArray?
|
||||||
|
|
||||||
|
fun readColours(buffer: Reader) {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
originalColours = ShortArray(length)
|
||||||
|
modifiedColours = ShortArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
originalColours!![count] = buffer.readUnsignedShort().toShort()
|
||||||
|
modifiedColours!![count] = buffer.readUnsignedShort().toShort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readTextures(buffer: Reader) {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
originalTextureColours = ShortArray(length)
|
||||||
|
modifiedTextureColours = ShortArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
originalTextureColours!![count] = buffer.readUnsignedShort().toShort()
|
||||||
|
modifiedTextureColours!![count] = buffer.readUnsignedShort().toShort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
124
src/main/kotlin/cacheops/cache/definition/data/AnimationDefinition.kt
vendored
Normal file
124
src/main/kotlin/cacheops/cache/definition/data/AnimationDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import cacheops.cache.definition.Extra
|
||||||
|
|
||||||
|
data class AnimationDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var durations: IntArray? = null,
|
||||||
|
var primaryFrames: IntArray? = null,
|
||||||
|
var loopOffset: Int = -1,
|
||||||
|
var interleaveOrder: BooleanArray? = null,
|
||||||
|
var priority: Int = 5,
|
||||||
|
var leftHandItem: Int = -1,
|
||||||
|
var rightHandItem: Int = -1,
|
||||||
|
var maxLoops: Int = 99,
|
||||||
|
var animatingPrecedence: Int = -1,
|
||||||
|
var walkingPrecedence: Int = -1,
|
||||||
|
var replayMode: Int = 2,
|
||||||
|
var secondaryFrames: IntArray? = null,
|
||||||
|
var anIntArrayArray700: Array<IntArray?>? = null,
|
||||||
|
var aBoolean691: Boolean = false,
|
||||||
|
var tweened: Boolean = false,
|
||||||
|
var aBoolean699: Boolean = false,
|
||||||
|
var anIntArray701: IntArray? = null,
|
||||||
|
var anIntArray690: IntArray? = null,
|
||||||
|
var anIntArray692: IntArray? = null,
|
||||||
|
override var extras: Map<String, Any> = emptyMap()
|
||||||
|
) : Definition, Extra {
|
||||||
|
|
||||||
|
val time: Long
|
||||||
|
get() = (durations?.sum() ?: 0) * 20L
|
||||||
|
|
||||||
|
val clientTicks: Int
|
||||||
|
get() {
|
||||||
|
if (durations == null) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var total = 0
|
||||||
|
for (i in 0 until durations!!.size - 3) {
|
||||||
|
total += durations!![i]
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as AnimationDefinition
|
||||||
|
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (durations != null) {
|
||||||
|
if (other.durations == null) return false
|
||||||
|
if (!durations!!.contentEquals(other.durations!!)) return false
|
||||||
|
} else if (other.durations != null) return false
|
||||||
|
if (primaryFrames != null) {
|
||||||
|
if (other.primaryFrames == null) return false
|
||||||
|
if (!primaryFrames!!.contentEquals(other.primaryFrames!!)) return false
|
||||||
|
} else if (other.primaryFrames != null) return false
|
||||||
|
if (loopOffset != other.loopOffset) return false
|
||||||
|
if (interleaveOrder != null) {
|
||||||
|
if (other.interleaveOrder == null) return false
|
||||||
|
if (!interleaveOrder!!.contentEquals(other.interleaveOrder!!)) return false
|
||||||
|
} else if (other.interleaveOrder != null) return false
|
||||||
|
if (priority != other.priority) return false
|
||||||
|
if (leftHandItem != other.leftHandItem) return false
|
||||||
|
if (rightHandItem != other.rightHandItem) return false
|
||||||
|
if (maxLoops != other.maxLoops) return false
|
||||||
|
if (animatingPrecedence != other.animatingPrecedence) return false
|
||||||
|
if (walkingPrecedence != other.walkingPrecedence) return false
|
||||||
|
if (replayMode != other.replayMode) return false
|
||||||
|
if (secondaryFrames != null) {
|
||||||
|
if (other.secondaryFrames == null) return false
|
||||||
|
if (!secondaryFrames!!.contentEquals(other.secondaryFrames!!)) return false
|
||||||
|
} else if (other.secondaryFrames != null) return false
|
||||||
|
if (anIntArrayArray700 != null) {
|
||||||
|
if (other.anIntArrayArray700 == null) return false
|
||||||
|
if (!anIntArrayArray700!!.contentDeepEquals(other.anIntArrayArray700!!)) return false
|
||||||
|
} else if (other.anIntArrayArray700 != null) return false
|
||||||
|
if (aBoolean691 != other.aBoolean691) return false
|
||||||
|
if (tweened != other.tweened) return false
|
||||||
|
if (aBoolean699 != other.aBoolean699) return false
|
||||||
|
if (anIntArray701 != null) {
|
||||||
|
if (other.anIntArray701 == null) return false
|
||||||
|
if (!anIntArray701!!.contentEquals(other.anIntArray701!!)) return false
|
||||||
|
} else if (other.anIntArray701 != null) return false
|
||||||
|
if (anIntArray690 != null) {
|
||||||
|
if (other.anIntArray690 == null) return false
|
||||||
|
if (!anIntArray690!!.contentEquals(other.anIntArray690!!)) return false
|
||||||
|
} else if (other.anIntArray690 != null) return false
|
||||||
|
if (anIntArray692 != null) {
|
||||||
|
if (other.anIntArray692 == null) return false
|
||||||
|
if (!anIntArray692!!.contentEquals(other.anIntArray692!!)) return false
|
||||||
|
} else if (other.anIntArray692 != null) return false
|
||||||
|
if (extras != other.extras) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + (durations?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (primaryFrames?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + loopOffset
|
||||||
|
result = 31 * result + (interleaveOrder?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + priority
|
||||||
|
result = 31 * result + leftHandItem
|
||||||
|
result = 31 * result + rightHandItem
|
||||||
|
result = 31 * result + maxLoops
|
||||||
|
result = 31 * result + animatingPrecedence
|
||||||
|
result = 31 * result + walkingPrecedence
|
||||||
|
result = 31 * result + replayMode
|
||||||
|
result = 31 * result + (secondaryFrames?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anIntArrayArray700?.contentDeepHashCode() ?: 0)
|
||||||
|
result = 31 * result + aBoolean691.hashCode()
|
||||||
|
result = 31 * result + tweened.hashCode()
|
||||||
|
result = 31 * result + aBoolean699.hashCode()
|
||||||
|
result = 31 * result + (anIntArray701?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anIntArray690?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anIntArray692?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + extras.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/kotlin/cacheops/cache/definition/data/AtmosphereDefinition.kt
vendored
Normal file
19
src/main/kotlin/cacheops/cache/definition/data/AtmosphereDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import ext.Vector3f
|
||||||
|
|
||||||
|
//TODO: Maybe finish and come back who knows.
|
||||||
|
data class AtmosphereDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
val DEFAULT_SKY_COLOR: Int = 0x17c439a8,
|
||||||
|
val DEFAULT_SUN_COLOR: Int = 0x36dac459,
|
||||||
|
val DEFAULT_SUN_X_POSITION: Float = 0.69921875F,
|
||||||
|
val DEFAULT_SUN_Y_POSITION: Float = 1.2F,
|
||||||
|
val DEFAULT_SUN_X_ANGLE: Int = -50,
|
||||||
|
val DEFAULT_SUN_Y_ANGLE: Int = -60,
|
||||||
|
val DEFAULT_SUN_Z_ANGLE: Int = -50,
|
||||||
|
val DEFAULT_SUN_ANGLE: Vector3f = Vector3f(DEFAULT_SUN_X_ANGLE.toFloat(), DEFAULT_SUN_Y_ANGLE.toFloat(), DEFAULT_SUN_Z_ANGLE.toFloat()),
|
||||||
|
val DEFAULT_SUN_SHININESS: Float = 1.1523438F,
|
||||||
|
|
||||||
|
) : Definition
|
||||||
9
src/main/kotlin/cacheops/cache/definition/data/BlendedTextureDefinition.kt
vendored
Normal file
9
src/main/kotlin/cacheops/cache/definition/data/BlendedTextureDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
data class BlendedTextureDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var renderOnMap: Boolean = false,
|
||||||
|
var blendedColor: Int = -1
|
||||||
|
) : Definition
|
||||||
16
src/main/kotlin/cacheops/cache/definition/data/BodyDefinition.kt
vendored
Normal file
16
src/main/kotlin/cacheops/cache/definition/data/BodyDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equipment Slots Definition
|
||||||
|
*/
|
||||||
|
@Suppress("ArrayInDataClass")
|
||||||
|
data class BodyDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var disabledSlots: IntArray = IntArray(0),
|
||||||
|
var anInt4506: Int = -1,
|
||||||
|
var anInt4504: Int = -1,
|
||||||
|
var anIntArray4501: IntArray? = null,
|
||||||
|
var anIntArray4507: IntArray? = null
|
||||||
|
) : Definition
|
||||||
71
src/main/kotlin/cacheops/cache/definition/data/ClientScriptDefinition.kt
vendored
Normal file
71
src/main/kotlin/cacheops/cache/definition/data/ClientScriptDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
data class ClientScriptDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var intArgumentCount: Int = 0,
|
||||||
|
var stringVariableCount: Int = 0,
|
||||||
|
var longVariableCount: Int = 0,
|
||||||
|
var intVariableCount: Int = 0,
|
||||||
|
var stringArgumentCount: Int = 0,
|
||||||
|
var longArgumentCount: Int = 0,
|
||||||
|
var switchStatementIndices: Array<List<Pair<Int, Int>>>? = null,
|
||||||
|
var name: String? = null,
|
||||||
|
var instructions: IntArray = intArrayOf(),
|
||||||
|
var stringOperands: Array<String?>? = null,
|
||||||
|
var longOperands: LongArray? = null,
|
||||||
|
var intOperands: IntArray? = null
|
||||||
|
) : Definition {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as ClientScriptDefinition
|
||||||
|
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (intArgumentCount != other.intArgumentCount) return false
|
||||||
|
if (stringVariableCount != other.stringVariableCount) return false
|
||||||
|
if (longVariableCount != other.longVariableCount) return false
|
||||||
|
if (intVariableCount != other.intVariableCount) return false
|
||||||
|
if (stringArgumentCount != other.stringArgumentCount) return false
|
||||||
|
if (longArgumentCount != other.longArgumentCount) return false
|
||||||
|
if (switchStatementIndices != null) {
|
||||||
|
if (other.switchStatementIndices == null) return false
|
||||||
|
if (!switchStatementIndices!!.contentEquals(other.switchStatementIndices!!)) return false
|
||||||
|
} else if (other.switchStatementIndices != null) return false
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (!instructions.contentEquals(other.instructions)) return false
|
||||||
|
if (stringOperands != null) {
|
||||||
|
if (other.stringOperands == null) return false
|
||||||
|
if (!stringOperands!!.contentEquals(other.stringOperands!!)) return false
|
||||||
|
} else if (other.stringOperands != null) return false
|
||||||
|
if (longOperands != null) {
|
||||||
|
if (other.longOperands == null) return false
|
||||||
|
if (!longOperands!!.contentEquals(other.longOperands!!)) return false
|
||||||
|
} else if (other.longOperands != null) return false
|
||||||
|
if (intOperands != null) {
|
||||||
|
if (other.intOperands == null) return false
|
||||||
|
if (!intOperands!!.contentEquals(other.intOperands!!)) return false
|
||||||
|
} else if (other.intOperands != null) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + intArgumentCount
|
||||||
|
result = 31 * result + stringVariableCount
|
||||||
|
result = 31 * result + longVariableCount
|
||||||
|
result = 31 * result + intVariableCount
|
||||||
|
result = 31 * result + stringArgumentCount
|
||||||
|
result = 31 * result + longArgumentCount
|
||||||
|
result = 31 * result + (switchStatementIndices?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (name?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + instructions.contentHashCode()
|
||||||
|
result = 31 * result + (stringOperands?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (longOperands?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (intOperands?.contentHashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/kotlin/cacheops/cache/definition/data/EnumDefinition.kt
vendored
Normal file
19
src/main/kotlin/cacheops/cache/definition/data/EnumDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
data class EnumDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var keyType: Char = 0.toChar(),
|
||||||
|
var valueType: Char = 0.toChar(),
|
||||||
|
var defaultString: String = "null",
|
||||||
|
var defaultInt: Int = 0,
|
||||||
|
var length: Int = 0,
|
||||||
|
var map: HashMap<Int, Any>? = null
|
||||||
|
) : Definition {
|
||||||
|
fun getKey(value: Any) = map?.filterValues { it == value }?.keys?.firstOrNull() ?: -1
|
||||||
|
|
||||||
|
fun getInt(id: Int) = map?.get(id) as? Int ?: defaultInt
|
||||||
|
|
||||||
|
fun getString(id: Int) = map?.get(id) as? String ?: defaultString
|
||||||
|
}
|
||||||
82
src/main/kotlin/cacheops/cache/definition/data/GraphicDefinition.kt
vendored
Normal file
82
src/main/kotlin/cacheops/cache/definition/data/GraphicDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import cacheops.cache.definition.Extra
|
||||||
|
import cacheops.cache.definition.Recolourable
|
||||||
|
|
||||||
|
data class GraphicDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var modelId: Int = 0,
|
||||||
|
var animationId: Int = -1,
|
||||||
|
var sizeXY: Int = 128,
|
||||||
|
var sizeZ: Int = 128,
|
||||||
|
var rotation: Int = 0,
|
||||||
|
var ambience: Int = 0,
|
||||||
|
var contrast: Int = 0,
|
||||||
|
var aByte2381: Byte = 0,
|
||||||
|
var anInt2385: Int = -1,
|
||||||
|
var aBoolean2402: Boolean = false,
|
||||||
|
override var originalColours: ShortArray? = null,
|
||||||
|
override var modifiedColours: ShortArray? = null,
|
||||||
|
override var originalTextureColours: ShortArray? = null,
|
||||||
|
override var modifiedTextureColours: ShortArray? = null,
|
||||||
|
override var extras: Map<String, Any> = emptyMap()
|
||||||
|
) : Definition, Recolourable, Extra {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as GraphicDefinition
|
||||||
|
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (modelId != other.modelId) return false
|
||||||
|
if (animationId != other.animationId) return false
|
||||||
|
if (sizeXY != other.sizeXY) return false
|
||||||
|
if (sizeZ != other.sizeZ) return false
|
||||||
|
if (rotation != other.rotation) return false
|
||||||
|
if (ambience != other.ambience) return false
|
||||||
|
if (contrast != other.contrast) return false
|
||||||
|
if (aByte2381 != other.aByte2381) return false
|
||||||
|
if (anInt2385 != other.anInt2385) return false
|
||||||
|
if (aBoolean2402 != other.aBoolean2402) return false
|
||||||
|
if (originalColours != null) {
|
||||||
|
if (other.originalColours == null) return false
|
||||||
|
if (!originalColours!!.contentEquals(other.originalColours!!)) return false
|
||||||
|
} else if (other.originalColours != null) return false
|
||||||
|
if (modifiedColours != null) {
|
||||||
|
if (other.modifiedColours == null) return false
|
||||||
|
if (!modifiedColours!!.contentEquals(other.modifiedColours!!)) return false
|
||||||
|
} else if (other.modifiedColours != null) return false
|
||||||
|
if (originalTextureColours != null) {
|
||||||
|
if (other.originalTextureColours == null) return false
|
||||||
|
if (!originalTextureColours!!.contentEquals(other.originalTextureColours!!)) return false
|
||||||
|
} else if (other.originalTextureColours != null) return false
|
||||||
|
if (modifiedTextureColours != null) {
|
||||||
|
if (other.modifiedTextureColours == null) return false
|
||||||
|
if (!modifiedTextureColours!!.contentEquals(other.modifiedTextureColours!!)) return false
|
||||||
|
} else if (other.modifiedTextureColours != null) return false
|
||||||
|
if (extras != other.extras) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + modelId
|
||||||
|
result = 31 * result + animationId
|
||||||
|
result = 31 * result + sizeXY
|
||||||
|
result = 31 * result + sizeZ
|
||||||
|
result = 31 * result + rotation
|
||||||
|
result = 31 * result + ambience
|
||||||
|
result = 31 * result + contrast
|
||||||
|
result = 31 * result + aByte2381
|
||||||
|
result = 31 * result + anInt2385
|
||||||
|
result = 31 * result + aBoolean2402.hashCode()
|
||||||
|
result = 31 * result + (originalColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modifiedColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (originalTextureColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modifiedTextureColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + extras.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/main/kotlin/cacheops/cache/definition/data/IndexedSprite.kt
vendored
Normal file
36
src/main/kotlin/cacheops/cache/definition/data/IndexedSprite.kt
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage
|
||||||
|
|
||||||
|
@Suppress("ArrayInDataClass")
|
||||||
|
data class IndexedSprite(
|
||||||
|
var offsetX: Int = 0,
|
||||||
|
var offsetY: Int = 0,
|
||||||
|
var width: Int = 0,
|
||||||
|
var height: Int = 0,
|
||||||
|
var deltaHeight: Int = 0,
|
||||||
|
var deltaWidth: Int = 0,
|
||||||
|
var alpha: ByteArray? = null
|
||||||
|
) {
|
||||||
|
lateinit var raster: ByteArray
|
||||||
|
lateinit var palette: IntArray
|
||||||
|
|
||||||
|
fun toBufferedImage(): BufferedImage {
|
||||||
|
val bi = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
|
||||||
|
for (x in 0 until width) {
|
||||||
|
for (y in 0 until height) {
|
||||||
|
val i = x + y * width
|
||||||
|
if (alpha == null) {
|
||||||
|
val colour = palette[raster[i].toInt() and 255]
|
||||||
|
if (colour != 0) {
|
||||||
|
bi.setRGB(x, y, -16777216 or colour)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bi.setRGB(x, y, palette[raster[i].toInt() and 255] or (alpha!![i].toInt() shl 24))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bi
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
10
src/main/kotlin/cacheops/cache/definition/data/Instructions.kt
vendored
Normal file
10
src/main/kotlin/cacheops/cache/definition/data/Instructions.kt
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
object Instructions {
|
||||||
|
const val PUSH_INT = 0
|
||||||
|
const val PUSH_STRING = 3
|
||||||
|
const val MERGE_STRINGS = 37
|
||||||
|
const val CALL_CS2 = 40
|
||||||
|
const val SWITCH = 51
|
||||||
|
const val GOTO = 6
|
||||||
|
}
|
||||||
409
src/main/kotlin/cacheops/cache/definition/data/InterfaceComponentDefinition.kt
vendored
Normal file
409
src/main/kotlin/cacheops/cache/definition/data/InterfaceComponentDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,409 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import cacheops.cache.definition.Extra
|
||||||
|
|
||||||
|
data class InterfaceComponentDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var type: Int = 0,
|
||||||
|
var unknown: String? = null,
|
||||||
|
var contentType: Int = 0,
|
||||||
|
var basePositionX: Int = 0,
|
||||||
|
var basePositionY: Int = 0,
|
||||||
|
var baseWidth: Int = 0,
|
||||||
|
var baseHeight: Int = 0,
|
||||||
|
var horizontalSizeMode: Byte = 0,
|
||||||
|
var verticalSizeMode: Byte = 0,
|
||||||
|
var horizontalPositionMode: Byte = 0,
|
||||||
|
var verticalPositionMode: Byte = 0,
|
||||||
|
var parent: Int = -1,
|
||||||
|
var hidden: Boolean = false,
|
||||||
|
var disableHover: Boolean = false,
|
||||||
|
var scrollWidth: Int = 0,
|
||||||
|
var scrollHeight: Int = 0,
|
||||||
|
var colour: Int = 0,
|
||||||
|
var filled: Boolean = false,
|
||||||
|
var alpha: Int = 0,
|
||||||
|
var fontId: Int = -1,
|
||||||
|
var monochrome: Boolean = true,
|
||||||
|
var text: String = "",
|
||||||
|
var lineHeight: Int = 0,
|
||||||
|
var horizontalTextAlign: Int = 0,
|
||||||
|
var verticalTextAlign: Int = 0,
|
||||||
|
var shaded: Boolean = false,
|
||||||
|
var lineCount: Int = 0,
|
||||||
|
var defaultImage: Int = -1,
|
||||||
|
var imageRotation: Int = 0,
|
||||||
|
var aBoolean4861: Boolean = false,
|
||||||
|
var imageRepeat: Boolean = false,
|
||||||
|
var rotation: Int = 0,
|
||||||
|
var backgroundColour: Int = 0,
|
||||||
|
var flipVertical: Boolean = false,
|
||||||
|
var flipHorizontal: Boolean = false,
|
||||||
|
var aBoolean4782: Boolean = true,
|
||||||
|
var defaultMediaType: Int = 1,
|
||||||
|
var defaultMediaId: Int = 0,
|
||||||
|
var animated: Boolean = false,
|
||||||
|
var centreType: Boolean = false,
|
||||||
|
var ignoreZBuffer: Boolean = false,
|
||||||
|
var viewportX: Int = 0,
|
||||||
|
var viewportY: Int = 0,
|
||||||
|
var viewportZ: Int = 0,
|
||||||
|
var spritePitch: Int = 0,
|
||||||
|
var spriteRoll: Int = 0,
|
||||||
|
var spriteYaw: Int = 0,
|
||||||
|
var spriteScale: Int = 100,
|
||||||
|
var animation: Int = -1,
|
||||||
|
var viewportWidth: Int = 0,
|
||||||
|
var viewportHeight: Int = 0,
|
||||||
|
var lineWidth: Int = 1,
|
||||||
|
var lineMirrored: Boolean = false,
|
||||||
|
var keyRepeat: ByteArray? = null,
|
||||||
|
var keyCodes: ByteArray? = null,
|
||||||
|
var keyModifiers: IntArray? = null,
|
||||||
|
var clickable: Boolean = false,
|
||||||
|
var name: String = "",
|
||||||
|
var options: Array<String>? = null,
|
||||||
|
var mouseIcon: IntArray? = null,
|
||||||
|
var optionOverride: String? = null,
|
||||||
|
var anInt4708: Int = 0,// Drag type
|
||||||
|
var anInt4795: Int = 0,// Drag slider?
|
||||||
|
var anInt4860: Int = 0,// Friends list icons/buttons?
|
||||||
|
var useOption: String = "",
|
||||||
|
var anInt4698: Int = -1,
|
||||||
|
var anInt4839: Int = -1,// Unused
|
||||||
|
var anInt4761: Int = -1,// Unused
|
||||||
|
var setting: InterfaceComponentSetting = InterfaceComponentSetting(0, -1),
|
||||||
|
val params: HashMap<Long, Any>? = null,
|
||||||
|
var anObjectArray4758: Array<Any>? = null,
|
||||||
|
var mouseEnterHandler: Array<Any>? = null,
|
||||||
|
var mouseExitHandler: Array<Any>? = null,
|
||||||
|
var anObjectArray4771: Array<Any>? = null,
|
||||||
|
var anObjectArray4768: Array<Any>? = null,
|
||||||
|
var stateChangeHandler: Array<Any>? = null,
|
||||||
|
var invUpdateHandler: Array<Any>? = null,
|
||||||
|
var refreshHandler: Array<Any>? = null,
|
||||||
|
var updateHandler: Array<Any>? = null,
|
||||||
|
var anObjectArray4770: Array<Any>? = null,
|
||||||
|
var anObjectArray4751: Array<Any>? = null,
|
||||||
|
var mouseMotionHandler: Array<Any>? = null,
|
||||||
|
var mousePressedHandler: Array<Any>? = null,
|
||||||
|
var mouseDraggedHandler: Array<Any>? = null,
|
||||||
|
var mouseReleasedHandler: Array<Any>? = null,
|
||||||
|
var mouseDragPassHandler: Array<Any>? = null,
|
||||||
|
var anObjectArray4852: Array<Any>? = null,
|
||||||
|
var anObjectArray4711: Array<Any>? = null,
|
||||||
|
var anObjectArray4753: Array<Any>? = null,
|
||||||
|
var anObjectArray4688: Array<Any>? = null,
|
||||||
|
var anObjectArray4775: Array<Any>? = null,
|
||||||
|
var clientVarp: IntArray? = null,
|
||||||
|
var containers: IntArray? = null,
|
||||||
|
var anIntArray4789: IntArray? = null,
|
||||||
|
var clientVarc: IntArray? = null,
|
||||||
|
var anIntArray4805: IntArray? = null,
|
||||||
|
var hasScript: Boolean = false,
|
||||||
|
override var extras: Map<String, Any> = emptyMap()
|
||||||
|
) : Definition, Extra {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as InterfaceComponentDefinition
|
||||||
|
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (type != other.type) return false
|
||||||
|
if (unknown != other.unknown) return false
|
||||||
|
if (contentType != other.contentType) return false
|
||||||
|
if (basePositionX != other.basePositionX) return false
|
||||||
|
if (basePositionY != other.basePositionY) return false
|
||||||
|
if (baseWidth != other.baseWidth) return false
|
||||||
|
if (baseHeight != other.baseHeight) return false
|
||||||
|
if (horizontalSizeMode != other.horizontalSizeMode) return false
|
||||||
|
if (verticalSizeMode != other.verticalSizeMode) return false
|
||||||
|
if (horizontalPositionMode != other.horizontalPositionMode) return false
|
||||||
|
if (verticalPositionMode != other.verticalPositionMode) return false
|
||||||
|
if (parent != other.parent) return false
|
||||||
|
if (hidden != other.hidden) return false
|
||||||
|
if (disableHover != other.disableHover) return false
|
||||||
|
if (scrollWidth != other.scrollWidth) return false
|
||||||
|
if (scrollHeight != other.scrollHeight) return false
|
||||||
|
if (colour != other.colour) return false
|
||||||
|
if (filled != other.filled) return false
|
||||||
|
if (alpha != other.alpha) return false
|
||||||
|
if (fontId != other.fontId) return false
|
||||||
|
if (monochrome != other.monochrome) return false
|
||||||
|
if (text != other.text) return false
|
||||||
|
if (lineHeight != other.lineHeight) return false
|
||||||
|
if (horizontalTextAlign != other.horizontalTextAlign) return false
|
||||||
|
if (verticalTextAlign != other.verticalTextAlign) return false
|
||||||
|
if (shaded != other.shaded) return false
|
||||||
|
if (lineCount != other.lineCount) return false
|
||||||
|
if (defaultImage != other.defaultImage) return false
|
||||||
|
if (imageRotation != other.imageRotation) return false
|
||||||
|
if (aBoolean4861 != other.aBoolean4861) return false
|
||||||
|
if (imageRepeat != other.imageRepeat) return false
|
||||||
|
if (rotation != other.rotation) return false
|
||||||
|
if (backgroundColour != other.backgroundColour) return false
|
||||||
|
if (flipVertical != other.flipVertical) return false
|
||||||
|
if (flipHorizontal != other.flipHorizontal) return false
|
||||||
|
if (aBoolean4782 != other.aBoolean4782) return false
|
||||||
|
if (defaultMediaType != other.defaultMediaType) return false
|
||||||
|
if (defaultMediaId != other.defaultMediaId) return false
|
||||||
|
if (animated != other.animated) return false
|
||||||
|
if (centreType != other.centreType) return false
|
||||||
|
if (ignoreZBuffer != other.ignoreZBuffer) return false
|
||||||
|
if (viewportX != other.viewportX) return false
|
||||||
|
if (viewportY != other.viewportY) return false
|
||||||
|
if (viewportZ != other.viewportZ) return false
|
||||||
|
if (spritePitch != other.spritePitch) return false
|
||||||
|
if (spriteRoll != other.spriteRoll) return false
|
||||||
|
if (spriteYaw != other.spriteYaw) return false
|
||||||
|
if (spriteScale != other.spriteScale) return false
|
||||||
|
if (animation != other.animation) return false
|
||||||
|
if (viewportWidth != other.viewportWidth) return false
|
||||||
|
if (viewportHeight != other.viewportHeight) return false
|
||||||
|
if (lineWidth != other.lineWidth) return false
|
||||||
|
if (lineMirrored != other.lineMirrored) return false
|
||||||
|
if (keyRepeat != null) {
|
||||||
|
if (other.keyRepeat == null) return false
|
||||||
|
if (!keyRepeat!!.contentEquals(other.keyRepeat!!)) return false
|
||||||
|
} else if (other.keyRepeat != null) return false
|
||||||
|
if (keyCodes != null) {
|
||||||
|
if (other.keyCodes == null) return false
|
||||||
|
if (!keyCodes!!.contentEquals(other.keyCodes!!)) return false
|
||||||
|
} else if (other.keyCodes != null) return false
|
||||||
|
if (keyModifiers != null) {
|
||||||
|
if (other.keyModifiers == null) return false
|
||||||
|
if (!keyModifiers!!.contentEquals(other.keyModifiers!!)) return false
|
||||||
|
} else if (other.keyModifiers != null) return false
|
||||||
|
if (clickable != other.clickable) return false
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (options != null) {
|
||||||
|
if (other.options == null) return false
|
||||||
|
if (!options!!.contentEquals(other.options!!)) return false
|
||||||
|
} else if (other.options != null) return false
|
||||||
|
if (mouseIcon != null) {
|
||||||
|
if (other.mouseIcon == null) return false
|
||||||
|
if (!mouseIcon!!.contentEquals(other.mouseIcon!!)) return false
|
||||||
|
} else if (other.mouseIcon != null) return false
|
||||||
|
if (optionOverride != other.optionOverride) return false
|
||||||
|
if (anInt4708 != other.anInt4708) return false
|
||||||
|
if (anInt4795 != other.anInt4795) return false
|
||||||
|
if (anInt4860 != other.anInt4860) return false
|
||||||
|
if (useOption != other.useOption) return false
|
||||||
|
if (anInt4698 != other.anInt4698) return false
|
||||||
|
if (anInt4839 != other.anInt4839) return false
|
||||||
|
if (anInt4761 != other.anInt4761) return false
|
||||||
|
if (setting != other.setting) return false
|
||||||
|
if (params != other.params) return false
|
||||||
|
if (anObjectArray4758 != null) {
|
||||||
|
if (other.anObjectArray4758 == null) return false
|
||||||
|
if (!anObjectArray4758!!.contentEquals(other.anObjectArray4758!!)) return false
|
||||||
|
} else if (other.anObjectArray4758 != null) return false
|
||||||
|
if (mouseEnterHandler != null) {
|
||||||
|
if (other.mouseEnterHandler == null) return false
|
||||||
|
if (!mouseEnterHandler!!.contentEquals(other.mouseEnterHandler!!)) return false
|
||||||
|
} else if (other.mouseEnterHandler != null) return false
|
||||||
|
if (mouseExitHandler != null) {
|
||||||
|
if (other.mouseExitHandler == null) return false
|
||||||
|
if (!mouseExitHandler!!.contentEquals(other.mouseExitHandler!!)) return false
|
||||||
|
} else if (other.mouseExitHandler != null) return false
|
||||||
|
if (anObjectArray4771 != null) {
|
||||||
|
if (other.anObjectArray4771 == null) return false
|
||||||
|
if (!anObjectArray4771!!.contentEquals(other.anObjectArray4771!!)) return false
|
||||||
|
} else if (other.anObjectArray4771 != null) return false
|
||||||
|
if (anObjectArray4768 != null) {
|
||||||
|
if (other.anObjectArray4768 == null) return false
|
||||||
|
if (!anObjectArray4768!!.contentEquals(other.anObjectArray4768!!)) return false
|
||||||
|
} else if (other.anObjectArray4768 != null) return false
|
||||||
|
if (stateChangeHandler != null) {
|
||||||
|
if (other.stateChangeHandler == null) return false
|
||||||
|
if (!stateChangeHandler!!.contentEquals(other.stateChangeHandler!!)) return false
|
||||||
|
} else if (other.stateChangeHandler != null) return false
|
||||||
|
if (invUpdateHandler != null) {
|
||||||
|
if (other.invUpdateHandler == null) return false
|
||||||
|
if (!invUpdateHandler!!.contentEquals(other.invUpdateHandler!!)) return false
|
||||||
|
} else if (other.invUpdateHandler != null) return false
|
||||||
|
if (refreshHandler != null) {
|
||||||
|
if (other.refreshHandler == null) return false
|
||||||
|
if (!refreshHandler!!.contentEquals(other.refreshHandler!!)) return false
|
||||||
|
} else if (other.refreshHandler != null) return false
|
||||||
|
if (updateHandler != null) {
|
||||||
|
if (other.updateHandler == null) return false
|
||||||
|
if (!updateHandler!!.contentEquals(other.updateHandler!!)) return false
|
||||||
|
} else if (other.updateHandler != null) return false
|
||||||
|
if (anObjectArray4770 != null) {
|
||||||
|
if (other.anObjectArray4770 == null) return false
|
||||||
|
if (!anObjectArray4770!!.contentEquals(other.anObjectArray4770!!)) return false
|
||||||
|
} else if (other.anObjectArray4770 != null) return false
|
||||||
|
if (anObjectArray4751 != null) {
|
||||||
|
if (other.anObjectArray4751 == null) return false
|
||||||
|
if (!anObjectArray4751!!.contentEquals(other.anObjectArray4751!!)) return false
|
||||||
|
} else if (other.anObjectArray4751 != null) return false
|
||||||
|
if (mouseMotionHandler != null) {
|
||||||
|
if (other.mouseMotionHandler == null) return false
|
||||||
|
if (!mouseMotionHandler!!.contentEquals(other.mouseMotionHandler!!)) return false
|
||||||
|
} else if (other.mouseMotionHandler != null) return false
|
||||||
|
if (mousePressedHandler != null) {
|
||||||
|
if (other.mousePressedHandler == null) return false
|
||||||
|
if (!mousePressedHandler!!.contentEquals(other.mousePressedHandler!!)) return false
|
||||||
|
} else if (other.mousePressedHandler != null) return false
|
||||||
|
if (mouseDraggedHandler != null) {
|
||||||
|
if (other.mouseDraggedHandler == null) return false
|
||||||
|
if (!mouseDraggedHandler!!.contentEquals(other.mouseDraggedHandler!!)) return false
|
||||||
|
} else if (other.mouseDraggedHandler != null) return false
|
||||||
|
if (mouseReleasedHandler != null) {
|
||||||
|
if (other.mouseReleasedHandler == null) return false
|
||||||
|
if (!mouseReleasedHandler!!.contentEquals(other.mouseReleasedHandler!!)) return false
|
||||||
|
} else if (other.mouseReleasedHandler != null) return false
|
||||||
|
if (mouseDragPassHandler != null) {
|
||||||
|
if (other.mouseDragPassHandler == null) return false
|
||||||
|
if (!mouseDragPassHandler!!.contentEquals(other.mouseDragPassHandler!!)) return false
|
||||||
|
} else if (other.mouseDragPassHandler != null) return false
|
||||||
|
if (anObjectArray4852 != null) {
|
||||||
|
if (other.anObjectArray4852 == null) return false
|
||||||
|
if (!anObjectArray4852!!.contentEquals(other.anObjectArray4852!!)) return false
|
||||||
|
} else if (other.anObjectArray4852 != null) return false
|
||||||
|
if (anObjectArray4711 != null) {
|
||||||
|
if (other.anObjectArray4711 == null) return false
|
||||||
|
if (!anObjectArray4711!!.contentEquals(other.anObjectArray4711!!)) return false
|
||||||
|
} else if (other.anObjectArray4711 != null) return false
|
||||||
|
if (anObjectArray4753 != null) {
|
||||||
|
if (other.anObjectArray4753 == null) return false
|
||||||
|
if (!anObjectArray4753!!.contentEquals(other.anObjectArray4753!!)) return false
|
||||||
|
} else if (other.anObjectArray4753 != null) return false
|
||||||
|
if (anObjectArray4688 != null) {
|
||||||
|
if (other.anObjectArray4688 == null) return false
|
||||||
|
if (!anObjectArray4688!!.contentEquals(other.anObjectArray4688!!)) return false
|
||||||
|
} else if (other.anObjectArray4688 != null) return false
|
||||||
|
if (anObjectArray4775 != null) {
|
||||||
|
if (other.anObjectArray4775 == null) return false
|
||||||
|
if (!anObjectArray4775!!.contentEquals(other.anObjectArray4775!!)) return false
|
||||||
|
} else if (other.anObjectArray4775 != null) return false
|
||||||
|
if (clientVarp != null) {
|
||||||
|
if (other.clientVarp == null) return false
|
||||||
|
if (!clientVarp!!.contentEquals(other.clientVarp!!)) return false
|
||||||
|
} else if (other.clientVarp != null) return false
|
||||||
|
if (containers != null) {
|
||||||
|
if (other.containers == null) return false
|
||||||
|
if (!containers!!.contentEquals(other.containers!!)) return false
|
||||||
|
} else if (other.containers != null) return false
|
||||||
|
if (anIntArray4789 != null) {
|
||||||
|
if (other.anIntArray4789 == null) return false
|
||||||
|
if (!anIntArray4789!!.contentEquals(other.anIntArray4789!!)) return false
|
||||||
|
} else if (other.anIntArray4789 != null) return false
|
||||||
|
if (clientVarc != null) {
|
||||||
|
if (other.clientVarc == null) return false
|
||||||
|
if (!clientVarc!!.contentEquals(other.clientVarc!!)) return false
|
||||||
|
} else if (other.clientVarc != null) return false
|
||||||
|
if (anIntArray4805 != null) {
|
||||||
|
if (other.anIntArray4805 == null) return false
|
||||||
|
if (!anIntArray4805!!.contentEquals(other.anIntArray4805!!)) return false
|
||||||
|
} else if (other.anIntArray4805 != null) return false
|
||||||
|
if (hasScript != other.hasScript) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + type
|
||||||
|
result = 31 * result + (unknown?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + contentType
|
||||||
|
result = 31 * result + basePositionX
|
||||||
|
result = 31 * result + basePositionY
|
||||||
|
result = 31 * result + baseWidth
|
||||||
|
result = 31 * result + baseHeight
|
||||||
|
result = 31 * result + horizontalSizeMode
|
||||||
|
result = 31 * result + verticalSizeMode
|
||||||
|
result = 31 * result + horizontalPositionMode
|
||||||
|
result = 31 * result + verticalPositionMode
|
||||||
|
result = 31 * result + parent
|
||||||
|
result = 31 * result + hidden.hashCode()
|
||||||
|
result = 31 * result + disableHover.hashCode()
|
||||||
|
result = 31 * result + scrollWidth
|
||||||
|
result = 31 * result + scrollHeight
|
||||||
|
result = 31 * result + colour
|
||||||
|
result = 31 * result + filled.hashCode()
|
||||||
|
result = 31 * result + alpha
|
||||||
|
result = 31 * result + fontId
|
||||||
|
result = 31 * result + monochrome.hashCode()
|
||||||
|
result = 31 * result + text.hashCode()
|
||||||
|
result = 31 * result + lineHeight
|
||||||
|
result = 31 * result + horizontalTextAlign
|
||||||
|
result = 31 * result + verticalTextAlign
|
||||||
|
result = 31 * result + shaded.hashCode()
|
||||||
|
result = 31 * result + lineCount
|
||||||
|
result = 31 * result + defaultImage
|
||||||
|
result = 31 * result + imageRotation
|
||||||
|
result = 31 * result + aBoolean4861.hashCode()
|
||||||
|
result = 31 * result + imageRepeat.hashCode()
|
||||||
|
result = 31 * result + rotation
|
||||||
|
result = 31 * result + backgroundColour
|
||||||
|
result = 31 * result + flipVertical.hashCode()
|
||||||
|
result = 31 * result + flipHorizontal.hashCode()
|
||||||
|
result = 31 * result + aBoolean4782.hashCode()
|
||||||
|
result = 31 * result + defaultMediaType
|
||||||
|
result = 31 * result + defaultMediaId
|
||||||
|
result = 31 * result + animated.hashCode()
|
||||||
|
result = 31 * result + centreType.hashCode()
|
||||||
|
result = 31 * result + ignoreZBuffer.hashCode()
|
||||||
|
result = 31 * result + viewportX
|
||||||
|
result = 31 * result + viewportY
|
||||||
|
result = 31 * result + viewportZ
|
||||||
|
result = 31 * result + spritePitch
|
||||||
|
result = 31 * result + spriteRoll
|
||||||
|
result = 31 * result + spriteYaw
|
||||||
|
result = 31 * result + spriteScale
|
||||||
|
result = 31 * result + animation
|
||||||
|
result = 31 * result + viewportWidth
|
||||||
|
result = 31 * result + viewportHeight
|
||||||
|
result = 31 * result + lineWidth
|
||||||
|
result = 31 * result + lineMirrored.hashCode()
|
||||||
|
result = 31 * result + (keyRepeat?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (keyCodes?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (keyModifiers?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + clickable.hashCode()
|
||||||
|
result = 31 * result + name.hashCode()
|
||||||
|
result = 31 * result + (options?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (mouseIcon?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (optionOverride?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + anInt4708
|
||||||
|
result = 31 * result + anInt4795
|
||||||
|
result = 31 * result + anInt4860
|
||||||
|
result = 31 * result + useOption.hashCode()
|
||||||
|
result = 31 * result + anInt4698
|
||||||
|
result = 31 * result + anInt4839
|
||||||
|
result = 31 * result + anInt4761
|
||||||
|
result = 31 * result + setting.hashCode()
|
||||||
|
result = 31 * result + (params?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4758?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (mouseEnterHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (mouseExitHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4771?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4768?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (stateChangeHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (invUpdateHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (refreshHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (updateHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4770?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4751?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (mouseMotionHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (mousePressedHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (mouseDraggedHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (mouseReleasedHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (mouseDragPassHandler?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4852?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4711?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4753?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4688?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anObjectArray4775?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (clientVarp?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (containers?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anIntArray4789?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (clientVarc?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (anIntArray4805?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + hasScript.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/main/kotlin/cacheops/cache/definition/data/InterfaceComponentSetting.kt
vendored
Normal file
27
src/main/kotlin/cacheops/cache/definition/data/InterfaceComponentSetting.kt
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
data class InterfaceComponentSetting(var setting: Int, var anInt7413: Int) {
|
||||||
|
fun method2743(): Int {
|
||||||
|
return setting and 0x3fda8 shr 11
|
||||||
|
}
|
||||||
|
|
||||||
|
fun method2744(): Boolean {
|
||||||
|
return 0x1 and setting shr 22 != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun method2745(): Int {
|
||||||
|
return 0x1d36c1 and setting shr 18
|
||||||
|
}
|
||||||
|
|
||||||
|
fun method2746(): Boolean {
|
||||||
|
return 0x1 and setting != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun method2747(): Boolean {
|
||||||
|
return 0x1 and setting shr 21 != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unlockedSlot(slot: Int): Boolean {
|
||||||
|
return 0x1 and setting shr slot + 1 != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/kotlin/cacheops/cache/definition/data/InterfaceDefinition.kt
vendored
Normal file
11
src/main/kotlin/cacheops/cache/definition/data/InterfaceDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import cacheops.cache.definition.Extra
|
||||||
|
|
||||||
|
@Suppress("ArrayInDataClass")
|
||||||
|
data class InterfaceDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var components: Map<Int, InterfaceComponentDefinition>? = null,
|
||||||
|
override var extras: Map<String, Any> = emptyMap()
|
||||||
|
) : Definition, Extra
|
||||||
249
src/main/kotlin/cacheops/cache/definition/data/ItemDefinition.kt
vendored
Normal file
249
src/main/kotlin/cacheops/cache/definition/data/ItemDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,249 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import cacheops.cache.definition.ColorPalette
|
||||||
|
import cacheops.cache.definition.Extra
|
||||||
|
import cacheops.cache.definition.Parameterized
|
||||||
|
import cacheops.cache.definition.Recolourable
|
||||||
|
|
||||||
|
data class ItemDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var modelId: Int = 0,
|
||||||
|
var name: String = "null",
|
||||||
|
var spriteScale: Int = 2000,
|
||||||
|
var spritePitch: Int = 0,
|
||||||
|
var spriteCameraRoll: Int = 0,
|
||||||
|
var spriteTranslateX: Int = 0,
|
||||||
|
var spriteTranslateY: Int = 0,
|
||||||
|
var stackable: Int = 0,
|
||||||
|
var cost: Int = 1,
|
||||||
|
var members: Boolean = false,
|
||||||
|
var multiStackSize: Int = -1,
|
||||||
|
var primaryMaleModel: Int = -1,
|
||||||
|
var secondaryMaleModel: Int = -1,
|
||||||
|
var primaryFemaleModel: Int = -1,
|
||||||
|
var secondaryFemaleModel: Int = -1,
|
||||||
|
var floorOptions: Array<String?> = arrayOf(null, null, "Take", null, null, "Examine"),
|
||||||
|
var options: Array<String?> = arrayOf(null, null, null, null, "Drop"),
|
||||||
|
override var originalColours: ShortArray? = null,
|
||||||
|
override var modifiedColours: ShortArray? = null,
|
||||||
|
override var originalTextureColours: ShortArray? = null,
|
||||||
|
override var modifiedTextureColours: ShortArray? = null,
|
||||||
|
override var recolourPalette: ByteArray? = null,
|
||||||
|
var exchangeable: Boolean = false,
|
||||||
|
var tertiaryMaleModel: Int = -1,
|
||||||
|
var tertiaryFemaleModel: Int = -1,
|
||||||
|
var primaryMaleDialogueHead: Int = -1,
|
||||||
|
var primaryFemaleDialogueHead: Int = -1,
|
||||||
|
var secondaryMaleDialogueHead: Int = -1,
|
||||||
|
var secondaryFemaleDialogueHead: Int = -1,
|
||||||
|
var spriteCameraYaw: Int = 0,
|
||||||
|
var dummyItem: Int = 0,
|
||||||
|
var noteId: Int = -1,
|
||||||
|
var notedTemplateId: Int = -1,
|
||||||
|
var stackIds: IntArray? = null,
|
||||||
|
var stackAmounts: IntArray? = null,
|
||||||
|
var floorScaleX: Int = 128,
|
||||||
|
var floorScaleZ: Int = 128,
|
||||||
|
var floorScaleY: Int = 128,
|
||||||
|
var ambience: Int = 0,
|
||||||
|
var diffusion: Int = 0,
|
||||||
|
var team: Int = 0,
|
||||||
|
var lendId: Int = -1,
|
||||||
|
var lendTemplateId: Int = -1,
|
||||||
|
var maleWieldX: Int = 0,
|
||||||
|
var maleWieldZ: Int = 0,
|
||||||
|
var maleWieldY: Int = 0,
|
||||||
|
var femaleWieldX: Int = 0,
|
||||||
|
var femaleWieldZ: Int = 0,
|
||||||
|
var femaleWieldY: Int = 0,
|
||||||
|
var primaryCursorOpcode: Int = -1,
|
||||||
|
var primaryCursor: Int = -1,
|
||||||
|
var secondaryCursorOpcode: Int = -1,
|
||||||
|
var secondaryCursor: Int = -1,
|
||||||
|
var primaryInterfaceCursorOpcode: Int = -1,
|
||||||
|
var primaryInterfaceCursor: Int = -1,
|
||||||
|
var secondaryInterfaceCursorOpcode: Int = -1,
|
||||||
|
var secondaryInterfaceCursor: Int = -1,
|
||||||
|
var campaigns: IntArray? = null,
|
||||||
|
var pickSizeShift: Int = 0,
|
||||||
|
var singleNoteId: Int = -1,
|
||||||
|
var singleNoteTemplateId: Int = -1,
|
||||||
|
override var params: HashMap<Long, Any>? = null,
|
||||||
|
override var extras: Map<String, Any> = emptyMap()
|
||||||
|
) : Definition, Recolourable, ColorPalette, Parameterized, Extra {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as ItemDefinition
|
||||||
|
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (modelId != other.modelId) return false
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (spriteScale != other.spriteScale) return false
|
||||||
|
if (spritePitch != other.spritePitch) return false
|
||||||
|
if (spriteCameraRoll != other.spriteCameraRoll) return false
|
||||||
|
if (spriteTranslateX != other.spriteTranslateX) return false
|
||||||
|
if (spriteTranslateY != other.spriteTranslateY) return false
|
||||||
|
if (stackable != other.stackable) return false
|
||||||
|
if (cost != other.cost) return false
|
||||||
|
if (members != other.members) return false
|
||||||
|
if (multiStackSize != other.multiStackSize) return false
|
||||||
|
if (primaryMaleModel != other.primaryMaleModel) return false
|
||||||
|
if (secondaryMaleModel != other.secondaryMaleModel) return false
|
||||||
|
if (primaryFemaleModel != other.primaryFemaleModel) return false
|
||||||
|
if (secondaryFemaleModel != other.secondaryFemaleModel) return false
|
||||||
|
if (!floorOptions.contentEquals(other.floorOptions)) return false
|
||||||
|
if (!options.contentEquals(other.options)) return false
|
||||||
|
if (originalColours != null) {
|
||||||
|
if (other.originalColours == null) return false
|
||||||
|
if (!originalColours!!.contentEquals(other.originalColours!!)) return false
|
||||||
|
} else if (other.originalColours != null) return false
|
||||||
|
if (modifiedColours != null) {
|
||||||
|
if (other.modifiedColours == null) return false
|
||||||
|
if (!modifiedColours!!.contentEquals(other.modifiedColours!!)) return false
|
||||||
|
} else if (other.modifiedColours != null) return false
|
||||||
|
if (originalTextureColours != null) {
|
||||||
|
if (other.originalTextureColours == null) return false
|
||||||
|
if (!originalTextureColours!!.contentEquals(other.originalTextureColours!!)) return false
|
||||||
|
} else if (other.originalTextureColours != null) return false
|
||||||
|
if (modifiedTextureColours != null) {
|
||||||
|
if (other.modifiedTextureColours == null) return false
|
||||||
|
if (!modifiedTextureColours!!.contentEquals(other.modifiedTextureColours!!)) return false
|
||||||
|
} else if (other.modifiedTextureColours != null) return false
|
||||||
|
if (recolourPalette != null) {
|
||||||
|
if (other.recolourPalette == null) return false
|
||||||
|
if (!recolourPalette!!.contentEquals(other.recolourPalette!!)) return false
|
||||||
|
} else if (other.recolourPalette != null) return false
|
||||||
|
if (exchangeable != other.exchangeable) return false
|
||||||
|
if (tertiaryMaleModel != other.tertiaryMaleModel) return false
|
||||||
|
if (tertiaryFemaleModel != other.tertiaryFemaleModel) return false
|
||||||
|
if (primaryMaleDialogueHead != other.primaryMaleDialogueHead) return false
|
||||||
|
if (primaryFemaleDialogueHead != other.primaryFemaleDialogueHead) return false
|
||||||
|
if (secondaryMaleDialogueHead != other.secondaryMaleDialogueHead) return false
|
||||||
|
if (secondaryFemaleDialogueHead != other.secondaryFemaleDialogueHead) return false
|
||||||
|
if (spriteCameraYaw != other.spriteCameraYaw) return false
|
||||||
|
if (dummyItem != other.dummyItem) return false
|
||||||
|
if (noteId != other.noteId) return false
|
||||||
|
if (notedTemplateId != other.notedTemplateId) return false
|
||||||
|
if (stackIds != null) {
|
||||||
|
if (other.stackIds == null) return false
|
||||||
|
if (!stackIds!!.contentEquals(other.stackIds!!)) return false
|
||||||
|
} else if (other.stackIds != null) return false
|
||||||
|
if (stackAmounts != null) {
|
||||||
|
if (other.stackAmounts == null) return false
|
||||||
|
if (!stackAmounts!!.contentEquals(other.stackAmounts!!)) return false
|
||||||
|
} else if (other.stackAmounts != null) return false
|
||||||
|
if (floorScaleX != other.floorScaleX) return false
|
||||||
|
if (floorScaleZ != other.floorScaleZ) return false
|
||||||
|
if (floorScaleY != other.floorScaleY) return false
|
||||||
|
if (ambience != other.ambience) return false
|
||||||
|
if (diffusion != other.diffusion) return false
|
||||||
|
if (team != other.team) return false
|
||||||
|
if (lendId != other.lendId) return false
|
||||||
|
if (lendTemplateId != other.lendTemplateId) return false
|
||||||
|
if (maleWieldX != other.maleWieldX) return false
|
||||||
|
if (maleWieldZ != other.maleWieldZ) return false
|
||||||
|
if (maleWieldY != other.maleWieldY) return false
|
||||||
|
if (femaleWieldX != other.femaleWieldX) return false
|
||||||
|
if (femaleWieldZ != other.femaleWieldZ) return false
|
||||||
|
if (femaleWieldY != other.femaleWieldY) return false
|
||||||
|
if (primaryCursorOpcode != other.primaryCursorOpcode) return false
|
||||||
|
if (primaryCursor != other.primaryCursor) return false
|
||||||
|
if (secondaryCursorOpcode != other.secondaryCursorOpcode) return false
|
||||||
|
if (secondaryCursor != other.secondaryCursor) return false
|
||||||
|
if (primaryInterfaceCursorOpcode != other.primaryInterfaceCursorOpcode) return false
|
||||||
|
if (primaryInterfaceCursor != other.primaryInterfaceCursor) return false
|
||||||
|
if (secondaryInterfaceCursorOpcode != other.secondaryInterfaceCursorOpcode) return false
|
||||||
|
if (secondaryInterfaceCursor != other.secondaryInterfaceCursor) return false
|
||||||
|
if (campaigns != null) {
|
||||||
|
if (other.campaigns == null) return false
|
||||||
|
if (!campaigns!!.contentEquals(other.campaigns!!)) return false
|
||||||
|
} else if (other.campaigns != null) return false
|
||||||
|
if (pickSizeShift != other.pickSizeShift) return false
|
||||||
|
if (singleNoteId != other.singleNoteId) return false
|
||||||
|
if (singleNoteTemplateId != other.singleNoteTemplateId) return false
|
||||||
|
if (params != other.params) return false
|
||||||
|
if (extras != other.extras) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + modelId
|
||||||
|
result = 31 * result + name.hashCode()
|
||||||
|
result = 31 * result + spriteScale
|
||||||
|
result = 31 * result + spritePitch
|
||||||
|
result = 31 * result + spriteCameraRoll
|
||||||
|
result = 31 * result + spriteTranslateX
|
||||||
|
result = 31 * result + spriteTranslateY
|
||||||
|
result = 31 * result + stackable
|
||||||
|
result = 31 * result + cost
|
||||||
|
result = 31 * result + members.hashCode()
|
||||||
|
result = 31 * result + multiStackSize
|
||||||
|
result = 31 * result + primaryMaleModel
|
||||||
|
result = 31 * result + secondaryMaleModel
|
||||||
|
result = 31 * result + primaryFemaleModel
|
||||||
|
result = 31 * result + secondaryFemaleModel
|
||||||
|
result = 31 * result + floorOptions.contentHashCode()
|
||||||
|
result = 31 * result + options.contentHashCode()
|
||||||
|
result = 31 * result + (originalColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modifiedColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (originalTextureColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modifiedTextureColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (recolourPalette?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + exchangeable.hashCode()
|
||||||
|
result = 31 * result + tertiaryMaleModel
|
||||||
|
result = 31 * result + tertiaryFemaleModel
|
||||||
|
result = 31 * result + primaryMaleDialogueHead
|
||||||
|
result = 31 * result + primaryFemaleDialogueHead
|
||||||
|
result = 31 * result + secondaryMaleDialogueHead
|
||||||
|
result = 31 * result + secondaryFemaleDialogueHead
|
||||||
|
result = 31 * result + spriteCameraYaw
|
||||||
|
result = 31 * result + dummyItem
|
||||||
|
result = 31 * result + noteId
|
||||||
|
result = 31 * result + notedTemplateId
|
||||||
|
result = 31 * result + (stackIds?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (stackAmounts?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + floorScaleX
|
||||||
|
result = 31 * result + floorScaleZ
|
||||||
|
result = 31 * result + floorScaleY
|
||||||
|
result = 31 * result + ambience
|
||||||
|
result = 31 * result + diffusion
|
||||||
|
result = 31 * result + team
|
||||||
|
result = 31 * result + lendId
|
||||||
|
result = 31 * result + lendTemplateId
|
||||||
|
result = 31 * result + maleWieldX
|
||||||
|
result = 31 * result + maleWieldZ
|
||||||
|
result = 31 * result + maleWieldY
|
||||||
|
result = 31 * result + femaleWieldX
|
||||||
|
result = 31 * result + femaleWieldZ
|
||||||
|
result = 31 * result + femaleWieldY
|
||||||
|
result = 31 * result + primaryCursorOpcode
|
||||||
|
result = 31 * result + primaryCursor
|
||||||
|
result = 31 * result + secondaryCursorOpcode
|
||||||
|
result = 31 * result + secondaryCursor
|
||||||
|
result = 31 * result + primaryInterfaceCursorOpcode
|
||||||
|
result = 31 * result + primaryInterfaceCursor
|
||||||
|
result = 31 * result + secondaryInterfaceCursorOpcode
|
||||||
|
result = 31 * result + secondaryInterfaceCursor
|
||||||
|
result = 31 * result + (campaigns?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + pickSizeShift
|
||||||
|
result = 31 * result + singleNoteId
|
||||||
|
result = 31 * result + singleNoteTemplateId
|
||||||
|
result = 31 * result + (params?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + extras.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
val noted: Boolean
|
||||||
|
get() = notedTemplateId != -1
|
||||||
|
|
||||||
|
val lent: Boolean
|
||||||
|
get() = lendTemplateId != -1
|
||||||
|
|
||||||
|
val singleNote: Boolean
|
||||||
|
get() = singleNoteTemplateId != -1
|
||||||
|
|
||||||
|
}
|
||||||
24
src/main/kotlin/cacheops/cache/definition/data/MapDefinition.kt
vendored
Normal file
24
src/main/kotlin/cacheops/cache/definition/data/MapDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
data class MapDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
val tiles: MutableMap<Int, MapTile> = mutableMapOf(),
|
||||||
|
val objects: MutableList<MapObject> = mutableListOf()
|
||||||
|
) : Definition {
|
||||||
|
|
||||||
|
fun getTile(localX: Int, localY: Int, plane: Int) = tiles[getHash(localX, localY, plane)] ?: MapTile.EMPTY
|
||||||
|
|
||||||
|
fun setTile(localX: Int, localY: Int, plane: Int, tile: MapTile) {
|
||||||
|
tiles[getHash(localX, localY, plane)] = tile
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getHash(localX: Int, localY: Int, plane: Int): Int {
|
||||||
|
return localY + (localX shl 6) + (plane shl 12)
|
||||||
|
}
|
||||||
|
fun getLocalX(tile: Int) = tile shr 6 and 0x3f
|
||||||
|
fun getLocalY(tile: Int) = tile and 0x3f
|
||||||
|
fun getPlane(tile: Int) = tile shr 12 and 0x3
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/main/kotlin/cacheops/cache/definition/data/MapObject.kt
vendored
Normal file
43
src/main/kotlin/cacheops/cache/definition/data/MapObject.kt
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
inline class MapObject(val hash: Long) {
|
||||||
|
|
||||||
|
constructor(id: Int, x: Int, y: Int, plane: Int, type: Int, rotation: Int) : this(getHash(id, x, y, plane, type, rotation))
|
||||||
|
|
||||||
|
val id: Int
|
||||||
|
get() = getId(hash)
|
||||||
|
val x: Int
|
||||||
|
get() = getX(hash)
|
||||||
|
val y: Int
|
||||||
|
get() = getY(hash)
|
||||||
|
val plane: Int
|
||||||
|
get() = getPlane(hash)
|
||||||
|
val type: Int
|
||||||
|
get() = getType(hash)
|
||||||
|
val rotation: Int
|
||||||
|
get() = getRotation(hash)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun getHash(id: Int, x: Int, y: Int, plane: Int, type: Int, rotation: Int): Long {
|
||||||
|
return getHash(id.toLong(), x.toLong(), y.toLong(), plane.toLong(), type.toLong(), rotation.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHash(id: Long, x: Long, y: Long, plane: Long, type: Long, rotation: Long): Long {
|
||||||
|
return rotation + (type shl 2) + (plane shl 7) + (y shl 9) + (x shl 23) + (id shl 37)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getId(hash: Long): Int = (hash shr 37 and 0x1ffff).toInt()
|
||||||
|
|
||||||
|
fun getX(hash: Long): Int = (hash shr 23 and 0x3fff).toInt()
|
||||||
|
|
||||||
|
fun getY(hash: Long): Int = (hash shr 9 and 0x3fff).toInt()
|
||||||
|
|
||||||
|
fun getPlane(hash: Long): Int = (hash shr 7 and 0x3).toInt()
|
||||||
|
|
||||||
|
fun getType(hash: Long): Int = (hash shr 2 and 0x1f).toInt()
|
||||||
|
|
||||||
|
fun getRotation(hash: Long): Int = (hash and 0x3).toInt()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
58
src/main/kotlin/cacheops/cache/definition/data/MapTile.kt
vendored
Normal file
58
src/main/kotlin/cacheops/cache/definition/data/MapTile.kt
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
inline class MapTile(val hash: Long) {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
height: Int = 0,
|
||||||
|
opcode: Int = 0,
|
||||||
|
overlay: Int = 0,
|
||||||
|
path: Int = 0,
|
||||||
|
rotation: Int = 0,
|
||||||
|
settings: Int = 0,
|
||||||
|
underlay: Int = 0
|
||||||
|
) : this(getHash(height, opcode, overlay, path, rotation, settings, underlay))
|
||||||
|
|
||||||
|
val height: Int
|
||||||
|
get() = getHeight(hash)
|
||||||
|
|
||||||
|
val attrOpcode: Int
|
||||||
|
get() = getOpcode(hash)
|
||||||
|
|
||||||
|
val overlayId: Int
|
||||||
|
get() = getOverlay(hash)
|
||||||
|
|
||||||
|
val overlayPath: Int
|
||||||
|
get() = getPath(hash)
|
||||||
|
|
||||||
|
val overlayRotation: Int
|
||||||
|
get() = getRotation(hash)
|
||||||
|
|
||||||
|
val settings: Int
|
||||||
|
get() = getSettings(hash)
|
||||||
|
|
||||||
|
val underlayId: Int
|
||||||
|
get() = getUnderlay(hash)
|
||||||
|
|
||||||
|
fun isTile(flag: Int) = settings and flag == flag
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val EMPTY = MapTile()
|
||||||
|
|
||||||
|
fun getHash(height: Int, opcode: Int, overlay: Int, path: Int, rotation: Int, settings: Int, underlay: Int): Long {
|
||||||
|
return getHash(height.toLong(), opcode.toLong(), overlay.toLong(), path.toLong(), rotation.toLong(), settings.toLong(), underlay.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHash(height: Long, opcode: Long, overlay: Long, path: Long, rotation: Long, settings: Long, underlay: Long): Long {
|
||||||
|
return height + (opcode shl 8) + (overlay shl 16) + (path shl 24) + (rotation shl 32) + (settings shl 40) + (underlay shl 48)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHeight(hash: Long): Int = (hash and 0xff).toInt()
|
||||||
|
fun getOpcode(hash: Long): Int = (hash shr 8 and 0xff).toInt()
|
||||||
|
fun getOverlay(hash: Long): Int = (hash shr 16 and 0xff).toInt()
|
||||||
|
fun getPath(hash: Long): Int = (hash shr 24 and 0xff).toInt()
|
||||||
|
fun getRotation(hash: Long): Int = (hash shr 32 and 0xff).toInt()
|
||||||
|
fun getSettings(hash: Long): Int = (hash shr 40 and 0xff).toInt()
|
||||||
|
fun getUnderlay(hash: Long): Int = (hash shr 48 and 0xff).toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
250
src/main/kotlin/cacheops/cache/definition/data/NPCDefinition.kt
vendored
Normal file
250
src/main/kotlin/cacheops/cache/definition/data/NPCDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import cacheops.cache.definition.Extra
|
||||||
|
import cacheops.cache.definition.Parameterized
|
||||||
|
import cacheops.cache.definition.Recolourable
|
||||||
|
|
||||||
|
data class NPCDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var modelIds: IntArray? = null,
|
||||||
|
var name: String = "null",
|
||||||
|
var size: Int = 1,
|
||||||
|
var options: Array<String?> = arrayOf(null, null, null, null, null, "Examine"),
|
||||||
|
override var originalColours: ShortArray? = null,
|
||||||
|
override var modifiedColours: ShortArray? = null,
|
||||||
|
override var originalTextureColours: ShortArray? = null,
|
||||||
|
override var modifiedTextureColours: ShortArray? = null,
|
||||||
|
var recolourPalette: ByteArray? = null,
|
||||||
|
var dialogueModels: IntArray? = null,
|
||||||
|
var drawMinimapDot: Boolean = true,
|
||||||
|
var combat: Int = -1,
|
||||||
|
var scaleXY: Int = 128,
|
||||||
|
var scaleZ: Int = 128,
|
||||||
|
var priorityRender: Boolean = false,
|
||||||
|
var lightModifier: Int = 0,
|
||||||
|
var shadowModifier: Int = 0,
|
||||||
|
var headIcon: Int = -1,
|
||||||
|
var rotation: Int = 32,
|
||||||
|
var varbit: Int = -1,
|
||||||
|
var varp: Int = -1,
|
||||||
|
var morphs: IntArray? = null,
|
||||||
|
var clickable: Boolean = true,
|
||||||
|
var slowWalk: Boolean = true,
|
||||||
|
var animateIdle: Boolean = true,
|
||||||
|
var primaryShadowColour: Short = 0,
|
||||||
|
var secondaryShadowColour: Short = 0,
|
||||||
|
var primaryShadowModifier: Byte = -96,
|
||||||
|
var secondaryShadowModifier: Byte = -16,
|
||||||
|
var walkMask: Byte = 0,
|
||||||
|
var translations: Array<IntArray?>? = null,
|
||||||
|
var hitbarSprite: Int = -1,
|
||||||
|
var height: Int = -1,
|
||||||
|
var respawnDirection: Byte = 4,
|
||||||
|
var renderEmote: Int = -1,
|
||||||
|
var idleSound: Int = -1,
|
||||||
|
var crawlSound: Int = -1,
|
||||||
|
var walkSound: Int = -1,
|
||||||
|
var runSound: Int = -1,
|
||||||
|
var soundDistance: Int = 0,
|
||||||
|
var primaryCursorOp: Int = -1,
|
||||||
|
var primaryCursor: Int = -1,
|
||||||
|
var secondaryCursorOp: Int = -1,
|
||||||
|
var secondaryCursor: Int = -1,
|
||||||
|
var attackCursor: Int = -1,
|
||||||
|
var armyIcon: Int = -1,
|
||||||
|
var spriteId: Int = -1,
|
||||||
|
var ambientSoundVolume: Int = 255,
|
||||||
|
var visiblePriority: Boolean = false,
|
||||||
|
var mapFunction: Int = -1,
|
||||||
|
var invisiblePriority: Boolean = false,
|
||||||
|
var hue: Byte = 0,
|
||||||
|
var saturation: Byte = 0,
|
||||||
|
var lightness: Byte = 0,
|
||||||
|
var opacity: Byte = 0,
|
||||||
|
var mainOptionIndex: Byte = -1,
|
||||||
|
var campaigns: IntArray? = null,
|
||||||
|
var aBoolean2883: Boolean = false,
|
||||||
|
var anInt2803: Int = -1,
|
||||||
|
var anInt2844: Int = 256,
|
||||||
|
var anInt2852: Int = 256,
|
||||||
|
var anInt2831: Int = 0,
|
||||||
|
var anInt2862: Int = 0,
|
||||||
|
override var params: HashMap<Long, Any>? = null,
|
||||||
|
override var extras: Map<String, Any> = emptyMap()
|
||||||
|
) : Definition, Recolourable, Parameterized, Extra {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as NPCDefinition
|
||||||
|
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (modelIds != null) {
|
||||||
|
if (other.modelIds == null) return false
|
||||||
|
if (!modelIds!!.contentEquals(other.modelIds!!)) return false
|
||||||
|
} else if (other.modelIds != null) return false
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (size != other.size) return false
|
||||||
|
if (!options.contentEquals(other.options)) return false
|
||||||
|
if (originalColours != null) {
|
||||||
|
if (other.originalColours == null) return false
|
||||||
|
if (!originalColours!!.contentEquals(other.originalColours!!)) return false
|
||||||
|
} else if (other.originalColours != null) return false
|
||||||
|
if (modifiedColours != null) {
|
||||||
|
if (other.modifiedColours == null) return false
|
||||||
|
if (!modifiedColours!!.contentEquals(other.modifiedColours!!)) return false
|
||||||
|
} else if (other.modifiedColours != null) return false
|
||||||
|
if (originalTextureColours != null) {
|
||||||
|
if (other.originalTextureColours == null) return false
|
||||||
|
if (!originalTextureColours!!.contentEquals(other.originalTextureColours!!)) return false
|
||||||
|
} else if (other.originalTextureColours != null) return false
|
||||||
|
if (modifiedTextureColours != null) {
|
||||||
|
if (other.modifiedTextureColours == null) return false
|
||||||
|
if (!modifiedTextureColours!!.contentEquals(other.modifiedTextureColours!!)) return false
|
||||||
|
} else if (other.modifiedTextureColours != null) return false
|
||||||
|
if (recolourPalette != null) {
|
||||||
|
if (other.recolourPalette == null) return false
|
||||||
|
if (!recolourPalette!!.contentEquals(other.recolourPalette!!)) return false
|
||||||
|
} else if (other.recolourPalette != null) return false
|
||||||
|
if (dialogueModels != null) {
|
||||||
|
if (other.dialogueModels == null) return false
|
||||||
|
if (!dialogueModels!!.contentEquals(other.dialogueModels!!)) return false
|
||||||
|
} else if (other.dialogueModels != null) return false
|
||||||
|
if (drawMinimapDot != other.drawMinimapDot) return false
|
||||||
|
if (combat != other.combat) return false
|
||||||
|
if (scaleXY != other.scaleXY) return false
|
||||||
|
if (scaleZ != other.scaleZ) return false
|
||||||
|
if (priorityRender != other.priorityRender) return false
|
||||||
|
if (lightModifier != other.lightModifier) return false
|
||||||
|
if (shadowModifier != other.shadowModifier) return false
|
||||||
|
if (headIcon != other.headIcon) return false
|
||||||
|
if (rotation != other.rotation) return false
|
||||||
|
if (varbit != other.varbit) return false
|
||||||
|
if (varp != other.varp) return false
|
||||||
|
if (morphs != null) {
|
||||||
|
if (other.morphs == null) return false
|
||||||
|
if (!morphs!!.contentEquals(other.morphs!!)) return false
|
||||||
|
} else if (other.morphs != null) return false
|
||||||
|
if (clickable != other.clickable) return false
|
||||||
|
if (slowWalk != other.slowWalk) return false
|
||||||
|
if (animateIdle != other.animateIdle) return false
|
||||||
|
if (primaryShadowColour != other.primaryShadowColour) return false
|
||||||
|
if (secondaryShadowColour != other.secondaryShadowColour) return false
|
||||||
|
if (primaryShadowModifier != other.primaryShadowModifier) return false
|
||||||
|
if (secondaryShadowModifier != other.secondaryShadowModifier) return false
|
||||||
|
if (walkMask != other.walkMask) return false
|
||||||
|
if (translations != null) {
|
||||||
|
if (other.translations == null) return false
|
||||||
|
if (!translations!!.contentDeepEquals(other.translations!!)) return false
|
||||||
|
} else if (other.translations != null) return false
|
||||||
|
if (hitbarSprite != other.hitbarSprite) return false
|
||||||
|
if (height != other.height) return false
|
||||||
|
if (respawnDirection != other.respawnDirection) return false
|
||||||
|
if (renderEmote != other.renderEmote) return false
|
||||||
|
if (idleSound != other.idleSound) return false
|
||||||
|
if (crawlSound != other.crawlSound) return false
|
||||||
|
if (walkSound != other.walkSound) return false
|
||||||
|
if (runSound != other.runSound) return false
|
||||||
|
if (soundDistance != other.soundDistance) return false
|
||||||
|
if (primaryCursorOp != other.primaryCursorOp) return false
|
||||||
|
if (primaryCursor != other.primaryCursor) return false
|
||||||
|
if (secondaryCursorOp != other.secondaryCursorOp) return false
|
||||||
|
if (secondaryCursor != other.secondaryCursor) return false
|
||||||
|
if (attackCursor != other.attackCursor) return false
|
||||||
|
if (armyIcon != other.armyIcon) return false
|
||||||
|
if (spriteId != other.spriteId) return false
|
||||||
|
if (ambientSoundVolume != other.ambientSoundVolume) return false
|
||||||
|
if (visiblePriority != other.visiblePriority) return false
|
||||||
|
if (mapFunction != other.mapFunction) return false
|
||||||
|
if (invisiblePriority != other.invisiblePriority) return false
|
||||||
|
if (hue != other.hue) return false
|
||||||
|
if (saturation != other.saturation) return false
|
||||||
|
if (lightness != other.lightness) return false
|
||||||
|
if (opacity != other.opacity) return false
|
||||||
|
if (mainOptionIndex != other.mainOptionIndex) return false
|
||||||
|
if (campaigns != null) {
|
||||||
|
if (other.campaigns == null) return false
|
||||||
|
if (!campaigns!!.contentEquals(other.campaigns!!)) return false
|
||||||
|
} else if (other.campaigns != null) return false
|
||||||
|
if (aBoolean2883 != other.aBoolean2883) return false
|
||||||
|
if (anInt2803 != other.anInt2803) return false
|
||||||
|
if (anInt2844 != other.anInt2844) return false
|
||||||
|
if (anInt2852 != other.anInt2852) return false
|
||||||
|
if (anInt2831 != other.anInt2831) return false
|
||||||
|
if (anInt2862 != other.anInt2862) return false
|
||||||
|
if (params != other.params) return false
|
||||||
|
if (extras != other.extras) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + (modelIds?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + name.hashCode()
|
||||||
|
result = 31 * result + size
|
||||||
|
result = 31 * result + options.contentHashCode()
|
||||||
|
result = 31 * result + (originalColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modifiedColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (originalTextureColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modifiedTextureColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (recolourPalette?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (dialogueModels?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + drawMinimapDot.hashCode()
|
||||||
|
result = 31 * result + combat
|
||||||
|
result = 31 * result + scaleXY
|
||||||
|
result = 31 * result + scaleZ
|
||||||
|
result = 31 * result + priorityRender.hashCode()
|
||||||
|
result = 31 * result + lightModifier
|
||||||
|
result = 31 * result + shadowModifier
|
||||||
|
result = 31 * result + headIcon
|
||||||
|
result = 31 * result + rotation
|
||||||
|
result = 31 * result + varbit
|
||||||
|
result = 31 * result + varp
|
||||||
|
result = 31 * result + (morphs?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + clickable.hashCode()
|
||||||
|
result = 31 * result + slowWalk.hashCode()
|
||||||
|
result = 31 * result + animateIdle.hashCode()
|
||||||
|
result = 31 * result + primaryShadowColour
|
||||||
|
result = 31 * result + secondaryShadowColour
|
||||||
|
result = 31 * result + primaryShadowModifier
|
||||||
|
result = 31 * result + secondaryShadowModifier
|
||||||
|
result = 31 * result + walkMask
|
||||||
|
result = 31 * result + (translations?.contentDeepHashCode() ?: 0)
|
||||||
|
result = 31 * result + hitbarSprite
|
||||||
|
result = 31 * result + height
|
||||||
|
result = 31 * result + respawnDirection
|
||||||
|
result = 31 * result + renderEmote
|
||||||
|
result = 31 * result + idleSound
|
||||||
|
result = 31 * result + crawlSound
|
||||||
|
result = 31 * result + walkSound
|
||||||
|
result = 31 * result + runSound
|
||||||
|
result = 31 * result + soundDistance
|
||||||
|
result = 31 * result + primaryCursorOp
|
||||||
|
result = 31 * result + primaryCursor
|
||||||
|
result = 31 * result + secondaryCursorOp
|
||||||
|
result = 31 * result + secondaryCursor
|
||||||
|
result = 31 * result + attackCursor
|
||||||
|
result = 31 * result + armyIcon
|
||||||
|
result = 31 * result + spriteId
|
||||||
|
result = 31 * result + ambientSoundVolume
|
||||||
|
result = 31 * result + visiblePriority.hashCode()
|
||||||
|
result = 31 * result + mapFunction
|
||||||
|
result = 31 * result + invisiblePriority.hashCode()
|
||||||
|
result = 31 * result + hue
|
||||||
|
result = 31 * result + saturation
|
||||||
|
result = 31 * result + lightness
|
||||||
|
result = 31 * result + opacity
|
||||||
|
result = 31 * result + mainOptionIndex
|
||||||
|
result = 31 * result + (campaigns?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + aBoolean2883.hashCode()
|
||||||
|
result = 31 * result + anInt2803
|
||||||
|
result = 31 * result + anInt2844
|
||||||
|
result = 31 * result + anInt2852
|
||||||
|
result = 31 * result + anInt2831
|
||||||
|
result = 31 * result + anInt2862
|
||||||
|
result = 31 * result + (params?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + extras.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
295
src/main/kotlin/cacheops/cache/definition/data/ObjectDefinition.kt
vendored
Normal file
295
src/main/kotlin/cacheops/cache/definition/data/ObjectDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,295 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import cacheops.cache.definition.ColorPalette
|
||||||
|
import cacheops.cache.definition.Extra
|
||||||
|
import cacheops.cache.definition.Parameterized
|
||||||
|
import cacheops.cache.definition.Recolourable
|
||||||
|
|
||||||
|
data class ObjectDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var modelIds: IntArray? = null,
|
||||||
|
var modelTypes: IntArray? = null,
|
||||||
|
var name: String = "null",
|
||||||
|
var sizeX: Int = 1,
|
||||||
|
var sizeY: Int = 1,
|
||||||
|
var blocksSky: Boolean = true,
|
||||||
|
var solid: Int = 2,
|
||||||
|
var interactive: Int = -1,
|
||||||
|
var contouredGround: Byte = 0,
|
||||||
|
var delayShading: Boolean = false,
|
||||||
|
var offsetMultiplier: Int = 64,
|
||||||
|
var brightness: Int = 0,
|
||||||
|
var options: Array<String?> = arrayOf(null, null, null, null, null, "Examine"),
|
||||||
|
var contrast: Int = 0,
|
||||||
|
override var originalColours: ShortArray? = null,
|
||||||
|
override var modifiedColours: ShortArray? = null,
|
||||||
|
override var originalTextureColours: ShortArray? = null,
|
||||||
|
override var modifiedTextureColours: ShortArray? = null,
|
||||||
|
override var recolourPalette: ByteArray? = null,
|
||||||
|
var mirrored: Boolean = false,
|
||||||
|
var castsShadow: Boolean = true,
|
||||||
|
var modelSizeX: Int = 128,
|
||||||
|
var modelSizeZ: Int = 128,
|
||||||
|
var modelSizeY: Int = 128,
|
||||||
|
var blockFlag: Int = 0,
|
||||||
|
var offsetX: Int = 0,
|
||||||
|
var offsetZ: Int = 0,
|
||||||
|
var offsetY: Int = 0,
|
||||||
|
var blocksLand: Boolean = false,
|
||||||
|
var ignoreOnRoute: Boolean = false,
|
||||||
|
var supportItems: Int = -1,
|
||||||
|
var varbitIndex: Int = -1,
|
||||||
|
var configId: Int = -1,
|
||||||
|
var configObjectIds: IntArray? = null,
|
||||||
|
var anInt3015: Int = -1,
|
||||||
|
var anInt3012: Int = 0,
|
||||||
|
var anInt2989: Int = 0,
|
||||||
|
var anInt2971: Int = 0,
|
||||||
|
var anIntArray3036: IntArray? = null,
|
||||||
|
var anInt3023: Int = -1,
|
||||||
|
var hideMinimap: Boolean = false,
|
||||||
|
var aBoolean2972: Boolean = true,
|
||||||
|
var animateImmediately: Boolean = true,
|
||||||
|
var aBoolean1502: Boolean = false,
|
||||||
|
var aBoolean1507: Boolean = false,
|
||||||
|
var isMembers: Boolean = false,
|
||||||
|
var adjustMapSceneRotation: Boolean = false,
|
||||||
|
var hasAnimation: Boolean = false,
|
||||||
|
var anInt2987: Int = -1,
|
||||||
|
var anInt3008: Int = -1,
|
||||||
|
var anInt3038: Int = -1,
|
||||||
|
var anInt3013: Int = -1,
|
||||||
|
var mapSceneRotation: Int = 0,
|
||||||
|
var mapscene: Int = -1,
|
||||||
|
var culling: Int = -1,
|
||||||
|
var anInt3024: Int = 255,
|
||||||
|
var invertMapScene: Boolean = false,
|
||||||
|
var animations: IntArray? = null,
|
||||||
|
var percents: IntArray? = null,
|
||||||
|
var mapDefinitionId: Int = -1,
|
||||||
|
var anIntArray2981: IntArray? = null,
|
||||||
|
var aByte2974: Byte = 0,
|
||||||
|
var aByte3045: Byte = 0,
|
||||||
|
var aByte3052: Byte = 0,
|
||||||
|
var aByte2960: Byte = 0,
|
||||||
|
var anInt2964: Int = 0,
|
||||||
|
var anInt2963: Int = 0,
|
||||||
|
var anInt3018: Int = 0,
|
||||||
|
var anInt2983: Int = 0,
|
||||||
|
var aBoolean2961: Boolean = false,
|
||||||
|
var aBoolean2993: Boolean = false,
|
||||||
|
var anInt3032: Int = 960,
|
||||||
|
var anInt2962: Int = 0,
|
||||||
|
var anInt3050: Int = 256,
|
||||||
|
var anInt3020: Int = 256,
|
||||||
|
var aBoolean2992: Boolean = false,
|
||||||
|
var anInt2975: Int = 0,
|
||||||
|
override var params: HashMap<Long, Any>? = null,
|
||||||
|
override var extras: Map<String, Any> = emptyMap()
|
||||||
|
) : Definition, Recolourable, ColorPalette, Parameterized, Extra {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as ObjectDefinition
|
||||||
|
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (modelIds != null) {
|
||||||
|
if (other.modelIds == null) return false
|
||||||
|
if (!modelIds!!.contentEquals(other.modelIds!!)) return false
|
||||||
|
} else if (other.modelIds != null) return false
|
||||||
|
if (modelTypes != null) {
|
||||||
|
if (other.modelTypes == null) return false
|
||||||
|
if (!modelTypes!!.contentEquals(other.modelTypes!!)) return false
|
||||||
|
} else if (other.modelTypes != null) return false
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (sizeX != other.sizeX) return false
|
||||||
|
if (sizeY != other.sizeY) return false
|
||||||
|
if (blocksSky != other.blocksSky) return false
|
||||||
|
if (solid != other.solid) return false
|
||||||
|
if (interactive != other.interactive) return false
|
||||||
|
if (contouredGround != other.contouredGround) return false
|
||||||
|
if (delayShading != other.delayShading) return false
|
||||||
|
if (offsetMultiplier != other.offsetMultiplier) return false
|
||||||
|
if (brightness != other.brightness) return false
|
||||||
|
if (!options.contentEquals(other.options)) return false
|
||||||
|
if (contrast != other.contrast) return false
|
||||||
|
if (originalColours != null) {
|
||||||
|
if (other.originalColours == null) return false
|
||||||
|
if (!originalColours!!.contentEquals(other.originalColours!!)) return false
|
||||||
|
} else if (other.originalColours != null) return false
|
||||||
|
if (modifiedColours != null) {
|
||||||
|
if (other.modifiedColours == null) return false
|
||||||
|
if (!modifiedColours!!.contentEquals(other.modifiedColours!!)) return false
|
||||||
|
} else if (other.modifiedColours != null) return false
|
||||||
|
if (originalTextureColours != null) {
|
||||||
|
if (other.originalTextureColours == null) return false
|
||||||
|
if (!originalTextureColours!!.contentEquals(other.originalTextureColours!!)) return false
|
||||||
|
} else if (other.originalTextureColours != null) return false
|
||||||
|
if (modifiedTextureColours != null) {
|
||||||
|
if (other.modifiedTextureColours == null) return false
|
||||||
|
if (!modifiedTextureColours!!.contentEquals(other.modifiedTextureColours!!)) return false
|
||||||
|
} else if (other.modifiedTextureColours != null) return false
|
||||||
|
if (recolourPalette != null) {
|
||||||
|
if (other.recolourPalette == null) return false
|
||||||
|
if (!recolourPalette!!.contentEquals(other.recolourPalette!!)) return false
|
||||||
|
} else if (other.recolourPalette != null) return false
|
||||||
|
if (mirrored != other.mirrored) return false
|
||||||
|
if (castsShadow != other.castsShadow) return false
|
||||||
|
if (modelSizeX != other.modelSizeX) return false
|
||||||
|
if (modelSizeZ != other.modelSizeZ) return false
|
||||||
|
if (modelSizeY != other.modelSizeY) return false
|
||||||
|
if (blockFlag != other.blockFlag) return false
|
||||||
|
if (offsetX != other.offsetX) return false
|
||||||
|
if (offsetZ != other.offsetZ) return false
|
||||||
|
if (offsetY != other.offsetY) return false
|
||||||
|
if (blocksLand != other.blocksLand) return false
|
||||||
|
if (ignoreOnRoute != other.ignoreOnRoute) return false
|
||||||
|
if (supportItems != other.supportItems) return false
|
||||||
|
if (varbitIndex != other.varbitIndex) return false
|
||||||
|
if (configId != other.configId) return false
|
||||||
|
if (configObjectIds != null) {
|
||||||
|
if (other.configObjectIds == null) return false
|
||||||
|
if (!configObjectIds!!.contentEquals(other.configObjectIds!!)) return false
|
||||||
|
} else if (other.configObjectIds != null) return false
|
||||||
|
if (anInt3015 != other.anInt3015) return false
|
||||||
|
if (anInt3012 != other.anInt3012) return false
|
||||||
|
if (anInt2989 != other.anInt2989) return false
|
||||||
|
if (anInt2971 != other.anInt2971) return false
|
||||||
|
if (anIntArray3036 != null) {
|
||||||
|
if (other.anIntArray3036 == null) return false
|
||||||
|
if (!anIntArray3036!!.contentEquals(other.anIntArray3036!!)) return false
|
||||||
|
} else if (other.anIntArray3036 != null) return false
|
||||||
|
if (anInt3023 != other.anInt3023) return false
|
||||||
|
if (hideMinimap != other.hideMinimap) return false
|
||||||
|
if (aBoolean2972 != other.aBoolean2972) return false
|
||||||
|
if (animateImmediately != other.animateImmediately) return false
|
||||||
|
if (isMembers != other.isMembers) return false
|
||||||
|
if (adjustMapSceneRotation != other.adjustMapSceneRotation) return false
|
||||||
|
if (hasAnimation != other.hasAnimation) return false
|
||||||
|
if (anInt2987 != other.anInt2987) return false
|
||||||
|
if (anInt3008 != other.anInt3008) return false
|
||||||
|
if (anInt3038 != other.anInt3038) return false
|
||||||
|
if (anInt3013 != other.anInt3013) return false
|
||||||
|
if (mapSceneRotation != other.mapSceneRotation) return false
|
||||||
|
if (mapscene != other.mapscene) return false
|
||||||
|
if (culling != other.culling) return false
|
||||||
|
if (anInt3024 != other.anInt3024) return false
|
||||||
|
if (invertMapScene != other.invertMapScene) return false
|
||||||
|
if (animations != null) {
|
||||||
|
if (other.animations == null) return false
|
||||||
|
if (!animations!!.contentEquals(other.animations!!)) return false
|
||||||
|
} else if (other.animations != null) return false
|
||||||
|
if (percents != null) {
|
||||||
|
if (other.percents == null) return false
|
||||||
|
if (!percents!!.contentEquals(other.percents!!)) return false
|
||||||
|
} else if (other.percents != null) return false
|
||||||
|
if (mapDefinitionId != other.mapDefinitionId) return false
|
||||||
|
if (anIntArray2981 != null) {
|
||||||
|
if (other.anIntArray2981 == null) return false
|
||||||
|
if (!anIntArray2981!!.contentEquals(other.anIntArray2981!!)) return false
|
||||||
|
} else if (other.anIntArray2981 != null) return false
|
||||||
|
if (aByte2974 != other.aByte2974) return false
|
||||||
|
if (aByte3045 != other.aByte3045) return false
|
||||||
|
if (aByte3052 != other.aByte3052) return false
|
||||||
|
if (aByte2960 != other.aByte2960) return false
|
||||||
|
if (anInt2964 != other.anInt2964) return false
|
||||||
|
if (anInt2963 != other.anInt2963) return false
|
||||||
|
if (anInt3018 != other.anInt3018) return false
|
||||||
|
if (anInt2983 != other.anInt2983) return false
|
||||||
|
if (aBoolean2961 != other.aBoolean2961) return false
|
||||||
|
if (aBoolean2993 != other.aBoolean2993) return false
|
||||||
|
if (anInt3032 != other.anInt3032) return false
|
||||||
|
if (anInt2962 != other.anInt2962) return false
|
||||||
|
if (anInt3050 != other.anInt3050) return false
|
||||||
|
if (anInt3020 != other.anInt3020) return false
|
||||||
|
if (aBoolean2992 != other.aBoolean2992) return false
|
||||||
|
if (anInt2975 != other.anInt2975) return false
|
||||||
|
if (params != other.params) return false
|
||||||
|
if (extras != other.extras) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + (modelIds?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modelTypes?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + name.hashCode()
|
||||||
|
result = 31 * result + sizeX
|
||||||
|
result = 31 * result + sizeY
|
||||||
|
result = 31 * result + blocksSky.hashCode()
|
||||||
|
result = 31 * result + solid
|
||||||
|
result = 31 * result + interactive
|
||||||
|
result = 31 * result + contouredGround
|
||||||
|
result = 31 * result + delayShading.hashCode()
|
||||||
|
result = 31 * result + offsetMultiplier
|
||||||
|
result = 31 * result + brightness
|
||||||
|
result = 31 * result + options.contentHashCode()
|
||||||
|
result = 31 * result + contrast
|
||||||
|
result = 31 * result + (originalColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modifiedColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (originalTextureColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (modifiedTextureColours?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (recolourPalette?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + mirrored.hashCode()
|
||||||
|
result = 31 * result + castsShadow.hashCode()
|
||||||
|
result = 31 * result + modelSizeX
|
||||||
|
result = 31 * result + modelSizeZ
|
||||||
|
result = 31 * result + modelSizeY
|
||||||
|
result = 31 * result + blockFlag
|
||||||
|
result = 31 * result + offsetX
|
||||||
|
result = 31 * result + offsetZ
|
||||||
|
result = 31 * result + offsetY
|
||||||
|
result = 31 * result + blocksLand.hashCode()
|
||||||
|
result = 31 * result + ignoreOnRoute.hashCode()
|
||||||
|
result = 31 * result + supportItems
|
||||||
|
result = 31 * result + varbitIndex
|
||||||
|
result = 31 * result + configId
|
||||||
|
result = 31 * result + (configObjectIds?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + anInt3015
|
||||||
|
result = 31 * result + anInt3012
|
||||||
|
result = 31 * result + anInt2989
|
||||||
|
result = 31 * result + anInt2971
|
||||||
|
result = 31 * result + (anIntArray3036?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + anInt3023
|
||||||
|
result = 31 * result + hideMinimap.hashCode()
|
||||||
|
result = 31 * result + aBoolean2972.hashCode()
|
||||||
|
result = 31 * result + animateImmediately.hashCode()
|
||||||
|
result = 31 * result + isMembers.hashCode()
|
||||||
|
result = 31 * result + adjustMapSceneRotation.hashCode()
|
||||||
|
result = 31 * result + hasAnimation.hashCode()
|
||||||
|
result = 31 * result + anInt2987
|
||||||
|
result = 31 * result + anInt3008
|
||||||
|
result = 31 * result + anInt3038
|
||||||
|
result = 31 * result + anInt3013
|
||||||
|
result = 31 * result + mapSceneRotation
|
||||||
|
result = 31 * result + mapscene
|
||||||
|
result = 31 * result + culling
|
||||||
|
result = 31 * result + anInt3024
|
||||||
|
result = 31 * result + invertMapScene.hashCode()
|
||||||
|
result = 31 * result + (animations?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + (percents?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + mapDefinitionId
|
||||||
|
result = 31 * result + (anIntArray2981?.contentHashCode() ?: 0)
|
||||||
|
result = 31 * result + aByte2974
|
||||||
|
result = 31 * result + aByte3045
|
||||||
|
result = 31 * result + aByte3052
|
||||||
|
result = 31 * result + aByte2960
|
||||||
|
result = 31 * result + anInt2964
|
||||||
|
result = 31 * result + anInt2963
|
||||||
|
result = 31 * result + anInt3018
|
||||||
|
result = 31 * result + anInt2983
|
||||||
|
result = 31 * result + aBoolean2961.hashCode()
|
||||||
|
result = 31 * result + aBoolean2993.hashCode()
|
||||||
|
result = 31 * result + anInt3032
|
||||||
|
result = 31 * result + anInt2962
|
||||||
|
result = 31 * result + anInt3050
|
||||||
|
result = 31 * result + anInt3020
|
||||||
|
result = 31 * result + aBoolean2992.hashCode()
|
||||||
|
result = 31 * result + anInt2975
|
||||||
|
result = 31 * result + (params?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + extras.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/kotlin/cacheops/cache/definition/data/OverlayDefinition.kt
vendored
Normal file
26
src/main/kotlin/cacheops/cache/definition/data/OverlayDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import java.awt.Color
|
||||||
|
|
||||||
|
data class OverlayDefinition(
|
||||||
|
var color: Int = 0,
|
||||||
|
var texture: Int = -1,
|
||||||
|
var hideUnderlay: Boolean = true,
|
||||||
|
var blendColor: Int = -1,
|
||||||
|
var scale: Int = 128,
|
||||||
|
var blockShadow: Boolean = true,
|
||||||
|
var aByte0: Int = 8,
|
||||||
|
var blendTexture: Boolean = false,
|
||||||
|
var waterColor: Int = 1190717,
|
||||||
|
var waterScale: Int = 16,
|
||||||
|
var anInt0: Int = -1,
|
||||||
|
var waterIntensity: Int = 16
|
||||||
|
) {
|
||||||
|
override fun toString(): String {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRGB(): Color {
|
||||||
|
return Color(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/main/kotlin/cacheops/cache/definition/data/QuickChatOptionDefinition.kt
vendored
Normal file
36
src/main/kotlin/cacheops/cache/definition/data/QuickChatOptionDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
@Suppress("ArrayInDataClass")
|
||||||
|
data class QuickChatOptionDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var optionText: String? = null,
|
||||||
|
var quickReplyOptions: IntArray? = null,
|
||||||
|
var navigateChars: CharArray? = null,
|
||||||
|
var dynamicData: IntArray? = null,
|
||||||
|
var staticData: CharArray? = null
|
||||||
|
) : Definition {
|
||||||
|
fun getDynamicIndex(c: Char): Int {
|
||||||
|
if (dynamicData == null) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for (i in dynamicData!!.indices) {
|
||||||
|
if (staticData!![i] == c) {
|
||||||
|
return dynamicData!![i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOption(c: Char): Int {
|
||||||
|
if (quickReplyOptions == null) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for (i in quickReplyOptions!!.indices) {
|
||||||
|
if (navigateChars!![i] == c) {
|
||||||
|
return quickReplyOptions!![i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/main/kotlin/cacheops/cache/definition/data/SpriteDefinition.kt
vendored
Normal file
8
src/main/kotlin/cacheops/cache/definition/data/SpriteDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
@Suppress("ArrayInDataClass")
|
||||||
|
data class SpriteDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var sprites: Array<IndexedSprite>? = null
|
||||||
|
) : Definition
|
||||||
25
src/main/kotlin/cacheops/cache/definition/data/TextureDefinition.kt
vendored
Normal file
25
src/main/kotlin/cacheops/cache/definition/data/TextureDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
data class TextureDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var useTextureColour: Boolean = false,
|
||||||
|
var aBoolean1204: Boolean = false,
|
||||||
|
var aBoolean1205: Boolean = false,
|
||||||
|
var aByte1217: Byte = 0,
|
||||||
|
var aByte1225: Byte = 0,
|
||||||
|
var type: Byte = 0,
|
||||||
|
var aByte1213: Byte = 0,
|
||||||
|
var colour: Int = 0,
|
||||||
|
var aByte1211: Byte = 0,
|
||||||
|
var aByte1203: Byte = 0,
|
||||||
|
var aBoolean1222: Boolean = false,
|
||||||
|
var aBoolean1216: Boolean = false,
|
||||||
|
var aByte1207: Byte = 0,
|
||||||
|
var aBoolean1212: Boolean = false,
|
||||||
|
var aBoolean1210: Boolean = false,
|
||||||
|
var aBoolean1215: Boolean = false,
|
||||||
|
var anInt1202: Int = 0,
|
||||||
|
var anInt1206: Int = 0,
|
||||||
|
var anInt1226: Int = 0
|
||||||
|
) : Definition
|
||||||
23
src/main/kotlin/cacheops/cache/definition/data/UnderlayDefinition.kt
vendored
Normal file
23
src/main/kotlin/cacheops/cache/definition/data/UnderlayDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
import java.awt.Color
|
||||||
|
|
||||||
|
data class UnderlayDefinition(
|
||||||
|
var color: Int = 0,
|
||||||
|
var hue: Int = 0,
|
||||||
|
var saturation: Int = 0,
|
||||||
|
var lumiance: Int = 0,
|
||||||
|
var texture: Int = -1,
|
||||||
|
var scale: Int = 128,
|
||||||
|
var blockShadow: Boolean = true,
|
||||||
|
var blendHueMultiplier: Int = 0,
|
||||||
|
var blendHue: Int = 0
|
||||||
|
) {
|
||||||
|
override fun toString(): String {
|
||||||
|
return "[RAW(HSL): $color, BlendH: $blendHue, H: $hue, S: $saturation, L: $lumiance, Texture: $texture, Scale: $scale, Shadow: $blockShadow]"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRGB(): Color {
|
||||||
|
return Color(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/main/kotlin/cacheops/cache/definition/data/VarBitDefinition.kt
vendored
Normal file
9
src/main/kotlin/cacheops/cache/definition/data/VarBitDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
data class VarBitDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var index: Int = 0,
|
||||||
|
var leastSignificantBit: Int = 0,
|
||||||
|
var mostSignificantBit: Int = 0
|
||||||
|
) : Definition
|
||||||
18
src/main/kotlin/cacheops/cache/definition/data/WorldMapDefinition.kt
vendored
Normal file
18
src/main/kotlin/cacheops/cache/definition/data/WorldMapDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
data class WorldMapDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var map: String = "",
|
||||||
|
var name: String = "",
|
||||||
|
var position: Int = -1,
|
||||||
|
var anInt9542: Int = -1,
|
||||||
|
var static: Boolean = false,
|
||||||
|
var anInt9547: Int = -1,
|
||||||
|
var sections: LinkedList<WorldMapSection>? = null,
|
||||||
|
var minX: Int = 12800,
|
||||||
|
var minY: Int = 12800,
|
||||||
|
var maxX: Int = 0,
|
||||||
|
var maxY: Int = 0
|
||||||
|
) : Definition
|
||||||
6
src/main/kotlin/cacheops/cache/definition/data/WorldMapIcon.kt
vendored
Normal file
6
src/main/kotlin/cacheops/cache/definition/data/WorldMapIcon.kt
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
data class WorldMapIcon(
|
||||||
|
var id: Int = -1,
|
||||||
|
var position: Int = -1
|
||||||
|
)
|
||||||
25
src/main/kotlin/cacheops/cache/definition/data/WorldMapIconDefinition.kt
vendored
Normal file
25
src/main/kotlin/cacheops/cache/definition/data/WorldMapIconDefinition.kt
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
import cacheops.cache.Definition
|
||||||
|
|
||||||
|
data class WorldMapIconDefinition(
|
||||||
|
override var id: Int = -1,
|
||||||
|
var icons: Array<WorldMapIcon> = emptyArray()
|
||||||
|
) : Definition {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as WorldMapIconDefinition
|
||||||
|
|
||||||
|
if (id != other.id) return false
|
||||||
|
if (!icons.contentEquals(other.icons)) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + icons.contentHashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/main/kotlin/cacheops/cache/definition/data/WorldMapSection.kt
vendored
Normal file
3
src/main/kotlin/cacheops/cache/definition/data/WorldMapSection.kt
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
package cacheops.cache.definition.data
|
||||||
|
|
||||||
|
data class WorldMapSection(val plane: Int, val minX: Int, val minY: Int, val maxX: Int, val maxY: Int, var startX: Int, var startY: Int, var endX: Int, var endY: Int)
|
||||||
7
src/main/kotlin/cacheops/cache/definition/decoder/AtmosphereDecoder.kt
vendored
Normal file
7
src/main/kotlin/cacheops/cache/definition/decoder/AtmosphereDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
class AtmosphereDecoder {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
95
src/main/kotlin/cacheops/cache/definition/decoder/BlendedTextureDecoder.kt
vendored
Normal file
95
src/main/kotlin/cacheops/cache/definition/decoder/BlendedTextureDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import cacheops.cache.Cache
|
||||||
|
import cacheops.cache.DefinitionDecoder
|
||||||
|
import cacheops.cache.buffer.read.BufferReader
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
import cacheops.cache.definition.data.BlendedTextureDefinition
|
||||||
|
import const.Indices
|
||||||
|
|
||||||
|
class BlendedTextureDecoder(cache: Cache) : DefinitionDecoder<BlendedTextureDefinition>(cache, Indices.MATERIALS) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val blendedTextureDef = HashMap<Int, BlendedTextureDefinition>()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun create() = BlendedTextureDefinition()
|
||||||
|
|
||||||
|
var metricsCount = 0
|
||||||
|
|
||||||
|
override val last: Int
|
||||||
|
get() = metricsCount
|
||||||
|
|
||||||
|
init {
|
||||||
|
val data = getData(0, 0)
|
||||||
|
if (data != null) {
|
||||||
|
decode(BufferReader(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun decode(buffer: Reader) {
|
||||||
|
metricsCount = buffer.readShort()
|
||||||
|
for (id in 0 until metricsCount) {
|
||||||
|
if (buffer.readUnsignedBoolean()) {
|
||||||
|
blendedTextureDef[id] = BlendedTextureDefinition(id = id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (texture in blendedTextureDef.values) { // J
|
||||||
|
texture.renderOnMap = !buffer.readUnsignedBoolean() // 0
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readUnsignedBoolean() // 1
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readUnsignedBoolean() // 1
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readByte().toByte() // 1
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
texture.blendedColor = buffer.readUnsignedShort()
|
||||||
|
println(texture.blendedColor)
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readUnsignedBoolean()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readUnsignedBoolean()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readUnsignedBoolean()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readUnsignedBoolean()
|
||||||
|
}
|
||||||
|
for (texture in blendedTextureDef.values) {
|
||||||
|
buffer.readUnsignedBoolean()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun BlendedTextureDefinition.read(opcode: Int, buffer: Reader) {
|
||||||
|
throw IllegalStateException("Shouldn't be used.")
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/main/kotlin/cacheops/cache/definition/decoder/FloorOverlayConfiguration.kt
vendored
Normal file
32
src/main/kotlin/cacheops/cache/definition/decoder/FloorOverlayConfiguration.kt
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.data.OverlayDefinition
|
||||||
|
import const.Archives
|
||||||
|
import const.Indices
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
object FloorOverlayConfiguration {
|
||||||
|
|
||||||
|
val cache = Rs2MapEditor.library.index(Indices.CONFIGURATION).archive(Archives.FLOOR_OVERLAYS)
|
||||||
|
|
||||||
|
var floorOverlays = hashMapOf<Int, OverlayDefinition>()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
cache!!.files().forEach {
|
||||||
|
val buffer = ByteBuffer.wrap(it.data)
|
||||||
|
val definition = FloorOverlayDecoder().decode(buffer)
|
||||||
|
floorOverlays[it.id] = definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
cache!!.files().forEach {
|
||||||
|
val buffer = ByteBuffer.wrap(it.data)
|
||||||
|
val definition = FloorOverlayDecoder().decode(buffer)
|
||||||
|
floorOverlays[it.id] = definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
157
src/main/kotlin/cacheops/cache/definition/decoder/FloorOverlayDecoder.kt
vendored
Normal file
157
src/main/kotlin/cacheops/cache/definition/decoder/FloorOverlayDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import cacheops.cache.definition.data.OverlayDefinition
|
||||||
|
import ext.medium
|
||||||
|
import ext.unsignedByte
|
||||||
|
import ext.unsignedShort
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
class FloorOverlayDecoder {
|
||||||
|
|
||||||
|
private var color = 0
|
||||||
|
private var texture = -1
|
||||||
|
private var hideUnderlay = true
|
||||||
|
private var blendColor = -1
|
||||||
|
private var anInt3081 = 0
|
||||||
|
private var scale = 128
|
||||||
|
private var blockShadow = true
|
||||||
|
private var aByte0 = 8
|
||||||
|
private var blendTexture = false
|
||||||
|
private var waterColor = 1190717
|
||||||
|
private var waterScale = 16
|
||||||
|
private var anInt0 = -1
|
||||||
|
private var waterIntensity = 16
|
||||||
|
|
||||||
|
fun decode(buffer: ByteBuffer): OverlayDefinition {
|
||||||
|
while (true) {
|
||||||
|
val opcode = buffer.unsignedByte()
|
||||||
|
if (opcode == 0) {
|
||||||
|
return OverlayDefinition(color, texture, hideUnderlay, blendColor, scale, blockShadow, aByte0, blendTexture, waterColor, waterScale, anInt0, waterIntensity)
|
||||||
|
}
|
||||||
|
decodeOverlayType(opcode, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overlay Type Decoder
|
||||||
|
*
|
||||||
|
* Takes the standard params for a decoder, [opcode], [rsByteBuffer] and a [ID].
|
||||||
|
*
|
||||||
|
* Currently opcode [10] is unknown.
|
||||||
|
*/
|
||||||
|
private fun decodeOverlayType(opcode: Int, buffer: ByteBuffer) {
|
||||||
|
|
||||||
|
when (opcode) {
|
||||||
|
1 -> color = buffer.medium()//rgbToHsl(buffer.medium())
|
||||||
|
2 -> texture = buffer.unsignedByte()
|
||||||
|
3 -> {
|
||||||
|
texture = buffer.unsignedShort()
|
||||||
|
if (texture == 65535) {
|
||||||
|
texture = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
5 -> hideUnderlay = false
|
||||||
|
7 -> blendColor = buffer.medium()//rgbToHsl(buffer.medium())
|
||||||
|
8 -> anInt3081
|
||||||
|
9 -> scale = buffer.unsignedShort()
|
||||||
|
10 -> blockShadow = false //Possibly blockShadow?
|
||||||
|
11 -> aByte0 = buffer.unsignedByte()
|
||||||
|
12 -> blendTexture = true
|
||||||
|
13 -> waterColor = buffer.medium()
|
||||||
|
14 -> waterScale = buffer.unsignedByte()
|
||||||
|
15 -> {
|
||||||
|
anInt0 = buffer.unsignedShort()
|
||||||
|
if (anInt0 == 65535) {
|
||||||
|
anInt0 = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
16 -> waterIntensity = buffer.unsignedByte()
|
||||||
|
/* 14
|
||||||
|
* Handles how deep into water the player is able to see,
|
||||||
|
* seems to (but not confirmed) work in jumps of 2, so: "0, 2, 4, 6" etc.
|
||||||
|
* It seems any number equals to or less than 0, removes any visual
|
||||||
|
* effect obscuring the depth view. The first increment in order,
|
||||||
|
* being 2, blocks almost 100% of the view of the underwater map (UM).
|
||||||
|
*/
|
||||||
|
else -> println("Unhandled opcode $opcode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rgbToHsl(rgb: Int): Int {
|
||||||
|
if (rgb == 16711935) {
|
||||||
|
return -1
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
val d = (((0xff80ae and rgb) shr 16).toDouble() / 256.0)
|
||||||
|
val d_8_ = (((0xff6a and rgb) shr 8).toDouble() / 256.0)
|
||||||
|
val d_9_ = ((rgb and 0xff).toDouble() / 256.0)
|
||||||
|
var d_11_ = d
|
||||||
|
if (d_11_ > d_8_) {
|
||||||
|
d_11_ = d_8_
|
||||||
|
}
|
||||||
|
if (d_11_ > d_9_) {
|
||||||
|
d_11_ = d_9_
|
||||||
|
}
|
||||||
|
var d_12_ = d
|
||||||
|
if (d_8_ > d_12_) {
|
||||||
|
d_12_ = d_8_
|
||||||
|
}
|
||||||
|
if (d_12_ < d_9_) {
|
||||||
|
d_12_ = d_9_
|
||||||
|
}
|
||||||
|
var h = 0.0
|
||||||
|
var s = 0.0
|
||||||
|
val l = (d_12_ + d_11_) / 2.0
|
||||||
|
if (d_11_ != d_12_) {
|
||||||
|
if (l < 0.5) {
|
||||||
|
s = (-d_11_ + d_12_) / (d_12_ + d_11_)
|
||||||
|
}
|
||||||
|
if (l >= 0.5) {
|
||||||
|
s = (d_12_ - d_11_) / (-d_12_ + 2.0 - d_11_)
|
||||||
|
}
|
||||||
|
if (d_12_ == d) {
|
||||||
|
h = (d_8_ - d_9_) / (d_12_ - d_11_)
|
||||||
|
} else if (d_12_ == d_8_) {
|
||||||
|
h = (-d + d_9_) / (-d_11_ + d_12_) + 2.0
|
||||||
|
} else if (d_12_ == d_9_) {
|
||||||
|
h = (d - d_8_) / (d_12_ - d_11_) + 4.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h /= 6.0
|
||||||
|
|
||||||
|
val hue = (h * 256.0).toInt()
|
||||||
|
var saturation = (s * 256.0).toInt()
|
||||||
|
var lumiance = (l * 256.0).toInt()
|
||||||
|
|
||||||
|
if (saturation >= 0) {
|
||||||
|
if (saturation > 255) {
|
||||||
|
saturation = 255
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
saturation = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lumiance >= 0) {
|
||||||
|
if (lumiance > 255) {
|
||||||
|
lumiance = 255
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lumiance = 0
|
||||||
|
}
|
||||||
|
if (lumiance > 243) {
|
||||||
|
saturation = (saturation shr 4)
|
||||||
|
} else if (lumiance <= 217) {
|
||||||
|
if (lumiance > 192) {
|
||||||
|
saturation = (saturation shr 2)
|
||||||
|
} else if (lumiance > 179) {
|
||||||
|
saturation = (saturation shr 1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
saturation = (saturation shr 3)
|
||||||
|
}
|
||||||
|
return ((((hue and 0xff) shr 2) shl 10) + ((saturation shr 5) shl 7) + (lumiance shr 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
33
src/main/kotlin/cacheops/cache/definition/decoder/FloorUnderlayConfiguration.kt
vendored
Normal file
33
src/main/kotlin/cacheops/cache/definition/decoder/FloorUnderlayConfiguration.kt
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.data.UnderlayDefinition
|
||||||
|
import const.Archives
|
||||||
|
import const.Indices
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
object FloorUnderlayConfiguration {
|
||||||
|
|
||||||
|
val cache = Rs2MapEditor.library.index(Indices.CONFIGURATION).archive(Archives.FLOOR_UNDERLAYS)
|
||||||
|
|
||||||
|
var floorUnderlays = hashMapOf<Int, UnderlayDefinition>()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
cache!!.files().forEach {
|
||||||
|
val buffer = ByteBuffer.wrap(it.data)
|
||||||
|
val definition = FloorUnderlayDecoder().decode(buffer)
|
||||||
|
floorUnderlays[it.id] = definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
cache!!.files().forEach {
|
||||||
|
val buffer = ByteBuffer.wrap(it.data)
|
||||||
|
val definition = FloorUnderlayDecoder().decode(buffer)
|
||||||
|
floorUnderlays[it.id] = definition
|
||||||
|
//println(definition.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
132
src/main/kotlin/cacheops/cache/definition/decoder/FloorUnderlayDecoder.kt
vendored
Normal file
132
src/main/kotlin/cacheops/cache/definition/decoder/FloorUnderlayDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import cacheops.cache.definition.data.UnderlayDefinition
|
||||||
|
import ext.medium
|
||||||
|
import ext.unsignedByte
|
||||||
|
import ext.unsignedShort
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
class FloorUnderlayDecoder {
|
||||||
|
|
||||||
|
private var color: Int = 0
|
||||||
|
private var hsl16: Int = 0
|
||||||
|
private var blendHueMultiplier: Int = 0
|
||||||
|
private var hue: Int = 0
|
||||||
|
private var saturation: Int = 0
|
||||||
|
private var lumiance: Int = 0
|
||||||
|
private var textureID = -1
|
||||||
|
private var textureSize = 128
|
||||||
|
private var blockShadow = true
|
||||||
|
private var blendHue: Int = 0
|
||||||
|
|
||||||
|
fun decode(buffer: ByteBuffer): UnderlayDefinition {
|
||||||
|
while (true) {
|
||||||
|
val opcode = buffer.unsignedByte()
|
||||||
|
if (opcode == 0) {
|
||||||
|
return UnderlayDefinition(color, hue, saturation, lumiance, textureID, textureSize, blockShadow, blendHueMultiplier, blendHue)
|
||||||
|
}
|
||||||
|
decodeUnderlayType(opcode, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun decodeUnderlayType(opcode: Int, buffer: ByteBuffer) {
|
||||||
|
when (opcode) {
|
||||||
|
1 -> {
|
||||||
|
color = buffer.medium()
|
||||||
|
intToColor(color)
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
textureID = buffer.unsignedShort()
|
||||||
|
if (textureID == 65535) {
|
||||||
|
textureID = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
textureSize = buffer.unsignedShort()
|
||||||
|
}
|
||||||
|
4 -> {
|
||||||
|
blockShadow = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun intToColor(rgb: Int) {
|
||||||
|
val r: Double = (rgb shr 16 and 0xff) / 256.0
|
||||||
|
val g: Double = (rgb shr 8 and 0xff) / 256.0
|
||||||
|
val b: Double = (rgb and 0xff) / 256.0
|
||||||
|
var min = r
|
||||||
|
if (g < min) {
|
||||||
|
min = g
|
||||||
|
}
|
||||||
|
if (b < min) {
|
||||||
|
min = b
|
||||||
|
}
|
||||||
|
var max = r
|
||||||
|
if (g > max) {
|
||||||
|
max = g
|
||||||
|
}
|
||||||
|
if (b > max) {
|
||||||
|
max = b
|
||||||
|
}
|
||||||
|
var h = 0.0
|
||||||
|
var s = 0.0
|
||||||
|
val l = (min + max) / 2.0
|
||||||
|
if (min != max) {
|
||||||
|
if (l < 0.5) {
|
||||||
|
s = (max - min) / (max + min)
|
||||||
|
}
|
||||||
|
if (l >= 0.5) {
|
||||||
|
s = (max - min) / (2.0 - max - min)
|
||||||
|
}
|
||||||
|
if (r == max) {
|
||||||
|
h = (g - b) / (max - min)
|
||||||
|
} else if (g == max) {
|
||||||
|
h = 2.0 + (b - r) / (max - min)
|
||||||
|
} else if (b == max) {
|
||||||
|
h = 4.0 + (r - g) / (max - min)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h /= 6.0
|
||||||
|
hue = (h * 256.0).toInt()
|
||||||
|
saturation = (s * 256.0).toInt()
|
||||||
|
lumiance = (l * 256.0).toInt()
|
||||||
|
if (saturation < 0) {
|
||||||
|
saturation = 0
|
||||||
|
} else if (saturation > 255) {
|
||||||
|
saturation = 255
|
||||||
|
}
|
||||||
|
if (lumiance < 0) {
|
||||||
|
lumiance = 0
|
||||||
|
} else if (lumiance > 255) {
|
||||||
|
lumiance = 255
|
||||||
|
}
|
||||||
|
blendHueMultiplier = if (l > 0.5) {
|
||||||
|
((1.0 - l) * s * 512.0).toInt()
|
||||||
|
} else {
|
||||||
|
(l * s * 512.0).toInt()
|
||||||
|
}
|
||||||
|
if (blendHueMultiplier < 1) {
|
||||||
|
blendHueMultiplier = 1
|
||||||
|
}
|
||||||
|
blendHue = (h * blendHueMultiplier).toInt()
|
||||||
|
hsl16 = hsl24to16(hue, saturation, lumiance)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun hsl24to16(h: Int, s: Int, l: Int): Int {
|
||||||
|
var s = s
|
||||||
|
if (l > 179) {
|
||||||
|
s /= 2
|
||||||
|
}
|
||||||
|
if (l > 192) {
|
||||||
|
s /= 2
|
||||||
|
}
|
||||||
|
if (l > 217) {
|
||||||
|
s /= 2
|
||||||
|
}
|
||||||
|
if (l > 243) {
|
||||||
|
s /= 2
|
||||||
|
}
|
||||||
|
return (h / (4 shl 10)) + (s / (32 shl 7)) + l / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/main/kotlin/cacheops/cache/definition/decoder/GroundItemDecoder.kt
vendored
Normal file
53
src/main/kotlin/cacheops/cache/definition/decoder/GroundItemDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.data.ItemDefinition
|
||||||
|
import const.cache
|
||||||
|
import ext.unsignedShort
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
val itemDecoder = ItemDecoder(cache)
|
||||||
|
|
||||||
|
class GroundItemDecoder {
|
||||||
|
|
||||||
|
fun decode(data: ByteArray): ArrayList<Item> {
|
||||||
|
|
||||||
|
val buffer = ByteBuffer.wrap(data)
|
||||||
|
val list = ArrayList<Item>()
|
||||||
|
|
||||||
|
while (buffer.hasRemaining()) {
|
||||||
|
val coords = buffer.unsignedShort()
|
||||||
|
|
||||||
|
val lz = coords shr 14
|
||||||
|
val lx = (coords shr 7) and 0x3f
|
||||||
|
val ly = coords and 0x3f
|
||||||
|
|
||||||
|
val itemID = buffer.unsignedShort()
|
||||||
|
|
||||||
|
val respawnTime = buffer.unsignedShort()
|
||||||
|
|
||||||
|
val amount = buffer.int
|
||||||
|
|
||||||
|
list.add(Item(itemID, lx, ly, lz, respawnTime, amount))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object GroundItemSpawnParser {
|
||||||
|
|
||||||
|
fun parseItemSpawns(regionId: Int): ArrayList<Item> {
|
||||||
|
val x = (regionId shr 8) and 0xFF
|
||||||
|
val y = regionId and 0xFF
|
||||||
|
val groundItemData = Rs2MapEditor.library.data(5, "i${x}_${y}")
|
||||||
|
|
||||||
|
if (groundItemData != null && groundItemData.isNotEmpty()) {
|
||||||
|
return GroundItemDecoder().decode(groundItemData)
|
||||||
|
}
|
||||||
|
return ArrayList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Item(val id: Int, val x: Int, val y: Int, val plane: Int, val respawnTime: Int, val amount: Int) {
|
||||||
|
val definition: ItemDefinition = itemDecoder.forId(id)
|
||||||
|
}
|
||||||
251
src/main/kotlin/cacheops/cache/definition/decoder/ItemDecoder.kt
vendored
Normal file
251
src/main/kotlin/cacheops/cache/definition/decoder/ItemDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import cacheops.cache.Cache
|
||||||
|
import cacheops.cache.DefinitionDecoder
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
import cacheops.cache.definition.data.ItemDefinition
|
||||||
|
import const.Indices
|
||||||
|
|
||||||
|
class ItemDecoder(cache: Cache) : DefinitionDecoder<ItemDefinition>(cache, Indices.CONFIGURATION_ITEMS) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val DEFINITIONS = HashMap<Int, ItemDefinition>()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun create() = ItemDefinition()
|
||||||
|
|
||||||
|
override fun getFile(id: Int) = id and 0xff
|
||||||
|
|
||||||
|
override fun getArchive(id: Int) = id ushr 8
|
||||||
|
|
||||||
|
override fun readData(id: Int): ItemDefinition? {
|
||||||
|
return super.readData(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forId(id : Int): ItemDefinition {
|
||||||
|
if(DEFINITIONS[id] != null) return DEFINITIONS[id]!!
|
||||||
|
val def = readData(id)
|
||||||
|
DEFINITIONS[id] = def ?: ItemDefinition(id, 0, "null")
|
||||||
|
return DEFINITIONS[id]!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ItemDefinition.read(opcode: Int, buffer: Reader) {
|
||||||
|
when (opcode) {
|
||||||
|
1 -> modelId = buffer.readShort()
|
||||||
|
2 -> name = buffer.readString()
|
||||||
|
4 -> spriteScale = buffer.readShort()
|
||||||
|
5 -> spritePitch = buffer.readShort()
|
||||||
|
6 -> spriteCameraRoll = buffer.readShort()
|
||||||
|
7 -> {
|
||||||
|
spriteTranslateX = buffer.readShort()
|
||||||
|
if (spriteTranslateX > 32767) {
|
||||||
|
spriteTranslateX -= 65536
|
||||||
|
}
|
||||||
|
}
|
||||||
|
8 -> {
|
||||||
|
spriteTranslateY = buffer.readShort()
|
||||||
|
if (spriteTranslateY > 32767) {
|
||||||
|
spriteTranslateY -= 65536
|
||||||
|
}
|
||||||
|
}
|
||||||
|
11 -> stackable = 1
|
||||||
|
12 -> cost = buffer.readInt()
|
||||||
|
16 -> members = true
|
||||||
|
18 -> multiStackSize = buffer.readShort()
|
||||||
|
23 -> primaryMaleModel = buffer.readUnsignedShort()
|
||||||
|
24 -> secondaryMaleModel = buffer.readUnsignedShort()
|
||||||
|
25 -> primaryFemaleModel = buffer.readUnsignedShort()
|
||||||
|
26 -> secondaryFemaleModel = buffer.readUnsignedShort()
|
||||||
|
in 30..34 -> floorOptions[opcode - 30] = buffer.readString()
|
||||||
|
in 35..39 -> options[opcode - 35] = buffer.readString()
|
||||||
|
40 -> readColours(buffer)
|
||||||
|
41 -> readTextures(buffer)
|
||||||
|
42 -> readColourPalette(buffer)
|
||||||
|
65 -> exchangeable = true
|
||||||
|
78 -> tertiaryMaleModel = buffer.readShort()
|
||||||
|
79 -> tertiaryFemaleModel = buffer.readShort()
|
||||||
|
90 -> primaryMaleDialogueHead = buffer.readShort()
|
||||||
|
91 -> primaryFemaleDialogueHead = buffer.readShort()
|
||||||
|
92 -> secondaryMaleDialogueHead = buffer.readShort()
|
||||||
|
93 -> secondaryFemaleDialogueHead = buffer.readShort()
|
||||||
|
95 -> spriteCameraYaw = buffer.readShort()
|
||||||
|
96 -> dummyItem = buffer.readUnsignedByte()
|
||||||
|
97 -> noteId = buffer.readShort()
|
||||||
|
98 -> notedTemplateId = buffer.readShort()
|
||||||
|
in 100..109 -> {
|
||||||
|
if (stackIds == null) {
|
||||||
|
stackAmounts = IntArray(10)
|
||||||
|
stackIds = IntArray(10)
|
||||||
|
}
|
||||||
|
stackIds!![opcode - 100] = buffer.readShort()
|
||||||
|
stackAmounts!![opcode - 100] = buffer.readShort()
|
||||||
|
}
|
||||||
|
110 -> floorScaleX = buffer.readShort()
|
||||||
|
111 -> floorScaleZ = buffer.readShort()
|
||||||
|
112 -> floorScaleY = buffer.readShort()
|
||||||
|
113 -> ambience = buffer.readByte()
|
||||||
|
114 -> diffusion = buffer.readByte() * 5
|
||||||
|
115 -> team = buffer.readUnsignedByte()
|
||||||
|
121 -> lendId = buffer.readShort()
|
||||||
|
122 -> lendTemplateId = buffer.readShort()
|
||||||
|
125 -> {
|
||||||
|
maleWieldX = buffer.readByte() shl 2
|
||||||
|
maleWieldZ = buffer.readByte() shl 2
|
||||||
|
maleWieldY = buffer.readByte() shl 2
|
||||||
|
}
|
||||||
|
126 -> {
|
||||||
|
femaleWieldX = buffer.readByte() shl 2
|
||||||
|
femaleWieldZ = buffer.readByte() shl 2
|
||||||
|
femaleWieldY = buffer.readByte() shl 2
|
||||||
|
}
|
||||||
|
127 -> {
|
||||||
|
primaryCursorOpcode = buffer.readUnsignedByte()
|
||||||
|
primaryCursor = buffer.readShort()
|
||||||
|
}
|
||||||
|
128 -> {
|
||||||
|
secondaryCursorOpcode = buffer.readUnsignedByte()
|
||||||
|
secondaryCursor = buffer.readShort()
|
||||||
|
}
|
||||||
|
129 -> {
|
||||||
|
primaryInterfaceCursorOpcode = buffer.readUnsignedByte()
|
||||||
|
primaryInterfaceCursor = buffer.readShort()
|
||||||
|
}
|
||||||
|
130 -> {
|
||||||
|
secondaryInterfaceCursorOpcode = buffer.readUnsignedByte()
|
||||||
|
secondaryInterfaceCursor = buffer.readShort()
|
||||||
|
}
|
||||||
|
132 -> {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
campaigns = IntArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
campaigns!![count] = buffer.readShort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
134 -> pickSizeShift = buffer.readUnsignedByte()
|
||||||
|
139 -> singleNoteId = buffer.readShort()
|
||||||
|
140 -> singleNoteTemplateId = buffer.readShort()
|
||||||
|
249 -> readParameters(buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ItemDefinition.changeValues() {
|
||||||
|
if (notedTemplateId != -1) {
|
||||||
|
toNote(getOrNull(notedTemplateId), getOrNull(noteId))
|
||||||
|
}
|
||||||
|
if (lendTemplateId != -1) {
|
||||||
|
toLend(getOrNull(lendId), getOrNull(lendTemplateId))
|
||||||
|
}
|
||||||
|
if (singleNoteTemplateId != -1) {
|
||||||
|
toSingleNote(getOrNull(singleNoteTemplateId), getOrNull(singleNoteId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ItemDefinition.toLend(item: ItemDefinition?, template: ItemDefinition?) {
|
||||||
|
if (item == null || template == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
modifiedColours = item.modifiedColours
|
||||||
|
primaryMaleDialogueHead = item.primaryMaleDialogueHead
|
||||||
|
secondaryMaleDialogueHead = item.secondaryMaleDialogueHead
|
||||||
|
tertiaryMaleModel = item.tertiaryMaleModel
|
||||||
|
team = item.team
|
||||||
|
params = item.params
|
||||||
|
members = item.members
|
||||||
|
modifiedTextureColours = item.modifiedTextureColours
|
||||||
|
maleWieldZ = item.maleWieldZ
|
||||||
|
secondaryFemaleModel = item.secondaryFemaleModel
|
||||||
|
spriteCameraYaw = template.spriteCameraYaw
|
||||||
|
floorOptions = item.floorOptions
|
||||||
|
secondaryFemaleDialogueHead = item.secondaryFemaleDialogueHead
|
||||||
|
recolourPalette = item.recolourPalette
|
||||||
|
femaleWieldZ = item.femaleWieldZ
|
||||||
|
spritePitch = template.spritePitch
|
||||||
|
primaryFemaleModel = item.primaryFemaleModel
|
||||||
|
modelId = template.modelId
|
||||||
|
options = arrayOfNulls(5)
|
||||||
|
spriteCameraRoll = template.spriteCameraRoll
|
||||||
|
spriteTranslateY = template.spriteTranslateY
|
||||||
|
originalTextureColours = item.originalTextureColours
|
||||||
|
femaleWieldX = item.femaleWieldX
|
||||||
|
secondaryMaleModel = item.secondaryMaleModel
|
||||||
|
cost = 0
|
||||||
|
maleWieldY = item.maleWieldY
|
||||||
|
originalColours = item.originalColours
|
||||||
|
spriteTranslateX = template.spriteTranslateX
|
||||||
|
femaleWieldY = item.femaleWieldY
|
||||||
|
primaryFemaleDialogueHead = item.primaryFemaleDialogueHead
|
||||||
|
spriteScale = template.spriteScale
|
||||||
|
name = item.name
|
||||||
|
tertiaryFemaleModel = item.tertiaryFemaleModel
|
||||||
|
primaryMaleModel = item.primaryMaleModel
|
||||||
|
maleWieldX = item.maleWieldX
|
||||||
|
System.arraycopy(item.options, 0, options, 0, 4)
|
||||||
|
options[4] = "Discard"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ItemDefinition.toNote(template: ItemDefinition?, item: ItemDefinition?) {
|
||||||
|
if (item == null || template == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
spriteTranslateY = template.spriteTranslateY
|
||||||
|
originalColours = template.originalColours
|
||||||
|
cost = item.cost
|
||||||
|
name = item.name
|
||||||
|
modifiedTextureColours = template.modifiedTextureColours
|
||||||
|
spriteCameraRoll = template.spriteCameraRoll
|
||||||
|
spriteCameraYaw = template.spriteCameraYaw
|
||||||
|
originalTextureColours = template.originalTextureColours
|
||||||
|
modelId = template.modelId
|
||||||
|
spriteScale = template.spriteScale
|
||||||
|
recolourPalette = template.recolourPalette
|
||||||
|
stackable = 1
|
||||||
|
spritePitch = template.spritePitch
|
||||||
|
spriteTranslateX = template.spriteTranslateX
|
||||||
|
members = item.members
|
||||||
|
modifiedColours = template.modifiedColours
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ItemDefinition.toSingleNote(template: ItemDefinition?, item: ItemDefinition?) {
|
||||||
|
if (item == null || template == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cost = 0
|
||||||
|
tertiaryMaleModel = item.tertiaryMaleModel
|
||||||
|
stackable = item.stackable
|
||||||
|
members = item.members
|
||||||
|
recolourPalette = item.recolourPalette
|
||||||
|
spriteTranslateY = template.spriteTranslateY
|
||||||
|
team = item.team
|
||||||
|
secondaryMaleModel = item.secondaryMaleModel
|
||||||
|
options = arrayOfNulls(5)
|
||||||
|
floorOptions = item.floorOptions
|
||||||
|
maleWieldZ = item.maleWieldZ
|
||||||
|
primaryMaleDialogueHead = item.primaryMaleDialogueHead
|
||||||
|
femaleWieldZ = item.femaleWieldZ
|
||||||
|
name = item.name
|
||||||
|
spriteScale = template.spriteScale
|
||||||
|
originalColours = item.originalColours
|
||||||
|
secondaryFemaleDialogueHead = item.secondaryFemaleDialogueHead
|
||||||
|
params = item.params
|
||||||
|
primaryFemaleModel = item.primaryFemaleModel
|
||||||
|
spritePitch = template.spritePitch
|
||||||
|
spriteCameraRoll = template.spriteCameraRoll
|
||||||
|
femaleWieldX = item.femaleWieldX
|
||||||
|
secondaryMaleDialogueHead = item.secondaryMaleDialogueHead
|
||||||
|
tertiaryFemaleModel = item.tertiaryFemaleModel
|
||||||
|
modifiedTextureColours = item.modifiedTextureColours
|
||||||
|
maleWieldX = item.maleWieldX
|
||||||
|
primaryFemaleDialogueHead = item.primaryFemaleDialogueHead
|
||||||
|
modelId = template.modelId
|
||||||
|
modifiedColours = item.modifiedColours
|
||||||
|
secondaryFemaleModel = item.secondaryFemaleModel
|
||||||
|
spriteTranslateX = template.spriteTranslateX
|
||||||
|
spriteCameraYaw = template.spriteCameraYaw
|
||||||
|
primaryMaleModel = item.primaryMaleModel
|
||||||
|
femaleWieldY = item.femaleWieldY
|
||||||
|
maleWieldY = item.maleWieldY
|
||||||
|
originalTextureColours = item.originalTextureColours
|
||||||
|
System.arraycopy(item.options, 0, options, 0, 4)
|
||||||
|
options[4] = "Discard"
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/main/kotlin/cacheops/cache/definition/decoder/MapTileDecoder.kt
vendored
Normal file
48
src/main/kotlin/cacheops/cache/definition/decoder/MapTileDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import cacheops.cache.definition.data.MapDefinition
|
||||||
|
import cacheops.cache.definition.data.MapTile
|
||||||
|
import ext.unsignedByte
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
class MapTileDecoder {
|
||||||
|
|
||||||
|
fun readLoop(definition: MapDefinition, buffer: ByteBuffer): ByteArray {
|
||||||
|
|
||||||
|
for (plane in 0 until 4) {
|
||||||
|
for (localX in 0 until 64) {
|
||||||
|
for (localY in 0 until 64) {
|
||||||
|
var height = 0
|
||||||
|
var attrOpcode = 0
|
||||||
|
var overlayPath = 0
|
||||||
|
var overlayRotation = 0
|
||||||
|
var overlayId = 0
|
||||||
|
var settings = 0
|
||||||
|
var underlayId = 0
|
||||||
|
loop@ while (true) {
|
||||||
|
val config = buffer.unsignedByte()
|
||||||
|
if (config == 0) {
|
||||||
|
break@loop
|
||||||
|
} else if (config == 1) {
|
||||||
|
height = buffer.unsignedByte()
|
||||||
|
break@loop
|
||||||
|
} else if (config <= 49) {
|
||||||
|
attrOpcode = config
|
||||||
|
overlayId = buffer.unsignedByte()
|
||||||
|
overlayPath = (config - 2) / 4
|
||||||
|
overlayRotation = 3 and (config - 2)
|
||||||
|
} else if (config <= 81) {
|
||||||
|
settings = config - 49
|
||||||
|
} else {
|
||||||
|
underlayId = (config - 81) and 0xff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (height != 0 || attrOpcode != 0 || overlayPath != 0 || overlayRotation != 0 || overlayId != 0 || settings != 0 || underlayId != 0) {
|
||||||
|
definition.setTile(localX, localY, plane, MapTile(height, attrOpcode, if(overlayId == 42) 0 else overlayId, overlayPath, overlayRotation, settings, underlayId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.array().copyOfRange(buffer.position(), buffer.capacity())
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/main/kotlin/cacheops/cache/definition/decoder/MapTileParser.kt
vendored
Normal file
55
src/main/kotlin/cacheops/cache/definition/decoder/MapTileParser.kt
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.data.MapDefinition
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
object MapTileParser {
|
||||||
|
|
||||||
|
val definition = MapDefinition()
|
||||||
|
|
||||||
|
lateinit var atmosphereDataTail: ByteArray
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
|
||||||
|
val region = 12850
|
||||||
|
val baseX = ((region shr 8) shl 6)
|
||||||
|
val baseY = ((region and 0xFF) shl 6)
|
||||||
|
val x = (region shr 8) and 0xFF
|
||||||
|
val y = region and 0xFF
|
||||||
|
val mapData = Rs2MapEditor.library.data(5,"m${x}_${y}")
|
||||||
|
|
||||||
|
MapTileDecoder().readLoop(definition, ByteBuffer.wrap(mapData))
|
||||||
|
|
||||||
|
for (lclX in 0 until 64) {
|
||||||
|
for (lclY in 0 until 64) {
|
||||||
|
println(definition.getTile(lclX,lclY,0).underlayId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
definition.objects.clear()
|
||||||
|
definition.tiles.clear()
|
||||||
|
val region = Rs2MapEditor.region
|
||||||
|
val baseX = ((region shr 8) shl 6)
|
||||||
|
val baseY = ((region and 0xFF) shl 6)
|
||||||
|
val x = (region shr 8) and 0xFF
|
||||||
|
val y = region and 0xFF
|
||||||
|
val mapData = Rs2MapEditor.library.data(5,"m${x}_${y}")
|
||||||
|
println(mapData!!.size)
|
||||||
|
atmosphereDataTail = MapTileDecoder().readLoop(definition, ByteBuffer.wrap(mapData))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun coordinateX(x: Int): Int {
|
||||||
|
val baseX = ((Rs2MapEditor.region shr 8) shl 6)
|
||||||
|
return x + baseX
|
||||||
|
}
|
||||||
|
|
||||||
|
fun coordinateY(y: Int): Int {
|
||||||
|
val baseY = ((Rs2MapEditor.region and 0xFF) shl 6)
|
||||||
|
return y + baseY
|
||||||
|
}
|
||||||
|
}
|
||||||
194
src/main/kotlin/cacheops/cache/definition/decoder/NPCDecoder.kt
vendored
Normal file
194
src/main/kotlin/cacheops/cache/definition/decoder/NPCDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import cacheops.cache.Cache
|
||||||
|
import cacheops.cache.DefinitionDecoder
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
import cacheops.cache.definition.data.NPCDefinition
|
||||||
|
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 ?: NPCDefinition(id,null,"null")
|
||||||
|
return DEFINITIONS[id]!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun NPCDefinition.read(opcode: Int, buffer: Reader) {
|
||||||
|
when (opcode) {
|
||||||
|
1 -> {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
modelIds = IntArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
modelIds!![count] = buffer.readShort()
|
||||||
|
if (modelIds!![count] == 65535) {
|
||||||
|
modelIds!![count] = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 -> name = buffer.readString()
|
||||||
|
12 -> size = buffer.readUnsignedByte()
|
||||||
|
in 30..34 -> options[-30 + opcode] = buffer.readString()
|
||||||
|
40 -> readColours(buffer)
|
||||||
|
41 -> readTextures(buffer)
|
||||||
|
42 -> {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
recolourPalette = ByteArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
recolourPalette!![count] = buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
60 -> {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
dialogueModels = IntArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
dialogueModels!![count] = buffer.readShort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
93 -> drawMinimapDot = false
|
||||||
|
95 -> combat = buffer.readShort()
|
||||||
|
97 -> scaleXY = buffer.readShort()
|
||||||
|
98 -> scaleZ = buffer.readShort()
|
||||||
|
99 -> priorityRender = true
|
||||||
|
100 -> lightModifier = buffer.readByte()
|
||||||
|
101 -> shadowModifier = 5 * buffer.readByte()
|
||||||
|
102 -> headIcon = buffer.readShort()
|
||||||
|
103 -> rotation = buffer.readShort()
|
||||||
|
106, 118 -> {
|
||||||
|
varbit = buffer.readShort()
|
||||||
|
if (varbit == 65535) {
|
||||||
|
varbit = -1
|
||||||
|
}
|
||||||
|
varp = buffer.readShort()
|
||||||
|
if (varp == 65535) {
|
||||||
|
varp = -1
|
||||||
|
}
|
||||||
|
var last = -1
|
||||||
|
if (opcode == 118) {
|
||||||
|
last = buffer.readShort()
|
||||||
|
if (last == 65535) {
|
||||||
|
last = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val count = buffer.readUnsignedByte()
|
||||||
|
morphs = IntArray(count + 2)
|
||||||
|
for (index in 0..count) {
|
||||||
|
morphs!![index] = buffer.readShort()
|
||||||
|
if (morphs!![index] == 65535) {
|
||||||
|
morphs!![index] = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
morphs!![count + 1] = last
|
||||||
|
}
|
||||||
|
107 -> clickable = false
|
||||||
|
109 -> slowWalk = false
|
||||||
|
111 -> animateIdle = false
|
||||||
|
113 -> {
|
||||||
|
primaryShadowColour = buffer.readShort().toShort()
|
||||||
|
secondaryShadowColour = buffer.readShort().toShort()
|
||||||
|
}
|
||||||
|
114 -> {
|
||||||
|
primaryShadowModifier = buffer.readByte().toByte()
|
||||||
|
secondaryShadowModifier = buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
119 -> walkMask = buffer.readByte().toByte()
|
||||||
|
121 -> {
|
||||||
|
translations = arrayOfNulls(modelIds!!.size)
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
repeat(length) {
|
||||||
|
val index = buffer.readUnsignedByte()
|
||||||
|
translations!![index] = intArrayOf(
|
||||||
|
buffer.readByte(),
|
||||||
|
buffer.readByte(),
|
||||||
|
buffer.readByte()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
122 -> hitbarSprite = buffer.readShort()
|
||||||
|
123 -> height = buffer.readShort()
|
||||||
|
125 -> respawnDirection = buffer.readByte().toByte()
|
||||||
|
127 -> renderEmote = buffer.readShort()
|
||||||
|
128 -> buffer.readUnsignedByte()
|
||||||
|
134 -> {
|
||||||
|
idleSound = buffer.readShort()
|
||||||
|
if (idleSound == 65535) {
|
||||||
|
idleSound = -1
|
||||||
|
}
|
||||||
|
crawlSound = buffer.readShort()
|
||||||
|
if (crawlSound == 65535) {
|
||||||
|
crawlSound = -1
|
||||||
|
}
|
||||||
|
walkSound = buffer.readShort()
|
||||||
|
if (walkSound == 65535) {
|
||||||
|
walkSound = -1
|
||||||
|
}
|
||||||
|
runSound = buffer.readShort()
|
||||||
|
if (runSound == 65535) {
|
||||||
|
runSound = -1
|
||||||
|
}
|
||||||
|
soundDistance = buffer.readUnsignedByte()
|
||||||
|
}
|
||||||
|
135 -> {
|
||||||
|
primaryCursorOp = buffer.readUnsignedByte()
|
||||||
|
primaryCursor = buffer.readShort()
|
||||||
|
}
|
||||||
|
136 -> {
|
||||||
|
secondaryCursorOp = buffer.readUnsignedByte()
|
||||||
|
secondaryCursor = buffer.readShort()
|
||||||
|
}
|
||||||
|
137 -> attackCursor = buffer.readShort()
|
||||||
|
138 -> armyIcon = buffer.readShort()
|
||||||
|
139 -> spriteId = buffer.readShort()
|
||||||
|
140 -> ambientSoundVolume = buffer.readUnsignedByte()
|
||||||
|
141 -> visiblePriority = true
|
||||||
|
142 -> mapFunction = buffer.readShort()
|
||||||
|
143 -> invisiblePriority = true
|
||||||
|
in 150..154 -> {
|
||||||
|
options[opcode - 150] = buffer.readString()
|
||||||
|
if (!member) {
|
||||||
|
options[opcode - 150] = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
155 -> {
|
||||||
|
hue = buffer.readByte().toByte()
|
||||||
|
saturation = buffer.readByte().toByte()
|
||||||
|
lightness = buffer.readByte().toByte()
|
||||||
|
opacity = buffer.readByte().toByte()
|
||||||
|
}
|
||||||
|
158 -> mainOptionIndex = 1.toByte()
|
||||||
|
159 -> mainOptionIndex = 0.toByte()
|
||||||
|
160 -> {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
campaigns = IntArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
campaigns!![count] = buffer.readShort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
162 -> aBoolean2883 = true
|
||||||
|
163 -> anInt2803 = buffer.readUnsignedByte()
|
||||||
|
164 -> {
|
||||||
|
anInt2844 = buffer.readShort()
|
||||||
|
anInt2852 = buffer.readShort()
|
||||||
|
}
|
||||||
|
165 -> anInt2831 = buffer.readUnsignedByte()
|
||||||
|
168 -> anInt2862 = buffer.readUnsignedByte()
|
||||||
|
249 -> readParameters(buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
48
src/main/kotlin/cacheops/cache/definition/decoder/NPCSpawnDecoder.kt
vendored
Normal file
48
src/main/kotlin/cacheops/cache/definition/decoder/NPCSpawnDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.data.NPCDefinition
|
||||||
|
import const.cache
|
||||||
|
import ext.unsignedShort
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
val decoder = NPCDecoder(cache, true)
|
||||||
|
|
||||||
|
class NPCSpawnDecoder {
|
||||||
|
|
||||||
|
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 lx = (coords shr 7) and 0x3f
|
||||||
|
val ly = coords and 0x3f
|
||||||
|
|
||||||
|
val npcID = buffer.unsignedShort()
|
||||||
|
list.add(NPC(npcID, lx, ly, lz))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object NPCSpawnParser {
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
237
src/main/kotlin/cacheops/cache/definition/decoder/ObjectDecoder.kt
vendored
Normal file
237
src/main/kotlin/cacheops/cache/definition/decoder/ObjectDecoder.kt
vendored
Normal file
|
|
@ -0,0 +1,237 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import cacheops.cache.Cache
|
||||||
|
import cacheops.cache.DefinitionDecoder
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
import cacheops.cache.definition.data.ObjectDefinition
|
||||||
|
import const.Indices
|
||||||
|
|
||||||
|
open class ObjectDecoder(cache: Cache, val member: Boolean, val configReplace: Boolean) : DefinitionDecoder<ObjectDefinition>(cache, Indices.CONFIGURATION_OBJECT) {
|
||||||
|
|
||||||
|
val DEFINITIONS = HashMap<Int,ObjectDefinition>()
|
||||||
|
|
||||||
|
fun forId(id: Int): ObjectDefinition{
|
||||||
|
if(DEFINITIONS[id] != null) return DEFINITIONS[id]!!
|
||||||
|
val def = readData(id)
|
||||||
|
DEFINITIONS[id] = def ?: ObjectDefinition(id,null,null,"null")
|
||||||
|
return DEFINITIONS[id]!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun create() = ObjectDefinition()
|
||||||
|
|
||||||
|
override fun getFile(id: Int) = id and 0xff
|
||||||
|
|
||||||
|
override fun getArchive(id: Int) = id ushr 8
|
||||||
|
|
||||||
|
override fun readData(id: Int): ObjectDefinition? {
|
||||||
|
val def = super.readData(id)
|
||||||
|
val replacement = def?.getReplacementId() ?: return def
|
||||||
|
return super.readData(replacement)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ObjectDefinition.getReplacementId(): Int? {
|
||||||
|
if (!configReplace) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val configIndex = 0
|
||||||
|
val configs = configObjectIds ?: return null
|
||||||
|
val config = if (configIndex < 0 || (configIndex >= configs.size - 1 || configs[configIndex] == -1)) {
|
||||||
|
configs[configs.size - 1]
|
||||||
|
} else {
|
||||||
|
configs.getOrNull(configIndex)
|
||||||
|
}
|
||||||
|
return if (config != -1) config else null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ObjectDefinition.read(opcode: Int, buffer: Reader) {
|
||||||
|
when (opcode) {
|
||||||
|
1 -> {
|
||||||
|
val count = buffer.readUnsignedByte()
|
||||||
|
if (count > 0) {
|
||||||
|
if (modelIds == null) {
|
||||||
|
modelIds = IntArray(count)
|
||||||
|
modelTypes = IntArray(count)
|
||||||
|
var i = 0
|
||||||
|
while (count > i) {
|
||||||
|
modelIds!![i] = buffer.readUnsignedShort()
|
||||||
|
modelTypes!![i] = buffer.readUnsignedByte()
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.position(buffer.position() + count * 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 -> name = buffer.readString()
|
||||||
|
5 -> {
|
||||||
|
val i_30_ = buffer.readUnsignedByte()
|
||||||
|
if (i_30_ > 0) {
|
||||||
|
if (modelIds == null) {
|
||||||
|
modelIds = IntArray(i_30_)
|
||||||
|
modelTypes = null
|
||||||
|
var i_31_ = 0
|
||||||
|
while (i_30_ > i_31_) {
|
||||||
|
modelIds!![i_31_] = buffer.readUnsignedShort()
|
||||||
|
i_31_++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.position(buffer.position() + i_30_ * 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
14 -> sizeX = buffer.readUnsignedByte()
|
||||||
|
15 -> sizeY = buffer.readUnsignedByte()
|
||||||
|
17 -> {
|
||||||
|
blocksSky = false
|
||||||
|
solid = 0
|
||||||
|
}
|
||||||
|
18 -> blocksSky = false
|
||||||
|
19 -> interactive = buffer.readUnsignedByte()
|
||||||
|
21 -> contouredGround = 1
|
||||||
|
22 -> delayShading = true
|
||||||
|
23 -> culling = 1
|
||||||
|
24 -> {
|
||||||
|
val length = buffer.readUnsignedShort()
|
||||||
|
if (length != 65535) {
|
||||||
|
animations = intArrayOf(length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
27 -> solid = 1
|
||||||
|
28 -> offsetMultiplier = buffer.readUnsignedByte()
|
||||||
|
29 -> brightness = buffer.readByte()
|
||||||
|
in 30..34 -> options[opcode - 30] = buffer.readString()
|
||||||
|
39 -> contrast = buffer.readByte() * 5
|
||||||
|
40 -> readColours(buffer)
|
||||||
|
41 -> readTextures(buffer)
|
||||||
|
42 -> readColourPalette(buffer)
|
||||||
|
62 -> mirrored = true
|
||||||
|
64 -> castsShadow = false
|
||||||
|
65 -> modelSizeX = buffer.readUnsignedShort()
|
||||||
|
66 -> modelSizeZ = buffer.readUnsignedShort()
|
||||||
|
67 -> modelSizeY = buffer.readUnsignedShort()
|
||||||
|
69 -> blockFlag = buffer.readUnsignedByte()
|
||||||
|
70 -> offsetX = buffer.readUnsignedShort() shl 2
|
||||||
|
71 -> offsetZ = buffer.readUnsignedShort() shl 2
|
||||||
|
72 -> offsetY = buffer.readUnsignedShort() shl 2
|
||||||
|
73 -> blocksLand = true
|
||||||
|
74 -> ignoreOnRoute = true
|
||||||
|
75 -> supportItems = buffer.readUnsignedByte()
|
||||||
|
77, 92 -> {
|
||||||
|
varbitIndex = buffer.readUnsignedShort()
|
||||||
|
if (varbitIndex == 65535) {
|
||||||
|
varbitIndex = -1
|
||||||
|
}
|
||||||
|
configId = buffer.readUnsignedShort()
|
||||||
|
if (configId == 65535) {
|
||||||
|
configId = -1
|
||||||
|
}
|
||||||
|
var last = -1
|
||||||
|
if (opcode == 92) {
|
||||||
|
last = buffer.readUnsignedShort()
|
||||||
|
if (last == 65535) {
|
||||||
|
last = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
configObjectIds = IntArray(length + 2)
|
||||||
|
for (count in 0..length) {
|
||||||
|
configObjectIds!![count] = buffer.readUnsignedShort()
|
||||||
|
if (configObjectIds!![count] == 65535) {
|
||||||
|
configObjectIds!![count] = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configObjectIds!![length + 1] = last
|
||||||
|
}
|
||||||
|
78 -> {
|
||||||
|
anInt3015 = buffer.readUnsignedShort()
|
||||||
|
anInt3012 = buffer.readUnsignedByte()
|
||||||
|
}
|
||||||
|
79 -> {
|
||||||
|
anInt2989 = buffer.readUnsignedShort()
|
||||||
|
anInt2971 = buffer.readUnsignedShort()
|
||||||
|
anInt3012 = buffer.readUnsignedByte()
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
anIntArray3036 = IntArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
anIntArray3036!![count] = buffer.readUnsignedShort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
81 -> {
|
||||||
|
contouredGround = 2.toByte()
|
||||||
|
anInt3023 = buffer.readUnsignedByte() * 256
|
||||||
|
}
|
||||||
|
82 -> hideMinimap = true
|
||||||
|
88 -> aBoolean2972 = false
|
||||||
|
89 -> animateImmediately = false
|
||||||
|
90 -> aBoolean1502 = true
|
||||||
|
91 -> isMembers = true
|
||||||
|
93 -> {
|
||||||
|
contouredGround = 3
|
||||||
|
anInt3023 = buffer.readUnsignedShort()
|
||||||
|
}
|
||||||
|
94 -> contouredGround = 4
|
||||||
|
95 -> {
|
||||||
|
contouredGround = 5
|
||||||
|
}
|
||||||
|
96 -> aBoolean1507 = true
|
||||||
|
97 -> adjustMapSceneRotation = true
|
||||||
|
98 -> hasAnimation = true
|
||||||
|
99 -> {
|
||||||
|
anInt2987 = buffer.readUnsignedByte()
|
||||||
|
anInt3008 = buffer.readUnsignedShort()
|
||||||
|
}
|
||||||
|
100 -> {
|
||||||
|
anInt3038 = buffer.readUnsignedByte()
|
||||||
|
anInt3013 = buffer.readUnsignedShort()
|
||||||
|
}
|
||||||
|
101 -> mapSceneRotation = buffer.readUnsignedByte()
|
||||||
|
102 -> mapscene = buffer.readUnsignedShort()
|
||||||
|
103 -> culling = 0
|
||||||
|
104 -> anInt3024 = buffer.readUnsignedByte()
|
||||||
|
105 -> invertMapScene = true
|
||||||
|
106 -> {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
var total = 0
|
||||||
|
animations = IntArray(length)
|
||||||
|
percents = IntArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
animations!![count] = buffer.readUnsignedShort()
|
||||||
|
if (animations!![count] == 65535) {
|
||||||
|
animations!![count] = -1
|
||||||
|
}
|
||||||
|
percents!![count] = buffer.readUnsignedByte()
|
||||||
|
total += percents!![count]
|
||||||
|
}
|
||||||
|
repeat(length) { count ->
|
||||||
|
percents!![count] = 65535 * percents!![count] / total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
107 -> mapDefinitionId = buffer.readUnsignedShort()
|
||||||
|
in 150..154 -> {
|
||||||
|
options[-150 + opcode] = buffer.readString()
|
||||||
|
if (!member) {
|
||||||
|
options[-150 + opcode] = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
160 -> {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
anIntArray2981 = IntArray(length)
|
||||||
|
repeat(length) { count ->
|
||||||
|
anIntArray2981!![count] = buffer.readUnsignedShort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
249 -> readParameters(buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun skip(buffer: Reader) {
|
||||||
|
val length = buffer.readUnsignedByte()
|
||||||
|
repeat(length) {
|
||||||
|
buffer.skip(1)
|
||||||
|
val amount = buffer.readUnsignedByte()
|
||||||
|
buffer.skip(amount * 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
src/main/kotlin/cacheops/cache/definition/decoder/TileSceneryParser.kt
vendored
Normal file
59
src/main/kotlin/cacheops/cache/definition/decoder/TileSceneryParser.kt
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.data.ObjectDefinition
|
||||||
|
import const.cache
|
||||||
|
import ext.getBigSmart
|
||||||
|
import ext.getSmart
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
val objectDecoder = ObjectDecoder(cache, true, false)
|
||||||
|
|
||||||
|
object TileSceneryParser {
|
||||||
|
fun parseRegion(id: Int): ArrayList<Scenery>{
|
||||||
|
if(XteaKeys.XTEAS.isEmpty()){
|
||||||
|
XteaKeys.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
val regionX = (id shr 8) and 0xFF;
|
||||||
|
val regionY = id and 0xFF;
|
||||||
|
val data = Rs2MapEditor.library.data(5, "l${regionX}_${regionY}",XteaKeys.get(id))
|
||||||
|
|
||||||
|
return if(data != null) decode(ByteBuffer.wrap(data))
|
||||||
|
else ArrayList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun decode(data: ByteBuffer): ArrayList<Scenery>{
|
||||||
|
val list = ArrayList<Scenery>()
|
||||||
|
var objectId = -1
|
||||||
|
while (true) {
|
||||||
|
var offset: Int = data.getBigSmart()
|
||||||
|
if (offset == 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
objectId += offset
|
||||||
|
var location = 0
|
||||||
|
while (true) {
|
||||||
|
offset = data.getSmart()
|
||||||
|
if (offset == 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
location += offset - 1
|
||||||
|
val y = location and 0x3f
|
||||||
|
val x = (location shr 6) and 0x3f
|
||||||
|
val configuration: Int = data.get().toInt() and 0xFF
|
||||||
|
val rotation = configuration and 0x3
|
||||||
|
val type = configuration shr 2
|
||||||
|
val z = location shr 12
|
||||||
|
|
||||||
|
list.add(Scenery(objectId,x,y,z,rotation,type))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Scenery(val id: Int, val x: Int, val y: Int, val plane: Int, val rotation: Int, val type: Int){
|
||||||
|
val definition = objectDecoder.forId(id)
|
||||||
|
}
|
||||||
|
|
||||||
33
src/main/kotlin/cacheops/cache/definition/decoder/XteaKeys.kt
vendored
Normal file
33
src/main/kotlin/cacheops/cache/definition/decoder/XteaKeys.kt
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package cacheops.cache.definition.decoder
|
||||||
|
|
||||||
|
import const.xteaJson
|
||||||
|
import org.json.simple.JSONArray
|
||||||
|
import org.json.simple.JSONObject
|
||||||
|
import org.json.simple.parser.JSONParser
|
||||||
|
import java.io.FileReader
|
||||||
|
|
||||||
|
object XteaKeys {
|
||||||
|
val XTEAS = HashMap<Int,IntArray>()
|
||||||
|
val DEFAULT_REGION_KEYS = intArrayOf(0,0,0,0)
|
||||||
|
|
||||||
|
fun get(regionId: Int): IntArray{
|
||||||
|
return XTEAS[regionId] ?: DEFAULT_REGION_KEYS
|
||||||
|
}
|
||||||
|
|
||||||
|
val parser = JSONParser()
|
||||||
|
var reader: FileReader? = null
|
||||||
|
|
||||||
|
fun load() {
|
||||||
|
var count = 0
|
||||||
|
reader = FileReader(xteaJson)
|
||||||
|
val obj = parser.parse(reader) as JSONObject
|
||||||
|
val configlist = obj["xteas"] as JSONArray
|
||||||
|
for(config in configlist){
|
||||||
|
val e = config as JSONObject
|
||||||
|
val id = e["regionId"].toString().toInt()
|
||||||
|
val keys = e["keys"].toString().split(",").map(String::toInt)
|
||||||
|
XTEAS[id] = intArrayOf(keys[0],keys[1],keys[2],keys[3])
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/main/kotlin/cacheops/cache/definition/encoder/GroundItemEncoder.kt
vendored
Normal file
48
src/main/kotlin/cacheops/cache/definition/encoder/GroundItemEncoder.kt
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cacheops.cache.definition.encoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.decoder.Item
|
||||||
|
import const.Indices
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import javax.swing.JOptionPane
|
||||||
|
|
||||||
|
object GroundItemEncoder {
|
||||||
|
|
||||||
|
fun write(item: ArrayList<Item>) {
|
||||||
|
|
||||||
|
// Setup buffer | Determine capacity (ArrayList size * (short2 + short2 + short2 + int4))
|
||||||
|
val buffer = ByteBuffer.allocate(item.size * 10)
|
||||||
|
|
||||||
|
// Put data to buffer
|
||||||
|
item.forEach {
|
||||||
|
val formattedCoord = (it.plane shl 14) or (it.x shl 7) or it.y
|
||||||
|
buffer.putShort(formattedCoord.toShort())
|
||||||
|
buffer.putShort(it.id.toShort())
|
||||||
|
buffer.putShort(it.respawnTime.toShort())
|
||||||
|
buffer.putInt(it.amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert buffer to byte array
|
||||||
|
val dataArray = buffer.array()
|
||||||
|
|
||||||
|
// Get region information
|
||||||
|
val region = Rs2MapEditor.region
|
||||||
|
val x = (region shr 8) and 0xFF
|
||||||
|
val y = region and 0xFF
|
||||||
|
|
||||||
|
// Put region data
|
||||||
|
if (dataArray != null) {
|
||||||
|
Rs2MapEditor.library.put(Indices.LANDSCAPES, "i${x}_${y}", dataArray, intArrayOf(0,0,0,0))
|
||||||
|
Rs2MapEditor.library.update()
|
||||||
|
JOptionPane.showMessageDialog(Rs2MapEditor.mapPanel, "Items written to cache [✓]")
|
||||||
|
Rs2MapEditor.itemsUpdated = false
|
||||||
|
} else {
|
||||||
|
System.err.println("Panic! Something went VERY wrong!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val itemList = arrayListOf<Item>(Item(946, 24, 2,0, 6, 1))
|
||||||
|
GroundItemEncoder.write(itemList)
|
||||||
|
}
|
||||||
49
src/main/kotlin/cacheops/cache/definition/encoder/MapTileEncoder.kt
vendored
Normal file
49
src/main/kotlin/cacheops/cache/definition/encoder/MapTileEncoder.kt
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
package cacheops.cache.definition.encoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.data.MapDefinition
|
||||||
|
import cacheops.cache.definition.decoder.MapTileParser
|
||||||
|
import const.Indices
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
object MapTileEncoder {
|
||||||
|
|
||||||
|
fun write(definition: MapDefinition) {
|
||||||
|
val buffer = ByteBuffer.allocate(80000)
|
||||||
|
for (plane in 0 until 4) {
|
||||||
|
for (localX in 0 until 64) {
|
||||||
|
for (localY in 0 until 64) {
|
||||||
|
val tile = definition.getTile(localX, localY, plane)
|
||||||
|
if (tile.underlayId != 0) {
|
||||||
|
buffer.put(((tile.underlayId + 81) and 0xFF).toByte())
|
||||||
|
}
|
||||||
|
if (tile.settings != 0) {
|
||||||
|
buffer.put(((tile.settings + 49) and 0xFF).toByte())
|
||||||
|
}
|
||||||
|
if (tile.attrOpcode != 0) {
|
||||||
|
buffer.put((tile.attrOpcode and 0xFF).toByte())
|
||||||
|
buffer.put((tile.overlayId and 0xFF).toByte())
|
||||||
|
}
|
||||||
|
if (tile.height == 0) {
|
||||||
|
buffer.put((0).toByte())
|
||||||
|
} else {
|
||||||
|
buffer.put((1).toByte())
|
||||||
|
buffer.put((tile.height and 0xFF).toByte())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val data = buffer.array().copyOf(buffer.position())
|
||||||
|
val combinedData = data.plus(MapTileParser.atmosphereDataTail)
|
||||||
|
|
||||||
|
val x = (Rs2MapEditor.region shr 8) and 0xFF
|
||||||
|
val y = Rs2MapEditor.region and 0xFF
|
||||||
|
|
||||||
|
if (combinedData != null) {
|
||||||
|
Rs2MapEditor.library.put(Indices.LANDSCAPES, "m${x}_${y}", combinedData)
|
||||||
|
Rs2MapEditor.library.update()
|
||||||
|
} else {
|
||||||
|
System.err.println("Something went VERY wrong!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/main/kotlin/cacheops/cache/definition/encoder/NPCSpawnEncoder.kt
vendored
Normal file
35
src/main/kotlin/cacheops/cache/definition/encoder/NPCSpawnEncoder.kt
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
package cacheops.cache.definition.encoder
|
||||||
|
|
||||||
|
import Rs2MapEditor
|
||||||
|
import cacheops.cache.definition.decoder.NPC
|
||||||
|
import const.Indices
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import javax.swing.JOptionPane
|
||||||
|
|
||||||
|
object NPCSpawnEncoder {
|
||||||
|
|
||||||
|
fun write(npc: ArrayList<NPC>) {
|
||||||
|
val buffer = ByteBuffer.allocate(npc.size * 4)
|
||||||
|
|
||||||
|
npc.forEach {
|
||||||
|
val formattedCoord = (it.plane shl 14) or (it.x shl 7) or it.y
|
||||||
|
buffer.putShort(formattedCoord.toShort())
|
||||||
|
buffer.putShort(it.id.toShort())
|
||||||
|
}
|
||||||
|
|
||||||
|
val dataArray = buffer.array()
|
||||||
|
|
||||||
|
val region = Rs2MapEditor.region
|
||||||
|
val x = (region shr 8) and 0xFF
|
||||||
|
val y = region and 0xFF
|
||||||
|
|
||||||
|
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!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
210
src/main/kotlin/cacheops/cache/secure/Huffman.kt
vendored
Normal file
210
src/main/kotlin/cacheops/cache/secure/Huffman.kt
vendored
Normal file
|
|
@ -0,0 +1,210 @@
|
||||||
|
package cacheops.cache.secure
|
||||||
|
|
||||||
|
import cacheops.cache.Cache
|
||||||
|
import cacheops.cache.buffer.read.Reader
|
||||||
|
import cacheops.cache.buffer.write.BufferWriter
|
||||||
|
|
||||||
|
class Huffman(cache: Cache) {
|
||||||
|
|
||||||
|
private var masks: IntArray? = null
|
||||||
|
private val frequencies: ByteArray
|
||||||
|
private var decryptKeys: IntArray
|
||||||
|
private val decryptedKeys: IntArray
|
||||||
|
private var decryptionValues = listOf(0, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load huffman tree from cache for compression
|
||||||
|
*/
|
||||||
|
init {
|
||||||
|
val huffman = cache.getFile(10, 1)!!
|
||||||
|
frequencies = huffman
|
||||||
|
masks = IntArray(huffman.size)
|
||||||
|
decryptKeys = IntArray(8)
|
||||||
|
val freq = IntArray(33)
|
||||||
|
var key = 0
|
||||||
|
//For each non-zero frequency
|
||||||
|
for ((index, size) in huffman.map { it.toInt() }.filter { it != 0 }.toIntArray().withIndex()) {
|
||||||
|
//Calculate maximum frequency
|
||||||
|
val maximumFreq = 1 shl 32 - size
|
||||||
|
//zero or the previous minimum
|
||||||
|
val currentFreq = freq[size]
|
||||||
|
//Store the min
|
||||||
|
masks!![index] = currentFreq
|
||||||
|
//Set the frequency to the
|
||||||
|
freq[size] = if (currentFreq and maximumFreq == 0) {//If the min and max are equal ish?
|
||||||
|
//Starting from the bottom find the smallest frequency indices
|
||||||
|
for (idx in size - 1 downTo 1) {
|
||||||
|
val leftFreq = freq[idx]
|
||||||
|
if (leftFreq != currentFreq) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
val rightFreq = 1 shl 32 - idx
|
||||||
|
if (rightFreq and leftFreq != 0) {
|
||||||
|
//Move up the tree?
|
||||||
|
freq[idx] = freq[idx - 1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
//Merge the two smallest trees
|
||||||
|
freq[idx] = leftFreq + rightFreq
|
||||||
|
}
|
||||||
|
//Sum of their frequencies
|
||||||
|
maximumFreq + currentFreq
|
||||||
|
} else {
|
||||||
|
//Move up the tree?
|
||||||
|
freq[size - 1]
|
||||||
|
}
|
||||||
|
for (idx in size + 1..32) {
|
||||||
|
if (currentFreq == freq[idx]) {
|
||||||
|
freq[idx] = freq[size]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var decryptIndex = 0
|
||||||
|
val value: Long = Int.MAX_VALUE + 1L
|
||||||
|
for(count in 0 until size) {
|
||||||
|
if (currentFreq and value.ushr(count).toInt() == 0) {
|
||||||
|
decryptIndex++
|
||||||
|
} else {
|
||||||
|
if (decryptKeys[decryptIndex] == 0) {
|
||||||
|
decryptKeys[decryptIndex] = key
|
||||||
|
}
|
||||||
|
decryptIndex = decryptKeys[decryptIndex]
|
||||||
|
}
|
||||||
|
if (decryptKeys.size <= decryptIndex) {
|
||||||
|
val keys = IntArray(decryptKeys.size * 2)
|
||||||
|
System.arraycopy(decryptKeys, 0, keys, 0, decryptKeys.size)
|
||||||
|
decryptKeys = keys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decryptKeys[decryptIndex] = index xor -0x1
|
||||||
|
if (key <= decryptIndex) {
|
||||||
|
key = 1 + decryptIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptedKeys = decryptKeys.map { it xor -0x1 }.toIntArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decompresses string of length [characters] using Huffman coding
|
||||||
|
* @param packet The packet containing the compressed data
|
||||||
|
* @param characters The number of string characters to decompress
|
||||||
|
*/
|
||||||
|
fun decompress(packet: Reader, characters: Int): String {
|
||||||
|
val textBuffer = ByteArray(packet.readableBytes())
|
||||||
|
packet.readBytes(textBuffer)
|
||||||
|
return decompress(textBuffer, characters) ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun decompress(message: ByteArray, length: Int): String? {
|
||||||
|
return try {
|
||||||
|
if(masks == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
var charsDecoded = 0
|
||||||
|
var keyIndex = 0
|
||||||
|
val sb = StringBuilder()
|
||||||
|
chars@ for (character in message) {
|
||||||
|
for (value in decryptionValues) {
|
||||||
|
if (if (value == 0) character >= 0 else character.toInt() and value == 0) {
|
||||||
|
keyIndex++
|
||||||
|
} else {
|
||||||
|
keyIndex = decryptKeys[keyIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
val char = decryptedKeys[keyIndex]
|
||||||
|
if (char >= 0) {
|
||||||
|
sb.append(char.toChar())
|
||||||
|
if (length <= ++charsDecoded) {
|
||||||
|
break@chars
|
||||||
|
}
|
||||||
|
keyIndex = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.toString()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats, compresses and writes [message] to [builder] using Huffman coding
|
||||||
|
* @param message The message to encode
|
||||||
|
* @param builder The packet to write the compressed data too
|
||||||
|
*/
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
fun compress(message: String, builder: BufferWriter) {
|
||||||
|
try {
|
||||||
|
//Format the message
|
||||||
|
val messageData = formatMessage(message)
|
||||||
|
//Write message length
|
||||||
|
builder.writeSmart(messageData.size)
|
||||||
|
//Write the compressed message
|
||||||
|
compress(messageData, builder)
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
exception.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compresses [message] using Huffman coding and writes to [builder]
|
||||||
|
* @param message The message to compress, split by symbol into a byte array
|
||||||
|
* @param builder The packet to write the compressed data too
|
||||||
|
*/
|
||||||
|
private fun compress(message: ByteArray, builder: BufferWriter) {
|
||||||
|
try {
|
||||||
|
if(masks == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var key = 0
|
||||||
|
val startPosition = builder.position()
|
||||||
|
var position = startPosition shl 3
|
||||||
|
for (char in message) {
|
||||||
|
val character = char.toInt() and 0xff
|
||||||
|
val min = masks!![character]
|
||||||
|
val size = frequencies[character]
|
||||||
|
|
||||||
|
var offset = position shr 3
|
||||||
|
var bitOffset = position and 0x7
|
||||||
|
key = key and (-bitOffset shr 31)
|
||||||
|
position += size
|
||||||
|
val byteSize = (bitOffset + size - 1 shr 3) + offset
|
||||||
|
bitOffset += 24
|
||||||
|
key += min.ushr(bitOffset)
|
||||||
|
builder.setByte(offset, key)
|
||||||
|
|
||||||
|
while (offset < byteSize) {
|
||||||
|
bitOffset -= 8
|
||||||
|
key = min.ushr(bitOffset)
|
||||||
|
builder.setByte(++offset, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the packet position to the correct place
|
||||||
|
builder.position(7 + position shr 3)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces unknown symbols with question marks
|
||||||
|
* @param message The text to format
|
||||||
|
* @return message split by character
|
||||||
|
*/
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
private fun formatMessage(message: String): ByteArray {
|
||||||
|
val array = ByteArray(message.length)
|
||||||
|
for ((index, c) in message.withIndex()) {
|
||||||
|
val char = c.code
|
||||||
|
array[index] = if (char <= 0 || (char in 128..159) || char > 255) {
|
||||||
|
63.toByte()
|
||||||
|
} else {
|
||||||
|
char.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/main/kotlin/cacheops/cache/secure/RSA.kt
vendored
Normal file
56
src/main/kotlin/cacheops/cache/secure/RSA.kt
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
package cacheops.cache.secure
|
||||||
|
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.security.SecureRandom
|
||||||
|
|
||||||
|
object RSA {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt/decrypts bytes with key and modulus
|
||||||
|
*/
|
||||||
|
fun crypt(data: ByteArray, modulus: BigInteger, key: BigInteger): ByteArray {
|
||||||
|
return BigInteger(data).modPow(key, modulus).toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt/decrypts [ByteBuffer] with key and modulus
|
||||||
|
*/
|
||||||
|
fun crypt(data: ByteBuffer, modulus: BigInteger, key: BigInteger): ByteBuffer {
|
||||||
|
return ByteBuffer.wrap(BigInteger(data.array()).modPow(key, modulus).toByteArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
generateRsa()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates rsa values
|
||||||
|
*/
|
||||||
|
private fun generateRsa() {
|
||||||
|
val bits = 1024
|
||||||
|
val random = SecureRandom()
|
||||||
|
|
||||||
|
var p: BigInteger
|
||||||
|
var q: BigInteger
|
||||||
|
var phi: BigInteger
|
||||||
|
var modulus: BigInteger
|
||||||
|
var publicKey: BigInteger
|
||||||
|
var privateKey: BigInteger
|
||||||
|
|
||||||
|
do {
|
||||||
|
p = BigInteger.probablePrime(bits / 2, random)
|
||||||
|
q = BigInteger.probablePrime(bits / 2, random)
|
||||||
|
phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE))
|
||||||
|
|
||||||
|
modulus = p.multiply(q)
|
||||||
|
publicKey = BigInteger("65537")
|
||||||
|
privateKey = publicKey.modInverse(phi)
|
||||||
|
} while (modulus.bitLength() != bits || privateKey.bitLength() != bits || phi.gcd(publicKey) != BigInteger.ONE)
|
||||||
|
|
||||||
|
println("modulus: ${modulus.toString(16)}")
|
||||||
|
println("public key: ${publicKey.toString(16)}")
|
||||||
|
println("private key: ${privateKey.toString(16)}")
|
||||||
|
}
|
||||||
|
}
|
||||||
77
src/main/kotlin/cacheops/cache/secure/Xtea.kt
vendored
Normal file
77
src/main/kotlin/cacheops/cache/secure/Xtea.kt
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
package cacheops.cache.secure
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
object Xtea {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The golden ratio.
|
||||||
|
*/
|
||||||
|
private const val GOLDEN_RATIO = -0x61c88647
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of rounds.
|
||||||
|
*/
|
||||||
|
private const val ROUNDS = 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deciphers the specified [ByteBuffer] with the given key.
|
||||||
|
* @param buffer The buffer.
|
||||||
|
* @param key The key.
|
||||||
|
* @throws IllegalArgumentException if the key is not exactly 4 elements
|
||||||
|
* long.
|
||||||
|
*/
|
||||||
|
fun decipher(buffer: ByteArray, key: IntArray, start: Int = 0) {
|
||||||
|
if (key.size != 4) {
|
||||||
|
throw IllegalArgumentException()
|
||||||
|
}
|
||||||
|
|
||||||
|
val numQuads = buffer.size / 8
|
||||||
|
for (i in 0 until numQuads) {
|
||||||
|
var sum = GOLDEN_RATIO * ROUNDS
|
||||||
|
var v0 = getInt(buffer, start + i * 8)
|
||||||
|
var v1 = getInt(buffer, start + i * 8 + 4)
|
||||||
|
for (j in 0 until ROUNDS) {
|
||||||
|
v1 -= (v0 shl 4 xor v0.ushr(5)) + v0 xor sum + key[sum.ushr(11) and 3]
|
||||||
|
sum -= GOLDEN_RATIO
|
||||||
|
v0 -= (v1 shl 4 xor v1.ushr(5)) + v1 xor sum + key[sum and 3]
|
||||||
|
}
|
||||||
|
putInt(buffer, start + i * 8, v0)
|
||||||
|
putInt(buffer, start + i * 8 + 4, v1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enciphers the specified [ByteArray] with the given key.
|
||||||
|
* @param buffer The buffer.
|
||||||
|
* @param key The key.
|
||||||
|
* @throws IllegalArgumentException if the key is not exactly 4 elements
|
||||||
|
* long.
|
||||||
|
*/
|
||||||
|
fun encipher(buffer: ByteArray, start: Int, end: Int, key: IntArray) {
|
||||||
|
if (key.size != 4)
|
||||||
|
throw IllegalArgumentException()
|
||||||
|
|
||||||
|
val numQuads = (end - start) / 8
|
||||||
|
for (i in 0 until numQuads) {
|
||||||
|
var sum = 0
|
||||||
|
var v0 = getInt(buffer, start + i * 8)
|
||||||
|
var v1 = getInt(buffer, start + i * 8 + 4)
|
||||||
|
for (j in 0 until ROUNDS) {
|
||||||
|
v0 += (v1 shl 4 xor v1.ushr(5)) + v1 xor sum + key[sum and 3]
|
||||||
|
sum += GOLDEN_RATIO
|
||||||
|
v1 += (v0 shl 4 xor v0.ushr(5)) + v0 xor sum + key[sum.ushr(11) and 3]
|
||||||
|
}
|
||||||
|
putInt(buffer, start + i * 8, v0)
|
||||||
|
putInt(buffer, start + i * 8 + 4, v1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInt(buffer: ByteArray, index: Int) = (buffer[index].toInt() and 0xff shl 24) or (buffer[index + 1].toInt() and 0xff shl 16) or (buffer[index + 2].toInt() and 0xff shl 8) or (buffer[index + 3].toInt() and 0xff)
|
||||||
|
private fun putInt(buffer: ByteArray, index: Int, value: Int) {
|
||||||
|
buffer[index] = (value shr 24).toByte()
|
||||||
|
buffer[index + 1] = (value shr 16).toByte()
|
||||||
|
buffer[index + 2] = (value shr 8).toByte()
|
||||||
|
buffer[index + 3] = value.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/main/kotlin/const/Archives.kt
Normal file
10
src/main/kotlin/const/Archives.kt
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package const
|
||||||
|
|
||||||
|
object Archives {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Archives that are located in the CONFIGURATION index (2)
|
||||||
|
*/
|
||||||
|
const val FLOOR_UNDERLAYS = 1
|
||||||
|
const val FLOOR_OVERLAYS = 4
|
||||||
|
}
|
||||||
13
src/main/kotlin/const/Image.kt
Normal file
13
src/main/kotlin/const/Image.kt
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
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")))
|
||||||
|
val DELETE_HI = ImageIcon(ImageIO.read(javaClass.getResource("/trash_hi.png")))
|
||||||
|
val DELTE_LO = ImageIcon(ImageIO.read(javaClass.getResource("/trash_dark.png")))
|
||||||
|
val ADD_HI = ImageIcon(ImageIO.read(javaClass.getResource("/add_hi.png")))
|
||||||
|
val ADD_LO = ImageIcon(ImageIO.read(javaClass.getResource("/add_dark.png")))
|
||||||
|
}
|
||||||
32
src/main/kotlin/const/Indices.kt
Normal file
32
src/main/kotlin/const/Indices.kt
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package const
|
||||||
|
|
||||||
|
object Indices {
|
||||||
|
const val SKELETONS = 0
|
||||||
|
const val SKINS = 1
|
||||||
|
const val CONFIGURATION = 2
|
||||||
|
const val INTERFACES = 3
|
||||||
|
const val SYNTH_SOUNDS = 4
|
||||||
|
const val LANDSCAPES = 5
|
||||||
|
const val MUSIC = 6
|
||||||
|
const val MODELS = 7
|
||||||
|
const val SPRITES = 8
|
||||||
|
const val TEXTURES = 9
|
||||||
|
const val HUFFMAN_ENCODING = 10
|
||||||
|
const val MIDI_JINGLES = 11
|
||||||
|
const val CLIENT_SCRIPTS = 12
|
||||||
|
const val FONT_METRICS = 13
|
||||||
|
const val VORBIS = 14
|
||||||
|
const val MIDI_INSTRUMENTS = 15
|
||||||
|
const val CONFIGURATION_OBJECT = 16
|
||||||
|
const val CONFIGURATION_ENUMS = 17
|
||||||
|
const val CONFIGURATION_NPCS = 18
|
||||||
|
const val CONFIGURATION_ITEMS = 19
|
||||||
|
const val CONFIGURATION_SEQUENCES = 20
|
||||||
|
const val CONFIGURATION_SPOTANIM = 21
|
||||||
|
const val CONFIGURATION_VARBIT = 22
|
||||||
|
const val WORLD_MAP = 23
|
||||||
|
const val QUICKCHAT_MESSAGES = 24
|
||||||
|
const val QUICKCHAT_MENUS = 25
|
||||||
|
const val MATERIALS = 26
|
||||||
|
const val CONFIGURATION_PARTICLES = 27
|
||||||
|
}
|
||||||
8
src/main/kotlin/const/Misc.kt
Normal file
8
src/main/kotlin/const/Misc.kt
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
package const
|
||||||
|
|
||||||
|
import cacheops.cache.Cache
|
||||||
|
import cacheops.cache.CacheDelegate
|
||||||
|
|
||||||
|
val cachePath = "/home/ceikry/IdeaProjects/2009scape/Server/data/cache"
|
||||||
|
val xteaJson = "/home/ceikry/IdeaProjects/2009scape/Server/data/configs/xteas.json"
|
||||||
|
val cache: Cache = CacheDelegate(cachePath)
|
||||||
61
src/main/kotlin/ext/JagexTypes.kt
Normal file
61
src/main/kotlin/ext/JagexTypes.kt
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
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() and 0xff) + (get().toInt() shl 8 and 0xff00) + )
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteBuffer.putJagexString(string: String) {
|
||||||
|
put(0)
|
||||||
|
put(string.toByteArray())
|
||||||
|
put(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteBuffer.putJagexStringQuickChat(string: String) {
|
||||||
|
put(1)
|
||||||
|
put(string.toByteArray())
|
||||||
|
put(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteBuffer.getJagexString(): String {
|
||||||
|
val stringBuilder = StringBuilder()
|
||||||
|
var b: Byte
|
||||||
|
while (get().also { b = it }.toInt() != 0) {
|
||||||
|
stringBuilder.append(b.toInt().toChar())
|
||||||
|
}
|
||||||
|
return stringBuilder.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteBuffer.readNullCircumfixedString(): String {
|
||||||
|
if (unsignedByte() != 0)
|
||||||
|
throw IllegalArgumentException("byte != 0 infront of null-circumfixed string")
|
||||||
|
return getJagexString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteBuffer.unsignedByte(): Int {
|
||||||
|
return get().toInt() and 0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteBuffer.unsignedShort(): Int {
|
||||||
|
return short.toInt() and 0xFFFF
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteBuffer.getBigSmart(): Int {
|
||||||
|
var value = 0
|
||||||
|
var current: Int = getSmart()
|
||||||
|
while (current == 32767) {
|
||||||
|
current = getSmart()
|
||||||
|
value += 32767
|
||||||
|
}
|
||||||
|
value += current
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteBuffer.getSmart(): Int {
|
||||||
|
val peek: Int = get().toInt() and 0xFF
|
||||||
|
return if (peek <= Byte.MAX_VALUE) {
|
||||||
|
peek
|
||||||
|
} else (peek shl 8 or (get().toInt() and 0xFF)) - 32768
|
||||||
|
}
|
||||||
12
src/main/kotlin/ext/Misc.kt
Normal file
12
src/main/kotlin/ext/Misc.kt
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import cacheops.cache.definition.data.MapTile
|
||||||
|
import cacheops.cache.definition.decoder.MapTileParser
|
||||||
|
|
||||||
|
fun Pair<Int,Int>.getSurroundingTiles() : List<MapTile> {
|
||||||
|
val list = ArrayList<MapTile>()
|
||||||
|
list.add(MapTileParser.definition.getTile(first, second + 1, Rs2MapEditor.plane))
|
||||||
|
list.add(MapTileParser.definition.getTile(first + 1, second, Rs2MapEditor.plane))
|
||||||
|
list.add(MapTileParser.definition.getTile(first, second - 1, Rs2MapEditor.plane))
|
||||||
|
list.add(MapTileParser.definition.getTile(first - 1, second, Rs2MapEditor.plane))
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
24
src/main/kotlin/ext/Vector3f.kt
Normal file
24
src/main/kotlin/ext/Vector3f.kt
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package ext
|
||||||
|
|
||||||
|
class Vector3f(var x: Float, var y: Float, var z: Float) {
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = x.hashCode()
|
||||||
|
result = 31 * result + y.hashCode()
|
||||||
|
result = 31 * result + z.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as Vector3f
|
||||||
|
|
||||||
|
if (x != other.x) return false
|
||||||
|
if (y != other.y) return false
|
||||||
|
if (z != other.z) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/main/kotlin/misc/CustomEventQueue.kt
Normal file
22
src/main/kotlin/misc/CustomEventQueue.kt
Normal file
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/main/kotlin/misc/GlobalKeybinds.kt
Normal file
65
src/main/kotlin/misc/GlobalKeybinds.kt
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
package misc
|
||||||
|
|
||||||
|
import cacheops.cache.definition.encoder.GroundItemEncoder
|
||||||
|
import cacheops.cache.definition.encoder.NPCSpawnEncoder
|
||||||
|
import java.awt.Event
|
||||||
|
import java.awt.event.KeyEvent
|
||||||
|
import tools.*
|
||||||
|
|
||||||
|
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)
|
||||||
|
Editors.NPC_SPAWNS.data.save()
|
||||||
|
}
|
||||||
|
if(Rs2MapEditor.itemsUpdated){
|
||||||
|
GroundItemEncoder.write(Rs2MapEditor.items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyEvent.VK_UP -> {
|
||||||
|
var newRegion = Util.getRegion (Rs2MapEditor.region, 0, 1)
|
||||||
|
Rs2MapEditor.loadRegion(newRegion)
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyEvent.VK_DOWN -> {
|
||||||
|
var newRegion = Util.getRegion (Rs2MapEditor.region, 0, -1)
|
||||||
|
Rs2MapEditor.loadRegion(newRegion)
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyEvent.VK_LEFT -> {
|
||||||
|
var newRegion = Util.getRegion (Rs2MapEditor.region, -1, 0)
|
||||||
|
Rs2MapEditor.loadRegion(newRegion)
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyEvent.VK_RIGHT -> {
|
||||||
|
var newRegion = Util.getRegion (Rs2MapEditor.region, 1, 0)
|
||||||
|
Rs2MapEditor.loadRegion(newRegion)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else when(event.keyCode){
|
||||||
|
KeyEvent.VK_ESCAPE -> Rs2MapEditor.state = EditorState.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/main/kotlin/misc/ImgButton.kt
Normal file
56
src/main/kotlin/misc/ImgButton.kt
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
package misc
|
||||||
|
|
||||||
|
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(enabledImg: ImageIcon, disabledImage: ImageIcon = enabledImg, val autoHandleMouse: Boolean = true) : JLabel() {
|
||||||
|
|
||||||
|
private var hoverMethod: (MouseEvent) -> Unit = {}
|
||||||
|
private var mouseLeaveMethod: (MouseEvent) -> Unit = {}
|
||||||
|
private var onClickMethod: (MouseEvent) -> Unit = {}
|
||||||
|
|
||||||
|
init {
|
||||||
|
isEnabled = false
|
||||||
|
icon = enabledImg
|
||||||
|
disabledIcon = disabledImage
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/main/kotlin/tools/ItemSearchTool.kt
Normal file
101
src/main/kotlin/tools/ItemSearchTool.kt
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
package tools
|
||||||
|
|
||||||
|
import cacheops.cache.definition.decoder.decoder
|
||||||
|
import cacheops.cache.definition.decoder.itemDecoder
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
import java.awt.Dimension
|
||||||
|
import java.awt.event.KeyEvent
|
||||||
|
import java.awt.event.KeyListener
|
||||||
|
import java.awt.event.MouseEvent
|
||||||
|
import java.awt.event.MouseListener
|
||||||
|
import java.util.*
|
||||||
|
import java.util.regex.PatternSyntaxException
|
||||||
|
import javax.swing.*
|
||||||
|
import javax.swing.table.DefaultTableCellRenderer
|
||||||
|
import javax.swing.table.DefaultTableModel
|
||||||
|
import javax.swing.table.TableRowSorter
|
||||||
|
|
||||||
|
object ItemSearchTool : JFrame("Item Search") {
|
||||||
|
var model = DefaultTableModel()
|
||||||
|
var searchField = JTextField()
|
||||||
|
var sorter = TableRowSorter(model)
|
||||||
|
var cellRenderer = DefaultTableCellRenderer()
|
||||||
|
var populated = false
|
||||||
|
var caller: ((Int,String) -> Unit)? = null
|
||||||
|
private fun filter() {
|
||||||
|
var rf: RowFilter<DefaultTableModel?, Any?>? = null
|
||||||
|
//If current expression doesn't parse, don't update.
|
||||||
|
rf = try {
|
||||||
|
RowFilter.regexFilter(searchField.text.capitalize(), 1)
|
||||||
|
} catch (e: PatternSyntaxException) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sorter.rowFilter = rf
|
||||||
|
}
|
||||||
|
|
||||||
|
fun open() {
|
||||||
|
if (!populated) {
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
for (i in 0..15431) {
|
||||||
|
model.addRow(arrayOf(i, itemDecoder.forId(i).name))
|
||||||
|
}
|
||||||
|
isVisible = true
|
||||||
|
populated = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
layout = BorderLayout()
|
||||||
|
cellRenderer.toolTipText = "Double-Click to select."
|
||||||
|
val searchPanel = JPanel()
|
||||||
|
val searchLabel = JLabel("Search for NPC:")
|
||||||
|
searchField.preferredSize = Dimension(100, 20)
|
||||||
|
searchPanel.add(searchLabel)
|
||||||
|
searchPanel.add(searchField)
|
||||||
|
add(searchPanel, BorderLayout.NORTH)
|
||||||
|
setLocationRelativeTo(null)
|
||||||
|
val itemTable: JTable = object : JTable(model) {
|
||||||
|
override fun editCellAt(i: Int, i1: Int, eventObject: EventObject): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.addColumn("ID")
|
||||||
|
model.addColumn("Name")
|
||||||
|
itemTable.rowSorter = sorter
|
||||||
|
itemTable.columnModel.getColumn(0).maxWidth = 55
|
||||||
|
itemTable.columnModel.getColumn(0).cellRenderer = cellRenderer
|
||||||
|
itemTable.columnModel.getColumn(1).cellRenderer = cellRenderer
|
||||||
|
itemTable.addMouseListener(object : MouseListener {
|
||||||
|
override fun mouseClicked(mouseEvent: MouseEvent) {
|
||||||
|
if (mouseEvent.clickCount == 2) {
|
||||||
|
val table = mouseEvent.source as JTable
|
||||||
|
val row = table.selectedRow
|
||||||
|
val selectedID = table.getValueAt(row,0).toString().toInt()
|
||||||
|
val selectedName = table.getValueAt(row,1).toString()
|
||||||
|
caller?.invoke(selectedID,selectedName)
|
||||||
|
isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mousePressed(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseReleased(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseEntered(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseExited(mouseEvent: MouseEvent) {}
|
||||||
|
})
|
||||||
|
searchField.addKeyListener(object : KeyListener {
|
||||||
|
override fun keyTyped(keyEvent: KeyEvent) {
|
||||||
|
filter()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyPressed(keyEvent: KeyEvent) {}
|
||||||
|
override fun keyReleased(keyEvent: KeyEvent) {}
|
||||||
|
})
|
||||||
|
val scrollPane = JScrollPane(itemTable)
|
||||||
|
add(scrollPane, BorderLayout.SOUTH)
|
||||||
|
pack()
|
||||||
|
isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/main/kotlin/tools/NPCSearchTool.kt
Normal file
100
src/main/kotlin/tools/NPCSearchTool.kt
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
package tools
|
||||||
|
|
||||||
|
import cacheops.cache.definition.decoder.decoder
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
import java.awt.Dimension
|
||||||
|
import java.awt.event.KeyEvent
|
||||||
|
import java.awt.event.KeyListener
|
||||||
|
import java.awt.event.MouseEvent
|
||||||
|
import java.awt.event.MouseListener
|
||||||
|
import java.util.*
|
||||||
|
import java.util.regex.PatternSyntaxException
|
||||||
|
import javax.swing.*
|
||||||
|
import javax.swing.table.DefaultTableCellRenderer
|
||||||
|
import javax.swing.table.DefaultTableModel
|
||||||
|
import javax.swing.table.TableRowSorter
|
||||||
|
|
||||||
|
object NPCSearchTool : JFrame("NPC Search") {
|
||||||
|
var model = DefaultTableModel()
|
||||||
|
var searchField = JTextField()
|
||||||
|
var sorter = TableRowSorter(model)
|
||||||
|
var cellRenderer = DefaultTableCellRenderer()
|
||||||
|
var populated = false
|
||||||
|
var caller: ((Int,String) -> Unit)? = null
|
||||||
|
private fun filter() {
|
||||||
|
var rf: RowFilter<DefaultTableModel?, Any?>? = null
|
||||||
|
//If current expression doesn't parse, don't update.
|
||||||
|
rf = try {
|
||||||
|
RowFilter.regexFilter(searchField.text.capitalize(), 1)
|
||||||
|
} catch (e: PatternSyntaxException) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sorter.rowFilter = rf
|
||||||
|
}
|
||||||
|
|
||||||
|
fun open() {
|
||||||
|
if (!populated) {
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
for (i in 0..9422) {
|
||||||
|
model.addRow(arrayOf(i, decoder.forId(i).name))
|
||||||
|
}
|
||||||
|
isVisible = true
|
||||||
|
populated = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
layout = BorderLayout()
|
||||||
|
cellRenderer.toolTipText = "Double-Click to select."
|
||||||
|
val searchPanel = JPanel()
|
||||||
|
val searchLabel = JLabel("Search for NPC:")
|
||||||
|
searchField.preferredSize = Dimension(100, 20)
|
||||||
|
searchPanel.add(searchLabel)
|
||||||
|
searchPanel.add(searchField)
|
||||||
|
add(searchPanel, BorderLayout.NORTH)
|
||||||
|
setLocationRelativeTo(null)
|
||||||
|
val npcTable: JTable = object : JTable(model) {
|
||||||
|
override fun editCellAt(i: Int, i1: Int, eventObject: EventObject): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.addColumn("ID")
|
||||||
|
model.addColumn("Name")
|
||||||
|
npcTable.rowSorter = sorter
|
||||||
|
npcTable.columnModel.getColumn(0).maxWidth = 55
|
||||||
|
npcTable.columnModel.getColumn(0).cellRenderer = cellRenderer
|
||||||
|
npcTable.columnModel.getColumn(1).cellRenderer = cellRenderer
|
||||||
|
npcTable.addMouseListener(object : MouseListener {
|
||||||
|
override fun mouseClicked(mouseEvent: MouseEvent) {
|
||||||
|
if (mouseEvent.clickCount == 2) {
|
||||||
|
val table = mouseEvent.source as JTable
|
||||||
|
val row = table.selectedRow
|
||||||
|
val selectedID = table.getValueAt(row,0).toString().toInt()
|
||||||
|
val selectedName = table.getValueAt(row,1).toString()
|
||||||
|
caller?.invoke(selectedID,selectedName)
|
||||||
|
isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mousePressed(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseReleased(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseEntered(mouseEvent: MouseEvent) {}
|
||||||
|
override fun mouseExited(mouseEvent: MouseEvent) {}
|
||||||
|
})
|
||||||
|
searchField.addKeyListener(object : KeyListener {
|
||||||
|
override fun keyTyped(keyEvent: KeyEvent) {
|
||||||
|
filter()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyPressed(keyEvent: KeyEvent) {}
|
||||||
|
override fun keyReleased(keyEvent: KeyEvent) {}
|
||||||
|
})
|
||||||
|
val scrollPane = JScrollPane(npcTable)
|
||||||
|
add(scrollPane, BorderLayout.SOUTH)
|
||||||
|
pack()
|
||||||
|
isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/main/kotlin/tools/Util.kt
Normal file
23
src/main/kotlin/tools/Util.kt
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package tools
|
||||||
|
|
||||||
|
object Util {
|
||||||
|
fun getRegionId(location: TableData.Location) : Int {
|
||||||
|
return ((location.x shr 6) shl 8) or (location.y shr 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRegionCoordinates(location: TableData.Location) : IntArray {
|
||||||
|
return intArrayOf(location.x and 63, location.y and 63, location.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAbsoluteCoordinates(regionId: Int, regionX: Int, regionY: Int, plane: Int) : TableData.Location {
|
||||||
|
val x = regionId shr 8
|
||||||
|
val y = regionId and 0xFF
|
||||||
|
return TableData.Location((x shl 6) or regionX, (y shl 6) or regionY, plane)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRegion (currentRegionId: Int, changeX: Int, changeY: Int) : Int {
|
||||||
|
var x = ((currentRegionId shr 8) + changeX) shl 8
|
||||||
|
var y = ((currentRegionId and 0xFF) + changeY)
|
||||||
|
return (x or y)
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/main/kotlin/ui/InfoPane.kt
Normal file
23
src/main/kotlin/ui/InfoPane.kt
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import java.awt.Color
|
||||||
|
import java.awt.Dimension
|
||||||
|
import java.awt.event.KeyEvent
|
||||||
|
import javax.swing.JComponent
|
||||||
|
import javax.swing.JTabbedPane
|
||||||
|
import javax.swing.border.CompoundBorder
|
||||||
|
import javax.swing.border.EmptyBorder
|
||||||
|
import javax.swing.border.LineBorder
|
||||||
|
|
||||||
|
class InfoPane : JTabbedPane() {
|
||||||
|
init {
|
||||||
|
val informationComponent: JComponent = TileInformationPanel()
|
||||||
|
|
||||||
|
preferredSize = Dimension(230, 4000)
|
||||||
|
border = CompoundBorder(LineBorder(Color.DARK_GRAY), EmptyBorder(0, 0, 0, 0))
|
||||||
|
|
||||||
|
addTab("Information", informationComponent)
|
||||||
|
add("NPC Spawn", Rs2MapEditor.npcPanel)
|
||||||
|
add("Item Spawn", Rs2MapEditor.itemPanel)
|
||||||
|
}
|
||||||
|
}
|
||||||
128
src/main/kotlin/ui/ItemSpawnPanel.kt
Normal file
128
src/main/kotlin/ui/ItemSpawnPanel.kt
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import cacheops.cache.definition.decoder.Item
|
||||||
|
import const.Image
|
||||||
|
import misc.ImgButton
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
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 ItemSpawnPanel : JPanel() {
|
||||||
|
val rowBorder = MatteBorder(1, 1, 1, 1, Color.WHITE)
|
||||||
|
init {
|
||||||
|
layout = BoxLayout(this, BoxLayout.PAGE_AXIS)
|
||||||
|
|
||||||
|
add(ItemSpawnerPanel())
|
||||||
|
|
||||||
|
Rs2MapEditor.items.forEach {
|
||||||
|
val row = ItemRow(it, this)
|
||||||
|
row.border = rowBorder
|
||||||
|
Rs2MapEditor.itemRows.add(row)
|
||||||
|
add(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun redrawRows() {
|
||||||
|
Rs2MapEditor.itemRows.forEach {
|
||||||
|
remove(it)
|
||||||
|
}
|
||||||
|
Rs2MapEditor.itemRows.clear()
|
||||||
|
Rs2MapEditor.items.filter { it.plane == Rs2MapEditor.plane }.forEach {
|
||||||
|
val row = ItemRow(it, this)
|
||||||
|
row.border = rowBorder
|
||||||
|
Rs2MapEditor.itemRows.add(row)
|
||||||
|
add(row)
|
||||||
|
}
|
||||||
|
repaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemSpawnerPanel : JPanel() {
|
||||||
|
init {
|
||||||
|
val topPanel = JPanel(FlowLayout())
|
||||||
|
val bottomPanel = JPanel(FlowLayout())
|
||||||
|
val addButton = ImgButton(Image.ADD_HI, Image.ADD_LO)
|
||||||
|
addButton.onClick {
|
||||||
|
Rs2MapEditor.state = EditorState.ADD_GROUNDITEM
|
||||||
|
}
|
||||||
|
Rs2MapEditor.itemIdInput.minimumSize = Dimension(200, 25)
|
||||||
|
Rs2MapEditor.itemIdInput.maximumSize = Dimension(200, 25)
|
||||||
|
Rs2MapEditor.itemIdInput.preferredSize = Dimension(200, 25)
|
||||||
|
|
||||||
|
Rs2MapEditor.itemRespawnInput.minimumSize = Dimension(50, 25)
|
||||||
|
Rs2MapEditor.itemRespawnInput.maximumSize = Dimension(50, 25)
|
||||||
|
Rs2MapEditor.itemRespawnInput.preferredSize = Dimension(50, 25)
|
||||||
|
Rs2MapEditor.itemRespawnInput.text = "1"
|
||||||
|
|
||||||
|
Rs2MapEditor.itemAmountInput.minimumSize = Dimension(75, 25)
|
||||||
|
Rs2MapEditor.itemAmountInput.maximumSize = Dimension(75, 25)
|
||||||
|
Rs2MapEditor.itemAmountInput.preferredSize = Dimension(75, 25)
|
||||||
|
Rs2MapEditor.itemAmountInput.text = "1"
|
||||||
|
|
||||||
|
val timeLabel = JLabel("\uD83D\uDD64")
|
||||||
|
timeLabel.toolTipText = "Respawn Time (ticks)"
|
||||||
|
|
||||||
|
minimumSize = Dimension(300, 68)
|
||||||
|
preferredSize = Dimension(300, 68)
|
||||||
|
maximumSize = Dimension(300, 68)
|
||||||
|
|
||||||
|
layout = BorderLayout()
|
||||||
|
topPanel.add(Rs2MapEditor.itemIdInput)
|
||||||
|
topPanel.add(addButton)
|
||||||
|
bottomPanel.add(timeLabel)
|
||||||
|
bottomPanel.add(Rs2MapEditor.itemRespawnInput)
|
||||||
|
bottomPanel.add(JLabel("AMT:"))
|
||||||
|
bottomPanel.add(Rs2MapEditor.itemAmountInput)
|
||||||
|
add(topPanel,BorderLayout.NORTH)
|
||||||
|
add(bottomPanel,BorderLayout.SOUTH)
|
||||||
|
border = MatteBorder(1, 1, 1, 1, Color.GREEN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemRow(val item: Item, val parent: JPanel) : JPanel(){
|
||||||
|
init {
|
||||||
|
layout = FlowLayout()
|
||||||
|
add(JLabel("${item.definition.name} [${item.amount}] -- \uD83D\uDD64 ${item.respawnTime}"))
|
||||||
|
val deleteButton = ImgButton(Image.DELETE_HI, Image.DELTE_LO)
|
||||||
|
add(deleteButton)
|
||||||
|
minimumSize = Dimension(300, 40)
|
||||||
|
preferredSize = Dimension(300, 40)
|
||||||
|
maximumSize = Dimension(300, 40)
|
||||||
|
deleteButton.onClick {
|
||||||
|
Rs2MapEditor.items.remove(item)
|
||||||
|
parent.remove(this)
|
||||||
|
parent.repaint()
|
||||||
|
Rs2MapEditor.itemRows.remove(this)
|
||||||
|
if(Rs2MapEditor.items.filter { it.x == item.x && it.y == item.y }.isEmpty()){
|
||||||
|
Rs2MapEditor.componentPointMap.filter { it.key.x == item.x && it.key.y == item.y }.forEach { (_,cell) ->
|
||||||
|
cell.components.forEach { c ->
|
||||||
|
if(c is JLabel && c.icon == Image.RED_DOT) cell.remove(c)
|
||||||
|
}
|
||||||
|
cell.repaint()
|
||||||
|
Rs2MapEditor.itemsUpdated = 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 == item.x && it.key.y == item.y }.forEach { it.value.border = border }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseExited(e: MouseEvent?) {
|
||||||
|
super.mouseExited(e)
|
||||||
|
Rs2MapEditor.componentPointMap.filter { it.key.x == item.x && it.key.y == item.y }.forEach{ it.value.border = defaultBorder }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
396
src/main/kotlin/ui/MapCell.kt
Normal file
396
src/main/kotlin/ui/MapCell.kt
Normal file
|
|
@ -0,0 +1,396 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import EditorData
|
||||||
|
import EditorState
|
||||||
|
import Rs2MapEditor
|
||||||
|
import TableData
|
||||||
|
import cacheops.cache.definition.data.MapTile
|
||||||
|
import cacheops.cache.definition.decoder.Item
|
||||||
|
import cacheops.cache.definition.decoder.MapTileParser
|
||||||
|
import cacheops.cache.definition.decoder.NPC
|
||||||
|
import cacheops.cache.definition.decoder.Scenery
|
||||||
|
import const.Image
|
||||||
|
import tools.Util
|
||||||
|
import java.awt.*
|
||||||
|
import java.awt.event.MouseAdapter
|
||||||
|
import java.awt.event.MouseEvent
|
||||||
|
import javax.swing.JLabel
|
||||||
|
import javax.swing.JPanel
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
|
class MapCell : JPanel() {
|
||||||
|
var defaultBackground: Color = background
|
||||||
|
val scenery = ArrayList<Scenery>()
|
||||||
|
override fun getPreferredSize(): Dimension {
|
||||||
|
return Dimension(Rs2MapEditor.cellX, Rs2MapEditor.cellY)
|
||||||
|
}
|
||||||
|
init {
|
||||||
|
|
||||||
|
//add(underlayLabel)
|
||||||
|
addMouseListener(object : MouseAdapter() {
|
||||||
|
override fun mouseEntered(e: MouseEvent) {
|
||||||
|
Rs2MapEditor.selectedPointX = e.component.bounds.location.x / Rs2MapEditor.cellX
|
||||||
|
Rs2MapEditor.selectedPointY = e.component.bounds.location.y / Rs2MapEditor.cellY
|
||||||
|
Rs2MapEditor.statusLabel.foreground = Color.YELLOW
|
||||||
|
Rs2MapEditor.statusLabel.text = "<html>Region: ${Rs2MapEditor.region} | " +
|
||||||
|
"Local Coordinates: [${Rs2MapEditor.selectedPointX}, ${Rs2MapEditor.selectedPointY}] | " +
|
||||||
|
"Global Coordinates: [${MapTileParser.coordinateX(Rs2MapEditor.selectedPointX)}, ${
|
||||||
|
MapTileParser.coordinateX(
|
||||||
|
Rs2MapEditor.selectedPointY
|
||||||
|
)
|
||||||
|
}] | " +
|
||||||
|
"Viewing Underlay: ${
|
||||||
|
MapTileParser.definition.getTile(
|
||||||
|
Rs2MapEditor.selectedPointX,
|
||||||
|
Rs2MapEditor.selectedPointY, 0).underlayId} | " +
|
||||||
|
"Selected Underlay: ${if (Rs2MapEditor.selectedUnderlayId == null) "<font color='red'>No underlay selected!</font>" else "${Rs2MapEditor.selectedUnderlayId}"}</html>"
|
||||||
|
defaultBackground = background
|
||||||
|
if(Rs2MapEditor.state == EditorState.SET_UNDERLAY || Rs2MapEditor.state == EditorState.NONE) {
|
||||||
|
background = Color.BLUE
|
||||||
|
} else if (Rs2MapEditor.state == EditorState.ADD_NPC){
|
||||||
|
background = Color.YELLOW
|
||||||
|
} else if (Rs2MapEditor.state == EditorState.ADD_GROUNDITEM){
|
||||||
|
background = Color.RED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseExited(e: MouseEvent) {
|
||||||
|
background = defaultBackground
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClicked(e: MouseEvent) {
|
||||||
|
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||||
|
if (Rs2MapEditor.selectedUnderlayId != null && Rs2MapEditor.state == EditorState.SET_UNDERLAY) {
|
||||||
|
val originalTile = MapTileParser.definition.getTile(
|
||||||
|
Rs2MapEditor.selectedPointX,
|
||||||
|
Rs2MapEditor.selectedPointY, 0)
|
||||||
|
val underlayID = Rs2MapEditor.selectedUnderlayId
|
||||||
|
val point = Point(Rs2MapEditor.selectedPointX, Rs2MapEditor.selectedPointY)
|
||||||
|
val oldValue = Rs2MapEditor.colorPointMap[point]
|
||||||
|
Rs2MapEditor.colorPointMap[point] = underlayID!!
|
||||||
|
println("UPDATED UNDERLAY VALUES @ [${point.x}, ${point.y}] [$oldValue >> ${Rs2MapEditor.colorPointMap[point]}]")
|
||||||
|
defaultBackground = Rs2MapEditor.underlayMap[Rs2MapEditor.selectedUnderlayId]?.getRGB()!!
|
||||||
|
background = Rs2MapEditor.underlayMap[Rs2MapEditor.selectedUnderlayId]?.getRGB()
|
||||||
|
|
||||||
|
// Update map tile cacheops.definitions with new tile information
|
||||||
|
MapTileParser.definition.setTile(point.x, point.y, Rs2MapEditor.plane,
|
||||||
|
MapTile(
|
||||||
|
originalTile.height,
|
||||||
|
originalTile.attrOpcode,
|
||||||
|
originalTile.overlayId,
|
||||||
|
originalTile.overlayPath,
|
||||||
|
originalTile.overlayRotation,
|
||||||
|
originalTile.settings,
|
||||||
|
underlayID
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (Rs2MapEditor.npcIdInput.text.isNotEmpty() && Rs2MapEditor.state == EditorState.ADD_NPC){
|
||||||
|
val id = Rs2MapEditor.npcIdInput.text.toIntOrNull()
|
||||||
|
if(id == null){
|
||||||
|
Rs2MapEditor.state = EditorState.NONE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val canWalk = Rs2MapEditor.npcCanWalkCheckbox.isSelected()
|
||||||
|
var spawnDirection = 0
|
||||||
|
for ((index, checkbox) in Rs2MapEditor.npcDirectionCheckboxes.withIndex()) {
|
||||||
|
if (checkbox.isSelected()) { spawnDirection = index; break }
|
||||||
|
}
|
||||||
|
val absolute = Util.getAbsoluteCoordinates(Rs2MapEditor.region, Rs2MapEditor.selectedPointX, Rs2MapEditor.selectedPointY, Rs2MapEditor.plane)
|
||||||
|
val npcSpawn = TableData.NPCSpawn(id, absolute, canWalk, spawnDirection)
|
||||||
|
Rs2MapEditor.npcs!!.add(npcSpawn)
|
||||||
|
Rs2MapEditor.componentPointMap.filter { it.key.x == Rs2MapEditor.selectedPointX && it.key.y == Rs2MapEditor.selectedPointY }.forEach { (_, cell) ->
|
||||||
|
var hasLabel = false
|
||||||
|
cell.components.forEach { if(it is JLabel && it.icon == Image.YELLOW_DOT) hasLabel = true }
|
||||||
|
cell.layout = FlowLayout()
|
||||||
|
if(!hasLabel) cell.add(JLabel(Image.YELLOW_DOT))
|
||||||
|
cell.repaint()
|
||||||
|
}
|
||||||
|
Rs2MapEditor.npcPanel.redrawRows()
|
||||||
|
Rs2MapEditor.npcsUpdated = true
|
||||||
|
}
|
||||||
|
else if (Rs2MapEditor.itemIdInput.text.isNotEmpty() && Rs2MapEditor.state == EditorState.ADD_GROUNDITEM){
|
||||||
|
val id = Rs2MapEditor.itemIdInput.text.toIntOrNull()
|
||||||
|
val amount = Rs2MapEditor.itemAmountInput.text.toIntOrNull() ?: 1
|
||||||
|
val respawnTime = Rs2MapEditor.itemRespawnInput.text.toIntOrNull() ?: 1
|
||||||
|
if(id == null){
|
||||||
|
Rs2MapEditor.state = EditorState.NONE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val item = Item(
|
||||||
|
id,
|
||||||
|
Rs2MapEditor.selectedPointX,
|
||||||
|
Rs2MapEditor.selectedPointY,
|
||||||
|
Rs2MapEditor.plane,
|
||||||
|
respawnTime,
|
||||||
|
amount
|
||||||
|
)
|
||||||
|
Rs2MapEditor.items.add(item)
|
||||||
|
Rs2MapEditor.componentPointMap.filter { it.key.x == Rs2MapEditor.selectedPointX && it.key.y == Rs2MapEditor.selectedPointY }.forEach { (_, cell) ->
|
||||||
|
var hasLabel = false
|
||||||
|
cell.components.forEach { if(it is JLabel && it.icon == Image.RED_DOT) hasLabel = true }
|
||||||
|
cell.layout = FlowLayout()
|
||||||
|
if(!hasLabel) cell.add(JLabel(Image.RED_DOT))
|
||||||
|
cell.repaint()
|
||||||
|
}
|
||||||
|
Rs2MapEditor.itemPanel.redrawRows()
|
||||||
|
Rs2MapEditor.itemsUpdated = true
|
||||||
|
}
|
||||||
|
} else if (SwingUtilities.isRightMouseButton(e)) {
|
||||||
|
val point = Point(Rs2MapEditor.selectedPointX, Rs2MapEditor.selectedPointY)
|
||||||
|
val def = MapTileParser.definition.getTile(point.x, point.y, Rs2MapEditor.plane)
|
||||||
|
val floDef = Rs2MapEditor.overlayMap[def.overlayId]!!
|
||||||
|
val cell = Rs2MapEditor.componentPointMap[point]!!
|
||||||
|
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("<table style=\"border:1px solid gray;margin-left:auto;margin-right:auto;>")
|
||||||
|
.append("<thead>")
|
||||||
|
.append("<tr style=\"text-align:center\">")
|
||||||
|
.append("<th>OverlayID</th>")
|
||||||
|
.append("<th>Color</th>")
|
||||||
|
.append("<th>Hide underlay</th>")
|
||||||
|
.append("</tr>")
|
||||||
|
.append("</thead>")
|
||||||
|
.append("<tbody>")
|
||||||
|
.append("<tr style=\"text-align:center\">")
|
||||||
|
.append("<td>${def.overlayId}</td>")
|
||||||
|
.append("<td>${floDef.color}</td>")
|
||||||
|
.append("<td>${floDef.hideUnderlay}</td>")
|
||||||
|
.append("</tr>")
|
||||||
|
.append("</tbody>")
|
||||||
|
.append("</table>")
|
||||||
|
.append("<br/>")
|
||||||
|
val thisAbsolute = Util.getAbsoluteCoordinates(Rs2MapEditor.region, Rs2MapEditor.selectedPointX, Rs2MapEditor.selectedPointY, Rs2MapEditor.plane)
|
||||||
|
val itemsHere = Rs2MapEditor.items.filter { it.x == Rs2MapEditor.selectedPointX && it.y == Rs2MapEditor.selectedPointY && it.plane == Rs2MapEditor.plane }.toList()
|
||||||
|
val npcsHere = Rs2MapEditor.npcs!!.filter { it.location == thisAbsolute }.toList()
|
||||||
|
|
||||||
|
if(npcsHere.isNotEmpty()) {
|
||||||
|
string.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>")
|
||||||
|
for (npc in npcsHere) {
|
||||||
|
string.append("<tr style=\"text-align:center\">")
|
||||||
|
string.append("<td>${npc.id}</td>")
|
||||||
|
string.append("<td>${TableData.npcNames[npc.id]}</td>")
|
||||||
|
string.append("</tr>")
|
||||||
|
}
|
||||||
|
string.append("</tbody></table><br/>")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(itemsHere.isNotEmpty()) {
|
||||||
|
string.append("<table style=\"border:1px solid gray;margin-left:auto;margin-right:auto;>")
|
||||||
|
.append("<thead>")
|
||||||
|
.append("<tr style=\"text-align:center\">")
|
||||||
|
.append("<th>Item ID</th>")
|
||||||
|
.append("<th>Info</th>")
|
||||||
|
.append("</tr>")
|
||||||
|
.append("</thead>")
|
||||||
|
.append("<tbody>")
|
||||||
|
for (item in itemsHere) {
|
||||||
|
string.append("<tr style=\"text-align:center\">")
|
||||||
|
string.append("<td>${item.id}</td>")
|
||||||
|
string.append("<td>${item.definition.name}[${item.amount}] \uD83D\uDD64${item.respawnTime}</td>")
|
||||||
|
string.append("</tr>")
|
||||||
|
}
|
||||||
|
string.append("</tbody></table><br/>")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scenery.isNotEmpty()) {
|
||||||
|
string.append("<h3>Scenery Info</h3>")
|
||||||
|
for(sc in scenery) {
|
||||||
|
if (sc.id != -1) {
|
||||||
|
string.append("${sc.definition.name} [ID: ${sc.id}]<br/>")
|
||||||
|
string.append("Type: ${sc.type}<br/>")
|
||||||
|
string.append("Rotation: ${sc.rotation}<br/>")
|
||||||
|
string.append("---------------------<br/>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rs2MapEditor.underlayInfo.text = String.format("<html><body style=\"text-align: center;\">%s</body></html>", string.toString())
|
||||||
|
Rs2MapEditor.infoPane.selectedIndex = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun flagScenery(scenery: Scenery){
|
||||||
|
this.scenery.add(scenery)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun paintComponent(g: Graphics) {
|
||||||
|
if(this.defaultBackground == Color(0,0,0,0)) return
|
||||||
|
super.paintComponent(g)
|
||||||
|
for(sc in scenery) {
|
||||||
|
var pointX1 = 0
|
||||||
|
var pointY1 = 0
|
||||||
|
var pointX2 = 0
|
||||||
|
var pointY2 = 0
|
||||||
|
val color = g.color
|
||||||
|
val rotationOdd = sc.rotation % 2 != 0
|
||||||
|
when (sc.type) {
|
||||||
|
10 -> g.drawOval(5, 5, this.width - 10, this.height - 10)
|
||||||
|
4 -> {
|
||||||
|
val offSetX =
|
||||||
|
if (!rotationOdd) (sc.rotation * 0.375 * width).toInt() else (0.35 * width).toInt()
|
||||||
|
val offSetY =
|
||||||
|
if (!rotationOdd) (0.65 * height).toInt() else (sc.rotation * 0.375 * height).toInt()
|
||||||
|
g.drawString("=", offSetX, offSetY)
|
||||||
|
}
|
||||||
|
11 -> {
|
||||||
|
g.color = Color(255, 255, 255, 75)
|
||||||
|
g.drawString("⛝", (0.25 * width).toInt(), (0.75 * height).toInt())
|
||||||
|
g.color = color
|
||||||
|
}
|
||||||
|
22 -> {
|
||||||
|
g.color = Color(255, 255, 255, 55)
|
||||||
|
g.drawString("⛆", (0.15 * width).toInt(), (0.65 * height).toInt())
|
||||||
|
g.color = color
|
||||||
|
}
|
||||||
|
0, 5 -> {
|
||||||
|
if (sc.id == 85) return
|
||||||
|
when (sc.rotation) {
|
||||||
|
0 -> {
|
||||||
|
pointX1 = 1; pointY1 = this.height - 1; pointX2 = 1; pointY2 = 1
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
pointX1 = 1; pointY1 = 1; pointX2 = this.width - 1; pointY2 = 1
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
pointX1 = this.width - 1; pointY1 = 1; pointX2 = this.width - 1; pointY2 = this.height - 1
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
pointX1 = 1; pointY1 = this.height - 1; pointX2 = this.width - 1; pointY2 = this.height - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sc.definition.interactive == 1 && sc.type == 0) {
|
||||||
|
g.color = Color.RED
|
||||||
|
}
|
||||||
|
g.drawLine(pointX1, pointY1, pointX2, pointY2)
|
||||||
|
g.color = color
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
val nPoints = 4
|
||||||
|
var xArray: IntArray = intArrayOf(0, 0, 0, 0)
|
||||||
|
var yArray: IntArray = intArrayOf(0, 0, 0, 0)
|
||||||
|
when (sc.rotation) {
|
||||||
|
0 -> {
|
||||||
|
xArray = intArrayOf(1, 1, 1, this.width - 1); yArray = intArrayOf(1, this.height - 1, 1, 1)
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
xArray = intArrayOf(1, this.width - 1, this.width - 1, this.width - 1); yArray = intArrayOf(1, 1, 1, this.height - 1)
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
xArray = intArrayOf(1, this.width - 1, this.width - 1, this.width - 1); yArray = intArrayOf(this.height - 1, this.height - 1, 1, this.height - 1)
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
xArray = intArrayOf(1,1,1,this.width - 1); yArray = intArrayOf(1,this.height - 1, this.height - 1, this.height - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sc.definition.interactive == 1) {
|
||||||
|
g.color = Color.RED
|
||||||
|
}
|
||||||
|
g.drawPolyline(xArray, yArray, nPoints)
|
||||||
|
g.color = color
|
||||||
|
}
|
||||||
|
|
||||||
|
9, 7, 6, 8 -> {
|
||||||
|
if (sc.id == 85 || sc.id == 83) return
|
||||||
|
when (sc.rotation) {
|
||||||
|
0, 2 -> {
|
||||||
|
pointX1 = 0; pointY1 = height; pointX2 = width; pointY2 = 0
|
||||||
|
}
|
||||||
|
1, 3 -> {
|
||||||
|
pointX1 = 0; pointY1 = 0; pointX2 = width; pointY2 = height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val overlayNorth = getOverlayId(sc.x + 1, sc.y)
|
||||||
|
val overlaySouth = getOverlayId(sc.x - 1, sc.y)
|
||||||
|
val northWest = getOverlayId(sc.x - 1, sc.y + 1)
|
||||||
|
val north = getOverlayId(sc.x, sc.y + 1)
|
||||||
|
val northEast = getOverlayId(sc.x + 1, sc.y + 1)
|
||||||
|
val east = getOverlayId(sc.x + 1, sc.y)
|
||||||
|
val southWest = getOverlayId(sc.x - 1, sc.y - 1)
|
||||||
|
val south = getOverlayId(sc.x, sc.y - 1)
|
||||||
|
val southEast = getOverlayId(sc.x + 1, sc.y - 1)
|
||||||
|
val west = getOverlayId(sc.x - 1, sc.y)
|
||||||
|
|
||||||
|
var backFillVertice = Pair(0, 0)
|
||||||
|
when (sc.rotation) {
|
||||||
|
0, 2 -> {
|
||||||
|
val sumA = getOverlaySum(north, northWest, west)
|
||||||
|
val sumB = getOverlaySum(south, southEast, east)
|
||||||
|
backFillVertice = if (sumA > sumB) Pair(width, height)
|
||||||
|
else if (sumA == sumB) Pair(-1, -1)
|
||||||
|
else Pair(0, 0)
|
||||||
|
}
|
||||||
|
1, 3 -> {
|
||||||
|
val sumA = getOverlaySum(north, northEast, east)
|
||||||
|
val sumB = getOverlaySum(south, southWest, west)
|
||||||
|
backFillVertice = if (sumA > sumB) Pair(0, height)
|
||||||
|
else if (sumA == sumB) Pair(-1, -1)
|
||||||
|
else Pair(width, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val fluDef = getUnderlayColor(sc.x, sc.y)
|
||||||
|
g.color = fluDef
|
||||||
|
if (overlaySouth != overlayNorth && backFillVertice.first != -1)
|
||||||
|
g.fillPolygon(
|
||||||
|
intArrayOf(pointX1, pointX2, backFillVertice.first),
|
||||||
|
intArrayOf(pointY1, pointY2, backFillVertice.second),
|
||||||
|
3
|
||||||
|
)
|
||||||
|
g.color = color
|
||||||
|
g.drawLine(pointX1, pointY1, pointX2, pointY2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOverlaySum(vararg overlays: Int): Int{
|
||||||
|
var sum = 0
|
||||||
|
for(overlay in overlays){
|
||||||
|
sum += overlay.coerceAtMost(1)
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUnderlayColor(x: Int, y: Int): Color {
|
||||||
|
var underlayID = (MapTileParser.definition.getTile(x, y, Rs2MapEditor.plane).underlayId - 1)
|
||||||
|
if (underlayID < 0) {
|
||||||
|
underlayID = 0
|
||||||
|
}
|
||||||
|
return Rs2MapEditor.underlayMap[underlayID]?.getRGB() ?: Color.BLACK
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOverlayId(x: Int, y: Int): Int {
|
||||||
|
return MapTileParser.definition.getTile(x, y, Rs2MapEditor.plane).overlayId
|
||||||
|
}
|
||||||
|
}
|
||||||
215
src/main/kotlin/ui/NPCSpawnPanel.kt
Normal file
215
src/main/kotlin/ui/NPCSpawnPanel.kt
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import EditorState
|
||||||
|
import Rs2MapEditor
|
||||||
|
import TableData
|
||||||
|
import cacheops.cache.definition.decoder.NPC
|
||||||
|
import const.Image
|
||||||
|
import misc.ImgButton
|
||||||
|
import tools.Util
|
||||||
|
import java.awt.Color
|
||||||
|
import java.awt.Dimension
|
||||||
|
import java.awt.FlowLayout
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
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.JTextField
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.Box
|
||||||
|
import javax.swing.SwingConstants
|
||||||
|
import javax.swing.border.MatteBorder
|
||||||
|
import javax.swing.event.DocumentListener
|
||||||
|
import javax.swing.event.DocumentEvent
|
||||||
|
|
||||||
|
class NPCSpawnPanel : JPanel() {
|
||||||
|
val rowBorder = MatteBorder(1, 1, 1, 1, Color.WHITE)
|
||||||
|
val removedRows = ArrayList<NPCRow>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
layout = BoxLayout(this, BoxLayout.Y_AXIS)
|
||||||
|
|
||||||
|
add(NPCSpawnerPanel())
|
||||||
|
|
||||||
|
val filterPanel = JPanel(FlowLayout())
|
||||||
|
val filterLabel = JLabel("Filter ")
|
||||||
|
val filterBox = JTextField("Enter search term...")
|
||||||
|
filterBox.document.addDocumentListener(FilterBoxListener(filterBox, ::filterRows))
|
||||||
|
|
||||||
|
filterPanel.add(filterLabel)
|
||||||
|
filterPanel.add(filterBox)
|
||||||
|
filterBox.minimumSize = Dimension(150, 30)
|
||||||
|
filterBox.preferredSize = Dimension(150, 30)
|
||||||
|
filterBox.maximumSize = Dimension(150, 60)
|
||||||
|
filterPanel.minimumSize = Dimension(300, 60)
|
||||||
|
filterPanel.maximumSize = Dimension(300, 60)
|
||||||
|
|
||||||
|
add(filterPanel)
|
||||||
|
|
||||||
|
|
||||||
|
Rs2MapEditor.npcs!!.forEach {
|
||||||
|
val row = NPCRow(it, this)
|
||||||
|
row.border = rowBorder
|
||||||
|
Rs2MapEditor.npcRows.add(row)
|
||||||
|
add(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun filterRows (term: String) {
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
var termAsInt = term.toIntOrNull()
|
||||||
|
Rs2MapEditor.npcRows.addAll(removedRows)
|
||||||
|
var rows = Rs2MapEditor.npcRows.toTypedArray()
|
||||||
|
removedRows.clear()
|
||||||
|
|
||||||
|
if (term.isNotEmpty() && termAsInt != null) {
|
||||||
|
for (row in rows) {
|
||||||
|
if (row.npc.id != termAsInt) {
|
||||||
|
removedRows.add(row)
|
||||||
|
Rs2MapEditor.npcRows.remove(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (term.isNotEmpty()) {
|
||||||
|
for (row in rows) {
|
||||||
|
var name = TableData.npcNames[row.npc.id]?.toLowerCase() ?: "null"
|
||||||
|
if (!name.contains(term, ignoreCase = true) && !term.contains(name, ignoreCase = true) && term.toLowerCase() != name) {
|
||||||
|
removedRows.add(row)
|
||||||
|
Rs2MapEditor.npcRows.remove(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (row in rows) {
|
||||||
|
remove(row)
|
||||||
|
revalidate()
|
||||||
|
}
|
||||||
|
for (row in Rs2MapEditor.npcRows) {
|
||||||
|
add(row)
|
||||||
|
revalidate()
|
||||||
|
}
|
||||||
|
Rs2MapEditor.infoPane.revalidate()
|
||||||
|
|
||||||
|
repaint(5L)
|
||||||
|
Rs2MapEditor.infoScrollPane.scrollFrame.viewport.repaint(5L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun redrawRows() {
|
||||||
|
Rs2MapEditor.npcRows.forEach {
|
||||||
|
remove(it)
|
||||||
|
}
|
||||||
|
Rs2MapEditor.npcRows.clear()
|
||||||
|
Rs2MapEditor.npcs!!.filter { it.location.z == Rs2MapEditor.plane }.forEach {
|
||||||
|
val row = NPCRow(it, this)
|
||||||
|
row.border = rowBorder
|
||||||
|
Rs2MapEditor.npcRows.add(row)
|
||||||
|
add(row)
|
||||||
|
}
|
||||||
|
removedRows.clear()
|
||||||
|
repaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
class NPCSpawnerPanel : JPanel() {
|
||||||
|
init {
|
||||||
|
val addButton = ImgButton(Image.ADD_HI, Image.ADD_LO)
|
||||||
|
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)
|
||||||
|
|
||||||
|
Rs2MapEditor.npcIdInput.addMouseListener (object : MouseAdapter() {
|
||||||
|
override fun mouseClicked (e: MouseEvent) {
|
||||||
|
NPCMenu.caller = {id, name ->
|
||||||
|
Rs2MapEditor.npcIdInput.text = id.toString()
|
||||||
|
}
|
||||||
|
NPCMenu.open()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minimumSize = Dimension(300, 120)
|
||||||
|
preferredSize = Dimension(300, 120)
|
||||||
|
maximumSize = Dimension(300, 120)
|
||||||
|
|
||||||
|
layout = FlowLayout()
|
||||||
|
add(Rs2MapEditor.npcIdInput)
|
||||||
|
add(addButton)
|
||||||
|
add(Rs2MapEditor.directionalCheckboxPanel)
|
||||||
|
add(JLabel("Can Walk?"))
|
||||||
|
add(Rs2MapEditor.npcCanWalkCheckbox)
|
||||||
|
border = MatteBorder(1, 1, 1, 1, Color.GREEN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterBoxListener (val textField: JTextField, val filterRows: (String) -> Unit) : DocumentListener {
|
||||||
|
override fun changedUpdate (e: DocumentEvent) {
|
||||||
|
filterRows(textField.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun insertUpdate (e: DocumentEvent) {
|
||||||
|
filterRows(textField.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeUpdate (e: DocumentEvent) {
|
||||||
|
filterRows(textField.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NPCRow(val npc: TableData.NPCSpawn, val parent: JPanel) : JPanel(){
|
||||||
|
init {
|
||||||
|
layout = BorderLayout()
|
||||||
|
val topPanel = JPanel(FlowLayout())
|
||||||
|
topPanel.add(JLabel("${TableData.npcNames[npc.id]}[${npc.id}]"))
|
||||||
|
|
||||||
|
val deleteButton = ImgButton(Image.DELETE_HI, Image.DELTE_LO)
|
||||||
|
topPanel.add(deleteButton)
|
||||||
|
|
||||||
|
val bottomPanel = JPanel(FlowLayout())
|
||||||
|
bottomPanel.add(JLabel("Direction [${spawnArrows[npc.spawnDirection]}] Walks? ${npc.canWalk}"))
|
||||||
|
add(topPanel, BorderLayout.NORTH)
|
||||||
|
add(JLabel("{${npc.location.x}, ${npc.location.y}, ${npc.location.z}}", SwingConstants.CENTER), BorderLayout.CENTER)
|
||||||
|
add(bottomPanel, BorderLayout.SOUTH)
|
||||||
|
|
||||||
|
minimumSize = Dimension(300, 65)
|
||||||
|
preferredSize = Dimension(300, 65)
|
||||||
|
maximumSize = Dimension(300, 65)
|
||||||
|
deleteButton.onClick {
|
||||||
|
Rs2MapEditor.npcs!!.remove(npc)
|
||||||
|
parent.remove(this)
|
||||||
|
parent.repaint()
|
||||||
|
Rs2MapEditor.npcRows.remove(this)
|
||||||
|
if(Rs2MapEditor.npcs!!.filter { it.location.x == npc.location.x && it.location.y == npc.location.y }.isEmpty()){
|
||||||
|
Rs2MapEditor.componentPointMap.filter { it.key.x == npc.location.localCoords[0] && it.key.y == npc.location.localCoords[1] }.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.location.localCoords[0] && it.key.y == npc.location.localCoords[1] }.forEach { it.value.border = border }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseExited(e: MouseEvent?) {
|
||||||
|
super.mouseExited(e)
|
||||||
|
Rs2MapEditor.componentPointMap.filter { it.key.x == npc.location.localCoords[0] && it.key.y == npc.location.localCoords[1] }.forEach{ it.value.border = defaultBorder }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val spawnArrows = arrayOf("⇖","⇑","⇗","⇐","⇒","⇙","⇓","⇘")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/main/kotlin/ui/PlaneButton.kt
Normal file
16
src/main/kotlin/ui/PlaneButton.kt
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import javax.swing.JButton
|
||||||
|
|
||||||
|
class PlaneButton(val plane: Int) : JButton(plane.toString()){
|
||||||
|
init {
|
||||||
|
addActionListener {
|
||||||
|
if(Rs2MapEditor.plane != this.plane){
|
||||||
|
Rs2MapEditor.plane = this.plane
|
||||||
|
Rs2MapEditor.npcPanel.redrawRows()
|
||||||
|
Rs2MapEditor.itemPanel.redrawRows()
|
||||||
|
Rs2MapEditor.mapPanel.repaintMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
src/main/kotlin/ui/SelectableUnderlayCell.kt
Normal file
80
src/main/kotlin/ui/SelectableUnderlayCell.kt
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import cacheops.cache.definition.decoder.MapTileParser
|
||||||
|
import java.awt.Color
|
||||||
|
import java.awt.Dimension
|
||||||
|
import java.awt.event.MouseAdapter
|
||||||
|
import java.awt.event.MouseEvent
|
||||||
|
import javax.swing.BorderFactory
|
||||||
|
import javax.swing.JLabel
|
||||||
|
import javax.swing.JPanel
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.border.Border
|
||||||
|
import javax.swing.border.MatteBorder
|
||||||
|
|
||||||
|
class SelectableUnderlayCell(color: Color, size: Int, val id: Any) : JPanel() {
|
||||||
|
init {
|
||||||
|
when (id) {
|
||||||
|
is Int -> {
|
||||||
|
background = color
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
background = color
|
||||||
|
border = BorderFactory.createDashedBorder(Color.GREEN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val text = JLabel("$id")
|
||||||
|
text.foreground = Color((color.rgb).inv()).brighter()
|
||||||
|
|
||||||
|
minimumSize = Dimension(size, size)
|
||||||
|
maximumSize = Dimension(size, size)
|
||||||
|
preferredSize = Dimension(size, size)
|
||||||
|
add(text)
|
||||||
|
|
||||||
|
addMouseListener(object : MouseAdapter() {
|
||||||
|
val border: Border = MatteBorder(1, 1, 1, 1, Color.GRAY)
|
||||||
|
val highlight: Border = MatteBorder(1, 1, 1, 1, Color.YELLOW)
|
||||||
|
val selectionBorder = MatteBorder(1, 1, 1, 1, Color.WHITE)
|
||||||
|
|
||||||
|
override fun mouseEntered(e: MouseEvent?) {
|
||||||
|
this@SelectableUnderlayCell.border = selectionBorder
|
||||||
|
Rs2MapEditor.colorPointMap.filter { it.value == id }.forEach{ Rs2MapEditor.componentPointMap[it.key]!!.border = highlight}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseExited(e: MouseEvent?) {
|
||||||
|
this@SelectableUnderlayCell.border = null
|
||||||
|
Rs2MapEditor.colorPointMap.filter { it.value == id }.forEach{ Rs2MapEditor.componentPointMap[it.key]!!.border = border}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClicked(e: MouseEvent) {
|
||||||
|
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||||
|
when (id) {
|
||||||
|
is Int -> {
|
||||||
|
if(Rs2MapEditor.selectedUnderlayId == id){
|
||||||
|
Rs2MapEditor.state = EditorState.NONE
|
||||||
|
} else {
|
||||||
|
Rs2MapEditor.state = EditorState.SET_UNDERLAY
|
||||||
|
Rs2MapEditor.selectedUnderlayId = id
|
||||||
|
}
|
||||||
|
Rs2MapEditor.statusLabel.text = "<html>Region: ${Rs2MapEditor.region} | " +
|
||||||
|
"Local Coordinates: [${Rs2MapEditor.selectedPointX}, ${Rs2MapEditor.selectedPointY}, ${Rs2MapEditor.plane}] | " +
|
||||||
|
"Global Coordinates: [${MapTileParser.coordinateX(Rs2MapEditor.selectedPointX)}, ${
|
||||||
|
MapTileParser.coordinateX(
|
||||||
|
Rs2MapEditor.selectedPointY
|
||||||
|
)
|
||||||
|
}, ${Rs2MapEditor.plane}] | " +
|
||||||
|
"Viewing Underlay: ${
|
||||||
|
MapTileParser.definition.getTile(
|
||||||
|
Rs2MapEditor.selectedPointX,
|
||||||
|
Rs2MapEditor.selectedPointY, 0).underlayId - 1} | " +
|
||||||
|
"Selected Underlay: ${if (Rs2MapEditor.selectedUnderlayId == null) "<font color='red'>No underlay selected!</font>" else "${Rs2MapEditor.selectedUnderlayId}"}</html>"
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println("User trying to add new underlay")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/main/kotlin/ui/TileInformationPanel.kt
Normal file
16
src/main/kotlin/ui/TileInformationPanel.kt
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
import java.awt.Color
|
||||||
|
import javax.swing.JPanel
|
||||||
|
import javax.swing.SwingConstants
|
||||||
|
|
||||||
|
class TileInformationPanel : JPanel() {
|
||||||
|
init {
|
||||||
|
Rs2MapEditor.underlayInfo.foreground = Color.white
|
||||||
|
Rs2MapEditor.underlayInfo.verticalAlignment = SwingConstants.TOP
|
||||||
|
Rs2MapEditor.underlayInfo.horizontalAlignment = SwingConstants.CENTER
|
||||||
|
layout = BorderLayout()
|
||||||
|
add(Rs2MapEditor.underlayInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main/kotlin/ui/UnderlaySelectionPanel.kt
Normal file
15
src/main/kotlin/ui/UnderlaySelectionPanel.kt
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import java.awt.Color
|
||||||
|
import javax.swing.JPanel
|
||||||
|
|
||||||
|
class UnderlaySelectionPanel : JPanel() {
|
||||||
|
init {
|
||||||
|
Rs2MapEditor.underlayMap.forEach {
|
||||||
|
val underlay = SelectableUnderlayCell(it.value.getRGB(), 30, it.key)
|
||||||
|
add(underlay)
|
||||||
|
}
|
||||||
|
val addAnUnderlay = SelectableUnderlayCell(Color.darkGray, 30, "+")
|
||||||
|
add(addAnUnderlay)
|
||||||
|
}
|
||||||
|
}
|
||||||
185
src/main/kotlin/worldmap/OverlayHandler.kt
Normal file
185
src/main/kotlin/worldmap/OverlayHandler.kt
Normal file
|
|
@ -0,0 +1,185 @@
|
||||||
|
package worldmap
|
||||||
|
|
||||||
|
import cacheops.cache.definition.data.OverlayDefinition
|
||||||
|
import cacheops.cache.definition.decoder.BlendedTextureDecoder
|
||||||
|
import cacheops.cache.definition.decoder.FloorOverlayConfiguration
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
object OverlayHandler {
|
||||||
|
|
||||||
|
var blendedOverlayColors: IntArray = IntArray(FloorOverlayConfiguration.floorOverlays.size + 1)
|
||||||
|
var p: IntArray = IntArray(65536)
|
||||||
|
|
||||||
|
var f_l = (Math.random() * 11.0).toInt() - 5
|
||||||
|
var n = (Math.random() * 17.0).toInt() - 8
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
f(0)
|
||||||
|
f_l += -2 + (5.0 * Math.random()).toInt()
|
||||||
|
if (f_l < -8) {
|
||||||
|
f_l = -8
|
||||||
|
}
|
||||||
|
n += -2 + (Math.random() * 5.0).toInt()
|
||||||
|
if (f_l > 8) {
|
||||||
|
f_l = 8
|
||||||
|
}
|
||||||
|
if (n < -16) {
|
||||||
|
n = -16
|
||||||
|
}
|
||||||
|
if (n > 16) {
|
||||||
|
n = 16
|
||||||
|
}
|
||||||
|
setOverlayColorArray(((f_l shr 2) shl 10), n shr 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOverlayColorArray(randomColorOffset1: Int, randomColorOffset2: Int) {
|
||||||
|
for (overlayId in 0 until FloorOverlayConfiguration.floorOverlays.size) {
|
||||||
|
blendedOverlayColors[overlayId + 1] = getOverlayColor(overlayId,randomColorOffset1,randomColorOffset2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOverlayColor(id: Int, colorOffset1: Int, colorOffset2: Int): Int {
|
||||||
|
val floDefinition: OverlayDefinition = FloorOverlayConfiguration.floorOverlays[id] ?: return 0
|
||||||
|
var floorOverlayTexture = floDefinition.texture
|
||||||
|
if (floorOverlayTexture >= 0 && BlendedTextureDecoder.blendedTextureDef[floorOverlayTexture]!!.renderOnMap) {
|
||||||
|
floorOverlayTexture = -1
|
||||||
|
}
|
||||||
|
val negativeRGBColor: Int
|
||||||
|
if (floDefinition.blendColor >= 0) {
|
||||||
|
val floorOverlayBlendColor = floDefinition.blendColor
|
||||||
|
var offsetBlendedValue = ((floorOverlayBlendColor and 0x7F) + colorOffset2)
|
||||||
|
if (offsetBlendedValue < 0) {
|
||||||
|
offsetBlendedValue = 0
|
||||||
|
} else if (offsetBlendedValue > 127) {
|
||||||
|
offsetBlendedValue = 127
|
||||||
|
}
|
||||||
|
val combinedBlendedValue = ((floorOverlayBlendColor + (colorOffset1 and 0xfc00) + ((floorOverlayBlendColor and 0x380))) + offsetBlendedValue)
|
||||||
|
negativeRGBColor = (0xffffff.inv() or p[colorFunc2(colorFunc1(96, 2, combinedBlendedValue),-2045205981).toInt() and 0xffff])
|
||||||
|
} else if (floorOverlayTexture >= 0) {
|
||||||
|
negativeRGBColor = (0xffffff.inv() or p[colorFunc2(colorFunc1(96, 2, BlendedTextureDecoder.blendedTextureDef[floorOverlayTexture]!!.blendedColor),-2045205981).toInt() and 0xffff])
|
||||||
|
} else if (floDefinition.color == -1) {
|
||||||
|
negativeRGBColor = 0
|
||||||
|
} else {
|
||||||
|
val floorOverlayColor = floDefinition.color
|
||||||
|
var offsetColorValue = ((floorOverlayColor and 0x7f) + colorOffset2)
|
||||||
|
if (offsetColorValue < 0) {
|
||||||
|
offsetColorValue = 0
|
||||||
|
} else if (offsetColorValue > 127) {
|
||||||
|
offsetColorValue = 127
|
||||||
|
}
|
||||||
|
val combinedColorValue = (((colorOffset1 and 0xfc00) + floorOverlayColor) + ((floorOverlayColor and 0x380) + offsetColorValue))
|
||||||
|
negativeRGBColor = (0xffffff.inv() or p[colorFunc2(colorFunc1(96, 2, combinedColorValue),-2045205981).toInt() and 0xffff])
|
||||||
|
}
|
||||||
|
return negativeRGBColor
|
||||||
|
}
|
||||||
|
|
||||||
|
fun colorFunc1(i: Int, i_1_: Int, i_2_: Int): Int {
|
||||||
|
var i = i
|
||||||
|
if (i_1_ != 2) {
|
||||||
|
return 64
|
||||||
|
}
|
||||||
|
if (i_2_ == -2) {
|
||||||
|
return 12345678
|
||||||
|
}
|
||||||
|
if (i_2_ == -1) {
|
||||||
|
if (i >= 2) {
|
||||||
|
if (i > 126) {
|
||||||
|
i = 126
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i = 2
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
i = i * (i_2_ and 0x7f) shr 7
|
||||||
|
if (i < 2) {
|
||||||
|
i = 2
|
||||||
|
} else if (i > 126) {
|
||||||
|
i = 126
|
||||||
|
}
|
||||||
|
return (0xff80 and i_2_) + i
|
||||||
|
}
|
||||||
|
|
||||||
|
fun colorFunc2(i: Int, i_1_: Int): Short {
|
||||||
|
return try {
|
||||||
|
val i_2_ = ((0xfddc and i) shr 10)
|
||||||
|
if (i_1_ != -2045205981) {
|
||||||
|
return 123.toShort()
|
||||||
|
}
|
||||||
|
var i_3_ = 0x384 and i shr 3
|
||||||
|
val i_4_ = 0x7f and i
|
||||||
|
i_3_ = if (i_4_ <= 64) i_4_ * i_3_ shr 7 else (127 - i_4_) * i_3_ shr 7
|
||||||
|
val i_5_ = i_3_ + i_4_
|
||||||
|
var i_6_: Int
|
||||||
|
do {
|
||||||
|
if (i_5_ == 0) {
|
||||||
|
i_6_ = i_3_ shl 1
|
||||||
|
if (!true) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i_6_ = (i_3_ shl 8) / i_5_
|
||||||
|
} while (false)
|
||||||
|
(i_5_ or (i_2_ shl 10 or i_6_ shr 4 shl 7)).toShort()
|
||||||
|
} catch (runtimeexception: RuntimeException) {
|
||||||
|
throw error("fuk")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f(i: Int) {
|
||||||
|
val d = -0.015 + 0.03 * Math.random() + 0.7
|
||||||
|
var i_7_ = i
|
||||||
|
for (i_8_ in 0..511) {
|
||||||
|
val f = (0.0078125f + (i_8_ shr 3).toFloat() / 64.0f) * 360.0f
|
||||||
|
val f_9_ = (i_8_ and 0x7).toFloat() / 8.0f + 0.0625f
|
||||||
|
for (i_10_ in 0..127) {
|
||||||
|
val f_11_ = i_10_.toFloat() / 128.0f
|
||||||
|
var f_12_ = 0.0f
|
||||||
|
var f_13_ = 0.0f
|
||||||
|
var f_14_ = 0.0f
|
||||||
|
val f_15_ = f / 60.0f
|
||||||
|
val i_16_ = f_15_.toInt()
|
||||||
|
val i_17_ = i_16_ % 6
|
||||||
|
val f_18_ = f_15_ - i_16_.toFloat()
|
||||||
|
val f_19_ = f_11_ * (1.0f - f_9_)
|
||||||
|
val f_20_ = f_11_ * (-(f_18_ * f_9_) + 1.0f)
|
||||||
|
val f_21_ = f_11_ * (-(f_9_ * (-f_18_ + 1.0f)) + 1.0f)
|
||||||
|
if (i_17_ == 0) {
|
||||||
|
f_13_ = f_21_
|
||||||
|
f_14_ = f_19_
|
||||||
|
f_12_ = f_11_
|
||||||
|
} else if (i_17_ == 1) {
|
||||||
|
f_14_ = f_19_
|
||||||
|
f_13_ = f_11_
|
||||||
|
f_12_ = f_20_
|
||||||
|
} else if (i_17_ == 2) {
|
||||||
|
f_14_ = f_21_
|
||||||
|
f_13_ = f_11_
|
||||||
|
f_12_ = f_19_
|
||||||
|
} else if (i_17_ == 3) {
|
||||||
|
f_13_ = f_20_
|
||||||
|
f_12_ = f_19_
|
||||||
|
f_14_ = f_11_
|
||||||
|
} else if (i_17_ == 4) {
|
||||||
|
f_13_ = f_19_
|
||||||
|
f_12_ = f_21_
|
||||||
|
f_14_ = f_11_
|
||||||
|
} else if (i_17_ == 5) {
|
||||||
|
f_12_ = f_11_
|
||||||
|
f_13_ = f_19_
|
||||||
|
f_14_ = f_20_
|
||||||
|
}
|
||||||
|
f_12_ = f_12_.toDouble().pow(d).toFloat()
|
||||||
|
f_13_ = f_13_.toDouble().pow(d).toFloat()
|
||||||
|
f_14_ = f_14_.toDouble().pow(d).toFloat()
|
||||||
|
val i_22_ = (f_12_ * 256.0f).toInt()
|
||||||
|
val i_23_ = (f_13_ * 254.0f).toInt()
|
||||||
|
val i_24_ = (f_14_ * 256.0f).toInt()
|
||||||
|
val i_25_ = i_24_ + ((i_23_ shl 8) - 16777216 + (i_22_ shl 16))
|
||||||
|
p[i_7_++] = i_25_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
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