diff options
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/utils/chat')
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/utils/chat/ChatClickActionManager.kt | 36 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt | 101 |
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" + } + +} |