mirror of
https://gitlab.com/2009scape/tools/rs09-thanos-tool.git
synced 2026-08-01 14:39:20 -06:00
Added v1.0
This commit is contained in:
commit
af4b79a14b
18 changed files with 1751 additions and 0 deletions
37
build.gradle
Normal file
37
build.gradle
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
plugins {
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.4.32'
|
||||
}
|
||||
|
||||
group 'org.example'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
repositories {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains:markdown-jvm:0.2.0"
|
||||
implementation "com.github.ajalt.mordant:mordant:2.0.0-alpha2"
|
||||
implementation "com.github.weisj:darklaf-core:2.5.5"
|
||||
implementation "com.googlecode.json-simple:json-simple:1.1.1"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib"
|
||||
}
|
||||
|
||||
task buildJar(type: Jar) {
|
||||
manifest {
|
||||
attributes(
|
||||
'Main-Class': 'MainScreenKt'
|
||||
)
|
||||
}
|
||||
from {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
{
|
||||
exclude "META-INF/*.SF"
|
||||
exclude "META-INF/*.DSA"
|
||||
exclude "META-INF/*.RSA"
|
||||
}
|
||||
with jar
|
||||
}
|
||||
1
gradle.properties
Normal file
1
gradle.properties
Normal file
|
|
@ -0,0 +1 @@
|
|||
kotlin.code.style=official
|
||||
2
settings.gradle
Normal file
2
settings.gradle
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
rootProject.name = 'rs09-thanos-tool'
|
||||
|
||||
363
src/main/kotlin/DropTableEditor.kt
Normal file
363
src/main/kotlin/DropTableEditor.kt
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.event.*
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
import java.util.*
|
||||
import javax.swing.*
|
||||
import javax.swing.event.ChangeEvent
|
||||
import javax.swing.table.DefaultTableModel
|
||||
|
||||
class DropTableEditor(val table: NPCDropTable) : JFrame("Editing ${if(table.ids.isNotBlank()) TableData.npcNames[table.ids.split(",")[0].toInt()] ?: "Unknown Table" else "None"}") {
|
||||
val IDsField = JTextField()
|
||||
val descriptionField = JTextField()
|
||||
val mainModel = object : DefaultTableModel(){}
|
||||
val defaultModel = object : DefaultTableModel(){}
|
||||
val charmModel = object : DefaultTableModel(){}
|
||||
|
||||
val mainTable = object : JTable(mainModel){
|
||||
override fun editCellAt(row: Int, column: Int): Boolean {
|
||||
if(column == 0 || column == 1){
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.setValueAt(id,row,0)
|
||||
model.setValueAt(name,row,1)
|
||||
table[row].id = id
|
||||
}
|
||||
ItemMenu.open()
|
||||
return false
|
||||
}
|
||||
return super.editCellAt(row, column)
|
||||
}
|
||||
|
||||
override fun editCellAt(row: Int, column: Int, e: EventObject?): Boolean {
|
||||
if(column == 0 || column == 1){
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.setValueAt(id,row,0)
|
||||
model.setValueAt(name,row,1)
|
||||
table[row].id = id
|
||||
}
|
||||
ItemMenu.open()
|
||||
return false
|
||||
}
|
||||
return super.editCellAt(row, column, e)
|
||||
}
|
||||
override fun editingStopped(e: ChangeEvent?) {
|
||||
val editor = cellEditor
|
||||
val newValue = editor.cellEditorValue.toString()
|
||||
when(editingColumn){
|
||||
2 -> table[editingRow].minAmt = newValue
|
||||
3 -> table[editingRow].maxAmt = newValue
|
||||
4 -> {
|
||||
table.totalWeight += newValue.toDouble() - table[editingRow].weight
|
||||
table[editingRow].weight = newValue.toDouble()
|
||||
updateMainPercentages()
|
||||
}
|
||||
}
|
||||
super.editingStopped(e)
|
||||
}
|
||||
}
|
||||
val mainScrollpane = JScrollPane(mainTable)
|
||||
val mainSubtable = Subtable("Main",mainScrollpane,table,mainModel)
|
||||
|
||||
val defaultTable = object : JTable(defaultModel){
|
||||
override fun editCellAt(row: Int, column: Int): Boolean {
|
||||
if(column == 0 || column == 1){
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.setValueAt(id,row,0)
|
||||
model.setValueAt(name,row,1)
|
||||
table.alwaysTable[row].id = id
|
||||
}
|
||||
ItemMenu.open()
|
||||
return false
|
||||
}
|
||||
return super.editCellAt(row, column)
|
||||
}
|
||||
|
||||
override fun editCellAt(row: Int, column: Int, e: EventObject?): Boolean {
|
||||
if(column == 0 || column == 1){
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.setValueAt(id,row,0)
|
||||
model.setValueAt(name,row,1)
|
||||
table.alwaysTable[row].id = id
|
||||
}
|
||||
ItemMenu.open()
|
||||
return false
|
||||
}
|
||||
return super.editCellAt(row, column, e)
|
||||
}
|
||||
override fun editingStopped(e: ChangeEvent?) {
|
||||
val editor = cellEditor
|
||||
val newValue = editor.cellEditorValue.toString()
|
||||
when(editingColumn){
|
||||
2 -> table.alwaysTable[editingRow].minAmt = newValue
|
||||
3 -> table.alwaysTable[editingRow].maxAmt = newValue
|
||||
}
|
||||
super.editingStopped(e)
|
||||
}
|
||||
}
|
||||
val defaultScrollPane = JScrollPane(defaultTable)
|
||||
val defaultSubtable = Subtable("Always",defaultScrollPane,table.alwaysTable,defaultModel)
|
||||
|
||||
val charmTable = object : JTable(charmModel){
|
||||
override fun editCellAt(row: Int, column: Int): Boolean {
|
||||
if(column == 0 || column == 1){
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.setValueAt(id,row,0)
|
||||
model.setValueAt(name,row,1)
|
||||
table.charmTable[row].id = id
|
||||
}
|
||||
ItemMenu.open()
|
||||
return false
|
||||
}
|
||||
return super.editCellAt(row, column)
|
||||
}
|
||||
|
||||
override fun editCellAt(row: Int, column: Int, e: EventObject?): Boolean {
|
||||
if(column == 0 || column == 1){
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.setValueAt(id,row,0)
|
||||
model.setValueAt(name,row,1)
|
||||
table.charmTable[row].id = id
|
||||
}
|
||||
ItemMenu.open()
|
||||
return false
|
||||
}
|
||||
return super.editCellAt(row, column, e)
|
||||
}
|
||||
override fun editingStopped(e: ChangeEvent?) {
|
||||
val editor = cellEditor
|
||||
val newValue = editor.cellEditorValue.toString()
|
||||
when(editingColumn){
|
||||
2 -> table.charmTable[editingRow].minAmt = newValue
|
||||
3 -> table.charmTable[editingRow].maxAmt = newValue
|
||||
4 -> {
|
||||
table.charmTable.totalWeight += newValue.toDouble() - table.charmTable[editingRow].weight
|
||||
table.charmTable[editingRow].weight = newValue.toDouble()
|
||||
updateCharmPercentages()
|
||||
}
|
||||
}
|
||||
super.editingStopped(e)
|
||||
}
|
||||
}
|
||||
val charmScrollPane = JScrollPane(charmTable)
|
||||
val charmSubtable = Subtable("Charm",charmScrollPane,table.charmTable,charmModel)
|
||||
|
||||
init {
|
||||
layout = BorderLayout()
|
||||
val topPanel = JPanel()
|
||||
val IDsLabel = JLabel("IDs: ")
|
||||
IDsField.preferredSize = Dimension(200,20)
|
||||
IDsField.addKeyListener(object : KeyListener {
|
||||
override fun keyTyped(e: KeyEvent?) {}
|
||||
override fun keyPressed(e: KeyEvent?) {}
|
||||
override fun keyReleased(e: KeyEvent?) {
|
||||
table.ids = IDsField.text
|
||||
}
|
||||
})
|
||||
IDsField.text = table.ids
|
||||
descriptionField.preferredSize = Dimension(400,20)
|
||||
descriptionField.text = table.description
|
||||
descriptionField.addKeyListener(object : KeyListener{
|
||||
override fun keyTyped(e: KeyEvent?) {}
|
||||
override fun keyPressed(e: KeyEvent?) {}
|
||||
override fun keyReleased(e: KeyEvent?) {
|
||||
table.description = descriptionField.text
|
||||
}
|
||||
})
|
||||
topPanel.add(IDsLabel)
|
||||
topPanel.add(IDsField)
|
||||
|
||||
val mainButton = JButton("Edit Main")
|
||||
mainButton.addActionListener {
|
||||
mainSubtable.open()
|
||||
}
|
||||
topPanel.add(mainButton)
|
||||
|
||||
val charmsButton = JButton("Edit Charms")
|
||||
charmsButton.addActionListener {
|
||||
charmSubtable.open()
|
||||
}
|
||||
topPanel.add(charmsButton)
|
||||
|
||||
val defaultButton = JButton("Edit Default")
|
||||
defaultButton.addActionListener {
|
||||
defaultSubtable.open()
|
||||
}
|
||||
topPanel.add(defaultButton)
|
||||
|
||||
add(topPanel,BorderLayout.NORTH)
|
||||
|
||||
val descriptionPanel = JPanel()
|
||||
val descriptionLabel = JLabel("Description: ")
|
||||
descriptionPanel.add(descriptionLabel)
|
||||
descriptionPanel.add(descriptionField)
|
||||
|
||||
add(descriptionPanel,BorderLayout.SOUTH)
|
||||
|
||||
mainModel.addColumn("ID")
|
||||
mainModel.addColumn("Name")
|
||||
mainModel.addColumn("Min Amt")
|
||||
mainModel.addColumn("Max Amt")
|
||||
mainModel.addColumn("Weight")
|
||||
mainModel.addColumn("(%)")
|
||||
|
||||
defaultModel.addColumn("ID")
|
||||
defaultModel.addColumn("Name")
|
||||
defaultModel.addColumn("Min Amt")
|
||||
defaultModel.addColumn("Max Amt")
|
||||
|
||||
charmModel.addColumn("ID")
|
||||
charmModel.addColumn("Name")
|
||||
charmModel.addColumn("Min Amt")
|
||||
charmModel.addColumn("Max Amt")
|
||||
charmModel.addColumn("Weight")
|
||||
charmModel.addColumn("(%)")
|
||||
|
||||
mainTable.inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete")
|
||||
mainTable.actionMap.put("delete",object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
try {
|
||||
table.totalWeight -= table[mainTable.selectedRow].weight
|
||||
table.removeAt(mainTable.selectedRow)
|
||||
mainModel.removeRow(mainTable.selectedRow)
|
||||
updateMainPercentages()
|
||||
} catch(e: Exception){
|
||||
Logger.logErr("Tried to remove nonexistent row ${mainTable.selectedRow}")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
defaultTable.inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete")
|
||||
defaultTable.actionMap.put("delete",object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
try {
|
||||
table.alwaysTable.removeAt(defaultTable.selectedRow)
|
||||
defaultModel.removeRow(defaultTable.selectedRow)
|
||||
} catch(e: Exception){
|
||||
Logger.logErr("Tried to remove nonexistent row ${defaultTable.selectedRow}")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
charmTable.inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete")
|
||||
charmTable.actionMap.put("delete",object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
try {
|
||||
table.totalWeight -= table.charmTable[charmTable.selectedRow].weight
|
||||
table.charmTable.removeAt(charmTable.selectedRow)
|
||||
charmModel.removeRow(charmTable.selectedRow)
|
||||
updateCharmPercentages()
|
||||
} catch(e: Exception){
|
||||
Logger.logErr("Tried to remove nonexistent row ${charmTable.selectedRow}")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
addWindowListener(object : WindowAdapter(){
|
||||
override fun windowClosing(e: WindowEvent?) {
|
||||
FileLoader.dropTableList?.populated = false
|
||||
FileLoader.dropTableList?.dispatchEvent(WindowEvent(FileLoader.dropTableList!!, WindowEvent.WINDOW_CLOSING))
|
||||
FileLoader.dropTableList?.open()
|
||||
super.windowClosing(e)
|
||||
}
|
||||
})
|
||||
|
||||
pack()
|
||||
|
||||
isVisible = false
|
||||
}
|
||||
|
||||
class Subtable(val label: String, val pane: JScrollPane, val table: WeightBasedTable, val model: DefaultTableModel) : JFrame("Editing $label Drops"){
|
||||
init {
|
||||
layout = BorderLayout()
|
||||
|
||||
val panel = JPanel()
|
||||
panel.layout = BorderLayout()
|
||||
val topPanel = JPanel()
|
||||
|
||||
val mainLabel = JLabel("$label Drops")
|
||||
topPanel.add(mainLabel)
|
||||
val addButton = JButton("Add Drop")
|
||||
addButton.addActionListener {
|
||||
ItemMenu.caller = {id,name ->
|
||||
when(label){
|
||||
"Always" -> {
|
||||
model.addRow(arrayOf(id,name,1,1))
|
||||
table.add(WeightedItem(id,"1","1",1.0,true))
|
||||
}
|
||||
else -> {
|
||||
model.addRow(arrayOf(id,name,1,1,1.0,""))
|
||||
table.add(WeightedItem(id,"1","1",1.0,false))
|
||||
updatePercentages(model)
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemMenu.open()
|
||||
}
|
||||
topPanel.add(addButton)
|
||||
|
||||
panel.add(topPanel,BorderLayout.NORTH)
|
||||
panel.add(pane,BorderLayout.SOUTH)
|
||||
|
||||
add(panel)
|
||||
pack()
|
||||
minimumSize = Dimension(width + 40,height + 50)
|
||||
isVisible = false
|
||||
}
|
||||
|
||||
fun open(){
|
||||
isVisible = true
|
||||
}
|
||||
fun updatePercentages(model: DefaultTableModel){
|
||||
for(i in 0 until model.rowCount){
|
||||
model.setValueAt(getPercentage(table[i].weight,table),i,5)
|
||||
}
|
||||
}
|
||||
|
||||
fun getPercentage(weight: Double, table: WeightBasedTable): String{
|
||||
return "${round((weight / table.totalWeight) * 100.0,2)}%"
|
||||
}
|
||||
fun round(value: Double, places: Int): Double {
|
||||
require(places >= 0)
|
||||
var bd: BigDecimal = BigDecimal.valueOf(value)
|
||||
bd = bd.setScale(places, RoundingMode.HALF_UP)
|
||||
return bd.toDouble()
|
||||
}
|
||||
}
|
||||
|
||||
fun open(){
|
||||
for(item in table.alwaysTable){
|
||||
defaultModel.addRow(arrayOf(item.id,TableData.getItemName(item.id),item.minAmt,item.maxAmt))
|
||||
}
|
||||
for(item in table.charmTable){
|
||||
charmModel.addRow(arrayOf(item.id,TableData.getItemName(item.id),item.minAmt,item.maxAmt,item.weight,getPercentage(item.weight,table.charmTable)))
|
||||
}
|
||||
for(item in table){
|
||||
mainModel.addRow(arrayOf(item.id,TableData.getItemName(item.id),item.minAmt,item.maxAmt,item.weight,getPercentage(item.weight,table)))
|
||||
}
|
||||
isVisible = true
|
||||
}
|
||||
|
||||
fun getPercentage(weight: Double, table: WeightBasedTable): String{
|
||||
return "${round((weight / table.totalWeight) * 100.0,2)}%"
|
||||
}
|
||||
|
||||
fun updateCharmPercentages(){
|
||||
for(i in 0 until charmModel.rowCount){
|
||||
charmModel.setValueAt(getPercentage(table.charmTable[i].weight,table.charmTable),i,5)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateMainPercentages(){
|
||||
for(i in 0 until mainModel.rowCount){
|
||||
mainModel.setValueAt(getPercentage(table[i].weight,table),i,5)
|
||||
}
|
||||
}
|
||||
|
||||
fun round(value: Double, places: Int): Double {
|
||||
require(places >= 0)
|
||||
var bd: BigDecimal = BigDecimal.valueOf(value)
|
||||
bd = bd.setScale(places, RoundingMode.HALF_UP)
|
||||
return bd.toDouble()
|
||||
}
|
||||
}
|
||||
21
src/main/kotlin/EditorConstants.kt
Normal file
21
src/main/kotlin/EditorConstants.kt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import com.github.weisj.darklaf.LafManager
|
||||
import com.github.weisj.darklaf.theme.OneDarkTheme
|
||||
|
||||
object EditorConstants {
|
||||
var BUILD_NUMBER = "0.1.0"
|
||||
|
||||
var DARK_MODE = true
|
||||
|
||||
var CONFIG_PATH = ""
|
||||
|
||||
var VALID_FILES = arrayOf("drop_tables.json","npc_configs.json","item_configs.json", "shops.json", "object_configs.json")
|
||||
|
||||
var CREDITS = arrayOf(
|
||||
"weisJ - darklaf look and feel themes http://github.com/weisj",
|
||||
"ceikry - design and programming http://gitlab.com/ceikry"
|
||||
)
|
||||
|
||||
fun updateTheme(){
|
||||
if(EditorConstants.DARK_MODE) LafManager.install(OneDarkTheme()) else LafManager.install()
|
||||
}
|
||||
}
|
||||
19
src/main/kotlin/EditorData.kt
Normal file
19
src/main/kotlin/EditorData.kt
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import org.json.simple.JSONArray
|
||||
import org.json.simple.parser.JSONParser
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
|
||||
open class EditorData(val fileName: String) {
|
||||
var reader: FileReader? = null// = FileReader(EditorConstants.CONFIG_PATH + File.separator + fileName)
|
||||
val parser = JSONParser()
|
||||
var data = JSONArray()
|
||||
|
||||
fun configureParser(){
|
||||
reader = FileReader(EditorConstants.CONFIG_PATH + File.separator + fileName)
|
||||
data = parser.parse(reader) as JSONArray
|
||||
}
|
||||
|
||||
open fun parse() {}
|
||||
open fun save() {}
|
||||
open fun show() {}
|
||||
}
|
||||
269
src/main/kotlin/Editors.kt
Normal file
269
src/main/kotlin/Editors.kt
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import org.json.simple.parser.JSONParser
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.lang.Exception
|
||||
import java.lang.StringBuilder
|
||||
import javax.script.ScriptEngineManager
|
||||
|
||||
enum class Editors(val data: EditorData) {
|
||||
DROP_TABLES(object : EditorData("drop_tables.json"){
|
||||
var counter = 0
|
||||
override fun parse() {
|
||||
Logger.logInfo("Parsing Drop Tables")
|
||||
configureParser()
|
||||
data.forEach { dropTableRaw ->
|
||||
val dropTable = dropTableRaw as org.json.simple.JSONObject
|
||||
val table = NPCDropTable()
|
||||
table.ids = dropTable["ids"].toString()
|
||||
parseTable(dropTable["main"] as JSONArray,table,false)
|
||||
parseTable(dropTable["default"] as JSONArray,table,true)
|
||||
parseTable(dropTable["charm"] as JSONArray,table,false)
|
||||
table.description = (dropTable["description"] ?: "").toString()
|
||||
TableData.tables.add(table)
|
||||
counter++
|
||||
}
|
||||
Logger.logInfo("$counter Drop Tables Parsed.")
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
val CHARMS = intArrayOf(12160,12163,12159,12158)
|
||||
val dtables = JSONArray()
|
||||
for(table in TableData.tables){
|
||||
val t = JSONObject()
|
||||
t.put("ids",table.ids)
|
||||
val main = saveTable(table)
|
||||
val charms = saveTable(table.charmTable)
|
||||
val always = saveTable(table.alwaysTable)
|
||||
t.put("main",main)
|
||||
t.put("charm",charms)
|
||||
t.put("default",always)
|
||||
t.put("description",table.description)
|
||||
dtables.add(t)
|
||||
}
|
||||
|
||||
|
||||
val manager = ScriptEngineManager()
|
||||
val scriptEngine = manager.getEngineByName("JavaScript")
|
||||
scriptEngine.put("jsonString", dtables.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()
|
||||
}
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
super.show()
|
||||
}
|
||||
}),
|
||||
NPC_CONFIGS(object : EditorData("npc_configs.json"){
|
||||
override fun parse() {
|
||||
Logger.logInfo("Parsing NPC configs")
|
||||
configureParser()
|
||||
data.forEach { npcDataRaw ->
|
||||
val npcData = npcDataRaw as JSONObject
|
||||
val id = npcData["id"].toString().toInt()
|
||||
val name = npcData["name"].toString()
|
||||
TableData.npcNames[id] = name
|
||||
TableData.npcConfigKeys.addAll(npcData.keys.toHashSet() as HashSet<String>)
|
||||
TableData.npcConfigs.add(npcData)
|
||||
}
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
val array = JSONArray()
|
||||
TableData.npcConfigs.forEach {
|
||||
array.add(it)
|
||||
}
|
||||
val manager = ScriptEngineManager()
|
||||
val scriptEngine = manager.getEngineByName("JavaScript")
|
||||
scriptEngine.put("jsonString", array.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()
|
||||
}
|
||||
}
|
||||
}),
|
||||
ITEM_CONFIGS(object : EditorData("item_configs.json"){
|
||||
override fun parse() {
|
||||
configureParser()
|
||||
data.forEach { itemDataRaw ->
|
||||
val itemData = itemDataRaw as JSONObject
|
||||
val id = itemData["id"].toString().toInt()
|
||||
val name = itemData["name"].toString()
|
||||
TableData.itemConfigKeys.addAll(itemData.keys.toHashSet() as HashSet<String>)
|
||||
TableData.itemNames[id] = name
|
||||
TableData.itemConfigs.add(itemData)
|
||||
}
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
val array = JSONArray()
|
||||
TableData.itemConfigs.forEach {
|
||||
array.add(it)
|
||||
}
|
||||
val manager = ScriptEngineManager()
|
||||
val scriptEngine = manager.getEngineByName("JavaScript")
|
||||
scriptEngine.put("jsonString", array.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()
|
||||
}
|
||||
}
|
||||
}),
|
||||
OBJECT_CONFIGS(object : EditorData("object_configs.json"){
|
||||
override fun parse() {
|
||||
Logger.logInfo("Parsing Object configs")
|
||||
configureParser()
|
||||
data.forEach { ObjDataRaw ->
|
||||
val objData = ObjDataRaw as JSONObject
|
||||
TableData.objConfigKeys.addAll(objData.keys.toHashSet() as HashSet<String>)
|
||||
TableData.objConfigs.add(objData)
|
||||
}
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
val array = JSONArray()
|
||||
TableData.objConfigs.forEach {
|
||||
array.add(it)
|
||||
}
|
||||
val manager = ScriptEngineManager()
|
||||
val scriptEngine = manager.getEngineByName("JavaScript")
|
||||
scriptEngine.put("jsonString", array.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()
|
||||
}
|
||||
}
|
||||
}),
|
||||
SHOPS(object : EditorData("shops.json"){
|
||||
override fun parse() {
|
||||
Logger.logInfo("Parsing shop data...")
|
||||
configureParser()
|
||||
var counter = 0
|
||||
|
||||
data.forEach { shopDataRaw ->
|
||||
val shopData = shopDataRaw as JSONObject
|
||||
val id = shopData["id"].toString().toInt()
|
||||
val title = shopData["title"].toString()
|
||||
val general = shopData["general_store"].toString().toBoolean()
|
||||
val stock = parseStock(shopData["stock"].toString())
|
||||
val npcs = if(shopData["npcs"].toString().isNotBlank()) shopData["npcs"].toString() else ""
|
||||
val currency = shopData["currency"].toString().toInt()
|
||||
val highAlch = shopData["high_alch"].toString() == "1"
|
||||
TableData.shops[id] = TableData.Shop(id,title,stock,npcs,currency,general,highAlch)
|
||||
counter++
|
||||
}
|
||||
|
||||
Logger.logInfo("Loaded $counter shops.")
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
val shs = JSONArray()
|
||||
|
||||
fun <T> ArrayList<T>.isLast(thing: T): Boolean{
|
||||
return indexOf(thing) == size - 1
|
||||
}
|
||||
|
||||
for((_,shop) in TableData.shops){
|
||||
val sh = JSONObject()
|
||||
sh.put("id",shop.id.toString())
|
||||
sh.put("title",shop.title)
|
||||
val stockBuilder = StringBuilder()
|
||||
for(item in shop.stock){
|
||||
stockBuilder.append("{${item.id},${if(item.infinite) "inf" else item.amount}}${if(shop.stock.isLast(item)) "" else "-"}")
|
||||
}
|
||||
sh.put("stock",stockBuilder.toString())
|
||||
sh.put("npcs",shop.npcs)
|
||||
sh.put("currency",shop.currency.toString())
|
||||
sh.put("high_alch",if(shop.high_alch) "1" else "0")
|
||||
sh.put("general_store",shop.general_store.toString())
|
||||
shs.add(sh)
|
||||
}
|
||||
|
||||
|
||||
val manager = ScriptEngineManager()
|
||||
val scriptEngine = manager.getEngineByName("JavaScript")
|
||||
scriptEngine.put("jsonString", shs.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()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fun parseStock(stock: String): ArrayList<Item>{
|
||||
val items = ArrayList<Item>()
|
||||
if(stock.isEmpty()){
|
||||
return items
|
||||
}
|
||||
stock.split('-').map {
|
||||
val tokens = it.replace("{", "").replace("}", "").split(",".toRegex()).toTypedArray()
|
||||
var amount = tokens[1].trim()
|
||||
items.add(Item(tokens[0].trim().toInt(),amount,amount == "inf"))
|
||||
}
|
||||
return items
|
||||
}
|
||||
private fun parseTable(data: JSONArray, destTable: WeightBasedTable, isAlways: Boolean) {
|
||||
for(it in data){
|
||||
val item = it as JSONObject
|
||||
val id = item["id"].toString().toInt()
|
||||
val minAmount = item["minAmount"].toString().toInt()
|
||||
val maxAmount = item["maxAmount"].toString().toInt()
|
||||
val weight = item["weight"].toString().toDouble()
|
||||
val newItem = WeightedItem(id,minAmount.toString(),maxAmount.toString(),weight.toDouble(),isAlways)
|
||||
destTable.add(newItem)
|
||||
}
|
||||
}
|
||||
private fun saveTable(table: WeightBasedTable): JSONArray{
|
||||
val arr = JSONArray()
|
||||
for(item in table){
|
||||
val it = JSONObject()
|
||||
it.put("id",item.id.toString())
|
||||
it.put("weight",item.weight.toString())
|
||||
it.put("minAmount",item.minAmt.toString())
|
||||
it.put("maxAmount",item.maxAmt.toString())
|
||||
arr.add(it)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
106
src/main/kotlin/FileLoader.kt
Normal file
106
src/main/kotlin/FileLoader.kt
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import org.json.simple.parser.JSONParser
|
||||
import java.io.FileReader
|
||||
import java.lang.Exception
|
||||
import javax.swing.*
|
||||
|
||||
object FileLoader{
|
||||
val loadStatus = JLabel("File not loaded.")
|
||||
val loadButton = JButton("Select drop_tables.json")
|
||||
val chooser = JFileChooser()
|
||||
var dropTableList: TableList? = null
|
||||
|
||||
private fun parseTable(data: JSONArray, destTable: WeightBasedTable, isAlways: Boolean) {
|
||||
for(it in data){
|
||||
val item = it as JSONObject
|
||||
val id = item["id"].toString().toInt()
|
||||
val minAmount = item["minAmount"].toString().toInt()
|
||||
val maxAmount = item["maxAmount"].toString().toInt()
|
||||
val weight = item["weight"].toString().toDouble()
|
||||
val newItem = WeightedItem(id,minAmount.toString(),maxAmount.toString(),weight.toDouble(),isAlways)
|
||||
destTable.add(newItem)
|
||||
}
|
||||
}
|
||||
|
||||
fun load(){
|
||||
Logger.logInfo("Parsing Drop Tables...")
|
||||
var parser = JSONParser()
|
||||
var reader = FileReader(EditorConstants.CONFIG_PATH + "/drop_tables.json")
|
||||
var data = parser.parse(reader) as JSONArray
|
||||
var counter = 0
|
||||
|
||||
data.forEach { dropTableRaw ->
|
||||
val dropTable = dropTableRaw as JSONObject
|
||||
val table = NPCDropTable()
|
||||
table.ids = dropTable["ids"].toString()
|
||||
parseTable(dropTable["main"] as JSONArray,table,false)
|
||||
parseTable(dropTable["default"] as JSONArray,table,true)
|
||||
parseTable(dropTable["charm"] as JSONArray,table,false)
|
||||
table.description = (dropTable["description"] ?: "").toString()
|
||||
TableData.tables.add(table)
|
||||
counter++
|
||||
}
|
||||
Logger.logInfo("Parsed Drop Tables.")
|
||||
Logger.logInfo("Loaded $counter drop tables.")
|
||||
|
||||
Logger.logInfo("Parsing Item Configs...")
|
||||
try {
|
||||
data = parser.parse(FileReader(EditorConstants.CONFIG_PATH + "/item_configs.json")) as JSONArray
|
||||
data.forEach { itemDataRaw ->
|
||||
val itemData = itemDataRaw as JSONObject
|
||||
val id = itemData["id"].toString().toInt()
|
||||
val name = itemData["name"].toString()
|
||||
TableData.itemNames[id] = name
|
||||
}
|
||||
Logger.logInfo("Parsed item configs.")
|
||||
} catch (e: Exception){
|
||||
Logger.logErr("Failed to load item_configs.json. Item names will be unavailable when viewing and editing shops.")
|
||||
}
|
||||
Logger.logInfo("Parsing NPC configs...")
|
||||
try {
|
||||
data = parser.parse(FileReader(EditorConstants.CONFIG_PATH + "/npc_configs.json")) as JSONArray
|
||||
data.forEach { npcDataRaw ->
|
||||
val npcData = npcDataRaw as JSONObject
|
||||
val id = npcData["id"].toString().toInt()
|
||||
val name = npcData["name"].toString()
|
||||
TableData.npcNames[id] = name
|
||||
}
|
||||
Logger.logInfo("Parsed NPC configs")
|
||||
} catch (e: Exception){
|
||||
Logger.logErr("Failed to load npc_configs.json. Drop tables will lack proper naming. Good luck figuring out what you want to edit.")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class Item(var id: Int,var amount: String,var infinite: Boolean)
|
||||
class WeightedItem(var id: Int, var minAmt: String, var maxAmt: String, var weight: Double, var isAlways: Boolean)
|
||||
|
||||
private val CHARMS = intArrayOf(12160,12163,12159,12158)
|
||||
|
||||
open class WeightBasedTable() : ArrayList<WeightedItem>(){
|
||||
var totalWeight: Double = 0.0
|
||||
override fun add(element: WeightedItem): Boolean {
|
||||
totalWeight += element.weight
|
||||
return super.add(element)
|
||||
}
|
||||
}
|
||||
|
||||
class NPCDropTable() : WeightBasedTable(){
|
||||
val charmTable = WeightBasedTable()
|
||||
val alwaysTable = WeightBasedTable()
|
||||
var ids = ""
|
||||
var description = ""
|
||||
override fun add(element: WeightedItem): Boolean {
|
||||
if(element.isAlways){
|
||||
alwaysTable.add(element)
|
||||
return true
|
||||
}
|
||||
if(CHARMS.contains(element.id)){
|
||||
charmTable.add(element)
|
||||
return true
|
||||
}
|
||||
return super.add(element)
|
||||
}
|
||||
}
|
||||
57
src/main/kotlin/Globals.kt
Normal file
57
src/main/kotlin/Globals.kt
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import javax.swing.*
|
||||
|
||||
val confirmation = object : JFrame("Notice"){
|
||||
init {
|
||||
layout = BorderLayout()
|
||||
minimumSize = Dimension(250,100)
|
||||
defaultCloseOperation = HIDE_ON_CLOSE
|
||||
val okButton = JButton("OK")
|
||||
okButton.addActionListener {
|
||||
isVisible = false
|
||||
}
|
||||
add(JLabel("Added a new row to the table."), BorderLayout.NORTH)
|
||||
add(okButton, BorderLayout.SOUTH)
|
||||
setLocationRelativeTo(null)
|
||||
isVisible = false
|
||||
pack()
|
||||
}
|
||||
}
|
||||
val saveConfirmation = object : JFrame("Notice"){
|
||||
init {
|
||||
minimumSize = Dimension(250,100)
|
||||
defaultCloseOperation = HIDE_ON_CLOSE
|
||||
layout = BorderLayout()
|
||||
val okButton = JButton("OK")
|
||||
okButton.addActionListener {
|
||||
isVisible = false
|
||||
}
|
||||
add(JLabel("Data saved."), BorderLayout.NORTH)
|
||||
add(okButton, BorderLayout.SOUTH)
|
||||
isVisible = false
|
||||
setLocationRelativeTo(null)
|
||||
pack()
|
||||
}
|
||||
}
|
||||
|
||||
val credits = object : JFrame("Credits"){
|
||||
init {
|
||||
defaultCloseOperation = HIDE_ON_CLOSE
|
||||
val creditPanel = JPanel()
|
||||
creditPanel.layout = BoxLayout(creditPanel, BoxLayout.PAGE_AXIS)
|
||||
layout = BorderLayout()
|
||||
|
||||
for(credit in EditorConstants.CREDITS){
|
||||
creditPanel.add(JLabel(credit))
|
||||
}
|
||||
|
||||
add(creditPanel)
|
||||
|
||||
isVisible = false
|
||||
|
||||
setLocationRelativeTo(null)
|
||||
|
||||
pack()
|
||||
}
|
||||
}
|
||||
100
src/main/kotlin/ItemMenu.kt
Normal file
100
src/main/kotlin/ItemMenu.kt
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
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 ItemMenu : JFrame("Item Selection Menu") {
|
||||
var model = DefaultTableModel()
|
||||
var searchField = JTextField()
|
||||
var amountField = 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, 1)
|
||||
} catch (e: PatternSyntaxException) {
|
||||
return
|
||||
}
|
||||
sorter.rowFilter = rf
|
||||
}
|
||||
|
||||
fun open() {
|
||||
if (!populated) {
|
||||
SwingUtilities.invokeLater {
|
||||
for ((id,_) in TableData.itemNames) {
|
||||
model.addRow(arrayOf(id,TableData.getItemName(id)))
|
||||
}
|
||||
isVisible = true
|
||||
populated = true
|
||||
}
|
||||
} else {
|
||||
isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
layout = BorderLayout()
|
||||
cellRenderer.toolTipText = "Double-Click to select."
|
||||
val searchPanel = JPanel()
|
||||
val searchLabel = JLabel("Search for Item:")
|
||||
val amountLabel = JLabel("Amount: ")
|
||||
amountField.preferredSize = Dimension(45, 20)
|
||||
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
|
||||
}
|
||||
}
|
||||
21
src/main/kotlin/Logger.kt
Normal file
21
src/main/kotlin/Logger.kt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import com.github.ajalt.mordant.rendering.TextColors
|
||||
import com.github.ajalt.mordant.terminal.Terminal
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
object Logger {
|
||||
val t = Terminal()
|
||||
val formatter = SimpleDateFormat("HH:mm:ss")
|
||||
|
||||
fun logInfo(message: String){
|
||||
t.println("${getTime()} ${TextColors.white("[INFO] $message")}")
|
||||
}
|
||||
|
||||
fun logErr(message: String){
|
||||
t.println("${getTime()} ${TextColors.red("[ ERR] $message")}")
|
||||
}
|
||||
|
||||
fun getTime(): String{
|
||||
return "[" + formatter.format(Date(System.currentTimeMillis())) +"]"
|
||||
}
|
||||
}
|
||||
143
src/main/kotlin/MainScreen.kt
Normal file
143
src/main/kotlin/MainScreen.kt
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
import com.github.weisj.darklaf.LafManager
|
||||
import com.github.weisj.darklaf.theme.DarculaTheme
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.FlowLayout
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import javax.swing.*
|
||||
import javax.swing.table.DefaultTableModel
|
||||
|
||||
object MainScreen : JFrame("RS09 Thanos Tool") {
|
||||
val dirChooser = object : JFileChooser(){
|
||||
override fun updateUI() {
|
||||
EditorConstants.updateTheme()
|
||||
super.updateUI()
|
||||
}
|
||||
}
|
||||
val selectDir = JButton("Select Config Folder")
|
||||
val openDrops = JButton("Edit Drop Tables")
|
||||
val openNPC = JButton("Edit NPC Configs")
|
||||
val openItem = JButton("Edit Item Configs")
|
||||
val openShops = JButton("Edit Shops")
|
||||
val openObjects = JButton("Edit Object Configs")
|
||||
var loadedModel = object : DefaultTableModel(){}
|
||||
val loadedTable = object : JTable(loadedModel){
|
||||
override fun editCellAt(p0: Int, p1: Int): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun editCellAt(p0: Int, p1: Int, p2: EventObject?): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
val pane = JScrollPane(loadedTable)
|
||||
|
||||
init {
|
||||
isResizable = false
|
||||
layout = BorderLayout()
|
||||
dirChooser.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
|
||||
defaultCloseOperation = EXIT_ON_CLOSE
|
||||
preferredSize = Dimension(550,300)
|
||||
loadedModel.addColumn("Filename")
|
||||
|
||||
iconImage = ImageIcon(javaClass.getResource("/thanos.png")).image
|
||||
|
||||
|
||||
selectDir.addActionListener {
|
||||
val response = dirChooser.showOpenDialog(null)
|
||||
EditorConstants.updateTheme()
|
||||
if(response == JFileChooser.APPROVE_OPTION){
|
||||
Logger.logInfo("Selected directory: ${dirChooser.selectedFile.absolutePath}")
|
||||
EditorConstants.CONFIG_PATH = dirChooser.selectedFile.absolutePath
|
||||
showLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
openDrops.addActionListener {
|
||||
FileLoader.dropTableList = TableList()
|
||||
FileLoader.dropTableList!!.open()
|
||||
}
|
||||
|
||||
openItem.addActionListener {
|
||||
TableEditor(Editors.ITEM_CONFIGS).open()
|
||||
}
|
||||
|
||||
openNPC.addActionListener {
|
||||
TableEditor(Editors.NPC_CONFIGS).open()
|
||||
}
|
||||
|
||||
openObjects.addActionListener {
|
||||
TableEditor(Editors.OBJECT_CONFIGS).open()
|
||||
}
|
||||
|
||||
openShops.addActionListener {
|
||||
ShopList().open()
|
||||
}
|
||||
|
||||
val showCredits = JButton("Show Credits")
|
||||
showCredits.addActionListener {
|
||||
credits.isVisible = true
|
||||
}
|
||||
|
||||
val editorPanel = JPanel()
|
||||
val selectionPanel = JPanel()
|
||||
|
||||
editorPanel.layout = BoxLayout(editorPanel, BoxLayout.Y_AXIS)//BoxLayout(editorPanel, BoxLayout.PAGE_AXIS)
|
||||
for(i in arrayOf(openDrops, openNPC, openItem, openObjects, openShops, showCredits)){
|
||||
i.preferredSize = Dimension(175,40)
|
||||
i.maximumSize = Dimension(175,40)
|
||||
i.isEnabled = i == showCredits
|
||||
editorPanel.add(i)
|
||||
}
|
||||
|
||||
add(editorPanel, BorderLayout.WEST)
|
||||
|
||||
val buttonPane = JPanel()
|
||||
buttonPane.layout = BorderLayout()
|
||||
selectDir.preferredSize = Dimension(300,40)
|
||||
selectDir.maximumSize = Dimension(300,40)
|
||||
buttonPane.add(selectDir, BorderLayout.CENTER)
|
||||
|
||||
selectionPanel.layout = BoxLayout(selectionPanel, BoxLayout.Y_AXIS)
|
||||
selectionPanel.add(buttonPane)
|
||||
|
||||
pane.preferredSize = Dimension(225,200)
|
||||
selectionPanel.add(pane)
|
||||
|
||||
add(JSeparator(SwingConstants.VERTICAL), BorderLayout.CENTER)
|
||||
|
||||
setLocationRelativeTo(null)
|
||||
add(selectionPanel, BorderLayout.EAST)
|
||||
EditorConstants.updateTheme()
|
||||
pack()
|
||||
}
|
||||
}
|
||||
|
||||
fun showLoaded(){
|
||||
MainScreen.loadedModel = object : DefaultTableModel(){}
|
||||
MainScreen.loadedModel.addColumn("Filename")
|
||||
MainScreen.loadedTable.model = MainScreen.loadedModel
|
||||
|
||||
val files = File(EditorConstants.CONFIG_PATH).listFiles() ?: return
|
||||
|
||||
for(file in files){
|
||||
if(file.name in EditorConstants.VALID_FILES){
|
||||
MainScreen.loadedModel.addRow(arrayOf(file.name))
|
||||
when(file.nameWithoutExtension){
|
||||
"drop_tables" -> MainScreen.openDrops.isEnabled = true.also { Editors.DROP_TABLES.data.parse() }
|
||||
"npc_configs" -> MainScreen.openNPC.isEnabled = true.also { Editors.NPC_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() }
|
||||
"object_configs" -> MainScreen.openObjects.isEnabled = true.also { Editors.OBJECT_CONFIGS.data.parse()}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainScreen.pane.revalidate()
|
||||
MainScreen.pane.repaint()
|
||||
}
|
||||
|
||||
fun main() {
|
||||
MainScreen.isVisible = true
|
||||
}
|
||||
170
src/main/kotlin/ShopEdit.kt
Normal file
170
src/main/kotlin/ShopEdit.kt
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.event.*
|
||||
import java.util.*
|
||||
import javax.swing.*
|
||||
import javax.swing.event.ChangeEvent
|
||||
import javax.swing.table.DefaultTableModel
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ShopEdit(val shopID: Int) : JFrame("Edit Shop") {
|
||||
val shop = TableData.shops[shopID]
|
||||
val idField = JTextField()
|
||||
val titleField = JTextField()
|
||||
val currencyField = JTextField()
|
||||
val generalCheckbox = JCheckBox("General Store")
|
||||
val highAlchCheckbox = JCheckBox("High Alch Prices")
|
||||
var model = DefaultTableModel()
|
||||
|
||||
|
||||
init {
|
||||
layout = BorderLayout()
|
||||
val topPanel = JPanel()
|
||||
val idLabel = JLabel("ID: ")
|
||||
idField.preferredSize = Dimension(40, 20)
|
||||
idField.text = shopID.toString()
|
||||
idField.addKeyListener(object : KeyListener{
|
||||
override fun keyTyped(e: KeyEvent?) {}
|
||||
override fun keyPressed(e: KeyEvent?) {}
|
||||
override fun keyReleased(e: KeyEvent?) {
|
||||
shop?.id = idField.text.toInt()
|
||||
}
|
||||
})
|
||||
topPanel.add(idLabel)
|
||||
topPanel.add(idField)
|
||||
|
||||
val currencyLabel = JLabel("Currency: ")
|
||||
currencyField.preferredSize = Dimension(50,20)
|
||||
currencyField.text = shop?.currency.toString()
|
||||
currencyField.addKeyListener(object : KeyListener{
|
||||
override fun keyTyped(e: KeyEvent?) {}
|
||||
override fun keyPressed(e: KeyEvent?) {}
|
||||
override fun keyReleased(e: KeyEvent?) {
|
||||
shop?.currency = currencyField.text.toInt()
|
||||
}
|
||||
})
|
||||
topPanel.add(currencyLabel)
|
||||
topPanel.add(currencyField)
|
||||
|
||||
val titleLabel = JLabel("Title: ")
|
||||
titleField.preferredSize = Dimension(300,20)
|
||||
titleField.text = shop?.title
|
||||
titleField.addKeyListener(object : KeyListener{
|
||||
override fun keyTyped(e: KeyEvent?) {}
|
||||
override fun keyPressed(e: KeyEvent?) {}
|
||||
override fun keyReleased(e: KeyEvent?) {
|
||||
shop?.title = titleField.text
|
||||
}
|
||||
})
|
||||
topPanel.add(titleLabel)
|
||||
topPanel.add(titleField)
|
||||
|
||||
add(topPanel,BorderLayout.NORTH)
|
||||
|
||||
val checkPanel = JPanel()
|
||||
val npcLabel = JLabel("NPCs: ")
|
||||
val npcField = JTextField()
|
||||
npcField.addKeyListener(object : KeyListener{
|
||||
override fun keyTyped(e: KeyEvent?) {
|
||||
shop?.npcs = npcField.text + e?.keyChar
|
||||
}
|
||||
override fun keyPressed(e: KeyEvent?) {}
|
||||
override fun keyReleased(e: KeyEvent?) {}
|
||||
})
|
||||
npcField.preferredSize = Dimension(50,20)
|
||||
npcField.text = shop?.npcs
|
||||
checkPanel.add(npcLabel)
|
||||
checkPanel.add(npcField)
|
||||
generalCheckbox.isSelected = shop?.general_store ?: false
|
||||
generalCheckbox.addChangeListener {
|
||||
shop!!.general_store = !shop.general_store
|
||||
}
|
||||
checkPanel.add(generalCheckbox)
|
||||
highAlchCheckbox.isBorderPaintedFlat = shop?.high_alch ?: false
|
||||
highAlchCheckbox.isSelected = shop?.high_alch ?: false
|
||||
highAlchCheckbox.addChangeListener {
|
||||
shop!!.high_alch = !shop.high_alch
|
||||
}
|
||||
checkPanel.add(highAlchCheckbox)
|
||||
|
||||
val addButton = JButton("Add Item")
|
||||
addButton.addActionListener {
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.addRow(arrayOf(name,id,0,false))
|
||||
shop!!.stock.add(Item(id,"0",false))
|
||||
}
|
||||
ItemMenu.open()
|
||||
}
|
||||
checkPanel.add(addButton)
|
||||
add(checkPanel,BorderLayout.CENTER)
|
||||
|
||||
val itemTable: JTable = object : JTable(model) {
|
||||
override fun editCellAt(row: Int, column: Int): Boolean {
|
||||
if(column == 0 || column == 1){
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.setValueAt(name,row,0)
|
||||
model.setValueAt(id,row,1)
|
||||
shop!!.stock[row].id = id
|
||||
}
|
||||
ItemMenu.open()
|
||||
return false
|
||||
}
|
||||
return super.editCellAt(row, column)
|
||||
}
|
||||
|
||||
override fun editCellAt(row: Int, column: Int, e: EventObject?): Boolean {
|
||||
if(column == 0 || column == 1){
|
||||
ItemMenu.caller = {id,name ->
|
||||
model.setValueAt(name,row,0)
|
||||
model.setValueAt(id,row,1)
|
||||
shop!!.stock[row].id = id
|
||||
}
|
||||
ItemMenu.open()
|
||||
return false
|
||||
}
|
||||
return super.editCellAt(row, column, e)
|
||||
}
|
||||
override fun editingStopped(e: ChangeEvent?) {
|
||||
val editor = cellEditor
|
||||
val newValue = editor.cellEditorValue.toString()
|
||||
when(editingColumn){
|
||||
1 -> TableData.shops[shopID]!!.stock[editingRow].id = newValue.toInt()
|
||||
2 -> TableData.shops[shopID]!!.stock[editingRow].amount = newValue
|
||||
3 -> TableData.shops[shopID]!!.stock[editingRow].infinite = newValue.toBoolean()
|
||||
}
|
||||
super.editingStopped(e)
|
||||
}
|
||||
}
|
||||
itemTable.putClientProperty("terminateEditOnFocusLost", true);
|
||||
|
||||
itemTable.inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete")
|
||||
itemTable.actionMap.put("delete",object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
try {
|
||||
shop!!.stock.removeAt(itemTable.selectedRow)
|
||||
model.removeRow(itemTable.selectedRow)
|
||||
} catch(e: Exception){
|
||||
Logger.logErr("Tried to remove nonexistent row ${itemTable.selectedRow}")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
model.addColumn("Name")
|
||||
model.addColumn("ID")
|
||||
model.addColumn("Amount")
|
||||
model.addColumn("Infinite?")
|
||||
|
||||
val scrollPane = JScrollPane(itemTable)
|
||||
add(scrollPane,BorderLayout.SOUTH)
|
||||
|
||||
pack()
|
||||
isVisible = false
|
||||
}
|
||||
|
||||
fun open(){
|
||||
for(item in shop?.stock ?: ArrayList()){
|
||||
model.addRow(arrayOf(TableData.itemNames[item.id] ?: "unknown",item.id,item.amount,item.infinite))
|
||||
}
|
||||
isVisible = true
|
||||
}
|
||||
}
|
||||
131
src/main/kotlin/ShopList.kt
Normal file
131
src/main/kotlin/ShopList.kt
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.event.*
|
||||
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
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ShopList : JFrame("RS09 Shop Editor") {
|
||||
val searchField = JTextField()
|
||||
var model = DefaultTableModel()
|
||||
var sorter = TableRowSorter(model)
|
||||
var cellRenderer = DefaultTableCellRenderer()
|
||||
var populated = false
|
||||
|
||||
init {
|
||||
isVisible = false
|
||||
layout = BorderLayout()
|
||||
|
||||
val searchPanel = JPanel()
|
||||
val searchLabel = JLabel("Search for shop: ")
|
||||
val addButton = JButton("Add Shop")
|
||||
val saveButton = JButton("Save Shops")
|
||||
addButton.addActionListener {
|
||||
val highestID = TableData.shops.keys.toIntArray()[TableData.shops.size - 1]
|
||||
TableData.shops.put(highestID + 1, TableData.Shop(highestID + 1,"", ArrayList(),"",995,false,false))
|
||||
ShopEdit(highestID + 1).open()
|
||||
}
|
||||
saveButton.addActionListener {
|
||||
Editors.SHOPS.data.save()
|
||||
saveConfirmation.isVisible = true
|
||||
}
|
||||
searchField.preferredSize = Dimension(100, 20)
|
||||
searchPanel.add(searchLabel)
|
||||
searchPanel.add(searchField)
|
||||
searchPanel.add(addButton)
|
||||
searchPanel.add(saveButton)
|
||||
add(searchPanel, BorderLayout.NORTH)
|
||||
setLocationRelativeTo(null)
|
||||
|
||||
val itemTable: JTable = object : JTable(model) {
|
||||
override fun editCellAt(i: Int, i1: Int, eventObject: EventObject): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
itemTable.inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete")
|
||||
itemTable.actionMap.put("delete",object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
try {
|
||||
val table = e?.source as JTable
|
||||
TableData.shops.remove(table.getValueAt(table.selectedRow,0))
|
||||
model.removeRow(table.convertRowIndexToModel(table.selectedRow))
|
||||
} catch(e: Exception){
|
||||
Logger.logErr("Tried to remove nonexistent row ${itemTable.selectedRow}")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
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
|
||||
ShopEdit(table.getValueAt(row,0) as Int).open()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
private fun filter() {
|
||||
var rf: RowFilter<DefaultTableModel?, Any?>? = null
|
||||
//If current expression doesn't parse, don't update.
|
||||
rf = try {
|
||||
RowFilter.regexFilter(searchField.text, 1)
|
||||
} catch (e: PatternSyntaxException) {
|
||||
return
|
||||
}
|
||||
sorter.rowFilter = rf
|
||||
}
|
||||
|
||||
fun open() {
|
||||
if (!populated) {
|
||||
Logger.logInfo("Loading shops data...")
|
||||
for(i in 0 until model.rowCount){
|
||||
model.removeRow(0)
|
||||
}
|
||||
SwingUtilities.invokeLater {
|
||||
for ((id,shop) in TableData.shops) {
|
||||
model.addRow(arrayOf<Any>(id, shop.title))
|
||||
}
|
||||
isVisible = true
|
||||
populated = true
|
||||
}
|
||||
} else {
|
||||
isVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/main/kotlin/TableData.kt
Normal file
33
src/main/kotlin/TableData.kt
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.lang.StringBuilder
|
||||
import javax.script.ScriptEngineManager
|
||||
|
||||
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)
|
||||
val tables = ArrayList<NPCDropTable>()
|
||||
val itemNames = hashMapOf<Int,String>()
|
||||
val npcNames = hashMapOf<Int,String>()
|
||||
val npcConfigKeys = HashSet<String>()
|
||||
val npcConfigs = ArrayList<JSONObject>()
|
||||
val objConfigKeys = HashSet<String>()
|
||||
val objConfigs = ArrayList<JSONObject>()
|
||||
var itemConfigKeys = HashSet<String>()
|
||||
var itemConfigs = ArrayList<JSONObject>()
|
||||
val shops = hashMapOf<Int,Shop>()
|
||||
|
||||
fun getItemName(id: Int): String{
|
||||
return when(id){
|
||||
31 -> "RDT Slot"
|
||||
1 -> "Clue Scroll (easy)"
|
||||
5733 -> "Clue Scroll (med)"
|
||||
12070 -> "Clue Scroll (hard)"
|
||||
0 -> "Nothing"
|
||||
else -> itemNames[id] ?: "Unknown"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
152
src/main/kotlin/TableEditor.kt
Normal file
152
src/main/kotlin/TableEditor.kt
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.FlowLayout
|
||||
import java.awt.event.ActionEvent
|
||||
import java.awt.event.KeyEvent
|
||||
import java.awt.event.KeyListener
|
||||
import java.util.regex.PatternSyntaxException
|
||||
import javax.swing.*
|
||||
import javax.swing.event.TableModelEvent
|
||||
import javax.swing.event.TableModelListener
|
||||
import javax.swing.table.DefaultTableModel
|
||||
import javax.swing.table.TableRowSorter
|
||||
|
||||
/**
|
||||
* Represents a generic JTable-based editor. Pretty much just a cleaner visualisation of JSON objects with editing functionality.
|
||||
*/
|
||||
class TableEditor(val editor: Editors) : JFrame("Editing ${editor.name.replace("_"," ").toLowerCase()}") {
|
||||
val searchField = JTextField()
|
||||
val model = DefaultTableModel()
|
||||
var table = JTable(model)
|
||||
val sorter = TableRowSorter(model)
|
||||
|
||||
init {
|
||||
layout = BorderLayout()
|
||||
isVisible = false
|
||||
table.autoResizeMode = JTable.AUTO_RESIZE_OFF
|
||||
searchField.preferredSize = Dimension(200,20)
|
||||
searchField.maximumSize = Dimension(200,20)
|
||||
minimumSize = Dimension(1000, 650)
|
||||
|
||||
searchField.addKeyListener(object : KeyListener{
|
||||
override fun keyTyped(p0: KeyEvent?) { filter() }
|
||||
override fun keyPressed(p0: KeyEvent?) {}
|
||||
override fun keyReleased(p0: KeyEvent?) {}
|
||||
})
|
||||
|
||||
table.rowSorter = sorter
|
||||
|
||||
|
||||
val addButton = JButton("Add Row")
|
||||
val saveButton = JButton("Save Data")
|
||||
|
||||
addButton.addActionListener {
|
||||
getData().add(JSONObject())
|
||||
model.addRow(arrayOf())
|
||||
confirmation.isVisible = true
|
||||
}
|
||||
|
||||
saveButton.addActionListener {
|
||||
editor.data.save()
|
||||
saveConfirmation.isVisible = true
|
||||
}
|
||||
|
||||
val searchPanel = JPanel()
|
||||
searchPanel.layout = FlowLayout()
|
||||
searchPanel.add(JLabel("Search by Name "))
|
||||
searchPanel.add(searchField)
|
||||
searchPanel.add(addButton)
|
||||
searchPanel.add(saveButton)
|
||||
|
||||
val pane = JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS)
|
||||
add(pane, BorderLayout.CENTER)
|
||||
add(searchPanel, BorderLayout.NORTH)
|
||||
|
||||
val keys = when (editor) {
|
||||
Editors.NPC_CONFIGS -> TableData.npcConfigKeys
|
||||
Editors.ITEM_CONFIGS -> TableData.itemConfigKeys
|
||||
Editors.OBJECT_CONFIGS -> TableData.objConfigKeys
|
||||
else -> ArrayList<JSONObject>()
|
||||
}
|
||||
|
||||
if(editor == Editors.OBJECT_CONFIGS){
|
||||
model.addColumn("ids")
|
||||
model.addColumn("examine")
|
||||
keys.remove("ids")
|
||||
keys.remove("examine")
|
||||
table.columnModel.getColumn(0).preferredWidth = 400
|
||||
table.columnModel.getColumn(1).preferredWidth = 600
|
||||
} else {
|
||||
model.addColumn("id")
|
||||
model.addColumn("name")
|
||||
keys.remove("id")
|
||||
keys.remove("name")
|
||||
}
|
||||
|
||||
keys.sortedBy { it.toString() }.forEach { model.addColumn(it) }
|
||||
if(editor != Editors.OBJECT_CONFIGS) {
|
||||
table.columnModel.getColumn(1).preferredWidth = 150
|
||||
}
|
||||
|
||||
model.addTableModelListener(object : TableModelListener{
|
||||
override fun tableChanged(event: TableModelEvent?) {
|
||||
event ?: return
|
||||
if(event.type != TableModelEvent.UPDATE) return
|
||||
val label = model.getColumnName(event.column)
|
||||
getData()[event.firstRow][label] = model.getValueAt(event.firstRow, event.column)
|
||||
Logger.logInfo("Changed ${getData()[event.firstRow]["name"]}'s $label to ${model.getValueAt(event.firstRow,event.column)}")
|
||||
}
|
||||
})
|
||||
|
||||
table.actionMap.put("delete",object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
try {
|
||||
val table = e?.source as JTable
|
||||
getData().removeAt(table.convertRowIndexToModel(table.selectedRow))
|
||||
model.removeRow(table.convertRowIndexToModel(table.selectedRow))
|
||||
} catch(e: Exception){
|
||||
Logger.logErr("Tried to remove nonexistent row ${table.selectedRow}")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
EditorConstants.updateTheme()
|
||||
pack()
|
||||
}
|
||||
|
||||
fun open(){
|
||||
val data = getData()
|
||||
|
||||
for(datum in data){
|
||||
val vals = JSONArray()
|
||||
for(i in 0 until model.columnCount){
|
||||
val label = model.getColumnName(i)
|
||||
vals.add(datum[label] ?: "")
|
||||
}
|
||||
model.addRow(vals.toArray())
|
||||
}
|
||||
isVisible = true
|
||||
}
|
||||
|
||||
private fun filter() {
|
||||
var rf: RowFilter<DefaultTableModel?, Any?>? = null
|
||||
//If current expression doesn't parse, don't update.
|
||||
rf = try {
|
||||
RowFilter.regexFilter(searchField.text)
|
||||
} catch (e: PatternSyntaxException) {
|
||||
return
|
||||
}
|
||||
sorter.rowFilter = rf
|
||||
}
|
||||
|
||||
fun getData(): ArrayList<JSONObject> {
|
||||
return when(editor){
|
||||
Editors.ITEM_CONFIGS -> TableData.itemConfigs
|
||||
Editors.NPC_CONFIGS -> TableData.npcConfigs
|
||||
Editors.OBJECT_CONFIGS -> TableData.objConfigs
|
||||
else -> ArrayList()
|
||||
}
|
||||
}
|
||||
}
|
||||
126
src/main/kotlin/TableList.kt
Normal file
126
src/main/kotlin/TableList.kt
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.event.*
|
||||
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
|
||||
|
||||
class TableList : JFrame("RS09 Drop Table Editor") {
|
||||
val searchField = JTextField()
|
||||
var model = DefaultTableModel()
|
||||
var sorter = TableRowSorter(model)
|
||||
var cellRenderer = DefaultTableCellRenderer()
|
||||
var populated = false
|
||||
|
||||
init {
|
||||
isVisible = false
|
||||
layout = BorderLayout()
|
||||
|
||||
val searchPanel = JPanel()
|
||||
val searchLabel = JLabel("Search for table: ")
|
||||
val addButton = JButton("Add Table")
|
||||
val saveButton = JButton("Save Tables")
|
||||
addButton.addActionListener {
|
||||
TableData.tables.add(NPCDropTable())
|
||||
DropTableEditor(TableData.tables.last()).open()
|
||||
}
|
||||
saveButton.addActionListener {
|
||||
Editors.DROP_TABLES.data.save()
|
||||
saveConfirmation.isVisible = true
|
||||
}
|
||||
searchField.preferredSize = Dimension(100, 20)
|
||||
searchPanel.add(searchLabel)
|
||||
searchPanel.add(searchField)
|
||||
searchPanel.add(addButton)
|
||||
searchPanel.add(saveButton)
|
||||
add(searchPanel, BorderLayout.NORTH)
|
||||
setLocationRelativeTo(null)
|
||||
|
||||
val itemTable: JTable = object : JTable(model) {
|
||||
override fun editCellAt(i: Int, i1: Int, eventObject: EventObject): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
itemTable.inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete")
|
||||
itemTable.actionMap.put("delete",object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
try {
|
||||
val table = e?.source as JTable
|
||||
TableData.tables.removeAt(table.convertRowIndexToModel(table.selectedRow))
|
||||
model.removeRow(table.convertRowIndexToModel(table.selectedRow))
|
||||
} catch(e: Exception){
|
||||
Logger.logErr("Tried to remove nonexistent row ${itemTable.selectedRow}")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
model.addColumn("Name")
|
||||
|
||||
itemTable.rowSorter = sorter
|
||||
itemTable.columnModel.getColumn(0).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
|
||||
DropTableEditor(TableData.tables[table.convertRowIndexToModel(row)]).open()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
private fun filter() {
|
||||
var rf: RowFilter<DefaultTableModel?, Any?>? = null
|
||||
//If current expression doesn't parse, don't update.
|
||||
rf = try {
|
||||
RowFilter.regexFilter(searchField.text, 0)
|
||||
} catch (e: PatternSyntaxException) {
|
||||
return
|
||||
}
|
||||
sorter.rowFilter = rf
|
||||
}
|
||||
|
||||
fun open() {
|
||||
if (!populated) {
|
||||
Logger.logInfo("Loading table data...")
|
||||
for(i in 0 until model.rowCount){
|
||||
model.removeRow(0)
|
||||
}
|
||||
SwingUtilities.invokeLater {
|
||||
for (table in TableData.tables) {
|
||||
model.addRow(arrayOf<Any>(if(table.ids.isNotBlank()) TableData.npcNames[table.ids.split(",")[0].toInt()] ?: "Unknown Table" else "None"))
|
||||
}
|
||||
isVisible = true
|
||||
populated = true
|
||||
}
|
||||
} else {
|
||||
isVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
src/main/resources/thanos.png
Normal file
BIN
src/main/resources/thanos.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
Loading…
Add table
Add a link
Reference in a new issue