Add Broadcast plugin source

This commit is contained in:
Disy committed 2026-10-05 11:15:02 +08:00
1 parent e84ee52c31
commit f386740e2a
9 files changed
+315

No files matched your search

+119
View File
@@ -0,0 +1,119 @@
# User-specific stuff
.idea/
*.iml
*.ipr
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
# Cache of project
.gradletasknamecache
**/build/
# Common working directory
run/
runs/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
+54
View File
@@ -0,0 +1,54 @@
import org.jetbrains.gradle.ext.settings
import org.jetbrains.gradle.ext.taskTriggers
plugins {
kotlin("jvm") version "2.0.20-Beta1"
// kotlin("kapt") version "2.0.20-Beta1"
kotlin("plugin.serialization") version "2.0.20-Beta1"
id("com.github.johnrengelman.shadow") version "8.1.1"
id("eclipse")
id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.8"
}
group = "cn.disy920"
version = "1.0.0"
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/") {
name = "papermc-repo"
}
maven("https://oss.sonatype.org/content/groups/public/") {
name = "sonatype"
}
}
dependencies {
compileOnly("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT")
compileOnly("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0")
}
val targetJavaVersion = 17
kotlin {
jvmToolchain(targetJavaVersion)
}
val templateSource = file("src/main/templates")
val templateDest = layout.buildDirectory.dir("generated/sources/templates")
val generateTemplates = tasks.register<Copy>("generateTemplates") {
val props = mapOf("version" to project.version)
inputs.properties(props)
from(templateSource)
into(templateDest)
expand(props)
}
sourceSets.main.configure { java.srcDir(generateTemplates.map { it.outputs }) }
project.idea.project.settings.taskTriggers.afterSync(generateTemplates)
project.eclipse.synchronizationTasks(generateTemplates)
View File
Whitespace-only changes.
+1
View File
@@ -0,0 +1 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
+1
View File
@@ -0,0 +1 @@
rootProject.name = "Broadcast"
@@ -0,0 +1,59 @@
package cn.disy920.broadcast;
import cn.disy920.broadcast.config.ConfigLoader
import com.google.inject.Inject
import com.velocitypowered.api.event.Subscribe
import com.velocitypowered.api.event.player.PlayerChatEvent
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent
import com.velocitypowered.api.plugin.Plugin
import com.velocitypowered.api.plugin.annotation.DataDirectory
import com.velocitypowered.api.proxy.ProxyServer
import net.kyori.adventure.text.Component
import org.slf4j.Logger
import java.nio.file.Path
import kotlin.jvm.optionals.getOrNull
@Plugin(
id = "broadcast",
name = "Broadcast",
version = BuildConstants.VERSION,
url = "www.starlight.cool",
authors = ["Disy920"]
)
class Main @Inject constructor(
private val proxyServer: ProxyServer,
private val logger: Logger,
@DataDirectory private val dataDirectory: Path
) {
private val configLoader = ConfigLoader(dataDirectory)
private val config
get() = configLoader.load()
@Subscribe
fun onProxyInitialization(event: ProxyInitializeEvent) {
logger.info("跨服聊天插件 v${BuildConstants.VERSION} 已加载,作者Disy920")
}
@Subscribe
fun onPlayerChat(event: PlayerChatEvent) {
if (!config.enable) return
val player = event.player
val message = event.message
val serverName = player.currentServer?.getOrNull()?.serverInfo?.name ?: return
if (config.bannedServer.contains(serverName)) return
val displayServerName = config.prefixMap.getOrDefault(serverName, serverName)
logger.info("[$displayServerName] <${player.username}> $message")
for (subServer in proxyServer.allServers) {
if (subServer?.serverInfo?.name == serverName) continue
subServer.sendMessage(Component.text("[$displayServerName] <${player.username}> $message").color(config.broadcastColor))
}
}
}
@@ -0,0 +1,33 @@
package cn.disy920.broadcast.config
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextColor
@Serializable
@JvmRecord
data class Config(
val enable: Boolean = false,
val prefixMap: Map<String, String> = emptyMap(), // 名字的映射,可以把默认的服务器名转化成一个自定义名称
val bannedServer: Set<String> = emptySet(), // 不接收跨服聊天的服务器
@Serializable(with = ColorSerializer::class)
val broadcastColor: TextColor = NamedTextColor.GRAY, // 跨服聊天消息的颜色
)
private object ColorSerializer : KSerializer<TextColor> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("TextColor", PrimitiveKind.INT)
override fun deserialize(decoder: Decoder): TextColor {
return TextColor.color(decoder.decodeInt())
}
override fun serialize(encoder: Encoder, value: TextColor) {
encoder.encodeInt(value.value())
}
}
@@ -0,0 +1,41 @@
package cn.disy920.broadcast.config
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.nio.file.Path
class ConfigLoader(rootDir: Path) {
private val configFile = rootDir.resolve("config.json").toFile()
private val json = Json {
prettyPrint = true
ignoreUnknownKeys = true
encodeDefaults = true
}
private lateinit var _config: Config
val config: Config
get() = load()
fun load(): Config {
if (!::_config.isInitialized) reload()
return _config
}
fun save(config: Config) {
configFile.writeText(json.encodeToString(config))
}
fun reload() {
if (!configFile.isFile) {
configFile.createNewFile()
_config = Config()
configFile.writeText(json.encodeToString(_config))
}
else {
_config = json.decodeFromString(configFile.readText())
}
}
}
@@ -0,0 +1,7 @@
package cn.disy920.broadcast;
// The constants are replaced before compilation
public class BuildConstants {
public static final String VERSION = "${version}";
}