aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-11-13 13:40:50 +0100
committerLinnea Gräf <nea@nea.moe>2024-11-13 13:40:50 +0100
commitd267913e206f5f7bfc16607c0dc058290e6b556f (patch)
treeae586ff39bb970f51b84f89c7e0b96130e9f4e3b
parentdb87e5293846e27dc684dd141744390ae6e8bc67 (diff)
downloadFirmament-d267913e206f5f7bfc16607c0dc058290e6b556f.tar.gz
Firmament-d267913e206f5f7bfc16607c0dc058290e6b556f.tar.bz2
Firmament-d267913e206f5f7bfc16607c0dc058290e6b556f.zip
test: Add sack util test
-rw-r--r--build.gradle.kts33
-rw-r--r--buildSrc/src/RepoDownload.kt41
-rw-r--r--gradle.properties3
-rw-r--r--src/main/kotlin/features/diana/AncestralSpadeSolver.kt4
-rw-r--r--src/main/kotlin/repo/ItemCache.kt342
-rw-r--r--src/main/kotlin/repo/ItemNameLookup.kt155
-rw-r--r--src/main/kotlin/repo/RepoManager.kt61
-rw-r--r--src/main/kotlin/util/ErrorUtil.kt2
-rw-r--r--src/main/kotlin/util/MC.kt2
-rw-r--r--src/main/kotlin/util/TestUtil.kt5
-rw-r--r--src/main/kotlin/util/skyblock/SackUtil.kt7
-rw-r--r--src/main/kotlin/util/skyblock/SkyBlockItems.kt10
-rw-r--r--src/test/kotlin/util/skyblock/SackUtilTest.kt29
13 files changed, 425 insertions, 269 deletions
diff --git a/build.gradle.kts b/build.gradle.kts
index 7887641..53b0b87 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,6 +7,8 @@
*/
import com.google.devtools.ksp.gradle.KspTaskJvm
+import com.google.gson.Gson
+import com.google.gson.JsonObject
import moe.nea.licenseextractificator.LicenseDiscoveryTask
import moe.nea.mcautotranslations.gradle.CollectTranslations
import net.fabricmc.loom.LoomGradleExtension
@@ -219,7 +221,8 @@ val configuredSourceSet = createIsolatedSourceSet("configured",
val sodiumSourceSet = createIsolatedSourceSet("sodium")
val citResewnSourceSet = createIsolatedSourceSet("citresewn", isEnabled = false) // TODO: Wait for update
val yaclSourceSet = createIsolatedSourceSet("yacl")
-val explosiveEnhancementSourceSet = createIsolatedSourceSet("explosiveEnhancement", isEnabled = false) // TODO: wait for their port
+val explosiveEnhancementSourceSet =
+ createIsolatedSourceSet("explosiveEnhancement", isEnabled = false) // TODO: wait for their port
val wildfireGenderSourceSet = createIsolatedSourceSet("wildfireGender", isEnabled = false) // TODO: wait on their port
val modmenuSourceSet = createIsolatedSourceSet("modmenu")
val reiSourceSet = createIsolatedSourceSet("rei")
@@ -344,7 +347,35 @@ mcAutoTranslations {
translationFunctionResolved.set("moe.nea.firmament.util.trResolved")
}
+val downloadTestRepo by tasks.registering(RepoDownload::class) {
+ this.hash.set(project.property("firmament.compiletimerepohash") as String)
+}
+
+val updateTestRepo by tasks.registering {
+ outputs.upToDateWhen { false }
+ doLast {
+ val propertiesFile = rootProject.file("gradle.properties")
+ val json =
+ Gson().fromJson(uri("https://api.github.com/repos/NotEnoughUpdates/NotEnoughUpdates-REPO/branches/master")
+ .toURL().readText(), JsonObject::class.java)
+ val latestSha = json["commit"].asJsonObject["sha"].asString
+ var text = propertiesFile.readText()
+ text = text.replace("firmament\\.compiletimerepohash=[^\n]*".toRegex(),
+ "firmament.compiletimerepohash=$latestSha")
+ propertiesFile.writeText(text)
+ }
+}
+
+
tasks.test {
+ val wd =file("build/testWorkDir")
+ workingDir(wd)
+ dependsOn(downloadTestRepo)
+ doFirst {
+ wd.mkdirs()
+ wd.resolve("config").deleteRecursively()
+ systemProperty("firmament.testrepo", downloadTestRepo.flatMap { it.outputDirectory.asFile }.map { it.absolutePath }.get())
+ }
useJUnitPlatform()
}
diff --git a/buildSrc/src/RepoDownload.kt b/buildSrc/src/RepoDownload.kt
new file mode 100644
index 0000000..42a09b3
--- /dev/null
+++ b/buildSrc/src/RepoDownload.kt
@@ -0,0 +1,41 @@
+import java.net.URI
+import java.util.zip.ZipInputStream
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+
+abstract class RepoDownload : DefaultTask() {
+ @get:Input
+ abstract val hash: Property<String>
+
+ @get:OutputDirectory
+ abstract val outputDirectory: DirectoryProperty
+
+ init {
+ outputDirectory.convention(project.layout.buildDirectory.dir("extracted-test-repo"))
+ }
+
+ @TaskAction
+ fun performDownload() {
+ val outputDir = outputDirectory.asFile.get().absoluteFile
+ outputDir.mkdirs()
+ URI("https://github.com/notEnoughUpdates/notEnoughUpdates-rEPO/archive/${hash.get()}.zip").toURL().openStream()
+ .let(::ZipInputStream)
+ .use { zipInput ->
+ while (true) {
+ val entry = zipInput.nextEntry ?: break
+ val destination = outputDir.resolve(
+ entry.name.substringAfter('/')).absoluteFile
+ require(outputDir in generateSequence(destination) { it.parentFile })
+ if (entry.isDirectory) continue
+ destination.parentFile.mkdirs()
+ destination.outputStream().use { output ->
+ zipInput.copyTo(output)
+ }
+ }
+ }
+ }
+}
diff --git a/gradle.properties b/gradle.properties
index abca2cd..ec779d5 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
+# SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
#
# SPDX-License-Identifier: CC0-1.0
# suppress inspection "UnusedProperty" for whole file
@@ -9,3 +9,4 @@ loom.platform=fabric
archives_base_name=Firmament
maven_group=moe.nea.firmament
+firmament.compiletimerepohash=a6116d945491d7c57c93d43f51250f93d62d8434
diff --git a/src/main/kotlin/features/diana/AncestralSpadeSolver.kt b/src/main/kotlin/features/diana/AncestralSpadeSolver.kt
index 8918e66..ff85c00 100644
--- a/src/main/kotlin/features/diana/AncestralSpadeSolver.kt
+++ b/src/main/kotlin/features/diana/AncestralSpadeSolver.kt
@@ -20,6 +20,7 @@ import moe.nea.firmament.util.TimeMark
import moe.nea.firmament.util.WarpUtil
import moe.nea.firmament.util.render.RenderInWorldContext
import moe.nea.firmament.util.skyBlockId
+import moe.nea.firmament.util.skyblock.SkyBlockItems
object AncestralSpadeSolver : SubscriptionOwner {
var lastDing = TimeMark.farPast()
@@ -29,13 +30,12 @@ object AncestralSpadeSolver : SubscriptionOwner {
var nextGuess: Vec3d? = null
private set
- val ancestralSpadeId = SkyblockId("ANCESTRAL_SPADE")
private var lastTeleportAttempt = TimeMark.farPast()
fun isEnabled() =
DianaWaypoints.TConfig.ancestralSpadeSolver
&& SBData.skyblockLocation == SkyBlockIsland.HUB
- && MC.player?.inventory?.containsAny { it.skyBlockId == ancestralSpadeId } == true // TODO: add a reactive property here
+ && MC.player?.inventory?.containsAny { it.skyBlockId == SkyBlockItems.ANCESTRAL_SPADE } == true // TODO: add a reactive property here
@Subscribe
fun onKeyBind(event: WorldKeyboardEvent) {
diff --git a/src/main/kotlin/repo/ItemCache.kt b/src/main/kotlin/repo/ItemCache.kt
index c86934c..6fb2ab8 100644
--- a/src/main/kotlin/repo/ItemCache.kt
+++ b/src/main/kotlin/repo/ItemCache.kt
@@ -1,5 +1,3 @@
-
-
package moe.nea.firmament.repo
import com.mojang.serialization.Dynamic
@@ -30,186 +28,194 @@ import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.config.HudMeta
import moe.nea.firmament.gui.config.HudPosition
import moe.nea.firmament.gui.hud.MoulConfigHud
+import moe.nea.firmament.repo.RepoManager.initialize
import moe.nea.firmament.util.LegacyTagParser
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SkyblockId
+import moe.nea.firmament.util.TestUtil
import moe.nea.firmament.util.mc.appendLore
+import moe.nea.firmament.util.mc.modifyLore
import moe.nea.firmament.util.mc.setCustomName
import moe.nea.firmament.util.mc.setSkullOwner
-import moe.nea.firmament.util.mc.modifyLore
import moe.nea.firmament.util.skyblockId
object ItemCache : IReloadable {
- private val cache: MutableMap<String, ItemStack> = ConcurrentHashMap()
- private val df = Schemas.getFixer()
- val logger = LogManager.getLogger("${Firmament.logger.name}.ItemCache")
- var isFlawless = true
- private set
-
- private fun NEUItem.get10809CompoundTag(): NbtCompound = NbtCompound().apply {
- put("tag", LegacyTagParser.parse(nbttag))
- putString("id", minecraftItemId)
- putByte("Count", 1)
- putShort("Damage", damage.toShort())
- }
-
- private fun NbtCompound.transformFrom10809ToModern(): NbtCompound? =
- try {
- df.update(
- TypeReferences.ITEM_STACK,
- Dynamic(NbtOps.INSTANCE, this),
- -1,
- SharedConstants.getGameVersion().saveVersion.id
- ).value as NbtCompound
- } catch (e: Exception) {
- isFlawless = false
- logger.error("Could not data fix up $this", e)
- null
- }
-
- fun brokenItemStack(neuItem: NEUItem?, idHint: SkyblockId? = null): ItemStack {
- return ItemStack(Items.PAINTING).apply {
- setCustomName(Text.literal(neuItem?.displayName ?: idHint?.neuItem ?: "null"))
- appendLore(
- listOf(
- Text.stringifiedTranslatable(
- "firmament.repo.brokenitem",
- (neuItem?.skyblockItemId ?: idHint)
- )
- )
- )
- }
- }
-
- private fun NEUItem.asItemStackNow(): ItemStack {
- try {
- val oldItemTag = get10809CompoundTag()
- val modernItemTag = oldItemTag.transformFrom10809ToModern()
- ?: return brokenItemStack(this)
- val itemInstance =
- ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this)
- val extraAttributes = oldItemTag.getCompound("tag").getCompound("ExtraAttributes")
- if (extraAttributes != null)
- itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes))
- return itemInstance
- } catch (e: Exception) {
- e.printStackTrace()
- return brokenItemStack(this)
- }
- }
-
- fun NEUItem?.asItemStack(idHint: SkyblockId? = null, loreReplacements: Map<String, String>? = null): ItemStack {
- if (this == null) return brokenItemStack(null, idHint)
- var s = cache[this.skyblockItemId]
- if (s == null) {
- s = asItemStackNow()
- cache[this.skyblockItemId] = s
- }
- if (!loreReplacements.isNullOrEmpty()) {
- s = s.copy()!!
- s.applyLoreReplacements(loreReplacements)
- s.setCustomName(s.name.applyLoreReplacements(loreReplacements))
- }
- return s
- }
-
- fun ItemStack.applyLoreReplacements(loreReplacements: Map<String, String>) {
- modifyLore { lore ->
- lore.map {
- it.applyLoreReplacements(loreReplacements)
- }
- }
- }
-
- fun Text.applyLoreReplacements(loreReplacements: Map<String, String>): Text {
- assert(this.siblings.isEmpty())
- var string = this.string
- loreReplacements.forEach { (find, replace) ->
- string = string.replace("{$find}", replace)
- }
- return Text.literal(string).styled { this.style }
- }
-
- fun NEUItem.getIdentifier() = skyblockId.identifier
-
- var job: Job? = null
- object ReloadProgressHud : MoulConfigHud(
- "repo_reload", HudMeta(HudPosition(0.0, 0.0, 1F), Text.literal("Repo Reload"), 180, 18)) {
-
-
- var isEnabled = false
- override fun shouldRender(): Boolean {
- return isEnabled
- }
-
- @get:Bind("current")
- var current: Double = 0.0
-
- @get:Bind("label")
- var label: String = ""
-
- @get:Bind("max")
- var max: Double = 0.0
-
- fun reportProgress(label: String, current: Int, max: Int) {
- this.label = label
- this.current = current.toDouble()
- this.max = max.toDouble()
- }
- }
-
- override fun reload(repository: NEURepository) {
- val j = job
- if (j != null && j.isActive) {
- j.cancel()
- }
- cache.clear()
- isFlawless = true
-
- job = Firmament.coroutineScope.launch {
- val items = repository.items?.items
- if (items == null) {
- ReloadProgressHud.isEnabled = false
- return@launch
- }
- val recacheItems = I18n.translate("firmament.repo.cache")
- ReloadProgressHud.reportProgress(recacheItems, 0, items.size)
- ReloadProgressHud.isEnabled = true
- var i = 0
- items.values.forEach {
- it.asItemStack() // Rebuild cache
- ReloadProgressHud.reportProgress(recacheItems, i++, items.size)
- }
- ReloadProgressHud.isEnabled = false
- }
- }
-
- fun coinItem(coinAmount: Int): ItemStack {
- var uuid = UUID.fromString("2070f6cb-f5db-367a-acd0-64d39a7e5d1b")
- var texture =
- "http://textures.minecraft.net/texture/538071721cc5b4cd406ce431a13f86083a8973e1064d2f8897869930ee6e5237"
- if (coinAmount >= 100000) {
- uuid = UUID.fromString("94fa2455-2881-31fe-bb4e-e3e24d58dbe3")
- texture =
- "http://textures.minecraft.net/texture/c9b77999fed3a2758bfeaf0793e52283817bea64044bf43ef29433f954bb52f6"
- }
- if (coinAmount >= 10000000) {
- uuid = UUID.fromString("0af8df1f-098c-3b72-ac6b-65d65fd0b668")
- texture =
- "http://textures.minecraft.net/texture/7b951fed6a7b2cbc2036916dec7a46c4a56481564d14f945b6ebc03382766d3b"
- }
- val itemStack = ItemStack(Items.PLAYER_HEAD)
- itemStack.setCustomName(Text.literal("§r§6" + NumberFormat.getInstance().format(coinAmount) + " Coins"))
- itemStack.setSkullOwner(uuid, texture)
- return itemStack
- }
+ private val cache: MutableMap<String, ItemStack> = ConcurrentHashMap()
+ private val df = Schemas.getFixer()
+ val logger = LogManager.getLogger("${Firmament.logger.name}.ItemCache")
+ var isFlawless = true
+ private set
+
+ private fun NEUItem.get10809CompoundTag(): NbtCompound = NbtCompound().apply {
+ put("tag", LegacyTagParser.parse(nbttag))
+ putString("id", minecraftItemId)
+ putByte("Count", 1)
+ putShort("Damage", damage.toShort())
+ }
+
+ private fun NbtCompound.transformFrom10809ToModern(): NbtCompound? =
+ try {
+ df.update(
+ TypeReferences.ITEM_STACK,
+ Dynamic(NbtOps.INSTANCE, this),
+ -1,
+ SharedConstants.getGameVersion().saveVersion.id
+ ).value as NbtCompound
+ } catch (e: Exception) {
+ isFlawless = false
+ logger.error("Could not data fix up $this", e)
+ null
+ }
+
+ fun brokenItemStack(neuItem: NEUItem?, idHint: SkyblockId? = null): ItemStack {
+ return ItemStack(Items.PAINTING).apply {
+ setCustomName(Text.literal(neuItem?.displayName ?: idHint?.neuItem ?: "null"))
+ appendLore(
+ listOf(
+ Text.stringifiedTranslatable(
+ "firmament.repo.brokenitem",
+ (neuItem?.skyblockItemId ?: idHint)
+ )
+ )
+ )
+ }
+ }
+
+ private fun NEUItem.asItemStackNow(): ItemStack {
+ try {
+ val oldItemTag = get10809CompoundTag()
+ val modernItemTag = oldItemTag.transformFrom10809ToModern()
+ ?: return brokenItemStack(this)
+ val itemInstance =
+ ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this)
+ val extraAttributes = oldItemTag.getCompound("tag").getCompound("ExtraAttributes")
+ if (extraAttributes != null)
+ itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes))
+ return itemInstance
+ } catch (e: Exception) {
+ e.printStackTrace()
+ return brokenItemStack(this)
+ }
+ }
+
+ fun NEUItem?.asItemStack(idHint: SkyblockId? = null, loreReplacements: Map<String, String>? = null): ItemStack {
+ if (this == null) return brokenItemStack(null, idHint)
+ var s = cache[this.skyblockItemId]
+ if (s == null) {
+ s = asItemStackNow()
+ cache[this.skyblockItemId] = s
+ }
+ if (!loreReplacements.isNullOrEmpty()) {
+ s = s.copy()!!
+ s.applyLoreReplacements(loreReplacements)
+ s.setCustomName(s.name.applyLoreReplacements(loreReplacements))
+ }
+ return s
+ }
+
+ fun ItemStack.applyLoreReplacements(loreReplacements: Map<String, String>) {
+ modifyLore { lore ->
+ lore.map {
+ it.applyLoreReplacements(loreReplacements)
+ }
+ }
+ }
+
+ fun Text.applyLoreReplacements(loreReplacements: Map<String, String>): Text {
+ assert(this.siblings.isEmpty())
+ var string = this.string
+ loreReplacements.forEach { (find, replace) ->
+ string = string.replace("{$find}", replace)
+ }
+ return Text.literal(string).styled { this.style }
+ }
+
+ var job: Job? = null
+
+ object ReloadProgressHud : MoulConfigHud(
+ "repo_reload", HudMeta(HudPosition(0.0, 0.0, 1F), Text.literal("Repo Reload"), 180, 18)) {
+
+
+ var isEnabled = false
+ override fun shouldRender(): Boolean {
+ return isEnabled
+ }
+
+ @get:Bind("current")
+ var current: Double = 0.0
+
+ @get:Bind("label")
+ var label: String = ""
+
+ @get:Bind("max")
+ var max: Double = 0.0
+
+ fun reportProgress(label: String, current: Int, max: Int) {
+ this.label = label
+ this.current = current.toDouble()
+ this.max = max.toDouble()
+ }
+ }
+
+ override fun reload(repository: NEURepository) {
+ val j = job
+ if (j != null && j.isActive) {
+ j.cancel()
+ }
+ cache.clear()
+ isFlawless = true
+ if (TestUtil.isInTest) return
+ job = Firmament.coroutineScope.launch {
+ val items = repository.items?.items
+ if (items == null) {
+ ReloadProgressHud.isEnabled = false
+ return@launch
+ }
+ val recacheItems = I18n.translate("firmament.repo.cache")
+ ReloadProgressHud.reportProgress(recacheItems, 0, items.size)
+ ReloadProgressHud.isEnabled = true
+ var i = 0
+ items.values.forEach {
+ it.asItemStack() // Rebuild cache
+ ReloadProgressHud.reportProgress(recacheItems, i++, items.size)
+ }
+ ReloadProgressHud.isEnabled = false
+ }
+ }
+
+ fun coinItem(coinAmount: Int): ItemStack {
+ var uuid = UUID.fromString("2070f6cb-f5db-367a-acd0-64d39a7e5d1b")
+ var texture =
+ "http://textures.minecraft.net/texture/538071721cc5b4cd406ce431a13f86083a8973e1064d2f8897869930ee6e5237"
+ if (coinAmount >= 100000) {
+ uuid = UUID.fromString("94fa2455-2881-31fe-bb4e-e3e24d58dbe3")
+ texture =
+ "http://textures.minecraft.net/texture/c9b77999fed3a2758bfeaf0793e52283817bea64044bf43ef29433f954bb52f6"
+ }
+ if (coinAmount >= 10000000) {
+ uuid = UUID.fromString("0af8df1f-098c-3b72-ac6b-65d65fd0b668")
+ texture =
+ "http://textures.minecraft.net/texture/7b951fed6a7b2cbc2036916dec7a46c4a56481564d14f945b6ebc03382766d3b"
+ }
+ val itemStack = ItemStack(Items.PLAYER_HEAD)
+ itemStack.setCustomName(Text.literal("§r§6" + NumberFormat.getInstance().format(coinAmount) + " Coins"))
+ itemStack.setSkullOwner(uuid, texture)
+ return itemStack
+ }
+
+ init {
+ if (TestUtil.isInTest) {
+ initialize()
+ }
+ }
+
}
operator fun NbtCompound.set(key: String, value: String) {
- putString(key, value)
+ putString(key, value)
}
operator fun NbtCompound.set(key: String, value: NbtElement) {
- put(key, value)
+ put(key, value)
}
diff --git a/src/main/kotlin/repo/ItemNameLookup.kt b/src/main/kotlin/repo/ItemNameLookup.kt
index 770de85..1250730 100644
--- a/src/main/kotlin/repo/ItemNameLookup.kt
+++ b/src/main/kotlin/repo/ItemNameLookup.kt
@@ -1,4 +1,3 @@
-
package moe.nea.firmament.repo
import io.github.moulberry.repo.IReloadable
@@ -12,87 +11,91 @@ import moe.nea.firmament.util.skyblockId
object ItemNameLookup : IReloadable {
- fun getItemNameChunks(name: String): Set<String> {
- return name.removeColorCodes().split(" ").filterTo(mutableSetOf()) { it.isNotBlank() }
- }
+ fun getItemNameChunks(name: String): Set<String> {
+ return name.removeColorCodes().split(" ").filterTo(mutableSetOf()) { it.isNotBlank() }
+ }
+
+ var nameMap: NavigableMap<String, out Set<SkyblockId>> = TreeMap()
- var nameMap: NavigableMap<String, out Set<SkyblockId>> = TreeMap()
+ override fun reload(repository: NEURepository) {
+ val nameMap = TreeMap<String, MutableSet<SkyblockId>>()
+ repository.items.items.values.forEach { item ->
+ getAllNamesForItem(item).forEach { name ->
+ val chunks = getItemNameChunks(name)
+ chunks.forEach { chunk ->
+ val set = nameMap.getOrPut(chunk, ::mutableSetOf)
+ set.add(item.skyblockId)
+ }
+ }
+ }
+ this.nameMap = nameMap
+ }
- override fun reload(repository: NEURepository) {
- val nameMap = TreeMap<String, MutableSet<SkyblockId>>()
- repository.items.items.values.forEach { item ->
- getAllNamesForItem(item).forEach { name ->
- val chunks = getItemNameChunks(name)
- chunks.forEach { chunk ->
- val set = nameMap.getOrPut(chunk, ::mutableSetOf)
- set.add(item.skyblockId)
- }
- }
- }
- this.nameMap = nameMap
- }
+ fun getAllNamesForItem(item: NEUItem): Set<String> {
+ val names = mutableSetOf<String>()
+ names.add(item.displayName)
+ if (item.displayName.contains("Enchanted Book")) {
+ val enchantName = item.lore.firstOrNull()
+ if (enchantName != null) {
+ names.add(enchantName)
+ }
+ }
+ return names
+ }
- fun getAllNamesForItem(item: NEUItem): Set<String> {
- val names = mutableSetOf<String>()
- names.add(item.displayName)
- if (item.displayName.contains("Enchanted Book")) {
- val enchantName = item.lore.firstOrNull()
- if (enchantName != null) {
- names.add(enchantName)
- }
- }
- return names
- }
+ fun findItemCandidatesByName(name: String): MutableSet<SkyblockId> {
+ val candidates = mutableSetOf<SkyblockId>()
+ for (chunk in getItemNameChunks(name)) {
+ val set = nameMap[chunk] ?: emptySet()
+ candidates.addAll(set)
+ }
+ return candidates
+ }
- fun findItemCandidatesByName(name: String): MutableSet<SkyblockId> {
- val candidates = mutableSetOf<SkyblockId>()
- for (chunk in getItemNameChunks(name)) {
- val set = nameMap[chunk] ?: emptySet()
- candidates.addAll(set)
- }
- return candidates
- }
+ fun guessItemByName(
+ /**
+ * The display name of the item. Color codes will be ignored.
+ */
+ name: String,
+ /**
+ * Whether the [name] may contain other text, such as reforges, master stars and such.
+ */
+ mayBeMangled: Boolean
+ ): SkyblockId? {
+ val cleanName = name.removeColorCodes()
+ return findBestItemFromCandidates(
+ findItemCandidatesByName(cleanName),
+ cleanName,
+ true
+ )
+ }
- fun guessItemByName(
- /**
- * The display name of the item. Color codes will be ignored.
- */
- name: String,
- /**
- * Whether the [name] may contain other text, such as reforges, master stars and such.
- */
- mayBeMangled: Boolean
- ): SkyblockId? {
- val cleanName = name.removeColorCodes()
- return findBestItemFromCandidates(
- findItemCandidatesByName(cleanName),
- cleanName,
- true
- )
- }
+ fun findBestItemFromCandidates(
+ candidates: Iterable<SkyblockId>,
+ name: String, mayBeMangled: Boolean
+ ): SkyblockId? {
+ val expectedClean = name.removeColorCodes()
+ var bestMatch: SkyblockId? = null
+ var bestMatchLength = -1
+ for (candidate in candidates) {
+ val item = RepoManager.getNEUItem(candidate) ?: continue
+ for (name in getAllNamesForItem(item)) {
+ val actualClean = name.removeColorCodes()
+ val matches = if (mayBeMangled) expectedClean == actualClean
+ else expectedClean.contains(actualClean)
+ if (!matches) continue
+ if (actualClean.length > bestMatchLength) {
+ bestMatch = candidate
+ bestMatchLength = actualClean.length
+ }
+ }
+ }
+ return bestMatch
+ }
- fun findBestItemFromCandidates(
- candidates: Iterable<SkyblockId>,
- name: String, mayBeMangled: Boolean
- ): SkyblockId? {
- val expectedClean = name.removeColorCodes()
- var bestMatch: SkyblockId? = null
- var bestMatchLength = -1
- for (candidate in candidates) {
- val item = RepoManager.getNEUItem(candidate) ?: continue
- for (name in getAllNamesForItem(item)) {
- val actualClean = name.removeColorCodes()
- val matches = if (mayBeMangled) expectedClean == actualClean
- else expectedClean.contains(actualClean)
- if (!matches) continue
- if (actualClean.length > bestMatchLength) {
- bestMatch = candidate
- bestMatchLength = actualClean.length
- }
- }
- }
- return bestMatch
- }
+ init {
+ RepoManager.initialize()
+ }
}
diff --git a/src/main/kotlin/repo/RepoManager.kt b/src/main/kotlin/repo/RepoManager.kt
index 725642e..dc39511 100644
--- a/src/main/kotlin/repo/RepoManager.kt
+++ b/src/main/kotlin/repo/RepoManager.kt
@@ -5,6 +5,7 @@ import io.github.moulberry.repo.NEURepositoryException
import io.github.moulberry.repo.data.NEUItem
import io.github.moulberry.repo.data.NEURecipe
import io.github.moulberry.repo.data.Rarity
+import java.nio.file.Path
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
import kotlinx.coroutines.launch
import net.minecraft.client.MinecraftClient
@@ -14,9 +15,11 @@ import moe.nea.firmament.Firmament
import moe.nea.firmament.Firmament.logger
import moe.nea.firmament.events.ReloadRegistrationEvent
import moe.nea.firmament.gui.config.ManagedConfig
+import moe.nea.firmament.util.ErrorUtil
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.MinecraftDispatcher
import moe.nea.firmament.util.SkyblockId
+import moe.nea.firmament.util.TestUtil
import moe.nea.firmament.util.tr
object RepoManager {
@@ -49,28 +52,31 @@ object RepoManager {
var recentlyFailedToUpdateItemList = false
- val neuRepo: NEURepository = NEURepository.of(RepoDownloadManager.repoSavedLocation).apply {
- registerReloadListener(ItemCache)
- registerReloadListener(ExpLadders)
- registerReloadListener(ItemNameLookup)
- ReloadRegistrationEvent.publish(ReloadRegistrationEvent(this))
- registerReloadListener {
- Firmament.coroutineScope.launch(MinecraftDispatcher) {
- if (!trySendClientboundUpdateRecipesPacket()) {
- logger.warn("Failed to issue a ClientboundUpdateRecipesPacket (to reload REI). This may lead to an outdated item list.")
- recentlyFailedToUpdateItemList = true
+ val essenceRecipeProvider = EssenceRecipeProvider()
+ val recipeCache = BetterRepoRecipeCache(essenceRecipeProvider)
+
+ fun makeNEURepository(path: Path): NEURepository {
+ return NEURepository.of(path).apply {
+ registerReloadListener(ItemCache)
+ registerReloadListener(ExpLadders)
+ registerReloadListener(ItemNameLookup)
+ ReloadRegistrationEvent.publish(ReloadRegistrationEvent(this))
+ registerReloadListener {
+ if (TestUtil.isInTest) return@registerReloadListener
+ Firmament.coroutineScope.launch(MinecraftDispatcher) {
+ if (!trySendClientboundUpdateRecipesPacket()) {
+ logger.warn("Failed to issue a ClientboundUpdateRecipesPacket (to reload REI). This may lead to an outdated item list.")
+ recentlyFailedToUpdateItemList = true
+ }
}
}
+ registerReloadListener(essenceRecipeProvider)
+ registerReloadListener(recipeCache)
}
}
- val essenceRecipeProvider = EssenceRecipeProvider()
- val recipeCache = BetterRepoRecipeCache(essenceRecipeProvider)
-
- init {
- neuRepo.registerReloadListener(essenceRecipeProvider)
- neuRepo.registerReloadListener(recipeCache)
- }
+ lateinit var neuRepo: NEURepository
+ private set
fun getAllRecipes() = neuRepo.items.items.values.asSequence().flatMap { it.recipes }
@@ -106,6 +112,11 @@ object RepoManager {
}
}
+ fun reloadForTest(from: Path) {
+ neuRepo = makeNEURepository(from)
+ reload()
+ }
+
fun reload() {
try {
ItemCache.ReloadProgressHud.reportProgress("Reloading from Disk",
@@ -114,16 +125,24 @@ object RepoManager {
ItemCache.ReloadProgressHud.isEnabled = true
neuRepo.reload()
} catch (exc: NEURepositoryException) {
+ ErrorUtil.softError("Failed to reload repository", exc)
MC.sendChat(
tr("firmament.repo.reloadfail",
"Failed to reload repository. This will result in some mod features not working.")
)
ItemCache.ReloadProgressHud.isEnabled = false
- exc.printStackTrace()
}
}
+ private var wasInitialized = false
fun initialize() {
+ if (wasInitialized) return
+ wasInitialized = true
+ System.getProperty("firmament.testrepo")?.let { compTimeRepo ->
+ reloadForTest(Path.of(compTimeRepo))
+ return
+ }
+ neuRepo = makeNEURepository(RepoDownloadManager.repoSavedLocation)
if (Config.autoUpdate) {
launchAsyncUpdate()
} else {
@@ -131,6 +150,12 @@ object RepoManager {
}
}
+ init {
+ if (TestUtil.isInTest) {
+ initialize()
+ }
+ }
+
fun getPotentialStubPetData(skyblockId: SkyblockId): PetData? {
val parts = skyblockId.neuItem.split(";")
if (parts.size != 2) {
diff --git a/src/main/kotlin/util/ErrorUtil.kt b/src/main/kotlin/util/ErrorUtil.kt
index b06093b..5dc44d3 100644
--- a/src/main/kotlin/util/ErrorUtil.kt
+++ b/src/main/kotlin/util/ErrorUtil.kt
@@ -10,7 +10,7 @@ import moe.nea.firmament.Firmament
@Suppress("NOTHING_TO_INLINE") // Suppressed since i want the logger to not pick up the ErrorUtil stack-frame
object ErrorUtil {
var aggressiveErrors = run {
- Thread.currentThread().stackTrace.any { it.className.startsWith("org.junit.") } || Firmament.DEBUG
+ TestUtil.isInTest || Firmament.DEBUG
|| ErrorUtil::class.java.desiredAssertionStatus()
}
diff --git a/src/main/kotlin/util/MC.kt b/src/main/kotlin/util/MC.kt
index cbcd8ae..3f5d633 100644
--- a/src/main/kotlin/util/MC.kt
+++ b/src/main/kotlin/util/MC.kt
@@ -102,7 +102,7 @@ object MC {
inline val handledScreen: HandledScreen<*>? get() = instance.currentScreen as? HandledScreen<*>
inline val window get() = instance.window
inline val currentRegistries: RegistryWrapper.WrapperLookup? get() = world?.registryManager
- val defaultRegistries: RegistryWrapper.WrapperLookup = BuiltinRegistries.createWrapperLookup()
+ val defaultRegistries: RegistryWrapper.WrapperLookup by lazy { BuiltinRegistries.createWrapperLookup() }
inline val currentOrDefaultRegistries get() = currentRegistries ?: defaultRegistries
val defaultItems: RegistryWrapper.Impl<Item> = defaultRegistries.getOrThrow(RegistryKeys.ITEM)
var lastWorld: World? = null
diff --git a/src/main/kotlin/util/TestUtil.kt b/src/main/kotlin/util/TestUtil.kt
new file mode 100644
index 0000000..68a406f
--- /dev/null
+++ b/src/main/kotlin/util/TestUtil.kt
@@ -0,0 +1,5 @@
+package moe.nea.firmament.util
+
+object TestUtil {
+ val isInTest = Thread.currentThread().stackTrace.any { it.className.startsWith("org.junit.") }
+}
diff --git a/src/main/kotlin/util/skyblock/SackUtil.kt b/src/main/kotlin/util/skyblock/SackUtil.kt
index 2679949..fd67c44 100644
--- a/src/main/kotlin/util/skyblock/SackUtil.kt
+++ b/src/main/kotlin/util/skyblock/SackUtil.kt
@@ -60,8 +60,13 @@ object SackUtil {
@Subscribe
fun updateFromChat(event: ProcessChatEvent) {
if (!event.unformattedString.startsWith("[Sacks]")) return
+ getUpdatesFromMessage(event.text)
+ }
+
+ fun getUpdatesFromMessage(text: Text): List<SackUpdate> {
val update = ChatUpdate()
- event.text.siblings.forEach(update::updateFromHoverText)
+ text.siblings.forEach(update::updateFromHoverText)
+ return update.updates
}
data class SackUpdate(
diff --git a/src/main/kotlin/util/skyblock/SkyBlockItems.kt b/src/main/kotlin/util/skyblock/SkyBlockItems.kt
new file mode 100644
index 0000000..c94ebfe
--- /dev/null
+++ b/src/main/kotlin/util/skyblock/SkyBlockItems.kt
@@ -0,0 +1,10 @@
+package moe.nea.firmament.util.skyblock
+
+import moe.nea.firmament.util.SkyblockId
+
+object SkyBlockItems {
+ val ROTTEN_FLESH = SkyblockId("ROTTEN_FLESH")
+ val ENCHANTED_DIAMOND = SkyblockId("ENCHANTED_DIAMOND")
+ val DIAMOND = SkyblockId("DIAMOND")
+ val ANCESTRAL_SPADE = SkyblockId("ANCESTRAL_SPADE")
+}
diff --git a/src/test/kotlin/util/skyblock/SackUtilTest.kt b/src/test/kotlin/util/skyblock/SackUtilTest.kt
new file mode 100644
index 0000000..e0e3e63
--- /dev/null
+++ b/src/test/kotlin/util/skyblock/SackUtilTest.kt
@@ -0,0 +1,29 @@
+package moe.nea.firmament.test.util.skyblock
+
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+import moe.nea.firmament.test.testutil.ItemResources
+import moe.nea.firmament.util.skyblock.SackUtil
+import moe.nea.firmament.util.skyblock.SkyBlockItems
+
+class SackUtilTest {
+ @Test
+ fun testOneRottenFlesh() {
+ Assertions.assertEquals(
+ listOf(
+ SackUtil.SackUpdate(SkyBlockItems.ROTTEN_FLESH, "Rotten Flesh", 1)
+ ),
+ SackUtil.getUpdatesFromMessage(ItemResources.loadText("sacks/gain-rotten-flesh"))
+ )
+ }
+
+ @Test
+ fun testAFewRegularItems() {
+ Assertions.assertEquals(
+ listOf(
+ SackUtil.SackUpdate(SkyBlockItems.ROTTEN_FLESH, "Rotten Flesh", 1)
+ ),
+ SackUtil.getUpdatesFromMessage(ItemResources.loadText("sacks/gain-and-lose-regular"))
+ )
+ }
+}