Skip to content
This repository has been archived by the owner on Apr 27, 2021. It is now read-only.

Commit

Permalink
自動部屋分け処理の効率化・軽量化をした
Browse files Browse the repository at this point in the history
- 準最適移動(チャンネルスワップ)を実装 #7
- 移動時ではなく、スケジューラで部屋移動をさせるようにした
- 全てのユーザーの接続チャンネルを connectChannel に格納するようにした
- 再帰関数を末尾再帰に変更
- 移動をキャンセルするのではなく、部屋を固定するようにした
  • Loading branch information
sya-ri committed Feb 24, 2021
1 parent 9c08589 commit d069556
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 39 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ plugins {
id("net.minecrell.plugin-yml.bukkit") version "0.3.0"
}

version = "1.0.2"
version = "1.0.3"

repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Main : JavaPlugin() {
override fun onEnable() {
ConfigLoader.load(server.consoleSender)
CommandCreator.create()
registerEvents(ToggleMuteUseItem, AutoGroupOnMove)
registerEvents(ToggleMuteUseItem)
}

override fun onDisable() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,8 @@ object DiscordClient {
}

private val lastRoom = mutableMapOf<Long, Long>()
private val moveCoolTime = mutableSetOf<UUIDPlayer>()

fun move(player: Player, room: Long): String? {
val uuidPlayer = UUIDPlayer.from(player)
if (moveCoolTime.contains(uuidPlayer)) return null
moveCoolTime.add(uuidPlayer)
plugin.runTaskLater(15) {
moveCoolTime.remove(uuidPlayer)
}
val guild = guild ?: return "ギルドが見つかりませんでした"
val userId = DiscordMember.get(player)?.discordUserId ?: return "アカウントの紐付けがされていません"
if (lastRoom[userId] == room) return null
Expand Down Expand Up @@ -148,6 +141,20 @@ object DiscordClient {
}
}

fun removeMutePermission(id: Long): String? {
val guild = guild ?: return "ギルドが見つかりませんでした"
val channel = jda?.getVoiceChannelById(id) ?: return "チャンネルが見つかりませんでした"
return try {
val overrideAction = channel.getPermissionOverride(guild.publicRole)?.manager ?: channel.createPermissionOverride(guild.publicRole)
overrideAction.setAllow(Permission.VOICE_SPEAK).complete()
null
} catch (ex: InsufficientPermissionException) {
"ボットの権限がありません"
} catch (ex: IllegalArgumentException) {
"存在しないメンバーです"
}
}

fun getUser(id: Long): User? {
return jda?.getUserById(id)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package com.github.syari.plugin.talk.with.near.player.mode
import com.github.syari.plugin.talk.with.near.player.Main.Companion.plugin
import com.github.syari.plugin.talk.with.near.player.discord.DiscordClient
import com.github.syari.plugin.talk.with.near.player.discord.DiscordMember
import com.github.syari.spigot.api.event.register.EventRegister
import com.github.syari.spigot.api.event.register.Events
import com.github.syari.spigot.api.scheduler.runTaskLater
import com.github.syari.spigot.api.scheduler.runTaskTimer
import com.github.syari.spigot.api.util.uuid.UUIDPlayer
import org.bukkit.entity.Player
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.scheduler.BukkitTask

object AutoGroupOnMove : EventRegister {
object AutoGroupOnMove {
const val defaultRadius = 5.0

var radius = defaultRadius
Expand All @@ -19,14 +18,18 @@ object AutoGroupOnMove : EventRegister {

fun createAllVoiceChannel() {
plugin.runTaskLater(20, true) {
(owners + null).forEach(::createVoiceChannel)
createVoiceChannel(null)
owners.forEach(::createVoiceChannel)
ownerToChannel[null]?.let(DiscordClient::addMutePermission)
}
}

private var createChannelIndex = 0

fun createVoiceChannel(uuidPlayer: UUIDPlayer?) {
if (ownerToChannel.contains(uuidPlayer).not()) {
val result = DiscordClient.crate("twnp-${uuidPlayer?.uniqueId ?: "wait"}", categoryId)
val result = DiscordClient.crate("twnp-auto-$createChannelIndex", categoryId)
createChannelIndex ++
if (result is DiscordClient.CreateResult.Success) {
ownerToChannel[uuidPlayer] = result.channel.idLong
} else if (result is DiscordClient.CreateResult.Failure) {
Expand All @@ -46,22 +49,23 @@ object AutoGroupOnMove : EventRegister {

private val ownerToChannel = mutableMapOf<UUIDPlayer?, Long>()

private val coolTime = mutableSetOf<UUIDPlayer>()
private var task: BukkitTask? = null

override fun Events.register() {
event<PlayerMoveEvent> {
if (Mode.mode == Mode.Auto) {
val uuidPlayer = UUIDPlayer.from(it.player)
if (coolTime.contains(uuidPlayer)) return@event
fun registerTask() {
if (task == null) {
task = plugin.runTaskTimer(15) {
updateConnectChannel()
coolTime.add(uuidPlayer)
plugin.runTaskLater(5) {
coolTime.remove(uuidPlayer)
}
}
}
}

fun unregisterTask() {
task?.cancel()
task = null
}

private var lastConnectOwner = mapOf<UUIDPlayer, UUIDPlayer?>()

private fun updateConnectChannel() {
val voiceMemberList = DiscordMember.playerList.toMutableSet()

Expand All @@ -83,38 +87,81 @@ object AutoGroupOnMove : EventRegister {
}
} else {
put(player, owner)
voiceMemberList.remove(player)
}
voiceMemberList.remove(player)
}
}
put(owner, owner)
voiceMemberList.remove(owner)
}
}

fun solveMerge(player: UUIDPlayer): UUIDPlayer {
return mergeGroups[player]?.let(::solveMerge) ?: player
tailrec fun solveMerge(player: UUIDPlayer): UUIDPlayer {
val group = mergeGroups[player]
return if (group != null) {
solveMerge(group)
} else {
player
}
}

val solvedMergerGroups = mergeGroups.map { it.key to solveMerge(it.value) }.associate { it.first to it.second }

val connectChannel = mutableMapOf<UUIDPlayer, Long>().apply {
val connectOwner = mutableMapOf<UUIDPlayer, UUIDPlayer?>().apply {
playerToOwner.forEach { (player, owner) ->
val channel = ownerToChannel[solvedMergerGroups[owner] ?: owner] ?: return@forEach
put(player, channel)
put(player, solvedMergerGroups[owner] ?: owner)
}
voiceMemberList.forEach {
put(it, null)
}
}

connectChannel.forEach { (uuidPlayer, channel) ->
val player = uuidPlayer.player ?: return@forEach
DiscordClient.move(player, channel)
val moveChannelSize = mutableMapOf<Pair<UUIDPlayer?, UUIDPlayer?>, Int>()

connectOwner.forEach { (uuidPlayer, owner) ->
val lastOwner = if (lastConnectOwner.contains(uuidPlayer)) {
lastConnectOwner[uuidPlayer] ?: owner
} else {
null
}
val moveChannel = lastOwner to owner
val lastSize = moveChannelSize.getOrDefault(moveChannel, 0)
moveChannelSize[moveChannel] = lastSize + 1
}
voiceMemberList.forEach {
val player = it.player ?: return@forEach
val channel = ownerToChannel[null]
if (channel != null) {
DiscordClient.move(player, channel)

val ownerToChannelList = ownerToChannel.toList()
val iterator1 = ownerToChannelList.listIterator()
while (iterator1.hasNext()) {
val (owner1, channel1) = iterator1.next()
val iterator2 = ownerToChannelList.listIterator(iterator1.nextIndex())
while (iterator2.hasNext()) {
val (owner2, channel2) = iterator2.next()
val m1t1 = moveChannelSize.getOrDefault(owner1 to owner1, 0)
val m1t2 = moveChannelSize.getOrDefault(owner1 to owner2, 0)
val m2t1 = moveChannelSize.getOrDefault(owner2 to owner1, 0)
val m2t2 = moveChannelSize.getOrDefault(owner2 to owner2, 0)
when {
(m1t1 + m2t2) < (m1t2 + m2t1) -> {
ownerToChannel[owner1] = channel2
ownerToChannel[owner2] = channel1
if (owner1 == null) {
DiscordClient.removeMutePermission(channel1)
DiscordClient.addMutePermission(channel2)
} else if (owner2 == null) {
DiscordClient.removeMutePermission(channel2)
DiscordClient.addMutePermission(channel1)
}
}
}
}
}

connectOwner.forEach { (uuidPlayer, owner) ->
val player = uuidPlayer.player ?: return@forEach
val channel = ownerToChannel[owner] ?: return@forEach
DiscordClient.move(player, channel)
}

lastConnectOwner = connectOwner
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ enum class Mode(val key: String) {
fun applyMode() {
if (mode == Auto) {
AutoGroupOnMove.createAllVoiceChannel()
AutoGroupOnMove.registerTask()
} else {
AutoGroupOnMove.clearVoiceChannels()
AutoGroupOnMove.unregisterTask()
}
}
}
Expand Down

0 comments on commit d069556

Please sign in to comment.