Skip to content

Commit

Permalink
Process achievements and player card data asynchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
4Ply committed Jan 26, 2025
1 parent fceaade commit 48cfb70
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 35 deletions.
4 changes: 4 additions & 0 deletions src/main/kotlin/org/trackedout/AgroNet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,11 @@ object AgroNet : ModInitializer {
fun runAsyncTask(task: suspend () -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
try {
// log the time it takes to run this task
val startTime = System.currentTimeMillis()
task()
val endTime = System.currentTimeMillis()
logger.info("Async IO task completed in ${endTime - startTime}ms")
} catch (e: Exception) {
e.printStackTrace()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class AddDeckToPlayerInventoryAction(
) {
private val logger = LoggerFactory.getLogger("Agronet")

fun execute(source: ServerCommandSource, player: ServerPlayerEntity) {
fun execute(source: ServerCommandSource, player: ServerPlayerEntity) = runAsyncTask {
val playerName = player.name.string
logger.debug("Fetch player deck command")

Expand All @@ -43,12 +43,12 @@ class AddDeckToPlayerInventoryAction(
source.sendMessage("Player $playerName already has their shulker box, refusing to give them another one", Formatting.RED)
player.debug("You already have your shulker box, refusing to give you another one")
logger.warn("Player $playerName already has their shulker box, refusing to give them another one")
return
return@runAsyncTask
}

if (!RunContext.initialized) {
player.sendMessage("Run data is not initialized, unable to determine which deck to give to $playerName", Formatting.RED)
return
return@runAsyncTask
}

val context = RunContext.playerContext(playerName)
Expand Down Expand Up @@ -201,7 +201,7 @@ class AddDeckToPlayerInventoryAction(
if (!inventory.insertStack(shulkerBox)) {
logger.warn("Failed to give ${player.name} a Decked Out Shulker as their inventory is full")
player.sendMessage("Failed to give you your Decked Out Shulker as your inventory is full", Formatting.RED)
return
return@runAsyncTask
}
inventory.updateItems()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener
import net.minecraft.resource.ResourceManager
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayNetworkHandler
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Formatting
import net.minecraft.util.Identifier
import net.minecraft.world.GameRules
import org.slf4j.LoggerFactory
import org.trackedout.AgroNet.runAsyncTask
import org.trackedout.RunContext
import org.trackedout.RunContext.serverName
import org.trackedout.actions.AddDeckToPlayerInventoryAction
Expand Down Expand Up @@ -82,6 +84,8 @@ class AgroNetPlayerConnectionListener(
return
}

val joinEventStartTime = System.currentTimeMillis()

var givePlayerTheirShulker = false
try {
if (!RunContext.initialized) {
Expand Down Expand Up @@ -123,11 +127,13 @@ class AgroNetPlayerConnectionListener(
val advancementFilter = "$runType-advancement-"

logger.info("Scoreboard filter: $filter")
var startTime = System.currentTimeMillis()
val scores = scoreApi.scoresGet(
player = playerName,
prefixFilter = filter,
limit = 10000,
)
logger.info("Fetched ${scores.results?.size} scoreboards for $playerName in ${System.currentTimeMillis() - startTime}ms")

val scoreboards = scores.results!!
.filter { it.key!!.startsWith(filter) }
Expand All @@ -136,44 +142,18 @@ class AgroNetPlayerConnectionListener(
.filter { it.key!!.isNotBlank() }

logger.info("Applying scoreboards: ${scoreboards.map { it.key to it.value }}")
startTime = System.currentTimeMillis()
scoreboards.forEach {
val objective = server.scoreboard.getObjective(it.key)

val playerScore = server.scoreboard.getPlayerScore(playerName, objective)
playerScore.score = it.value!!.toInt()
}
logger.info("Finished processing ${scoreboards.size} scoreboards for $playerName in ${System.currentTimeMillis() - startTime}ms")

val tracker = handler.player.advancementTracker
server.gameRules.get(GameRules.ANNOUNCE_ADVANCEMENTS).set(false, server)

scores.results
.filter { it.key!!.startsWith(advancementFilter) }
.map { it.copy(key = it.key?.substring(advancementFilter.length)) }
.filter { it.key!!.isNotBlank() && it.key.contains("#") }
.filter { it.value!!.toInt() > 0 }
.forEach { score ->
val split = score.key!!.split("#")
var namespace = "do2"
var key = split[0]
var criterion = split[1]

if (split.size == 3) {
namespace = split[0]
key = split[1]
criterion = split[2]
}

server.advancementLoader.advancements.find { it.id.namespace == namespace && it.id.path == key }?.let { advancement ->
val obtained: Boolean? = tracker.getProgress(advancement).getCriterionProgress(criterion)?.isObtained
if (obtained == null || obtained == false) {
tracker.grantCriterion(advancement, criterion)
// logger.info("Granted Advancement progress $key (criterion: $criterion) to $playerName")
// logger.info("Advancement: ${tracker.getProgress(advancement)}")
} else {
// logger.info("$playerName already has advancement progress $key (criterion: $criterion)")
}
}
}
runAsyncTask {
applyAdvancements(handler.player, scores.results, advancementFilter)
}

} catch (e: Exception) {
e.printStackTrace()
Expand All @@ -195,7 +175,72 @@ class AgroNetPlayerConnectionListener(
}
}

logger.info("Finished handling join event for $playerName in ${System.currentTimeMillis() - joinEventStartTime}ms")
}

private fun applyAdvancements(
player: ServerPlayerEntity,
results: List<Score>,
advancementFilter: String,
) {
val startTime = System.currentTimeMillis()
val tracker = player.advancementTracker

val playerName = player.name
val server = player.server

val advancements = results
.filter { it.key!!.startsWith(advancementFilter) }
.map { it.copy(key = it.key?.substring(advancementFilter.length)) }
.filter { it.key!!.isNotBlank() && it.key.contains("#") }
.filter { it.value!!.toInt() > 0 }

logger.info("Applying ${advancements.size} advancements for $playerName")
server.gameRules.get(GameRules.ANNOUNCE_ADVANCEMENTS).set(false, server)

val advancementProgressMap = mutableMapOf<String, List<String>>()
advancements.forEach { score ->
val split = score.key!!.split("#")
var namespace = "do2"
var key = split[0]
var criterion = split[1]

if (split.size == 3) {
namespace = split[0]
key = split[1]
criterion = split[2]
}

val nsKey = "$namespace#$key"
advancementProgressMap[nsKey] = advancementProgressMap.getOrDefault(nsKey, listOf()) + criterion
}

advancements.forEach { score ->
val split = score.key!!.split("#")
var namespace = "do2"
var key = split[0]
var criterion = split[1]

if (split.size == 3) {
namespace = split[0]
key = split[1]
criterion = split[2]
}

server.advancementLoader.advancements.find { it.id.namespace == namespace && it.id.path == key }?.let { advancement ->
val obtained: Boolean? = tracker.getProgress(advancement).getCriterionProgress(criterion)?.isObtained
if (obtained == null || !obtained) {
tracker.grantCriterion(advancement, criterion)
// logger.info("Granted Advancement progress $key (criterion: $criterion) to $playerName")
// logger.info("Advancement: ${tracker.getProgress(advancement)}")
} else {
// logger.info("$playerName already has advancement progress $key (criterion: $criterion)")
}
}
}

server.gameRules.get(GameRules.ANNOUNCE_ADVANCEMENTS).set(true, server)
logger.info("Finished processing ${advancements.size} advancements for $playerName in ${System.currentTimeMillis() - startTime}ms")
}

override fun onPlayDisconnect(handler: ServerPlayNetworkHandler, server: MinecraftServer) {
Expand Down

0 comments on commit 48cfb70

Please sign in to comment.