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