aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-12-31 16:52:29 +0100
committerLinnea Gräf <nea@nea.moe>2024-12-31 16:52:29 +0100
commita892a5f90b87b530331a7652dd4eb5bc07bf1c03 (patch)
tree808ac4b59557b2b0a6c8459a2dac13ce272937a6
parent533fd68e2be8236c842f53fd0cafa52341226226 (diff)
parent620f1a45ac02b078e95c68a59a45bd4d24ff176b (diff)
downloadFirmament-a892a5f90b87b530331a7652dd4eb5bc07bf1c03.tar.gz
Firmament-a892a5f90b87b530331a7652dd4eb5bc07bf1c03.tar.bz2
Firmament-a892a5f90b87b530331a7652dd4eb5bc07bf1c03.zip
Merge branch 'mc-1.21.3'
-rw-r--r--build.gradle.kts1
-rw-r--r--gradle.properties3
-rw-r--r--gradle/libs.versions.toml2
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt34
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt6
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt210
-rw-r--r--src/compat/yacl/java/YaclIntegration.kt29
-rw-r--r--src/main/java/moe/nea/firmament/mixins/AlwaysDisplayFirmamentClientCommandErrors.java18
-rw-r--r--src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java2
-rw-r--r--src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java29
-rw-r--r--src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java17
-rw-r--r--src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java18
-rw-r--r--src/main/kotlin/commands/Duration.kt75
-rw-r--r--src/main/kotlin/events/PartyMessageReceivedEvent.kt9
-rw-r--r--src/main/kotlin/features/chat/PartyCommands.kt134
-rw-r--r--src/main/kotlin/features/chat/QuickCommands.kt212
-rw-r--r--src/main/kotlin/features/fixes/Fixes.kt94
-rw-r--r--src/main/kotlin/features/inventory/ItemRarityCosmetics.kt13
-rw-r--r--src/main/kotlin/features/inventory/SlotLocking.kt44
-rw-r--r--src/main/kotlin/features/inventory/TimerInLore.kt130
-rw-r--r--src/main/kotlin/features/inventory/storageoverlay/VirtualInventory.kt82
-rw-r--r--src/main/kotlin/features/mining/PickaxeAbility.kt2
-rw-r--r--src/main/kotlin/features/misc/TimerFeature.kt124
-rw-r--r--src/main/kotlin/gui/config/ChoiceHandler.kt1
-rw-r--r--src/main/kotlin/gui/config/ManagedConfig.kt19
-rw-r--r--src/main/kotlin/gui/config/ManagedOption.kt9
-rw-r--r--src/main/kotlin/gui/entity/EntityRenderer.kt13
-rw-r--r--src/main/kotlin/repo/BetterRepoRecipeCache.kt36
-rw-r--r--src/main/kotlin/repo/EssenceRecipeProvider.kt75
-rw-r--r--src/main/kotlin/repo/ExtraRecipeProvider.kt7
-rw-r--r--src/main/kotlin/repo/ItemCache.kt48
-rw-r--r--src/main/kotlin/repo/Reforge.kt160
-rw-r--r--src/main/kotlin/repo/ReforgeStore.kt124
-rw-r--r--src/main/kotlin/repo/RepoItemTypeCache.kt15
-rw-r--r--src/main/kotlin/repo/RepoManager.kt6
-rw-r--r--src/main/kotlin/repo/SBItemStack.kt186
-rw-r--r--src/main/kotlin/util/AprilFoolsUtil.kt10
-rw-r--r--src/main/kotlin/util/FirmFormatters.kt14
-rw-r--r--src/main/kotlin/util/LegacyFormattingCode.kt54
-rw-r--r--src/main/kotlin/util/MC.kt5
-rw-r--r--src/main/kotlin/util/SBData.kt116
-rw-r--r--src/main/kotlin/util/SkyBlockIsland.kt1
-rw-r--r--src/main/kotlin/util/SkyblockId.kt23
-rw-r--r--src/main/kotlin/util/mc/NbtItemData.kt4
-rw-r--r--src/main/kotlin/util/mc/TolerantRegistriesOps.kt29
-rw-r--r--src/main/kotlin/util/skyblock/ItemType.kt27
-rw-r--r--src/main/kotlin/util/skyblock/Rarity.kt38
-rw-r--r--src/main/kotlin/util/skyblock/SkyBlockItems.kt1
-rw-r--r--src/main/kotlin/util/textutil.kt9
-rw-r--r--src/main/resources/firmament.accesswidener3
-rw-r--r--src/test/resources/testdata/items/hyperion.snbt96
-rw-r--r--src/test/resources/testdata/items/implosion-belt.snbt105
-rw-r--r--translations/en_us.json30
53 files changed, 2182 insertions, 370 deletions
diff --git a/build.gradle.kts b/build.gradle.kts
index e56d273..51c981d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -177,6 +177,7 @@ fun createIsolatedSourceSet(name: String, path: String = "compat/$name", isEnabl
classpath.from(configurations.getByName(ss.compileClasspathConfigurationName))
}
collectTranslations {
+ // TODO: this does not work, somehow
this.classes.from(sourceSets.main.get().kotlin.classesDirectory)
}
return ss
diff --git a/gradle.properties b/gradle.properties
index ec779d5..2385103 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -10,3 +10,6 @@ archives_base_name=Firmament
maven_group=moe.nea.firmament
firmament.compiletimerepohash=a6116d945491d7c57c93d43f51250f93d62d8434
+
+# TODO: remove after https://github.com/google/ksp/issues/2072
+ksp.incremental=false
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 43f9251..9b8a7d6 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -48,7 +48,7 @@ notenoughanimations = "BQ8qstAV"
# Update from https://modrinth.com/mod/cit-resewn/versions?l=fabric
citresewn = "1.2.0+1.21"
-devauth = "1.2.0"
+devauth = "1.2.1"
# Update from https://ktor.io/
ktor = "3.0.2"
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt
index d8238be..2b9e4bf 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt
@@ -1,19 +1,22 @@
package moe.nea.firmament.compat.rei
import me.shedaniel.math.Dimension
+import me.shedaniel.math.FloatingDimension
import me.shedaniel.math.Point
import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.Drawable
import net.minecraft.client.gui.Element
-import net.minecraft.client.gui.ParentElement
import net.minecraft.entity.LivingEntity
import moe.nea.firmament.gui.entity.EntityRenderer
import moe.nea.firmament.util.ErrorUtil
-class EntityWidget(val entity: LivingEntity?, val point: Point) : WidgetWithBounds() {
+class EntityWidget(
+ val entity: LivingEntity?,
+ val point: Point,
+ val size: FloatingDimension = FloatingDimension(defaultSize)
+) : WidgetWithBounds() {
override fun children(): List<Element> {
return emptyList()
}
@@ -22,18 +25,35 @@ class EntityWidget(val entity: LivingEntity?, val point: Point) : WidgetWithBoun
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
try {
- if (!hasErrored)
- EntityRenderer.renderEntity(entity!!, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat())
+ context.matrices.push()
+ if (!hasErrored) {
+ context.matrices.translate(point.x.toDouble(), point.y.toDouble(), 0.0)
+ val xScale = size.width / defaultSize.width.toDouble()
+ val yScale = size.height / defaultSize.height.toDouble()
+ context.matrices.scale(xScale.toFloat(), yScale.toFloat(), 1.0F)
+ EntityRenderer.renderEntity(
+ entity!!,
+ context,
+ 0, 0,
+ (mouseX - point.x) * xScale,
+ (mouseY - point.y) * yScale)
+ }
} catch (ex: Exception) {
ErrorUtil.softError("Failed to render constructed entity: $entity", ex)
hasErrored = true
+ } finally {
+ context.matrices.pop()
}
if (hasErrored) {
- context.fill(point.x, point.y, point.x + 50, point.y + 80, 0xFFAA2222.toInt())
+ context.fill(point.x, point.y, point.x + size.width.toInt(), point.y + size.height.toInt(), 0xFFAA2222.toInt())
}
}
+ companion object {
+ val defaultSize = Dimension(50, 80)
+ }
+
override fun getBounds(): Rectangle {
- return Rectangle(point, Dimension(50, 80))
+ return Rectangle(point, size)
}
}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt
index f576eda..92f2cfc 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt
@@ -24,6 +24,7 @@ import moe.nea.firmament.compat.rei.recipes.SBEssenceUpgradeRecipe
import moe.nea.firmament.compat.rei.recipes.SBForgeRecipe
import moe.nea.firmament.compat.rei.recipes.SBKatRecipe
import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe
+import moe.nea.firmament.compat.rei.recipes.SBReforgeRecipe
import moe.nea.firmament.events.HandledScreenPushREIEvent
import moe.nea.firmament.features.inventory.CraftingOverlay
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
@@ -78,6 +79,7 @@ class FirmamentReiPlugin : REIClientPlugin {
registry.add(SBForgeRecipe.Category)
registry.add(SBMobDropRecipe.Category)
registry.add(SBKatRecipe.Category)
+ registry.add(SBReforgeRecipe.Category)
registry.add(SBEssenceUpgradeRecipe.Category)
}
@@ -91,6 +93,10 @@ class FirmamentReiPlugin : REIClientPlugin {
SBCraftingRecipe.Category.catIdentifier,
SkyblockCraftingRecipeDynamicGenerator)
registry.registerDisplayGenerator(
+ SBReforgeRecipe.catIdentifier,
+ SBReforgeRecipe.DynamicGenerator
+ )
+ registry.registerDisplayGenerator(
SBForgeRecipe.Category.categoryIdentifier,
SkyblockForgeRecipeDynamicGenerator)
registry.registerDisplayGenerator(
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt
new file mode 100644
index 0000000..9c8d8f4
--- /dev/null
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt
@@ -0,0 +1,210 @@
+package moe.nea.firmament.compat.rei.recipes
+
+import java.util.Optional
+import me.shedaniel.math.Dimension
+import me.shedaniel.math.FloatingDimension
+import me.shedaniel.math.Point
+import me.shedaniel.math.Rectangle
+import me.shedaniel.rei.api.client.gui.Renderer
+import me.shedaniel.rei.api.client.gui.widgets.Label
+import me.shedaniel.rei.api.client.gui.widgets.Widget
+import me.shedaniel.rei.api.client.gui.widgets.Widgets
+import me.shedaniel.rei.api.client.registry.display.DisplayCategory
+import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator
+import me.shedaniel.rei.api.client.view.ViewSearchBuilder
+import me.shedaniel.rei.api.common.category.CategoryIdentifier
+import me.shedaniel.rei.api.common.display.Display
+import me.shedaniel.rei.api.common.display.DisplaySerializer
+import me.shedaniel.rei.api.common.entry.EntryIngredient
+import me.shedaniel.rei.api.common.entry.EntryStack
+import net.minecraft.entity.EntityType
+import net.minecraft.entity.SpawnReason
+import net.minecraft.text.Text
+import net.minecraft.util.Identifier
+import net.minecraft.village.VillagerProfession
+import moe.nea.firmament.Firmament
+import moe.nea.firmament.compat.rei.EntityWidget
+import moe.nea.firmament.compat.rei.SBItemEntryDefinition
+import moe.nea.firmament.gui.entity.EntityRenderer
+import moe.nea.firmament.repo.Reforge
+import moe.nea.firmament.repo.ReforgeStore
+import moe.nea.firmament.repo.RepoItemTypeCache
+import moe.nea.firmament.repo.RepoManager
+import moe.nea.firmament.repo.SBItemStack
+import moe.nea.firmament.util.AprilFoolsUtil
+import moe.nea.firmament.util.FirmFormatters
+import moe.nea.firmament.util.SkyblockId
+import moe.nea.firmament.util.gold
+import moe.nea.firmament.util.grey
+import moe.nea.firmament.util.skyblock.ItemType
+import moe.nea.firmament.util.skyblock.Rarity
+import moe.nea.firmament.util.skyblock.SkyBlockItems
+import moe.nea.firmament.util.skyblockId
+import moe.nea.firmament.util.tr
+
+class SBReforgeRecipe(
+ val reforge: Reforge,
+ val limitToItem: SkyblockId?,
+) : Display {
+ companion object {
+ val catIdentifier = CategoryIdentifier.of<SBReforgeRecipe>(Firmament.MOD_ID, "reforge_recipe")
+ }
+
+ object Category : DisplayCategory<SBReforgeRecipe> {
+ override fun getCategoryIdentifier(): CategoryIdentifier<out SBReforgeRecipe> {
+ return catIdentifier
+ }
+
+ override fun getTitle(): Text {
+ return tr("firmament.recipecategory.reforge", "Reforge")
+ }
+
+ override fun getIcon(): Renderer {
+ return SBItemEntryDefinition.getEntry(SkyBlockItems.REFORGE_ANVIL)
+ }
+
+ override fun setupDisplay(display: SBReforgeRecipe, bounds: Rectangle): MutableList<Widget> {
+ val list = mutableListOf<Widget>()
+ list.add(Widgets.createRecipeBase(bounds))
+ val inputSlot = Widgets.createSlot(Point(bounds.minX + 10, bounds.centerY - 9))
+ .markInput().entries(display.inputItems)
+ list.add(inputSlot)
+ if (display.reforgeStone != null) {
+ list.add(Widgets.createSlot(Point(bounds.minX + 10 + 24, bounds.centerY - 9 - 10))
+ .markInput().entry(display.reforgeStone))
+ list.add(Widgets.withTooltip(
+ Widgets.withTranslate(Widgets.wrapRenderer(
+ Rectangle(Point(bounds.minX + 10 + 24, bounds.centerY - 9 + 10), Dimension(16, 16)),
+ SBItemEntryDefinition.getEntry(SkyBlockItems.REFORGE_ANVIL)), 0.0, 0.0, 150.0),
+ Rarity.entries.mapNotNull { rarity ->
+ display.reforge.reforgeCosts?.get(rarity)?.let { rarity to it }
+ }.map { (rarity, cost) ->
+ Text.literal("")
+ .append(rarity.text)
+ .append(": ")
+ .append(Text.literal("${FirmFormatters.formatCommas(cost, 0)} Coins").gold())
+ }
+ ))
+ } else {
+ val size = if (AprilFoolsUtil.isAprilFoolsDay) 1.2 else 0.6
+ val dimension =
+ FloatingDimension(EntityWidget.defaultSize.width * size, EntityWidget.defaultSize.height * size)
+ list.add(Widgets.withTooltip(
+ EntityWidget(
+ EntityType.VILLAGER.create(EntityRenderer.fakeWorld, SpawnReason.COMMAND)
+ ?.also { it.villagerData = it.villagerData.withProfession(VillagerProfession.WEAPONSMITH) },
+ Point(bounds.minX + 10 + 24 + 8 - dimension.width / 2, bounds.centerY - dimension.height / 2),
+ dimension
+ ),
+ tr("firmament.recipecategory.reforge.basic",
+ "This is a basic reforge, available at the Blacksmith.").grey()
+ ))
+ }
+ list.add(Widgets.createSlot(Point(bounds.minX + 10 + 24 + 24, bounds.centerY - 9))
+ .markInput().entries(display.outputItems))
+ val statToLineMappings = mutableListOf<Pair<String, Label>>()
+ for ((i, statId) in display.reforge.statUniverse.withIndex()) {
+ val label = Widgets.createLabel(
+ Point(bounds.minX + 10 + 24 + 24 + 20, bounds.minY + 8 + i * 11),
+ SBItemStack.Companion.StatLine(SBItemStack.statIdToName(statId), null).reconstitute(7))
+ .horizontalAlignment(Label.LEFT_ALIGNED)
+ statToLineMappings.add(statId to label)
+ list.add(label)
+ }
+ fun updateStatLines() {
+ val entry = inputSlot.currentEntry?.castValue<SBItemStack>() ?: return
+ val stats = display.reforge.reforgeStats?.get(entry.rarity) ?: mapOf()
+ for ((stat, label) in statToLineMappings) {
+ label.message =
+ SBItemStack.Companion.StatLine(
+ SBItemStack.statIdToName(stat), null,
+ valueNum = stats[stat]
+ ).reconstitute(7)
+ }
+ }
+ updateStatLines()
+ inputSlot.withEntriesListener { updateStatLines() }
+ return list
+ }
+ }
+
+ object DynamicGenerator : DynamicDisplayGenerator<SBReforgeRecipe> {
+ fun getRecipesForSBItemStack(item: SBItemStack): Optional<List<SBReforgeRecipe>> {
+ val reforgeRecipes = mutableListOf<SBReforgeRecipe>()
+ for (reforge in ReforgeStore.findEligibleForInternalName(item.skyblockId)) {
+ reforgeRecipes.add(SBReforgeRecipe(reforge, item.skyblockId))
+ }
+ for (reforge in ReforgeStore.findEligibleForItem(item.itemType ?: ItemType.NIL)) {
+ reforgeRecipes.add(SBReforgeRecipe(reforge, item.skyblockId))
+ }
+ if (reforgeRecipes.isEmpty()) return Optional.empty()
+ return Optional.of(reforgeRecipes)
+ }
+
+ override fun getRecipeFor(entry: EntryStack<*>): Optional<List<SBReforgeRecipe>> {
+ if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
+ val item = entry.castValue<SBItemStack>()
+ return getRecipesForSBItemStack(item)
+ }
+
+ override fun getUsageFor(entry: EntryStack<*>): Optional<List<SBReforgeRecipe>> {
+ if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
+ val item = entry.castValue<SBItemStack>()
+ ReforgeStore.byReforgeStone[item.skyblockId]?.let { stoneReforge ->
+ return Optional.of(listOf(SBReforgeRecipe(stoneReforge, null)))
+ }
+ return getRecipesForSBItemStack(item)
+ }
+
+ override fun generate(builder: ViewSearchBuilder): Optional<List<SBReforgeRecipe>> {
+ // TODO: check builder.recipesFor and such and optionally return all reforge recipes
+ return Optional.empty()
+ }
+ }
+
+ private val eligibleItems =
+ if (limitToItem != null) listOfNotNull(RepoManager.getNEUItem(limitToItem))
+ else reforge.eligibleItems.flatMap {
+ when (it) {
+ is Reforge.ReforgeEligibilityFilter.AllowsInternalName ->
+ listOfNotNull(RepoManager.getNEUItem(it.internalName))
+
+ is Reforge.ReforgeEligibilityFilter.AllowsItemType ->
+ ReforgeStore.resolveItemType(it.itemType)
+ .flatMap {
+ RepoItemTypeCache.byItemType[it] ?: listOf()
+ }
+
+ is Reforge.ReforgeEligibilityFilter.AllowsVanillaItemType -> {
+ listOf() // TODO: add filter support for this and potentially rework this to search for the declared item type in repo, instead of remapped item type
+ }
+ }
+ }
+ private val inputItems = eligibleItems.map { SBItemEntryDefinition.getEntry(it.skyblockId) }
+ private val outputItems =
+ inputItems.map { SBItemEntryDefinition.getEntry(it.value.copy(reforge = reforge.reforgeId)) }
+ private val reforgeStone = reforge.reforgeStone?.let(SBItemEntryDefinition::getEntry)
+ private val inputEntries =
+ listOf(EntryIngredient.of(inputItems)) + listOfNotNull(reforgeStone?.let(EntryIngredient::of))
+ private val outputEntries = listOf(EntryIngredient.of(outputItems))
+
+ override fun getInputEntries(): List<EntryIngredient> {
+ return inputEntries
+ }
+
+ override fun getOutputEntries(): List<EntryIngredient> {
+ return outputEntries
+ }
+
+ override fun getCategoryIdentifier(): CategoryIdentifier<*> {
+ return catIdentifier
+ }
+
+ override fun getDisplayLocation(): Optional<Identifier> {
+ return Optional.empty()
+ }
+
+ override fun getSerializer(): DisplaySerializer<out Display>? {
+ return null
+ }
+}
diff --git a/src/compat/yacl/java/YaclIntegration.kt b/src/compat/yacl/java/YaclIntegration.kt
index 9aec501..45a0d02 100644
--- a/src/compat/yacl/java/YaclIntegration.kt
+++ b/src/compat/yacl/java/YaclIntegration.kt
@@ -11,9 +11,11 @@ import dev.isxander.yacl3.api.OptionGroup
import dev.isxander.yacl3.api.YetAnotherConfigLib
import dev.isxander.yacl3.api.controller.ControllerBuilder
import dev.isxander.yacl3.api.controller.DoubleSliderControllerBuilder
+import dev.isxander.yacl3.api.controller.EnumControllerBuilder
import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder
import dev.isxander.yacl3.api.controller.StringControllerBuilder
import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder
+import dev.isxander.yacl3.api.controller.ValueFormatter
import dev.isxander.yacl3.gui.YACLScreen
import dev.isxander.yacl3.gui.tab.ListHolderWidget
import kotlin.time.Duration
@@ -23,8 +25,10 @@ import net.minecraft.client.gui.Element
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
import moe.nea.firmament.gui.config.BooleanHandler
+import moe.nea.firmament.gui.config.ChoiceHandler
import moe.nea.firmament.gui.config.ClickHandler
import moe.nea.firmament.gui.config.DurationHandler
+import moe.nea.firmament.gui.config.EnumRenderer
import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider
import moe.nea.firmament.gui.config.HudMeta
import moe.nea.firmament.gui.config.HudMetaHandler
@@ -89,6 +93,10 @@ class YaclIntegration : FirmamentConfigScreenProvider {
}
.build()
+ is ChoiceHandler<*> -> return createDefaultBinding {
+ createChoiceBinding(handler as ChoiceHandler<*>, managedOption as ManagedOption<*>, it as Option<*>)
+ }.build()
+
is BooleanHandler -> return createDefaultBinding(TickBoxControllerBuilder::create).build()
is StringHandler -> return createDefaultBinding(StringControllerBuilder::create).build()
is IntegerHandler -> return createDefaultBinding {
@@ -114,6 +122,27 @@ class YaclIntegration : FirmamentConfigScreenProvider {
}
}
+ private enum class Sacrifice {}
+
+ private fun createChoiceBinding(
+ handler: ChoiceHandler<*>,
+ managedOption: ManagedOption<*>,
+ option: Option<*>
+ ): ControllerBuilder<Any> {
+ val b = EnumControllerBuilder.create(option as Option<Sacrifice>)
+ b.enumClass(handler.enumClass as Class<Sacrifice>)
+ /**
+ * This is a function with E to avoid realizing the Sacrifice outside of a `X<E>` wrapper.
+ */
+ fun <E : Enum<*>> makeValueFormatter(): ValueFormatter<E> {
+ return ValueFormatter<E> {
+ (handler.renderer as EnumRenderer<E>).getName(managedOption as ManagedOption<E>, it)
+ }
+ }
+ b.formatValue(makeValueFormatter())
+ return b as ControllerBuilder<Any>
+ }
+
fun buildConfig(): YetAnotherConfigLib {
return YetAnotherConfigLib.createBuilder()
diff --git a/src/main/java/moe/nea/firmament/mixins/AlwaysDisplayFirmamentClientCommandErrors.java b/src/main/java/moe/nea/firmament/mixins/AlwaysDisplayFirmamentClientCommandErrors.java
new file mode 100644
index 0000000..59769c6
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/AlwaysDisplayFirmamentClientCommandErrors.java
@@ -0,0 +1,18 @@
+package moe.nea.firmament.mixins;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import com.llamalad7.mixinextras.sugar.Local;
+import net.fabricmc.fabric.impl.command.client.ClientCommandInternals;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(ClientCommandInternals.class)
+public class AlwaysDisplayFirmamentClientCommandErrors {
+ @ModifyExpressionValue(method = "executeCommand", at = @At(value = "INVOKE", target = "Lnet/fabricmc/fabric/impl/command/client/ClientCommandInternals;isIgnoredException(Lcom/mojang/brigadier/exceptions/CommandExceptionType;)Z"))
+ private static boolean markFirmamentExceptionsAsNotIgnores(boolean original, @Local(argsOnly = true) String command) {
+ if (command.startsWith("firm ") || command.equals("firm") || command.startsWith("firmament ") || command.equals("firmament")) {
+ return false;
+ }
+ return original;
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java b/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java
index b386604..699d5b7 100644
--- a/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java
@@ -51,7 +51,7 @@ public class FirmKeybindsInVanillaControlsPatch {
var config = FirmamentKeyBindings.INSTANCE.getKeyBindings().get(binding);
if (config == null) return;
resetButton.active = false;
- editButton.setMessage(Text.translatable("firmament.keybinding.external", config.value.format()));
+ editButton.setMessage(Text.translatable("firmament.keybinding.external", config.getValue().format()));
ci.cancel();
}
diff --git a/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java b/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java
new file mode 100644
index 0000000..c5af8b6
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java
@@ -0,0 +1,29 @@
+package moe.nea.firmament.mixins;
+
+import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
+import moe.nea.firmament.features.fixes.Fixes;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.ingame.InventoryScreen;
+import net.minecraft.client.gui.screen.ingame.StatusEffectsDisplay;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+@Mixin(InventoryScreen.class)
+public abstract class HideStatusEffectsPatch {
+ @Shadow
+ public abstract boolean shouldHideStatusEffectHud();
+
+ @Inject(method = "shouldHideStatusEffectHud", at = @At("HEAD"), cancellable = true)
+ private void hideStatusEffects(CallbackInfoReturnable<Boolean> cir) {
+ cir.setReturnValue(!Fixes.TConfig.INSTANCE.getHidePotionEffects());
+ }
+
+ @WrapWithCondition(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/StatusEffectsDisplay;drawStatusEffects(Lnet/minecraft/client/gui/DrawContext;IIF)V"))
+ private boolean conditionalRenderStatuses(StatusEffectsDisplay instance, DrawContext context, int mouseX, int mouseY, float tickDelta) {
+ return shouldHideStatusEffectHud() || !Fixes.TConfig.INSTANCE.getHidePotionEffects();
+ }
+