From c4587423fd139604062f162d93e0b6e303cbe8fb Mon Sep 17 00:00:00 2001 From: Gabber235 Date: Sun, 29 Sep 2024 14:39:54 +0200 Subject: [PATCH] Create BlockCommandCinematicEntry --- .../entry/cinematic/CinematicSequence.kt | 5 +- .../paper/interaction/ChatHistoryHandler.kt | 11 +- .../cinematic/BlockCommandCinematicEntry.kt | 102 ++++++++++++++++++ .../entries/cinematic/SkipCinematicEntry.kt | 5 +- 4 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/BlockCommandCinematicEntry.kt diff --git a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/cinematic/CinematicSequence.kt b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/cinematic/CinematicSequence.kt index 293f4e9fab..2aa310ead1 100644 --- a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/cinematic/CinematicSequence.kt +++ b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/cinematic/CinematicSequence.kt @@ -90,7 +90,10 @@ class CinematicSequence( state = ENDING val originalFrame = frame - if (settings.blockChatMessages) player.stopBlockingMessages() + if (settings.blockChatMessages) { + player.stopBlockingMessages() + player.chatHistory.resendMessages(player) + } if (settings.blockActionBarMessages) player.stopBlockingActionBar() actions.forEach { diff --git a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/interaction/ChatHistoryHandler.kt b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/interaction/ChatHistoryHandler.kt index 6a4b42d096..48fb48e659 100644 --- a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/interaction/ChatHistoryHandler.kt +++ b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/interaction/ChatHistoryHandler.kt @@ -9,11 +9,10 @@ import com.github.retrooper.packetevents.protocol.packettype.PacketType import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChatMessage import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSystemChatMessage import com.github.shynixn.mccoroutine.bukkit.registerSuspendingEvents -import lirand.api.extensions.server.server import com.typewritermc.engine.paper.plugin import com.typewritermc.engine.paper.snippets.snippet import com.typewritermc.engine.paper.utils.plainText -import io.papermc.paper.event.player.AsyncChatEvent +import lirand.api.extensions.server.server import net.kyori.adventure.text.Component import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.format.TextColor @@ -27,7 +26,11 @@ import java.util.* import java.util.concurrent.ConcurrentLinkedQueue import kotlin.math.min -private val darkenLimit by snippet("chat.darken-limit", 12, "The amount of messages displayed in the chat history during a dialogue") +private val darkenLimit by snippet( + "chat.darken-limit", + 12, + "The amount of messages displayed in the chat history during a dialogue" +) private val spacing by snippet("chat.spacing", 3, "The amount of padding between the dialogue and the chat history") class ChatHistoryHandler : @@ -60,11 +63,13 @@ class ChatHistoryHandler : val message = packet.message as? ChatMessage_v1_19_3 ?: return packet.message.chatContent message.unsignedChatContent.orElseGet { message.chatContent } } + PacketType.Play.Server.SYSTEM_CHAT_MESSAGE -> { val packet = WrapperPlayServerSystemChatMessage(event) if (packet.isOverlay) return null packet.message } + else -> null } } diff --git a/extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/BlockCommandCinematicEntry.kt b/extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/BlockCommandCinematicEntry.kt new file mode 100644 index 0000000000..eb55fe3c2a --- /dev/null +++ b/extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/BlockCommandCinematicEntry.kt @@ -0,0 +1,102 @@ +package com.typewritermc.basic.entries.cinematic + +import com.github.retrooper.packetevents.protocol.packettype.PacketType +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientChatCommand +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientChatCommandUnsigned +import com.typewritermc.core.books.pages.Colors +import com.typewritermc.core.extension.annotations.Entry +import com.typewritermc.core.extension.annotations.Help +import com.typewritermc.core.extension.annotations.Regex +import com.typewritermc.core.extension.annotations.Segments +import com.typewritermc.engine.paper.entry.Criteria +import com.typewritermc.engine.paper.entry.cinematic.SimpleCinematicAction +import com.typewritermc.engine.paper.entry.entries.CinematicAction +import com.typewritermc.engine.paper.entry.entries.CinematicEntry +import com.typewritermc.engine.paper.entry.entries.Segment +import com.typewritermc.engine.paper.interaction.InterceptionBundle +import com.typewritermc.engine.paper.interaction.interceptPackets +import com.typewritermc.engine.paper.utils.ThreadType +import org.bukkit.entity.Player + +@Entry("block_command_cinematic", "Block commands during the cinematic", Colors.RED, "mdi:console") +/** + * The `Block Command Cinematic` entry is used to block commands during the cinematic. + * + * The `/typewriter` command is always allowed. + * + * ## How could this be used? + * + * This could be used to block commands during a cinematic. + */ +class BlockCommandCinematicEntry( + override val id: String = "", + override val name: String = "", + override val criteria: List = emptyList(), + @Segments(Colors.RED, "mdi:console") + val segments: List = emptyList(), +) : CinematicEntry { + override fun create(player: Player): CinematicAction = BlockCommandCinematicAction(player, this) +} + +data class BlockCommandSegment( + override val startFrame: Int = 0, + override val endFrame: Int = 0, + @Regex + @Help("No need to include the slash. For example, use `say` instead of `/say`") + val allowedCommands: List = emptyList(), +) : Segment + +class BlockCommandCinematicAction( + private val player: Player, + entry: BlockCommandCinematicEntry, +) : SimpleCinematicAction() { + override val segments: List = entry.segments + + private var bundle: InterceptionBundle? = null + private val ranCommands = mutableListOf() + + override suspend fun startSegment(segment: BlockCommandSegment) { + super.startSegment(segment) + bundle = player.interceptPackets { + PacketType.Play.Client.CHAT_COMMAND { event -> + val packet = WrapperPlayClientChatCommand(event) + if (isAllowedCommand(segment, packet.command)) { + return@CHAT_COMMAND + } + ranCommands.add(packet.command) + event.isCancelled = true + } + + PacketType.Play.Client.CHAT_COMMAND_UNSIGNED { event -> + val packet = WrapperPlayClientChatCommandUnsigned(event) + if (isAllowedCommand(segment, packet.command)) { + return@CHAT_COMMAND_UNSIGNED + } + ranCommands.add(packet.command) + event.isCancelled = true + } + } + } + + override suspend fun stopSegment(segment: BlockCommandSegment) { + super.stopSegment(segment) + bundle?.cancel() + bundle = null + if (ranCommands.isNotEmpty()) { + ThreadType.SYNC.switchContext { + ranCommands.forEach { + player.performCommand(it) + } + } + } + ranCommands.clear() + } + + private fun isAllowedCommand(segment: BlockCommandSegment, command: String): Boolean { + if (command.startsWith("tw")) return true + if (command.startsWith("typewriter")) return true + return segment.allowedCommands.any { allowedCommand -> + Regex(allowedCommand).matches(command) + } + } +} \ No newline at end of file diff --git a/extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/SkipCinematicEntry.kt b/extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/SkipCinematicEntry.kt index 4b14337181..00affd6d35 100644 --- a/extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/SkipCinematicEntry.kt +++ b/extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/SkipCinematicEntry.kt @@ -1,9 +1,7 @@ package com.typewritermc.basic.entries.cinematic import com.github.retrooper.packetevents.protocol.packettype.PacketType.Play -import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientClickWindow import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction -import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientHeldItemChange import com.typewritermc.core.books.pages.Colors import com.typewritermc.core.extension.annotations.Entry import com.typewritermc.core.extension.annotations.Segments @@ -108,7 +106,8 @@ class SkipCinematicAction( } } -class CinematicSkippableEvent(player: Player, val canSkip: Boolean, val confirmationKey: SkipConfirmationKey) : PlayerEvent(player, !Bukkit.isPrimaryThread()) { +class CinematicSkippableEvent(player: Player, val canSkip: Boolean, val confirmationKey: SkipConfirmationKey) : + PlayerEvent(player, !Bukkit.isPrimaryThread()) { override fun getHandlers(): HandlerList = HANDLER_LIST companion object {