Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: thread starvation from non-constant time method call #502

Merged
merged 3 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

package gg.skytils.skytilsmod.features.impl.dungeons.catlas.handlers

import gg.essential.universal.UChat
import gg.skytils.skytilsmod.Skytils
import gg.skytils.skytilsmod.Skytils.Companion.IO
import gg.skytils.skytilsmod.Skytils.Companion.mc
import gg.skytils.skytilsmod.features.impl.dungeons.DungeonFeatures.dungeonFloorNumber
Expand All @@ -26,6 +28,7 @@ import gg.skytils.skytilsmod.features.impl.dungeons.catlas.handlers.DungeonScann
import gg.skytils.skytilsmod.features.impl.dungeons.catlas.utils.ScanUtils
import gg.skytils.skytilsmod.listeners.DungeonListener
import gg.skytils.skytilsmod.utils.SBInfo
import gg.skytils.skytilsmod.utils.printDevMessage
import gg.skytils.skytilsws.shared.packet.C2SPacketDungeonRoom
import kotlinx.coroutines.launch
import net.minecraft.init.Blocks
Expand Down Expand Up @@ -80,7 +83,13 @@ object DungeonScanner {
DungeonInfo.dungeonList[z * 11 + x] = it
if (it is Room && it.data.name != "Unknown") {
SBInfo.server?.let { server ->
DungeonListener.outboundRoomQueue.add(C2SPacketDungeonRoom(server, it.data.name, xPos, zPos, x, z, it.core, it.isSeparator))
printDevMessage("Sending room data to channel: ${it.data.name}", "dungeonws")
val result = DungeonListener.outboundRoomQueue.trySend(
C2SPacketDungeonRoom(server, it.data.name, xPos, zPos, x, z, it.core, it.isSeparator)
)
if (result.isFailure) {
UChat.chat("${Skytils.failPrefix} §cFailed to send room data to server. ${result.isClosed}")
}
}
}
}
Expand Down
36 changes: 29 additions & 7 deletions src/main/kotlin/gg/skytils/skytilsmod/listeners/DungeonListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import gg.skytils.skytilsmod.core.API
import gg.skytils.skytilsmod.core.tickTimer
import gg.skytils.skytilsmod.events.impl.MainReceivePacketEvent
import gg.skytils.skytilsmod.events.impl.skyblock.DungeonEvent
import gg.skytils.skytilsmod.events.impl.skyblock.LocationChangeEvent
import gg.skytils.skytilsmod.features.impl.dungeons.DungeonFeatures
import gg.skytils.skytilsmod.features.impl.dungeons.DungeonTimer
import gg.skytils.skytilsmod.features.impl.dungeons.ScoreCalculation
Expand All @@ -52,7 +53,10 @@ import gg.skytils.skytilsws.shared.packet.C2SPacketDungeonEnd
import gg.skytils.skytilsws.shared.packet.C2SPacketDungeonRoom
import gg.skytils.skytilsws.shared.packet.C2SPacketDungeonRoomSecret
import gg.skytils.skytilsws.shared.packet.C2SPacketDungeonStart
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.hypixel.modapi.packet.impl.clientbound.ClientboundPartyInfoPacket
Expand All @@ -64,7 +68,7 @@ import net.minecraftforge.client.event.ClientChatReceivedEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.util.concurrent.ConcurrentLinkedQueue
import kotlin.jvm.optionals.getOrNull

object DungeonListener {
val team = hashMapOf<String, DungeonTeammate>()
Expand Down Expand Up @@ -114,7 +118,7 @@ object DungeonListener {
private val keyPickupRegex = Regex("§r§e§lRIGHT CLICK §r§7on §r§7.+?§r§7 to open it\\. This key can only be used to open §r§a(?<num>\\d+)§r§7 door!§r")
private val witherDoorOpenedRegex = Regex("^(?:\\[.+?] )?(?<name>\\w+) opened a WITHER door!$")
private const val bloodOpenedString = "§r§cThe §r§c§lBLOOD DOOR§r§c has been opened!§r"
val outboundRoomQueue = ConcurrentLinkedQueue<C2SPacketDungeonRoom>()
var outboundRoomQueue = Channel<C2SPacketDungeonRoom>(UNLIMITED)
var isSoloDungeon = false

@SubscribeEvent
Expand All @@ -125,10 +129,22 @@ object DungeonListener {
missingPuzzles.clear()
completedPuzzles.clear()
teamCached.clear()
outboundRoomQueue.clear()
printDevMessage("closed room queue world load", "dungeonws")
outboundRoomQueue.cancel()
isSoloDungeon = false
}

@SubscribeEvent
fun onLocationUpdate(event: LocationChangeEvent) {
if (event.packet.mode.getOrNull() == "dungeon") {
printDevMessage("closed room queue", "dungeonws")
outboundRoomQueue.cancel()
outboundRoomQueue = Channel(UNLIMITED) {
printDevMessage("failed to deliver $it", "dungeonws")
}
}
}

@SubscribeEvent
fun onPacket(event: MainReceivePacketEvent<*, *>) {
if (!Utils.inDungeons) return
Expand Down Expand Up @@ -213,19 +229,25 @@ object DungeonListener {
}
val partyMembers = party.await().members.ifEmpty { setOf(mc.thePlayer.uniqueID) }.mapTo(hashSetOf()) { it.toString() }
val entrance = DungeonInfo.uniqueRooms.first { it.mainRoom.data.type == RoomType.ENTRANCE }
async(WSClient.wsClient.coroutineContext) {
printDevMessage("hi", "dungeonws")
launch(IO.coroutineContext) {
WSClient.sendPacketAsync(C2SPacketDungeonStart(
serverId = SBInfo.server ?: return@async,
serverId = SBInfo.server ?: return@launch,
floor = DungeonFeatures.dungeonFloor!!,
members = partyMembers,
startTime = DungeonTimer.dungeonStartTime,
entranceLoc = entrance.mainRoom.z * entrance.mainRoom.x
))
while (DungeonTimer.dungeonStartTime != -1L) {
while (outboundRoomQueue.isNotEmpty()) {
val packet = outboundRoomQueue.poll() ?: continue
for (packet in outboundRoomQueue) {
My-Name-Is-Jeff marked this conversation as resolved.
Show resolved Hide resolved
WSClient.sendPacketAsync(packet)
printDevMessage(packet.toString(), "dungeonws")
}
printDevMessage("escaped loop", "dungeonws")
}
}.also {
it.invokeOnCompletion {
printDevMessage("loop exit $it", "dungeonws")
}
}
}
Expand Down
Loading