Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.

Commit 61b223f

Browse files
committed
feat: add broadcast command for sending messages to servers and groups
1 parent 560a06e commit 61b223f

File tree

7 files changed

+215
-0
lines changed

7 files changed

+215
-0
lines changed

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/server/CloudServerManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ interface CloudServerManager {
7373
players: Collection<CloudPlayer>
7474
): @Unmodifiable ObjectList<Pair<CloudPlayer, ConnectionResultEnum>>
7575

76+
suspend fun broadcastToGroup(group: String, message: Component)
77+
suspend fun broadcast(message: Component)
7678

7779
companion object : CloudServerManager by INSTANCE {
7880
@InternalApi

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/server/CommonCloudServer.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import dev.slne.surf.cloud.api.common.player.ConnectionResult
55
import dev.slne.surf.cloud.api.common.server.state.ServerState
66
import it.unimi.dsi.fastutil.objects.Object2ObjectMap
77
import net.kyori.adventure.audience.ForwardingAudience
8+
import net.kyori.adventure.text.Component
89
import org.jetbrains.annotations.ApiStatus
910

1011
/**
@@ -104,6 +105,8 @@ interface CommonCloudServer : ForwardingAudience {
104105

105106
fun isInGroup(group: String): Boolean
106107

108+
suspend fun broadcast(message: Component)
109+
107110
/**
108111
* Shuts down the server.
109112
*

surf-cloud-bukkit/src/main/kotlin/dev/slne/surf/cloud/bukkit/command/PaperCommandManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.slne.surf.cloud.bukkit.command
22

3+
import dev.slne.surf.cloud.bukkit.command.broadcast.broadcastCommand
34
import dev.slne.surf.cloud.bukkit.command.lastseen.lastSeenCommand
45
import dev.slne.surf.cloud.bukkit.command.network.findCommand
56
import dev.slne.surf.cloud.bukkit.command.network.sendCommand
@@ -13,5 +14,6 @@ object PaperCommandManager {
1314
sendCommand()
1415
playtimeCommand()
1516
lastSeenCommand()
17+
broadcastCommand()
1618
}
1719
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package dev.slne.surf.cloud.bukkit.command.broadcast
2+
3+
import com.github.shynixn.mccoroutine.folia.launch
4+
import dev.jorel.commandapi.CommandTree
5+
import dev.jorel.commandapi.arguments.Argument
6+
import dev.jorel.commandapi.kotlindsl.*
7+
import dev.slne.surf.cloud.api.client.paper.command.args.cloudServerArgument
8+
import dev.slne.surf.cloud.api.client.paper.command.args.cloudServerGroupArgument
9+
import dev.slne.surf.cloud.api.common.server.CloudServer
10+
import dev.slne.surf.cloud.api.common.server.CloudServerManager
11+
import dev.slne.surf.cloud.bukkit.plugin
12+
import dev.slne.surf.surfapi.bukkit.api.command.args.MiniMessageArgument
13+
import dev.slne.surf.surfapi.core.api.messages.Colors
14+
import dev.slne.surf.surfapi.core.api.messages.adventure.sendText
15+
import net.kyori.adventure.text.Component
16+
import org.bukkit.command.CommandSender
17+
18+
@Suppress("DuplicatedCode")
19+
fun broadcastCommand() = commandTree("broadcast") {
20+
literalArgument("--server") {
21+
cloudServerArgument("server") {
22+
literalArgument("--message") {
23+
argument(MiniMessageArgument("message")) {
24+
anyExecutor { sender, args ->
25+
val server: CloudServer by args
26+
val message: Component by args
27+
executeBroadcast(sender, message, server = server)
28+
}
29+
}
30+
}
31+
literalArgument("--prefix") {
32+
argument(MiniMessageArgument("prefix")) {
33+
literalArgument("--message") {
34+
argument(MiniMessageArgument("message")) {
35+
anyExecutor { sender, args ->
36+
val server: CloudServer by args
37+
val prefix: Component by args
38+
val message: Component by args
39+
executeBroadcast(sender, message, prefix = prefix, server = server)
40+
}
41+
}
42+
}
43+
}
44+
}
45+
}
46+
}
47+
48+
literalArgument("--group") {
49+
cloudServerGroupArgument("group") {
50+
literalArgument("--message") {
51+
argument(MiniMessageArgument("message")) {
52+
anyExecutor { sender, args ->
53+
val group: String by args
54+
val message: Component by args
55+
executeBroadcast(sender, message, group = group)
56+
}
57+
}
58+
}
59+
literalArgument("--prefix") {
60+
argument(MiniMessageArgument("prefix")) {
61+
literalArgument("--message") {
62+
argument(MiniMessageArgument("message")) {
63+
anyExecutor { sender, args ->
64+
val group: String by args
65+
val prefix: Component by args
66+
val message: Component by args
67+
executeBroadcast(sender, message, prefix = prefix, group = group)
68+
}
69+
}
70+
}
71+
}
72+
}
73+
}
74+
}
75+
76+
literalArgument("--prefix") {
77+
argument(MiniMessageArgument("prefix")) {
78+
literalArgument("--message") {
79+
argument(MiniMessageArgument("message")) {
80+
anyExecutor { sender, args ->
81+
val prefix: Component by args
82+
val message: Component by args
83+
executeBroadcast(sender, message, prefix = prefix)
84+
}
85+
}
86+
}
87+
literalArgument("--server") {
88+
cloudServerArgument("server") {
89+
literalArgument("--message") {
90+
argument(MiniMessageArgument("message")) {
91+
anyExecutor { sender, args ->
92+
val server: CloudServer by args
93+
val prefix: Component by args
94+
val message: Component by args
95+
executeBroadcast(sender, message, prefix = prefix, server = server)
96+
}
97+
}
98+
}
99+
}
100+
}
101+
literalArgument("--group") {
102+
cloudServerGroupArgument("group") {
103+
literalArgument("--message") {
104+
argument(MiniMessageArgument("message")) {
105+
anyExecutor { sender, args ->
106+
val group: String by args
107+
val prefix: Component by args
108+
val message: Component by args
109+
executeBroadcast(sender, message, prefix = prefix, group = group)
110+
}
111+
}
112+
}
113+
}
114+
}
115+
}
116+
}
117+
118+
literalArgument("--message") {
119+
argument(MiniMessageArgument("message")) {
120+
anyExecutor { sender, args ->
121+
val message: Component by args
122+
executeBroadcast(sender, message)
123+
}
124+
}
125+
}
126+
}
127+
128+
private fun executeBroadcast(
129+
sender: CommandSender,
130+
message: Component,
131+
prefix: Component? = null,
132+
server: CloudServer? = null,
133+
group: String? = null
134+
) = plugin.launch{
135+
val prefix = prefix ?: Colors.PREFIX
136+
val message = message.replaceText {
137+
it.match("(?m)^")
138+
.replacement(prefix)
139+
.replaceInsideHoverEvents(false)
140+
}
141+
142+
when {
143+
server != null -> server.sendMessage(message)
144+
group != null -> CloudServerManager.broadcastToGroup(group, message)
145+
else -> CloudServerManager.broadcast(message)
146+
}
147+
148+
sender.sendText {
149+
appendPrefix()
150+
success("Die Nachricht wurde erfolgreich an ")
151+
if (server != null) {
152+
success("den Server ")
153+
variableValue(server.name)
154+
} else if (group != null) {
155+
success("die Gruppe ")
156+
variableValue(group)
157+
} else {
158+
success("alle")
159+
}
160+
success(" gesendet.")
161+
}
162+
}

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/server/CommonCloudServerImpl.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ import dev.slne.surf.cloud.api.common.util.mutableObject2ObjectMapOf
1111
import dev.slne.surf.cloud.core.common.coreCloudInstance
1212
import dev.slne.surf.cloud.core.common.coroutines.PlayerBatchTransferScope
1313
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.ClientInformation
14+
import dev.slne.surf.cloud.core.common.sound.CommonSounds
1415
import kotlinx.coroutines.Deferred
1516
import kotlinx.coroutines.async
17+
import kotlinx.coroutines.delay
18+
import net.kyori.adventure.sound.Sound
19+
import net.kyori.adventure.sound.Sound.Emitter
20+
import net.kyori.adventure.text.Component
1621

1722
abstract class CommonCloudServerImpl(
1823
override val uid: Long,
@@ -52,6 +57,14 @@ abstract class CommonCloudServerImpl(
5257
return group.equals(group, ignoreCase = true)
5358
}
5459

60+
override suspend fun broadcast(message: Component) {
61+
sendMessage(message)
62+
for (sound in CommonSounds.broadcastSounds) {
63+
playSound(sound, Emitter.self())
64+
delay(150)
65+
}
66+
}
67+
5568
override val maxPlayerCount get() = information.maxPlayerCount
5669
override val currentPlayerCount get() = users.size
5770
override val state get() = information.state

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/server/CommonCloudServerManagerImpl.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import dev.slne.surf.cloud.api.common.util.toObjectSet
1111
import it.unimi.dsi.fastutil.objects.ObjectCollection
1212
import kotlinx.coroutines.sync.Mutex
1313
import kotlinx.coroutines.sync.withLock
14+
import net.kyori.adventure.text.Component
1415

1516
abstract class CommonCloudServerManagerImpl<S : CommonCloudServer> : CloudServerManager {
1617
protected val servers = mutableLong2ObjectMapOf<S>().synchronize()
@@ -64,4 +65,14 @@ abstract class CommonCloudServerManagerImpl<S : CommonCloudServer> : CloudServer
6465
override suspend fun retrieveAllServers(): ObjectCollection<S> {
6566
return serversMutex.withLock { servers.values.toObjectSet() }
6667
}
68+
69+
override suspend fun broadcastToGroup(group: String, message: Component) =
70+
serversMutex.withLock {
71+
servers.values.filter { it.isInGroup(group) }.filterIsInstance<CloudServer>()
72+
}.forEach { it.broadcast(message) }
73+
74+
75+
override suspend fun broadcast(message: Component) = serversMutex.withLock {
76+
servers.values.filterIsInstance<CloudServer>()
77+
}.forEach { it.broadcast(message) }
6778
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dev.slne.surf.cloud.core.common.sound
2+
3+
import dev.slne.surf.cloud.api.common.util.objectListOf
4+
import dev.slne.surf.surfapi.core.api.generated.SoundKeys
5+
import dev.slne.surf.surfapi.core.api.messages.adventure.Sound
6+
import net.kyori.adventure.sound.Sound.Source
7+
8+
object CommonSounds {
9+
val BROADCAST_SOUND_1 = Sound {
10+
type(SoundKeys.BLOCK_NOTE_BLOCK_CHIME)
11+
pitch(0.9f)
12+
volume(1f)
13+
source(Source.MASTER)
14+
}
15+
val BROADCAST_SOUND_2 = Sound {
16+
type(SoundKeys.BLOCK_NOTE_BLOCK_CHIME)
17+
pitch(1.3f)
18+
volume(1f)
19+
source(Source.MASTER)
20+
}
21+
val broadcastSounds = objectListOf(BROADCAST_SOUND_1, BROADCAST_SOUND_2)
22+
}

0 commit comments

Comments
 (0)