Ironman helmets in chatbox (dummy plugin)

This commit is contained in:
downthecrop 2025-09-08 23:50:37 -07:00
parent eee924e915
commit fec060626b
3 changed files with 334 additions and 3 deletions

View file

@ -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 = "<img=3>"
private val gson = Gson()
val TYPE_ICONS: Map<Int, String> = hashMapOf(
0 to "",
1 to "<img=4>", // IM
2 to "<img=5>", // HCIM
3 to "<img=6>", // 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<Char, String> = 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<Skill>
)
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
)
}

View file

@ -0,0 +1,3 @@
AUTHOR=YourName
DESCRIPTION=Replaces the username part of Component Index: 51 ID: 8978483 with "foo"
VERSION=1.0

View file

@ -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