├── settings.gradle.kts
├── .idea
├── .gitignore
├── vcs.xml
├── kotlinc.xml
├── gradle.xml
└── misc.xml
├── icon.png
├── icon_8x.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── src
└── main
│ ├── resources
│ ├── bungee.yml
│ └── plugin.yml
│ └── kotlin
│ └── io
│ └── github
│ └── bluesheep2804
│ └── selenechat
│ ├── common
│ ├── Platforms.kt
│ ├── ConvertMode.kt
│ └── ComponentSerializer.kt
│ ├── command
│ ├── ChannelCommandSpigot.kt
│ ├── MessageCommandSpigot.kt
│ ├── ChannelCommandBungee.kt
│ ├── ChannelCommandVelocity.kt
│ ├── JapanizeCommandBungee.kt
│ ├── JapanizeCommandSpigot.kt
│ ├── MessageCommandBungee.kt
│ ├── MessageCommandVelocity.kt
│ ├── JapanizeCommandVelocity.kt
│ ├── SeleneChatCommandBungee.kt
│ ├── SeleneChatCommandSpigot.kt
│ ├── SeleneChatCommandVelocity.kt
│ ├── ICommand.kt
│ ├── channel
│ │ ├── SubCommand.kt
│ │ ├── SubEditCommand.kt
│ │ ├── EditFormatCommand.kt
│ │ ├── CreateCommand.kt
│ │ ├── EditVisibleCommand.kt
│ │ ├── EditJpCommand.kt
│ │ ├── EditInfoCommand.kt
│ │ ├── LeaveCommand.kt
│ │ ├── DeleteCommand.kt
│ │ ├── ListCommand.kt
│ │ ├── JoinCommand.kt
│ │ └── EditModeratorCommand.kt
│ ├── CommandBungee.kt
│ ├── CommandSpigot.kt
│ ├── CommandVelocity.kt
│ ├── JapanizeCommand.kt
│ ├── SeleneChatCommand.kt
│ ├── MessageCommand.kt
│ └── ChannelCommand.kt
│ ├── player
│ ├── SeleneChatPlayerOffline.kt
│ ├── SeleneChatPlayerConsole.kt
│ ├── SeleneChatPlayerBungeeConsole.kt
│ ├── SeleneChatPlayerVelocityConsole.kt
│ ├── SeleneChatPlayerVelocity.kt
│ ├── SeleneChatPlayerSpigotConsole.kt
│ ├── SeleneChatPlayerSpigot.kt
│ ├── SeleneChatPlayerBungee.kt
│ └── SeleneChatPlayer.kt
│ ├── japanize
│ ├── GoogleIME.kt
│ ├── Japanizer.kt
│ ├── JapanizePlayersManager.kt
│ ├── IMEConverter.kt
│ └── RomaToKana.kt
│ ├── message
│ ├── PluginMessage.kt
│ └── ChatMessage.kt
│ ├── SeleneChat.kt
│ ├── listener
│ ├── ChatListenerSpigot.kt
│ ├── ChatListener.kt
│ ├── ChatListenerVelocity.kt
│ └── ChatListenerBungee.kt
│ ├── IPlugin.kt
│ ├── resource
│ ├── ResourceManager.kt
│ ├── ResourceData.kt
│ └── CommandResourceData.kt
│ ├── config
│ ├── SeleneChatConfigManager.kt
│ └── SeleneChatConfigData.kt
│ ├── channel
│ ├── ChannelData.kt
│ └── ChannelManager.kt
│ ├── SeleneChatBungee.kt
│ ├── SeleneChatSpigot.kt
│ └── SeleneChatVelocity.kt
├── .github
└── workflows
│ └── release-please.yml
├── .gitignore
├── README_ja.md
├── README.md
├── gradlew.bat
├── CHANGELOG.md
├── LICENSE
└── gradlew
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "SeleneChat"
2 |
3 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # デフォルトの無視対象ファイル
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSheep2804/SeleneChat/HEAD/icon.png
--------------------------------------------------------------------------------
/icon_8x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSheep2804/SeleneChat/HEAD/icon_8x.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSheep2804/SeleneChat/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/bungee.yml:
--------------------------------------------------------------------------------
1 | name: SeleneChat
2 | version: ${version}
3 | description: Chat plugin inspired by LunaChat
4 | main: io.github.bluesheep2804.selenechat.SeleneChatBungee
5 | author: BlueSheep2804
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/common/Platforms.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.common
2 |
3 | enum class Platforms {
4 | BUKKIT,
5 | BUNGEECORD,
6 | VELOCITY
7 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/ChannelCommandSpigot.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class ChannelCommandSpigot : CommandSpigot() {
4 | override val command = ChannelCommand()
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/MessageCommandSpigot.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class MessageCommandSpigot : CommandSpigot() {
4 | override val command = MessageCommand()
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/ChannelCommandBungee.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class ChannelCommandBungee(override val command: ICommand = ChannelCommand()) : CommandBungee(command)
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/ChannelCommandVelocity.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class ChannelCommandVelocity : CommandVelocity() {
4 | override val command = ChannelCommand()
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/JapanizeCommandBungee.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class JapanizeCommandBungee(override val command: ICommand = JapanizeCommand()) : CommandBungee(command)
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/JapanizeCommandSpigot.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class JapanizeCommandSpigot : CommandSpigot() {
4 | override val command = JapanizeCommand()
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/MessageCommandBungee.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class MessageCommandBungee(override val command: ICommand = MessageCommand()) : CommandBungee(command)
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/MessageCommandVelocity.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class MessageCommandVelocity : CommandVelocity() {
4 | override val command = MessageCommand()
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/JapanizeCommandVelocity.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class JapanizeCommandVelocity : CommandVelocity() {
4 | override val command = JapanizeCommand()
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/SeleneChatCommandBungee.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class SeleneChatCommandBungee(override val command: ICommand = SeleneChatCommand()) : CommandBungee(command)
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/SeleneChatCommandSpigot.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class SeleneChatCommandSpigot : CommandSpigot() {
4 | override val command = SeleneChatCommand()
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/SeleneChatCommandVelocity.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | class SeleneChatCommandVelocity : CommandVelocity() {
4 | override val command = SeleneChatCommand()
5 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/common/ConvertMode.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.common
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | enum class ConvertMode {
8 | @SerialName("none") NONE,
9 | @SerialName("kana") KANA,
10 | @SerialName("ime") IME
11 | }
12 |
--------------------------------------------------------------------------------
/.github/workflows/release-please.yml:
--------------------------------------------------------------------------------
1 | name: release-please
2 | on:
3 | push:
4 | branches:
5 | - main
6 |
7 | permissions:
8 | contents: write
9 | pull-requests: write
10 |
11 | jobs:
12 | release-please:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: google-github-actions/release-please-action@v3
16 | with:
17 | release-type: simple
18 | package-name: selenechat
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/ICommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
4 |
5 | interface ICommand {
6 | val COMMAND_NAME: String
7 | val COMMAND_ALIASES: Array
8 | val PERMISSION: String
9 | fun execute(sender: SeleneChatPlayer, args: Array): Boolean
10 | fun suggest(sender: SeleneChatPlayer, args: Array): List
11 | }
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayerOffline.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import net.kyori.adventure.text.Component
4 | import java.util.*
5 |
6 | class SeleneChatPlayerOffline(override val uniqueId: UUID = UUID.fromString("0-0-0-0-0"), override val displayName: String = "", override val currentServerName: String = "") : SeleneChatPlayer() {
7 | override val isOnline = false
8 | override fun sendMessage(msg: Component) {}
9 | override fun sendCommandResult(msg: Component) {}
10 | override fun hasPermission(permission: String): Boolean {
11 | return false
12 | }
13 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/japanize/GoogleIME.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.japanize
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.JsonArray
5 |
6 | /**
7 | * GoogleIMEの最初の変換候補を抽出して結合するクラス
8 | *
9 | * @author ucchy, BlueSheep2804
10 | * @see [LunaChat Github](https://github.com/ucchyocean/LunaChat/tree/master/src/main/java/com/github/ucchyocean/lc3/japanize/GoogleIME.java)
11 | */
12 | object GoogleIME {
13 | @JvmStatic
14 | fun parseJson(json: String?): String {
15 | val result = StringBuilder()
16 | for (response in Gson().fromJson(json, JsonArray::class.java)) {
17 | result.append(response.asJsonArray[1].asJsonArray[0].asString)
18 | }
19 | return result.toString()
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/SubCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
4 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
5 |
6 | abstract class SubCommand {
7 | abstract val commandName: String
8 | abstract val permission: String
9 |
10 | abstract fun execute(sender: SeleneChatPlayer, args: Array): Boolean
11 |
12 | fun checkPermission(sender: SeleneChatPlayer): Boolean {
13 | return if (!sender.hasPermission(permission)) {
14 | sender.sendCommandResult(resource.command.generalErrorNoPermission)
15 | false
16 | } else {
17 | true
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayerConsole.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import net.kyori.adventure.text.Component
4 | import net.kyori.adventure.text.event.HoverEvent
5 | import net.kyori.examination.Examinable
6 | import java.util.*
7 |
8 | abstract class SeleneChatPlayerConsole: SeleneChatPlayer() {
9 | override val displayName: String
10 | get() = "CONSOLE"
11 |
12 | override val uniqueId: UUID
13 | get() = UUID.fromString("0-0-0-0-0")
14 |
15 | override val currentServerName: String
16 | get() = ""
17 |
18 | override val isConsole: Boolean
19 | get() = true
20 |
21 | override fun asHoverEvent(): HoverEvent {
22 | return HoverEvent.showText(Component.text("CONSOLE"))
23 | }
24 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build/
3 | !gradle/wrapper/gradle-wrapper.jar
4 | !**/src/main/**/build/
5 | !**/src/test/**/build/
6 |
7 | ### IntelliJ IDEA ###
8 | .idea/modules.xml
9 | .idea/jarRepositories.xml
10 | .idea/compiler.xml
11 | .idea/uiDesigner.xml
12 | .idea/discord.xml
13 | .idea/libraries/
14 | *.iws
15 | *.iml
16 | *.ipr
17 | out/
18 | !**/src/main/**/out/
19 | !**/src/test/**/out/
20 |
21 | ### Eclipse ###
22 | .apt_generated
23 | .classpath
24 | .factorypath
25 | .project
26 | .settings
27 | .springBeans
28 | .sts4-cache
29 | bin/
30 | !**/src/main/**/bin/
31 | !**/src/test/**/bin/
32 |
33 | ### NetBeans ###
34 | /nbproject/private/
35 | /nbbuild/
36 | /dist/
37 | /nbdist/
38 | /.nb-gradle/
39 |
40 | ### VS Code ###
41 | .vscode/
42 |
43 | ### Mac OS ###
44 | .DS_Store
45 |
46 | /run_paper
47 | /run_velocity
48 | /run_waterfall
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/SubEditCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.channel.ChannelData
5 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
6 |
7 | abstract class SubEditCommand {
8 | abstract val commandName: String
9 | abstract val permission: String
10 |
11 | abstract fun execute(sender: SeleneChatPlayer, args: Array, channel: ChannelData): Boolean
12 |
13 | fun checkPermission(sender: SeleneChatPlayer): Boolean {
14 | return if (!sender.hasPermission(permission)) {
15 | sender.sendCommandResult(SeleneChat.resource.command.generalErrorNoPermission)
16 | false
17 | } else {
18 | true
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayerBungeeConsole.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
4 | import net.kyori.adventure.text.Component
5 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer
6 | import net.md_5.bungee.api.CommandSender
7 |
8 | class SeleneChatPlayerBungeeConsole(private val player: CommandSender) : SeleneChatPlayerConsole() {
9 | override fun sendMessage(msg: Component) {
10 | player.sendMessage(*BungeeComponentSerializer.get().serialize(msg))
11 | }
12 |
13 | override fun sendCommandResult(msg: Component) {
14 | sendMessage(resource.prefix.append(msg))
15 | }
16 |
17 | override fun hasPermission(permission: String): Boolean {
18 | return player.hasPermission(permission)
19 | }
20 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/common/ComponentSerializer.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.common
2 |
3 | import kotlinx.serialization.KSerializer
4 | import kotlinx.serialization.descriptors.PrimitiveKind
5 | import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
6 | import kotlinx.serialization.descriptors.SerialDescriptor
7 | import kotlinx.serialization.encoding.Decoder
8 | import kotlinx.serialization.encoding.Encoder
9 | import net.kyori.adventure.text.Component
10 | import net.kyori.adventure.text.minimessage.MiniMessage
11 |
12 | object ComponentSerializer : KSerializer {
13 | private val mm = MiniMessage.miniMessage()
14 | override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Component", PrimitiveKind.STRING)
15 | override fun serialize(encoder: Encoder, value: Component) {
16 | encoder.encodeString(mm.serialize(value))
17 | }
18 |
19 | override fun deserialize(decoder: Decoder): Component {
20 | return mm.deserialize(decoder.decodeString())
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayerVelocityConsole.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import com.velocitypowered.api.command.CommandSource
4 | import com.velocitypowered.api.proxy.ConsoleCommandSource
5 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
6 | import net.kyori.adventure.text.Component
7 |
8 | class SeleneChatPlayerVelocityConsole(private val player: ConsoleCommandSource) : SeleneChatPlayerConsole() {
9 | override fun sendMessage(msg: Component) {
10 | player.sendMessage(msg)
11 | }
12 |
13 | override fun sendCommandResult(msg: Component) {
14 | sendMessage(resource.prefix.append(msg))
15 | }
16 |
17 | override fun hasPermission(permission: String): Boolean {
18 | return player.hasPermission(permission)
19 | }
20 |
21 | companion object {
22 | fun getPlayer(source: CommandSource): SeleneChatPlayerVelocityConsole {
23 | return SeleneChatPlayerVelocityConsole(source as ConsoleCommandSource)
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/japanize/Japanizer.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.japanize
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.config
4 | import io.github.bluesheep2804.selenechat.common.ConvertMode
5 | import io.github.bluesheep2804.selenechat.common.ConvertMode.*
6 |
7 | /**
8 | * ローマ字表記を漢字に変換するクラス
9 | * @author BlueSheep2804
10 | * @see [LunaChat Github](https://github.com/ucchyocean/LunaChat/tree/master/src/main/java/com/github/ucchyocean/lc3/japanize/Japanizer.java)
11 | */
12 | class Japanizer(private val original: String) {
13 | fun japanize(convertMode: ConvertMode): String {
14 | return when (convertMode) {
15 | NONE -> ""
16 | KANA -> RomaToKana.convert(original)
17 | IME -> IMEConverter.googleIME(RomaToKana.convert(original))
18 | }
19 | }
20 |
21 | fun shouldConvert(): Boolean {
22 | return (original.toByteArray().size == original.length // 2バイト文字が無い
23 | && !original.matches("[ \\uFF61-\\uFF9F]+".toRegex())) // 半角カタカナが無い
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/message/PluginMessage.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.message
2 |
3 | import com.google.common.io.ByteArrayDataInput
4 | import com.google.common.io.ByteStreams
5 | import io.github.bluesheep2804.selenechat.SeleneChat
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
7 | import java.util.*
8 |
9 | class PluginMessage(val message: String, val player: SeleneChatPlayer) {
10 | fun build(): ByteArray {
11 | val output = ByteStreams.newDataOutput()
12 | output.writeUTF(message)
13 | output.writeUTF(player.uniqueId.toString())
14 | output.writeUTF(player.displayName)
15 | return output.toByteArray()
16 | }
17 |
18 | companion object {
19 | fun fromByteArrayDataInput(input: ByteArrayDataInput): PluginMessage {
20 | val message = input.readUTF()
21 | val playerUUID = input.readUTF()
22 | val playerDisplayName = input.readUTF()
23 | val player = SeleneChat.plugin.getPlayer(UUID.fromString(playerUUID))
24 | return PluginMessage(message, player)
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/EditFormatCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.channel.ChannelData
5 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
6 |
7 | class EditFormatCommand: SubEditCommand() {
8 | override val commandName: String = "format"
9 | override val permission: String = "selenechat.channel.format"
10 |
11 | override fun execute(sender: SeleneChatPlayer, args: Array, channel: ChannelData): Boolean {
12 | if (args.size < 3) {
13 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessEditFormatCurrentValue(channel.format))
14 | } else {
15 | var format = args[2]
16 | if (args.size > 3) {
17 | for (i in 3 until args.size) {
18 | format += " ${args[i]}"
19 | }
20 | }
21 | channel.format = format
22 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessEditFormat(channel.format))
23 | SeleneChat.channelManager.save(channel)
24 | }
25 | return true
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayerVelocity.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import com.velocitypowered.api.command.CommandSource
4 | import com.velocitypowered.api.proxy.Player
5 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
6 | import net.kyori.adventure.text.Component
7 | import java.util.*
8 |
9 | class SeleneChatPlayerVelocity(private val player: Player) : SeleneChatPlayer() {
10 | override val displayName: String
11 | get() = player.username
12 |
13 | override val uniqueId: UUID
14 | get() = player.uniqueId
15 |
16 | override val currentServerName: String
17 | get() = player.currentServer.get().serverInfo.name
18 |
19 | override fun sendMessage(msg: Component) {
20 | player.sendMessage(msg)
21 | }
22 |
23 | override fun sendCommandResult(msg: Component) {
24 | sendMessage(resource.prefix.append(msg))
25 | }
26 |
27 | override fun hasPermission(permission: String): Boolean {
28 | return player.hasPermission(permission)
29 | }
30 |
31 | companion object {
32 | fun getPlayer(source: CommandSource): SeleneChatPlayerVelocity {
33 | return SeleneChatPlayerVelocity(source as Player)
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/SeleneChat.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat
2 |
3 | import io.github.bluesheep2804.selenechat.channel.ChannelManager
4 | import io.github.bluesheep2804.selenechat.config.SeleneChatConfigData
5 | import io.github.bluesheep2804.selenechat.config.SeleneChatConfigManager
6 | import io.github.bluesheep2804.selenechat.japanize.JapanizePlayersManager
7 | import io.github.bluesheep2804.selenechat.resource.ResourceData
8 | import io.github.bluesheep2804.selenechat.resource.ResourceManager
9 |
10 | object SeleneChat {
11 | lateinit var plugin: IPlugin
12 | val configManager: SeleneChatConfigManager
13 | get() = plugin.configManager
14 | val config: SeleneChatConfigData
15 | get() = plugin.config
16 | val resourceManager: ResourceManager
17 | get() = plugin.resourceManager
18 | val resource: ResourceData
19 | get() = plugin.resource
20 | val japanizePlayersManager: JapanizePlayersManager
21 | get() = plugin.japanizePlayersManager
22 | val japanizePlayers: MutableMap
23 | get() = plugin.japanizePlayers
24 | val channelManager: ChannelManager
25 | get() = plugin.channelManager
26 |
27 | fun setPluginInstance(plugin: IPlugin) {
28 | this.plugin = plugin
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/CommandBungee.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerBungee
4 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerBungeeConsole
5 | import net.md_5.bungee.api.CommandSender
6 | import net.md_5.bungee.api.connection.ProxiedPlayer
7 | import net.md_5.bungee.api.plugin.Command
8 | import net.md_5.bungee.api.plugin.TabExecutor
9 |
10 | abstract class CommandBungee(open val command: ICommand) : Command(command.COMMAND_NAME, command.PERMISSION, *command.COMMAND_ALIASES), TabExecutor {
11 | override fun execute(commandSender: CommandSender, args: Array) {
12 | val sender = when (commandSender) {
13 | is ProxiedPlayer -> SeleneChatPlayerBungee(commandSender)
14 | else -> SeleneChatPlayerBungeeConsole(commandSender)
15 | }
16 | command.execute(sender, args)
17 | }
18 |
19 | override fun onTabComplete(commandSender: CommandSender, args: Array): List {
20 | val sender = when (commandSender) {
21 | is ProxiedPlayer -> SeleneChatPlayerBungee(commandSender)
22 | else -> SeleneChatPlayerBungeeConsole(commandSender)
23 | }
24 | return command.suggest(sender, args)
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/listener/ChatListenerSpigot.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.listener
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.config
4 | import io.github.bluesheep2804.selenechat.SeleneChatSpigot
5 | import io.github.bluesheep2804.selenechat.message.PluginMessage
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerSpigot
7 | import net.kyori.adventure.text.Component
8 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
9 | import org.bukkit.event.EventHandler
10 | import org.bukkit.event.Listener
11 | import org.bukkit.event.player.AsyncPlayerChatEvent
12 |
13 | class ChatListenerSpigot(private val plugin: SeleneChatSpigot) : Listener {
14 | @EventHandler
15 | fun onPlayerChat(event: AsyncPlayerChatEvent) {
16 | val message = event.message
17 | val sender = SeleneChatPlayerSpigot(event.player)
18 |
19 | val result = ChatListener.chat(message, sender)
20 | if (result is Component)
21 | event.message = LegacyComponentSerializer.legacySection().serialize(result)
22 | else
23 | event.isCancelled = true
24 |
25 | if (config.shouldSendPluginMessage) {
26 | plugin.sendPluginMessage(PluginMessage(event.message, sender).build())
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/CommandSpigot.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerSpigot
4 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerSpigotConsole
5 | import org.bukkit.command.*
6 | import org.bukkit.entity.Player
7 |
8 | abstract class CommandSpigot : CommandExecutor, TabExecutor {
9 | abstract val command: ICommand
10 | override fun onCommand(commandSender: CommandSender, command: Command, label: String, args: Array): Boolean {
11 | val sender = when (commandSender) {
12 | is Player -> SeleneChatPlayerSpigot(commandSender)
13 | is ConsoleCommandSender -> SeleneChatPlayerSpigotConsole(commandSender)
14 | else -> return false
15 | }
16 | return this.command.execute(sender, args)
17 | }
18 |
19 | override fun onTabComplete(commandSender: CommandSender, command: Command, label: String, args: Array): List {
20 | val sender = when (commandSender) {
21 | is Player -> SeleneChatPlayerSpigot(commandSender)
22 | is ConsoleCommandSender -> SeleneChatPlayerSpigotConsole(commandSender)
23 | else -> return emptyList()
24 | }
25 | return this.command.suggest(sender, args)
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/CreateCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import arrow.core.Either
4 | import io.github.bluesheep2804.selenechat.SeleneChat
5 | import io.github.bluesheep2804.selenechat.channel.ChannelManager
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
7 |
8 | class CreateCommand: SubCommand() {
9 | override val commandName: String = "create"
10 | override val permission: String = "selenechat.channel.create"
11 |
12 | override fun execute(sender: SeleneChatPlayer, args: Array): Boolean {
13 | if (args.size < 2) {
14 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorCreateEmpty)
15 | return false
16 | }
17 |
18 | when (val result = SeleneChat.channelManager.create(args[1].lowercase(), sender)) {
19 | is Either.Left -> {
20 | sender.sendCommandResult(when (result.value) {
21 | is ChannelManager.ChannelCreateError.AlreadyExists -> SeleneChat.resource.command.channelErrorCreateExists
22 | })
23 | return false
24 | }
25 | is Either.Right -> sender.sendCommandResult(SeleneChat.resource.command.channelSuccessCreate(result.value))
26 | }
27 | return true
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/EditVisibleCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.channel.ChannelData
5 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
6 |
7 | class EditVisibleCommand: SubEditCommand() {
8 | override val commandName: String = "visible"
9 | override val permission: String = "selenechat.channel.visible"
10 |
11 | override fun execute(sender: SeleneChatPlayer, args: Array, channel: ChannelData): Boolean {
12 | if (args.size < 3) {
13 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessEditVisibleCurrentValue(channel.visible))
14 | } else {
15 | channel.visible = when (args[2].lowercase()) {
16 | "true" -> true
17 | "false" -> false
18 | else -> {
19 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorEditVisibleUnexpectedArgs)
20 | return false
21 | }
22 | }
23 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessEditVisible(channel.visible))
24 | SeleneChat.channelManager.save(channel)
25 | }
26 | return true
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/README_ja.md:
--------------------------------------------------------------------------------
1 | # SeleneChat
2 | [](https://github.com/BlueSheep2804/SeleneChat/blob/main/LICENSE)
3 | [](https://github.com/BlueSheep2804/SeleneChat/releases/latest)
4 |
5 | SeleneChatは、LunaChatに影響を受けたMinecraft用チャットプラグインです。
6 | Bukkit, BungeeCord, Velocityで利用可能です。
7 | 動作確認済みのMinecraftバージョン: 1.12.2-1.20.1
8 |
9 | ## Feature
10 | - MiniMessage形式のフォーマットされたチャット
11 | - チャットで送信されたローマ字を日本語に変換
12 | - プライベートメッセージ
13 |
14 | ## Customize
15 | 詳しい説明は[wiki](https://github.com/BlueSheep2804/SeleneChat/wiki)をご覧ください。
16 |
17 | ## Support
18 | バグ報告や新機能の提案などは[Issues](https://github.com/BlueSheep2804/SeleneChat/issues)で受け付けています。
19 | [Pull requests](https://github.com/BlueSheep2804/SeleneChat/pulls)も歓迎です。
20 |
21 | ## Links
22 | - [ソースコード](https://github.com/BlueSheep2804/SeleneChat)
23 | - [SpigotMC project page](https://www.spigotmc.org/resources/selenechat.111119/)
24 | - [CurseForge project page](https://curseforge.com/minecraft/bukkit-plugins/selenechat)
25 | - [Modrinth project page](https://modrinth.com/plugin/selenechat)
26 | - [Hangar project page](https://hangar.papermc.io/BlueSheep/SeleneChat)
27 | - [Twitter](https://twitter.com/BlueSheep2804)
28 |
29 | [](https://ko-fi.com/I3I2F9ODT)
30 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayerSpigotConsole.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
4 | import net.kyori.adventure.text.Component
5 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer
6 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
7 | import org.bukkit.command.CommandSender
8 | import org.bukkit.command.ConsoleCommandSender
9 |
10 | class SeleneChatPlayerSpigotConsole(private val player: ConsoleCommandSender) : SeleneChatPlayerConsole() {
11 | override fun sendMessage(msg: Component) {
12 | try {
13 | player.spigot().sendMessage(*BungeeComponentSerializer.get().serialize(msg))
14 | } catch (_: NoSuchMethodError) {
15 | player.sendMessage(LegacyComponentSerializer.legacySection().serialize(msg))
16 | }
17 | }
18 |
19 | override fun sendCommandResult(msg: Component) {
20 | sendMessage(resource.prefix.append(msg))
21 | }
22 |
23 | override fun hasPermission(permission: String): Boolean {
24 | return player.hasPermission(permission)
25 | }
26 |
27 | companion object {
28 | fun getPlayer(source: CommandSender): SeleneChatPlayerSpigotConsole {
29 | return SeleneChatPlayerSpigotConsole(source as ConsoleCommandSender)
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/IPlugin.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat
2 |
3 | import io.github.bluesheep2804.selenechat.channel.ChannelManager
4 | import io.github.bluesheep2804.selenechat.common.Platforms
5 | import io.github.bluesheep2804.selenechat.config.SeleneChatConfigData
6 | import io.github.bluesheep2804.selenechat.config.SeleneChatConfigManager
7 | import io.github.bluesheep2804.selenechat.japanize.JapanizePlayersManager
8 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
9 | import io.github.bluesheep2804.selenechat.resource.ResourceData
10 | import io.github.bluesheep2804.selenechat.resource.ResourceManager
11 | import net.kyori.adventure.text.Component
12 | import java.util.*
13 |
14 | interface IPlugin {
15 | val platform: Platforms
16 | val configManager: SeleneChatConfigManager
17 | val config: SeleneChatConfigData
18 | get() = configManager.config
19 | val resourceManager: ResourceManager
20 | val resource: ResourceData
21 | get() = resourceManager.resource
22 | val japanizePlayersManager: JapanizePlayersManager
23 | val japanizePlayers: MutableMap
24 | get() = japanizePlayersManager.japanizePlayers
25 | val channelManager: ChannelManager
26 | fun getAllPlayers(): List
27 | fun getPlayer(name: String): SeleneChatPlayer
28 | fun getPlayer(uuid: UUID): SeleneChatPlayer
29 | fun sendMessage(component: Component)
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/EditJpCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.channel.ChannelData
5 | import io.github.bluesheep2804.selenechat.common.ConvertMode
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
7 |
8 | class EditJpCommand: SubEditCommand() {
9 | override val commandName: String = "jp"
10 | override val permission: String = "selenechat.channel.jp"
11 |
12 | override fun execute(sender: SeleneChatPlayer, args: Array, channel: ChannelData): Boolean {
13 | if (args.size < 3) {
14 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessEditJapanizeCurrentValue(channel.japanize))
15 | } else {
16 | channel.japanize = when (args[2]) {
17 | "none" -> ConvertMode.NONE
18 | "kana" -> ConvertMode.KANA
19 | "ime" -> ConvertMode.IME
20 | else -> {
21 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorEditJapanizeUnexpectedArgs)
22 | return false
23 | }
24 | }
25 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessEditJapanize(channel.japanize))
26 | SeleneChat.channelManager.save(channel)
27 | }
28 | return true
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/listener/ChatListener.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.listener
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.channelManager
4 | import io.github.bluesheep2804.selenechat.SeleneChat.config
5 | import io.github.bluesheep2804.selenechat.SeleneChat.plugin
6 | import io.github.bluesheep2804.selenechat.channel.ChannelData
7 | import io.github.bluesheep2804.selenechat.common.Platforms
8 | import io.github.bluesheep2804.selenechat.message.ChatMessage
9 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
10 | import net.kyori.adventure.text.Component
11 |
12 | object ChatListener {
13 | fun chat(message: String, sender: SeleneChatPlayer): Component? {
14 | val channel = if (message.startsWith(config.globalMarker) || !config.enableChannelChat) null else channelManager.getPlayerChannel(sender)
15 | return if (channel is ChannelData) {
16 | channel.sendMessage(ChatMessage.channelChat(message, sender, channel))
17 | null
18 | } else {
19 | val message = if (message.startsWith(config.globalMarker)) message.removePrefix(config.globalMarker) else message
20 | if (plugin.platform == Platforms.BUKKIT && !config.useSeleneChatFormat) {
21 | ChatMessage.message(message, sender)
22 | } else {
23 | plugin.sendMessage(ChatMessage.chat(message, sender))
24 | null
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SeleneChat
2 | [](https://github.com/BlueSheep2804/SeleneChat/blob/main/LICENSE)
3 | [](https://github.com/BlueSheep2804/SeleneChat/releases/latest)
4 |
5 | ([Click here for Japanese documentation. / 日本語ドキュメントはこちら](README_ja.md))
6 |
7 | SeleneChat is a chat plugin for Minecraft inspired by LunaChat.
8 | Available at Bukkit, BungeeCord, and Velocity.
9 | Tested minecraft versions: 1.12.2-1.20.1
10 |
11 | ## Feature
12 | - MiniMessage formatted chat
13 | - Converts romaji sent in chat to Japanese
14 | - Private message
15 |
16 | ## Customize
17 | You can find detailed instructions on the [Wiki](https://github.com/BlueSheep2804/SeleneChat/wiki).
18 |
19 | ## Support
20 | Bug reports and requests for new features are welcome on [Issues](https://github.com/BlueSheep2804/SeleneChat/issues).
21 | [Pull requests](https://github.com/BlueSheep2804/SeleneChat/pulls) are also accepted.
22 |
23 | ## Links
24 | - [Source code](https://github.com/BlueSheep2804/SeleneChat)
25 | - [SpigotMC project page](https://www.spigotmc.org/resources/selenechat.111119/)
26 | - [CurseForge project page](https://curseforge.com/minecraft/bukkit-plugins/selenechat)
27 | - [Modrinth project page](https://modrinth.com/plugin/selenechat)
28 | - [Hangar project page](https://hangar.papermc.io/BlueSheep/SeleneChat)
29 | - [Twitter](https://twitter.com/BlueSheep2804)
30 |
31 | [](https://ko-fi.com/I3I2F9ODT)
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayerSpigot.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
4 | import net.kyori.adventure.text.Component
5 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer
6 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
7 | import org.bukkit.command.CommandSender
8 | import org.bukkit.entity.Player
9 | import java.util.*
10 |
11 | open class SeleneChatPlayerSpigot(private val player: Player) : SeleneChatPlayer() {
12 | override val displayName: String
13 | get() = player.displayName
14 |
15 | override val uniqueId: UUID
16 | get() = player.uniqueId
17 |
18 | override val currentServerName: String
19 | get() = ""
20 |
21 | override fun sendMessage(msg: Component) {
22 | try {
23 | player.spigot().sendMessage(*BungeeComponentSerializer.get().serialize(msg))
24 | } catch (_: NoSuchMethodError) {
25 | player.sendMessage(LegacyComponentSerializer.legacySection().serialize(msg))
26 | }
27 | }
28 |
29 | override fun sendCommandResult(msg: Component) {
30 | sendMessage(resource.prefix.append(msg))
31 | }
32 |
33 | override fun hasPermission(permission: String): Boolean {
34 | return player.hasPermission(permission)
35 | }
36 |
37 | companion object {
38 | fun getPlayer(source: CommandSender): SeleneChatPlayerSpigot {
39 | return SeleneChatPlayerSpigot(source as Player)
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayerBungee.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
4 | import net.kyori.adventure.text.Component
5 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer
6 | import net.md_5.bungee.api.CommandSender
7 | import net.md_5.bungee.api.connection.Connection
8 | import net.md_5.bungee.api.connection.ProxiedPlayer
9 | import java.util.*
10 |
11 | class SeleneChatPlayerBungee(private val player: ProxiedPlayer) : SeleneChatPlayer() {
12 | override val displayName: String
13 | get() = player.displayName
14 |
15 | override val uniqueId: UUID
16 | get() = player.uniqueId
17 |
18 | override val currentServerName: String
19 | get() = player.server.info.name
20 |
21 | override fun sendMessage(msg: Component) {
22 | player.sendMessage(*BungeeComponentSerializer.get().serialize(msg))
23 | }
24 |
25 | override fun sendCommandResult(msg: Component) {
26 | sendMessage(resource.prefix.append(msg))
27 | }
28 |
29 | override fun hasPermission(permission: String): Boolean {
30 | return player.hasPermission(permission)
31 | }
32 |
33 | companion object {
34 | fun getPlayer(source: CommandSender): SeleneChatPlayerBungee {
35 | return SeleneChatPlayerBungee(source as ProxiedPlayer)
36 | }
37 |
38 | fun getPlayer(connection: Connection): SeleneChatPlayerBungee {
39 | return SeleneChatPlayerBungee(connection as ProxiedPlayer)
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/japanize/JapanizePlayersManager.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.japanize
2 |
3 | import com.charleskorn.kaml.Yaml
4 | import kotlinx.serialization.builtins.MapSerializer
5 | import kotlinx.serialization.builtins.serializer
6 | import java.io.File
7 | import java.io.FileInputStream
8 | import java.io.FileOutputStream
9 |
10 | class JapanizePlayersManager(private val file: File) {
11 | lateinit var japanizePlayers: MutableMap
12 | private val japanizePlayersSerializer = MapSerializer(String.serializer(), Boolean.serializer())
13 | init {
14 | reload()
15 | }
16 | fun reload() {
17 | val japanizeFile = File(file, "japanize.yml")
18 | if (!file.exists()) {
19 | file.mkdir()
20 | }
21 | if (!japanizeFile.exists()) {
22 | japanizeFile.createNewFile()
23 | val japanizePlayers = emptyMap()
24 | val output = FileOutputStream(japanizeFile)
25 | Yaml.default.encodeToStream(japanizePlayersSerializer, japanizePlayers, output)
26 | }
27 | val japanizeFileInputStream = FileInputStream(japanizeFile)
28 | japanizePlayers = Yaml.default.decodeFromStream(japanizePlayersSerializer, japanizeFileInputStream).toMutableMap()
29 | }
30 | fun save() {
31 | val japanizeFile = File(file, "japanize.yml")
32 | if (!file.exists()) {
33 | file.mkdir()
34 | }
35 | val output = FileOutputStream(japanizeFile)
36 | Yaml.default.encodeToStream(japanizePlayersSerializer, japanizePlayers, output)
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/CommandVelocity.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | import com.velocitypowered.api.command.SimpleCommand
4 | import com.velocitypowered.api.proxy.ConsoleCommandSource
5 | import com.velocitypowered.api.proxy.Player
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerVelocity
7 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerVelocityConsole
8 |
9 | abstract class CommandVelocity : SimpleCommand {
10 | abstract val command: ICommand
11 | override fun execute(invocation: SimpleCommand.Invocation) {
12 | val source = invocation.source()
13 | val args = invocation.arguments()
14 | val sender = when (source) {
15 | is Player -> SeleneChatPlayerVelocity(source)
16 | is ConsoleCommandSource -> SeleneChatPlayerVelocityConsole(source)
17 | else -> return
18 | }
19 | command.execute(sender, args)
20 | }
21 |
22 | override fun hasPermission(invocation: SimpleCommand.Invocation): Boolean {
23 | return invocation.source().hasPermission(command.PERMISSION)
24 | }
25 |
26 | override fun suggest(invocation: SimpleCommand.Invocation): List {
27 | val sender = when (val source = invocation.source()) {
28 | is Player -> SeleneChatPlayerVelocity(source)
29 | is ConsoleCommandSource -> SeleneChatPlayerVelocityConsole(source)
30 | else -> return emptyList()
31 | }
32 | val args = if (invocation.arguments().isNotEmpty()) invocation.arguments() else invocation.arguments() + ""
33 | return command.suggest(sender, args)
34 | }
35 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/player/SeleneChatPlayer.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.player
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.SeleneChat.config
5 | import net.kyori.adventure.key.Key
6 | import net.kyori.adventure.text.Component
7 | import net.kyori.adventure.text.event.HoverEvent
8 | import net.kyori.examination.Examinable
9 | import java.util.*
10 |
11 | abstract class SeleneChatPlayer {
12 | abstract val displayName: String
13 | abstract val uniqueId: UUID
14 | abstract val currentServerName: String
15 | open val isOnline = true
16 | open val isConsole = false
17 | val isEnabledJapanize: Boolean
18 | get() {
19 | return if (SeleneChat.japanizePlayers.containsKey(uniqueId.toString())) {
20 | SeleneChat.japanizePlayers[uniqueId.toString()]!!
21 | } else {
22 | config.japanizeDefault
23 | }
24 | }
25 | abstract fun sendMessage(msg: Component)
26 | abstract fun sendCommandResult(msg: Component)
27 | open fun asHoverEvent(): HoverEvent {
28 | return HoverEvent.showEntity(Key.key("player"), uniqueId, Component.text(displayName))
29 | }
30 | abstract fun hasPermission(permission: String): Boolean
31 | fun enableJapanize() {
32 | SeleneChat.japanizePlayers[uniqueId.toString()] = true
33 | SeleneChat.japanizePlayersManager.save()
34 | }
35 | fun disableJapanize() {
36 | SeleneChat.japanizePlayers[uniqueId.toString()] = false
37 | SeleneChat.japanizePlayersManager.save()
38 | }
39 | fun toggleJapanize() {
40 | if (isEnabledJapanize) disableJapanize() else enableJapanize()
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/JapanizeCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
4 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
5 |
6 | class JapanizeCommand : ICommand {
7 | override val COMMAND_NAME: String = JapanizeCommand.COMMAND_NAME
8 | override val COMMAND_ALIASES: Array = JapanizeCommand.COMMAND_ALIASES
9 | override val PERMISSION: String = JapanizeCommand.PERMISSION
10 |
11 | override fun execute(sender: SeleneChatPlayer, args: Array): Boolean {
12 | if (args.isEmpty()) {
13 | sender.sendCommandResult(resource.command.japanizeSuccessCurrentValueComponent(sender.isEnabledJapanize))
14 | } else {
15 | if (args[0] == "on") {
16 | sender.enableJapanize()
17 | } else if (args[0] == "off") {
18 | sender.disableJapanize()
19 | } else {
20 | sender.sendCommandResult(resource.command.japanizeErrorUnexpectedArgs)
21 | return false
22 | }
23 | sender.sendCommandResult(resource.command.japanizeSuccessChangedComponent(sender.isEnabledJapanize))
24 | }
25 | return true
26 | }
27 |
28 | override fun suggest(sender: SeleneChatPlayer, args: Array): List {
29 | return when (args.size) {
30 | 1 -> listOf("on", "off").filter { it.startsWith(args[0]) || args[0] == "" }
31 | else -> emptyList()
32 | }
33 | }
34 |
35 | companion object {
36 | const val COMMAND_NAME = "japanize"
37 | val COMMAND_ALIASES = arrayOf("jp")
38 | const val PERMISSION = "selenechat.command.japanize"
39 | }
40 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/resource/ResourceManager.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.resource
2 |
3 | import com.charleskorn.kaml.Yaml
4 | import com.charleskorn.kaml.YamlConfiguration
5 | import java.io.File
6 | import java.io.FileInputStream
7 | import java.io.FileOutputStream
8 |
9 | class ResourceManager(private val file: File) {
10 | lateinit var resource: ResourceData
11 | private val yamlConfiguration = YamlConfiguration(strictMode = false, breakScalarsAt = 160)
12 | private val yaml = Yaml(configuration = yamlConfiguration)
13 | private val defaultResource = ResourceData()
14 | init {
15 | reload()
16 | }
17 |
18 | fun reload() {
19 | val resourceFile = File(file, "message.yml")
20 | if (!file.exists()) {
21 | file.mkdir()
22 | }
23 | if (!resourceFile.exists()) {
24 | resourceFile.createNewFile()
25 | val messages = ResourceData()
26 | val output = FileOutputStream(resourceFile)
27 | yaml.encodeToStream(ResourceData.serializer(), messages, output)
28 | }
29 | val resourceFileInputStream = FileInputStream(resourceFile)
30 | this.resource = yaml.decodeFromStream(ResourceData.serializer(), resourceFileInputStream)
31 |
32 | if (resource.resourceVersion < defaultResource.resourceVersion) {
33 | resource.resourceVersion = defaultResource.resourceVersion
34 | save()
35 | }
36 | }
37 |
38 | fun save() {
39 | val resourceFile = File(file, "message.yml")
40 | if (!file.exists()) {
41 | file.mkdir()
42 | }
43 | val output = FileOutputStream(resourceFile)
44 | yaml.encodeToStream(ResourceData.serializer(), resource, output)
45 | }
46 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/EditInfoCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
5 | import io.github.bluesheep2804.selenechat.channel.ChannelData
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
7 | import net.kyori.adventure.text.Component
8 | import net.kyori.adventure.text.format.NamedTextColor
9 | import java.util.*
10 |
11 | class EditInfoCommand: SubEditCommand() {
12 | override val commandName: String = "info"
13 | override val permission: String = "selenechat.channel.info"
14 |
15 | override fun execute(sender: SeleneChatPlayer, args: Array, channel: ChannelData): Boolean {
16 | val component = Component.text().append(resource.command.channelSuccessEditInfoHeader(channel)).appendNewline()
17 |
18 | if (channel.playerList.isEmpty()) {
19 | component.append(resource.command.channelSuccessEditInfoNoPlayer)
20 | } else {
21 | component.append(resource.command.channelSuccessEditInfoPlayer(channel.playerList.size)).appendNewline()
22 | channel.playerList.forEach {
23 | val player = SeleneChat.plugin.getPlayer(UUID.fromString(it))
24 | component.append(
25 | (
26 | if (player.isOnline) Component.text(player.displayName) else Component.translatable("gui.socialInteractions.status_offline").color(NamedTextColor.GRAY)
27 | ).hoverEvent(player.asHoverEvent())
28 | ).append(Component.text(", "))
29 | }
30 | }
31 |
32 | sender.sendMessage(component.build())
33 | return true
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/SeleneChatCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
5 |
6 | class SeleneChatCommand : ICommand {
7 | override val COMMAND_NAME: String = SeleneChatCommand.COMMAND_NAME
8 | override val COMMAND_ALIASES: Array = SeleneChatCommand.COMMAND_ALIASES
9 | override val PERMISSION: String = SeleneChatCommand.PERMISSION
10 |
11 | override fun execute(sender: SeleneChatPlayer, args: Array): Boolean {
12 | if (args.isEmpty()) {
13 | sender.sendCommandResult(SeleneChat.resource.command.selenechatErrorSubCommandEmpty)
14 | return false
15 | }
16 | if (args[0] == "reload") {
17 | if (!sender.hasPermission("selenechat.command.selenechat.reload")) {
18 | sender.sendCommandResult(SeleneChat.resource.command.selenechatErrorSubCommandPermission)
19 | return false
20 | }
21 | SeleneChat.configManager.reload()
22 | SeleneChat.resourceManager.reload()
23 | SeleneChat.japanizePlayersManager.reload()
24 | SeleneChat.channelManager.reload()
25 | sender.sendCommandResult(SeleneChat.resource.command.selenechatSuccessReload)
26 | }
27 | return true
28 | }
29 |
30 | override fun suggest(sender: SeleneChatPlayer, args: Array): List {
31 | return when (args.size) {
32 | 1 -> listOf("reload").filter { it.startsWith(args[0]) || args[0] == "" }
33 | else -> emptyList()
34 | }
35 | }
36 |
37 | companion object {
38 | const val COMMAND_NAME = "selenechat"
39 | val COMMAND_ALIASES = arrayOf("sc")
40 | const val PERMISSION = "selenechat.command.selenechat"
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/LeaveCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import arrow.core.Either
4 | import io.github.bluesheep2804.selenechat.SeleneChat
5 | import io.github.bluesheep2804.selenechat.channel.ChannelData
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
7 |
8 | class LeaveCommand: SubCommand() {
9 | override val commandName: String = "leave"
10 | override val permission: String = "selenechat.channel.leave"
11 |
12 | override fun execute(sender: SeleneChatPlayer, args: Array): Boolean {
13 | val channel = if (args.size < 2) {
14 | SeleneChat.channelManager.getPlayerChannel(sender)
15 | } else {
16 | SeleneChat.channelManager.allChannels[args[1]]
17 | }
18 | if (channel is ChannelData) {
19 | when (val result = channel.leave(sender)) {
20 | is Either.Left -> {
21 | sender.sendCommandResult(when (result.value) {
22 | is ChannelData.ChannelLeaveError.NotInChannel -> SeleneChat.resource.command.channelErrorLeaveNotInChannel
23 | })
24 | }
25 | is Either.Right -> {
26 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessLeave(channel))
27 |
28 | if (channel.name == SeleneChat.channelManager.playerChannelMap[sender.uniqueId]) {
29 | SeleneChat.channelManager.playerChannelMap.remove(sender.uniqueId)
30 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessJoinSwitchGlobal)
31 | }
32 | }
33 | }
34 | } else {
35 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorLeaveNotFound)
36 | return false
37 | }
38 | return true
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/DeleteCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import arrow.core.Either
4 | import io.github.bluesheep2804.selenechat.SeleneChat
5 | import io.github.bluesheep2804.selenechat.channel.ChannelData
6 | import io.github.bluesheep2804.selenechat.channel.ChannelManager
7 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
8 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerConsole
9 |
10 | class DeleteCommand: SubCommand() {
11 | override val commandName: String = "delete"
12 | override val permission: String = "selenechat.channel.delete"
13 |
14 | override fun execute(sender: SeleneChatPlayer, args: Array): Boolean {
15 | if (args.size < 2) {
16 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorDeleteEmpty)
17 | return false
18 | }
19 | val channel = SeleneChat.channelManager.allChannels[args[1]]
20 | if (channel !is ChannelData) {
21 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorDeleteNotExists)
22 | return false
23 | }
24 |
25 | if (!channel.isModerator(sender) && sender !is SeleneChatPlayerConsole) {
26 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorDeleteNotModerator)
27 | return false
28 | }
29 | when (val result = SeleneChat.channelManager.delete(args[1])) {
30 | is Either.Left -> {
31 | sender.sendCommandResult(when (result.value) {
32 | is ChannelManager.ChannelDeleteError.ChannelNotFound -> SeleneChat.resource.command.channelErrorDeleteNotExists
33 | })
34 | return false
35 | }
36 | is Either.Right -> sender.sendCommandResult(SeleneChat.resource.command.channelSuccessDelete(result.value))
37 | }
38 | return true
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/listener/ChatListenerVelocity.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.listener
2 |
3 | import com.velocitypowered.api.event.Subscribe
4 | import com.velocitypowered.api.event.connection.PluginMessageEvent
5 | import com.velocitypowered.api.event.player.PlayerChatEvent
6 | import io.github.bluesheep2804.selenechat.SeleneChat.config
7 | import io.github.bluesheep2804.selenechat.SeleneChat.plugin
8 | import io.github.bluesheep2804.selenechat.SeleneChatVelocity
9 | import io.github.bluesheep2804.selenechat.message.ChatMessage
10 | import io.github.bluesheep2804.selenechat.message.PluginMessage
11 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerVelocity
12 |
13 | class ChatListenerVelocity(plugin: SeleneChatVelocity) {
14 | private val proxy = plugin.proxy
15 | private val logger = plugin.logger
16 | @Subscribe
17 | fun onPlayerChatEvent(event: PlayerChatEvent) {
18 | val sender = SeleneChatPlayerVelocity(event.player)
19 | val message = event.message
20 |
21 | // デフォルトのイベントを無効化する
22 | // クライアントのバージョンが1.19.1以降だとキックされるがUnSignedVelocityで回避できる
23 | event.result = PlayerChatEvent.ChatResult.denied()
24 | ChatListener.chat(message, sender)
25 | }
26 |
27 | @Subscribe
28 | fun onPluginMessageEvent(event: PluginMessageEvent) {
29 | if (event.identifier.id != "selenechat:message") {
30 | return
31 | }
32 | if (!config.shouldReceivePluginMessage) {
33 | return
34 | }
35 | val input = event.dataAsDataStream()
36 | val pm = PluginMessage.fromByteArrayDataInput(input)
37 | val sender = plugin.getPlayer(pm.player.uniqueId)
38 | val returnMessage = ChatMessage.chat(pm.message, sender)
39 |
40 | for (server in proxy.allServers) {
41 | if (server.serverInfo.name != sender.currentServerName) {
42 | server.sendMessage(returnMessage)
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/ListCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat.channelManager
4 | import io.github.bluesheep2804.selenechat.SeleneChat.resource
5 | import io.github.bluesheep2804.selenechat.channel.ChannelData
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
7 | import net.kyori.adventure.text.Component
8 | import net.kyori.adventure.text.format.NamedTextColor
9 |
10 | class ListCommand: SubCommand() {
11 | override val commandName: String = "list"
12 | override val permission: String = "selenechat.channel.list"
13 |
14 | override fun execute(sender: SeleneChatPlayer, args: Array): Boolean {
15 | val returnMessage = Component.text().append(resource.command.channelSuccessList)
16 | channelManager.allChannels.forEach { (_, channel) ->
17 | if (!channel.visible) return@forEach
18 | returnMessage.appendNewline()
19 | .append(channelIndicator(sender, channel)).appendSpace()
20 | .append(channel.displayName)
21 | .append(Component.text("(${channel.name})", NamedTextColor.GRAY))
22 | }
23 | sender.sendCommandResult(returnMessage.build())
24 | return true
25 | }
26 |
27 | private fun channelIndicator(sender: SeleneChatPlayer, channel: ChannelData): Component {
28 | if (channelManager.playerChannelMap[sender.uniqueId] == channel.name) {
29 | return resource.command.channelSuccessListIndicatorSpeak.hoverEvent(resource.command.channelSuccessListIndicatorSpeakHover)
30 | }
31 |
32 | if (channel.playerList.contains(sender.uniqueId.toString())) {
33 | return resource.command.channelSuccessListIndicatorJoins.hoverEvent(resource.command.channelSuccessListIndicatorJoinsHover)
34 | }
35 |
36 | return resource.command.channelSuccessListIndicator.hoverEvent(resource.command.channelSuccessListIndicatorHover)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/resource/ResourceData.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.resource
2 |
3 | import io.github.bluesheep2804.selenechat.common.ComponentSerializer
4 | import kotlinx.serialization.Serializable
5 | import net.kyori.adventure.text.Component
6 | import net.kyori.adventure.text.format.NamedTextColor
7 | import net.kyori.adventure.text.minimessage.MiniMessage
8 |
9 | @Serializable
10 | data class ResourceData(
11 | var resourceVersion: Int = 1,
12 | val configVersionOutdated: String = "The config file appears to be out of date. The config file will be loaded, but unexpected glitches may occur.",
13 | val configVersionNewer: String = "The config file has been created with a newer version than the current one. The config file will be loaded, but unexpected glitches may occur.",
14 | val configVersionLatest: String = "The config file is up-to-date!",
15 | @Serializable(with = ComponentSerializer::class)
16 | val prefix: Component = MiniMessage.miniMessage().deserialize("[<#d9e4ff>SC]"),
17 | @Serializable(with = ComponentSerializer::class)
18 | val enabled: Component = Component.text("Enabled", NamedTextColor.GREEN),
19 | @Serializable(with = ComponentSerializer::class)
20 | val disabled: Component = Component.text("Disabled", NamedTextColor.RED),
21 | @Serializable(with = ComponentSerializer::class)
22 | val offline: Component = Component.translatable("gui.socialInteractions.status_offline"),
23 | @Serializable(with = ComponentSerializer::class)
24 | val hoverTextServer: Component = Component.translatable("selectServer.select"),
25 | @Serializable(with = ComponentSerializer::class)
26 | val hoverTextChannel: Component = Component.text("Change chat channel"),
27 | val command: CommandResourceData = CommandResourceData()
28 | ) {
29 | fun switch(value: Boolean): Component {
30 | return if (value) {
31 | enabled
32 | } else {
33 | disabled
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/japanize/IMEConverter.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.japanize
2 |
3 | import com.google.common.io.CharStreams
4 | import io.github.bluesheep2804.selenechat.japanize.GoogleIME.parseJson
5 | import java.io.BufferedReader
6 | import java.io.IOException
7 | import java.io.InputStreamReader
8 | import java.io.UnsupportedEncodingException
9 | import java.net.*
10 |
11 | /**
12 | * ひらがなのみの文章を漢字に変換するクラス
13 | * @author ucchy, BlueSheep2804
14 | * @see [LunaChat Github](https://github.com/ucchyocean/LunaChat/tree/master/src/main/java/com/github/ucchyocean/lc3/japanize/IMEConverter.java)
15 | */
16 | object IMEConverter {
17 | private const val GOOGLE_IME_URL = "http://www.google.com/transliterate?langpair=ja-Hira|ja&text="
18 | fun googleIME(original: String?): String {
19 | var urlconn: HttpURLConnection? = null
20 | var reader: BufferedReader? = null
21 | return try {
22 | val url = URL(GOOGLE_IME_URL + URLEncoder.encode(original, "UTF-8"))
23 | urlconn = url.openConnection() as HttpURLConnection
24 | urlconn.requestMethod = "GET"
25 | urlconn.instanceFollowRedirects = false
26 | urlconn.connect()
27 | reader = BufferedReader(
28 | InputStreamReader(urlconn.inputStream, "UTF-8")
29 | )
30 | val json = CharStreams.toString(reader)
31 | parseJson(json)
32 | } catch (e: ProtocolException) {
33 | throw RuntimeException(e)
34 | } catch (e: MalformedURLException) {
35 | throw RuntimeException(e)
36 | } catch (e: UnsupportedEncodingException) {
37 | throw RuntimeException(e)
38 | } catch (e: IOException) {
39 | throw RuntimeException(e)
40 | } finally {
41 | urlconn?.disconnect()
42 | if (reader != null) {
43 | try {
44 | reader.close()
45 | } catch (e: IOException) {
46 | throw RuntimeException(e)
47 | }
48 | }
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/JoinCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import arrow.core.Either
4 | import io.github.bluesheep2804.selenechat.SeleneChat
5 | import io.github.bluesheep2804.selenechat.channel.ChannelData
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
7 |
8 | class JoinCommand: SubCommand() {
9 | override val commandName: String = "join"
10 | override val permission: String = "selenechat.channel.join"
11 |
12 | override fun execute(sender: SeleneChatPlayer, args: Array): Boolean {
13 | if (args.size < 2) {
14 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorJoinEmpty)
15 | return false
16 | }
17 |
18 | val channel = SeleneChat.channelManager.allChannels[args[1]]
19 | if (channel is ChannelData) {
20 | when (val result = channel.join(sender)) {
21 | is Either.Left -> when (result.value) {
22 | ChannelData.ChannelJoinError.ConsolePlayer -> {
23 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorJoinConsole)
24 | return false
25 | }
26 | ChannelData.ChannelJoinError.AlreadyJoins -> {}
27 | }
28 | is Either.Right -> sender.sendCommandResult(SeleneChat.resource.command.channelSuccessJoin(channel))
29 | }
30 | SeleneChat.channelManager.playerChannelMap[sender.uniqueId] = channel.name
31 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessJoinSwitch(channel))
32 | } else {
33 | if (args[1] == SeleneChat.config.globalMarker) {
34 | SeleneChat.channelManager.playerChannelMap.remove(sender.uniqueId)
35 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessJoinSwitchGlobal)
36 | } else {
37 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorJoinNotFound)
38 | return false
39 | }
40 | }
41 | return true
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/config/SeleneChatConfigManager.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.config
2 |
3 | import com.charleskorn.kaml.Yaml
4 | import com.charleskorn.kaml.YamlConfiguration
5 | import io.github.bluesheep2804.selenechat.SeleneChat
6 | import java.io.File
7 | import java.io.FileInputStream
8 | import java.io.FileOutputStream
9 |
10 | class SeleneChatConfigManager(private val file: File) {
11 | lateinit var config: SeleneChatConfigData
12 | private val yamlConfiguration = YamlConfiguration(strictMode = false, breakScalarsAt = 120)
13 | private val yaml = Yaml(configuration = yamlConfiguration)
14 | private val defaultConfig = SeleneChatConfigData()
15 | init {
16 | reload()
17 | }
18 | fun reload() {
19 | val configFile = File(file, "config.yml")
20 | if (!file.exists()) {
21 | file.mkdir()
22 | }
23 | if (!configFile.exists()) {
24 | configFile.createNewFile()
25 | val config = SeleneChatConfigData()
26 | val output = FileOutputStream(configFile)
27 | yaml.encodeToStream(SeleneChatConfigData.serializer(), config, output)
28 | }
29 | val configFileInputStream = FileInputStream(configFile)
30 | config = yaml.decodeFromStream(SeleneChatConfigData.serializer(), configFileInputStream)
31 |
32 | if (config.configVersion < defaultConfig.configVersion) {
33 | config.configVersion = defaultConfig.configVersion
34 | save()
35 | }
36 | }
37 |
38 | fun save() {
39 | val configFile = File(file, "config.yml")
40 | if (!file.exists()) {
41 | file.mkdir()
42 | }
43 | val output = FileOutputStream(configFile)
44 | yaml.encodeToStream(SeleneChatConfigData.serializer(), config, output)
45 | }
46 |
47 | fun checkVersion(): String {
48 | return if (config.configVersion < defaultConfig.configVersion) SeleneChat.resource.configVersionOutdated
49 | else if (config.configVersion > defaultConfig.configVersion) SeleneChat.resource.configVersionNewer
50 | else SeleneChat.resource.configVersionLatest
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/listener/ChatListenerBungee.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.listener
2 |
3 | import com.google.common.io.ByteStreams
4 | import io.github.bluesheep2804.selenechat.SeleneChat
5 | import io.github.bluesheep2804.selenechat.SeleneChat.config
6 | import io.github.bluesheep2804.selenechat.SeleneChatBungee
7 | import io.github.bluesheep2804.selenechat.message.ChatMessage
8 | import io.github.bluesheep2804.selenechat.message.PluginMessage
9 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerBungee
10 | import net.md_5.bungee.api.connection.ProxiedPlayer
11 | import net.md_5.bungee.api.event.ChatEvent
12 | import net.md_5.bungee.api.event.PluginMessageEvent
13 | import net.md_5.bungee.api.plugin.Listener
14 | import net.md_5.bungee.event.EventHandler
15 |
16 | class ChatListenerBungee(private val plugin: SeleneChatBungee) : Listener {
17 | private val proxy = plugin.proxy
18 | private val logger = proxy.logger
19 | @EventHandler
20 | fun onChat(event: ChatEvent) {
21 | if (event.isCommand || event.isProxyCommand) {
22 | return
23 | }
24 | if (event.sender !is ProxiedPlayer) {
25 | return
26 | }
27 | proxy.scheduler.runAsync(plugin) {
28 | val message = event.message
29 | val sender = SeleneChatPlayerBungee.getPlayer(event.sender)
30 | ChatListener.chat(message, sender)
31 | }
32 | event.isCancelled = true
33 | }
34 |
35 | @EventHandler
36 | fun onPluginMessage(event: PluginMessageEvent) {
37 | if (event.tag != "selenechat:message") {
38 | return
39 | }
40 | if (!config.shouldReceivePluginMessage) {
41 | return
42 | }
43 | val input = ByteStreams.newDataInput(event.data)
44 | val pm = PluginMessage.fromByteArrayDataInput(input)
45 | val sender = SeleneChat.plugin.getPlayer(pm.player.uniqueId)
46 | val returnMessage = ChatMessage.chat(pm.message, sender)
47 |
48 | for (player in SeleneChat.plugin.getAllPlayers()) {
49 | if (player.currentServerName != sender.currentServerName) {
50 | player.sendMessage(returnMessage)
51 | }
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/MessageCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.message.ChatMessage
5 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
6 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerOffline
7 |
8 | class MessageCommand : ICommand {
9 | override val COMMAND_NAME: String = MessageCommand.COMMAND_NAME
10 | override val COMMAND_ALIASES: Array = MessageCommand.COMMAND_ALIASES
11 | override val PERMISSION: String = MessageCommand.PERMISSION
12 |
13 | override fun execute(sender: SeleneChatPlayer, args: Array): Boolean {
14 | if (args.isEmpty()) {
15 | sender.sendCommandResult(SeleneChat.resource.command.messageErrorPlayer)
16 | return false
17 | }
18 | if (args.size == 1) {
19 | sender.sendCommandResult(SeleneChat.resource.command.messageErrorMessage)
20 | return false
21 | }
22 | val receiver = SeleneChat.plugin.getPlayer(args[0])
23 | if (receiver is SeleneChatPlayerOffline) {
24 | sender.sendCommandResult(SeleneChat.resource.command.messageErrorPlayerNotFoundComponent(args[0]))
25 | return false
26 | }
27 |
28 | var message = args[1]
29 | if (args.size > 2) {
30 | for (i in 2 until args.size) {
31 | message += " ${args[i]}"
32 | }
33 | }
34 |
35 | val returnMessage = ChatMessage.privateMessage(message, sender, receiver)
36 | sender.sendMessage(returnMessage)
37 | receiver.sendMessage(returnMessage)
38 | return true
39 | }
40 |
41 | override fun suggest(sender: SeleneChatPlayer, args: Array): List {
42 | return when (args.size) {
43 | 1 -> (SeleneChat.plugin.getAllPlayers().map { it.displayName }).filter { it.startsWith(args[0]) || args[0] == "" }
44 | else -> emptyList()
45 | }
46 | }
47 |
48 | companion object {
49 | const val COMMAND_NAME = "message"
50 | val COMMAND_ALIASES = arrayOf("msg", "tell", "w")
51 | const val PERMISSION = "selenechat.command.message"
52 | }
53 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/channel/ChannelData.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.channel
2 |
3 | import arrow.core.Either
4 | import arrow.core.left
5 | import arrow.core.right
6 | import io.github.bluesheep2804.selenechat.SeleneChat
7 | import io.github.bluesheep2804.selenechat.common.ComponentSerializer
8 | import io.github.bluesheep2804.selenechat.common.ConvertMode
9 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
10 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerConsole
11 | import kotlinx.serialization.Serializable
12 | import net.kyori.adventure.text.Component
13 | import java.util.*
14 |
15 | @Serializable
16 | data class ChannelData(
17 | var version: Int = 1,
18 | val name: String,
19 | @Serializable(with = ComponentSerializer::class)
20 | var displayName: Component = Component.text(name),
21 | var format: String = "",
22 | var japanize: ConvertMode = ConvertMode.IME,
23 | var moderators: MutableList = mutableListOf(),
24 | val playerList: MutableList = mutableListOf(),
25 | var visible: Boolean = true,
26 | ) {
27 | fun join(player: SeleneChatPlayer): Either {
28 | if (player is SeleneChatPlayerConsole) return ChannelJoinError.ConsolePlayer.left()
29 | if (playerList.contains(player.uniqueId.toString())) return ChannelJoinError.AlreadyJoins.left()
30 | playerList.add(player.uniqueId.toString())
31 | SeleneChat.channelManager.save(this)
32 | return player.right()
33 | }
34 |
35 | fun leave(player: SeleneChatPlayer): Either {
36 | if (!playerList.contains(player.uniqueId.toString())) return ChannelLeaveError.NotInChannel.left()
37 | playerList.remove(player.uniqueId.toString())
38 | SeleneChat.channelManager.save(this)
39 | return player.right()
40 | }
41 |
42 | fun sendMessage(text: Component) {
43 | playerList.forEach {
44 | SeleneChat.plugin.getPlayer(UUID.fromString(it)).sendMessage(text) // TODO: プレイヤーのキャッシュをするべきな気がする
45 | }
46 | }
47 |
48 | fun isModerator(player: SeleneChatPlayer): Boolean {
49 | return moderators.contains(player.uniqueId.toString())
50 | }
51 |
52 | sealed interface ChannelJoinError {
53 | object AlreadyJoins: ChannelJoinError
54 | object ConsolePlayer: ChannelJoinError
55 | }
56 |
57 | sealed interface ChannelLeaveError {
58 | object NotInChannel: ChannelLeaveError
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: SeleneChat
2 | version: ${version}
3 | description: Chat plugin inspired by LunaChat
4 | main: io.github.bluesheep2804.selenechat.SeleneChatSpigot
5 | author: BlueSheep2804
6 | api-version: 1.13
7 |
8 | commands:
9 | selenechat:
10 | description: SeleneChat command
11 | aliases:
12 | - sc
13 | permission: selenechat.command.selenechat
14 | message:
15 | description: Selenechat message command
16 | aliases:
17 | - msg
18 | - tell
19 | - w
20 | permission: selenechat.command.message
21 | japanize:
22 | description: SeleneChat japanize command
23 | aliases:
24 | - jp
25 | permission: selenechat.command.japanize
26 | channel:
27 | description: SeleneChat channel command
28 | aliases:
29 | - ch
30 | permission: selenechat.command.channel
31 |
32 | permissions:
33 | selenechat.colorcode:
34 | description: Allow color codes to be used in chat
35 | default: true
36 | selenechat.command.selenechat:
37 | description: Allow the use of SeleneChat commands
38 | default: op
39 | selenechat.command.selenechat.reload:
40 | description: Allow use of SeleneChat reload command
41 | default: op
42 | selenechat.command.message:
43 | description: Allow use of SeleneChat message command
44 | default: true
45 | selenechat.command.japanize:
46 | description: Allow use of SeleneChat japanize command
47 | default: true
48 | selenechat.channel:
49 | description: Allow use of SeleneChat channel command
50 | default: true
51 | selenechat.channel.create:
52 | description: Allow use of channel create command
53 | default: true
54 | selenechat.channel.delete:
55 | description: Allow use of channel delete command
56 | default: true
57 | selenechat.channel.list:
58 | description: Allow use of channel list command
59 | default: true
60 | selenechat.channel.join:
61 | description: Allow use of channel join command
62 | default: true
63 | selenechat.channel.leave:
64 | description: Allow use of channel leave command
65 | default: true
66 |
67 | selenechat.channel.format:
68 | description: Allow use of channel format command
69 | default: true
70 | selenechat.channel.info:
71 | description: Allow use of channel info command,
72 | default: true
73 | selenechat.channel.jp:
74 | description: Allow use of channel jp command
75 | default: true
76 | selenechat.channel.moderator:
77 | description: Allow use of channel moderator command
78 | default: true
79 | selenechat.channel.visible:
80 | description: Allow use of channel visible command
81 | default: true
82 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if %ERRORLEVEL% equ 0 goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if %ERRORLEVEL% equ 0 goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | set EXIT_CODE=%ERRORLEVEL%
84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
86 | exit /b %EXIT_CODE%
87 |
88 | :mainEnd
89 | if "%OS%"=="Windows_NT" endlocal
90 |
91 | :omega
92 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/command/channel/EditModeratorCommand.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.command.channel
2 |
3 | import io.github.bluesheep2804.selenechat.SeleneChat
4 | import io.github.bluesheep2804.selenechat.channel.ChannelData
5 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
6 | import net.kyori.adventure.key.Key
7 | import net.kyori.adventure.text.Component
8 | import net.kyori.adventure.text.event.HoverEvent
9 | import net.kyori.adventure.text.format.NamedTextColor
10 | import java.util.*
11 |
12 | class EditModeratorCommand: SubEditCommand() {
13 | override val commandName: String = "moderator"
14 | override val permission: String = "selenechat.channel.moderator"
15 |
16 | override fun execute(sender: SeleneChatPlayer, args: Array, channel: ChannelData): Boolean {
17 | if (args.size < 3) {
18 | val moderators = Component.text().append(SeleneChat.resource.command.channelSuccessEditModeratorCurrentValue)
19 | channel.moderators.forEach {
20 | val player = SeleneChat.plugin.getPlayer(UUID.fromString(it))
21 | val playerComponent = if (player.isOnline) {
22 | Component.text(player.displayName).hoverEvent(player.asHoverEvent())
23 | } else {
24 | Component.text().content("(")
25 | .append(SeleneChat.resource.offline)
26 | .append(Component.text(")${it}"))
27 | .color(NamedTextColor.GRAY)
28 | .hoverEvent(HoverEvent.showEntity(Key.key("player"), player.uniqueId))
29 | }
30 | moderators.appendNewline()
31 | .append(Component.text("- "))
32 | .append(playerComponent)
33 | }
34 | sender.sendCommandResult(moderators.build())
35 | } else {
36 | val player = SeleneChat.plugin.getPlayer(if (args[2].startsWith("-")) args[2].removePrefix("-") else args[2])
37 | if (!player.isOnline) {
38 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorEditModeratorNotOnline)
39 | return false
40 | }
41 | if (args[2].startsWith("-")) {
42 | if (!channel.isModerator(player)) {
43 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorEditModeratorNotModerator)
44 | return false
45 | }
46 | channel.moderators -= player.uniqueId.toString()
47 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessEditModeratorExclude(player))
48 | } else {
49 | if (channel.isModerator(player)) {
50 | sender.sendCommandResult(SeleneChat.resource.command.channelErrorEditModeratorAlreadyModerator)
51 | return false
52 | }
53 | channel.moderators += player.uniqueId.toString()
54 | sender.sendCommandResult(SeleneChat.resource.command.channelSuccessEditModerator(player))
55 | }
56 | SeleneChat.channelManager.save(channel)
57 | }
58 | return true
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/channel/ChannelManager.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.channel
2 |
3 | import arrow.core.Either
4 | import arrow.core.left
5 | import arrow.core.right
6 | import com.charleskorn.kaml.Yaml
7 | import com.charleskorn.kaml.YamlConfiguration
8 | import io.github.bluesheep2804.selenechat.SeleneChat
9 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
10 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerConsole
11 | import java.io.File
12 | import java.io.FileInputStream
13 | import java.io.FileOutputStream
14 | import java.util.*
15 |
16 | class ChannelManager(private val file: File) {
17 | private val channelDirectory = File(file, "channel")
18 | private val yamlConfiguration = YamlConfiguration(strictMode = false)
19 | private val yaml = Yaml(configuration = yamlConfiguration)
20 | val allChannels = mutableMapOf()
21 | val playerChannelMap = mutableMapOf()
22 | val defaultChannel = ChannelData(name = "")
23 |
24 | init {
25 | reload()
26 | }
27 |
28 | fun reload() {
29 | if (allChannels.isNotEmpty()) {
30 | allChannels.clear()
31 | }
32 | channelDirectory.listFiles()?.forEach {
33 | val input = FileInputStream(it)
34 | val channel = yaml.decodeFromStream(ChannelData.serializer(), input)
35 | allChannels[channel.name] = channel
36 |
37 | if (defaultChannel.version > channel.version) {
38 | channel.version = defaultChannel.version
39 | save(channel)
40 | }
41 | }
42 | }
43 |
44 | fun save(channel: ChannelData) {
45 | val channelFile = File(channelDirectory, "${channel.name}.yml")
46 | val output = FileOutputStream(channelFile)
47 | yaml.encodeToStream(ChannelData.serializer(), channel, output)
48 | }
49 |
50 | fun create(name: String, moderator: SeleneChatPlayer): Either {
51 | if (!allChannels.none { it.key == name }) {
52 | return ChannelCreateError.AlreadyExists.left()
53 | }
54 | val channelFile = File(channelDirectory, "${name}.yml")
55 | val channel = ChannelData(name=name)
56 | channel.japanize = SeleneChat.plugin.config.convertMode
57 | if (moderator !is SeleneChatPlayerConsole) {
58 | channel.moderators += moderator.uniqueId.toString()
59 | }
60 |
61 | if (!channelDirectory.exists()) {
62 | channelDirectory.mkdirs()
63 | }
64 | channelFile.createNewFile()
65 | val output = FileOutputStream(channelFile)
66 | yaml.encodeToStream(ChannelData.serializer(), channel, output)
67 | allChannels[channel.name] = channel
68 | return channel.right()
69 | }
70 |
71 | sealed interface ChannelCreateError {
72 | object AlreadyExists : ChannelCreateError
73 | }
74 |
75 | fun delete(name: String): Either {
76 | val channel = allChannels.remove(name) ?: return ChannelDeleteError.ChannelNotFound.left()
77 | val channelFile = File(channelDirectory, "${name}.yml")
78 | if (channelFile.exists()) {
79 | channelFile.delete()
80 | }
81 | return channel.right()
82 | }
83 |
84 | sealed interface ChannelDeleteError {
85 | object ChannelNotFound : ChannelDeleteError
86 | }
87 |
88 | fun getPlayerChannel(player: SeleneChatPlayer): ChannelData? {
89 | val channelName = playerChannelMap[player.uniqueId]
90 | return allChannels[channelName]
91 | }
92 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/SeleneChatBungee.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat
2 |
3 | import io.github.bluesheep2804.selenechat.channel.ChannelManager
4 | import io.github.bluesheep2804.selenechat.command.ChannelCommandBungee
5 | import io.github.bluesheep2804.selenechat.command.JapanizeCommandBungee
6 | import io.github.bluesheep2804.selenechat.command.MessageCommandBungee
7 | import io.github.bluesheep2804.selenechat.command.SeleneChatCommandBungee
8 | import io.github.bluesheep2804.selenechat.common.Platforms
9 | import io.github.bluesheep2804.selenechat.config.SeleneChatConfigManager
10 | import io.github.bluesheep2804.selenechat.japanize.JapanizePlayersManager
11 | import io.github.bluesheep2804.selenechat.listener.ChatListenerBungee
12 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
13 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerBungee
14 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerOffline
15 | import io.github.bluesheep2804.selenechat.resource.ResourceManager
16 | import net.kyori.adventure.platform.bungeecord.BungeeAudiences
17 | import net.kyori.adventure.text.Component
18 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer
19 | import net.md_5.bungee.api.plugin.Plugin
20 | import java.util.*
21 |
22 | class SeleneChatBungee : Plugin(), IPlugin {
23 | private lateinit var adventure: BungeeAudiences
24 | override val platform = Platforms.BUNGEECORD
25 | override val configManager: SeleneChatConfigManager = SeleneChatConfigManager(dataFolder)
26 | override val resourceManager: ResourceManager = ResourceManager(dataFolder)
27 | override val japanizePlayersManager: JapanizePlayersManager = JapanizePlayersManager(dataFolder)
28 | override val channelManager: ChannelManager = ChannelManager(dataFolder)
29 | init {
30 | SeleneChat.setPluginInstance(this)
31 |
32 | logger.info(configManager.checkVersion())
33 | }
34 |
35 | override fun onEnable() {
36 | adventure = BungeeAudiences.create(this)
37 | proxy.pluginManager.registerListener(this, ChatListenerBungee(this))
38 | proxy.registerChannel("selenechat:message")
39 |
40 | proxy.pluginManager.registerCommand(this, SeleneChatCommandBungee())
41 | proxy.pluginManager.registerCommand(this, MessageCommandBungee())
42 | proxy.pluginManager.registerCommand(this, JapanizeCommandBungee())
43 | proxy.pluginManager.registerCommand(this, ChannelCommandBungee())
44 |
45 | logger.info("Loaded!")
46 | }
47 |
48 | override fun onDisable() {
49 | adventure.close()
50 | }
51 |
52 | override fun getAllPlayers(): List {
53 | val players = mutableListOf()
54 | for (p in proxy.players) {
55 | when (val player = getPlayer(p.uniqueId)) {
56 | is SeleneChatPlayerBungee -> players += player
57 | is SeleneChatPlayerOffline -> continue
58 | }
59 | }
60 | return players.toList()
61 | }
62 |
63 | override fun getPlayer(name: String): SeleneChatPlayer {
64 | val player = proxy.getPlayer(name)
65 | return if (player == null) SeleneChatPlayerOffline(displayName = name) else SeleneChatPlayerBungee(player)
66 | }
67 |
68 | override fun getPlayer(uuid: UUID): SeleneChatPlayer {
69 | val player = proxy.getPlayer(uuid)
70 | return if (player == null) SeleneChatPlayerOffline(uuid) else SeleneChatPlayerBungee(player)
71 | }
72 |
73 | override fun sendMessage(component: Component) {
74 | proxy.broadcast(*BungeeComponentSerializer.get().serialize(component))
75 | }
76 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/SeleneChatSpigot.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat
2 |
3 | import io.github.bluesheep2804.selenechat.channel.ChannelManager
4 | import io.github.bluesheep2804.selenechat.command.*
5 | import io.github.bluesheep2804.selenechat.common.Platforms
6 | import io.github.bluesheep2804.selenechat.config.SeleneChatConfigManager
7 | import io.github.bluesheep2804.selenechat.japanize.JapanizePlayersManager
8 | import io.github.bluesheep2804.selenechat.listener.ChatListenerSpigot
9 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayer
10 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerOffline
11 | import io.github.bluesheep2804.selenechat.player.SeleneChatPlayerSpigot
12 | import io.github.bluesheep2804.selenechat.resource.ResourceManager
13 | import net.kyori.adventure.platform.bukkit.BukkitAudiences
14 | import net.kyori.adventure.text.Component
15 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer
16 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
17 | import org.bukkit.plugin.java.JavaPlugin
18 | import java.util.*
19 |
20 | class SeleneChatSpigot : JavaPlugin(), IPlugin {
21 | private lateinit var adventure: BukkitAudiences
22 | override val platform = Platforms.BUKKIT
23 | override val configManager: SeleneChatConfigManager = SeleneChatConfigManager(dataFolder)
24 | override val resourceManager: ResourceManager = ResourceManager(dataFolder)
25 | override val japanizePlayersManager: JapanizePlayersManager = JapanizePlayersManager(dataFolder)
26 | override val channelManager: ChannelManager = ChannelManager(dataFolder)
27 | init {
28 | SeleneChat.setPluginInstance(this)
29 |
30 | logger.info(configManager.checkVersion())
31 | }
32 |
33 | override fun onEnable() {
34 | adventure = BukkitAudiences.create(this)
35 | server.pluginManager.registerEvents(ChatListenerSpigot(this), this)
36 | server.messenger.registerOutgoingPluginChannel(this, "selenechat:message")
37 |
38 | this.getCommand(SeleneChatCommand.COMMAND_NAME)?.setExecutor(SeleneChatCommandSpigot())
39 | this.getCommand(MessageCommand.COMMAND_NAME)?.setExecutor(MessageCommandSpigot())
40 | this.getCommand(JapanizeCommand.COMMAND_NAME)?.setExecutor(JapanizeCommandSpigot())
41 | this.getCommand(ChannelCommand.COMMAND_NAME)?.setExecutor(ChannelCommandSpigot())
42 |
43 | logger.info("Loaded!")
44 | }
45 |
46 | override fun onDisable() {
47 | adventure.close()
48 | }
49 |
50 | fun sendPluginMessage(msg: ByteArray) {
51 | server.sendPluginMessage(this, "selenechat:message", msg)
52 | }
53 |
54 | override fun getAllPlayers(): List {
55 | val players = mutableListOf()
56 | for (p in server.onlinePlayers) {
57 | when (val player = getPlayer(p.uniqueId)) {
58 | is SeleneChatPlayerSpigot -> players += player
59 | is SeleneChatPlayerOffline -> continue
60 | }
61 | }
62 | return players.toList()
63 | }
64 |
65 | override fun getPlayer(name: String): SeleneChatPlayer {
66 | val player = server.getPlayerExact(name)
67 | return if (player == null) SeleneChatPlayerOffline(displayName = name) else SeleneChatPlayerSpigot(player)
68 | }
69 |
70 | override fun getPlayer(uuid: UUID): SeleneChatPlayer {
71 | val player = server.getPlayer(uuid)
72 | return if (player == null) SeleneChatPlayerOffline(uuid) else SeleneChatPlayerSpigot(player)
73 | }
74 |
75 | override fun sendMessage(component: Component) {
76 | try {
77 | server.spigot().broadcast(*BungeeComponentSerializer.get().serialize(component))
78 | } catch (_: NoSuchMethodError) {
79 | server.broadcastMessage(LegacyComponentSerializer.legacySection().serialize(component))
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/github/bluesheep2804/selenechat/config/SeleneChatConfigData.kt:
--------------------------------------------------------------------------------
1 | package io.github.bluesheep2804.selenechat.config
2 |
3 | import com.charleskorn.kaml.YamlComment
4 | import io.github.bluesheep2804.selenechat.common.ConvertMode
5 | import kotlinx.serialization.Serializable
6 |
7 | @Serializable
8 | data class SeleneChatConfigData(
9 | @YamlComment("Version of the config file. Do not change.")
10 | var configVersion: Int = 2,
11 |
12 | @YamlComment("Specifying the chat conversion mode.", "Possible values: none, hiragana, ime")
13 | var convertMode: ConvertMode = ConvertMode.IME,
14 | @YamlComment("Set a marker to indicate that you do not want to Japanize temporarily.")
15 | var nonJapanizeMarker: String = "$",
16 | @YamlComment("Whether to Japanize by default.")
17 | var japanizeDefault: Boolean = true,
18 | @YamlComment("Enables the channel chat feature.")
19 | var enableChannelChat: Boolean = false,
20 | @YamlComment("Set a marker for the global channel.")
21 | var globalMarker: String = "!",
22 | @YamlComment("Whether to send message content to proxy servers using plugin messages.", "Applies to Spigot only.")
23 | var shouldSendPluginMessage: Boolean = false,
24 | @YamlComment("Choose whether to send the message in the standard Minecraft message format or in SeleneChat's own format.", "If true, SeleneChat's format will be used.", "Applies to Spigot only.")
25 | var useSeleneChatFormat: Boolean = false,
26 | @YamlComment("Whether to receive plugin messages from the server to the proxy server.", "Applies to Bungeecord and Velocity only.")
27 | var shouldReceivePluginMessage: Boolean = false,
28 | @YamlComment("Whether to use color codes (e.g. &4, &b) in the chat.")
29 | var useColorCode: Boolean = true,
30 |
31 | @YamlComment(
32 | "Specifies the format of the chat.",
33 | "MiniMessage tags can be used.",
34 | " -> Display name of sender",
35 | " -> Name of the server where the sender is located",
36 | " -> Date",
37 | "