blob: ed486f53e08947f3c635b9f3a6a50724e1192285 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
package moe.nea.firmament.features.texturepack
import java.util.regex.Matcher
import util.json.CodecSerializer
import kotlinx.serialization.Serializable
import net.minecraft.network.chat.Style
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.ComponentSerialization
import moe.nea.firmament.util.directLiteralStringContent
import moe.nea.firmament.util.transformEachRecursively
@Serializable
data class TreeishTextReplacer(
val match: StringMatcher,
val replacements: List<SubPartReplacement>
) {
@Serializable
data class SubPartReplacement(
val match: StringMatcher,
val style: @Serializable(StyleSerializer::class) Style? = null,
val replace: @Serializable(TextSerializer::class) Component,
)
object TextSerializer : CodecSerializer<Component>(ComponentSerialization.CODEC)
object StyleSerializer : CodecSerializer<Style>(Style.Serializer.CODEC)
companion object {
val pattern = "[$]\\{(?<name>[^}]+)}".toPattern()
fun injectMatchResults(text: Component, matches: Matcher): Component {
return text.transformEachRecursively { it ->
val content = it.directLiteralStringContent ?: return@transformEachRecursively it
val matcher = pattern.matcher(content)
val builder = StringBuilder()
while (matcher.find()) {
matcher.appendReplacement(builder, matches.group(matcher.group("name")).toString())
}
matcher.appendTail(builder)
Component.literal(builder.toString()).setStyle(it.style)
}
}
}
fun match(text: Component): Boolean {
return match.matches(text)
}
fun replaceText(text: Component): Component {
return text.transformEachRecursively { part ->
var part: Component = part
for (replacement in replacements) {
val rawPartText = part.string
replacement.style?.let { expectedStyle ->
val parentStyle = part.style
val parented = expectedStyle.applyTo(parentStyle)
if (parented.isStrikethrough != parentStyle.isStrikethrough
|| parented.isObfuscated != parentStyle.isObfuscated
|| parented.isBold != parentStyle.isBold
|| parented.isUnderlined != parentStyle.isUnderlined
|| parented.isItalic != parentStyle.isItalic
|| parented.color?.value != parentStyle.color?.value)
continue
}
val matcher = replacement.match.asRegex.matcher(rawPartText)
if (!matcher.find()) continue
val p = Component.literal("")
p.setStyle(part.style)
var lastAppendPosition = 0
do {
p.append(rawPartText.substring(lastAppendPosition, matcher.start()))
lastAppendPosition = matcher.end()
p.append(injectMatchResults(replacement.replace, matcher))
} while (matcher.find())
p.append(rawPartText.substring(lastAppendPosition))
part = p
}
part
}
}
}
|