Skip to content

Commit

Permalink
Use data from Brilliance to limit card counts when generating a playe…
Browse files Browse the repository at this point in the history
…r's deck

Resolves #37
  • Loading branch information
4Ply committed Dec 26, 2024
1 parent 6f2f4f9 commit c542863
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 3,159 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ jobs:
run: cp Brilliance/scoreboards.json src/main/resources/assets/agronet/scoreboards.json

- name: build
env:
ORG_GRADLE_PROJECT_scoreboards_json: brilliance-configs/scoreboards.json
ORG_GRADLE_PROJECT_cards_json: brilliance-configs/Cards.json
ORG_GRADLE_PROJECT_artifacts_json: brilliance-configs/Artifacts.json
run: ./gradlew build

- name: capture build artifacts
Expand Down
18 changes: 18 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,30 @@ dependencies {
include(modImplementation('me.lucko:fabric-permissions-api:0.2-SNAPSHOT'))
}

def brillianceDataDir = "data/brilliance-data"
def scoreboardsJsonPath = property('scoreboards_json')
def cardsJsonPath = property('cards_json')
def artifactsJsonPath = property('artifacts_json')

processResources {
inputs.property "version", project.version

filesMatching("fabric.mod.json") {
expand "version": project.version
}

// Place json files in resources/brilliance-data/
from(scoreboardsJsonPath) {
into(brillianceDataDir)
}
from(cardsJsonPath) {
rename { "cards.json" }
into(brillianceDataDir)
}
from(artifactsJsonPath) {
rename { "artifacts.json" }
into(brillianceDataDir)
}
}

tasks.withType(JavaCompile).configureEach {
Expand Down
5 changes: 5 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ maven_group=org.trackedout
archives_base_name=agronet
# Dependencies
fabric_version=0.91.0+1.20.1

# You can overwrite this with ORG_GRADLE_PROJECT_cards_json="<path>"
scoreboards_json=../Brilliance/JSON/scoreboards.json
cards_json=../Brilliance/JSON/items_json/Cards.json
artifacts_json=../Brilliance/JSON/items_json/Artifacts.json
3 changes: 3 additions & 0 deletions src/main/kotlin/org/trackedout/RunContext.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.trackedout

import com.google.common.collect.Maps
import org.trackedout.data.BrillianceCard
import java.util.UUID
import java.util.concurrent.ConcurrentMap

Expand All @@ -9,6 +10,8 @@ data object RunContext {
var runId = UUID.randomUUID().toString()
var initialized = false

var brillianceCards = mapOf<String, BrillianceCard>()

private val playerContextMap: ConcurrentMap<String, PlayerContext> = Maps.newConcurrentMap()

fun addPlayerContext(playerName: String, context: PlayerContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import org.trackedout.fullRunType
import org.trackedout.runType
import org.trackedout.sendMessage
import org.trackedout.shortDeckId
import kotlin.math.max
import kotlin.math.min

class AddDeckToPlayerInventoryAction(
private val eventsApi: EventsApiWithContext,
Expand Down Expand Up @@ -79,14 +81,54 @@ class AddDeckToPlayerInventoryAction(
val cardCount = cards
.filter { Cards.findCard(it.name!!) != null }
.groupingBy { it.name!! }.eachCount()
var cardIndex = 0
player.debug("Your shulker should contain ${cards.size} cards:")
cardCount.forEach { (cardName, count) ->
player.debug("- ${count}x $cardName")
logger.info("$playerName's shulker should contain ${count}x $cardName")
var cardIndex = 0
var totalCards = 0
var sentTruncationWarning = false
val modificationLog = mutableMapOf<String, String>()

cardCount.forEach { (cardName, countInDeck) ->
player.debug("- ${countInDeck}x $cardName")
val card = Cards.findCard(cardName)!!
val maxCopies = RunContext.brillianceCards[card.key]?.maxCopies
var count = min(countInDeck, maxCopies ?: countInDeck)
logger.info("$playerName's shulker should contain ${count}x $cardName (deck has $countInDeck, max copies is $maxCopies, deck contains $totalCards cards)")

if (countInDeck > (maxCopies ?: 0)) {
// If the player has more copies of a card than they should, log the new count that we're giving them
modificationLog["new-card-count-${cardName.replace("_", "-")}"] = "$count"
logger.warn("$playerName has too many copies of $cardName in their deck, truncating to $count")
player.sendMessage("You have too many copies of $cardName in your deck, truncating to $count", Formatting.RED)
}

// If the new cards would take the total over 40, truncate the count to only fill up to 40
if (totalCards + count > 40) {
count = max(0, 40 - totalCards)
modificationLog["new-card-count-${cardName.replace("_", "-")}"] = "$count"
if (!sentTruncationWarning) {
logger.warn("$playerName has too many cards in their deck, truncating to 40")
player.sendMessage("You have too many cards in your deck, truncating to 40", Formatting.RED)
sentTruncationWarning = true
}
logger.info("Deck limit exceeded. New count for $cardName is $count")
}

if (count <= 0) {
eventsApi.eventsPost(
Event(
name = "card-skipped-on-join-${cardName.replace("_", "-")}",
player = playerName,
x = 0.0,
y = 0.0,
z = 0.0,
count = count,
)
)
return@forEach
}

val cardData = createCard(cardIndex++, card, count)
totalCards += count
shulkerItems.add(cardData)

eventsApi.eventsPost(
Expand All @@ -101,6 +143,20 @@ class AddDeckToPlayerInventoryAction(
)
}

if (modificationLog.isNotEmpty()) {
eventsApi.eventsPost(
Event(
name = "deck-modified-on-join",
player = playerName,
x = 0.0,
y = 0.0,
z = 0.0,
count = 1,
metadata = modificationLog
)
)
}

cards
.filter { Cards.findCard(it.name!!) == null }
.forEach { item ->
Expand Down
66 changes: 66 additions & 0 deletions src/main/kotlin/org/trackedout/data/BrillianceCard.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.trackedout.data

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/*
Example:
{
"shorthand": "MOC",
"id": "minecraft:iron_nugget",
"maxCopies": 5,
"tag": {
"NameFormat": {
"color": "gray",
"OriginalName": "'{\"color\":\"gray\",\"text\":\"✲ Moment of Clarity ✲\"}'",
"ModifiedName": "'{\"color\":\"gray\",\"text\":\"✲ Moment of Clarity ✲\"}'"
},
"CustomRoleplayData": "1b",
"CustomModelData": 106,
"display": {
"Name": "'{\"color\":\"gray\",\"text\":\"✲ Moment of Clarity ✲\"}'"
},
"tracked": "0b"
}
}
*/

@Serializable
data class BrillianceCard(
val shorthand: String,
val id: String,
val tag: Tag,
val maxCopies: Int? = null,
)

@Serializable
data class Tag(
@SerialName("NameFormat")
val nameFormat: NameFormat? = null,

@SerialName("CustomRoleplayData")
val customRoleplayData: String? = null,

@SerialName("CustomModelData")
val customModelData: Long? = null,

val display: Display,
val tracked: String? = null,
)

@Serializable
data class Display(
@SerialName("Name")
val name: String? = null,
)

@Serializable
data class NameFormat(
val color: String? = null,

@SerialName("OriginalName")
val originalName: String? = null,

@SerialName("ModifiedName")
val modifiedName: String? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ data class BrillianceScoreboardDescription(
val target: String,
val category: String,
val description: String,
val values: Map<String, String>? = mapOf(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ import org.trackedout.client.apis.ScoreApi
import org.trackedout.client.apis.TasksApi
import org.trackedout.client.models.Score
import org.trackedout.client.models.Task
import org.trackedout.data.BrillianceCard
import org.trackedout.data.BrillianceScoreboardDescription
import org.trackedout.fullRunType
import org.trackedout.runType
import org.trackedout.sendMessage
import java.nio.charset.StandardCharsets

val json = Json { ignoreUnknownKeys = true }

class AgroNetPlayerConnectionListener(
private val scoreApi: ScoreApi,
private val claimApi: ClaimApi,
Expand All @@ -40,27 +43,35 @@ class AgroNetPlayerConnectionListener(
return Identifier("agronet", "scoreboard")
}

// Use scoreboards.json (authored in Brilliance) to determine which objectives to store
// Use data from Brilliance to determine which objectives to store, and Card limits
override fun reload(resourceManager: ResourceManager) {
val resourceId = Identifier("agronet", "scoreboards.json")
parseBrillianceData<Map<String, BrillianceScoreboardDescription>>(resourceManager, "scoreboards.json") { map ->
objectivesToStore = map.filter { it.value.category == "totals" }.keys.toList()
println("Updated objectives to store to: $objectivesToStore")
}

parseBrillianceData<Map<String, BrillianceCard>>(resourceManager, "cards.json") { map ->
RunContext.brillianceCards = map
println("Card data from Brilliance: ${RunContext.brillianceCards}")
}
}

private inline fun <reified T> parseBrillianceData(resourceManager: ResourceManager, fileName: String, unit: (T) -> Unit) {
val resourceId = Identifier("brilliance-data", fileName)

try {
// Obtain the resource as an InputStream
val resource = resourceManager.getResource(resourceId).orElseThrow {
throw IllegalStateException("Resource not found: $resourceId")
throw IllegalStateException("Resource $fileName not found: $resourceId")
}

// Read and parse the JSON file using Gson
resource.inputStream.use { inputStream ->
val jsonData = inputStream.bufferedReader(StandardCharsets.UTF_8).use { it.readText() }
val scoreboardDescriptionMap: Map<String, BrillianceScoreboardDescription> = Json.decodeFromString(jsonData)

objectivesToStore = scoreboardDescriptionMap.filter { it.value.category == "totals" }.keys.toList()

println("Updated objectives to store to: $objectivesToStore")
unit(json.decodeFromString<T>(jsonData))
}
} catch (e: Exception) {
println("Failed to load JSON: ${e.message}")
println("Failed to load $fileName: ${e.message}")
}
}

Expand Down
Loading

0 comments on commit c542863

Please sign in to comment.