aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/utils/chat
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/utils/chat')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/chat/ChatClickActionManager.kt36
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt101
2 files changed, 137 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/chat/ChatClickActionManager.kt b/src/main/java/at/hannibal2/skyhanni/utils/chat/ChatClickActionManager.kt
new file mode 100644
index 000000000..17264a020
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/chat/ChatClickActionManager.kt
@@ -0,0 +1,36 @@
+package at.hannibal2.skyhanni.utils.chat
+
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.StringUtils
+
+object ChatClickActionManager {
+
+ private val actions = mutableMapOf<String, ClickableAction>()
+
+ fun createAction(onClick: () -> Any, expiresAt: SimpleTimeMark, oneTime: Boolean = true): String {
+ val token = StringUtils.generateRandomId()
+ actions[token] = ClickableAction(onClick, oneTime, expiresAt)
+ return token
+ }
+
+ fun onCommand(args: Array<String>) {
+ if (args.size == 1) {
+ actions[args.first()]?.apply {
+ if (expiresAt.isInPast()) {
+ actions.remove(args.first())
+ return
+ }
+ onClick()
+ if (oneTime) {
+ actions.remove(args.first())
+ }
+ }
+ }
+ }
+
+ class ClickableAction(
+ val onClick: () -> Any,
+ val oneTime: Boolean = true,
+ val expiresAt: SimpleTimeMark = SimpleTimeMark.farFuture(),
+ )
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt b/src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt
new file mode 100644
index 000000000..5bec46867
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt
@@ -0,0 +1,101 @@
+package at.hannibal2.skyhanni.utils.chat
+
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import net.minecraft.client.Minecraft
+import net.minecraft.event.ClickEvent
+import net.minecraft.event.HoverEvent
+import net.minecraft.util.ChatComponentText
+import net.minecraft.util.ChatStyle
+import net.minecraft.util.IChatComponent
+
+object Text {
+
+ val NEWLINE = "\n".asComponent()
+ val HYPHEN = "-".asComponent()
+ val SPACE = " ".asComponent()
+ val EMPTY = "".asComponent()
+
+ fun text(text: String, init: IChatComponent.() -> Unit = {}) = text.asComponent(init)
+ fun String.asComponent(init: IChatComponent.() -> Unit = {}) = ChatComponentText(this).also(init)
+
+ fun multiline(vararg lines: Any?) = join(*lines, separator = NEWLINE)
+ fun join(vararg components: Any?, separator: IChatComponent? = null): IChatComponent {
+ val result = ChatComponentText("")
+ components.forEachIndexed { index, it ->
+ when (it) {
+ is IChatComponent -> result.appendSibling(it)
+ is String -> result.appendText(it)
+ is List<*> -> result.appendSibling(join(*it.toTypedArray(), separator = separator))
+ null -> return@forEachIndexed
+ else -> error("Unsupported type: ${it::class.simpleName}")
+ }
+
+ if (index < components.size - 1 && separator != null) {
+ result.appendSibling(separator)
+ }
+ }
+ return result
+ }
+
+ fun IChatComponent.style(init: ChatStyle.() -> Unit): IChatComponent {
+ this.chatStyle.init()
+ return this
+ }
+
+ fun IChatComponent.prefix(prefix: String): IChatComponent = join(prefix, this)
+ fun IChatComponent.suffix(suffix: String): IChatComponent = join(this, suffix)
+ fun IChatComponent.wrap(prefix: String, suffix: String) = this.prefix(prefix).suffix(suffix)
+
+ fun IChatComponent.width(): Int = Minecraft.getMinecraft().fontRendererObj.getStringWidth(this.formattedText)
+
+ fun IChatComponent.fitToChat(): IChatComponent {
+ val width = this.width()
+ val maxWidth = Minecraft.getMinecraft().ingameGUI.chatGUI.chatWidth
+ if (width < maxWidth) {
+ val repeat = maxWidth / width
+ val component = ChatComponentText("")
+ repeat(repeat) { component.appendSibling(this) }
+ return component
+ }
+ return this
+ }
+ fun IChatComponent.center(width: Int = Minecraft.getMinecraft().ingameGUI.chatGUI.chatWidth): IChatComponent {
+ val textWidth = this.width()
+ val spaceWidth = SPACE.width()
+ val padding = (width - textWidth) / 2
+ return join(" ".repeat(padding / spaceWidth), this)
+ }
+
+ fun IChatComponent.send(id: Int = 0) =
+ Minecraft.getMinecraft().ingameGUI.chatGUI.printChatMessageWithOptionalDeletion(this, id)
+
+ var IChatComponent.hover: IChatComponent?
+ get() = this.chatStyle.chatHoverEvent?.value
+ set(value) {
+ this.chatStyle.chatHoverEvent = value?.let { HoverEvent(HoverEvent.Action.SHOW_TEXT, it) }
+ }
+
+ var IChatComponent.command: String?
+ get() = this.chatStyle.chatClickEvent?.let { if (it.action == ClickEvent.Action.RUN_COMMAND) it.value else null }
+ set(value) {
+ this.chatStyle.chatClickEvent = value?.let { ClickEvent(ClickEvent.Action.RUN_COMMAND, it) }
+ }
+
+ var IChatComponent.suggest: String?
+ get() = this.chatStyle.chatClickEvent?.let { if (it.action == ClickEvent.Action.SUGGEST_COMMAND) it.value else null }
+ set(value) {
+ this.chatStyle.chatClickEvent = value?.let { ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, it) }
+ }
+
+ var IChatComponent.url: String?
+ get() = this.chatStyle.chatClickEvent?.let { if (it.action == ClickEvent.Action.OPEN_URL) it.value else null }
+ set(value) {
+ this.chatStyle.chatClickEvent = value?.let { ClickEvent(ClickEvent.Action.OPEN_URL, it) }
+ }
+
+ fun IChatComponent.onClick(expiresAt: SimpleTimeMark = SimpleTimeMark.farFuture(), oneTime: Boolean = true, onClick: () -> Any) {
+ val token = ChatClickActionManager.createAction(onClick, expiresAt, oneTime)
+ this.command = "/shaction $token"
+ }
+
+}