mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-01 14:39:13 -06:00
Merge branch 'escapeTags' into 'master'
The sign "<" now displays in global and more short-hands %R %U Closes #2611 See merge request 2009scape/2009scape!2492
This commit is contained in:
commit
7f3ce3e02c
2 changed files with 85 additions and 12 deletions
|
|
@ -4,9 +4,29 @@ import kotlin.math.ceil
|
|||
|
||||
object DialUtils {
|
||||
val tagRegex = "<([A-Za-z0-9=/]+)>".toRegex()
|
||||
private val visibleCharacterTags = setOf("<lt>", "<gt>", "<nbsp>", "<shy>", "<times>", "<euro>", "<copy>", "<reg>")
|
||||
private val formattingTags = setOf("col", "shad", "u", "str", "trans")
|
||||
|
||||
fun removeMatches(message: String, regex: Regex): String {
|
||||
return regex.replace(message, "")
|
||||
fun renderedLength(message: String): Int {
|
||||
var length = 0
|
||||
var position = 0
|
||||
|
||||
for (match in tagRegex.findAll(message)) {
|
||||
length += match.range.first - position
|
||||
length += when {
|
||||
match.value == "<img=2>" -> 2
|
||||
match.value.startsWith("<img=") -> 1
|
||||
match.value in visibleCharacterTags -> 1
|
||||
else -> 0
|
||||
}
|
||||
position = match.range.last + 1
|
||||
}
|
||||
|
||||
return length + message.length - position
|
||||
}
|
||||
|
||||
fun isFormattingTag(tag: String): Boolean {
|
||||
return tag.removePrefix("<").removePrefix("/").substringBefore("=").substringBefore(">") in formattingTags
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -15,7 +35,7 @@ object DialUtils {
|
|||
* Should this not work out for any reason, you should fallback to standard npc and player methods for dialogue.
|
||||
*/
|
||||
fun splitLines(message: String, perLineLimit: Int = 54): Array<String> {
|
||||
var lines = Array(ceil(DialUtils.removeMatches(message, DialUtils.tagRegex).length / perLineLimit.toFloat()).toInt()) { "" }
|
||||
var lines = Array(ceil(DialUtils.renderedLength(message) / perLineLimit.toFloat()).toInt()) { "" }
|
||||
|
||||
//short circuit when possible because it's cheaper.
|
||||
if (lines.size == 1) {
|
||||
|
|
@ -45,7 +65,7 @@ fun splitLines(message: String, perLineLimit: Int = 54): Array<String> {
|
|||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (DialUtils.isFormattingTag(lineTag.value)) {
|
||||
openTags.add(lineTag.value)
|
||||
}
|
||||
}
|
||||
|
|
@ -65,11 +85,14 @@ fun splitLines(message: String, perLineLimit: Int = 54): Array<String> {
|
|||
}
|
||||
|
||||
while (!tokenQueue.isEmpty()) {
|
||||
val shouldSpace = DialUtils.removeMatches(line.toString(), DialUtils.tagRegex).isNotEmpty()
|
||||
accumulator += DialUtils.removeMatches(tokenQueue.peek(), DialUtils.tagRegex).length
|
||||
val shouldSpace = DialUtils.renderedLength(line.toString()) > 0
|
||||
accumulator += DialUtils.renderedLength(tokenQueue.peek())
|
||||
|
||||
if (shouldSpace) accumulator += 1
|
||||
if (accumulator > perLineLimit) {
|
||||
if (line.isEmpty()) {
|
||||
line.append(tokenQueue.pop())
|
||||
}
|
||||
pushLine()
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import core.api.sendMessage
|
|||
import core.api.setAttribute
|
||||
import core.game.system.command.Privilege
|
||||
import core.game.world.repository.Repository
|
||||
import core.game.node.entity.player.info.Rights
|
||||
import core.tools.colorize
|
||||
|
||||
class GlobalChat : Commands {
|
||||
|
|
@ -21,9 +20,34 @@ class GlobalChat : Commands {
|
|||
|
||||
companion object {
|
||||
val ATTR_GLOBAL_MUTE = "/save:globalmute"
|
||||
fun process(sender: String, message: String, rights: Int) {
|
||||
val msgSD = prepare(sender, message, false, rights)
|
||||
val msgHD = prepare(sender, message, true, rights)
|
||||
private val ANGLE_BRACKETS = Regex("[<>]")
|
||||
private val COLORED_STYLE = Regex("%(u|str|shad)=([0-9a-fA-F]{6})")
|
||||
private val TRANSPARENCY = Regex("%trans=([0-9]{1,3})")
|
||||
private val COMMON_SHORTCUTS = mapOf(
|
||||
"%ironman" to "<img=4>",
|
||||
"%chat" to "<img=3>",
|
||||
"%hcim" to "<img=5>",
|
||||
"%uim" to "<img=6>",
|
||||
"%/trans" to "</trans>",
|
||||
"%trans" to "<trans=128>",
|
||||
"%/shad" to "</shad>",
|
||||
"%shad" to "<shad>",
|
||||
"%/str" to "</str>",
|
||||
"%str" to "<str>",
|
||||
"%/u" to "</u>",
|
||||
"%u" to "<u>",
|
||||
"%<gt><gt>" to "<img=2>"
|
||||
)
|
||||
private val COMMON_SHORTCUT_PATTERN = Regex("%ironman|%chat|%hcim|%uim|%/trans|%trans(?!=)|%/shad|%shad(?!=)|%/str|%str(?!=)|%/u|%u(?!=)|%<gt><gt>")
|
||||
private const val MAX_ENCODED_MESSAGE_LENGTH = 255
|
||||
|
||||
fun process(sender: String, message: String, chatIcon: Int) {
|
||||
val msgSD = prepare(sender, message, false, chatIcon)
|
||||
val msgHD = prepare(sender, message, true, chatIcon)
|
||||
if (msgSD.length > MAX_ENCODED_MESSAGE_LENGTH || msgHD.length > MAX_ENCODED_MESSAGE_LENGTH) {
|
||||
return
|
||||
}
|
||||
|
||||
for (player in Repository.players.filter { !getAttribute(it, ATTR_GLOBAL_MUTE, false) }) {
|
||||
if (player.interfaceManager.isResizable)
|
||||
sendMessage(player, msgHD)
|
||||
|
|
@ -32,10 +56,36 @@ class GlobalChat : Commands {
|
|||
}
|
||||
}
|
||||
|
||||
private fun prepare(sender: String, message: String, isResizable: Boolean, rights: Int): String {
|
||||
private fun prepare(sender: String, message: String, isResizable: Boolean, chatIcon: Int): String {
|
||||
val baseColor = if (isResizable) "%f1b04c" else "%7512ff"
|
||||
val bracketColor = if (isResizable) "%ffffff" else "%000000"
|
||||
return colorize("$bracketColor[${baseColor}G$bracketColor] ${if (rights > 0) "<img=${rights - 1}>" else ""}$sender: ${baseColor}$message")
|
||||
val formattedMessage = formatPlayerMessage(message, chatIcon)
|
||||
return colorize("$bracketColor[${baseColor}G$bracketColor] ${if (chatIcon > 0) "<img=${chatIcon - 1}>" else ""}$sender: ${baseColor}$formattedMessage")
|
||||
}
|
||||
|
||||
private fun formatPlayerMessage(message: String, chatIcon: Int): String {
|
||||
var formatted = ANGLE_BRACKETS.replace(message) {
|
||||
if (it.value == "<") "<lt>" else "<gt>"
|
||||
}
|
||||
|
||||
formatted = COLORED_STYLE.replace(formatted) {
|
||||
"<${it.groupValues[1]}=${it.groupValues[2]}>"
|
||||
}
|
||||
formatted = TRANSPARENCY.replace(formatted) {
|
||||
val transparency = it.groupValues[1].toInt()
|
||||
if (transparency in 0..255) "<trans=$transparency>" else it.value
|
||||
}
|
||||
|
||||
formatted = COMMON_SHORTCUT_PATTERN.replace(formatted) {
|
||||
COMMON_SHORTCUTS[it.value] ?: it.value
|
||||
}
|
||||
|
||||
if (chatIcon == 1 || chatIcon == 2)
|
||||
formatted = formatted.replace("%mod", "<img=0>")
|
||||
if (chatIcon == 2)
|
||||
formatted = formatted.replace("%admin", "<img=1>")
|
||||
|
||||
return formatted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue