diff options
Diffstat (limited to 'src/compat')
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") + } + +} |