Merge branch 'server-gui' into 'master'
Server Performance Monitor, Plethora of Performance Improvements See merge request 2009scape/2009scape!349
This commit is contained in:
@@ -74,4 +74,5 @@
|
||||
- Fix granting hp xp on controlled
|
||||
- Implemented HCIM Rework
|
||||
< --- ABOVE Released December 15, 2021 https://gitlab.com/2009scape/2009scape/-/tags/Dec-15-2021 ---- >
|
||||
- Implemented server performance monitor, many performance improvements
|
||||
- Fishing and fishing trawler now use closer-to-empirical formulae.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package core.game.system;
|
||||
|
||||
import core.game.system.security.EncryptionManager;
|
||||
import gui.ServerMonitor;
|
||||
import rs09.game.world.GameWorld;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
package gui
|
||||
|
||||
import java.awt.*
|
||||
import javax.swing.JPanel
|
||||
|
||||
|
||||
/**
|
||||
* @author Rodrigo, Maritaria
|
||||
* @author Ceikry (rewrote into Kotlin, adapted for specific use case)
|
||||
*/
|
||||
class GraphView() : JPanel() {
|
||||
private val values: MutableList<Int> = ArrayList(10)
|
||||
fun setValues(newValues: Collection<Int>) {
|
||||
values.clear()
|
||||
addValues(newValues)
|
||||
}
|
||||
|
||||
fun addValues(newValues: Collection<Int>) {
|
||||
if(values.size > 200) values.removeFirst()
|
||||
values.addAll(newValues)
|
||||
updateUI()
|
||||
}
|
||||
|
||||
override fun paintComponent(graphics: Graphics) {
|
||||
super.paintComponent(graphics)
|
||||
if (graphics !is Graphics2D) {
|
||||
graphics.drawString("Graphics is not Graphics2D, unable to render", 0, 0)
|
||||
return
|
||||
}
|
||||
val g: Graphics2D = graphics
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
|
||||
val length: Int = values.size
|
||||
val width: Int = width
|
||||
val height: Int = height
|
||||
val maxScore: Double = maxScore
|
||||
val minScore: Double = minScore
|
||||
val scoreRange: Double = maxScore - minScore
|
||||
|
||||
// draw white background
|
||||
g.color = Color.WHITE
|
||||
g.fillRect(
|
||||
padding + labelPadding,
|
||||
padding,
|
||||
width - (2 * padding) - labelPadding,
|
||||
height - (2 * padding) - labelPadding
|
||||
)
|
||||
g.color = Color.BLACK
|
||||
val fontMetrics: FontMetrics = g.fontMetrics
|
||||
val fontHeight: Int = fontMetrics.height
|
||||
|
||||
// create hatch marks and grid lines for y axis.
|
||||
for (i in 0 until numberYDivisions + 1) {
|
||||
val x1: Int = padding + labelPadding
|
||||
val x2: Int = pointWidth + padding + labelPadding
|
||||
val y: Int =
|
||||
height - (((i * (height - (padding * 2) - labelPadding)) / numberYDivisions) + padding + labelPadding)
|
||||
if (length > 0) {
|
||||
g.color = gridColor
|
||||
g.drawLine(padding + labelPadding + 1 + pointWidth, y, width - padding, y)
|
||||
g.color = Color.BLACK
|
||||
val tickValue: Int = (minScore + ((scoreRange * i) / numberYDivisions)).toInt()
|
||||
val yLabel: String = tickValue.toString() + ""
|
||||
val labelWidth: Int = fontMetrics.stringWidth(yLabel)
|
||||
g.drawString(yLabel, x1 - labelWidth - 5, y + (fontHeight / 2) - 3)
|
||||
}
|
||||
g.drawLine(x1, y, x2, y)
|
||||
}
|
||||
|
||||
// create x and y axes
|
||||
g.drawLine(padding + labelPadding, height - padding - labelPadding, padding + labelPadding, padding)
|
||||
g.drawLine(
|
||||
padding + labelPadding,
|
||||
height - padding - labelPadding,
|
||||
width - padding,
|
||||
height - padding - labelPadding
|
||||
)
|
||||
val oldStroke: Stroke = g.stroke
|
||||
g.color = lineColor
|
||||
g.stroke = graphStroke
|
||||
val xScale: Double = (width.toDouble() - (2 * padding) - labelPadding) / (length - 1)
|
||||
val yScale: Double = (height.toDouble() - (2 * padding) - labelPadding) / scoreRange
|
||||
val graphPoints: MutableList<Point> = ArrayList(length)
|
||||
for (i in 0 until length) {
|
||||
val x1: Int = ((i * xScale) + padding + labelPadding).toInt()
|
||||
val y1: Int = ((maxScore - values.get(i)) * yScale + padding).toInt()
|
||||
graphPoints.add(Point(x1, y1))
|
||||
}
|
||||
for (i in 0 until graphPoints.size - 1) {
|
||||
val x1: Int = graphPoints[i].x
|
||||
val y1: Int = graphPoints[i].y
|
||||
val x2: Int = graphPoints[i + 1].x
|
||||
val y2: Int = graphPoints[i + 1].y
|
||||
if(y2 != 0) {
|
||||
g.drawLine(x1, y1, x2, y2)
|
||||
}
|
||||
}
|
||||
val drawDots: Boolean = width > (length * pointWidth)
|
||||
if (drawDots) {
|
||||
g.stroke = oldStroke
|
||||
g.color = pointColor
|
||||
for (graphPoint: Point in graphPoints) {
|
||||
val x: Int = graphPoint.x - pointWidth / 2
|
||||
val y: Int = graphPoint.y - pointWidth / 2
|
||||
g.fillOval(x, y, pointWidth, pointWidth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val minScore: Double
|
||||
get() = values.stream().min { obj: Int, integer: Int? -> obj.compareTo((integer)!!) }.orElse(0)
|
||||
.toDouble()
|
||||
private val maxScore: Double
|
||||
get() {
|
||||
return values.stream().max { obj: Int, integer: Int? -> obj.compareTo((integer)!!) }.orElse(0)
|
||||
.toDouble()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val padding: Int = 25
|
||||
private const val labelPadding: Int = 25
|
||||
private const val pointWidth: Int = 4
|
||||
private const val numberYDivisions: Int = 10
|
||||
private val lineColor: Color = Color(44, 102, 230, 180)
|
||||
private val pointColor: Color = Color(100, 100, 100, 180)
|
||||
private val gridColor: Color = Color(200, 200, 200, 200)
|
||||
private val graphStroke: Stroke = BasicStroke(2f)
|
||||
}
|
||||
|
||||
init {
|
||||
preferredSize = Dimension(padding * 2 + 300, padding * 2 + 200)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package gui
|
||||
|
||||
sealed class GuiEvent {
|
||||
class UpdatePulseCount(val amount: Int) : GuiEvent()
|
||||
class UpdateTickTime(val time: Long) : GuiEvent()
|
||||
class UpdateQueuedPackets(val amount: Int) : GuiEvent()
|
||||
class AddDebugMessage(val message: String) : GuiEvent()
|
||||
class AddDefaultMessage(val message: String) : GuiEvent()
|
||||
class AddAIPMessage(val message: String): GuiEvent()
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package gui
|
||||
|
||||
import rs09.game.system.SystemLogger
|
||||
import rs09.game.world.GameWorld
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import java.awt.Dimension
|
||||
import javax.swing.*
|
||||
import javax.swing.border.Border
|
||||
|
||||
object ServerMonitor : JFrame("Server Monitor"){
|
||||
|
||||
val eventQueue = ArrayList<GuiEvent>()
|
||||
val pulseCount = JLabel("0")
|
||||
val tickTime = JLabel("0")
|
||||
val queuedPackets = JLabel("0")
|
||||
val pulseList = JTextArea("")
|
||||
val debugLog = JTextArea("")
|
||||
val defaultLog = JTextArea("")
|
||||
val AIPlog = JTextArea("")
|
||||
val tickTimeGraph = GraphView()
|
||||
val pulseCountGraph = GraphView()
|
||||
val packetQueueGraph = GraphView()
|
||||
|
||||
init {
|
||||
isVisible = false
|
||||
layout = BorderLayout()
|
||||
size = Dimension(800,640)
|
||||
preferredSize = Dimension(800,640)
|
||||
minimumSize = Dimension(800,640)
|
||||
isResizable = false
|
||||
|
||||
val tabs = JTabbedPane()
|
||||
tabs.addTab("Overview", constructOverviewTab())
|
||||
tabs.addTab("Graphs", constructGraphsTab())
|
||||
add(tabs)
|
||||
|
||||
pack()
|
||||
}
|
||||
|
||||
private fun constructGraphsTab(): JPanel {
|
||||
val graphPanel = JPanel()
|
||||
|
||||
graphPanel.placeAt(0,10,800,590)
|
||||
|
||||
val tickTimeBorder = BorderFactory.createTitledBorder("Tick Time")
|
||||
val pulseCountBorder = BorderFactory.createTitledBorder("Pulse Count")
|
||||
val packetQueueBorder = BorderFactory.createTitledBorder("Queued Packets")
|
||||
|
||||
tickTimeGraph.placeAt(0, 20, 300, 200)
|
||||
tickTimeGraph.border = tickTimeBorder
|
||||
|
||||
pulseCountGraph.placeAt(300,20,300,200)
|
||||
pulseCountGraph.border = pulseCountBorder
|
||||
|
||||
packetQueueGraph.placeAt(0,220,300,200)
|
||||
packetQueueGraph.border = packetQueueBorder
|
||||
|
||||
graphPanel.add(tickTimeGraph)
|
||||
graphPanel.add(pulseCountGraph)
|
||||
graphPanel.add(packetQueueGraph)
|
||||
return graphPanel
|
||||
}
|
||||
|
||||
private fun constructOverviewTab(): JPanel {
|
||||
val overviewPanel = JPanel(null)
|
||||
overviewPanel.placeAt(0,10,800,590)
|
||||
|
||||
val pulseLabel = JLabel("Pulse Count: ")
|
||||
pulseLabel.placeAt(0,20,100,10)
|
||||
pulseCount.placeAt(150,20,100,10)
|
||||
|
||||
val tickLabel = JLabel("Tick Time: ")
|
||||
tickLabel.placeAt(0,35,100,10)
|
||||
tickTime.placeAt(150,35,100,10)
|
||||
|
||||
val packetLabel = JLabel("Queued Packets: ")
|
||||
packetLabel.placeAt(0,50,200,10)
|
||||
queuedPackets.placeAt(150, 50, 100, 10)
|
||||
|
||||
val scrollPane = JScrollPane(pulseList)
|
||||
scrollPane.placeAt(400,10,390,275)
|
||||
|
||||
val border = BorderFactory.createTitledBorder("Pulses")
|
||||
scrollPane.border = border
|
||||
|
||||
overviewPanel.add(pulseLabel)
|
||||
overviewPanel.add(pulseCount)
|
||||
overviewPanel.add(tickLabel)
|
||||
overviewPanel.add(tickTime)
|
||||
overviewPanel.add(packetLabel)
|
||||
overviewPanel.add(queuedPackets)
|
||||
overviewPanel.add(scrollPane)
|
||||
|
||||
val logPane = constructLogPane()
|
||||
logPane.placeAt(0,280,800,300)
|
||||
overviewPanel.add(logPane)
|
||||
|
||||
return overviewPanel
|
||||
}
|
||||
|
||||
private fun constructLogPane() : JTabbedPane {
|
||||
val logPane = JTabbedPane()
|
||||
|
||||
debugLog.isEditable = false
|
||||
val debugPanel = JPanel(BorderLayout())
|
||||
val debugScrollpane = JScrollPane(debugLog)
|
||||
debugScrollpane.placeAt(0,300,800,300)
|
||||
debugPanel.add(debugScrollpane, BorderLayout.CENTER)
|
||||
|
||||
defaultLog.isEditable = false
|
||||
val defaultPanel = JPanel(BorderLayout())
|
||||
val defaultScrollpane = JScrollPane(defaultLog)
|
||||
defaultScrollpane.placeAt(0,300,800,300)
|
||||
defaultPanel.add(defaultScrollpane, BorderLayout.CENTER)
|
||||
|
||||
AIPlog.isEditable = false
|
||||
val AIPPanel = JPanel(BorderLayout())
|
||||
val AIPscrollpane = JScrollPane(AIPlog)
|
||||
AIPscrollpane.placeAt(0,300,800,300)
|
||||
AIPPanel.add(AIPscrollpane, BorderLayout.CENTER)
|
||||
|
||||
logPane.addTab("Default",defaultPanel)
|
||||
logPane.addTab("Debug",debugPanel)
|
||||
logPane.addTab("AIP",AIPPanel)
|
||||
|
||||
return logPane
|
||||
}
|
||||
|
||||
|
||||
private fun Component.placeAt(x: Int, y: Int, width: Int, height: Int){
|
||||
this.setBounds(x,y,width,height)
|
||||
}
|
||||
|
||||
fun open() {
|
||||
isVisible = true
|
||||
Thread() {
|
||||
while (true) {
|
||||
SwingUtilities.invokeLater {
|
||||
val removeList = ArrayList<GuiEvent>()
|
||||
eventQueue.toTypedArray().forEach { event ->
|
||||
when (event) {
|
||||
is GuiEvent.UpdatePulseCount -> {
|
||||
pulseCount.text = event.amount.toString()
|
||||
pulseCountGraph.addValues(intArrayOf(event.amount).toList())
|
||||
}
|
||||
is GuiEvent.UpdateTickTime -> {
|
||||
tickTime.text = event.time.toString() + "ms"
|
||||
tickTimeGraph.addValues(intArrayOf(event.time.toInt()).toList())
|
||||
}
|
||||
is GuiEvent.AddDefaultMessage -> defaultLog.text = defaultLog.text + event.message + "\n"
|
||||
is GuiEvent.AddAIPMessage -> AIPlog.text = AIPlog.text + event.message + "\n"
|
||||
is GuiEvent.AddDebugMessage -> debugLog.text = debugLog.text + event.message + "\n"
|
||||
is GuiEvent.UpdateQueuedPackets -> {
|
||||
queuedPackets.text = event.amount.toString()
|
||||
packetQueueGraph.addValues(intArrayOf(event.amount).toList())
|
||||
}
|
||||
}
|
||||
removeList.add(event)
|
||||
}
|
||||
|
||||
pulseList.text = GameWorld.Pulser.TASKS.toArray().filterNotNull().map { it.javaClass.simpleName + "\n" }
|
||||
.filter { it.replace("\n", "").isNotEmpty() }.sorted().joinToString("")
|
||||
eventQueue.removeAll(removeList)
|
||||
repaint()
|
||||
}
|
||||
Thread.sleep(600L)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import core.gui.ConsoleFrame
|
||||
import core.net.NioReactor
|
||||
import core.net.amsc.WorldCommunicator
|
||||
import core.tools.TimeStamp
|
||||
import gui.ServerMonitor
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -28,7 +29,6 @@ import kotlin.system.exitProcess
|
||||
/**
|
||||
* The main class, for those that are unable to read the class' name.
|
||||
* @author Emperor
|
||||
* @author Vexia
|
||||
* @author Ceikry
|
||||
*/
|
||||
object Server {
|
||||
@@ -95,6 +95,7 @@ object Server {
|
||||
|
||||
GEAutoStock.autostock()
|
||||
val scanner = Scanner(System.`in`)
|
||||
|
||||
running = true
|
||||
GlobalScope.launch {
|
||||
while(scanner.hasNextLine()){
|
||||
@@ -112,7 +113,7 @@ object Server {
|
||||
GlobalScope.launch {
|
||||
delay(20000)
|
||||
while(running){
|
||||
if(System.currentTimeMillis() - lastHeartbeat > 1800 && running){
|
||||
if(System.currentTimeMillis() - lastHeartbeat > 7200 && running){
|
||||
SystemLogger.logErr("Triggering reboot due to heartbeat timeout")
|
||||
SystemLogger.logErr("Creating thread dump...")
|
||||
val dump = threadDump(true, true)
|
||||
|
||||
@@ -17,6 +17,9 @@ class ServerConstants {
|
||||
@JvmField
|
||||
var SHUTDOWN_HOOK: Thread = Thread(SystemShutdownHook())
|
||||
|
||||
@JvmField
|
||||
var ALLOW_GUI: Boolean = false
|
||||
|
||||
@JvmField
|
||||
var DATA_PATH: String? = null
|
||||
|
||||
@@ -209,6 +212,9 @@ class ServerConstants {
|
||||
if(data.containsKey("writeLogs")){
|
||||
WRITE_LOGS = data["writeLogs"] as Boolean
|
||||
}
|
||||
if(data.containsKey("enable_gui")){
|
||||
ALLOW_GUI = data["enable_gui"] as Boolean
|
||||
}
|
||||
|
||||
DATABASE_NAME = data["database_name"].toString()
|
||||
DATABASE_USER = data["database_username"].toString()
|
||||
|
||||
@@ -374,7 +374,9 @@ class ScriptAPI(private val bot: Player) {
|
||||
diffX /= 2
|
||||
diffY /= 2
|
||||
}
|
||||
GameWorld.Pulser.submit(object : MovementPulse(bot, bot.location.transform(diffX, diffY, 0), Pathfinder.SMART) {
|
||||
val dest = bot.location.transform(diffX,diffY,0)
|
||||
bot.pulseManager.run(object :
|
||||
MovementPulse(bot, dest, Pathfinder.SMART) {
|
||||
override fun pulse(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,8 @@ package rs09.game.system
|
||||
|
||||
import com.github.ajalt.mordant.rendering.TextColors
|
||||
import com.github.ajalt.mordant.terminal.Terminal
|
||||
import gui.GuiEvent
|
||||
import gui.ServerMonitor
|
||||
import rs09.ServerConstants
|
||||
import java.io.*
|
||||
import java.text.SimpleDateFormat
|
||||
@@ -42,28 +44,48 @@ object SystemLogger {
|
||||
@JvmStatic
|
||||
fun logInfo(vararg messages: String){
|
||||
for(m in messages){
|
||||
if(m.isNotBlank()) t.println("${getTime()}: [INFO] $m")
|
||||
val msg = "${getTime()}: [INFO] $m"
|
||||
if(m.isNotBlank()) {
|
||||
t.println(msg)
|
||||
ServerMonitor.eventQueue.add(GuiEvent.AddDefaultMessage(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logErr(message: String){
|
||||
if(message.isNotBlank()) t.println("${getTime()}: ${TextColors.brightRed("[ ERR] $message")}")
|
||||
val msg = "${getTime()}: [ ERR] $message"
|
||||
if(message.isNotBlank()) {
|
||||
t.println(msg)
|
||||
ServerMonitor.eventQueue.add(GuiEvent.AddDebugMessage(msg))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logWarn(message: String){
|
||||
if(message.isNotBlank()) t.println("${getTime()}: ${TextColors.yellow("[WARN] $message")}")
|
||||
val msg = "${getTime()}: [WARN] $message"
|
||||
if(message.isNotBlank()) {
|
||||
t.println(msg)
|
||||
ServerMonitor.eventQueue.add(GuiEvent.AddDebugMessage(msg))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logAlert(message: String){
|
||||
if(message.isNotBlank()) t.println("${getTime()}: ${TextColors.brightYellow("[ALRT] $message")}")
|
||||
val msg = "${getTime()}: [ALRT] $message"
|
||||
if(message.isNotBlank()) {
|
||||
t.println(msg)
|
||||
ServerMonitor.eventQueue.add(GuiEvent.AddDebugMessage(msg))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logAI(message: String){
|
||||
if(message.isNotBlank()) t.println("${getTime()}: ${TextColors.gray("[AIPL] $message")}")
|
||||
val msg = "${getTime()}: [AIPL] $message"
|
||||
if(message.isNotBlank()) {
|
||||
t.println(msg)
|
||||
ServerMonitor.eventQueue.add(GuiEvent.AddAIPMessage(msg))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -115,6 +115,7 @@ class DisconnectionQueue {
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun add(player: Player, clear: Boolean = false) {
|
||||
if(queue[player.name] != null) return
|
||||
queue[player.name] = DisconnectionEntry(player, clear)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package rs09.net.packet
|
||||
|
||||
import core.net.packet.OutgoingPacket
|
||||
import core.net.packet.out.*
|
||||
import gui.GuiEvent
|
||||
import gui.ServerMonitor
|
||||
import rs09.game.system.SystemLogger
|
||||
import java.util.*
|
||||
|
||||
@@ -28,6 +30,7 @@ object PacketWriteQueue {
|
||||
|
||||
@JvmStatic
|
||||
fun flush(){
|
||||
ServerMonitor.eventQueue.add(GuiEvent.UpdateQueuedPackets(PacketsToWrite.size))
|
||||
while(!PacketsToWrite.isEmpty()){
|
||||
val p = PacketsToWrite.poll() ?: continue
|
||||
write(p.out,p.context)
|
||||
|
||||
@@ -5,12 +5,15 @@ import core.game.system.SystemManager
|
||||
import core.game.system.SystemState
|
||||
import core.game.system.task.Pulse
|
||||
import core.plugin.CorePluginTypes.Managers
|
||||
import gui.GuiEvent
|
||||
import gui.ServerMonitor
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import rs09.Server
|
||||
import rs09.ServerConstants
|
||||
import rs09.ServerStore
|
||||
import rs09.game.ai.general.GeneralBotCreator
|
||||
import rs09.game.system.SystemLogger
|
||||
import rs09.game.world.GameWorld
|
||||
import rs09.game.world.repository.Repository
|
||||
@@ -44,7 +47,25 @@ class MajorUpdateWorker {
|
||||
|
||||
//run our pulses
|
||||
for(pulse in list) {
|
||||
val b = System.currentTimeMillis()
|
||||
if (pulse == null || pulse.update()) rmlist.add(pulse)
|
||||
|
||||
val time = System.currentTimeMillis() - b
|
||||
|
||||
if(time >= 100){
|
||||
if(pulse is GeneralBotCreator.BotScriptPulse){
|
||||
SystemLogger.logWarn("CRITICALLY Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms")
|
||||
} else {
|
||||
SystemLogger.logWarn("CRITICALLY long running pulse: ${pulse.javaClass.name} - $time ms")
|
||||
}
|
||||
}
|
||||
else if(time >= 30){
|
||||
if(pulse is GeneralBotCreator.BotScriptPulse){
|
||||
SystemLogger.logWarn("Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms")
|
||||
} else {
|
||||
SystemLogger.logWarn("Long Running Pulse: ${pulse.javaClass.name} - $time ms")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//remove all null or finished pulses from the list
|
||||
@@ -58,7 +79,9 @@ class MajorUpdateWorker {
|
||||
sequence.start()
|
||||
sequence.run()
|
||||
sequence.end()
|
||||
PacketWriteQueue.flush()
|
||||
GlobalScope.launch {
|
||||
PacketWriteQueue.flush()
|
||||
}
|
||||
} catch (e: Exception){
|
||||
e.printStackTrace()
|
||||
}
|
||||
@@ -95,12 +118,18 @@ class MajorUpdateWorker {
|
||||
}
|
||||
|
||||
val end = System.currentTimeMillis()
|
||||
ServerMonitor.eventQueue.add(GuiEvent.UpdateTickTime(end - start))
|
||||
ServerMonitor.eventQueue.add(GuiEvent.UpdatePulseCount(GameWorld.Pulser.TASKS.size))
|
||||
Thread.sleep(max(600 - (end - start), 0))
|
||||
}
|
||||
}
|
||||
|
||||
fun start() {
|
||||
if(!started){
|
||||
worker.start()
|
||||
}
|
||||
|
||||
if (ServerConstants.ALLOW_GUI)
|
||||
ServerMonitor.open()
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
"enable_bots": true,
|
||||
"autostock_ge": true,
|
||||
"allow_token_purchase": true,
|
||||
"max_adv_bots": "0",
|
||||
"max_adv_bots": "100",
|
||||
"message_of_the_week_identifier": "0",
|
||||
"skillcape_perks": false,
|
||||
"message_of_the_week_text": "Welcome to 2009Scape! <br><col=11ff00>N</col><col=ecff00>o</col><col=ff8300>w</col <col=ff0000>i</col><col=ff00d4>n</col> <col=6100ff>T</col><col=000fff>e</col><col=00f0ff>c</col><col=00ff59>h</col><col=93ff00>n</col><col=ff9e00>i</col><col=ff0000>c</col><col=ff00d1>o</col><col=2700ff>l</col><col=00f7ff>o</col><col=00ff0c>r</col><col=ff0000>!</col>"
|
||||
@@ -45,7 +45,8 @@
|
||||
"database_password": "",
|
||||
"database_address": "127.0.0.1",
|
||||
"database_port": "3306",
|
||||
"ms_secret_key": "2009scape_development"
|
||||
"ms_secret_key": "2009scape_development",
|
||||
"enable_gui": false
|
||||
},
|
||||
|
||||
"PluginToggles": {
|
||||
|
||||
Reference in New Issue
Block a user