Skip to content

Commit

Permalink
store players ids and collection of online VoicePlayers in groups ins…
Browse files Browse the repository at this point in the history
…tead of just VoicePlayer collection
  • Loading branch information
Apehum committed Mar 2, 2023
1 parent 05ef17e commit 9021b33
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,6 @@ class ActivationListener(
private val defaultPermission = PermissionDefault.TRUE
private val selfActivationInfo = SelfActivationInfo(voiceServer.udpConnectionManager)

@EventSubscribe(priority = EventPriority.HIGHEST)
fun onActivationRegister(event: ServerActivationRegisterEvent) {
if (activation != event.activation) return
activation.permissions.forEach {
voiceServer.minecraftServer.permissionsManager.register(it, defaultPermission)
}
}

@EventSubscribe(priority = EventPriority.HIGHEST)
fun onActivationUnregister(event: ServerActivationUnregisterEvent) {
if (activation != event.activation) return
Expand Down
22 changes: 12 additions & 10 deletions common/src/main/kotlin/su/plo/voice/groups/GroupsAddon.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package su.plo.voice.groups

import com.google.inject.Inject
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import su.plo.config.provider.ConfigurationProvider
import su.plo.config.provider.toml.TomlConfiguration
import su.plo.lib.api.server.command.MinecraftCommand
import su.plo.lib.api.server.command.MinecraftCommandManager
import su.plo.lib.api.server.permission.PermissionDefault
import su.plo.voice.api.PlasmoVoice
import su.plo.voice.api.server.PlasmoCommonVoiceServer
import su.plo.voice.groups.command.CommandHandler
Expand Down Expand Up @@ -61,6 +59,11 @@ open class GroupsAddon {
.setStereoSupported(false)
.build()

// register activation's permissions
activation.permissions.forEach {
server.minecraftServer.permissionsManager.register(it, PermissionDefault.TRUE)
}

val sourceLine = server.sourceLineManager.registerPlayers(
this,
activationName,
Expand All @@ -69,7 +72,7 @@ open class GroupsAddon {
config.sourceLineWeight
)

val groupManager = GroupsManager(config, server.sourceManager, this, activation, sourceLine).also {
val groupManager = GroupsManager(config, server, this, activation, sourceLine).also {
this.groupManager = it
}

Expand All @@ -79,17 +82,16 @@ open class GroupsAddon {
?.runCatching { Json.decodeFromString<GroupsManager.Data>(this) }
?.getOrNull()
?.also { fe -> fe.groups.forEach { group ->
group.data.apply {
group.apply {
groupManager.groups[id] = Group(
sourceLine.createBroadcastSet(),
id,
name,
password,
persistent
).apply {
owner = group.owner
// ?.let { server.minecraftServer.getGameProfile(it).orElse(null) } // how
}
persistent,
playersIds,
owner
)
}
} }
?.also { fe -> fe.groupByPlayer.mapNotNull {
Expand Down
58 changes: 31 additions & 27 deletions common/src/main/kotlin/su/plo/voice/groups/GroupsManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,24 @@ package su.plo.voice.groups
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import su.plo.voice.api.PlasmoVoice
import su.plo.voice.api.event.EventSubscribe
import su.plo.voice.api.server.PlasmoCommonVoiceServer
import su.plo.voice.api.server.audio.capture.ServerActivation
import su.plo.voice.api.server.audio.line.ServerPlayersSourceLine
import su.plo.voice.api.server.audio.source.BaseServerSourceManager
import su.plo.voice.api.server.audio.source.ServerDirectSource
import su.plo.voice.api.server.event.connection.UdpClientConnectedEvent
import su.plo.voice.api.server.event.connection.UdpClientDisconnectedEvent
import su.plo.voice.api.server.player.VoicePlayer
import su.plo.voice.groups.group.Group
import su.plo.voice.groups.group.GroupOfflineData
import su.plo.voice.groups.group.GroupData
import su.plo.voice.groups.utils.serializer.UUIDSerializer
import java.io.File
import java.util.*
import java.util.concurrent.ConcurrentHashMap

class GroupsManager(
val config: Config,
private val sourceManager: BaseServerSourceManager,
private val voiceServer: PlasmoCommonVoiceServer,
private val addon: GroupsAddon,
val activation: ServerActivation,
val sourceLine: ServerPlayersSourceLine,
Expand All @@ -34,47 +32,53 @@ class GroupsManager(
// val groupByPlayerCache: MutableMap<@Serializable(with = UUIDSerializer::class) UUID, UUID> = ConcurrentHashMap()

fun join(player: VoicePlayer, group: Group) {
leave(player)
leave(player.instance.uuid)
initSource(player, group)
groupByPlayer[player.instance.uuid] = group
group.playersSet.addPlayer(player)

group.addPlayer(player)
sourceLine.setPlayersSet(player, group.playersSet) // todo: DRY
}

private fun initSource(player: VoicePlayer, group: Group) {
val source = sourceManager.createDirectSource(addon, sourceLine, "opus", false)
val source = voiceServer.sourceManager.createDirectSource(addon, sourceLine, "opus", false)
source.setPlayers(group::onlinePlayers)
source.addFilter { it.instance != player.instance }
source.setSender(player)
source.setPlayers(group::players)
sourceByPlayer[player.instance.uuid] = source
}

fun leave(player: VoicePlayer): Boolean {

sourceByPlayer.remove(player.instance.uuid)
?.let { sourceManager.remove(it) }

val group = groupByPlayer.remove(player.instance.uuid)
val didLeft = group?.playersSet?.let {
it.removePlayer(player.instance.uuid).also {
sourceLine.setPlayersSet(player, null)
}
fun leave(player: VoicePlayer): Boolean =
leave(player.instance.uuid)

fun leave(playerUuid: UUID): Boolean {
sourceByPlayer.remove(playerUuid)
?.let { voiceServer.sourceManager.remove(it) }

val group = groupByPlayer.remove(playerUuid)
val didLeft = group?.removePlayer(playerUuid).also {
voiceServer.playerManager
.getPlayerById(playerUuid)
.orElse(null)
?.let {
sourceLine.setPlayersSet(it, null)
}
}

if (didLeft == false) return false

if (group?.persistent == false) {
if (group.owner?.id == player.instance.uuid)
if (group.owner?.id == playerUuid)
group.owner = group.onlinePlayers.randomOrNull()?.instance?.gameProfile
group.owner?.let { group.notifyPlayersTranslatable("pv.addon.groups.notifications.new_owner", it.name) }
group.owner?.let { group.notifyPlayersTranslatable("pv.addon.groups.notifications.new_owner", it.name) }
if (group.onlinePlayers.isEmpty()) deleteGroup(group)
}

return true
}

fun deleteGroup(group: Group) = groups.remove(group.id)?.let { group ->
group.players.forEach { leave(it) }
group.playersIds.forEach { leave(it) }
}

@EventSubscribe
Expand All @@ -88,8 +92,7 @@ class GroupsManager(
group.owner = player.instance.gameProfile
}

group.playersSet.removePlayer(playerId)
group.playersSet.addPlayer(player)
group.onPlayerJoin(player)
sourceLine.setPlayersSet(player, group.playersSet)
initSource(player, group)
}
Expand All @@ -98,16 +101,17 @@ class GroupsManager(
@EventSubscribe
fun onPlayerLeave(event: UdpClientDisconnectedEvent) {
val playerId = event.connection.player.instance.uuid
sourceByPlayer.remove(playerId)?.let { sourceManager.remove(it) }

sourceByPlayer.remove(playerId)?.let { voiceServer.sourceManager.remove(it) }
groupByPlayer[playerId]?.let {
if (it.onlinePlayers.isEmpty()) deleteGroup(it)
it.onPlayerQuit(playerId)
if (it.onlinePlayers.isEmpty() && !it.persistent) deleteGroup(it)
}
}

fun onVoiceServerShutdown(server: PlasmoCommonVoiceServer) {
val groups = groups.values
.filter { it.persistent }
.map { it.asOfflineData() }

File(addon.getAddonFolder(server), "groups.json")
.writeText(Json.encodeToString(Data(
Expand All @@ -118,7 +122,7 @@ class GroupsManager(

@Serializable
data class Data(
val groups: List<GroupOfflineData>,
val groups: List<GroupData>,
val groupByPlayer: Map<
@Serializable(with = UUIDSerializer::class) UUID,
@Serializable(with = UUIDSerializer::class) UUID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class InviteCommand(handler: CommandHandler): SubCommand(handler) {
val group = handler.groupManager.groupByPlayer[player.instance.uuid] ?: return listOf()

return handler.voiceServer.playerManager.players
.filter { !group.players.contains(it) && (it != player) }
.filter { !group.onlinePlayers.contains(it) && (it != player) }
.map { it.instance.name }
.filter { it.startsWith(arg, true) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ class SetCommand(handler: CommandHandler): SubCommand(handler) {

group.notifyPlayersTranslatable("pv.addon.groups.notifications.permissions_changed")

group.players
// todo: will not work with offline players, because it's just impossible without LP
group.onlinePlayers
.filter { !group.hasPermission(it.instance) }
.forEach {
handler.groupManager.leave(it)
Expand Down
Loading

0 comments on commit 9021b33

Please sign in to comment.