diff --git a/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.kt b/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.kt
new file mode 100644
index 0000000..19c07fa
--- /dev/null
+++ b/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.kt
@@ -0,0 +1,331 @@
+package FooTextPlugin
+
+import plugin.Plugin
+import rt4.Component
+import rt4.JagString
+import rt4.Player
+import java.nio.charset.StandardCharsets
+import com.google.gson.Gson
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.net.HttpURLConnection
+import java.net.URL
+
+/**
+ * Iron Helmets in Chatbox
+ *
+ * Will be integrated into Kondo
+ *
+ * @author downthecrop
+ */
+class plugin : Plugin() {
+
+ private val TARGET_COMPONENT_ID = 8978483
+ private val TARGET_COMPONENT_INDEX = 51
+ private val BUBBLE_ICON = "
"
+ private val gson = Gson()
+
+ val TYPE_ICONS: Map = hashMapOf(
+ 0 to "",
+ 1 to "
", // IM
+ 2 to "
", // HCIM
+ 3 to "
", // UIM
+ )
+
+ private var ACCOUNT_TYPE = 0
+
+
+ private var component: Component? = null
+
+ // See JagString.java parse(), There is special encoding
+ // and this correctly resolves specials.
+ val SPECIAL_ESCAPES: Map = hashMapOf(
+ ' ' to "(P",
+ '!' to "(Q",
+ '"' to "(R",
+ '#' to "(S",
+ '$' to "(T",
+ '%' to "(U",
+ '&' to "(V",
+ '\'' to "(W",
+ '(' to "(X",
+ ')' to "(Y",
+ '*' to "(Z",
+ '+' to ")0",
+ ',' to ")1",
+ '-' to ")2",
+ '.' to ")3",
+ '/' to ")4",
+ ':' to "(j",
+ ';' to "(k",
+ '=' to ")B",
+ '?' to ")D",
+ '@' to ")E",
+ '[' to "*5",
+ '\\' to "*6",
+ ']' to "*7",
+ '^' to "*8",
+ '_' to "*9",
+ '`' to ")e",
+ '{' to "*U",
+ '|' to "*V",
+ '}' to "*W",
+ '~' to "*X",
+ '\u0000' to "(0",
+ '\u0001' to "(1",
+ '\u0002' to "(2",
+ '\u0003' to "(3",
+ '\u0004' to "(4",
+ '\u0005' to "(5",
+ '\u0006' to "(6",
+ '\u0007' to "(7",
+ '\b' to "(8",
+ '\t' to "(9",
+ '\n' to "(:",
+ '\u000B' to "(;",
+ '\u000C' to "(<",
+ '\r' to "(=",
+ '\u000E' to "(>",
+ '\u000F' to "(?",
+ '\u0010' to "(@",
+ '\u0011' to "(A",
+ '\u0012' to "(B",
+ '\u0013' to "(C",
+ '\u0014' to "(D",
+ '\u0015' to "(E",
+ '\u0016' to "(F",
+ '\u0017' to "(G",
+ '\u0018' to "(H",
+ '\u0019' to "(I",
+ '\u001A' to "(J",
+ '\u001B' to "(K",
+ '\u001C' to "(L",
+ '\u001D' to "(M",
+ '\u001E' to "(N",
+ '\u001F' to "(O",
+ '\u007F' to "*Y",
+ '\u0080' to "*Z",
+ '\u0081' to "+0",
+ '\u0082' to "+1",
+ '\u0083' to "+2",
+ '\u0084' to "+3",
+ '\u0085' to "+4",
+ '\u0086' to "+5",
+ '\u0087' to "+6",
+ '\u0088' to "+7",
+ '\u0089' to "+8",
+ '\u008A' to "+9",
+ '\u008B' to "*e",
+ '\u008C' to "*f",
+ '\u008D' to "*g",
+ '\u008E' to "*h",
+ '\u008F' to "*i",
+ '\u0090' to "*j",
+ '\u0091' to "*k",
+ '\u0092' to "+A",
+ '\u0093' to "+B",
+ '\u0094' to "+C",
+ '\u0095' to "+D",
+ '\u0096' to "+E",
+ '\u0097' to "+F",
+ '\u0098' to "+G",
+ '\u0099' to "+H",
+ '\u009A' to "+I",
+ '\u009B' to "+J",
+ '\u009C' to "+K",
+ '\u009D' to "+L",
+ '\u009E' to "+M",
+ '\u009F' to "+N",
+ '\u00A0' to "+O",
+ '\u00A1' to "+P",
+ '\u00A2' to "+Q",
+ '\u00A3' to "+R",
+ '\u00A4' to "+S",
+ '\u00A5' to "+T",
+ '\u00A6' to "+U",
+ '\u00A7' to "+V",
+ '\u00A8' to "+W",
+ '\u00A9' to "+X",
+ '\u00AA' to "+Y",
+ '\u00AB' to "+Z",
+ '\u00AC' to ",0",
+ '\u00AD' to ",1",
+ '\u00AE' to ",2",
+ '\u00AF' to ",3",
+ '\u00B0' to ",4",
+ '\u00B1' to ",5",
+ '\u00B2' to ",6",
+ '\u00B3' to ",7",
+ '\u00B4' to ",8",
+ '\u00B5' to ",9",
+ '\u00B6' to "+e",
+ '\u00B7' to "+f",
+ '\u00B8' to "+g",
+ '\u00B9' to "+h",
+ '\u00BA' to "+i",
+ '\u00BB' to "+j",
+ '\u00BC' to "+k",
+ '\u00BD' to ",A",
+ '\u00BE' to ",B",
+ '\u00BF' to ",C",
+ '\u00C0' to ",D",
+ '\u00C1' to ",E",
+ '\u00C2' to ",F",
+ '\u00C3' to ",G",
+ '\u00C4' to ",H",
+ '\u00C5' to ",I",
+ '\u00C6' to ",J",
+ '\u00C7' to ",K",
+ '\u00C8' to ",L",
+ '\u00C9' to ",M",
+ '\u00CA' to ",N",
+ '\u00CB' to ",O",
+ '\u00CC' to ",P",
+ '\u00CD' to ",Q",
+ '\u00CE' to ",R",
+ '\u00CF' to ",S",
+ '\u00D0' to ",T",
+ '\u00D1' to ",U",
+ '\u00D2' to ",V",
+ '\u00D3' to ",W",
+ '\u00D4' to ",X",
+ '\u00D5' to ",Y",
+ '\u00D6' to ",Z",
+ '\u00D7' to "-0",
+ '\u00D8' to "-1",
+ '\u00D9' to "-2",
+ '\u00DA' to "-3",
+ '\u00DB' to "-4",
+ '\u00DC' to "-5",
+ '\u00DD' to "-6",
+ '\u00DE' to "-7",
+ '\u00DF' to "-8",
+ '\u00E0' to "-9",
+ '\u00E1' to ",e",
+ '\u00E2' to ",f",
+ '\u00E3' to ",g",
+ '\u00E4' to ",h",
+ '\u00E5' to ",i",
+ '\u00E6' to ",j",
+ '\u00E7' to ",k",
+ '\u00E8' to "-A",
+ '\u00E9' to "-B",
+ '\u00EA' to "-C",
+ '\u00EB' to "-D",
+ '\u00EC' to "-E",
+ '\u00ED' to "-F",
+ '\u00EE' to "-G",
+ '\u00EF' to "-H",
+ '\u00F0' to "-I",
+ '\u00F1' to "-J",
+ '\u00F2' to "-K",
+ '\u00F3' to "-L",
+ '\u00F4' to "-M",
+ '\u00F5' to "-N",
+ '\u00F6' to "-O",
+ '\u00F7' to "-P",
+ '\u00F8' to "-Q",
+ '\u00F9' to "-R",
+ '\u00FA' to "-S",
+ '\u00FB' to "-T",
+ '\u00FC' to "-U",
+ '\u00FD' to "-V",
+ '\u00FE' to "-W",
+ '\u00FF' to "-X"
+ )
+
+ override fun Draw(timeDelta: Long) {
+ if (component != null && component?.id == TARGET_COMPONENT_ID) {
+ val username = Player.usernameInput.toString().toLowerCase()
+ val modifiedStr = replaceUsernameInBytes(component!!.text.chars, username)
+ component?.text = JagString.parse(modifiedStr)
+ }
+ }
+
+ override fun ComponentDraw(componentIndex: Int, component: Component?, screenX: Int, screenY: Int) {
+ if (component?.id == TARGET_COMPONENT_ID && componentIndex == TARGET_COMPONENT_INDEX) {
+ this.component = component
+ }
+ }
+
+ private fun fetchAccountTypeFromAPI(){
+ println("Fetching Iron status from API...")
+ val cleanUsername = Player.usernameInput.toString().replace(" ", "_")
+ val apiUrl = "http://api.2009scape.org:3000/hiscores/playerSkills/1/${cleanUsername.toLowerCase()}"
+ Thread {
+ try {
+ val url = URL(apiUrl)
+ val connection = url.openConnection() as HttpURLConnection
+ connection.requestMethod = "GET"
+
+ // If a request take longer than 5 seconds timeout.
+ connection.connectTimeout = 5000
+ connection.readTimeout = 5000
+
+ val responseCode = connection.responseCode
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ val reader = BufferedReader(InputStreamReader(connection.inputStream))
+ val response = reader.use { it.readText() }
+ reader.close()
+ updatePlayerData(response)
+ }
+ } catch (_: Exception) { }
+ }.start()
+ }
+
+ private fun updatePlayerData(jsonResponse: String) {
+ val hiscoresResponse = gson.fromJson(jsonResponse, HiscoresResponse::class.java)
+ ACCOUNT_TYPE = hiscoresResponse.info.iron_mode.toInt()
+ println("Resolved you are account type: $ACCOUNT_TYPE")
+ }
+
+ override fun OnLogin() {
+ // The server doesn't tell us what account type we are.
+ // Requesting from API is the easier way to tell.
+ fetchAccountTypeFromAPI()
+ }
+
+ private fun replaceUsernameInBytes(bytes: ByteArray, username: String): String {
+ // Convert bytes to string to work with them
+ val text = String(bytes, StandardCharsets.ISO_8859_1)
+ val colonIndex = text.indexOf(": ")
+ if (colonIndex != -1) {
+ val suffix = text.substring(colonIndex)
+ // modify and add the rest (username is always before the first ':' )
+ val newText = "${TYPE_ICONS[ACCOUNT_TYPE]}$username$BUBBLE_ICON$suffix"
+ return encodeToJagStr(newText)
+ }
+ return encodeToJagStr(text)
+ }
+
+ private fun encodeToJagStr(str: String): String {
+ val result = StringBuilder()
+ for (char in str) {
+ val escaped = SPECIAL_ESCAPES[char]
+ if (escaped != null) {
+ result.append(escaped)
+ } else {
+ result.append(char)
+ }
+ }
+ return result.toString()
+ }
+
+ // Lifted from KondoHiscores view
+ data class HiscoresResponse(
+ val info: PlayerInfo,
+ val skills: List
+ )
+
+ data class PlayerInfo(
+ val exp_multiplier: String,
+ val iron_mode: String
+ )
+
+ data class Skill(
+ val id: String,
+ val dynamic: String,
+ val experience: String,
+ val static: String
+ )
+}
\ No newline at end of file
diff --git a/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.properties b/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.properties
new file mode 100644
index 0000000..8ef8645
--- /dev/null
+++ b/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.properties
@@ -0,0 +1,3 @@
+AUTHOR=YourName
+DESCRIPTION=Replaces the username part of Component Index: 51 ID: 8978483 with "foo"
+VERSION=1.0
\ No newline at end of file
diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt
index cd74c6f..022a390 100644
--- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt
+++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt
@@ -11,10 +11,7 @@ import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite
import KondoKit.Themes.Theme
import KondoKit.Themes.ThemeType
import KondoKit.Themes.getTheme
-import KondoKit.components.ProgressBar
import KondoKit.components.ScrollablePanel
-import KondoKit.components.ToggleSwitch
-import KondoKit.components.*
import KondoKit.views.XPTrackerView
import KondoKit.plugin.StateManager.focusedView
import KondoKit.views.Constants.COMBAT_LVL_SPRITE