Skip to content

Commit b0c8949

Browse files
committed
fix bugs & add extension functions for TextComponent
1 parent f189ea8 commit b0c8949

File tree

4 files changed

+78
-37
lines changed

4 files changed

+78
-37
lines changed

src/main/kotlin/tech/aliorpse/mcutils/model/server/TextComponentAdapter.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ internal class TextComponentAdapter {
4040
"text" -> {
4141
val rawText = reader.nextString()
4242
val parsed = rawText.toTextComponent()
43-
text = parsed.text
44-
color = parsed.color
45-
styles += parsed.styles
46-
if (parsed.extra.isNotEmpty()) {
47-
extra = parsed.extra
43+
44+
text = rawText.takeIf { "§" !in rawText } ?: parsed.text.also {
45+
color = parsed.color
46+
styles += parsed.styles
47+
if (parsed.extra.isNotEmpty()) extra = parsed.extra
4848
}
4949
}
5050
"color" -> color = reader.readColor()
@@ -64,21 +64,21 @@ internal class TextComponentAdapter {
6464
}
6565

6666
private fun JsonReader.readStyle(name: String): TextStyle? {
67-
return if (this.nextBoolean()) styleMap[name] else null
67+
return if (nextBoolean()) styleMap[name] else null
6868
}
6969

7070
private fun JsonReader.readColor(): String {
71-
val colorString = this.nextString()
71+
val colorString = nextString()
7272
return colors[colorString] ?: colorString
7373
}
7474

7575
private fun JsonReader.readExtras(): List<TextComponent> {
7676
val list = mutableListOf<TextComponent>()
77-
this.beginArray()
78-
while (this.hasNext()) {
77+
beginArray()
78+
while (hasNext()) {
7979
fromJson(this)?.let { list.add(it) }
8080
}
81-
this.endArray()
81+
endArray()
8282
return list
8383
}
8484

src/main/kotlin/tech/aliorpse/mcutils/utils/TextComponent.kt

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import java.util.EnumSet
77
/**
88
* Coverts string with "§" to a [TextComponent].
99
*/
10-
internal fun String.toTextComponent(): TextComponent {
10+
fun String.toTextComponent(): TextComponent {
1111
val components = mutableListOf<TextComponent>()
1212
var currentText = StringBuilder()
1313
var currentColor = ""
@@ -21,22 +21,20 @@ internal fun String.toTextComponent(): TextComponent {
2121

2222
if (currentText.isNotEmpty()) {
2323
components += TextComponent(
24-
text = currentText.toString(),
25-
color = currentColor,
26-
styles = EnumSet.copyOf(currentStyles)
24+
text = currentText.toString(), color = currentColor, styles = EnumSet.copyOf(currentStyles)
2725
)
2826
currentText = StringBuilder()
2927
}
3028

31-
// §r 重置
29+
// §r reset
3230
if (code == 'r') {
3331
currentColor = ""
3432
currentStyles.clear()
3533
} else {
36-
// §0-§f 颜色
37-
colorMap[code]?.let { currentColor = it }
38-
// §k-§o 样式
39-
styleMap[code]?.let { currentStyles += it }
34+
// §0-§f colors
35+
originalColorMap[code]?.let { currentColor = it }
36+
// §k-§o styles
37+
originalStyleMap[code]?.let { currentStyles += it }
4038
}
4139
} else {
4240
currentText.append(c)
@@ -45,35 +43,78 @@ internal fun String.toTextComponent(): TextComponent {
4543

4644
if (currentText.isNotEmpty()) {
4745
components += TextComponent(
48-
text = currentText.toString(),
49-
color = currentColor,
50-
styles = EnumSet.copyOf(currentStyles)
46+
text = currentText.toString(), color = currentColor, styles = EnumSet.copyOf(currentStyles)
5147
)
5248
}
5349

5450
return if (components.size == 1) {
5551
components[0]
5652
} else {
5753
TextComponent(
58-
text = "",
59-
color = "",
60-
styles = EnumSet.noneOf(TextStyle::class.java),
61-
extra = components
54+
text = "", color = "", styles = EnumSet.noneOf(TextStyle::class.java), extra = components
6255
)
6356
}
6457
}
6558

66-
private val colorMap = mapOf(
67-
'0' to "#000000", '1' to "#0000AA", '2' to "#00AA00", '3' to "#00AAAA",
68-
'4' to "#AA0000", '5' to "#AA00AA", '6' to "#FFAA00", '7' to "#AAAAAA",
69-
'8' to "#555555", '9' to "#5555FF", 'a' to "#55FF55", 'b' to "#55FFFF",
70-
'c' to "#FF5555", 'd' to "#FF55FF", 'e' to "#FFFF55", 'f' to "#FFFFFF"
59+
private val originalColorMap = mapOf(
60+
'0' to "#000000",
61+
'1' to "#0000AA",
62+
'2' to "#00AA00",
63+
'3' to "#00AAAA",
64+
'4' to "#AA0000",
65+
'5' to "#AA00AA",
66+
'6' to "#FFAA00",
67+
'7' to "#AAAAAA",
68+
'8' to "#555555",
69+
'9' to "#5555FF",
70+
'a' to "#55FF55",
71+
'b' to "#55FFFF",
72+
'c' to "#FF5555",
73+
'd' to "#FF55FF",
74+
'e' to "#FFFF55",
75+
'f' to "#FFFFFF"
7176
)
7277

73-
private val styleMap = mapOf(
78+
private val originalStyleMap = mapOf(
7479
'l' to TextStyle.BOLD,
7580
'o' to TextStyle.ITALIC,
7681
'n' to TextStyle.UNDERLINED,
7782
'm' to TextStyle.STRIKETHROUGH,
7883
'k' to TextStyle.OBFUSCATED
7984
)
85+
86+
/**
87+
* Converts [TextComponent] to a HTML element.
88+
*/
89+
fun TextComponent.toHtml(): String {
90+
var html = escapeHtml(text).replace(" ", "&nbsp;").replace("\n", "<br />")
91+
92+
if (extra.isNotEmpty()) {
93+
html += extra.joinToString("") { it.toHtml() }
94+
}
95+
96+
if (TextStyle.OBFUSCATED in styles) html = """<span class="obfuscated">$html</span>"""
97+
if (TextStyle.STRIKETHROUGH in styles) html = "<s>$html</s>"
98+
if (TextStyle.UNDERLINED in styles) html = "<u>$html</u>"
99+
if (TextStyle.ITALIC in styles) html = "<i>$html</i>"
100+
if (TextStyle.BOLD in styles) html = "<b>$html</b>"
101+
102+
return if (color.isNotEmpty()) {
103+
"""<span style="color:$color">$html</span>"""
104+
} else {
105+
html
106+
}
107+
}
108+
109+
private fun escapeHtml(text: String): String = buildString {
110+
for (c in text) {
111+
when (c) {
112+
'<' -> append("&lt;")
113+
'>' -> append("&gt;")
114+
'&' -> append("&amp;")
115+
'"' -> append("&quot;")
116+
'\'' -> append("&#39;")
117+
else -> append(c)
118+
}
119+
}
120+
}

src/test/kotlin/tech/aliorpse/mcutils/player/PlayerProfileTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package tech.aliorpse.mcutils.player
22

3+
import kotlinx.coroutines.runBlocking
34
import tech.aliorpse.mcutils.modules.player.Player
45
import kotlin.test.Test
56

@@ -9,7 +10,7 @@ class PlayerProfileTest {
910
*/
1011
@Test
1112
fun getProfileTest() {
12-
val result = Player.getProfileBlocking("ec042e1200ac4a249cc83eb1fab0bd88")
13+
val result = runBlocking { Player.getProfile("ec042e1200ac4a249cc83eb1fab0bd88") }
1314
println(result)
1415
assert(result.name.isNotEmpty())
1516
}

src/test/kotlin/tech/aliorpse/mcutils/server/ServerStatusTest.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
package tech.aliorpse.mcutils.server
22

3-
import kotlinx.coroutines.Dispatchers
43
import kotlinx.coroutines.runBlocking
5-
import kotlinx.coroutines.withContext
64
import tech.aliorpse.mcutils.modules.server.BedrockServer
75
import tech.aliorpse.mcutils.modules.server.JavaServer
6+
import tech.aliorpse.mcutils.utils.toHtml
87
import kotlin.test.Test
98

109
class ServerStatusTest {
1110
@Test
1211
fun javaGetStatusTest() {
13-
val result = runBlocking { JavaServer.getStatus("wdsj.net") }
12+
val result = runBlocking { JavaServer.getStatus("hypixel.net") }
1413

15-
println(result)
14+
println(result.description.toHtml())
1615
assert(result.version.protocol > 0)
1716
}
1817

0 commit comments

Comments
 (0)