aboutsummaryrefslogtreecommitdiff
path: root/src/compat
diff options
context:
space:
mode:
Diffstat (limited to 'src/compat')
-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.kt41
-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.kt78
-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.kt50
-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/ElementAccessor.java12
-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/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/FirmamentReiPlugin.kt46
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt62
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt22
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt1
-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.kt62
-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/SBReforgeRecipe.kt4
-rw-r--r--src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt13
23 files changed, 588 insertions, 228 deletions
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..53e3255
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt
@@ -0,0 +1,41 @@
+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.util.hit.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]
+ if (customBlock == null) return accessor
+ return registration.blockAccessor()
+ .from(accessor)
+ .fakeBlock(customBlock.getDisplayItem(accessor.block))
+ .build()
+ }
+
+ companion object {
+ @JvmStatic
+ fun hasCustomBlock(accessor: BlockAccessor): Boolean {
+ return getCustomBlock(accessor) != null
+ }
+
+ @JvmStatic
+ fun getCustomBlock(accessor: BlockAccessor): MiningRepoData.CustomMiningBlock? {
+ if (!accessor.isFakeBlock) return null
+ val item = accessor.fakeBlock
+ 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..29fecd2
--- /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.block.BlockState
+import net.minecraft.util.Identifier
+import net.minecraft.util.math.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(): Identifier =
+ 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?.isBreakingBlock ?: 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.toImmutable(), 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?.currentBreakingPos ?: 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..ab45e7c
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt
@@ -0,0 +1,78 @@
+package moe.nea.firmament.compat.jade
+
+import java.util.Optional
+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.IElement
+import snownee.jade.api.ui.IElementHelper
+import snownee.jade.impl.ui.ItemStackElement
+import snownee.jade.impl.ui.TextElement
+import kotlin.jvm.optionals.getOrDefault
+import net.minecraft.item.ItemStack
+import net.minecraft.item.Items
+import net.minecraft.text.Text
+import net.minecraft.util.Identifier
+import net.minecraft.util.math.Vec2f
+import moe.nea.firmament.Firmament
+import moe.nea.firmament.repo.ItemCache.asItemStack
+import moe.nea.firmament.repo.RepoManager
+import moe.nea.firmament.repo.SBItemStack
+import moe.nea.firmament.util.MC
+
+class DrillToolProvider : IBlockComponentProvider {
+ 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 TextElement && it.cachedSize == Vec2f.ZERO && it.text.visit {
+ if (it.isEmpty()) Optional.empty() else Optional.of(true)
+ }.getOrDefault(false)
+ }
+ val canHarvest = SBItemStack(MC.stackInHand).breakingPower >= customBlock.breakingPower
+ val lastItem = innerMut[lastItemIndex] as ItemStackElement
+ if (harvestIndicator < 0) {
+ innerMut.add(lastItemIndex + 1, canHarvestIndicator(canHarvest, lastItem.alignment))
+ } else {
+ innerMut.set(harvestIndicator, canHarvestIndicator(canHarvest, lastItem.alignment))
+ }
+ innerMut.set(lastItemIndex, IElementHelper.get()
+ .item(tool, 0.75f)
+ .translate(lastItem.translation)
+ .size(lastItem.size)
+ .message(null)
+ .align(lastItem.alignment))
+ innerMut.subList(0, lastItemIndex - 1).removeIf { it is ItemStackElement }
+ innerMut
+ }
+ })
+ }
+
+ fun canHarvestIndicator(canHarvest: Boolean, align: IElement.Align): IElement {
+ val t = IThemeHelper.get()
+ val text = if (canHarvest) t.success(CHECK) else t.danger(X)
+ return IElementHelper.get().text(text)
+ .scale(0.75F).zOffset(800).size(Vec2f.ZERO).translate(Vec2f(-3F, 3.25F)).align(align)
+ }
+
+ private val CHECK: Text = Text.literal("✔")
+ private val X: Text = Text.literal("✕")
+
+ override fun getUid(): Identifier {
+ 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..51e2453
--- /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.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..d411c26
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt
@@ -0,0 +1,50 @@
+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.block.Block
+import moe.nea.firmament.events.ReloadRegistrationEvent
+import moe.nea.firmament.gui.config.ManagedConfig
+
+object JadeIntegration {
+ 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/ElementAccessor.java b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/ElementAccessor.java
new file mode 100644
index 0000000..1b58e3c
--- /dev/null
+++ b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/ElementAccessor.java
@@ -0,0 +1,12 @@
+package moe.nea.firmament.mixins.compat.jade;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+import snownee.jade.api.ui.Element;
+import snownee.jade.api.ui.IElement;
+
+@Mixin(Element.class)
+public interface ElementAccessor {
+ @Accessor("align")
+ IElement.Align getAlign_firmament();
+}
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..3677d01
--- /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.block.Blocks;
+import net.minecraft.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/block/BlockState;isToolRequired()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..7d71ae8
--- /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.render.WorldRenderer;
+import net.minecraft.util.math.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(WorldRenderer.class)
+public class OnUpdateBreakProgress {
+ @Inject(method = "setBlockBreakingInfo", 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().currentBreakingPos, 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..203f7e4
--- /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/network/ClientPlayerInteractionManager;currentBreakingProgress:F", opcode = Opcodes.GETFIELD)
+ )
+ private static float replaceBlockBreakingProgress(float original) {
+ return CustomMiningHardnessProvider.replaceBreakProgress(original);
+ }
+
+ @ModifyExpressionValue(method = "drawBreakingProgress",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;calcBlockBreakingDelta(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;)F"))
+ private static float replacePlayerSpecificBreakingProgress(float original) {
+ return CustomMiningHardnessProvider.replaceBlockBreakSpeed(original);
+ }
+}
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/FirmamentReiPlugin.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt
index aade59e..b5c9a6d 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
@@ -19,11 +20,10 @@ 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 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
@@ -31,6 +31,9 @@ import moe.nea.firmament.features.inventory.CraftingOverlay
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
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
@@ -52,19 +55,23 @@ class FirmamentReiPlugin : REIClientPlugin {
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")
+ 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.Config.alwaysSuperCraft
if (neuItem.isVanilla && useSuperCraft) return@TransferHandler TransferHandler.Result.createFailed(Text.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? GenericContainerScreen)
+ ?.takeIf { it.title?.unformattedString == 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
@@ -75,13 +82,17 @@ 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)
+ registry.add(generics)
registry.add(SBMobDropRecipe.Category)
registry.add(SBKatRecipe.Category)
registry.add(SBReforgeRecipe.Category)
- registry.add(SBEssenceUpgradeRecipe.Category)
registry.add(SBShopRecipe.Category)
}
@@ -91,17 +102,14 @@ class FirmamentReiPlugin : REIClientPlugin {
}
override fun registerDisplays(registry: DisplayRegistry) {
- registry.registerDisplayGenerator(
- SBCraftingRecipe.Category.catIdentifier,
- SkyblockCraftingRecipeDynamicGenerator)
+ generics.forEach {
+ it.registerDynamicGenerator(registry)
+ }
registry.registerDisplayGenerator(
SBReforgeRecipe.catIdentifier,
SBReforgeRecipe.DynamicGenerator
)
registry.registerDisplayGenerator(
- SBForgeRecipe.Category.categoryIdentifier,
- SkyblockForgeRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
SBMobDropRecipe.Category.categoryIdentifier,
SkyblockMobDropRecipeDynamicGenerator)
registry.registerDisplayGenerator(
@@ -110,10 +118,6 @@ class FirmamentReiPlugin : REIClientPlugin {
registry.registerDisplayGenerator(
SBKatRecipe.Category.categoryIdentifier,
SkyblockKatRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBEssenceUpgradeRecipe.Category.categoryIdentifier,
- SkyblockEssenceRecipeDynamicGenerator
- )
}
override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) {
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..8e39f28
--- /dev/null
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt
@@ -0,0 +1,62 @@
+package moe.nea.firmament.compat.rei
+
+import io.github.notenoughupdates.moulconfig.gui.GuiComponent
+import me.shedaniel.math.Dimension
+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.text.Text
+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 createItemSlot(
+ x: Int,
+ y: Int,
+ content: SBItemStack?,
+ slotKind: RecipeLayouter.SlotKind
+ ) {
+ val slot = Widgets.createSlot(Point(x, y))
+ if (content != null)
+ slot.entry(SBItemEntryDefinition.getEntry(content))
+ 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)))
+ }
+ }
+ add(slot)
+ }
+
+ override fun createTooltip(rectangle: Rectangle, label: Text) {
+ add(Widgets.createTooltip(rectangle, label))
+ }
+
+ override fun createLabel(x: Int, y: Int, text: Text) {
+ add(Widgets.createLabel(Point(x, y), text))
+ }
+
+ 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(ingredientsCenter: Point, animationTicks: Int) {
+ add(Widgets.createBurningFire(ingredientsCenter).animationDurationTicks(animationTicks.toDouble()))
+ }
+}
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 e80840f..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,6 +1,5 @@
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
@@ -11,9 +10,6 @@ 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
@@ -22,33 +18,27 @@ 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) }
val SkyblockShopRecipeDynamicGenerator =
neuDisplayGenerator<SBShopRecipe, NEUNpcShopRecipe> { SBShopRecipe(it) }
val SkyblockKatRecipeDynamicGenerator =
neuDisplayGenerator<SBKatRecipe, NEUKatUpgradeRecipe> { SBKatRecipe(it) }
-val SkyblockEssenceRecipeDynamicGenerator =
- neuDisplayGeneratorWithItem<SBEssenceUpgradeRecipe, EssenceRecipeProvider.EssenceUpgradeRecipe> { item, recipe ->
- SBEssenceUpgradeRecipe(recipe, item)
- }
inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(crossinline mapper: (T) -> D) =
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>()
+ val craftingRecipes = recipes.filterIsInstance<T>(filter)
return Optional.of(craftingRecipes.map { mapper(item, it) })
}
@@ -60,7 +50,7 @@ inline fun <D : Display, reified T : NEURecipe> neuDisplayGeneratorWithItem(cros
if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
val item = entry.castValue<SBItemStack>()
val recipes = RepoManager.getUsagesFor(item.skyblockId)
- val craftingRecipes = recipes.filterIsInstance<T>()
+ 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 518f7b4..9ccfab4 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
@@ -9,7 +9,6 @@ import me.shedaniel.rei.api.common.entry.EntryStack
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.screen.ingame.HandledScreen
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<*>> {
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..15cb818
--- /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.text.Text
+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(): Text? {
+ 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 c02e078..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, "crafting_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 e0a3784..0000000
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBEssenceUpgradeRecipe.kt
+++ /dev/null
@@ -1,62 +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,
- val sourceItem: SBItemStack) : 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(display.sourceItem.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(display.sourceItem.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 7a0ec78..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 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)
- add(Widgets.createBurningFire(ingredientsCenter).animationDurationTicks(25.0))
- 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/SBReforgeRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt
index b8313a6..c5b4fb6 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
@@ -19,6 +19,7 @@ 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.registry.entry.RegistryEntry
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.village.VillagerProfession
@@ -33,6 +34,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
@@ -92,7 +94,7 @@ class SBReforgeRecipe(
list.add(Widgets.withTooltip(
EntityWidget(
EntityType.VILLAGER.create(EntityRenderer.fakeWorld, SpawnReason.COMMAND)
- ?.also { it.villagerData = it.villagerData.withProfession(VillagerProfession.WEAPONSMITH) },
+ ?.also { it.villagerData = it.villagerData.withProfession(MC.currentOrDefaultRegistries.getEntryOrThrow(VillagerProfession.WEAPONSMITH)) },
Point(bounds.minX + 10 + 24 + 8 - dimension.width / 2, bounds.centerY - dimension.height / 2),
dimension
),
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")
+ }
+
+}