diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96e8908b..3cab809f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: cache gradle packages uses: actions/cache@v4 with: @@ -18,7 +18,7 @@ jobs: - name: validate gradle wrapper uses: gradle/actions/wrapper-validation@v3 - name: setup jdk 8.0 - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: distribution: adopt java-version: 8.0 diff --git a/.gitignore b/.gitignore index 835e8dca..20f76491 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .gradle .idea +.kotlin build \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 15623385..cb327aa0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,10 +1,11 @@ import io.izzel.taboolib.gradle.* +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { java - id("io.izzel.taboolib") version "2.0.23" - id("org.jetbrains.kotlin.jvm") version "2.1.20" + id("io.izzel.taboolib") version "2.0.31" + id("org.jetbrains.kotlin.jvm") version "2.2.20" } subprojects { @@ -35,12 +36,13 @@ subprojects { ) install(JavaScript) install(Bukkit, BungeeCord, Velocity) + modules.remove("minecraft-chat") + disableOnSkippedVersion = false +// disableOnUnsupportedVersion = false } version { - taboolib = "6.2.3-12d4045" + taboolib = "6.2.4-e7fd043" coroutines = null -// isSkipKotlin = true -// isSkipKotlinRelocate = true } } @@ -61,7 +63,7 @@ subprojects { compileOnly(kotlin("stdlib")) compileOnly("com.google.code.gson:gson:2.8.5") compileOnly("com.google.guava:guava:21.0") - compileOnly("net.kyori:adventure-api:4.21.0") + compileOnly("net.kyori:adventure-api:4.26.1") } // 编译配置 @@ -74,9 +76,9 @@ subprojects { options.encoding = "UTF-8" } tasks.withType { - kotlinOptions { - jvmTarget = "1.8" - freeCompilerArgs = listOf("-Xjvm-default=all", "-Xextended-compiler-checks") + compilerOptions { + jvmTarget = JvmTarget.JVM_1_8 + freeCompilerArgs = listOf("-Xjvm-default=all") } } } diff --git a/gradle.properties b/gradle.properties index 9b160314..f17c28e3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,6 @@ group=me.arasple.mc.trchat -version=2.3.5 +version=2.4.1 kotlin.incremental=true kotlin.incremental.java=true -kotlin.incremental.useClasspathSnapshot=true kotlin.caching.enabled=true kotlin.parallel.tasks.in.project=true \ No newline at end of file diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 6f7600b1..388fbe3c 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -15,18 +15,21 @@ taboolib { name("EcoEnchants").with("bukkit").optional(true) name("ItemsAdder").with("bukkit").optional(true) name("Nova").with("bukkit").optional(true) + name("SayanVanish").with("bukkit").optional(true) name("Multiverse-Core").with("bukkit").loadafter(true) name("Geyser-Spigot").with("bukkit").loadafter(true) } +// version { +// isSkipKotlin = true +// isSkipKotlinRelocate = true +// } } relocate("com.eatthepath.uuid.", "${rootProject.group}.library.uuid.") -// relocate("net.md_5.bungee", "net.md_5.bungee121") // relocate("com.electronwill.nightconfig", "com.electronwill.nightconfig_3_6_7") } dependencies { taboo("com.eatthepath:fast-uuid:0.2.0") -// taboo("net.md-5:bungeecord-chat:1.21-R0.3") { isTransitive = false } } tasks { diff --git a/project/common/build.gradle.kts b/project/common/build.gradle.kts index dbb685a5..d4e414f0 100644 --- a/project/common/build.gradle.kts +++ b/project/common/build.gradle.kts @@ -1,5 +1,5 @@ dependencies { -// compileOnly(project(":project:module-chat")) + compileOnly(project(":project:module-chat")) compileOnly("com.eatthepath:fast-uuid:0.2.0") } diff --git a/project/common/src/main/kotlin/me/arasple/mc/trchat/api/ClientMessageManager.kt b/project/common/src/main/kotlin/me/arasple/mc/trchat/api/ClientMessageManager.kt index 8d44c0a1..2ebc9bf5 100644 --- a/project/common/src/main/kotlin/me/arasple/mc/trchat/api/ClientMessageManager.kt +++ b/project/common/src/main/kotlin/me/arasple/mc/trchat/api/ClientMessageManager.kt @@ -13,7 +13,7 @@ interface ClientMessageManager { fun close() = Unit - fun getPlayerNames(): Map + fun getPlayerNames(includeVanish: Boolean = false): Map fun getExactName(name: String): String? diff --git a/project/common/src/main/kotlin/me/arasple/mc/trchat/api/ProxyMessageManager.kt b/project/common/src/main/kotlin/me/arasple/mc/trchat/api/ProxyMessageManager.kt index c76d94f9..8a2d74f5 100644 --- a/project/common/src/main/kotlin/me/arasple/mc/trchat/api/ProxyMessageManager.kt +++ b/project/common/src/main/kotlin/me/arasple/mc/trchat/api/ProxyMessageManager.kt @@ -7,7 +7,7 @@ interface ProxyMessageManager { val executor: ExecutorService - val allNames: MutableMap> + val allNames: MutableMap>> fun sendMessage(recipient: Any, vararg args: String): Future<*> diff --git a/project/common/src/main/kotlin/me/arasple/mc/trchat/util/Cooldown.kt b/project/common/src/main/kotlin/me/arasple/mc/trchat/util/Cooldown.kt index b0702692..97ccc167 100644 --- a/project/common/src/main/kotlin/me/arasple/mc/trchat/util/Cooldown.kt +++ b/project/common/src/main/kotlin/me/arasple/mc/trchat/util/Cooldown.kt @@ -5,7 +5,7 @@ import java.util.concurrent.ConcurrentHashMap object Cooldowns { - private val COOLDOWNS = ConcurrentHashMap() + val COOLDOWNS = ConcurrentHashMap() fun getCooldownLeft(uuid: UUID, type: String): Long { return COOLDOWNS.computeIfAbsent(uuid) { Cooldown() }.data.getOrDefault(type, 0L) - System.currentTimeMillis() @@ -34,6 +34,5 @@ enum class CooldownType(val alias: String) { MENTION_ALL("MentionAll"), INVENTORY_SHOW("InventoryShow"), ENDERCHEST_SHOW("EnderChestShow"), - IMAGE_SHOW("ImageShow") } \ No newline at end of file diff --git a/project/common/src/main/kotlin/me/arasple/mc/trchat/util/Util.kt b/project/common/src/main/kotlin/me/arasple/mc/trchat/util/Util.kt index 11c1af73..308466ed 100644 --- a/project/common/src/main/kotlin/me/arasple/mc/trchat/util/Util.kt +++ b/project/common/src/main/kotlin/me/arasple/mc/trchat/util/Util.kt @@ -11,6 +11,15 @@ private val reportedErrors = mutableListOf() val nilUUID = UUID(0, 0) val papiRegex = "(%)(.+?)(%)|(:)(.+?)(:)|(?!\\{\")((\\{)(.+?)(}))".toRegex() +fun hasClass(className: String): Boolean { + return try { + Class.forName(className) + true + } catch (_: ClassNotFoundException) { + false + } +} + fun Throwable.print(title: String, printStackTrace: Boolean = true) { console().sendMessage("§c[TrChat] §7$title") console().sendMessage("§7${javaClass.name}: $localizedMessage") diff --git a/project/module-adventure/build.gradle.kts b/project/module-adventure/build.gradle.kts index c26647de..55a063cb 100644 --- a/project/module-adventure/build.gradle.kts +++ b/project/module-adventure/build.gradle.kts @@ -1,8 +1,9 @@ dependencies { compileOnly(project(":project:common")) -// compileOnly(project(":project:module-chat")) - compileOnly("net.kyori:adventure-platform-bukkit:4.4.0") - compileOnly("net.kyori:adventure-text-serializer-plain:4.21.0") + compileOnly(project(":project:module-chat")) + compileOnly("net.kyori:adventure-platform-bukkit:4.4.1") + compileOnly("net.kyori:adventure-text-serializer-plain:4.26.1") + implementation("net.kyori:adventure-text-minimessage:4.26.1") // paper native compileOnly(fileTree(rootDir.resolve("libs"))) } diff --git a/project/module-adventure/src/main/kotlin/me/arasple/mc/trchat/module/adventure/Adventure.kt b/project/module-adventure/src/main/kotlin/me/arasple/mc/trchat/module/adventure/Adventure.kt index cdfcfa50..bfe9a065 100644 --- a/project/module-adventure/src/main/kotlin/me/arasple/mc/trchat/module/adventure/Adventure.kt +++ b/project/module-adventure/src/main/kotlin/me/arasple/mc/trchat/module/adventure/Adventure.kt @@ -1,6 +1,7 @@ package me.arasple.mc.trchat.module.adventure import net.kyori.adventure.text.Component +import net.kyori.adventure.text.minimessage.MiniMessage import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer @@ -27,6 +28,12 @@ private val plainSerializer: Any? = try { null } +val miniMessage: Any? = try { + MiniMessage.miniMessage() +} catch (_: Throwable) { + null +} + fun gson(component: Component) = (gsonSerializer as GsonComponentSerializer).serialize(component) fun gson(string: String) = (gsonSerializer as GsonComponentSerializer).deserialize(string) @@ -47,4 +54,14 @@ fun ComponentText.hoverItemAdventure(item: ItemStack): ComponentText { this as? AdventureComponent ?: error("Unsupported component type.") this.latest.hoverEvent(item.asHoverEvent()) return this +} + +fun String.parseMiniMessage(): ComponentText { + val mm = miniMessage as? MiniMessage ?: return Components.text("No MiniMessage support in your environment!") + val component = mm.deserialize(this) + return if (Components.useAdventure) { + AdventureComponent(component) + } else { + Components.parseRaw(gson(component)) + } } \ No newline at end of file diff --git a/project/module-chat/build.gradle.kts b/project/module-chat/build.gradle.kts index 27a20c2c..1b42b8b0 100644 --- a/project/module-chat/build.gradle.kts +++ b/project/module-chat/build.gradle.kts @@ -1,8 +1,8 @@ dependencies { compileOnly("com.google.code.gson:gson:2.8.7") - compileOnly("net.md-5:bungeecord-api:1.21-R0.3") - compileOnly("net.kyori:adventure-platform-bukkit:4.4.0") - compileOnly("net.kyori:adventure-text-serializer-plain:4.21.0") + compileOnly("net.md-5:bungeecord-api:1.21-R0.4") + compileOnly("net.kyori:adventure-platform-bukkit:4.4.1") + compileOnly("net.kyori:adventure-text-serializer-plain:4.26.1") } taboolib { subproject = true } \ No newline at end of file diff --git a/project/module-chat/src/main/kotlin/taboolib/module/chat/ComponentText.kt b/project/module-chat/src/main/kotlin/taboolib/module/chat/ComponentText.kt index 776aa3ae..c523b968 100644 --- a/project/module-chat/src/main/kotlin/taboolib/module/chat/ComponentText.kt +++ b/project/module-chat/src/main/kotlin/taboolib/module/chat/ComponentText.kt @@ -1,6 +1,7 @@ package taboolib.module.chat import java.awt.Color +import java.util.* /** * TabooLib @@ -45,6 +46,9 @@ interface ComponentText : Source { /** 添加选择器文本块 */ fun appendSelector(selector: String): ComponentText + /** 添加玩家头像文本块 */ + fun appendHead(name: String? = null, id: UUID? = null, hat: Boolean = true, texture: String? = null): ComponentText + /** 显示文本 */ fun hoverText(text: String): ComponentText diff --git a/project/module-chat/src/main/kotlin/taboolib/module/chat/impl/AdventureComponent.kt b/project/module-chat/src/main/kotlin/taboolib/module/chat/impl/AdventureComponent.kt index d3cef6e5..775e9739 100644 --- a/project/module-chat/src/main/kotlin/taboolib/module/chat/impl/AdventureComponent.kt +++ b/project/module-chat/src/main/kotlin/taboolib/module/chat/impl/AdventureComponent.kt @@ -9,6 +9,7 @@ import net.kyori.adventure.text.event.ClickEvent import net.kyori.adventure.text.event.HoverEvent import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextDecoration +import net.kyori.adventure.text.`object`.ObjectContents import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer @@ -114,6 +115,19 @@ class AdventureComponent() : ComponentText { return this } + override fun appendHead(name: String?, id: UUID?, hat: Boolean, texture: String?): ComponentText { + flush() + latest += Component.`object`(ObjectContents.playerHead().also { + it.name(name) + it.id(id) + it.hat(hat) + if (texture != null) { + it.texture(Key.key(texture)) + } + }.build()) + return this + } + override fun hoverText(text: String): ComponentText { return hoverText(ComponentText.of(text)) } diff --git a/project/module-chat/src/main/kotlin/taboolib/module/chat/impl/DefaultComponent.kt b/project/module-chat/src/main/kotlin/taboolib/module/chat/impl/DefaultComponent.kt index f41f0b4e..d07d89e3 100644 --- a/project/module-chat/src/main/kotlin/taboolib/module/chat/impl/DefaultComponent.kt +++ b/project/module-chat/src/main/kotlin/taboolib/module/chat/impl/DefaultComponent.kt @@ -6,6 +6,8 @@ import net.md_5.bungee.api.chat.* import net.md_5.bungee.api.chat.hover.content.Entity import net.md_5.bungee.api.chat.hover.content.Item import net.md_5.bungee.api.chat.hover.content.Text +import net.md_5.bungee.api.chat.objects.PlayerObject +import net.md_5.bungee.api.chat.player.Profile import net.md_5.bungee.chat.ComponentSerializer import taboolib.common.UnsupportedVersionException import taboolib.common.platform.ProxyCommandSender @@ -13,6 +15,7 @@ import taboolib.common.platform.ProxyPlayer import taboolib.common.platform.function.onlinePlayers import taboolib.module.chat.* import java.awt.Color +import java.util.* /** * TabooLib @@ -125,6 +128,12 @@ class DefaultComponent() : ComponentText { return this } + override fun appendHead(name: String?, id: UUID?, hat: Boolean, texture: String?): ComponentText { + flush() + latest += ObjectComponent(PlayerObject(Profile(name, id, null), hat)) + return this + } + override fun hoverText(text: String): ComponentText { return hoverText(ComponentText.of(text)) } diff --git a/project/module-compat/build.gradle.kts b/project/module-compat/build.gradle.kts index 62f4ed45..1ffee8b1 100644 --- a/project/module-compat/build.gradle.kts +++ b/project/module-compat/build.gradle.kts @@ -2,22 +2,25 @@ repositories { maven("https://maven.devs.beer/") maven("https://nexus.scarsz.me/content/groups/public/") maven("https://repo.oraxen.com/releases") + maven("https://repo.sayandev.org/snapshots") // maven("https://repo.nexomc.com/releases") } dependencies { compileOnly(project(":project:common")) -// compileOnly(project(":project:module-chat")) - compileOnly("ink.ptms.core:v12005:12005:universal") + compileOnly(project(":project:module-chat")) + compileOnly("ink.ptms.core:v12107:12107:universal") compileOnly("com.discordsrv:discordsrv:1.26.0") { isTransitive = false } compileOnly("com.willfp:eco:6.35.1") { isTransitive = false } compileOnly("dev.lone:api-itemsadder:4.0.10") { isTransitive = false } +// compileOnly("io.th0rgal:oraxen:1.170.0") { isTransitive = false } // compileOnly("com.nexomc:nexo:0.7.0") - compileOnly("xyz.xenondevs.nova:nova-api:0.12.13") { isTransitive = false } - compileOnly("io.th0rgal:oraxen:1.170.0") { isTransitive = false } + + compileOnly("org.sayandev:sayanvanish-api:1.7.0-SNAPSHOT") { isTransitive = false } + compileOnly("org.sayandev:sayanvanish-bukkit:1.7.0-SNAPSHOT") { isTransitive = false } } taboolib { subproject = true } \ No newline at end of file diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/Hook.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/Hook.kt new file mode 100644 index 00000000..241ba273 --- /dev/null +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/Hook.kt @@ -0,0 +1,6 @@ +package me.arasple.mc.trchat.module.internal.hook + +import taboolib.common.platform.Platform + +@Target(AnnotationTarget.CLASS) +annotation class Hook(val platforms: Array = []) diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/HookPlugin.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/HookPlugin.kt index 8df3adec..cb07a239 100644 --- a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/HookPlugin.kt +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/HookPlugin.kt @@ -1,15 +1,12 @@ package me.arasple.mc.trchat.module.internal.hook -import me.arasple.mc.trchat.module.internal.hook.impl.HookDiscordSRV -import me.arasple.mc.trchat.module.internal.hook.impl.HookEcoEnchants -import me.arasple.mc.trchat.module.internal.hook.impl.HookItemsAdder -import me.arasple.mc.trchat.module.internal.hook.impl.HookNova import me.arasple.mc.trchat.module.internal.hook.type.HookDisplayItem import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack +import taboolib.common.io.runningClassesWithoutLibrary import taboolib.common.platform.Platform -import taboolib.common.platform.PlatformSide import taboolib.common.platform.function.console +import taboolib.common.platform.function.runningPlatform import taboolib.module.lang.sendLang import java.util.function.BiFunction @@ -17,15 +14,13 @@ import java.util.function.BiFunction * @author Arasple * @date 2021/1/26 22:04 */ -@PlatformSide(Platform.BUKKIT) object HookPlugin { - val registry = arrayListOf( - HookDiscordSRV(), - HookEcoEnchants(), - HookItemsAdder(), - HookNova() - ) + val registry = runningClassesWithoutLibrary + .filter { it.hasAnnotation(Hook::class.java) } + .filter { runningPlatform in it.getAnnotation(Hook::class.java).enumList("platforms") } + .map { it.newInstance() as HookAbstract } + .toMutableList() fun printInfo() { registry.filter { it.isHooked }.forEach { @@ -49,21 +44,4 @@ object HookPlugin { } }) } - - fun getDiscordSRV(): HookDiscordSRV { - return registry[0] as HookDiscordSRV - } - - fun getEcoEnchants(): HookEcoEnchants { - return registry[1] as HookEcoEnchants - } - - fun getItemsAdder(): HookItemsAdder { - return registry[2] as HookItemsAdder - } - - fun getNova(): HookNova { - return registry[3] as HookNova - } - } \ No newline at end of file diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/HookUtil.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/HookUtil.kt new file mode 100644 index 00000000..68348c75 --- /dev/null +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/HookUtil.kt @@ -0,0 +1,27 @@ +package me.arasple.mc.trchat.module.internal.hook + +import me.arasple.mc.trchat.module.internal.hook.impl.HookDiscordSRV +import me.arasple.mc.trchat.module.internal.hook.impl.HookItemsAdder +import me.arasple.mc.trchat.module.internal.hook.type.HookVanish +import org.bukkit.Bukkit +import org.bukkit.OfflinePlayer +import taboolib.common.util.unsafeLazy +import java.util.* + +val hookDiscordSRV by unsafeLazy { HookPlugin.registry.filterIsInstance().first() } +val hookItemsAdder by unsafeLazy { HookPlugin.registry.filterIsInstance().first() } + +fun OfflinePlayer.isVanished(): Boolean { + HookPlugin.registry.filterIsInstance().forEach { + if (it.isVanished(this)) return true + } + return false +} + +fun UUID.isVanished(): Boolean { + return Bukkit.getOfflinePlayer(this).isVanished() +} + +fun String.isVanished(): Boolean { + return Bukkit.getOfflinePlayer(this).isVanished() +} \ No newline at end of file diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookDiscordSRV.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookDiscordSRV.kt index 43fb1429..af6d1996 100644 --- a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookDiscordSRV.kt +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookDiscordSRV.kt @@ -1,8 +1,11 @@ package me.arasple.mc.trchat.module.internal.hook.impl import github.scarsz.discordsrv.DiscordSRV +import me.arasple.mc.trchat.module.internal.hook.Hook import me.arasple.mc.trchat.module.internal.hook.HookAbstract +import taboolib.common.platform.Platform +@Hook([Platform.BUKKIT]) class HookDiscordSRV : HookAbstract() { fun registerListener(listener: Any) { diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookEcoEnchants.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookEcoEnchants.kt index 0e477ee3..9aa0d068 100644 --- a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookEcoEnchants.kt +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookEcoEnchants.kt @@ -1,15 +1,18 @@ package me.arasple.mc.trchat.module.internal.hook.impl import com.willfp.eco.core.display.Display +import me.arasple.mc.trchat.module.internal.hook.Hook import me.arasple.mc.trchat.module.internal.hook.type.HookDisplayItem import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack +import taboolib.common.platform.Platform import taboolib.platform.util.isAir /** * @author ItsFlicker * @since 2022/2/5 22:30 */ +@Hook([Platform.BUKKIT]) class HookEcoEnchants : HookDisplayItem() { override fun displayItem(item: ItemStack, player: Player): ItemStack { diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookItemsAdder.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookItemsAdder.kt index fd08f66e..acff96b6 100644 --- a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookItemsAdder.kt +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookItemsAdder.kt @@ -1,13 +1,16 @@ package me.arasple.mc.trchat.module.internal.hook.impl import dev.lone.itemsadder.api.FontImages.FontImageWrapper +import me.arasple.mc.trchat.module.internal.hook.Hook import me.arasple.mc.trchat.module.internal.hook.HookAbstract import org.bukkit.entity.Player +import taboolib.common.platform.Platform /** * @author ItsFlicker * @since 2022/2/5 22:30 */ +@Hook([Platform.BUKKIT]) class HookItemsAdder : HookAbstract() { fun replaceFontImages(message: String, player: Player?): String { diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookNova.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookNova.kt index b4f4b6d2..ba260c1c 100644 --- a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookNova.kt +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookNova.kt @@ -1,8 +1,10 @@ package me.arasple.mc.trchat.module.internal.hook.impl +import me.arasple.mc.trchat.module.internal.hook.Hook import me.arasple.mc.trchat.module.internal.hook.type.HookDisplayItem import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack +import taboolib.common.platform.Platform import taboolib.common.platform.function.adaptPlayer import taboolib.library.xseries.XMaterial import taboolib.module.lang.getLocale @@ -10,6 +12,7 @@ import taboolib.platform.util.buildItem import taboolib.platform.util.isAir import xyz.xenondevs.nova.api.Nova +@Hook([Platform.BUKKIT]) class HookNova : HookDisplayItem() { override fun displayItem(item: ItemStack, player: Player): ItemStack { diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookSayanVanish.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookSayanVanish.kt new file mode 100644 index 00000000..b052ce4a --- /dev/null +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/impl/HookSayanVanish.kt @@ -0,0 +1,19 @@ +package me.arasple.mc.trchat.module.internal.hook.impl + +import me.arasple.mc.trchat.module.internal.hook.Hook +import me.arasple.mc.trchat.module.internal.hook.type.HookVanish +import org.bukkit.OfflinePlayer +import org.sayandev.sayanvanish.bukkit.api.SayanVanishBukkitAPI.Companion.user +import taboolib.common.platform.Platform + +@Hook([Platform.BUKKIT]) +class HookSayanVanish : HookVanish() { + + override fun isVanished(player: OfflinePlayer): Boolean { + if (!isHooked) { + return false + } + return player.user()?.isVanished ?: return false + } + +} \ No newline at end of file diff --git a/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/type/HookVanish.kt b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/type/HookVanish.kt new file mode 100644 index 00000000..ce81b10f --- /dev/null +++ b/project/module-compat/src/main/kotlin/me/arasple/mc/trchat/module/internal/hook/type/HookVanish.kt @@ -0,0 +1,9 @@ +package me.arasple.mc.trchat.module.internal.hook.type + +import me.arasple.mc.trchat.module.internal.hook.HookAbstract +import org.bukkit.OfflinePlayer + +abstract class HookVanish : HookAbstract() { + + abstract fun isVanished(player: OfflinePlayer): Boolean +} \ No newline at end of file diff --git a/project/module-nms/build.gradle.kts b/project/module-nms/build.gradle.kts index b028f4e5..bd4b434d 100644 --- a/project/module-nms/build.gradle.kts +++ b/project/module-nms/build.gradle.kts @@ -1,7 +1,8 @@ dependencies { compileOnly(project(":project:common")) -// compileOnly(project(":project:module-chat")) -// compileOnly("ink.ptms.core:v12105:12105:mapped") + compileOnly(project(":project:module-chat")) +// compileOnly("ink.ptms.core:v12111:12111:mapped") +// compileOnly("ink.ptms.core:v12107:12107:mapped") // compileOnly("ink.ptms.core:v12005:12005:mapped") compileOnly("ink.ptms.core:v12004:12004:mapped") compileOnly("ink.ptms.core:v12002:12002:mapped") diff --git a/project/runtime-bukkit/build.gradle.kts b/project/runtime-bukkit/build.gradle.kts index a7b967d3..19d8ce7b 100644 --- a/project/runtime-bukkit/build.gradle.kts +++ b/project/runtime-bukkit/build.gradle.kts @@ -5,14 +5,14 @@ repositories { dependencies { compileOnly(project(":project:common")) compileOnly(project(":project:module-adventure")) -// compileOnly(project(":project:module-chat")) + compileOnly(project(":project:module-chat")) compileOnly(project(":project:module-compat")) compileOnly(project(":project:module-nms")) compileOnly("ink.ptms.core:v12105:12105:universal") compileOnly("net.md-5:bungeecord-chat:1.21-R0.3") compileOnly(fileTree(rootDir.resolve("libs"))) - compileOnly("me.clip:placeholderapi:2.11.6") { isTransitive = false } + compileOnly("me.clip:placeholderapi:2.11.7") { isTransitive = false } compileOnly("com.discordsrv:discordsrv:1.26.0") { isTransitive = false } } diff --git a/project/runtime-bukkit/src/main/java/me/arasple/mc/trchat/util/color/HexUtils.java b/project/runtime-bukkit/src/main/java/me/arasple/mc/trchat/util/color/HexUtils.java index cffcb4ed..c33de6c2 100644 --- a/project/runtime-bukkit/src/main/java/me/arasple/mc/trchat/util/color/HexUtils.java +++ b/project/runtime-bukkit/src/main/java/me/arasple/mc/trchat/util/color/HexUtils.java @@ -106,33 +106,31 @@ public static String parseRainbow(String message) { int stop = findStop(parsed, matcher.end()); String content = parsed.substring(matcher.end(), stop); - int contentLength = content.length(); - char[] chars = content.toCharArray(); - for (int i = 0; i < chars.length - 1; i++) - if (chars[i] == '&' && "KkLlMmNnOoRr".indexOf(chars[i + 1]) > -1) - contentLength -= 2; - int length = looping ? Math.min(contentLength, CHARS_UNTIL_LOOP) : contentLength; + // 使用 codePoint 遍历,避免 emoji 被拆开 + int length = content.codePointCount(0, content.length()); + if (looping) length = Math.min(length, CHARS_UNTIL_LOOP); - ColorGenerator rainbow; - if (speed == -1) { - rainbow = new Rainbow(length, saturation, brightness); - } else { - rainbow = new AnimatedRainbow(length, saturation, brightness, speed); - } + ColorGenerator rainbow = (speed == -1) + ? new Rainbow(length, saturation, brightness) + : new AnimatedRainbow(length, saturation, brightness, speed); String compoundedFormat = ""; // Carry the format codes through the rainbow gradient - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - if (c == '&' && i + 1 < chars.length) { - char next = chars[i + 1]; + for (int i = 0; i < content.length(); ) { + int cp = content.codePointAt(i); + int charCount = Character.charCount(cp); + + if (cp == '&' && i + 1 < content.length()) { + char next = content.charAt(i + 1); if (HexKt.isFormat(next)) { compoundedFormat += String.valueOf(ChatColor.COLOR_CHAR) + next; - i++; // Skip next character + i += 2; // Skip next character continue; } } - parsedRainbow.append(rainbow.nextChatColor()).append(compoundedFormat).append(c); + + parsedRainbow.append(rainbow.nextChatColor()).append(compoundedFormat).appendCodePoint(cp); + i += charCount; } String before = parsed.substring(0, matcher.start()); @@ -168,32 +166,30 @@ public static String parseGradients(String message) { int stop = findStop(parsed, matcher.end()); String content = parsed.substring(matcher.end(), stop); - int contentLength = content.length(); - char[] chars = content.toCharArray(); - for (int i = 0; i < chars.length - 1; i++) - if (chars[i] == '&' && "KkLlMmNnOoRr".indexOf(chars[i + 1]) > -1) - contentLength -= 2; - - int length = looping ? Math.min(contentLength, CHARS_UNTIL_LOOP) : contentLength; - ColorGenerator gradient; - if (speed == -1) { - gradient = new Gradient(hexSteps, length); - } else { - gradient = new AnimatedGradient(hexSteps, length, speed); - } + + int length = content.codePointCount(0, content.length()); + if (looping) length = Math.min(length, CHARS_UNTIL_LOOP); + + ColorGenerator gradient = (speed == -1) + ? new Gradient(hexSteps, length) + : new AnimatedGradient(hexSteps, length, speed); String compoundedFormat = ""; // Carry the format codes through the gradient - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - if (c == '&' && i + 1 < chars.length) { - char next = chars[i + 1]; + for (int i = 0; i < content.length(); ) { + int cp = content.codePointAt(i); + int charCount = Character.charCount(cp); + + if (cp == '&' && i + 1 < content.length()) { + char next = content.charAt(i + 1); if (HexKt.isFormat(next)) { compoundedFormat += String.valueOf(ChatColor.COLOR_CHAR) + next; - i++; // Skip next character + i += 2; // Skip next character continue; } } - parsedGradient.append(gradient.nextChatColor()).append(compoundedFormat).append(c); + + parsedGradient.append(gradient.nextChatColor()).append(compoundedFormat).appendCodePoint(cp); + i += charCount; } String before = parsed.substring(0, matcher.start()); diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatEvent.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatEvent.kt index 8fef1bb3..d5e8cfcb 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatEvent.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatEvent.kt @@ -2,6 +2,7 @@ package me.arasple.mc.trchat.api.event import me.arasple.mc.trchat.module.display.ChatSession import me.arasple.mc.trchat.module.display.channel.Channel +import me.arasple.mc.trchat.module.display.channel.PrivateChannel import taboolib.module.chat.ComponentText import taboolib.module.chat.Components import taboolib.platform.type.BukkitProxyEvent @@ -10,6 +11,9 @@ import taboolib.platform.type.BukkitProxyEvent * TrChatEvent * me.arasple.mc.trchat.api.event * + * 在 ChannelEvents 前触发 + * component 仅包含玩家消息部分 + * * @author ItsFlicker * @since 2021/8/20 20:53 */ @@ -17,14 +21,24 @@ class TrChatEvent( val channel: Channel, val session: ChatSession, var component: ComponentText, + @Deprecated("Only for chat preview") val forward: Boolean = true ) : BukkitProxyEvent() { val player = session.player - var message = component.toPlainText() - set(value) { - field = value - component = Components.text(value) + init { + if (channel is PrivateChannel) { + val event = TrChatPrivateEvent(channel, session, component) + event.call() + this.isCancelled = event.isCancelled + this.component = event.component } + } + + fun getMessage() = component.toLegacyText() + + fun setMessage(message: String) { + component = Components.text(message) + } } \ No newline at end of file diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatPrivateEvent.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatPrivateEvent.kt new file mode 100644 index 00000000..92e36057 --- /dev/null +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatPrivateEvent.kt @@ -0,0 +1,26 @@ +package me.arasple.mc.trchat.api.event + +import me.arasple.mc.trchat.module.display.ChatSession +import me.arasple.mc.trchat.module.display.channel.Channel +import taboolib.module.chat.ComponentText +import taboolib.module.chat.Components +import taboolib.platform.type.BukkitProxyEvent + +class TrChatPrivateEvent( + val channel: Channel, + val session: ChatSession, + var component: ComponentText +) : BukkitProxyEvent() { + + val sender = session.player + var receiver + get() = session.lastPrivateTo + set(value) { session.lastPrivateTo = value } + + var message = component.toLegacyText() + set(value) { + field = value + component = Components.text(value) + } + +} \ No newline at end of file diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatSendEvent.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatSendEvent.kt new file mode 100644 index 00000000..3cf73e6f --- /dev/null +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/event/TrChatSendEvent.kt @@ -0,0 +1,36 @@ +package me.arasple.mc.trchat.api.event + +import me.arasple.mc.trchat.module.display.ChatSession +import me.arasple.mc.trchat.module.display.channel.Channel +import taboolib.module.chat.ComponentText +import taboolib.module.chat.Components +import taboolib.platform.type.BukkitProxyEvent + +/** + * TrChatSendEvent + * me.arasple.mc.trchat.api.event + * + * 在消息链构造完成后触发 + * component 包含整条即将发送的聊天消息 + * + */ +class TrChatSendEvent( + val channel: Channel, + val session: ChatSession, + var component: ComponentText, + val type: Type = Type.COMMON +) : BukkitProxyEvent() { + + val player = session.player + + fun getMessage() = component.toLegacyText() + + fun setMessage(message: String) { + component = Components.text(message) + } + + enum class Type { + COMMON, SENDER, RECEIVER + } + +} \ No newline at end of file diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/impl/BukkitComponentManager.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/impl/BukkitComponentManager.kt index 40aa3e5f..0177c7bb 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/impl/BukkitComponentManager.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/impl/BukkitComponentManager.kt @@ -59,7 +59,7 @@ object BukkitComponentManager : ComponentManager { is UUID -> sender else -> null } - if (commandSender is Player && uuid in commandSender.data.ignored) { + if (commandSender is Player && commandSender.data.hasIgnored(uuid)) { return } val event = TrChatReceiveEvent(commandSender, uuid, component) diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/impl/BukkitProxyManager.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/impl/BukkitProxyManager.kt index 308ccf35..01949436 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/impl/BukkitProxyManager.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/api/impl/BukkitProxyManager.kt @@ -4,12 +4,12 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder import me.arasple.mc.trchat.api.ClientMessageManager import me.arasple.mc.trchat.api.ProxyMode import me.arasple.mc.trchat.module.conf.file.Settings -import me.arasple.mc.trchat.module.internal.data.PlayerData +import me.arasple.mc.trchat.module.internal.hook.isVanished import me.arasple.mc.trchat.module.internal.proxy.BukkitProxyProcessor import me.arasple.mc.trchat.module.internal.proxy.redis.RedisManager import me.arasple.mc.trchat.util.parseString +import net.md_5.bungee.api.ChatColor import org.bukkit.Bukkit -import org.bukkit.ChatColor import org.bukkit.plugin.messaging.PluginMessageRecipient import org.spigotmc.SpigotConfig import taboolib.common.platform.Platform @@ -39,13 +39,11 @@ object BukkitProxyManager : ClientMessageManager { override var port = 25565 - var allPlayerNames = mapOf() + var allPlayerNames = listOf>() get() = if (mode == ProxyMode.NONE) { - onlinePlayers.associate { it.name to ChatColor.stripColor(it.displayName) } + onlinePlayers.map { Triple(it.name, ChatColor.stripColor(it.displayName), it.uniqueId) } } else if (mode == ProxyMode.REDIS) { - val result = mutableMapOf() - (processor as BukkitProxyProcessor.RedisSide).allNames.values.forEach { result += it } - result + (processor as BukkitProxyProcessor.RedisSide).allNames.values.flatten() } else { field } @@ -65,11 +63,12 @@ object BukkitProxyManager : ClientMessageManager { } override val mode: ProxyMode by unsafeLazy { - val force = kotlin.runCatching { - ProxyMode.valueOf(Settings.conf.getString("Options.Proxy")?.uppercase() ?: "AUTO") - } - if (force.isSuccess) { - return@unsafeLazy force.getOrThrow() + val force = Settings.conf.getString("Options.Proxy")?.uppercase() ?: "AUTO" + if (force != "AUTO") { + try { + return@unsafeLazy ProxyMode.valueOf(force) + } catch (_: IllegalArgumentException) { + } } if (RedisManager.enabled) { console().sendLang("Plugin-Proxy-Supported", "Redis") @@ -111,12 +110,16 @@ object BukkitProxyManager : ClientMessageManager { executor.shutdownNow() } - override fun getPlayerNames(): Map { - return allPlayerNames + override fun getPlayerNames(includeVanish: Boolean): Map { + return if (includeVanish) { + allPlayerNames.associate { it.first to it.second } + } else { + allPlayerNames.filterNot { it.third.isVanished() }.associate { it.first to it.second } + } } - fun getPlayerNamesMerged(): Set { - return allPlayerNames.let { it.keys + it.values.filterNotNull() } + fun getPlayerNamesMerged(includeVanish: Boolean = false): Set { + return getPlayerNames(includeVanish).let { it.keys + it.values.filterNotNull() } } override fun getExactName(name: String): String? { @@ -142,6 +145,8 @@ object BukkitProxyManager : ClientMessageManager { return processor!!.sendMessage(recipient, executor, data) } + + fun sendProxyLang(recipient: Any?, target: String, node: String, vararg args: String) { if (processor == null || Bukkit.getPlayerExact(target) != null) { getProxyPlayer(target)?.sendLang(node, *args) @@ -150,26 +155,37 @@ object BukkitProxyManager : ClientMessageManager { } } - fun sendBroadcastRaw(recipient: Any?, uuid: UUID, component: ComponentText, listenPerm: String = "", doubleTransfer: Boolean = true, ports: List = emptyList()) { + fun sendBroadcastRaw( + recipient: Any?, + uuid: UUID, + component: ComponentText, + listenPerm: String = "", + doubleTransfer: Boolean = true, + ports: List = emptyList(), + fallback: String = component.toLegacyText() + ) { sendMessage(recipient, arrayOf( "BroadcastRaw", uuid.parseString(), component.toRawMessage(), listenPerm, doubleTransfer.toString(), - ports.joinToString(";")) + ports.joinToString(";"), + fallback) ) } - fun sendPrivateRaw(recipient: Any?, to: String, from: String, component: ComponentText) { - sendMessage(recipient, arrayOf("ForwardMessage", "SendPrivateRaw", to, from, component.toRawMessage())) + fun sendPrivateRaw(recipient: Any?, to: String, from: String, component: ComponentText, fallback: String = component.toLegacyText()) { + sendMessage(recipient, arrayOf("ForwardMessage", "SendPrivateRaw", to, from, component.toRawMessage(), fallback)) } fun updateNames() { sendMessage(onlinePlayers.firstOrNull(), arrayOf( "UpdateNames", - onlinePlayers.filter { it.name !in PlayerData.vanishing }.joinToString(",") { it.name + "-" + ChatColor.stripColor(it.displayName) }, - port.toString() + port.toString(), + onlinePlayers.joinToString(",") { it.name }, + onlinePlayers.joinToString(",") { ChatColor.stripColor(it.displayName)?.ifEmpty { "#" } ?: "#" }, + onlinePlayers.joinToString(",") { it.uniqueId.parseString() } )) } diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/Loader.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/Loader.kt index de6f7c58..249fe27d 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/Loader.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/Loader.kt @@ -12,6 +12,7 @@ import me.arasple.mc.trchat.module.display.format.Format import me.arasple.mc.trchat.module.display.format.Group import me.arasple.mc.trchat.module.display.format.JsonComponent import me.arasple.mc.trchat.module.display.format.MsgComponent +import me.arasple.mc.trchat.module.display.format.obj.Head import me.arasple.mc.trchat.module.display.format.obj.Style import me.arasple.mc.trchat.module.display.format.obj.Text import me.arasple.mc.trchat.module.display.function.CustomFunction @@ -25,12 +26,14 @@ import taboolib.common.io.newFile import taboolib.common.platform.Platform import taboolib.common.platform.PlatformSide import taboolib.common.platform.ProxyCommandSender +import taboolib.common.platform.function.console import taboolib.common.platform.function.getDataFolder import taboolib.common.platform.function.releaseResourceFile import taboolib.common.util.asList import taboolib.common.util.orNull import taboolib.common.util.unsafeLazy import taboolib.common5.Coerce +import taboolib.common5.util.parseMillis import taboolib.library.configuration.ConfigurationSection import taboolib.module.configuration.util.getMap import taboolib.module.lang.sendLang @@ -196,10 +199,14 @@ object Loader { val priority = map.getInt("priority", 100) val regex = map.getString("pattern")!!.toRegex() val filterTextRegex = map.getString("text-filter")?.toRegex() + val cooldown = kotlin.runCatching { map.getString("cooldown")?.parseMillis() } + .onFailure { console().sendLang("Mute-Wrong-Format", map.getString("cooldown")!!) } + .getOrNull() + val cooldownMessage = map.getString("cooldown-message") val displayJson = parseJSON(map.getConfigurationSection("display")!!.toMap(), isMsg = false) val reaction = map["action"]?.let { Reaction(it.asList()) } - CustomFunction(id, condition, priority, regex, filterTextRegex, displayJson, reaction) + CustomFunction(id, condition, priority, regex, filterTextRegex, cooldown, cooldownMessage, displayJson, reaction) }.sortedBy { it.priority } Function.reload(functions) @@ -237,12 +244,14 @@ object Loader { style += content["file"]?.serialize()?.map { it.first to it.second.getCondition() }?.let { Style.Click.File(it) } style += content["insertion"]?.serialize()?.map { it.first to it.second.getCondition() }?.let { Style.Insertion(it) } style += content["font"]?.serialize()?.map { it.first to it.second.getCondition() }?.let { Style.Font(it) } + style += content["shadow"]?.serialize()?.map { it.first to it.second.getCondition() }?.let { Style.Shadow(it) } return if (isMsg) { val defaultColor = content["default-color"]!!.serialize().map { CustomColor.get(it.first) to it.second.getCondition() } MsgComponent(defaultColor, style.filterNotNull()) } else { - val text = Property.serialize(content["text"] ?: "null").map { Text(it.first, it.second.getCondition()) } - JsonComponent(text, style.filterNotNull()) + val text = content["text"]?.serialize()?.map { Text(it.first, it.second.getCondition()) } ?: emptyList() + val head = content["head"]?.serialize()?.map { Head(it.first, it.second.getCondition()) } ?: emptyList() + JsonComponent(text, head, style.filterNotNull()) } } diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/Property.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/Property.kt index 452477be..c1bfd9bc 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/Property.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/Property.kt @@ -20,7 +20,7 @@ enum class Property(val regex: Regex, val group: Int) { fun from(string: String): Pair> { var content = string - val map = values().mapNotNull { + val map = entries.mapNotNull { val value = it.regex.find(content)?.groupValues?.get(it.group) value?.let { v -> content = content.replace(it.regex, "") @@ -34,6 +34,7 @@ enum class Property(val regex: Regex, val group: Int) { fun serialize(contents: Any): List>> { return when (contents) { is String -> listOf(from(contents)) + is Boolean -> listOf(from(contents.toString())) is List<*> -> contents.map { from(it!!.toString()) } else -> error("Unexpected part: $contents") } diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/file/Functions.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/file/Functions.kt index 99e11df0..7c501f26 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/file/Functions.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/conf/file/Functions.kt @@ -36,7 +36,7 @@ object Functions { } @ConfigNode("General.Command-Controller.List", "function.yml") - val commandController = ConfigNodeTransfer, Map> { + val commandController = ConfigNodeTransfer, Map>(false, emptyMap()) { associate { string -> val (cmd, property) = Property.from(string!!.toString()) val mCmd = Bukkit.getCommandAliases().entries.firstOrNull { (_, value) -> diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/ChatSession.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/ChatSession.kt index 0194774a..f5afe29f 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/ChatSession.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/ChatSession.kt @@ -8,7 +8,6 @@ import me.arasple.mc.trchat.util.color.CustomColor import me.arasple.mc.trchat.util.color.MessageColors import me.arasple.mc.trchat.util.data import org.bukkit.entity.Player -import taboolib.expansion.getDataContainer import taboolib.library.reflex.Reflex.Companion.getProperty import taboolib.module.chat.ComponentText import taboolib.module.chat.Components @@ -52,7 +51,7 @@ class ChatSession(val player: Player) { return if (forces.isNotEmpty()) { CustomColor.get(forces[0]) } else { - val selectedColor = player.getDataContainer()["color"].takeIf { it != "null" } + val selectedColor = player.data.color if (selectedColor != null && player.hasPermission(MessageColors.COLOR_PERMISSION_NODE + selectedColor)) { CustomColor.get(selectedColor) } else { diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/channel/Channel.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/channel/Channel.kt index 612db45e..dd6310cb 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/channel/Channel.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/channel/Channel.kt @@ -2,12 +2,14 @@ package me.arasple.mc.trchat.module.display.channel import me.arasple.mc.trchat.TrChat import me.arasple.mc.trchat.api.event.TrChatEvent +import me.arasple.mc.trchat.api.event.TrChatSendEvent import me.arasple.mc.trchat.api.impl.BukkitProxyManager import me.arasple.mc.trchat.module.conf.file.Settings import me.arasple.mc.trchat.module.display.channel.obj.* import me.arasple.mc.trchat.module.display.format.Format import me.arasple.mc.trchat.module.display.format.MsgComponent import me.arasple.mc.trchat.module.display.function.Function +import me.arasple.mc.trchat.module.internal.TrChatBukkit import me.arasple.mc.trchat.module.internal.data.ChatLogs import me.arasple.mc.trchat.module.internal.service.Metrics import me.arasple.mc.trchat.util.* @@ -18,7 +20,6 @@ import taboolib.common.platform.command.command import taboolib.common.platform.function.adaptPlayer import taboolib.common.platform.function.console import taboolib.common.platform.function.getProxyPlayer -import taboolib.common.platform.function.unregisterCommand import taboolib.common.util.Strings import taboolib.common.util.subList import taboolib.module.chat.ComponentText @@ -40,6 +41,8 @@ open class Channel( val consoleFormat: List ) { + var isUnregistered = false + val listeners: MutableSet = mutableSetOf() open fun init() { @@ -57,7 +60,7 @@ open class Channel( } open fun registerCommand() { - if (bindings.command.isNullOrEmpty()) return + if (bindings.command.isNullOrEmpty() || TrChatBukkit.isActivated) return command( name = bindings.command[0], aliases = subList(bindings.command, 1), @@ -66,18 +69,19 @@ open class Channel( permissionDefault = PermissionDefault.TRUE ) { execute { sender, _, _ -> - if (sender.session.channel == this@Channel.id) { + if (sender.session.channel == id) { quit(sender, setDefault = true) } else { - join(sender, this@Channel) + join(sender, id) } } dynamic("message", optional = true) { execute { sender, _, argument -> + val channel = channels[id] ?: return@execute if (sender is Player) { - execute(sender, argument) + channel.execute(sender, argument) } else { - execute(sender, argument) + channel.execute(sender, argument) } } } @@ -150,7 +154,7 @@ open class Channel( ChatLogs.logNormal(player.name, plain) Metrics.increase(0) - val component = Components.empty() + var component = Components.empty() formats.firstOrNull { it.condition.pass(player) }?.let { format -> format.prefix .mapNotNull { prefix -> prefix.value.firstOrNull { it.condition.pass(player) }?.content?.toTextComponent(player) } @@ -166,6 +170,11 @@ open class Channel( session.cancelChat = false return ChannelExecuteResult(failedReason = ChannelExecuteResult.FailReason.EVENT) } + val sendEvent = TrChatSendEvent(this, session, component) + if (!sendEvent.call()) { + return ChannelExecuteResult(failedReason = ChannelExecuteResult.FailReason.EVENT) + } + component = sendEvent.component // Proxy if (settings.proxy) { if (BukkitProxyManager.processor != null || settings.forceProxy) { @@ -237,7 +246,7 @@ open class Channel( } if (!player.hasPermission("trchat.bypass.repeat")) { val lastMessage = player.session.lastPublicMessage - if (Settings.chatSimilarity > 0 && Strings.similarDegree(lastMessage, message) > Settings.chatSimilarity) { + if (Settings.chatSimilarity > 0 && Settings.chatSimilarity <= 1 && Strings.similarDegree(lastMessage, message) >= Settings.chatSimilarity) { player.sendLang("General-Too-Similar") return false } @@ -257,7 +266,7 @@ open class Channel( } open fun unregister() { - bindings.command?.forEach { unregisterCommand(it) } + isUnregistered = true listeners.clear() } diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/channel/PrivateChannel.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/channel/PrivateChannel.kt index 40941b19..e8699e5a 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/channel/PrivateChannel.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/channel/PrivateChannel.kt @@ -1,6 +1,7 @@ package me.arasple.mc.trchat.module.display.channel import me.arasple.mc.trchat.api.event.TrChatEvent +import me.arasple.mc.trchat.api.event.TrChatSendEvent import me.arasple.mc.trchat.api.impl.BukkitProxyManager import me.arasple.mc.trchat.module.display.channel.obj.ChannelBindings import me.arasple.mc.trchat.module.display.channel.obj.ChannelEvents @@ -8,6 +9,7 @@ import me.arasple.mc.trchat.module.display.channel.obj.ChannelExecuteResult import me.arasple.mc.trchat.module.display.channel.obj.ChannelSettings import me.arasple.mc.trchat.module.display.format.Format import me.arasple.mc.trchat.module.display.format.MsgComponent +import me.arasple.mc.trchat.module.internal.TrChatBukkit import me.arasple.mc.trchat.module.internal.command.main.CommandReply import me.arasple.mc.trchat.module.internal.data.ChatLogs import me.arasple.mc.trchat.module.internal.data.PlayerData @@ -20,7 +22,6 @@ import org.bukkit.command.CommandSender import org.bukkit.entity.Player import taboolib.common.platform.command.PermissionDefault import taboolib.common.platform.command.command -import taboolib.common.platform.command.suggest import taboolib.common.platform.function.console import taboolib.common.platform.function.getProxyPlayer import taboolib.common.util.subList @@ -54,7 +55,7 @@ class PrivateChannel( } override fun registerCommand() { - if (bindings.command.isNullOrEmpty()) return + if (bindings.command.isNullOrEmpty() || TrChatBukkit.isActivated) return command( name = bindings.command[0], aliases = subList(bindings.command, 1), @@ -63,27 +64,28 @@ class PrivateChannel( permissionDefault = PermissionDefault.TRUE ) { execute { sender, _, _ -> - if (sender.session.channel == this@PrivateChannel.id) { - quit(sender, true) + if (sender.session.channel == id) { + quit(sender, setDefault = true) } else { sender.sendLang("Private-Message-No-Player") } } dynamic("player", optional = true) { - suggest { - BukkitProxyManager.getPlayerNamesMerged().filter { it !in PlayerData.vanishing } + suggestion { sender, _ -> + BukkitProxyManager.getPlayerNamesMerged(sender.hasPermission("trchat.bypass.vanish")).toList() } execute { sender, _, argument -> sender.session.lastPrivateTo = BukkitProxyManager.getExactName(argument) ?: return@execute sender.sendLang("Command-Player-Not-Exist") - join(sender, this@PrivateChannel) + join(sender, id) } dynamic("message", optional = true) { execute { sender, ctx, argument -> + val channel = channels[id] ?: return@execute BukkitProxyManager.getExactName(ctx["player"])?.let { if (sender is Player) sender.session.lastPrivateTo = it else consolePrivateTo = it - execute(sender, argument) + channel.execute(sender, argument) } ?: sender.sendLang("Command-Player-Not-Exist") } } @@ -163,8 +165,8 @@ class PrivateChannel( ?: return ChannelExecuteResult(failedReason = ChannelExecuteResult.FailReason.EVENT) plain = msg.toPlainText() - val send = Components.empty() val msgComponent = Components.empty() + var send = Components.empty() sender.firstOrNull { it.condition.pass(player) }?.let { format -> format.prefix .mapNotNull { prefix -> prefix.value.firstOrNull { it.condition.pass(player) }?.content?.toTextComponent(player) } @@ -178,7 +180,7 @@ class PrivateChannel( .forEach { suffix -> send.append(suffix) } } ?: return ChannelExecuteResult(failedReason = ChannelExecuteResult.FailReason.NO_FORMAT) - val receive = Components.empty() + var receive = Components.empty() receiver.firstOrNull { it.condition.pass(player) }?.let { format -> format.prefix .mapNotNull { prefix -> prefix.value.firstOrNull { it.condition.pass(player) }?.content?.toTextComponent(player) } @@ -197,11 +199,14 @@ class PrivateChannel( if (!events.send(player, to, plain)) { return ChannelExecuteResult(failedReason = ChannelExecuteResult.FailReason.EVENT) } - player.sendComponent(player, send) + val senderEvent = TrChatSendEvent(this, session, send, type = TrChatSendEvent.Type.SENDER) + if (senderEvent.call()) { + send = senderEvent.component + player.sendComponent(player, send) + } PlayerData.spying.forEach { - Bukkit.getPlayer(it) - ?.sendLang("Private-Message-Spy-Format", player.name, to, msgComponent.toLegacyText()) + Bukkit.getPlayer(it)?.sendLang("Private-Message-Spy-Format", player.name, to, msgComponent.toLegacyText()) } console().sendLang("Private-Message-Spy-Format", player.name, to, msgComponent.toLegacyText()) @@ -209,6 +214,12 @@ class PrivateChannel( ChatLogs.logPrivate(player.name, to, plain) Metrics.increase(0) + val receiverEvent = TrChatSendEvent(this, session, receive, type = TrChatSendEvent.Type.RECEIVER) + if (!receiverEvent.call()) { + return ChannelExecuteResult(failedReason = ChannelExecuteResult.FailReason.EVENT) + } + receive = receiverEvent.component + if (settings.proxy && BukkitProxyManager.processor != null) { BukkitProxyManager.sendPrivateRaw( player, diff --git a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/format/JsonComponent.kt b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/format/JsonComponent.kt index fe1a9c5c..f6e2ee30 100644 --- a/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/format/JsonComponent.kt +++ b/project/runtime-bukkit/src/main/kotlin/me/arasple/mc/trchat/module/display/format/JsonComponent.kt @@ -1,5 +1,6 @@ package me.arasple.mc.trchat.module.display.format +import me.arasple.mc.trchat.module.display.format.obj.Head import me.arasple.mc.trchat.module.display.format.obj.Style import me.arasple.mc.trchat.module.display.format.obj.Style.Companion.applyTo import me.arasple.mc.trchat.module.display.format.obj.Text @@ -13,12 +14,15 @@ import taboolib.module.chat.Components * @date 2019/11/30 12:42 */ open class JsonComponent( - val text: List?, + val text: List? = null, + val head: List? = null, val style: List