aboutsummaryrefslogtreecommitdiff
path: root/src/compat
diff options
context:
space:
mode:
Diffstat (limited to 'src/compat')
-rw-r--r--src/compat/citresewn/java/ConditionDirectAccessHelper.kt59
-rw-r--r--src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java123
-rw-r--r--src/compat/configured/java/BaseConfigNode.kt40
-rw-r--r--src/compat/configured/java/ConfigCategory.kt48
-rw-r--r--src/compat/configured/java/ConfigNode.kt39
-rw-r--r--src/compat/configured/java/ConfigValue.kt72
-rw-r--r--src/compat/configured/java/ConfigValueNode.kt37
-rw-r--r--src/compat/configured/java/ConfiguredCompat.kt30
-rw-r--r--src/compat/configured/java/ConfiguredConfigScreenProvider.kt22
-rw-r--r--src/compat/explosiveEnhancement/java/ExplosiveEnhancementSpawner.kt17
-rw-r--r--src/compat/iris/java/moe/nea/firmament/compat/iris/Compat.kt12
-rw-r--r--src/compat/iris/java/moe/nea/firmament/compat/iris/IrisPipelineAssigner.kt19
-rw-r--r--src/compat/jade/java/moe/nea/firmament/compat/jade/Compat.kt12
-rw-r--r--src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt39
-rw-r--r--src/compat/jade/java/moe/nea/firmament/compat/jade/CustomMiningHardnessProvider.kt97
-rw-r--r--src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt72
-rw-r--r--src/compat/jade/java/moe/nea/firmament/compat/jade/FirmamentJadePlugin.kt21
-rw-r--r--src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt52
-rw-r--r--src/compat/jade/java/moe/nea/firmament/compat/jade/utils.kt6
-rw-r--r--src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/EnforceToolDisplayForCustomBlocksInHarvestToolProvider.java33
-rw-r--r--src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/OnUpdateBreakProgress.java22
-rw-r--r--src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/PatchBreakingBarSpeedJade.java25
-rw-r--r--src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt2
-rw-r--r--src/compat/moulconfig/java/MCConfigEditorIntegration.kt241
-rw-r--r--src/compat/moulconfig/java/ProcessedCategoryFirm.kt12
-rw-r--r--src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt14
-rw-r--r--src/compat/moulconfig/java/ProcessedOptionFirm.kt3
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/Compat.kt12
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt10
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt2
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt105
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt19
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt80
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt6
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt82
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt44
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt77
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt14
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/GenericREIRecipeCategory.kt67
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBCraftingRecipe.kt56
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBEssenceUpgradeRecipe.kt61
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBForgeRecipe.kt71
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt226
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt32
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt4
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt124
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBShopRecipe.kt61
-rw-r--r--src/compat/sodium/java/moe/nea/firmament/compat/sodium/Compat.kt12
-rw-r--r--src/compat/sodium/java/moe/nea/firmament/compat/sodium/SodiumChunkReloader.kt (renamed from src/compat/sodium/java/SodiumChunkReloader.kt)2
-rw-r--r--src/compat/sodium/java/moe/nea/firmament/mixins/custommodels/PatchBlockModelInSodiumChunkGenerator.java29
-rw-r--r--src/compat/sodium/java/moe/nea/firmament/mixins/sodium/accessor/AccessorSodiumWorldRenderer.java (renamed from src/compat/sodium/java/moe/nea/firmament/mixins/accessor/sodium/AccessorSodiumWorldRenderer.java)2
-rw-r--r--src/compat/sodium/java/moe/nea/firmament/mixins/sodium/custommodels/PatchBlockModelInSodiumChunkGenerator.java29
-rw-r--r--src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt13
-rw-r--r--src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java12
-rw-r--r--src/compat/yacl/java/KeybindingController.kt25
-rw-r--r--src/compat/yacl/java/YaclIntegration.kt100
56 files changed, 1361 insertions, 1185 deletions
diff --git a/src/compat/citresewn/java/ConditionDirectAccessHelper.kt b/src/compat/citresewn/java/ConditionDirectAccessHelper.kt
deleted file mode 100644
index af97a40..0000000
--- a/src/compat/citresewn/java/ConditionDirectAccessHelper.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package moe.nea.firmament.compat.citresewn
-
-import java.lang.invoke.MethodHandles
-import java.util.function.BiPredicate
-import java.util.function.Function
-import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionNBT
-
-object ConditionNBTMixin {
- class Helper<StringMatcher> {
- // TODO: make lambdametafactory work by way of modifying the actual modifiers
-
- val stringMatcherType = ConditionNBT::class.java.getDeclaredField("matchString").type
-
- val accessMatcher = run {
- val matchStringF = ConditionNBT::class.java.getDeclaredField("matchString");
- matchStringF.isAccessible = true
- val l = MethodHandles.privateLookupIn(ConditionNBT::class.java, MethodHandles.lookup())
-// val mt = MethodType.methodType(stringMatcherType, ConditionNBT::class.java)
-// val callsite = LambdaMetafactory.metafactory(
-// l, "apply",
-// MethodType.methodType(Function::class.java),
-// MethodType.methodType(java.lang.Object::class.java, java.lang.Object::class.java),
-// l.unreflectGetter(matchStringF),
-// mt
-// )
- val getter = l.unreflectGetter(matchStringF)
- Function<ConditionNBT, StringMatcher> { getter.invoke(it) as StringMatcher }
- }
- val directCaller = run {
- val matchM = stringMatcherType.getDeclaredMethod("matches", String::class.java);
- matchM.isAccessible = true
- val l = MethodHandles.privateLookupIn(ConditionNBT::class.java, MethodHandles.lookup())
-// val mt = MethodType.methodType(java.lang.Boolean.TYPE, stringMatcherType, String::class.java)
-// val callsite = LambdaMetafactory.metafactory(
-// l, "test",
-// MethodType.methodType(BiPredicate::class.java),
-// mt,
-// l.unreflect(matchM),
-// mt
-// )
- val func = l.unreflect(matchM)
- BiPredicate<StringMatcher, String> { a, b -> func.invoke(a, b) as Boolean }
- }
-
- fun test(condition: ConditionNBT, text: String): Boolean {
- return directCaller.test(accessMatcher.apply(condition), text) as Boolean
- }
- }
-
- val helper = Helper<Any>()
-
- @JvmStatic
- fun invokeDirectConditionNBTStringMatch(
- nbt: ConditionNBT,
- text: String,
- ): Boolean {
- return helper.test(nbt, text)
- }
-}
diff --git a/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java b/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java
deleted file mode 100644
index 0743d40..0000000
--- a/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package moe.nea.firmament.mixins.compat.citresewn;
-
-import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
-import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
-import com.llamalad7.mixinextras.sugar.Local;
-import com.llamalad7.mixinextras.sugar.ref.LocalRef;
-import com.mojang.serialization.Codec;
-import com.mojang.serialization.DataResult;
-import com.mojang.serialization.DynamicOps;
-import moe.nea.firmament.compat.citresewn.ConditionNBTMixin;
-import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures;
-import net.minecraft.component.ComponentType;
-import net.minecraft.component.DataComponentTypes;
-import net.minecraft.component.type.NbtComponent;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Pseudo;
-import org.spongepowered.asm.mixin.Shadow;
-import org.spongepowered.asm.mixin.Unique;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-import shcm.shsupercm.fabric.citresewn.CITResewn;
-import shcm.shsupercm.fabric.citresewn.cit.CITContext;
-import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionComponents;
-import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionNBT;
-import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup;
-import shcm.shsupercm.fabric.citresewn.pack.format.PropertyKey;
-import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue;
-
-// People are complaining but this really is not my place to fix things
-
-@Mixin(ConditionComponents.class)
-@Pseudo
-public class MixinConditionComponents {
- @Shadow
- private ComponentType<?> componentType;
-
- @Shadow(remap = false)
- private ConditionNBT fallbackNBTCheck;
- @Unique
- private String[] pathCheck;
- @Unique
- private int loreInt = -1;
-
- @Inject(method = "load", at = @At("HEAD"), remap = false)
- public void addExtraAttributeSupport(PropertyKey key, PropertyValue value, PropertyGroup properties, CallbackInfo ci,
- @Local(argsOnly = true) LocalRef<PropertyKey> keyRef,
- @Local(argsOnly = true) LocalRef<PropertyValue> valueRef) {
- if (!CustomSkyBlockTextures.TConfig.INSTANCE.getEnableLegacyCIT()) return;
- if (!"nbt".equals(key.path())) return;
- if (!value.keyMetadata().startsWith("ExtraAttributes.")) return;
- keyRef.set(new PropertyKey(key.namespace(), "component"));
- valueRef.set(new PropertyValue(
- "minecraft:custom_data" + value.keyMetadata().substring("ExtraAttributes".length()),
- value.value(),
- value.separator(),
- value.position(),
- value.propertiesIdentifier(),
- value.packName()
- ));
- CITResewn.logWarnLoading(properties.messageWithDescriptorOf("NBT condition is not supported since 1.21. THIS IS A FIRMAMENT SPECIAL FEATURE ALLOWING YOU TO CONTINUE TO USE nbt.ExtraAttributes.* PROPERTIES FOR A LIMITED TIME! UPDATE YOUR .PROPERTIES FILES OR SWITCH TO FIRMAMENT CIT (https://github.com/FirmamentMC/CitToFirm)",
- value.position()));
- }
-
- @Inject(method = "load",
- at = @At(value = "INVOKE", remap = false, target = "Lshcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionNBT;loadNbtCondition(Lshcm/shsupercm/fabric/citresewn/pack/format/PropertyValue;Lshcm/shsupercm/fabric/citresewn/pack/format/PropertyGroup;[Ljava/lang/String;Ljava/lang/String;)V"),
- remap = false)
- private void onLoadSavePath(PropertyKey key, PropertyValue value, PropertyGroup properties, CallbackInfo ci,
- @Local String[] path) {
- this.pathCheck = path;
- this.loreInt = -1;
- }
-
- @Unique
- private boolean matchStringDirect(String directString, CITContext context) {
- return ConditionNBTMixin.invokeDirectConditionNBTStringMatch(fallbackNBTCheck, directString);
- }
-
- @WrapOperation(method = "test", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/Codec;encodeStart(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;"), remap = false)
- DataResult fastPathUnsafeNbtComponent(
- Codec instance,
- DynamicOps dynamicOps,
- Object o,
- Operation<DataResult> original) {
- if (o instanceof NbtComponent nbtComponent) {
- return DataResult.success(nbtComponent.getNbt());
- }
- return original.call(instance, dynamicOps, o);
- }
-
- @Inject(method = "test", at = @At("HEAD"), cancellable = true, remap = false)
- void fastPathDisplayName(CITContext context, CallbackInfoReturnable<Boolean> cir) {
- if (this.componentType == DataComponentTypes.CUSTOM_NAME && pathCheck.length == 0) {
- var displayName = context.stack.getComponents().get(DataComponentTypes.CUSTOM_NAME);
- if (displayName != null) {
- cir.setReturnValue(matchStringDirect((displayName.getString()), context));
- }
- }
- if (this.componentType == DataComponentTypes.LORE && pathCheck.length == 1) {
- var lore = context.stack.getComponents().get(DataComponentTypes.LORE);
- if (lore != null) {
- var loreLines = lore.lines();
- if (pathCheck[0].equals("*")) {
- for (var loreLine : loreLines) {
- if (matchStringDirect((loreLine.getString()), context)) {
- cir.setReturnValue(true);
- return;
- }
- }
- cir.setReturnValue(false);
- } else {
- if (loreInt < 0)
- loreInt = Integer.parseInt(pathCheck[0]);
- cir.setReturnValue(0 <= loreInt && loreInt < loreLines.size() &&
- matchStringDirect((loreLines.get(loreInt).getString()), context));
- }
- }
- }
- }
-
-
-}
diff --git a/src/compat/configured/java/BaseConfigNode.kt b/src/compat/configured/java/BaseConfigNode.kt
deleted file mode 100644
index afe0375..0000000
--- a/src/compat/configured/java/BaseConfigNode.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package moe.nea.firmament.compat.configured
-
-import com.mrcrayfish.configured.api.IConfigEntry
-import com.mrcrayfish.configured.api.IConfigValue
-import net.minecraft.text.Text
-import moe.nea.firmament.gui.config.AllConfigsGui
-import moe.nea.firmament.gui.config.ManagedConfig
-
-object BaseConfigNode : IConfigEntry {
- override fun getChildren(): List<IConfigEntry> {
- return ManagedConfig.allManagedConfigs.getAll().map {
- ConfigNode(it) // TODO: fix add categories here
- }
- }
-
- override fun isRoot(): Boolean {
- return true
- }
-
- override fun isLeaf(): Boolean {
- return false
- }
-
- override fun getValue(): IConfigValue<*>? {
- return null
- }
-
- override fun getEntryName(): String {
- return "Firmament"
- }
-
- override fun getTooltip(): Text? {
- return null
- }
-
- override fun getTranslationKey(): String? {
- return null
- }
-
-}
diff --git a/src/compat/configured/java/ConfigCategory.kt b/src/compat/configured/java/ConfigCategory.kt
deleted file mode 100644
index 4e33b8b..0000000
--- a/src/compat/configured/java/ConfigCategory.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package moe.nea.firmament.compat.configured
-
-import com.mrcrayfish.configured.api.ConfigType
-import com.mrcrayfish.configured.api.IConfigEntry
-import com.mrcrayfish.configured.api.IModConfig
-import com.mrcrayfish.configured.util.ConfigHelper
-import java.nio.file.Path
-import java.util.function.Consumer
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.gui.config.ManagedConfig
-
-class ConfigCategory(
- val category: ManagedConfig
-) : BaseConfig() {
-
- override fun getRoot(): IConfigEntry {
- return ConfigNode(category)
- }
-
- override fun getTranslationKey(): String? {
- return category.translationKey
- }
-}
-
-abstract class BaseConfig : IModConfig {
- override fun update(p0: IConfigEntry) {
- ConfigHelper.getChangedValues(p0).forEach {
- it as ConfigValue
- it.saveValue()
- }
- }
-
- override fun getType(): ConfigType {
- return ConfigType.CLIENT
- }
-
- override fun getFileName(): String {
- return ""
- }
-
- override fun getModId(): String {
- return Firmament.MOD_ID
- }
-
- override fun loadWorldConfig(p0: Path?, p1: Consumer<IModConfig>?) {
- }
-
-}
diff --git a/src/compat/configured/java/ConfigNode.kt b/src/compat/configured/java/ConfigNode.kt
deleted file mode 100644
index 16e54a6..0000000
--- a/src/compat/configured/java/ConfigNode.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package moe.nea.firmament.compat.configured
-
-import com.mrcrayfish.configured.api.IConfigEntry
-import com.mrcrayfish.configured.api.IConfigValue
-import net.minecraft.text.Text
-import moe.nea.firmament.gui.config.ManagedConfig
-
-class ConfigNode(val config: ManagedConfig) : IConfigEntry {
- override fun getChildren(): List<IConfigEntry> {
- return config.allOptions.map {
- ConfigValueNode(it.value)
- }
- }
-
- override fun isRoot(): Boolean {
- return false
- }
-
- override fun isLeaf(): Boolean {
- return false
- }
-
- override fun getValue(): IConfigValue<*>? {
- return null
- }
-
- override fun getEntryName(): String {
- return config.translationKey
- }
-
- override fun getTooltip(): Text? {
- return null
- }
-
- override fun getTranslationKey(): String {
- return config.translationKey
- }
-
-}
diff --git a/src/compat/configured/java/ConfigValue.kt b/src/compat/configured/java/ConfigValue.kt
deleted file mode 100644
index e16c51c..0000000
--- a/src/compat/configured/java/ConfigValue.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package moe.nea.firmament.compat.configured
-
-import com.mrcrayfish.configured.api.IConfigValue
-import net.minecraft.text.Text
-import moe.nea.firmament.gui.config.ManagedOption
-
-class ConfigValue<T: Any>(val option: ManagedOption<T>) : IConfigValue<T> {
- var value = option.get()
- var initialValue = option.get()
-
- override fun get(): T {
- return value
- }
-
- override fun set(p0: T) {
- this.value = p0
- }
-
- override fun getDefault(): T {
- return option.default()
- }
-
- override fun isDefault(): Boolean {
- // TODO: should this be an option in handlers?
- return option == option.default()
- }
-
- override fun isChanged(): Boolean {
- return value != initialValue
- }
-
- override fun restore() {
- this.value = option.default()
- }
-
- override fun getComment(): Text? {
- return null
- }
-
- override fun getTranslationKey(): String? {
- return option.rawLabelText
- }
-
- override fun getValidationHint(): Text? {
- return null
- }
-
- override fun getName(): String {
- return ""
- }
-
- override fun cleanCache() {
-
- }
-
- override fun requiresWorldRestart(): Boolean {
- return false
- }
-
- override fun requiresGameRestart(): Boolean {
- return false
- }
-
- override fun isValid(p0: T): Boolean {
- // TODO: should this be validated?
- return true
- }
-
- fun saveValue() {
- option.set(value)
- }
-}
diff --git a/src/compat/configured/java/ConfigValueNode.kt b/src/compat/configured/java/ConfigValueNode.kt
deleted file mode 100644
index df59739..0000000
--- a/src/compat/configured/java/ConfigValueNode.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package moe.nea.firmament.compat.configured
-
-import com.mrcrayfish.configured.api.IConfigEntry
-import com.mrcrayfish.configured.api.IConfigValue
-import net.minecraft.text.Text
-import moe.nea.firmament.gui.config.ManagedOption
-
-class ConfigValueNode(val option: ManagedOption<*>) : IConfigEntry {
- override fun getChildren(): List<IConfigEntry> {
- return listOf()
- }
-
- override fun isRoot(): Boolean {
- return false
- }
-
- override fun isLeaf(): Boolean {
- return true
- }
-
- val value = ConfigValue(option)
- override fun getValue(): IConfigValue<*>? {
- return value
- }
-
- override fun getEntryName(): String {
- return option.propertyName
- }
-
- override fun getTooltip(): Text? {
- return null
- }
-
- override fun getTranslationKey(): String? {
- return option.rawLabelText
- }
-}
diff --git a/src/compat/configured/java/ConfiguredCompat.kt b/src/compat/configured/java/ConfiguredCompat.kt
deleted file mode 100644
index 8e8b022..0000000
--- a/src/compat/configured/java/ConfiguredCompat.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package moe.nea.firmament.compat.configured
-
-import com.mrcrayfish.configured.api.IConfigEntry
-import com.mrcrayfish.configured.api.IModConfig
-import com.mrcrayfish.configured.api.IModConfigProvider
-import com.mrcrayfish.configured.api.ModContext
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.gui.config.AllConfigsGui
-import moe.nea.firmament.gui.config.ManagedConfig
-
-/**
- * Registered in `fabric.mod.json` at `custom.configured.providers`
- */
-class ConfiguredCompat : IModConfigProvider {
- override fun getConfigurationsForMod(modContext: ModContext): Set<IModConfig> {
- if (modContext.modId != Firmament.MOD_ID) return emptySet()
- return buildSet {
- add(object : BaseConfig() {
- override fun getRoot(): IConfigEntry {
- return BaseConfigNode
- }
-
- override fun getTranslationKey(): String? {
- return "firmament.config.all-configs"
- }
- })
- ManagedConfig.allManagedConfigs.getAll().mapTo(this) { ConfigCategory(it) }
- }
- }
-}
diff --git a/src/compat/configured/java/ConfiguredConfigScreenProvider.kt b/src/compat/configured/java/ConfiguredConfigScreenProvider.kt
deleted file mode 100644
index c0095bf..0000000
--- a/src/compat/configured/java/ConfiguredConfigScreenProvider.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package moe.nea.firmament.compat.configured
-
-import com.google.auto.service.AutoService
-import com.mrcrayfish.configured.integration.CatalogueConfigFactory
-import net.fabricmc.loader.api.FabricLoader
-import net.minecraft.client.gui.screen.Screen
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider
-
-@AutoService(FirmamentConfigScreenProvider::class)
-class ConfiguredConfigScreenProvider : FirmamentConfigScreenProvider {
- override val key: String
- get() = "configured"
- override val isEnabled: Boolean
- get() = FabricLoader.getInstance().isModLoaded("configured")
-
- override fun open(parent: Screen?): Screen {
- return CatalogueConfigFactory.createConfigScreen(
- parent,
- FabricLoader.getInstance().getModContainer(Firmament.MOD_ID).get())
- }
-}
diff --git a/src/compat/explosiveEnhancement/java/ExplosiveEnhancementSpawner.kt b/src/compat/explosiveEnhancement/java/ExplosiveEnhancementSpawner.kt
deleted file mode 100644
index caf16a5..0000000
--- a/src/compat/explosiveEnhancement/java/ExplosiveEnhancementSpawner.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package moe.nea.firmament.compat.explosiveenhancement
-
-import com.google.auto.service.AutoService
-import net.superkat.explosiveenhancement.api.ExplosiveApi
-import net.minecraft.util.math.Vec3d
-import moe.nea.firmament.features.fixes.CompatibliltyFeatures
-import moe.nea.firmament.features.fixes.CompatibliltyFeatures.TConfig
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.compatloader.CompatLoader
-
-@AutoService(CompatibliltyFeatures.ExplosiveApiWrapper::class)
-@CompatLoader.RequireMod("explosiveenhancement")
-class ExplosiveEnhancementSpawner : CompatibliltyFeatures.ExplosiveApiWrapper {
- override fun spawnParticle(vec3d: Vec3d, power: Float) {
- ExplosiveApi.spawnParticles(MC.world, vec3d.x, vec3d.y, vec3d.z, TConfig.explosionSize / 10F)
- }
-}
diff --git a/src/compat/iris/java/moe/nea/firmament/compat/iris/Compat.kt b/src/compat/iris/java/moe/nea/firmament/compat/iris/Compat.kt
new file mode 100644
index 0000000..6d04842
--- /dev/null
+++ b/src/compat/iris/java/moe/nea/firmament/compat/iris/Compat.kt
@@ -0,0 +1,12 @@
+package moe.nea.firmament.compat.iris
+
+import net.fabricmc.loader.api.FabricLoader
+import moe.nea.firmament.util.compatloader.CompatMeta
+import moe.nea.firmament.util.compatloader.ICompatMeta
+
+@CompatMeta
+object Compat : ICompatMeta {
+ override fun shouldLoad(): Boolean {
+ return FabricLoader.getInstance().isModLoaded("iris")
+ }
+}
diff --git a/src/compat/iris/java/moe/nea/firmament/compat/iris/IrisPipelineAssigner.kt b/src/compat/iris/java/moe/nea/firmament/compat/iris/IrisPipelineAssigner.kt
new file mode 100644
index 0000000..b7b3e42
--- /dev/null
+++ b/src/compat/iris/java/moe/nea/firmament/compat/iris/IrisPipelineAssigner.kt
@@ -0,0 +1,19 @@
+package moe.nea.firmament.compat.iris
+
+import net.irisshaders.iris.api.v0.IrisApi
+import net.irisshaders.iris.api.v0.IrisProgram
+import util.render.CustomRenderPipelines
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.events.ClientInitEvent
+
+object IrisPipelineAssigner {
+ @Subscribe
+ fun initIrisAssignments(event: ClientInitEvent) {
+ val api = IrisApi.getInstance()
+ api.assignPipeline(CustomRenderPipelines.GUI_TEXTURED_NO_DEPTH_TRIS, IrisProgram.TEXTURED)
+ api.assignPipeline(CustomRenderPipelines.OMNIPRESENT_LINES, IrisProgram.LINES)
+ api.assignPipeline(CustomRenderPipelines.COLORED_OMNIPRESENT_QUADS, IrisProgram.BASIC)
+ api.assignPipeline(CustomRenderPipelines.CIRCLE_FILTER_TRANSLUCENT_GUI_TRIS, IrisProgram.TEXTURED)
+ api.assignPipeline(CustomRenderPipelines.PARALLAX_CAPE_SHADER, IrisProgram.ENTITIES)
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/Compat.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/Compat.kt
new file mode 100644
index 0000000..d1cfef4
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/Compat.kt
@@ -0,0 +1,12 @@
+package moe.nea.firmament.compat.jade
+
+import net.fabricmc.loader.api.FabricLoader
+import moe.nea.firmament.util.compatloader.CompatMeta
+import moe.nea.firmament.util.compatloader.ICompatMeta
+
+@CompatMeta
+object Compat : ICompatMeta {
+ override fun shouldLoad(): Boolean {
+ return FabricLoader.getInstance().isModLoaded("jade")
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt
new file mode 100644
index 0000000..58344ad
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt
@@ -0,0 +1,39 @@
+package moe.nea.firmament.compat.jade
+
+import snownee.jade.api.Accessor
+import snownee.jade.api.BlockAccessor
+import snownee.jade.api.IWailaClientRegistration
+import snownee.jade.api.callback.JadeRayTraceCallback
+import net.minecraft.world.phys.HitResult
+import moe.nea.firmament.repo.MiningRepoData
+import moe.nea.firmament.util.mc.FirmamentDataComponentTypes
+
+class CustomFakeBlockProvider(val registration: IWailaClientRegistration) : JadeRayTraceCallback {
+
+ override fun onRayTrace(
+ hitResult: HitResult,
+ accessor: Accessor<*>?,
+ originalAccessor: Accessor<*>?
+ ): Accessor<*>? {
+ if (!JadeIntegration.TConfig.blockDetection) return accessor
+ if (accessor !is BlockAccessor) return accessor
+ val customBlock = JadeIntegration.customBlocks[accessor.block] ?: return accessor
+ return registration.blockAccessor()
+ .from(accessor)
+ .serversideRep(customBlock.getDisplayItem(accessor.block))
+ .build()
+ }
+
+ companion object {
+ @JvmStatic
+ fun hasCustomBlock(accessor: BlockAccessor): Boolean {
+ return getCustomBlock(accessor) != null
+ }
+
+ @JvmStatic
+ fun getCustomBlock(accessor: BlockAccessor): MiningRepoData.CustomMiningBlock? {
+ val item = accessor.serversideRep ?: return null
+ return item.get(FirmamentDataComponentTypes.CUSTOM_MINING_BLOCK_DATA)
+ }
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomMiningHardnessProvider.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomMiningHardnessProvider.kt
new file mode 100644
index 0000000..01c06e5
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomMiningHardnessProvider.kt
@@ -0,0 +1,97 @@
+package moe.nea.firmament.compat.jade
+
+import snownee.jade.api.BlockAccessor
+import snownee.jade.api.IBlockComponentProvider
+import snownee.jade.api.ITooltip
+import snownee.jade.api.config.IPluginConfig
+import kotlin.time.DurationUnit
+import net.minecraft.world.level.block.state.BlockState
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.core.BlockPos
+import moe.nea.firmament.Firmament
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.events.TickEvent
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.TimeMark
+import moe.nea.firmament.util.tr
+
+object CustomMiningHardnessProvider : IBlockComponentProvider {
+
+ override fun appendTooltip(
+ tooltip: ITooltip,
+ block: BlockAccessor,
+ config: IPluginConfig?
+ ) {
+ val customBlock = CustomFakeBlockProvider.getCustomBlock(block) ?: return
+ if (customBlock.breakingPower > 0)
+ tooltip.add(tr("firmament.jade.breaking_power", "Required Breaking Power: ${customBlock.breakingPower}"))
+ }
+
+ override fun getUid(): ResourceLocation =
+ Firmament.identifier("custom_mining_hardness")
+
+ data class BreakingInfo(
+ val blockPos: BlockPos, val stage: Int,
+ val state: BlockState?,
+ val ts: TimeMark = TimeMark.now()
+ )
+
+ var previousBreakingInfo: BreakingInfo? = null
+ var currentBreakingInfo: BreakingInfo? = null
+
+ @Subscribe
+ fun clearInfoOnStopBreaking(event: TickEvent) {
+ val isBreakingBlock = MC.interactionManager?.isDestroying ?: false
+ if (!isBreakingBlock) {
+ previousBreakingInfo = null
+ currentBreakingInfo = null
+ }
+ }
+
+ @JvmStatic
+ fun setBreakingInfo(blockPos: BlockPos, stage: Int) {
+ previousBreakingInfo = currentBreakingInfo
+ val state = MC.world?.getBlockState(blockPos)
+ if (previousBreakingInfo?.let { it.state != state || it.blockPos != blockPos } ?: false)
+ previousBreakingInfo == null
+ currentBreakingInfo = BreakingInfo(blockPos.immutable(), stage, state)
+ // For some reason hypixel initially sends a stage 10 packet, and then fixes it up with a stage 0 packet.
+ // Ignore the stage 10 packet if we dont have any previous packets for this block.
+ // This could in theory still have issues if someone perfectly stops breaking a block the tick it finishes and then does not break another block until it respawns, but i deem that to be too much of an edge case.
+ if (stage == 10 && previousBreakingInfo == null) {
+ previousBreakingInfo = null
+ currentBreakingInfo = null
+ }
+ }
+
+ @JvmStatic
+ fun replaceBreakProgress(original: Float): Float {
+ if (!JadeIntegration.TConfig.miningProgress) return original
+ if (!isOnMiningIsland()) return original
+ val pos = MC.interactionManager?.destroyBlockPos ?: return original
+ val info = currentBreakingInfo
+ if (info?.blockPos != pos || info.state != MC.world?.getBlockState(pos)) {
+ currentBreakingInfo = null
+ previousBreakingInfo = null
+ return original
+ }
+ // TODO: improve this interpolation to work across all stages, to alleviate some of the jittery bar.
+ // Maybe introduce a proper mining API that tracks the actual progress with some sort of FSM
+ val interpolatedStage = previousBreakingInfo?.let { prev ->
+ val timeBetweenTicks = (info.ts - prev.ts).toDouble(DurationUnit.SECONDS)
+ val stagesPerUpdate = (info.stage - prev.stage).toDouble()
+ if (stagesPerUpdate < 1) return@let null
+ val stagesPerSecond = stagesPerUpdate / timeBetweenTicks
+ info.stage + (info.ts.passedTime().toDouble(DurationUnit.SECONDS) * stagesPerSecond)
+ .coerceAtMost(stagesPerUpdate)
+ }?.toFloat()
+ val stage = interpolatedStage ?: info.stage.toFloat()
+ return stage / 10F
+ }
+
+ @JvmStatic
+ fun replaceBlockBreakSpeed(original: Float): Float {
+ if (isOnMiningIsland()) return 0F
+ return original
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt
new file mode 100644
index 0000000..0083d78
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt
@@ -0,0 +1,72 @@
+package moe.nea.firmament.compat.jade
+
+import java.util.function.UnaryOperator
+import snownee.jade.api.BlockAccessor
+import snownee.jade.api.IBlockComponentProvider
+import snownee.jade.api.ITooltip
+import snownee.jade.api.JadeIds
+import snownee.jade.api.config.IPluginConfig
+import snownee.jade.api.theme.IThemeHelper
+import snownee.jade.api.ui.Element
+import snownee.jade.api.ui.JadeUI
+import snownee.jade.gui.JadeLinearLayout
+import snownee.jade.impl.ui.ItemStackElement
+import snownee.jade.impl.ui.TextElementImpl
+import net.minecraft.network.chat.Component
+import net.minecraft.resources.ResourceLocation
+import moe.nea.firmament.Firmament
+import moe.nea.firmament.repo.ExpensiveItemCacheApi
+import moe.nea.firmament.repo.RepoManager
+import moe.nea.firmament.repo.SBItemStack
+import moe.nea.firmament.util.MC
+
+class DrillToolProvider : IBlockComponentProvider {
+ @OptIn(ExpensiveItemCacheApi::class)
+ override fun appendTooltip(
+ tooltip: ITooltip,
+ accessor: BlockAccessor,
+ p2: IPluginConfig?
+ ) {
+ val customBlock = CustomFakeBlockProvider.getCustomBlock(accessor) ?: return
+ val tool = RepoManager.miningData.getToolsThatCanBreak(customBlock.breakingPower).firstOrNull()
+ ?.asImmutableItemStack() ?: return
+ tooltip.replace(JadeIds.MC_HARVEST_TOOL, UnaryOperator { elements ->
+ elements.map { inner ->
+ val lastItemIndex = inner.indexOfLast { it is ItemStackElement }
+ if (lastItemIndex < 0) return@map inner
+ val innerMut = inner.toMutableList()
+ val harvestIndicator = innerMut.indexOfLast {
+ it is TextElementImpl && it.width == 0 && it.string.isNotEmpty()
+ }
+ val canHarvest = SBItemStack(MC.stackInHand).breakingPower >= customBlock.breakingPower
+ val lastItem = innerMut[lastItemIndex] as ItemStackElement
+ if (harvestIndicator < 0) {
+ innerMut.add(lastItemIndex + 1, canHarvestIndicator(canHarvest))
+ } else {
+ innerMut.set(harvestIndicator, canHarvestIndicator(canHarvest))
+ }
+ innerMut.set(
+ lastItemIndex, JadeUI
+ .item(tool, 0.75f)
+ )
+ innerMut.subList(0, lastItemIndex - 1).removeIf { it is ItemStackElement }
+ innerMut
+ }
+ })
+ }
+
+ fun canHarvestIndicator(canHarvest: Boolean): Element {
+ val t = IThemeHelper.get()
+ val text = if (canHarvest) t.success(CHECK) else t.danger(X)
+ return JadeUI.text(text)
+ .scale(0.75F)
+ .alignSelfCenter()
+ }
+
+ private val CHECK: Component = Component.literal("✔")
+ private val X: Component = Component.literal("✕")
+
+ override fun getUid(): ResourceLocation {
+ return Firmament.identifier("toolprovider")
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/FirmamentJadePlugin.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/FirmamentJadePlugin.kt
new file mode 100644
index 0000000..a31492e
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/FirmamentJadePlugin.kt
@@ -0,0 +1,21 @@
+package moe.nea.firmament.compat.jade
+
+import snownee.jade.api.IWailaClientRegistration
+import snownee.jade.api.IWailaCommonRegistration
+import snownee.jade.api.IWailaPlugin
+import snownee.jade.api.WailaPlugin
+import net.minecraft.world.level.block.Block
+import moe.nea.firmament.Firmament
+
+@WailaPlugin
+class FirmamentJadePlugin : IWailaPlugin {
+ override fun register(registration: IWailaCommonRegistration) {
+ Firmament.logger.debug("Registering Jade integration...")
+ }
+
+ override fun registerClient(registration: IWailaClientRegistration) {
+ registration.registerBlockComponent(CustomMiningHardnessProvider, Block::class.java)
+ registration.registerBlockComponent(DrillToolProvider(), Block::class.java)
+ registration.addRayTraceCallback(CustomFakeBlockProvider(registration))
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt
new file mode 100644
index 0000000..c289810
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt
@@ -0,0 +1,52 @@
+package moe.nea.firmament.compat.jade
+
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.events.SkyblockServerUpdateEvent
+import moe.nea.firmament.repo.MiningRepoData
+import moe.nea.firmament.repo.RepoManager
+import moe.nea.firmament.util.ErrorUtil
+import net.minecraft.world.level.block.Block
+import moe.nea.firmament.events.ReloadRegistrationEvent
+import moe.nea.firmament.util.data.Config
+import moe.nea.firmament.util.data.ManagedConfig
+
+object JadeIntegration {
+ @Config
+ object TConfig : ManagedConfig("jade-integration", Category.INTEGRATIONS) {
+ val miningProgress by toggle("progress") { true }
+ val blockDetection by toggle("blocks") { true }
+ }
+
+ var customBlocks: Map<Block, MiningRepoData.CustomMiningBlock> = mapOf()
+
+ fun refreshBlockInfo() {
+ if (!isOnMiningIsland()) {
+ customBlocks = mapOf()
+ return
+ }
+ val blocks = RepoManager.miningData.customMiningBlocks
+ .flatMap { customBlock ->
+ // TODO: add a lifted helper method for this
+ customBlock.blocks189.filter { it.isCurrentlyActive }
+ .mapNotNull { it.block }
+ .map { customBlock to it }
+ }
+ .groupBy { it.second }
+ customBlocks = blocks.mapNotNull { (block, customBlocks) ->
+ val singleMatch =
+ ErrorUtil.notNullOr(customBlocks.singleOrNull()?.first,
+ "Two custom blocks both want to supply custom mining behaviour for $block.") { return@mapNotNull null }
+ block to singleMatch
+ }.toMap()
+ }
+
+ @Subscribe
+ fun onRepoReload(event: ReloadRegistrationEvent) {
+ event.repo.registerReloadListener { refreshBlockInfo() }
+ }
+
+ @Subscribe
+ fun onWorldSwap(event: SkyblockServerUpdateEvent) {
+ refreshBlockInfo()
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/utils.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/utils.kt
new file mode 100644
index 0000000..364dc02
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/utils.kt
@@ -0,0 +1,6 @@
+package moe.nea.firmament.compat.jade
+
+import moe.nea.firmament.util.SBData
+
+fun isOnMiningIsland(): Boolean =
+ SBData.skyblockLocation?.hasCustomMining ?: false
diff --git a/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/EnforceToolDisplayForCustomBlocksInHarvestToolProvider.java b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/EnforceToolDisplayForCustomBlocksInHarvestToolProvider.java
new file mode 100644
index 0000000..5fabba8
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/EnforceToolDisplayForCustomBlocksInHarvestToolProvider.java
@@ -0,0 +1,33 @@
+package moe.nea.firmament.mixins.compat.jade;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import com.llamalad7.mixinextras.sugar.Local;
+import moe.nea.firmament.compat.jade.CustomFakeBlockProvider;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import snownee.jade.addon.harvest.HarvestToolProvider;
+import snownee.jade.api.BlockAccessor;
+
+import java.util.List;
+
+@Mixin(HarvestToolProvider.class)
+public class EnforceToolDisplayForCustomBlocksInHarvestToolProvider {
+ @ModifyExpressionValue(method = "getText", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;requiresCorrectToolForDrops()Z"))
+ private boolean overwriteRequiresTool(boolean original, @Local(argsOnly = true) BlockAccessor accessor) {
+ if (CustomFakeBlockProvider.hasCustomBlock(accessor))
+ return true;
+ return original;
+ }
+
+ private static final List<ItemStack> REPLACEABLE_TOOL = List.of(new ItemStack(Blocks.ENCHANTING_TABLE));
+
+ @ModifyExpressionValue(method = "getText", at = @At(value = "INVOKE", target = "Lcom/google/common/cache/Cache;get(Ljava/lang/Object;Ljava/util/concurrent/Callable;)Ljava/lang/Object;"))
+ private Object overwriteAvailableTools(Object original, @Local(argsOnly = true) BlockAccessor accessor) {
+ var orig = (List<ItemStack>) original;
+ if (orig.isEmpty() && CustomFakeBlockProvider.hasCustomBlock(accessor))
+ return REPLACEABLE_TOOL;
+ return orig;
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/OnUpdateBreakProgress.java b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/OnUpdateBreakProgress.java
new file mode 100644
index 0000000..76084f8
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/OnUpdateBreakProgress.java
@@ -0,0 +1,22 @@
+package moe.nea.firmament.mixins.compat.jade;
+
+import moe.nea.firmament.compat.jade.CustomMiningHardnessProvider;
+import moe.nea.firmament.util.MC;
+import net.minecraft.client.renderer.LevelRenderer;
+import net.minecraft.core.BlockPos;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.util.Objects;
+
+@Mixin(LevelRenderer.class)
+public class OnUpdateBreakProgress {
+ @Inject(method = "destroyBlockProgress", at = @At("HEAD"))
+ private void replaceBreakProgress(int entityId, BlockPos pos, int stage, CallbackInfo ci) {
+ if (entityId == 0 && null != MC.INSTANCE.getInteractionManager() && Objects.equals(MC.INSTANCE.getInteractionManager().destroyBlockPos, pos)) {
+ CustomMiningHardnessProvider.setBreakingInfo(pos, stage);
+ }
+ }
+}
diff --git a/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/PatchBreakingBarSpeedJade.java b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/PatchBreakingBarSpeedJade.java
new file mode 100644
index 0000000..898923a
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/PatchBreakingBarSpeedJade.java
@@ -0,0 +1,25 @@
+package moe.nea.firmament.mixins.compat.jade;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import moe.nea.firmament.compat.jade.CustomMiningHardnessProvider;
+import org.objectweb.asm.Opcodes;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import snownee.jade.JadeClient;
+
+@Mixin(JadeClient.class)
+public class PatchBreakingBarSpeedJade {
+ @ModifyExpressionValue(
+ method = "drawBreakingProgress",
+ at = @At(value = "FIELD", target = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;destroyProgress:F", opcode = Opcodes.GETFIELD)
+ )
+ private static float replaceBlockBreakingProgress(float original) {
+ return CustomMiningHardnessProvider.replaceBreakProgress(original);
+ }
+
+ @ModifyExpressionValue(method = "drawBreakingProgress",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;getDestroyProgress(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)F"))
+ private static float replacePlayerSpecificBreakingProgress(float original) {
+ return CustomMiningHardnessProvider.replaceBlockBreakSpeed(original);
+ }
+}
diff --git a/src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt b/src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt
index b734e2c..ff58c20 100644
--- a/src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt
+++ b/src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt
@@ -6,6 +6,6 @@ import moe.nea.firmament.gui.config.AllConfigsGui
class FirmamentModMenuPlugin : ModMenuApi {
override fun getModConfigScreenFactory(): ConfigScreenFactory<*> {
- return ConfigScreenFactory { AllConfigsGui.makeScreen(it) }
+ return ConfigScreenFactory { AllConfigsGui.makeScreen(parent = it) }
}
}
diff --git a/src/compat/moulconfig/java/MCConfigEditorIntegration.kt b/src/compat/moulconfig/java/MCConfigEditorIntegration.kt
index dec2559..6b2df21 100644
--- a/src/compat/moulconfig/java/MCConfigEditorIntegration.kt
+++ b/src/compat/moulconfig/java/MCConfigEditorIntegration.kt
@@ -1,13 +1,16 @@
package moe.nea.firmament.compat.moulconfig
import com.google.auto.service.AutoService
+import io.github.notenoughupdates.moulconfig.ChromaColour
import io.github.notenoughupdates.moulconfig.Config
import io.github.notenoughupdates.moulconfig.DescriptionRendereringBehaviour
import io.github.notenoughupdates.moulconfig.Social
import io.github.notenoughupdates.moulconfig.common.IMinecraft
import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
+import io.github.notenoughupdates.moulconfig.common.text.StructuredText
import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiElementWrapper
+import io.github.notenoughupdates.moulconfig.gui.GuiContext
+import io.github.notenoughupdates.moulconfig.gui.GuiElementComponent
import io.github.notenoughupdates.moulconfig.gui.GuiOptionEditor
import io.github.notenoughupdates.moulconfig.gui.HorizontalAlign
import io.github.notenoughupdates.moulconfig.gui.MoulConfigEditor
@@ -20,9 +23,12 @@ import io.github.notenoughupdates.moulconfig.gui.editors.ComponentEditor
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorAccordion
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorBoolean
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorButton
+import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorColour
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorDropdown
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorText
import io.github.notenoughupdates.moulconfig.observer.GetSetter
+import io.github.notenoughupdates.moulconfig.platform.MoulConfigPlatform
+import io.github.notenoughupdates.moulconfig.platform.MoulConfigScreenComponent
import io.github.notenoughupdates.moulconfig.processor.ProcessedCategory
import io.github.notenoughupdates.moulconfig.processor.ProcessedOption
import java.lang.reflect.Type
@@ -30,21 +36,24 @@ import java.net.URI
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.util.Identifier
-import net.minecraft.util.StringIdentifiable
-import net.minecraft.util.Util
+import net.minecraft.client.gui.screens.Screen
+import net.minecraft.network.chat.Component
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.util.StringRepresentable
+import net.minecraft.Util
import moe.nea.firmament.Firmament
+import moe.nea.firmament.gui.config.AllConfigsGui
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.ColourHandler
import moe.nea.firmament.gui.config.DurationHandler
import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider
import moe.nea.firmament.gui.config.HudMeta
import moe.nea.firmament.gui.config.HudMetaHandler
import moe.nea.firmament.gui.config.IntegerHandler
import moe.nea.firmament.gui.config.KeyBindingHandler
-import moe.nea.firmament.gui.config.ManagedConfig
+import moe.nea.firmament.util.data.ManagedConfig
import moe.nea.firmament.gui.config.ManagedOption
import moe.nea.firmament.gui.config.StringHandler
import moe.nea.firmament.gui.toMoulConfig
@@ -96,29 +105,31 @@ class MCConfigEditorIntegration : FirmamentConfigScreenProvider {
val mappedSetter = setter.xmap(fromT, toT)
private val delegateI by lazy {
- wrapComponent(RowComponent(
- AlignComponent(
- TextComponent(
- IMinecraft.instance.defaultFontRenderer,
- { formatter(setter.get()) },
- 25,
- TextComponent.TextAlignment.CENTER, false, false
+ wrapComponent(
+ RowComponent(
+ AlignComponent(
+ TextComponent(
+ IMinecraft.INSTANCE.defaultFontRenderer,
+ { StructuredText.of(formatter(setter.get())) },
+ 25,
+ TextComponent.TextAlignment.CENTER, false, false
+ ),
+ GetSetter.constant(HorizontalAlign.CENTER),
+ GetSetter.constant(VerticalAlign.CENTER)
),
- GetSetter.constant(HorizontalAlign.CENTER),
- GetSetter.constant(VerticalAlign.CENTER)
- ),
- SliderComponent(
- mappedSetter,
- fromT(minValue),
- fromT(maxValue),
- minStep,
- 40
+ SliderComponent(
+ mappedSetter,
+ fromT(minValue),
+ fromT(maxValue),
+ minStep,
+ 40
+ )
)
- ))
+ )
}
}
- fun <T> helpRegisterChoice() where T : Enum<T>, T : StringIdentifiable {
+ fun <T> helpRegisterChoice() where T : Enum<T>, T : StringRepresentable {
register(ChoiceHandler::class.java as Class<ChoiceHandler<T>>) { handler, option, categoryAccordionId, configObject ->
object : ProcessedEditableOptionFirm<T>(option, categoryAccordionId, configObject) {
override fun createEditor(): GuiOptionEditor {
@@ -183,10 +194,30 @@ class MCConfigEditorIntegration : FirmamentConfigScreenProvider {
}
}
}
+ register(ColourHandler::class.java) { handler, option, accordionId, configObject ->
+ object : ProcessedEditableOptionFirm<ChromaColour>(option, accordionId, configObject) {
+ override fun fromT(t: ChromaColour): Any {
+ return t
+ }
+
+ override fun toT(any: Any?): ChromaColour? {
+ return any as ChromaColour?
+ }
+
+ override fun createEditor(): GuiOptionEditor {
+ return GuiOptionEditorColour(this)
+ }
+
+ override fun getType(): Type? {
+ return ChromaColour::class.java
+ }
+ }
+
+ }
register(ClickHandler::class.java) { handler, option, categoryAccordionId, configObject ->
object : ProcessedEditableOptionFirm<Unit>(option, categoryAccordionId, configObject) {
override fun createEditor(): GuiOptionEditor {
- return GuiOptionEditorButton(this, -1, "Click", configObject)
+ return GuiOptionEditorButton(this, -1, StructuredText.of("Click"), configObject)
}
override fun toT(any: Any?): Unit? {
@@ -205,7 +236,7 @@ class MCConfigEditorIntegration : FirmamentConfigScreenProvider {
register(HudMetaHandler::class.java) { handler, option, categoryAccordionId, configObject ->
object : ProcessedEditableOptionFirm<HudMeta>(option, categoryAccordionId, configObject) {
override fun createEditor(): GuiOptionEditor {
- return GuiOptionEditorButton(this, -1, "Edit HUD", configObject)
+ return GuiOptionEditorButton(this, -1, StructuredText.of("Edit HUD"), configObject)
}
override fun fromT(t: HudMeta): Any {
@@ -302,101 +333,111 @@ class MCConfigEditorIntegration : FirmamentConfigScreenProvider {
}
}
- override fun open(parent: Screen?): Screen {
- val configObject = object : Config() {
- override fun saveNow() {
- ManagedConfig.allManagedConfigs.getAll().forEach { it.save() }
- }
+ val configObject = object : Config() {
+ override fun saveNow() {
+ ManagedConfig.allManagedConfigs.getAll().forEach { it.markDirty() }
+ }
- override fun shouldAutoFocusSearchbar(): Boolean {
- return true
- }
+ override fun shouldAutoFocusSearchbar(): Boolean {
+ return true
+ }
+
+ override fun getTitle(): StructuredText {
+ return StructuredText.of("Firmament ${Firmament.version.friendlyString}")
+ }
- override fun getTitle(): String {
- return "Firmament"
+ @Deprecated("Deprecated in java")
+ override fun executeRunnable(runnableId: Int) {
+ if (runnableId >= 0)
+ ErrorUtil.softError("Executed runnable $runnableId")
+ }
+
+ override fun getDescriptionBehaviour(option: ProcessedOption?): DescriptionRendereringBehaviour {
+ return DescriptionRendereringBehaviour.EXPAND_PANEL
+ }
+
+ fun mkSocial(name: String, identifier: ResourceLocation, link: String) = object : Social() {
+ override fun onClick() {
+ MC.openUrl(link)
}
- @Deprecated("Deprecated in java")
- override fun executeRunnable(runnableId: Int) {
- if (runnableId >= 0)
- ErrorUtil.softError("Executed runnable $runnableId")
+ override fun getTooltip(): List<StructuredText> {
+ return listOf(StructuredText.of(name))
}
- override fun getDescriptionBehaviour(option: ProcessedOption?): DescriptionRendereringBehaviour {
- return DescriptionRendereringBehaviour.EXPAND_PANEL
+ override fun getIcon(): MyResourceLocation {
+ return identifier.toMoulConfig()
}
+ }
- fun mkSocial(name: String, identifier: Identifier, link: String) = object : Social() {
- override fun onClick() {
- Util.getOperatingSystem().open(URI(link))
+ private val socials = listOf<Social>(
+ mkSocial(
+ "Discord", Firmament.identifier("textures/socials/discord.png"),
+ Firmament.modContainer.metadata.contact.get("discord").get()
+ ),
+ mkSocial(
+ "Source Code", Firmament.identifier("textures/socials/git.png"),
+ Firmament.modContainer.metadata.contact.get("sources").get()
+ ),
+ mkSocial(
+ "Modrinth", Firmament.identifier("textures/socials/modrinth.png"),
+ Firmament.modContainer.metadata.contact.get("modrinth").get()
+ ),
+ )
+
+ override fun getSocials(): List<Social> {
+ return socials
+ }
+ }
+ val categories = ManagedConfig.Category.entries.map {
+ val options = mutableListOf<ProcessedOptionFirm>()
+ var nextAccordionId = 720
+ it.configs.forEach { config ->
+ val categoryAccordionId = nextAccordionId++
+ options.add(object : ProcessedOptionFirm(-1, configObject) {
+ override fun getDebugDeclarationLocation(): String {
+ return "FirmamentConfig:${config.name}"
}
- override fun getTooltip(): List<String> {
- return listOf(name)
+ override fun getName(): StructuredText {
+ return MoulConfigPlatform.wrap(config.labelText)
}
- override fun getIcon(): MyResourceLocation {
- return identifier.toMoulConfig()
+ override fun getDescription(): StructuredText {
+ return StructuredText.of("Missing description")
}
- }
-
- private val socials = listOf<Social>(
- mkSocial("Discord", Firmament.identifier("textures/socials/discord.png"),
- Firmament.modContainer.metadata.contact.get("discord").get()),
- mkSocial("Source Code", Firmament.identifier("textures/socials/git.png"),
- Firmament.modContainer.metadata.contact.get("sources").get()),
- mkSocial("Modrinth", Firmament.identifier("textures/socials/modrinth.png"),
- Firmament.modContainer.metadata.contact.get("modrinth").get()),
- )
- override fun getSocials(): List<Social> {
- return socials
- }
- }
- val categories = ManagedConfig.Category.entries.map {
- val options = mutableListOf<ProcessedOptionFirm>()
- var nextAccordionId = 720
- it.configs.forEach { config ->
- val categoryAccordionId = nextAccordionId++
- options.add(object : ProcessedOptionFirm(-1, configObject) {
- override fun getDebugDeclarationLocation(): String {
- return "FirmamentConfig:${config.name}"
- }
-
- override fun getName(): String {
- return config.labelText.string
- }
-
- override fun getDescription(): String {
- return "Missing description"
- }
-
- override fun get(): Any {
- return Unit
- }
+ override fun get(): Any {
+ return Unit
+ }
- override fun getType(): Type {
- return Unit.javaClass
- }
+ override fun getType(): Type {
+ return Unit.javaClass
+ }
- override fun set(value: Any?): Boolean {
- return false
- }
+ override fun set(value: Any?): Boolean {
+ return false
+ }
- override fun createEditor(): GuiOptionEditor {
- return GuiOptionEditorAccordion(this, categoryAccordionId)
- }
- })
- config.allOptions.forEach { (key, option) ->
- val processedOption = getHandler(option, categoryAccordionId, configObject)
- options.add(processedOption)
+ override fun createEditor(): GuiOptionEditor {
+ return GuiOptionEditorAccordion(this, categoryAccordionId)
}
+ })
+ config.allOptions.forEach { (key, option) ->
+ val processedOption = getHandler(option, categoryAccordionId, configObject)
+ options.add(processedOption)
}
-
- return@map ProcessedCategoryFirm(it, options)
}
+
+ return@map ProcessedCategoryFirm(it, options)
+ }
+
+ override fun open(search: String?, parent: Screen?): Screen {
val editor = MoulConfigEditor(ProcessedCategory.collect(categories), configObject)
- return GuiElementWrapper(editor) // TODO : add parent support
+ if (search != null)
+ editor.search(search)
+ editor.setWide(AllConfigsGui.ConfigConfig.enableWideMC)
+ return MoulConfigScreenComponent(Component.empty(), GuiContext(GuiElementComponent(editor)), parent) // TODO : add parent support
}
}
diff --git a/src/compat/moulconfig/java/ProcessedCategoryFirm.kt b/src/compat/moulconfig/java/ProcessedCategoryFirm.kt
index 5313441..7c99528 100644
--- a/src/compat/moulconfig/java/ProcessedCategoryFirm.kt
+++ b/src/compat/moulconfig/java/ProcessedCategoryFirm.kt
@@ -1,9 +1,11 @@
package moe.nea.firmament.compat.moulconfig
+import io.github.notenoughupdates.moulconfig.common.text.StructuredText
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorAccordion
+import io.github.notenoughupdates.moulconfig.platform.MoulConfigPlatform
import io.github.notenoughupdates.moulconfig.processor.ProcessedCategory
import io.github.notenoughupdates.moulconfig.processor.ProcessedOption
-import moe.nea.firmament.gui.config.ManagedConfig
+import moe.nea.firmament.util.data.ManagedConfig
class ProcessedCategoryFirm(
val category: ManagedConfig.Category,
@@ -21,12 +23,12 @@ class ProcessedCategoryFirm(
return "FirmamentCategory.${category.name}"
}
- override fun getDisplayName(): String {
- return category.labelText.string
+ override fun getDisplayName(): StructuredText {
+ return MoulConfigPlatform.wrap(category.labelText)
}
- override fun getDescription(): String {
- return category.description.string
+ override fun getDescription(): StructuredText {
+ return MoulConfigPlatform.wrap(category.description)
}
override fun getIdentifier(): String {
diff --git a/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt b/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt
index f0e9aa4..e1ad217 100644
--- a/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt
+++ b/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt
@@ -1,6 +1,8 @@
package moe.nea.firmament.compat.moulconfig
import io.github.notenoughupdates.moulconfig.Config
+import io.github.notenoughupdates.moulconfig.common.text.StructuredText
+import io.github.notenoughupdates.moulconfig.platform.MoulConfigPlatform
import moe.nea.firmament.gui.config.ManagedOption
import moe.nea.firmament.util.ErrorUtil
@@ -14,12 +16,12 @@ abstract class ProcessedEditableOptionFirm<T : Any>(
return "FirmamentOption:${managedConfig.name}:${managedOption.propertyName}"
}
- override fun getName(): String {
- return managedOption.labelText.string
+ override fun getName(): StructuredText {
+ return MoulConfigPlatform.wrap(managedOption.labelText)
}
- override fun getDescription(): String {
- return managedOption.labelDescription.string
+ override fun getDescription(): StructuredText {
+ return MoulConfigPlatform.wrap(managedOption.labelDescription)
}
abstract fun fromT(t: T): Any
@@ -34,11 +36,11 @@ abstract class ProcessedEditableOptionFirm<T : Any>(
ErrorUtil.softError("Failed to set value p0 in $this")
return false
}
- managedConfig.save()
+ managedConfig.markDirty()
return true
}
override fun explicitNotifyChange() {
- managedConfig.save()
+ managedConfig.markDirty()
}
}
diff --git a/src/compat/moulconfig/java/ProcessedOptionFirm.kt b/src/compat/moulconfig/java/ProcessedOptionFirm.kt
index 4d0096c..6936048 100644
--- a/src/compat/moulconfig/java/ProcessedOptionFirm.kt
+++ b/src/compat/moulconfig/java/ProcessedOptionFirm.kt
@@ -10,6 +10,9 @@ abstract class ProcessedOptionFirm(
private val accordionId: Int,
private val config: Config
) : ProcessedOption {
+ override fun getPath(): String? {
+ return "nonsense"
+ }
lateinit var category: ProcessedCategoryFirm
override fun getAccordionId(): Int {
return accordionId
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/Compat.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/Compat.kt
new file mode 100644
index 0000000..9ab4d22
--- /dev/null
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/Compat.kt
@@ -0,0 +1,12 @@
+package moe.nea.firmament.compat.rei
+
+import net.fabricmc.loader.api.FabricLoader
+import moe.nea.firmament.util.compatloader.CompatMeta
+import moe.nea.firmament.util.compatloader.ICompatMeta
+
+@CompatMeta
+object Compat : ICompatMeta {
+ override fun shouldLoad(): Boolean {
+ return FabricLoader.getInstance().isModLoaded("roughlyenoughitems")
+ }
+}
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 1097654..cc55fb8 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
@@ -5,9 +5,9 @@ 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.Element
-import net.minecraft.entity.LivingEntity
+import net.minecraft.client.gui.GuiGraphics
+import net.minecraft.client.gui.components.events.GuiEventListener
+import net.minecraft.world.entity.LivingEntity
import moe.nea.firmament.gui.entity.EntityRenderer
import moe.nea.firmament.util.ErrorUtil
@@ -17,13 +17,13 @@ class EntityWidget(
val point: Point,
val size: FloatingDimension = FloatingDimension(defaultSize)
) : WidgetWithBounds() {
- override fun children(): List<Element> {
+ override fun children(): List<GuiEventListener> {
return emptyList()
}
var hasErrored = false
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
+ override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
try {
if (!hasErrored) {
EntityRenderer.renderEntity(
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt
index 98ac276..71e867a 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt
@@ -2,9 +2,11 @@ package moe.nea.firmament.compat.rei
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
import me.shedaniel.rei.api.common.plugins.REICommonPlugin
+import moe.nea.firmament.repo.RepoManager
class FirmamentReiCommonPlugin : REICommonPlugin {
override fun registerEntryTypes(registry: EntryTypeRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
registry.register(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
}
}
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 92f2cfc..ad0da89 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
@@ -1,5 +1,6 @@
package moe.nea.firmament.compat.rei
+import io.github.moulberry.repo.data.NEUCraftingRecipe
import me.shedaniel.rei.api.client.plugins.REIClientPlugin
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry
@@ -12,24 +13,29 @@ import me.shedaniel.rei.api.client.registry.transfer.TransferHandler
import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
import me.shedaniel.rei.api.common.entry.EntryStack
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.item.ItemStack
-import net.minecraft.text.Text
-import net.minecraft.util.ActionResult
-import net.minecraft.util.Identifier
-import moe.nea.firmament.compat.rei.recipes.SBCraftingRecipe
-import moe.nea.firmament.compat.rei.recipes.SBEssenceUpgradeRecipe
-import moe.nea.firmament.compat.rei.recipes.SBForgeRecipe
+import net.minecraft.client.gui.screens.Screen
+import net.minecraft.client.gui.screens.inventory.ContainerScreen
+import net.minecraft.client.gui.screens.inventory.MenuAccess
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
+import net.minecraft.world.item.ItemStack
+import net.minecraft.network.chat.Component
+import net.minecraft.world.InteractionResult
+import net.minecraft.resources.ResourceLocation
+import moe.nea.firmament.compat.rei.recipes.GenericREIRecipeCategory
import moe.nea.firmament.compat.rei.recipes.SBKatRecipe
import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe
+import moe.nea.firmament.compat.rei.recipes.SBRecipe
import moe.nea.firmament.compat.rei.recipes.SBReforgeRecipe
+import moe.nea.firmament.compat.rei.recipes.SBShopRecipe
import moe.nea.firmament.events.HandledScreenPushREIEvent
import moe.nea.firmament.features.inventory.CraftingOverlay
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
+import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
+import moe.nea.firmament.repo.recipes.SBCraftingRecipeRenderer
+import moe.nea.firmament.repo.recipes.SBEssenceUpgradeRecipeRenderer
+import moe.nea.firmament.repo.recipes.SBForgeRecipeRenderer
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.guessRecipeId
@@ -40,30 +46,40 @@ import moe.nea.firmament.util.unformattedString
class FirmamentReiPlugin : REIClientPlugin {
companion object {
+ @ExpensiveItemCacheApi
fun EntryStack<SBItemStack>.asItemEntry(): EntryStack<ItemStack> {
return EntryStack.of(VanillaEntryTypes.ITEM, value.asImmutableItemStack())
}
- val SKYBLOCK_ITEM_TYPE_ID = Identifier.of("firmament", "skyblockitems")
+ val SKYBLOCK_ITEM_TYPE_ID = ResourceLocation.fromNamespaceAndPath("firmament", "skyblockitems")
}
+ @OptIn(ExpensiveItemCacheApi::class)
override fun registerTransferHandlers(registry: TransferHandlerRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
registry.register(TransferHandler { context ->
val screen = context.containerScreen
val display = context.display
- if (display !is SBCraftingRecipe) return@TransferHandler TransferHandler.Result.createNotApplicable()
- val neuItem = RepoManager.getNEUItem(SkyblockId(display.neuRecipe.output.itemId))
- ?: error("Could not find neu item ${display.neuRecipe.output.itemId} which is used in a recipe output")
- val useSuperCraft = context.isStackedCrafting || RepoManager.Config.alwaysSuperCraft
- if (neuItem.isVanilla && useSuperCraft) return@TransferHandler TransferHandler.Result.createFailed(Text.translatable(
- "firmament.recipe.novanilla"))
+ if (display !is SBRecipe) return@TransferHandler TransferHandler.Result.createNotApplicable()
+ val recipe = display.neuRecipe
+ if (recipe !is NEUCraftingRecipe) return@TransferHandler TransferHandler.Result.createNotApplicable()
+ val neuItem = RepoManager.getNEUItem(SkyblockId(recipe.output.itemId))
+ ?: error("Could not find neu item ${recipe.output.itemId} which is used in a recipe output")
+ val useSuperCraft = context.isStackedCrafting || RepoManager.TConfig.alwaysSuperCraft
+ if (neuItem.isVanilla && useSuperCraft) return@TransferHandler TransferHandler.Result.createFailed(
+ Component.translatable(
+ "firmament.recipe.novanilla"
+ )
+ )
var shouldReturn = true
if (context.isActuallyCrafting && !useSuperCraft) {
- if (screen !is GenericContainerScreen || screen.title?.unformattedString != CraftingOverlay.CRAFTING_SCREEN_NAME) {
+ val craftingScreen = (screen as? ContainerScreen)
+ ?.takeIf { it.title?.string == CraftingOverlay.CRAFTING_SCREEN_NAME }
+ if (craftingScreen == null) {
MC.sendCommand("craft")
shouldReturn = false
}
- CraftingOverlay.setOverlay(screen as? GenericContainerScreen, display.neuRecipe)
+ CraftingOverlay.setOverlay(craftingScreen, recipe)
}
if (context.isActuallyCrafting && useSuperCraft) {
shouldReturn = false
@@ -74,50 +90,61 @@ class FirmamentReiPlugin : REIClientPlugin {
}
+ val generics = listOf<GenericREIRecipeCategory<*>>(
+ // Order matters: The order in here is the order in which they show up in REI
+ GenericREIRecipeCategory(SBCraftingRecipeRenderer),
+ GenericREIRecipeCategory(SBForgeRecipeRenderer),
+ GenericREIRecipeCategory(SBEssenceUpgradeRecipeRenderer),
+ )
+
override fun registerCategories(registry: CategoryRegistry) {
- registry.add(SBCraftingRecipe.Category)
- registry.add(SBForgeRecipe.Category)
+ if (!RepoManager.shouldLoadREI()) return
+
+ registry.add(generics)
registry.add(SBMobDropRecipe.Category)
registry.add(SBKatRecipe.Category)
registry.add(SBReforgeRecipe.Category)
- registry.add(SBEssenceUpgradeRecipe.Category)
+ registry.add(SBShopRecipe.Category)
}
override fun registerExclusionZones(zones: ExclusionZones) {
- zones.register(HandledScreen::class.java) { HandledScreenPushREIEvent.publish(HandledScreenPushREIEvent(it)).rectangles }
+ zones.register(AbstractContainerScreen::class.java) { HandledScreenPushREIEvent.publish(HandledScreenPushREIEvent(it)).rectangles }
zones.register(StorageOverlayScreen::class.java) { it.getBounds() }
}
override fun registerDisplays(registry: DisplayRegistry) {
- registry.registerDisplayGenerator(
- SBCraftingRecipe.Category.catIdentifier,
- SkyblockCraftingRecipeDynamicGenerator)
+ if (!RepoManager.shouldLoadREI()) return
+
+ generics.forEach {
+ it.registerDynamicGenerator(registry)
+ }
registry.registerDisplayGenerator(
SBReforgeRecipe.catIdentifier,
SBReforgeRecipe.DynamicGenerator
)
registry.registerDisplayGenerator(
- SBForgeRecipe.Category.categoryIdentifier,
- SkyblockForgeRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
SBMobDropRecipe.Category.categoryIdentifier,
- SkyblockMobDropRecipeDynamicGenerator)
+ SkyblockMobDropRecipeDynamicGenerator
+ )
registry.registerDisplayGenerator(
- SBKatRecipe.Category.categoryIdentifier,
- SkyblockKatRecipeDynamicGenerator)
+ SBShopRecipe.Category.categoryIdentifier,
+ SkyblockShopRecipeDynamicGenerator
+ )
registry.registerDisplayGenerator(
- SBEssenceUpgradeRecipe.Category.categoryIdentifier,
- SkyblockEssenceRecipeDynamicGenerator
+ SBKatRecipe.Category.categoryIdentifier,
+ SkyblockKatRecipeDynamicGenerator
)
}
override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) {
- if (!RepoManager.Config.disableItemGroups)
+ if (!RepoManager.shouldLoadREI()) return
+
+ if (!RepoManager.TConfig.disableItemGroups)
RepoManager.neuRepo.constants.parents.parents
.forEach { (parent, children) ->
registry.group(
SkyblockId(parent).identifier,
- Text.literal(RepoManager.getNEUItem(SkyblockId(parent))?.displayName ?: parent),
+ Component.literal(RepoManager.getNEUItem(SkyblockId(parent))?.displayName ?: parent),
(children + parent).map { SBItemEntryDefinition.getEntry(SkyblockId(it)) })
}
}
@@ -128,14 +155,16 @@ class FirmamentReiPlugin : REIClientPlugin {
return screen == StorageOverlayScreen::class.java
}
- override fun <R : Screen?> shouldScreenBeOverlaid(screen: R): ActionResult {
- return ActionResult.SUCCESS
+ override fun <R : Screen?> shouldScreenBeOverlaid(screen: R): InteractionResult {
+ return InteractionResult.SUCCESS
}
})
registry.registerFocusedStack(SkyblockItemIdFocusedStackProvider)
}
override fun registerEntries(registry: EntryRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
+
registry.removeEntryIf { true }
RepoManager.neuRepo.items?.items?.values?.forEach { neuItem ->
registry.addEntry(SBItemEntryDefinition.getEntry(neuItem.skyblockId))
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt
index b917c3e..a19355b 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt
@@ -5,17 +5,18 @@ import me.shedaniel.math.impl.PointHelper
import me.shedaniel.rei.api.client.REIRuntime
import me.shedaniel.rei.api.client.gui.widgets.Slot
import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
-import net.minecraft.client.gui.Element
-import net.minecraft.client.gui.ParentElement
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.item.ItemStack
+import net.minecraft.client.gui.components.events.GuiEventListener
+import net.minecraft.client.gui.components.events.ContainerEventHandler
+import net.minecraft.client.gui.screens.Screen
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
+import net.minecraft.world.item.ItemStack
import moe.nea.firmament.util.HoveredItemStackProvider
import moe.nea.firmament.util.compatloader.CompatLoader
@AutoService(HoveredItemStackProvider::class)
@CompatLoader.RequireMod("roughlyenoughitems")
class ScreenRegistryHoveredItemStackProvider : HoveredItemStackProvider {
- override fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? {
+ override fun provideHoveredItemStack(screen: Screen): ItemStack? {
val entryStack = ScreenRegistry.getInstance().getFocusedStack(screen, PointHelper.ofMouse())
?: return null
return entryStack.value as? ItemStack ?: entryStack.cheatsAs().value
@@ -25,14 +26,14 @@ class ScreenRegistryHoveredItemStackProvider : HoveredItemStackProvider {
@AutoService(HoveredItemStackProvider::class)
@CompatLoader.RequireMod("roughlyenoughitems")
class OverlayHoveredItemStackProvider : HoveredItemStackProvider {
- override fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? {
- var baseElement: Element? = REIRuntime.getInstance().overlay.orElse(null)
+ override fun provideHoveredItemStack(screen: Screen): ItemStack? {
+ var baseElement: GuiEventListener? = REIRuntime.getInstance().overlay.orElse(null)
val mx = PointHelper.getMouseFloatingX()
val my = PointHelper.getMouseFloatingY()
while (true) {
if (baseElement is Slot) return baseElement.currentEntry.cheatsAs().value
- if (baseElement !is ParentElement) return null
- baseElement = baseElement.hoveredElement(mx, my).orElse(null)
+ if (baseElement !is ContainerEventHandler) return null
+ baseElement = baseElement.getChildAt(mx, my).orElse(null)
}
}
}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt
index c40f00b..0e24f4e 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt
@@ -15,40 +15,74 @@ import me.shedaniel.rei.api.client.gui.widgets.Tooltip
import me.shedaniel.rei.api.client.gui.widgets.TooltipContext
import me.shedaniel.rei.api.common.entry.EntryStack
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.item.tooltip.TooltipType
-import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.GuiGraphics
+import net.minecraft.world.item.ItemStack
+import net.minecraft.world.item.Items
+import net.minecraft.world.item.TooltipFlag
+import net.minecraft.network.chat.Component
import moe.nea.firmament.events.ItemTooltipEvent
+import moe.nea.firmament.repo.ExpensiveItemCacheApi
+import moe.nea.firmament.repo.ItemCache
+import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.ErrorUtil
+import moe.nea.firmament.util.FirmFormatters
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.darkGrey
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.loreAccordingToNbt
// TODO: make this re implement BatchedEntryRenderer, if possible (likely not, due to no-alloc rendering)
// Also it is probably not even that much faster now, with render layers.
object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
+ @OptIn(ExpensiveItemCacheApi::class)
override fun render(
entry: EntryStack<SBItemStack>,
- context: DrawContext,
+ context: GuiGraphics,
bounds: Rectangle,
mouseX: Int,
mouseY: Int,
delta: Float
) {
- context.matrices.push()
- context.matrices.translate(bounds.centerX.toFloat(), bounds.centerY.toFloat(), 0F)
- context.matrices.scale(bounds.width.toFloat() / 16F, bounds.height.toFloat() / 16F, 1f)
- val item = entry.asItemEntry().value
- context.drawItemWithoutEntity(item, -8, -8, )
- context.drawStackOverlay(minecraft.textRenderer, item, -8, -8)
- context.matrices.pop()
+ val neuItem = entry.value.neuItem
+ val itemToRender = if(!RepoManager.TConfig.perfectRenders.rendersPerfectVisuals() && !entry.value.isWarm() && neuItem != null) {
+ ItemCache.recacheSoon(neuItem)
+ ItemStack(Items.PAINTING)
+ } else {
+ entry.value.asImmutableItemStack()
+ }
+
+ context.pose().pushMatrix()
+ context.pose().translate(bounds.centerX.toFloat(), bounds.centerY.toFloat())
+ context.pose().scale(bounds.width.toFloat() / 16F, bounds.height.toFloat() / 16F)
+ context.renderItem(itemToRender, -8, -8)
+ context.renderItemDecorations(
+ MC.font, itemToRender, -8, -8,
+ if (entry.value.getStackSize() > 1000) FirmFormatters.shortFormat(
+ entry.value.getStackSize()
+ .toDouble()
+ )
+ else null
+ )
+ context.pose().popMatrix()
}
- val minecraft = MinecraftClient.getInstance()
+ val minecraft = Minecraft.getInstance()
var canUseVanillaTooltipEvents = true
+ @OptIn(ExpensiveItemCacheApi::class)
override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
+ if (!entry.value.isWarm() && !RepoManager.TConfig.perfectRenders.rendersPerfectText()) {
+ val neuItem = entry.value.neuItem
+ if (neuItem != null) {
+ val lore = mutableListOf<Component>()
+ lore.add(Component.literal(neuItem.displayName))
+ neuItem.lore.mapTo(mutableListOf()) { Component.literal(it) }
+ return Tooltip.create(lore)
+ }
+ }
+
val stack = entry.value.asImmutableItemStack()
val lore = mutableListOf(stack.displayNameAccordingToNbt)
@@ -56,20 +90,24 @@ object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
if (canUseVanillaTooltipEvents) {
try {
ItemTooltipCallback.EVENT.invoker().getTooltip(
- stack, tooltipContext.vanillaContext(), TooltipType.BASIC, lore
+ stack, tooltipContext.vanillaContext(), TooltipFlag.Default.NORMAL, lore
)
} catch (ex: Exception) {
canUseVanillaTooltipEvents = false
ErrorUtil.softError("Failed to use vanilla tooltips", ex)
}
} else {
- ItemTooltipEvent.publish(ItemTooltipEvent(
- stack,
- tooltipContext.vanillaContext(),
- TooltipType.BASIC,
- lore
- ))
+ ItemTooltipEvent.publish(
+ ItemTooltipEvent(
+ stack,
+ tooltipContext.vanillaContext(),
+ TooltipFlag.Default.NORMAL,
+ lore
+ )
+ )
}
+ if (entry.value.getStackSize() > 1000 && lore.isNotEmpty())
+ lore.add(1, Component.literal("${entry.value.getStackSize()}x").darkGrey())
// TODO: tags aren't sent as early now so some tooltip components that use tags will crash the game
// stack.getTooltip(
// Item.TooltipContext.create(
@@ -77,7 +115,7 @@ object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
// ?: MC.defaultRegistries
// ),
// MC.player,
-// TooltipType.BASIC
+// TooltipFlag.Default.NORMAL
// )
return Tooltip.create(lore)
}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt
index 724d193..9f32472 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt
@@ -2,8 +2,8 @@ package moe.nea.firmament.compat.rei
import com.mojang.serialization.Codec
import me.shedaniel.rei.api.common.entry.EntrySerializer
-import net.minecraft.network.RegistryByteBuf
-import net.minecraft.network.codec.PacketCodec
+import net.minecraft.network.RegistryFriendlyByteBuf
+import net.minecraft.network.codec.StreamCodec
import moe.nea.firmament.repo.SBItemStack
object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {
@@ -11,7 +11,7 @@ object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {
return SBItemStack.CODEC
}
- override fun streamCodec(): PacketCodec<RegistryByteBuf, SBItemStack> {
+ override fun streamCodec(): StreamCodec<RegistryFriendlyByteBuf, SBItemStack> {
return SBItemStack.PACKET_CODEC.cast()
}
}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt
new file mode 100644
index 0000000..54bc7f0
--- /dev/null
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt
@@ -0,0 +1,82 @@
+package moe.nea.firmament.compat.rei
+
+import io.github.notenoughupdates.moulconfig.gui.GuiComponent
+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.Widget
+import me.shedaniel.rei.api.client.gui.widgets.Widgets
+import net.minecraft.network.chat.Component
+import net.minecraft.world.entity.LivingEntity
+import moe.nea.firmament.compat.rei.recipes.wrapWidget
+import moe.nea.firmament.repo.SBItemStack
+import moe.nea.firmament.repo.recipes.RecipeLayouter
+
+class REIRecipeLayouter : RecipeLayouter {
+ val container: MutableList<Widget> = mutableListOf()
+ fun <T: Widget> add(t: T): T = t.also(container::add)
+
+ override fun createCyclingItemSlot(
+ x: Int,
+ y: Int,
+ content: List<SBItemStack>,
+ slotKind: RecipeLayouter.SlotKind
+ ): RecipeLayouter.CyclingItemSlot {
+ val slot = Widgets.createSlot(Point(x, y))
+ if (content.isNotEmpty())
+ slot.entries(content.map { SBItemEntryDefinition.getEntry(it) })
+ when (slotKind) {
+ RecipeLayouter.SlotKind.SMALL_INPUT -> slot.markInput()
+ RecipeLayouter.SlotKind.SMALL_OUTPUT -> slot.markOutput()
+ RecipeLayouter.SlotKind.BIG_OUTPUT -> {
+ slot.markOutput().disableBackground()
+ add(Widgets.createResultSlotBackground(Point(x, y)))
+ }
+ RecipeLayouter.SlotKind.DISPLAY -> {
+ slot.disableBackground()
+ slot.disableHighlight()
+ }
+ }
+ add(slot)
+ return object : RecipeLayouter.CyclingItemSlot {
+ override fun current(): SBItemStack = content.firstOrNull() ?: SBItemStack.EMPTY
+ override fun update(newValue: SBItemStack) {}
+ override fun onUpdate(action: () -> Unit) {}
+ }
+ }
+
+ override fun createTooltip(rectangle: Rectangle, label: List<Component>) {
+ add(Widgets.createTooltip(rectangle, *label.toTypedArray()))
+ }
+
+ override fun createLabel(x: Int, y: Int, text: Component): RecipeLayouter.Updater<Component> {
+ val label = add(Widgets.createLabel(Point(x, y), text))
+ return object : RecipeLayouter.Updater<Component> {
+ override fun update(newValue: Component) {
+ label.message = newValue
+ }
+ }
+ }
+
+ override fun createArrow(x: Int, y: Int) =
+ add(Widgets.createArrow(Point(x, y))).bounds
+
+ override fun createMoulConfig(
+ x: Int,
+ y: Int,
+ w: Int,
+ h: Int,
+ component: GuiComponent
+ ) {
+ add(wrapWidget(Rectangle(Point(x, y), Dimension(w, h)), component))
+ }
+
+ override fun createFire(point: Point, animationTicks: Int) {
+ add(Widgets.createBurningFire(point).animationDurationTicks(animationTicks.toDouble()))
+ }
+
+ override fun createEntity(rectangle: Rectangle, entity: LivingEntity) {
+ add(EntityWidget(entity, rectangle.location, FloatingDimension(rectangle.size)))
+ }
+}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt
index 9638281..fde3e3d 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt
@@ -9,24 +9,23 @@ import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext
import me.shedaniel.rei.api.common.entry.type.EntryDefinition
import me.shedaniel.rei.api.common.entry.type.EntryType
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
-import net.minecraft.item.ItemConvertible
-import net.minecraft.item.ItemStack
-import net.minecraft.registry.tag.TagKey
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
+import net.minecraft.world.level.ItemLike
+import net.minecraft.world.item.ItemStack
+import net.minecraft.tags.TagKey
+import net.minecraft.network.chat.Component
+import net.minecraft.resources.ResourceLocation
import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry
-import moe.nea.firmament.repo.PetData
+import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.petData
-import moe.nea.firmament.util.skyBlockId
object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
return o1.skyblockId == o2.skyblockId && o1.getStackSize() == o2.getStackSize()
}
+ @OptIn(ExpensiveItemCacheApi::class)
override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
return value.asCopiedItemStack()
}
@@ -44,8 +43,14 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
return Stream.empty()
}
- override fun asFormattedText(entry: EntryStack<SBItemStack>, value: SBItemStack): Text {
- return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asImmutableItemStack())
+ @OptIn(ExpensiveItemCacheApi::class)
+ override fun asFormattedText(entry: EntryStack<SBItemStack>, value: SBItemStack): Component {
+ val neuItem = entry.value.neuItem
+ return if (!RepoManager.TConfig.perfectRenders.rendersPerfectText() || entry.value.isWarm() || neuItem == null) {
+ VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asImmutableItemStack())
+ } else {
+ Component.literal(neuItem.displayName)
+ }
}
override fun hash(entry: EntryStack<SBItemStack>, value: SBItemStack, context: ComparisonContext): Long {
@@ -54,8 +59,10 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
}
override fun wildcard(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
- return value.copy(stackSize = 1, petData = RepoManager.getPotentialStubPetData(value.skyblockId),
- stars = 0, extraLore = listOf())
+ return value.copy(
+ stackSize = 1, petData = RepoManager.getPotentialStubPetData(value.skyblockId),
+ stars = 0, extraLore = listOf(), reforge = null
+ )
}
override fun normalize(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
@@ -70,7 +77,7 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
return value.getStackSize() == 0
}
- override fun getIdentifier(entry: EntryStack<SBItemStack>?, value: SBItemStack): Identifier {
+ override fun getIdentifier(entry: EntryStack<SBItemStack>?, value: SBItemStack): ResourceLocation {
return value.skyblockId.identifier
}
@@ -83,15 +90,8 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
fun getEntry(ingredient: NEUIngredient): EntryStack<SBItemStack> =
getEntry(SkyblockId(ingredient.itemId), count = ingredient.amount.toInt())
- fun getPassthrough(item: ItemConvertible) = getEntry(SBItemStack.passthrough(ItemStack(item.asItem())))
+ fun getPassthrough(item: ItemLike) = getEntry(SBItemStack.passthrough(ItemStack(item.asItem())))
fun getEntry(stack: ItemStack): EntryStack<SBItemStack> =
- getEntry(
- SBItemStack(
- stack.skyBlockId ?: SkyblockId.NULL,
- RepoManager.getNEUItem(stack.skyBlockId ?: SkyblockId.NULL),
- stack.count,
- petData = stack.petData?.let { PetData.fromHypixel(it) }
- )
- )
+ getEntry(SBItemStack(stack))
}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt
index f52f418..900ebab 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt
@@ -1,65 +1,56 @@
-
-
package moe.nea.firmament.compat.rei
-import io.github.moulberry.repo.data.NEUCraftingRecipe
import io.github.moulberry.repo.data.NEUForgeRecipe
import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
import io.github.moulberry.repo.data.NEUMobDropRecipe
+import io.github.moulberry.repo.data.NEUNpcShopRecipe
import io.github.moulberry.repo.data.NEURecipe
import java.util.Optional
import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator
import me.shedaniel.rei.api.client.view.ViewSearchBuilder
import me.shedaniel.rei.api.common.display.Display
import me.shedaniel.rei.api.common.entry.EntryStack
-import moe.nea.firmament.compat.rei.recipes.SBCraftingRecipe
-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.SBShopRecipe
import moe.nea.firmament.repo.EssenceRecipeProvider
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
-val SkyblockCraftingRecipeDynamicGenerator =
- neuDisplayGenerator<SBCraftingRecipe, NEUCraftingRecipe> { SBCraftingRecipe(it) }
-
-val SkyblockForgeRecipeDynamicGenerator =
- neuDisplayGenerator<SBForgeRecipe, NEUForgeRecipe> { SBForgeRecipe(it) }
-
val SkyblockMobDropRecipeDynamicGenerator =
- neuDisplayGenerator<SBMobDropRecipe, NEUMobDropRecipe> { SBMobDropRecipe(it) }
-
+ neuDisplayGenerator<SBMobDropRecipe, NEUMobDropRecipe> { SBMobDropRecipe(it) }
+val SkyblockShopRecipeDynamicGenerator =
+ neuDisplayGenerator<SBShopRecipe, NEUNpcShopRecipe> { SBShopRecipe(it) }
val SkyblockKatRecipeDynamicGenerator =
- neuDisplayGenerator<SBKatRecipe, NEUKatUpgradeRecipe> { SBKatRecipe(it) }
-val SkyblockEssenceRecipeDynamicGenerator =
- neuDisplayGenerator<SBEssenceUpgradeRecipe, EssenceRecipeProvider.EssenceUpgradeRecipe> { SBEssenceUpgradeRecipe(it) }
+ neuDisplayGenerator<SBKatRecipe, NEUKatUpgradeRecipe> { SBKatRecipe(it) }
inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(crossinline mapper: (T) -> D) =
- object : DynamicDisplayGenerator<D> {
- override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> {
- if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
- val item = entry.castValue<SBItemStack>()
- val recipes = RepoManager.getRecipesFor(item.skyblockId)
- val craftingRecipes = recipes.filterIsInstance<T>()
- return Optional.of(craftingRecipes.map(mapper))
- }
-
- override fun generate(builder: ViewSearchBuilder): Optional<List<D>> {
- if (SBCraftingRecipe.Category.catIdentifier !in builder.categories) return Optional.empty()
- return Optional.of(
- RepoManager.getAllRecipes().filterIsInstance<T>().map { mapper(it) }
- .toList()
- )
- }
-
- override fun getUsageFor(entry: EntryStack<*>): Optional<List<D>> {
- if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
- val item = entry.castValue<SBItemStack>()
- val recipes = RepoManager.getUsagesFor(item.skyblockId)
- val craftingRecipes = recipes.filterIsInstance<T>()
- return Optional.of(craftingRecipes.map(mapper))
-
- }
- }
+ neuDisplayGeneratorWithItem<D, T> { _, it -> mapper(it) }
+
+inline fun <D : Display, reified T : NEURecipe> neuDisplayGeneratorWithItem(crossinline mapper: (SBItemStack, T) -> D) =
+ neuDisplayGeneratorWithItem(T::class.java, mapper)
+inline fun <D : Display, T : NEURecipe> neuDisplayGeneratorWithItem(
+ filter: Class<T>,
+ crossinline mapper: (SBItemStack, T) -> D) =
+ object : DynamicDisplayGenerator<D> {
+ override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> {
+ if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
+ val item = entry.castValue<SBItemStack>()
+ val recipes = RepoManager.getRecipesFor(item.skyblockId)
+ val craftingRecipes = recipes.filterIsInstance<T>(filter)
+ return Optional.of(craftingRecipes.map { mapper(item, it) })
+ }
+
+ override fun generate(builder: ViewSearchBuilder): Optional<List<D>> {
+ return Optional.empty() // TODO: allows searching without blocking getRecipeFor
+ }
+
+ override fun getUsageFor(entry: EntryStack<*>): Optional<List<D>> {
+ if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
+ val item = entry.castValue<SBItemStack>()
+ val recipes = RepoManager.getUsagesFor(item.skyblockId)
+ val craftingRecipes = recipes.filterIsInstance<T>(filter)
+ return Optional.of(craftingRecipes.map { mapper(item, it) })
+ }
+ }
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt
index cfb6f74..1db0376 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt
@@ -6,19 +6,17 @@ import dev.architectury.event.CompoundEventResult
import me.shedaniel.math.Point
import me.shedaniel.rei.api.client.registry.screen.FocusedStackProvider
import me.shedaniel.rei.api.common.entry.EntryStack
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.client.gui.screen.ingame.HandledScreen
+import net.minecraft.client.gui.screens.Screen
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
-import moe.nea.firmament.util.skyBlockId
object SkyblockItemIdFocusedStackProvider : FocusedStackProvider {
override fun provide(screen: Screen?, mouse: Point?): CompoundEventResult<EntryStack<*>> {
- if (screen !is HandledScreen<*>) return CompoundEventResult.pass()
- screen as AccessorHandledScreen
+ if (screen !is AbstractContainerScreen<*>) return CompoundEventResult.pass()
+ if (screen !is AccessorHandledScreen) return CompoundEventResult.pass()
val focusedSlot = screen.focusedSlot_Firmament ?: return CompoundEventResult.pass()
- val item = focusedSlot.stack ?: return CompoundEventResult.pass()
- val skyblockId = item.skyBlockId ?: return CompoundEventResult.pass()
- return CompoundEventResult.interruptTrue(SBItemEntryDefinition.getEntry(skyblockId))
+ val item = focusedSlot.item ?: return CompoundEventResult.pass()
+ return CompoundEventResult.interruptTrue(SBItemEntryDefinition.getEntry(item))
}
override fun getPriority(): Double = 1_000_000.0
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/GenericREIRecipeCategory.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/GenericREIRecipeCategory.kt
new file mode 100644
index 0000000..aefb37d
--- /dev/null
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/GenericREIRecipeCategory.kt
@@ -0,0 +1,67 @@
+package moe.nea.firmament.compat.rei.recipes
+
+import io.github.moulberry.repo.data.NEURecipe
+import me.shedaniel.math.Rectangle
+import me.shedaniel.rei.api.client.gui.Renderer
+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.DisplayRegistry
+import me.shedaniel.rei.api.common.category.CategoryIdentifier
+import me.shedaniel.rei.api.common.util.EntryStacks
+import net.minecraft.network.chat.Component
+import moe.nea.firmament.compat.rei.REIRecipeLayouter
+import moe.nea.firmament.compat.rei.neuDisplayGeneratorWithItem
+import moe.nea.firmament.repo.SBItemStack
+import moe.nea.firmament.repo.recipes.GenericRecipeRenderer
+
+class GenericREIRecipeCategory<T : NEURecipe>(
+ val renderer: GenericRecipeRenderer<T>,
+) : DisplayCategory<GenericRecipe<T>> {
+ private val dynamicGenerator =
+ neuDisplayGeneratorWithItem<GenericRecipe<T>, T>(renderer.typ) { item, recipe ->
+ GenericRecipe(
+ recipe,
+ item,
+ categoryIdentifier
+ )
+ }
+
+ private val categoryIdentifier = CategoryIdentifier.of<GenericRecipe<T>>(renderer.identifier)
+ override fun getCategoryIdentifier(): CategoryIdentifier<GenericRecipe<T>> {
+ return categoryIdentifier
+ }
+
+ override fun getDisplayHeight(): Int {
+ return renderer.displayHeight
+ }
+
+ override fun getTitle(): Component? {
+ return renderer.title
+ }
+
+ override fun getIcon(): Renderer? {
+ return EntryStacks.of(renderer.icon)
+ }
+
+ override fun setupDisplay(display: GenericRecipe<T>, bounds: Rectangle): List<Widget> {
+ val layouter = REIRecipeLayouter()
+ layouter.container.add(Widgets.createRecipeBase(bounds))
+ renderer.render(display.neuRecipe, bounds, layouter, display.sourceItem)
+ return layouter.container
+ }
+
+ fun registerDynamicGenerator(registry: DisplayRegistry) {
+ registry.registerDisplayGenerator(categoryIdentifier, dynamicGenerator)
+ }
+}
+
+class GenericRecipe<T : NEURecipe>(
+ override val neuRecipe: T,
+ val sourceItem: SBItemStack?,
+ val id: CategoryIdentifier<GenericRecipe<T>>
+) : SBRecipe() {
+ override fun getCategoryIdentifier(): CategoryIdentifier<*>? {
+ return id
+ }
+}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBCraftingRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBCraftingRecipe.kt
deleted file mode 100644
index 8db3d75..0000000
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBCraftingRecipe.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package moe.nea.firmament.compat.rei.recipes
-
-import io.github.moulberry.repo.data.NEUCraftingRecipe
-import io.github.moulberry.repo.data.NEUIngredient
-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.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-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.util.EntryStacks
-import net.minecraft.block.Blocks
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.compat.rei.SBItemEntryDefinition
-import moe.nea.firmament.repo.SBItemStack
-
-class SBCraftingRecipe(override val neuRecipe: NEUCraftingRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier
-
- object Category : DisplayCategory<SBCraftingRecipe> {
- val catIdentifier = CategoryIdentifier.of<SBCraftingRecipe>(Firmament.MOD_ID, "crafing_recipe")
- override fun getCategoryIdentifier(): CategoryIdentifier<out SBCraftingRecipe> = catIdentifier
-
- override fun getTitle(): Text = Text.literal("SkyBlock Crafting")
-
- override fun getIcon(): Renderer = SBItemEntryDefinition.getPassthrough(Blocks.CRAFTING_TABLE)
- override fun setupDisplay(display: SBCraftingRecipe, bounds: Rectangle): List<Widget> {
- val point = Point(bounds.centerX - 58, bounds.centerY - 27)
- return buildList {
- add(Widgets.createRecipeBase(bounds))
- add(Widgets.createArrow(Point(point.x + 60, point.y + 18)))
- add(Widgets.createResultSlotBackground(Point(point.x + 95, point.y + 19)))
- for (i in 0 until 3) {
- for (j in 0 until 3) {
- val slot = Widgets.createSlot(Point(point.x + 1 + i * 18, point.y + 1 + j * 18)).markInput()
- add(slot)
- val item = display.neuRecipe.inputs[i + j * 3]
- if (item == NEUIngredient.SENTINEL_EMPTY) continue
- slot.entry(SBItemEntryDefinition.getEntry(item))
- }
- }
- add(
- Widgets.createSlot(Point(point.x + 95, point.y + 19))
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.output))
- .disableBackground().markOutput()
- )
- }
- }
-
- }
-
-}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBEssenceUpgradeRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBEssenceUpgradeRecipe.kt
deleted file mode 100644
index ec71ec8..0000000
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBEssenceUpgradeRecipe.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-package moe.nea.firmament.compat.rei.recipes
-
-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.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.compat.rei.SBItemEntryDefinition
-import moe.nea.firmament.repo.EssenceRecipeProvider
-import moe.nea.firmament.repo.SBItemStack
-import moe.nea.firmament.util.SkyblockId
-
-class SBEssenceUpgradeRecipe(override val neuRecipe: EssenceRecipeProvider.EssenceUpgradeRecipe) : SBRecipe() {
- object Category : DisplayCategory<SBEssenceUpgradeRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBEssenceUpgradeRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "essence_upgrade")
-
- override fun getTitle(): Text {
- return Text.literal("Essence Upgrades")
- }
-
- override fun getIcon(): Renderer {
- return SBItemEntryDefinition.getEntry(SkyblockId("ESSENCE_WITHER"))
- }
-
- override fun setupDisplay(display: SBEssenceUpgradeRecipe, bounds: Rectangle): List<Widget> {
- val recipe = display.neuRecipe
- val list = mutableListOf<Widget>()
- list.add(Widgets.createRecipeBase(bounds))
- list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 - 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter - 1))))
- list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 + 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(recipe.essenceIngredient)))
- list.add(Widgets.createSlot(Point(bounds.maxX - 12 - 16, bounds.centerY - 8))
- .markOutput()
- .entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter))))
- val extraItems = recipe.extraItems
- list.add(Widgets.createArrow(Point(bounds.centerX - 24 / 2,
- if (extraItems.isEmpty()) bounds.centerY - 17 / 2
- else bounds.centerY + 18 / 2)))
- for ((index, item) in extraItems.withIndex()) {
- list.add(Widgets.createSlot(
- Point(bounds.centerX - extraItems.size * 16 / 2 - 2 / 2 + index * 18,
- bounds.centerY - 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(item)))
- }
- return list
- }
- }
-
- override fun getCategoryIdentifier(): CategoryIdentifier<*> {
- return Category.categoryIdentifier
- }
-}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBForgeRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBForgeRecipe.kt
deleted file mode 100644
index 92b2f3f..0000000
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBForgeRecipe.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-package moe.nea.firmament.compat.rei.recipes
-
-import io.github.moulberry.repo.data.NEUForgeRecipe
-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.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import kotlin.math.cos
-import kotlin.math.sin
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.block.Blocks
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.compat.rei.SBItemEntryDefinition
-import moe.nea.firmament.compat.rei.plus
-
-class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
-
- object Category : DisplayCategory<SBForgeRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBForgeRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "forge_recipe")
-
- override fun getTitle(): Text = Text.literal("Forge Recipes")
- override fun getDisplayHeight(): Int {
- return 104
- }
-
- override fun getIcon(): Renderer = SBItemEntryDefinition.getPassthrough(Blocks.ANVIL)
- override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
- return buildList {
- add(Widgets.createRecipeBase(bounds))
- add(Widgets.createResultSlotBackground(Point(bounds.minX + 124, bounds.minY + 46)))
- val arrow = Widgets.createArrow(Point(bounds.minX + 90, bounds.minY + 54 - 18 / 2))
- add(arrow)
- add(Widgets.createTooltip(arrow.bounds,
- Text.stringifiedTranslatable("firmament.recipe.forge.time",
- display.neuRecipe.duration.seconds)))
- val ingredientsCenter = Point(bounds.minX + 49 - 8, bounds.minY + 54 - 8)
- val count = display.neuRecipe.inputs.size
- if (count == 1) {
- add(
- Widgets.createSlot(Point(ingredientsCenter.x, ingredientsCenter.y)).markInput()
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.inputs.single()))
- )
- } else {
- display.neuRecipe.inputs.forEachIndexed { idx, ingredient ->
- val rad = Math.PI * 2 * idx / count
- add(
- Widgets.createSlot(
- Point(
- cos(rad) * 30,
- sin(rad) * 30,
- ) + ingredientsCenter
- ).markInput().entry(SBItemEntryDefinition.getEntry(ingredient))
- )
- }
- }
- add(
- Widgets.createSlot(Point(bounds.minX + 124, bounds.minY + 46)).markOutput().disableBackground()
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
- )
- }
- }
- }
-
-}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt
index cce1465..2ce27a1 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt
@@ -8,7 +8,7 @@ import io.github.notenoughupdates.moulconfig.gui.MouseEvent
import io.github.notenoughupdates.moulconfig.gui.component.SliderComponent
import io.github.notenoughupdates.moulconfig.observer.GetSetter
import io.github.notenoughupdates.moulconfig.observer.Property
-import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
+import io.github.notenoughupdates.moulconfig.platform.MoulConfigRenderContext
import me.shedaniel.math.Point
import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.gui.Renderer
@@ -17,12 +17,13 @@ import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
import me.shedaniel.rei.api.client.gui.widgets.Widgets
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
import kotlin.time.Duration.Companion.seconds
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.Element
-import net.minecraft.item.Items
-import net.minecraft.text.Text
+import net.minecraft.client.gui.navigation.ScreenDirection
+import net.minecraft.client.gui.GuiGraphics
+import net.minecraft.client.gui.components.events.GuiEventListener
+import net.minecraft.client.input.MouseButtonEvent
+import net.minecraft.world.item.Items
+import net.minecraft.network.chat.Component
import moe.nea.firmament.Firmament
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.repo.PetData
@@ -38,7 +39,7 @@ class SBKatRecipe(override val neuRecipe: NEUKatUpgradeRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<SBKatRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "kat_recipe")
- override fun getTitle(): Text = Text.literal("Kat Pet Upgrade")
+ override fun getTitle(): Component = Component.literal("Kat Pet Upgrade")
override fun getDisplayHeight(): Int {
return 100
}
@@ -55,11 +56,13 @@ class SBKatRecipe(override val neuRecipe: NEUKatUpgradeRecipe) : SBRecipe() {
val inputLevelLabelCenter = Point(bounds.minX + 30 - 18 + 5 + 8, bounds.minY + 25)
val inputLevelLabel = Widgets.createLabel(
inputLevelLabelCenter,
- Text.literal("")).centered()
+ Component.literal("")
+ ).centered()
val outputLevelLabelCenter = Point(bounds.maxX - 30 + 8, bounds.minY + 25)
val outputLevelLabel = Widgets.createLabel(
outputLevelLabelCenter,
- Text.literal("")).centered()
+ Component.literal("")
+ ).centered()
val coinStack = SBItemStack(SkyblockId.COINS, recipe.coins.toInt())
levelValue.whenChanged { oldValue, newValue ->
if (oldValue.toInt() == newValue.toInt()) return@whenChanged
@@ -69,43 +72,63 @@ class SBKatRecipe(override val neuRecipe: NEUKatUpgradeRecipe) : SBRecipe() {
val oldOutput = outputStack.getPetData() ?: return@whenChanged
val newOutput = PetData(oldOutput.rarity, oldOutput.petId, newInput.exp)
outputStack.setPetData(newOutput)
- inputLevelLabel.message = Text.literal(newInput.levelData.currentLevel.toString())
+ inputLevelLabel.message = Component.literal(newInput.levelData.currentLevel.toString())
inputLevelLabel.bounds.location = Point(
- inputLevelLabelCenter.x - MC.font.getWidth(inputLevelLabel.message) / 2,
- inputLevelLabelCenter.y)
- outputLevelLabel.message = Text.literal(newOutput.levelData.currentLevel.toString())
+ inputLevelLabelCenter.x - MC.font.width(inputLevelLabel.message) / 2,
+ inputLevelLabelCenter.y
+ )
+ outputLevelLabel.message = Component.literal(newOutput.levelData.currentLevel.toString())
outputLevelLabel.bounds.location = Point(
- outputLevelLabelCenter.x - MC.font.getWidth(outputLevelLabel.message) / 2,
- outputLevelLabelCenter.y)
+ outputLevelLabelCenter.x - MC.font.width(outputLevelLabel.message) / 2,
+ outputLevelLabelCenter.y
+ )
coinStack.setStackSize((recipe.coins * (1 - 0.3 * newValue / 100)).toInt())
}
levelValue.set(1F)
add(Widgets.createRecipeBase(bounds))
- add(wrapWidget(Rectangle(bounds.centerX - slider.width / 2,
- bounds.maxY - 30,
- slider.width,
- slider.height),
- slider))
- add(Widgets.withTooltip(
- Widgets.createArrow(Point(bounds.centerX - arrowWidth / 2, bounds.minY + 40)),
- Text.literal("Upgrade time: " + FirmFormatters.formatTimespan(recipe.seconds.seconds))))
+ add(
+ wrapWidget(
+ Rectangle(
+ bounds.centerX - slider.width / 2,
+ bounds.maxY - 30,
+ slider.width,
+ slider.height
+ ),
+ slider
+ )
+ )
+ add(
+ Widgets.withTooltip(
+ Widgets.createArrow(Point(bounds.centerX - arrowWidth / 2, bounds.minY + 40)),
+ Component.literal("Upgrade time: " + FirmFormatters.formatTimespan(recipe.seconds.seconds))
+ )
+ )
add(Widgets.createResultSlotBackground(Point(bounds.maxX - 30, bounds.minY + 40)))
add(inputLevelLabel)
add(outputLevelLabel)
- add(Widgets.createSlot(Point(bounds.maxX - 30, bounds.minY + 40)).markOutput().disableBackground()
- .entry(SBItemEntryDefinition.getEntry(outputStack)))
- add(Widgets.createSlot(Point(bounds.minX + 30 - 18 + 5, bounds.minY + 40)).markInput()
- .entry(SBItemEntryDefinition.getEntry(inputStack)))
+ add(
+ Widgets.createSlot(Point(bounds.maxX - 30, bounds.minY + 40)).markOutput().disableBackground()
+ .entry(SBItemEntryDefinition.getEntry(outputStack))
+ )
+ add(
+ Widgets.createSlot(Point(bounds.minX + 30 - 18 + 5, bounds.minY + 40)).markInput()
+ .entry(SBItemEntryDefinition.getEntry(inputStack))
+ )
val allInputs = recipe.items.map { SBItemEntryDefinition.getEntry(it) } +
listOf(SBItemEntryDefinition.getEntry(coinStack))
for ((index, item) in allInputs.withIndex()) {
- add(Widgets.createSlot(
- Point(bounds.centerX + index * 20 - allInputs.size * 18 / 2 - (allInputs.size - 1) * 2 / 2,
- bounds.minY + 20))
- .markInput()
- .entry(item))
+ add(
+ Widgets.createSlot(
+ Point(
+ bounds.centerX + index * 20 - allInputs.size * 18 / 2 - (allInputs.size - 1) * 2 / 2,
+ bounds.minY + 20
+ )
+ )
+ .markInput()
+ .entry(item)
+ )
}
}
}
@@ -118,85 +141,88 @@ fun wrapWidget(bounds: Rectangle, component: GuiComponent): Widget {
return bounds
}
- override fun children(): List<Element> {
+ override fun children(): List<GuiEventListener> {
return listOf()
}
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- context.matrices.push()
- context.matrices.translate(bounds.minX.toFloat(), bounds.minY.toFloat(), 0F)
+ override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
+ context.pose().pushMatrix()
+ context.pose().translate(bounds.minX.toFloat(), bounds.minY.toFloat())
component.render(
GuiImmediateContext(
- ModernRenderContext(context),
+ MoulConfigRenderContext(context),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseX - bounds.minX, mouseY - bounds.minY,
mouseX, mouseY,
mouseX.toFloat(), mouseY.toFloat()
- ))
- context.matrices.pop()
+ )
+ )
+ context.pose().popMatrix()
}
override fun mouseMoved(mouseX: Double, mouseY: Double) {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
- component.mouseEvent(MouseEvent.Move(0F, 0F),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
+ component.mouseEvent(
+ MouseEvent.Move(0F, 0F),
+ GuiImmediateContext(
+ IMinecraft.INSTANCE.provideTopLevelRenderContext(),
+ bounds.minX, bounds.minY,
+ bounds.width, bounds.height,
+ mouseXInt - bounds.minX, mouseYInt - bounds.minY,
+ mouseXInt, mouseYInt,
+ mouseX.toFloat(), mouseY.toFloat()
+ )
+ )
}
- override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Click(button, true),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
+ override fun mouseClicked(event: MouseButtonEvent, isDoubleClick: Boolean): Boolean {
+ val mouseXInt = event.x.toInt()
+ val mouseYInt = event.y.toInt()
+ return component.mouseEvent(
+ MouseEvent.Click(event.button(), true),
+ GuiImmediateContext(
+ IMinecraft.INSTANCE.provideTopLevelRenderContext(),
+ bounds.minX, bounds.minY,
+ bounds.width, bounds.height,
+ mouseXInt - bounds.minX, mouseYInt - bounds.minY,
+ mouseXInt, mouseYInt,
+ event.x.toFloat(), event.y.toFloat()
+ )
+ )
}
- override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Click(button, false),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
+ override fun mouseReleased(event: MouseButtonEvent): Boolean {
+ val mouseXInt = event.x.toInt()
+ val mouseYInt = event.y.toInt()
+ return component.mouseEvent(
+ MouseEvent.Click(event.button(), false),
+ GuiImmediateContext(
+ IMinecraft.INSTANCE.provideTopLevelRenderContext(),
+ bounds.minX, bounds.minY,
+ bounds.width, bounds.height,
+ mouseXInt - bounds.minX, mouseYInt - bounds.minY,
+ mouseXInt, mouseYInt,
+ event.x.toFloat(), event.y.toFloat()
+ )
+ )
}
- override fun mouseDragged(
- mouseX: Double,
- mouseY: Double,
- button: Int,
- deltaX: Double,
- deltaY: Double
- ): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Move(deltaX.toFloat(), deltaY.toFloat()),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
+ override fun mouseDragged(event: MouseButtonEvent, mouseX: Double, mouseY: Double): Boolean {
+ val mouseXInt = event.x.toInt()
+ val mouseYInt = event.y.toInt()
+ return component.mouseEvent(
+ MouseEvent.Move(0f, 0f),
+ GuiImmediateContext(
+ IMinecraft.INSTANCE.provideTopLevelRenderContext(),
+ bounds.minX, bounds.minY,
+ bounds.width, bounds.height,
+ mouseXInt - bounds.minX, mouseYInt - bounds.minY,
+ mouseXInt, mouseYInt,
+ event.x.toFloat(), event.y.toFloat()
+ )
+ )
}
@@ -208,15 +234,17 @@ fun wrapWidget(bounds: Rectangle, component: GuiComponent): Widget {
): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Scroll(verticalAmount.toFloat()),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
+ return component.mouseEvent(
+ MouseEvent.Scroll(verticalAmount.toFloat()),
+ GuiImmediateContext(
+ IMinecraft.INSTANCE.provideTopLevelRenderContext(),
+ bounds.minX, bounds.minY,
+ bounds.width, bounds.height,
+ mouseXInt - bounds.minX, mouseYInt - bounds.minY,
+ mouseXInt, mouseYInt,
+ mouseX.toFloat(), mouseY.toFloat()
+ )
+ )
}
}
}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt
index b595c23..927c199 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt
@@ -9,9 +9,9 @@ import me.shedaniel.rei.api.client.gui.widgets.Widgets
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
import me.shedaniel.rei.api.common.category.CategoryIdentifier
import me.shedaniel.rei.api.common.util.EntryStacks
-import net.minecraft.item.Items
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
+import net.minecraft.world.item.Items
+import net.minecraft.network.chat.Component
+import net.minecraft.resources.ResourceLocation
import moe.nea.firmament.Firmament
import moe.nea.firmament.compat.rei.EntityWidget
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
@@ -24,7 +24,7 @@ class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<SBMobDropRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "mob_drop_recipe")
- override fun getTitle(): Text = Text.literal("Mob Drops")
+ override fun getTitle(): Component = Component.literal("Mob Drops")
override fun getDisplayHeight(): Int {
return 100
}
@@ -35,23 +35,23 @@ class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
add(Widgets.createRecipeBase(bounds))
val source = display.neuRecipe.render
val entity = if (source.startsWith("@")) {
- EntityRenderer.constructEntity(Identifier.of(source.substring(1)))
+ EntityRenderer.constructEntity(ResourceLocation.parse(source.substring(1)))
} else {
EntityRenderer.applyModifiers(source, listOf())
}
val level = display.neuRecipe.level
val fullMobName =
- if (level > 0) Text.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name)
- else Text.translatable("firmament.recipe.mobs.name.nolevel", display.neuRecipe.name)
- val tt = mutableListOf<Text>()
+ if (level > 0) Component.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name)
+ else Component.translatable("firmament.recipe.mobs.name.nolevel", display.neuRecipe.name)
+ val tt = mutableListOf<Component>()
tt.add((fullMobName))
- tt.add(Text.literal(""))
+ tt.add(Component.literal(""))
if (display.neuRecipe.coins > 0) {
- tt.add(Text.stringifiedTranslatable("firmament.recipe.mobs.coins", display.neuRecipe.coins))
+ tt.add(Component.translatable("firmament.recipe.mobs.coins", display.neuRecipe.coins))
}
if (display.neuRecipe.combatExperience > 0) {
tt.add(
- Text.stringifiedTranslatable(
+ Component.translatable(
"firmament.recipe.mobs.combat",
display.neuRecipe.combatExperience
)
@@ -59,14 +59,14 @@ class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
}
if (display.neuRecipe.enchantingExperience > 0) {
tt.add(
- Text.stringifiedTranslatable(
+ Component.translatable(
"firmament.recipe.mobs.exp",
display.neuRecipe.enchantingExperience
)
)
}
if (display.neuRecipe.extra != null)
- display.neuRecipe.extra.mapTo(tt) { Text.literal(it) }
+ display.neuRecipe.extra.mapTo(tt) { Component.literal(it) }
if (tt.size == 2)
tt.removeAt(1)
add(
@@ -76,15 +76,15 @@ class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
)
)
add(
- Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Text.literal(display.neuRecipe.name))
+ Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Component.literal(display.neuRecipe.name))
.leftAligned()
)
var x = bounds.minX + 60
var y = bounds.minY + 20
for (drop in display.neuRecipe.drops) {
- val lore = drop.extra.mapTo(mutableListOf()) { Text.literal(it) }
+ val lore = drop.extra.mapTo(mutableListOf()) { Component.literal(it) }
if (drop.chance != null) {
- lore += listOf(Text.translatable("firmament.recipe.mobs.drops", drop.chance))
+ lore += listOf(Component.translatable("firmament.recipe.mobs.drops", drop.chance))
}
val item = SBItemEntryDefinition.getEntry(drop.dropItem)
.value.copy(extraLore = lore)
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt
index de7779f..d6ca3f6 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt
@@ -6,12 +6,12 @@ import java.util.Optional
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 net.minecraft.util.Identifier
+import net.minecraft.resources.ResourceLocation
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.util.SkyblockId
abstract class SBRecipe : Display {
- override fun getDisplayLocation(): Optional<Identifier> {
+ override fun getDisplayLocation(): Optional<ResourceLocation> {
// In theory, we could return a location for the neuRecipe here. (Something along the lines of neurepo:items/item_id.json/0 for the 0th recipe in the items/item_id.json recipes array).
return Optional.empty()
}
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
index 4d00a4f..ca69782 100644
--- 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
@@ -1,3 +1,5 @@
+@file:OptIn(ExpensiveItemCacheApi::class)
+
package moe.nea.firmament.compat.rei.recipes
import java.util.Optional
@@ -17,15 +19,17 @@ 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 net.minecraft.world.entity.EntityType
+import net.minecraft.world.entity.EntitySpawnReason
+import net.minecraft.core.Holder
+import net.minecraft.network.chat.Component
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.world.entity.npc.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.ExpensiveItemCacheApi
import moe.nea.firmament.repo.Reforge
import moe.nea.firmament.repo.ReforgeStore
import moe.nea.firmament.repo.RepoItemTypeCache
@@ -33,6 +37,7 @@ 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.MC
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.gold
import moe.nea.firmament.util.grey
@@ -44,7 +49,7 @@ import moe.nea.firmament.util.tr
class SBReforgeRecipe(
val reforge: Reforge,
- val limitToItem: SkyblockId?,
+ val limitToItem: SBItemStack?,
) : Display {
companion object {
val catIdentifier = CategoryIdentifier.of<SBReforgeRecipe>(Firmament.MOD_ID, "reforge_recipe")
@@ -55,7 +60,7 @@ class SBReforgeRecipe(
return catIdentifier
}
- override fun getTitle(): Text {
+ override fun getTitle(): Component {
return tr("firmament.recipecategory.reforge", "Reforge")
}
@@ -69,37 +74,6 @@ class SBReforgeRecipe(
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>>()
@@ -124,6 +98,37 @@ class SBReforgeRecipe(
}
updateStatLines()
inputSlot.withEntriesListener { updateStatLines() }
+ 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.wrapRenderer(
+ Rectangle(Point(bounds.minX + 10 + 24, bounds.centerY - 9 + 10), Dimension(16, 16)),
+ SBItemEntryDefinition.getEntry(SkyBlockItems.REFORGE_ANVIL)),
+ Rarity.entries.mapNotNull { rarity ->
+ display.reforge.reforgeCosts?.get(rarity)?.let { rarity to it }
+ }.map { (rarity, cost) ->
+ Component.literal("")
+ .append(rarity.text)
+ .append(": ")
+ .append(Component.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, EntitySpawnReason.COMMAND)
+ ?.also { it.villagerData = it.villagerData.withProfession(MC.currentOrDefaultRegistries, 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()
+ ))
+ }
return list
}
}
@@ -132,10 +137,10 @@ class 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))
+ reforgeRecipes.add(SBReforgeRecipe(reforge, item))
}
for (reforge in ReforgeStore.findEligibleForItem(item.itemType ?: ItemType.NIL)) {
- reforgeRecipes.add(SBReforgeRecipe(reforge, item.skyblockId))
+ reforgeRecipes.add(SBReforgeRecipe(reforge, item))
}
if (reforgeRecipes.isEmpty()) return Optional.empty()
return Optional.of(reforgeRecipes)
@@ -162,26 +167,27 @@ class SBReforgeRecipe(
}
}
- private val eligibleItems =
- if (limitToItem != null) listOfNotNull(RepoManager.getNEUItem(limitToItem))
- else reforge.eligibleItems.flatMap {
+ private val inputItems = run {
+ if (limitToItem != null) return@run listOf(SBItemEntryDefinition.getEntry(limitToItem))
+ val eligibleItems = reforge.eligibleItems.flatMap {
when (it) {
- is Reforge.ReforgeEligibilityFilter.AllowsInternalName ->
- listOfNotNull(RepoManager.getNEUItem(it.internalName))
-
- is Reforge.ReforgeEligibilityFilter.AllowsItemType ->
- ReforgeStore.resolveItemType(it.itemType)
- .flatMapTo(mutableSetOf()) {
- (RepoItemTypeCache.byItemType[it] ?: listOf()) +
- (RepoItemTypeCache.byItemType[it.dungeonVariant] ?: listOf())
- }.toList()
-
- 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
+ is Reforge.ReforgeEligibilityFilter.AllowsInternalName ->
+ listOfNotNull(RepoManager.getNEUItem(it.internalName))
+
+ is Reforge.ReforgeEligibilityFilter.AllowsItemType ->
+ ReforgeStore.resolveItemType(it.itemType)
+ .flatMapTo(mutableSetOf()) {
+ (RepoItemTypeCache.byItemType[it] ?: listOf()) +
+ (RepoItemTypeCache.byItemType[it.dungeonVariant] ?: listOf())
+ }.toList()
+
+ 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) }
+ 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)
@@ -201,8 +207,8 @@ class SBReforgeRecipe(
return catIdentifier
}
- override fun getDisplayLocation(): Optional<Identifier> {
- return Optional.empty()
+ override fun getDisplayLocation(): Optional<ResourceLocation> {
+ return Optional.empty<ResourceLocation>()
}
override fun getSerializer(): DisplaySerializer<out Display>? {
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBShopRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBShopRecipe.kt
new file mode 100644
index 0000000..87d8bdf
--- /dev/null
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBShopRecipe.kt
@@ -0,0 +1,61 @@
+package moe.nea.firmament.compat.rei.recipes
+
+import io.github.moulberry.repo.data.NEUNpcShopRecipe
+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.Widget
+import me.shedaniel.rei.api.client.gui.widgets.Widgets
+import me.shedaniel.rei.api.client.registry.display.DisplayCategory
+import me.shedaniel.rei.api.common.category.CategoryIdentifier
+import me.shedaniel.rei.api.common.entry.EntryIngredient
+import net.minecraft.world.item.Items
+import net.minecraft.network.chat.Component
+import moe.nea.firmament.Firmament
+import moe.nea.firmament.compat.rei.SBItemEntryDefinition
+import moe.nea.firmament.util.skyblockId
+
+class SBShopRecipe(override val neuRecipe: NEUNpcShopRecipe) : SBRecipe() {
+ override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier
+ val merchant = SBItemEntryDefinition.getEntry(neuRecipe.isSoldBy.skyblockId)
+ override fun getInputEntries(): List<EntryIngredient> {
+ return listOf(EntryIngredient.of(merchant)) + super.getInputEntries()
+ }
+
+ object Category : DisplayCategory<SBShopRecipe> {
+ val catIdentifier = CategoryIdentifier.of<SBShopRecipe>(Firmament.MOD_ID, "npc_shopping")
+ override fun getCategoryIdentifier(): CategoryIdentifier<SBShopRecipe> = catIdentifier
+
+ override fun getTitle(): Component = Component.literal("SkyBlock NPC Shopping")
+
+ override fun getIcon(): Renderer = SBItemEntryDefinition.getPassthrough(Items.EMERALD)
+ override fun setupDisplay(display: SBShopRecipe, bounds: Rectangle): List<Widget> {
+ val point = Point(bounds.centerX, bounds.centerY)
+ return buildList {
+ add(Widgets.createRecipeBase(bounds))
+ add(Widgets.createSlot(Point(point.x - 2 - 18 / 2, point.y - 18 - 6))
+ .unmarkInputOrOutput()
+ .entry(display.merchant)
+ .disableBackground())
+ add(Widgets.createArrow(Point(point.x - 2 - 24 / 2, point.y - 6)))
+ val cost = display.neuRecipe.cost
+ for ((i, item) in cost.withIndex()) {
+ add(Widgets.createSlot(Point(
+ point.x - 14 - 18,
+ point.y + i * 18 - 18 * cost.size / 2))
+ .entry(SBItemEntryDefinition.getEntry(item))
+ .markInput())
+ // TODO: fix frame clipping
+ }
+ add(Widgets.createResultSlotBackground(Point(point.x + 18, point.y - 18 / 2)))
+ add(
+ Widgets.createSlot(Point(point.x + 18, point.y - 18 / 2))
+ .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.result))
+ .disableBackground().markOutput()
+ )
+ }
+ }
+
+ }
+
+}
diff --git a/src/compat/sodium/java/moe/nea/firmament/compat/sodium/Compat.kt b/src/compat/sodium/java/moe/nea/firmament/compat/sodium/Compat.kt
new file mode 100644
index 0000000..97ae1fc
--- /dev/null
+++ b/src/compat/sodium/java/moe/nea/firmament/compat/sodium/Compat.kt
@@ -0,0 +1,12 @@
+package moe.nea.firmament.compat.sodium
+
+import moe.nea.firmament.util.compatloader.CompatMeta
+import moe.nea.firmament.util.compatloader.ICompatMeta
+import net.fabricmc.loader.api.FabricLoader
+
+@CompatMeta
+object Compat : ICompatMeta {
+ override fun shouldLoad(): Boolean {
+ return FabricLoader.getInstance().isModLoaded("sodium")
+ }
+}
diff --git a/src/compat/sodium/java/SodiumChunkReloader.kt b/src/compat/sodium/java/moe/nea/firmament/compat/sodium/SodiumChunkReloader.kt
index 0256b88..e5d0fd9 100644
--- a/src/compat/sodium/java/SodiumChunkReloader.kt
+++ b/src/compat/sodium/java/moe/nea/firmament/compat/sodium/SodiumChunkReloader.kt
@@ -1,7 +1,7 @@
package moe.nea.firmament.compat.sodium
+import moe.nea.firmament.mixins.sodium.accessor.AccessorSodiumWorldRenderer
import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer
-import moe.nea.firmament.mixins.accessor.sodium.AccessorSodiumWorldRenderer
class SodiumChunkReloader : Runnable {
override fun run() {
diff --git a/src/compat/sodium/java/moe/nea/firmament/mixins/custommodels/PatchBlockModelInSodiumChunkGenerator.java b/src/compat/sodium/java/moe/nea/firmament/mixins/custommodels/PatchBlockModelInSodiumChunkGenerator.java
deleted file mode 100644
index fe87310..0000000
--- a/src/compat/sodium/java/moe/nea/firmament/mixins/custommodels/PatchBlockModelInSodiumChunkGenerator.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package moe.nea.firmament.mixins.custommodels;
-
-import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
-import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
-import com.llamalad7.mixinextras.sugar.Local;
-import moe.nea.firmament.features.texturepack.CustomBlockTextures;
-import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask;
-import net.minecraft.block.BlockState;
-import net.minecraft.client.render.block.BlockModels;
-import net.minecraft.client.render.model.BakedModel;
-import net.minecraft.util.math.BlockPos;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-
-@Mixin(ChunkBuilderMeshingTask.class)
-public class PatchBlockModelInSodiumChunkGenerator {
- @WrapOperation(
- method = "execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;)Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;",
- at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockModels;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;"))
- private BakedModel replaceBlockModel(BlockModels instance, BlockState state, Operation<BakedModel> original,
- @Local(name = "blockPos") BlockPos.Mutable pos) {
- var replacement = CustomBlockTextures.getReplacementModel(state, pos);
- if (replacement != null) return replacement;
- CustomBlockTextures.enterFallbackCall();
- var fallback = original.call(instance, state);
- CustomBlockTextures.exitFallbackCall();
- return fallback;
- }
-}
diff --git a/src/compat/sodium/java/moe/nea/firmament/mixins/accessor/sodium/AccessorSodiumWorldRenderer.java b/src/compat/sodium/java/moe/nea/firmament/mixins/sodium/accessor/AccessorSodiumWorldRenderer.java
index f75874d..bc2210a 100644
--- a/src/compat/sodium/java/moe/nea/firmament/mixins/accessor/sodium/AccessorSodiumWorldRenderer.java
+++ b/src/compat/sodium/java/moe/nea/firmament/mixins/sodium/accessor/AccessorSodiumWorldRenderer.java
@@ -1,4 +1,4 @@
-package moe.nea.firmament.mixins.accessor.sodium;
+package moe.nea.firmament.mixins.sodium.accessor;
import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer;
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
diff --git a/src/compat/sodium/java/moe/nea/firmament/mixins/sodium/custommodels/PatchBlockModelInSodiumChunkGenerator.java b/src/compat/sodium/java/moe/nea/firmament/mixins/sodium/custommodels/PatchBlockModelInSodiumChunkGenerator.java
new file mode 100644
index 0000000..50dba85
--- /dev/null
+++ b/src/compat/sodium/java/moe/nea/firmament/mixins/sodium/custommodels/PatchBlockModelInSodiumChunkGenerator.java
@@ -0,0 +1,29 @@
+package moe.nea.firmament.mixins.sodium.custommodels;
+
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
+import com.llamalad7.mixinextras.sugar.Local;
+import moe.nea.firmament.features.texturepack.CustomBlockTextures;
+import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.client.renderer.block.BlockModelShaper;
+import net.minecraft.client.renderer.block.model.BlockStateModel;
+import net.minecraft.core.BlockPos;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(ChunkBuilderMeshingTask.class)
+public class PatchBlockModelInSodiumChunkGenerator {
+ @WrapOperation(
+ method = "execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;)Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getBlockModel(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/model/BlockStateModel;"))
+ private BlockStateModel replaceBlockModel(BlockModelShaper instance, BlockState state, Operation<BlockStateModel> original,
+ @Local(name = "blockPos") BlockPos.MutableBlockPos pos) {
+ var replacement = CustomBlockTextures.getReplacementModel(state, pos);
+ if (replacement != null) return replacement;
+ CustomBlockTextures.enterFallbackCall();
+ var fallback = original.call(instance, state);
+ CustomBlockTextures.exitFallbackCall();
+ return fallback;
+ }
+}
diff --git a/src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt b/src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt
new file mode 100644
index 0000000..347dd5d
--- /dev/null
+++ b/src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt
@@ -0,0 +1,13 @@
+package moe.nea.firmament.compat.gender
+
+import net.fabricmc.loader.api.FabricLoader
+import moe.nea.firmament.util.compatloader.CompatMeta
+import moe.nea.firmament.util.compatloader.ICompatMeta
+
+@CompatMeta
+object Compat : ICompatMeta {
+ override fun shouldLoad(): Boolean {
+ return FabricLoader.getInstance().isModLoaded("wildfire_gender")
+ }
+
+}
diff --git a/src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java b/src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java
index c3e8950..f8999da 100644
--- a/src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java
+++ b/src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java
@@ -4,9 +4,9 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import com.wildfire.render.GenderArmorLayer;
import moe.nea.firmament.features.texturepack.CustomGlobalArmorOverrides;
-import net.minecraft.component.type.EquippableComponent;
-import net.minecraft.entity.EquipmentSlot;
-import net.minecraft.item.ItemStack;
+import net.minecraft.world.item.equipment.Equippable;
+import net.minecraft.world.entity.EquipmentSlot;
+import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.injection.At;
@@ -14,10 +14,10 @@ import org.spongepowered.asm.mixin.injection.At;
@Mixin(GenderArmorLayer.class)
@Pseudo
public class PatchArmorTexturesInGenderMod {
- @ModifyExpressionValue(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/BipedEntityRenderState;FF)V",
- at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;"))
+ @ModifyExpressionValue(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/renderer/entity/state/HumanoidRenderState;FF)V",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;get(Lnet/minecraft/core/component/DataComponentType;)Ljava/lang/Object;"))
private Object replaceArmorMaterial(Object original, @Local ItemStack chestplate) {
var overrides = CustomGlobalArmorOverrides.overrideArmor(chestplate, EquipmentSlot.CHEST);
- return overrides.orElse((EquippableComponent) original);
+ return overrides.orElse((Equippable) original);
}
}
diff --git a/src/compat/yacl/java/KeybindingController.kt b/src/compat/yacl/java/KeybindingController.kt
index 204d521..3714455 100644
--- a/src/compat/yacl/java/KeybindingController.kt
+++ b/src/compat/yacl/java/KeybindingController.kt
@@ -6,10 +6,13 @@ import dev.isxander.yacl3.api.utils.Dimension
import dev.isxander.yacl3.gui.AbstractWidget
import dev.isxander.yacl3.gui.YACLScreen
import dev.isxander.yacl3.gui.controllers.ControllerWidget
-import net.minecraft.text.Text
+import net.minecraft.client.input.MouseButtonEvent
+import net.minecraft.client.input.KeyEvent
+import net.minecraft.network.chat.Component
import moe.nea.firmament.gui.config.KeyBindingHandler
import moe.nea.firmament.gui.config.KeyBindingStateManager
import moe.nea.firmament.gui.config.ManagedOption
+import moe.nea.firmament.keybindings.GenericInputButton
import moe.nea.firmament.keybindings.SavedKeyBinding
class KeybindingController(
@@ -21,7 +24,7 @@ class KeybindingController(
return option
}
- override fun formatValue(): Text {
+ override fun formatValue(): Component {
return option.pendingValue().format()
}
@@ -52,16 +55,16 @@ class KeybindingWidget(
return 130
}
- override fun getValueText(): Text {
+ override fun getValueText(): Component {
return sm.label
}
- override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
- return sm.keyboardEvent(keyCode, true)
+ override fun keyPressed(keyEvent: KeyEvent): Boolean {
+ return sm.keyboardEvent(GenericInputButton.of(keyEvent), true)
}
- override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
- return sm.keyboardEvent(keyCode, false)
+ override fun keyReleased(keyEvent: KeyEvent): Boolean {
+ return sm.keyboardEvent(GenericInputButton.of(keyEvent), false)
}
override fun unfocus() {
@@ -73,11 +76,11 @@ class KeybindingWidget(
if (!focused) sm.onLostFocus()
}
- override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
- if (button == 0 && isHovered) {
- sm.onClick()
+ override fun mouseClicked(mouseButtonEvent: MouseButtonEvent, doubleClick: Boolean): Boolean {
+ if (isHovered) {
+ sm.onClick(mouseButtonEvent.button())
return true
}
- return super.mouseClicked(mouseX, mouseY, button)
+ return super.mouseClicked(mouseButtonEvent, doubleClick)
}
}
diff --git a/src/compat/yacl/java/YaclIntegration.kt b/src/compat/yacl/java/YaclIntegration.kt
index 45a0d02..e10b8c4 100644
--- a/src/compat/yacl/java/YaclIntegration.kt
+++ b/src/compat/yacl/java/YaclIntegration.kt
@@ -9,6 +9,7 @@ import dev.isxander.yacl3.api.Option
import dev.isxander.yacl3.api.OptionDescription
import dev.isxander.yacl3.api.OptionGroup
import dev.isxander.yacl3.api.YetAnotherConfigLib
+import dev.isxander.yacl3.api.controller.ColorControllerBuilder
import dev.isxander.yacl3.api.controller.ControllerBuilder
import dev.isxander.yacl3.api.controller.DoubleSliderControllerBuilder
import dev.isxander.yacl3.api.controller.EnumControllerBuilder
@@ -17,16 +18,19 @@ 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 io.github.notenoughupdates.moulconfig.ChromaColour
+import java.awt.Color
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
-import net.minecraft.client.gui.Element
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.text.Text
+import net.minecraft.client.gui.components.events.GuiEventListener
+import net.minecraft.client.gui.screens.Screen
+import net.minecraft.client.gui.components.AbstractContainerWidget
+import net.minecraft.network.chat.Component
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.ColourHandler
import moe.nea.firmament.gui.config.DurationHandler
import moe.nea.firmament.gui.config.EnumRenderer
import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider
@@ -34,11 +38,13 @@ import moe.nea.firmament.gui.config.HudMeta
import moe.nea.firmament.gui.config.HudMetaHandler
import moe.nea.firmament.gui.config.IntegerHandler
import moe.nea.firmament.gui.config.KeyBindingHandler
-import moe.nea.firmament.gui.config.ManagedConfig
+import moe.nea.firmament.util.data.ManagedConfig
import moe.nea.firmament.gui.config.ManagedOption
import moe.nea.firmament.gui.config.StringHandler
import moe.nea.firmament.keybindings.SavedKeyBinding
import moe.nea.firmament.util.FirmFormatters
+import moe.nea.firmament.util.getRGBAWithoutAnimation
+import moe.nea.firmament.util.toChromaWithoutAnimation
@AutoService(FirmamentConfigScreenProvider::class)
@@ -56,20 +62,22 @@ class YaclIntegration : FirmamentConfigScreenProvider {
OptionGroup.createBuilder()
.name(it.labelText)
.options(buildOptions(it.sortedOptions))
- .build())
+ .build()
+ )
}
}
.build()
}
fun buildOptions(options: List<ManagedOption<*>>): Collection<Option<*>> =
- options.map { buildOption(it) }
+ options.flatMap { buildOption(it) }
- private fun <T : Any> buildOption(managedOption: ManagedOption<T>): Option<*> {
+ private fun <T : Any> buildOption(managedOption: ManagedOption<T>): Collection<Option<*>> {
val handler = managedOption.handler
- val binding = Binding.generic(managedOption.default(),
- managedOption::value,
- { managedOption.value = it; managedOption.element.save() })
+ val binding = Binding.generic(
+ managedOption.default(),
+ managedOption::value,
+ { managedOption.value = it; managedOption.element.markDirty() })
fun <T> createDefaultBinding(function: (Option<T>) -> ControllerBuilder<T>): Option.Builder<T> {
return Option.createBuilder<T>()
@@ -78,47 +86,89 @@ class YaclIntegration : FirmamentConfigScreenProvider {
.binding(binding as Binding<T>)
.controller { function(it) }
}
+
+ fun Option<out Any>.single() = listOf(this)
+ fun ButtonOption.Builder.single() = build().single()
+ fun Option.Builder<out Any>.single() = build().single()
when (handler) {
is ClickHandler -> return ButtonOption.createBuilder()
.name(managedOption.labelText)
.action { t, u ->
handler.runnable()
}
- .build()
+ .single()
is HudMetaHandler -> return ButtonOption.createBuilder()
.name(managedOption.labelText)
.action { t, u ->
handler.openEditor(managedOption as ManagedOption<HudMeta>, t)
}
- .build()
+ .single()
is ChoiceHandler<*> -> return createDefaultBinding {
createChoiceBinding(handler as ChoiceHandler<*>, managedOption as ManagedOption<*>, it as Option<*>)
- }.build()
+ }.single()
+
+ is ColourHandler -> {
+ managedOption as ManagedOption<ChromaColour>
+ val colorBinding =
+ Binding.generic(
+ managedOption.default().getRGBAWithoutAnimation(),
+ { managedOption.value.getRGBAWithoutAnimation() },
+ {
+ managedOption.value =
+ it.toChromaWithoutAnimation(managedOption.value.timeForFullRotationInMillis)
+ managedOption.element.markDirty()
+ })
+ val speedBinding =
+ Binding.generic(
+ managedOption.default().timeForFullRotationInMillis,
+ { managedOption.value.timeForFullRotationInMillis },
+ {
+ managedOption.value = managedOption.value.copy(timeForFullRotationInMillis = it)
+ managedOption.element.markDirty()
+ }
+ )
+
+ return listOf(
+ Option.createBuilder<Color>()
+ .name(managedOption.labelText)
+ .binding(colorBinding)
+ .controller {
+ ColorControllerBuilder.create(it)
+ .allowAlpha(true)
+ }
+ .build(),
+ Option.createBuilder<Int>()
+ .name(managedOption.labelText)
+ .binding(speedBinding)
+ .controller { IntegerSliderControllerBuilder.create(it).range(0, 60_000).step(10) }
+ .build(),
+ )
+ }
- is BooleanHandler -> return createDefaultBinding(TickBoxControllerBuilder::create).build()
- is StringHandler -> return createDefaultBinding(StringControllerBuilder::create).build()
+ is BooleanHandler -> return createDefaultBinding(TickBoxControllerBuilder::create).single()
+ is StringHandler -> return createDefaultBinding(StringControllerBuilder::create).single()
is IntegerHandler -> return createDefaultBinding {
IntegerSliderControllerBuilder.create(it).range(handler.min, handler.max).step(1)
- }.build()
+ }.single()
is DurationHandler -> return Option.createBuilder<Double>()
.name(managedOption.labelText)
.binding((binding as Binding<Duration>).xmap({ it.toDouble(DurationUnit.SECONDS) }, { it.seconds }))
.controller {
DoubleSliderControllerBuilder.create(it)
- .formatValue { Text.literal(FirmFormatters.formatTimespan(it.seconds)) }
+ .formatValue { Component.literal(FirmFormatters.formatTimespan(it.seconds)) }
.step(0.1)
.range(handler.min.toDouble(DurationUnit.SECONDS), handler.max.toDouble(DurationUnit.SECONDS))
}
- .build()
+ .single()
is KeyBindingHandler -> return createDefaultBinding {
KeybindingBuilder(it, managedOption as ManagedOption<SavedKeyBinding>)
- }.build()
+ }.single()
- else -> return LabelOption.create(Text.literal("This option is currently unhandled for this config menu. Please report this as a bug."))
+ else -> return listOf(LabelOption.create(Component.literal("This option is currently unhandled for this config menu. Please report this as a bug.")))
}
}
@@ -146,7 +196,7 @@ class YaclIntegration : FirmamentConfigScreenProvider {
fun buildConfig(): YetAnotherConfigLib {
return YetAnotherConfigLib.createBuilder()
- .title(Text.literal("Firmament"))
+ .title(Component.literal("Firmament"))
.categories(buildCategories())
.build()
}
@@ -154,11 +204,11 @@ class YaclIntegration : FirmamentConfigScreenProvider {
override val key: String
get() = "yacl"
- override fun open(parent: Screen?): Screen {
+ override fun open(search: String?, parent: Screen?): Screen {
return object : YACLScreen(buildConfig(), parent) {
- override fun setFocused(focused: Element?) {
+ override fun setFocused(focused: GuiEventListener?) {
if (this.focused is KeybindingWidget &&
- focused is ListHolderWidget<*>
+ focused is AbstractContainerWidget
) {
return
}