diff --git a/src/main/kotlin/net/idylls/tickle/Panel.kt b/src/main/kotlin/net/idylls/tickle/Panel.kt index 84cc834..2a5a73e 100644 --- a/src/main/kotlin/net/idylls/tickle/Panel.kt +++ b/src/main/kotlin/net/idylls/tickle/Panel.kt @@ -2,7 +2,9 @@ package net.idylls.tickle import org.slf4j.LoggerFactory -import java.awt.GridBagLayout +import javax.inject.Inject + +import java.awt.GridLayout import java.awt.BorderLayout import java.awt.event.ActionEvent import java.awt.event.FocusEvent @@ -11,20 +13,69 @@ import java.awt.Color import javax.swing.AbstractAction import javax.swing.BorderFactory +import javax.swing.BoxLayout import javax.swing.JPanel -import javax.swing.JTextArea -import javax.swing.KeyStroke -import javax.swing.border.EmptyBorder -import javax.swing.text.BadLocationException -import javax.swing.text.Document -import javax.swing.undo.CannotUndoException -import javax.swing.undo.UndoManager +import javax.swing.JLabel import net.runelite.client.ui.ColorScheme import net.runelite.client.ui.PluginPanel +import net.runelite.api.Client +import net.runelite.client.ui.FontManager + +class CurrentWorldPanel +constructor( + val plugin: TicklePlugin, +) : JPanel() { + val lastTickTime = JLabel() + val averageTickTime = JLabel() + val goodTickPercentage = JLabel() + val worstTickDeviation = JLabel() + + init { + this.setLayout(BoxLayout(this, BoxLayout.Y_AXIS)) + this.setBackground(ColorScheme.DARKER_GRAY_COLOR) + + averageTickTime.setForeground(Color.WHITE); + averageTickTime.setFont(FontManager.getRunescapeFont()); + + worstTickDeviation.setForeground(Color.WHITE); + worstTickDeviation.setFont(FontManager.getRunescapeFont()); + + lastTickTime.setForeground(Color.WHITE); + lastTickTime.setFont(FontManager.getRunescapeFont()); + + goodTickPercentage.setForeground(Color.WHITE); + goodTickPercentage.setFont(FontManager.getRunescapeFont()); -class Panel : PluginPanel() { + this.add(lastTickTime) + this.add(averageTickTime) + this.add(goodTickPercentage) + this.add(worstTickDeviation) + } + + fun update() { + val current = plugin.worldsStats.current() + if (current == null) { + return + } + + this.lastTickTime.setText("Last tick time: ${current.lastTickTime}ms") + this.averageTickTime.setText("Avg tick time: ${current.averageTickTime}ms") + this.goodTickPercentage.setText("Good tick %: ${( + ((current.tickCount - current.badTickCount).toDouble() + / current.tickCount.toDouble()) * 100.0 + )}%") + this.worstTickDeviation.setText("Worst dev: ${current.worstTickDeviation}ms") + } +} + +class Panel +@Inject constructor( + val client: Client, + val plugin: TicklePlugin, +) : PluginPanel() { val log = LoggerFactory.getLogger(Panel::class.java) + val currentWorldPanel = CurrentWorldPanel(plugin) init { this.setLayout(BorderLayout()) @@ -33,8 +84,10 @@ class Panel : PluginPanel() { this.log.info("Initialized Tickle panel") - val panel = JPanel() + this.add(this.currentWorldPanel) + } - this.add(panel) + fun updateCurrentPanel() { + this.currentWorldPanel.update() } } diff --git a/src/main/kotlin/net/idylls/tickle/Stats.kt b/src/main/kotlin/net/idylls/tickle/Stats.kt new file mode 100644 index 0000000..4886890 --- /dev/null +++ b/src/main/kotlin/net/idylls/tickle/Stats.kt @@ -0,0 +1,66 @@ +package net.idylls.tickle + +import javax.inject.Inject + +import net.runelite.api.World +import net.runelite.api.Client + +import kotlin.math.abs + +const val IDEAL_TICK_MS = 600 +const val BAD_TICK_THRESHOLD_MS = 60 + +class WorldStats { + var tickCount = 0 + var badTickCount = 0 + + var averageTickTime = 0.0 + var worstTickDeviation = 0 + var lastTickTime = 0 + + fun track(tickTimeMs: Int) { + this.averageTickTime = ( + (tickTimeMs + (this.averageTickTime * this.tickCount)) + / (this.tickCount + 1) + ) + + this.tickCount += 1 + this.lastTickTime = tickTimeMs + + val tickDeviation = abs(tickTimeMs - IDEAL_TICK_MS) + + if (this.worstTickDeviation < tickDeviation) { + this.worstTickDeviation = tickDeviation + } + + if (tickDeviation > BAD_TICK_THRESHOLD_MS) { + this.badTickCount += 1 + } + } +} + +typealias WorldId = Int + +class WorldsStats +@Inject constructor( + val client: Client, +) { + val data = mutableMapOf() + + fun current(): WorldStats? { + val world = client.getWorld() + if (world == null) { + return null + } + + return this.get(world) + } + + fun get(worldId: WorldId): WorldStats { + if (!data.contains(worldId)) { + data.put(worldId, WorldStats()) + } + + return data.get(worldId)!! + } +} diff --git a/src/main/kotlin/net/idylls/tickle/TicklePlugin.kt b/src/main/kotlin/net/idylls/tickle/TicklePlugin.kt index 0a4904d..9bac5be 100644 --- a/src/main/kotlin/net/idylls/tickle/TicklePlugin.kt +++ b/src/main/kotlin/net/idylls/tickle/TicklePlugin.kt @@ -40,6 +40,9 @@ public class TicklePlugin : Plugin() { lateinit var navButton: NavigationButton; var ticksSinceLogin: Int = 0 + var lastTickTime = System.nanoTime() + + lateinit var worldsStats: WorldsStats override fun startUp() { log.info("Tickle started") @@ -54,8 +57,8 @@ public class TicklePlugin : Plugin() { .build() this.clientToolbar.addNavigation(this.navButton) - this.overlayManager.add(this.overlay) + this.worldsStats = WorldsStats(this.client) } override fun shutDown() { @@ -65,6 +68,17 @@ public class TicklePlugin : Plugin() { @Subscribe fun onGameTick(tick: GameTick) { - ticksSinceLogin++ + val now = System.nanoTime() + + this.ticksSinceLogin++ + + if (ticksSinceLogin > 30) { + val diff = ((now - this.lastTickTime) / 1000000).toInt() + + this.worldsStats.current()?.track(diff) + this.panel.updateCurrentPanel() + } + + this.lastTickTime = now } }