diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3ba2c44..856e83b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ on: types: [ opened, synchronize, reopened ] jobs: build: - uses: refinedmods/refinedarchitect/.github/workflows/build.yml@v0.17.1 + uses: refinedmods/refinedarchitect/.github/workflows/build.yml@v0.19.1 with: mutation-testing: false secrets: inherit diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index e21ed03..c6d98d5 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -17,7 +17,7 @@ on: type: string jobs: draft: - uses: refinedmods/refinedarchitect/.github/workflows/draft-release.yml@v0.17.1 + uses: refinedmods/refinedarchitect/.github/workflows/draft-release.yml@v0.19.1 with: release-type: ${{ inputs.release-type }} version-number-override: ${{ inputs.version-number-override }} diff --git a/.github/workflows/issue-for-unsupported-version.yml b/.github/workflows/issue-for-unsupported-version.yml index f8ce865..002c2ac 100644 --- a/.github/workflows/issue-for-unsupported-version.yml +++ b/.github/workflows/issue-for-unsupported-version.yml @@ -4,4 +4,4 @@ on: types: [ labeled, unlabeled, reopened ] jobs: unsupported-labeler: - uses: refinedmods/refinedarchitect/.github/workflows/issue-for-unsupported-version.yml@v0.17.1 \ No newline at end of file + uses: refinedmods/refinedarchitect/.github/workflows/issue-for-unsupported-version.yml@v0.19.1 \ No newline at end of file diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index f7c0e9a..1150b87 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -7,7 +7,7 @@ on: - closed jobs: publish-release: - uses: refinedmods/refinedarchitect/.github/workflows/publish-release.yml@v0.17.1 + uses: refinedmods/refinedarchitect/.github/workflows/publish-release.yml@v0.19.1 secrets: inherit with: project-name: 'Refined Storage - JEI Integration' diff --git a/.github/workflows/resolved-issue-locking.yml b/.github/workflows/resolved-issue-locking.yml index 67112b4..f8dbbdf 100644 --- a/.github/workflows/resolved-issue-locking.yml +++ b/.github/workflows/resolved-issue-locking.yml @@ -4,4 +4,4 @@ on: - cron: '0 0 * * *' jobs: lock: - uses: refinedmods/refinedarchitect/.github/workflows/resolved-issue-locking.yml@v0.17.1 \ No newline at end of file + uses: refinedmods/refinedarchitect/.github/workflows/resolved-issue-locking.yml@v0.19.1 \ No newline at end of file diff --git a/.github/workflows/validate-branch-name.yml b/.github/workflows/validate-branch-name.yml index ce5e06e..c1733fb 100644 --- a/.github/workflows/validate-branch-name.yml +++ b/.github/workflows/validate-branch-name.yml @@ -2,4 +2,4 @@ name: Validate branch name on: [ pull_request ] jobs: validate-branch-name: - uses: refinedmods/refinedarchitect/.github/workflows/validate-branch-name.yml@v0.17.1 \ No newline at end of file + uses: refinedmods/refinedarchitect/.github/workflows/validate-branch-name.yml@v0.19.1 \ No newline at end of file diff --git a/.github/workflows/validate-changelog.yml b/.github/workflows/validate-changelog.yml index db04af1..f5fb9ae 100644 --- a/.github/workflows/validate-changelog.yml +++ b/.github/workflows/validate-changelog.yml @@ -4,4 +4,4 @@ on: types: [ opened, synchronize, reopened, ready_for_review, labeled, unlabeled ] jobs: validate-changelog: - uses: refinedmods/refinedarchitect/.github/workflows/validate-changelog.yml@v0.17.1 \ No newline at end of file + uses: refinedmods/refinedarchitect/.github/workflows/validate-changelog.yml@v0.19.1 \ No newline at end of file diff --git a/.github/workflows/validate-commit-messages.yml b/.github/workflows/validate-commit-messages.yml index 043dba2..620b9e8 100644 --- a/.github/workflows/validate-commit-messages.yml +++ b/.github/workflows/validate-commit-messages.yml @@ -2,4 +2,4 @@ name: Validate commit messages on: [ pull_request ] jobs: validate-commit-messages: - uses: refinedmods/refinedarchitect/.github/workflows/validate-commit-messages.yml@v0.17.1 \ No newline at end of file + uses: refinedmods/refinedarchitect/.github/workflows/validate-commit-messages.yml@v0.19.1 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f49db75..f211068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- The recipe transfer support in the Pattern Grid and Crafting Grid now indicates whether all or some resources are autocraftable. +- You can now start autocrafting for missing autocraftable items from the Crafting Grid via the recipe transfer. +- Alias support for the Disk Interface (formerly known as "Disk Manipulator"). + +### Fixed + +- Support for Refined Storage v2.0.0-milestone.4.8. + ## [0.5.0] - 2024-08-11 ### Fixed diff --git a/README.md b/README.md index 98beac1..31a1406 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ Adds support for: - [Crowdin](https://crowdin.com/project/refined-storage-jei-integration) - [Discord](https://discordapp.com/invite/VYzsydb) - [Twitter](https://twitter.com/refinedmods) -- [Mastodon](https://anvil.social/@refinedmods) ## Building diff --git a/gradle.properties b/gradle.properties index 28825f7..8e11190 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,10 @@ -refinedarchitectVersion=0.17.1 -refinedstorageVersion=2.0.0-milestone.4.7 -jeiVersion=19.8.2.99 -minecraftVersion=1.21 +refinedarchitectVersion=0.19.1 +refinedstorageVersion=2.0.0-milestone.4.8 +jeiVersion=19.20.0.241 +minecraftVersion=1.21.1 # Gradle org.gradle.jvmargs=-Xmx1G +org.gradle.configureondemand=true +org.gradle.caching=true +org.gradle.configuration-cache=true +org.gradle.configuration-cache.problems=warn diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a441313..9355b41 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/AbstractPatternGridRecipeTransferHandler.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/AbstractPatternGridRecipeTransferHandler.java new file mode 100644 index 0000000..f382064 --- /dev/null +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/AbstractPatternGridRecipeTransferHandler.java @@ -0,0 +1,38 @@ +package com.refinedmods.refinedstorage.jei.common; + +import com.refinedmods.refinedstorage.api.grid.view.GridView; +import com.refinedmods.refinedstorage.api.resource.ResourceAmount; +import com.refinedmods.refinedstorage.common.autocrafting.PatternGridContainerMenu; + +import java.util.List; +import javax.annotation.Nullable; + +import mezz.jei.api.gui.ingredient.IRecipeSlotView; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.transfer.IRecipeTransferError; +import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; + +abstract class AbstractPatternGridRecipeTransferHandler + implements IRecipeTransferHandler { + + @Nullable + public static IRecipeTransferError autocraftableHint(final GridView view, final IRecipeSlotsView recipeSlots) { + final List inputs = recipeSlots.getSlotViews(RecipeIngredientRole.INPUT); + final boolean allAreAutocraftable = inputs.stream() + .filter(slotView -> !slotView.isEmpty()) + .allMatch(slotView -> SlotUtil.getResources(slotView) + .stream() + .map(ResourceAmount::resource) + .anyMatch(view::isAutocraftable)); + final List autocraftableSlots = inputs.stream() + .filter(slotView -> SlotUtil.getResources(slotView) + .stream() + .map(ResourceAmount::resource) + .anyMatch(view::isAutocraftable)) + .toList(); + return autocraftableSlots.isEmpty() + ? null + : new PatternGridRecipeTransferError(autocraftableSlots, allAreAutocraftable); + } +} diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/AbstractRecipeTransferError.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/AbstractRecipeTransferError.java new file mode 100644 index 0000000..abdae4a --- /dev/null +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/AbstractRecipeTransferError.java @@ -0,0 +1,18 @@ +package com.refinedmods.refinedstorage.jei.common; + +import com.refinedmods.refinedstorage.common.grid.AutocraftableResourceHint; + +import mezz.jei.api.recipe.transfer.IRecipeTransferError; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.network.chat.Component; + +abstract class AbstractRecipeTransferError implements IRecipeTransferError { + protected static final ClientTooltipComponent MOVE_ITEMS = ClientTooltipComponent.create( + Component.translatable("jei.tooltip.transfer").getVisualOrderText() + ); + protected static final int AUTOCRAFTABLE_COLOR = AutocraftableResourceHint.AUTOCRAFTABLE.getColor(); + + protected static ClientTooltipComponent createAutocraftableHint(final Component component) { + return ClientTooltipComponent.create(component.copy().withColor(AUTOCRAFTABLE_COLOR).getVisualOrderText()); + } +} diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/ClickableIngredient.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/ClickableIngredient.java index 6249589..2720024 100644 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/ClickableIngredient.java +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/ClickableIngredient.java @@ -1,5 +1,6 @@ package com.refinedmods.refinedstorage.jei.common; +import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.runtime.IClickableIngredient; import net.minecraft.client.renderer.Rect2i; @@ -14,10 +15,21 @@ class ClickableIngredient implements IClickableIngredient { } @Override + @SuppressWarnings({"removal"}) public ITypedIngredient getTypedIngredient() { return ingredient; } + @Override + public IIngredientType getIngredientType() { + return ingredient.getType(); + } + + @Override + public T getIngredient() { + return ingredient.getIngredient(); + } + @Override public Rect2i getArea() { return area; diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/CraftingGridRecipeTransferError.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/CraftingGridRecipeTransferError.java new file mode 100644 index 0000000..38b2336 --- /dev/null +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/CraftingGridRecipeTransferError.java @@ -0,0 +1,94 @@ +package com.refinedmods.refinedstorage.jei.common; + +import com.refinedmods.refinedstorage.common.Platform; +import com.refinedmods.refinedstorage.common.support.tooltip.HelpClientTooltipComponent; + +import java.awt.Color; +import java.util.Collections; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.network.chat.Component; + +import static com.refinedmods.refinedstorage.jei.common.Common.MOD_ID; + +class CraftingGridRecipeTransferError extends AbstractRecipeTransferError { + private static final Color MISSING_COLOR = new Color(1.0f, 0.0f, 0.0f, 0.4f); + private static final ClientTooltipComponent MISSING_ITEMS = ClientTooltipComponent.create( + Component.translatable("jei.tooltip.error.recipe.transfer.missing") + .withStyle(ChatFormatting.RED) + .getVisualOrderText()); + private static final List MISSING_TOOLTIP = List.of(MOVE_ITEMS, MISSING_ITEMS); + private static final Component CTRL_CLICK_TO_AUTOCRAFT = Component.translatable( + "gui.%s.transfer.ctrl_click_to_autocraft".formatted(MOD_ID) + ); + + private final List transferInputs; + private final TransferType type; + + CraftingGridRecipeTransferError(final List transferInputs, final TransferType type) { + this.transferInputs = transferInputs; + this.type = type; + } + + @Override + public Type getType() { + return Type.COSMETIC; + } + + @Override + public int getButtonHighlightColor() { + return switch (type) { + case MISSING -> MISSING_COLOR.getRGB(); + case MISSING_BUT_ALL_AUTOCRAFTABLE, MISSING_BUT_SOME_AUTOCRAFTABLE -> AUTOCRAFTABLE_COLOR; + default -> 0; + }; + } + + @Override + public void showError(final GuiGraphics graphics, + final int mouseX, + final int mouseY, + final IRecipeSlotsView recipeSlotsView, + final int recipeX, + final int recipeY) { + final PoseStack poseStack = graphics.pose(); + poseStack.pushPose(); + poseStack.translate(recipeX, recipeY, 0); + transferInputs.forEach(input -> drawInputHighlight(graphics, input)); + poseStack.popPose(); + Platform.INSTANCE.renderTooltip(graphics, calculateTooltip(), mouseX, mouseY); + } + + private List calculateTooltip() { + return switch (type) { + case MISSING -> MISSING_TOOLTIP; + case MISSING_BUT_ALL_AUTOCRAFTABLE -> List.of( + MOVE_ITEMS, + createAutocraftableHint( + Component.translatable("gui.%s.transfer.missing_but_all_autocraftable".formatted(MOD_ID)) + ), + HelpClientTooltipComponent.createAlwaysDisplayed(CTRL_CLICK_TO_AUTOCRAFT) + ); + case MISSING_BUT_SOME_AUTOCRAFTABLE -> List.of( + MOVE_ITEMS, + createAutocraftableHint( + Component.translatable("gui.%s.transfer.missing_but_some_autocraftable".formatted(MOD_ID)) + ), + HelpClientTooltipComponent.createAlwaysDisplayed(CTRL_CLICK_TO_AUTOCRAFT) + ); + default -> Collections.emptyList(); + }; + } + + private static void drawInputHighlight(final GuiGraphics graphics, final TransferInput input) { + switch (input.type()) { + case MISSING -> input.view().drawHighlight(graphics, MISSING_COLOR.getRGB()); + case AUTOCRAFTABLE -> input.view().drawHighlight(graphics, AUTOCRAFTABLE_COLOR); + } + } +} diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/CraftingGridRecipeTransferHandler.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/CraftingGridRecipeTransferHandler.java index 9dc9e8f..715a1e4 100644 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/CraftingGridRecipeTransferHandler.java +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/CraftingGridRecipeTransferHandler.java @@ -1,6 +1,10 @@ package com.refinedmods.refinedstorage.jei.common; -import com.refinedmods.refinedstorage.api.resource.list.ResourceList; +import com.refinedmods.refinedstorage.api.grid.view.GridView; +import com.refinedmods.refinedstorage.api.resource.ResourceAmount; +import com.refinedmods.refinedstorage.api.resource.list.MutableResourceList; +import com.refinedmods.refinedstorage.api.resource.list.MutableResourceListImpl; +import com.refinedmods.refinedstorage.common.api.RefinedStorageApi; import com.refinedmods.refinedstorage.common.content.Menus; import com.refinedmods.refinedstorage.common.grid.CraftingGridContainerMenu; import com.refinedmods.refinedstorage.common.support.resource.ItemResource; @@ -16,12 +20,18 @@ import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import mezz.jei.api.runtime.IRecipesGui; +import mezz.jei.common.transfer.RecipeTransferErrorInternal; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; +import static java.util.Comparator.comparingLong; + class CraftingGridRecipeTransferHandler implements IRecipeTransferHandler> { @Override @@ -47,13 +57,43 @@ public IRecipeTransferError transferRecipe(final CraftingGridContainerMenu conta final Player player, final boolean maxTransfer, final boolean doTransfer) { + final GridView view = containerMenu.getView(); + final MutableResourceList available = containerMenu.getAvailableListForRecipeTransfer(); + final List transferInputs = getTransferInputs(view, recipeSlots, available); + final TransferType type = getTransferType(transferInputs); if (doTransfer) { - doTransfer(recipeSlots, containerMenu); + if (type.canOpenAutocraftingPreview() && Screen.hasControlDown()) { + openAutocraftingPreview(transferInputs); + return RecipeTransferErrorInternal.INSTANCE; + } else { + doTransfer(recipeSlots, containerMenu); + } return null; } - final ResourceList available = containerMenu.getAvailableListForRecipeTransfer(); - final List missingSlots = findMissingSlots(recipeSlots, available); - return missingSlots.isEmpty() ? null : new MissingItemRecipeTransferError(missingSlots); + return type == TransferType.AVAILABLE ? null : new CraftingGridRecipeTransferError(transferInputs, type); + } + + private void openAutocraftingPreview(final List transferInputs) { + final Screen parentScreen = Minecraft.getInstance().screen instanceof IRecipesGui recipesGui + ? recipesGui.getParentScreen().orElse(null) + : null; + final List craftingRequests = createCraftingRequests(transferInputs); + RefinedStorageApi.INSTANCE.openAutocraftingPreview(craftingRequests, parentScreen); + } + + private TransferType getTransferType(final List transferInputs) { + if (transferInputs.stream().allMatch(input -> input.type() == TransferInputType.AVAILABLE)) { + return TransferType.AVAILABLE; + } + final boolean hasMissing = transferInputs.stream().anyMatch(input -> input.type() == TransferInputType.MISSING); + final boolean hasAutocraftable = transferInputs.stream() + .anyMatch(input -> input.type() == TransferInputType.AUTOCRAFTABLE); + if (hasMissing && hasAutocraftable) { + return TransferType.MISSING_BUT_SOME_AUTOCRAFTABLE; + } else if (hasAutocraftable) { + return TransferType.MISSING_BUT_ALL_AUTOCRAFTABLE; + } + return TransferType.MISSING; } private void doTransfer(final IRecipeSlotsView recipeSlots, final CraftingGridContainerMenu containerMenu) { @@ -61,23 +101,46 @@ private void doTransfer(final IRecipeSlotsView recipeSlots, final CraftingGridCo containerMenu.transferRecipe(inputs); } - private List findMissingSlots(final IRecipeSlotsView recipeSlots, final ResourceList available) { - return recipeSlots.getSlotViews(RecipeIngredientRole.INPUT).stream().filter(slotView -> { - if (slotView.isEmpty()) { - return false; - } - return !isAvailable(available, slotView); - }).toList(); + private List getTransferInputs(final GridView view, + final IRecipeSlotsView recipeSlots, + final MutableResourceList available) { + return recipeSlots.getSlotViews(RecipeIngredientRole.INPUT) + .stream() + .filter(slotView -> !slotView.isEmpty()) + .map(slotView -> toTransferInput(view, available, slotView)) + .toList(); } - private boolean isAvailable(final ResourceList available, final IRecipeSlotView slotView) { + private TransferInput toTransferInput(final GridView view, + final MutableResourceList available, + final IRecipeSlotView slotView) { final List possibilities = slotView.getItemStacks().toList(); for (final ItemStack possibility : possibilities) { final ItemResource possibilityResource = ItemResource.ofItemStack(possibility); if (available.remove(possibilityResource, 1).isPresent()) { - return true; + return new TransferInput(slotView, TransferInputType.AVAILABLE, null); + } + } + final List autocraftingPossibilities = possibilities + .stream() + .map(ItemResource::ofItemStack) + .filter(view::isAutocraftable) + .sorted(comparingLong(view::getAmount)) + .toList(); + if (!autocraftingPossibilities.isEmpty()) { + return new TransferInput(slotView, TransferInputType.AUTOCRAFTABLE, autocraftingPossibilities.getFirst()); + } + return new TransferInput(slotView, TransferInputType.MISSING, null); + } + + private static List createCraftingRequests(final List transferInputs) { + final MutableResourceList requests = MutableResourceListImpl.orderPreserving(); + for (final TransferInput transferInput : transferInputs) { + if (transferInput.type() == TransferInputType.AUTOCRAFTABLE + && transferInput.autocraftableResource() != null) { + requests.add(transferInput.autocraftableResource(), 1); } } - return false; + return requests.copyState().stream().toList(); } } diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/MissingItemRecipeTransferError.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/MissingItemRecipeTransferError.java deleted file mode 100644 index b409edd..0000000 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/MissingItemRecipeTransferError.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.refinedmods.refinedstorage.jei.common; - -import java.awt.Color; -import java.util.List; - -import com.mojang.blaze3d.vertex.PoseStack; -import mezz.jei.api.gui.ingredient.IRecipeSlotView; -import mezz.jei.api.gui.ingredient.IRecipeSlotsView; -import mezz.jei.api.recipe.transfer.IRecipeTransferError; -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.Component; -import net.minecraft.util.FormattedCharSequence; - -class MissingItemRecipeTransferError implements IRecipeTransferError { - private static final Color COLOR = new Color(1.0f, 0.0f, 0.0f, 0.4f); - private static final List MISSING_MESSAGE = List.of( - Component.translatable("jei.tooltip.transfer").getVisualOrderText(), - Component.translatable("jei.tooltip.error.recipe.transfer.missing").withStyle(ChatFormatting.RED) - .getVisualOrderText() - ); - - private final List slotsWithMissingItems; - - MissingItemRecipeTransferError(final List slotsWithMissingItems) { - this.slotsWithMissingItems = slotsWithMissingItems; - } - - @Override - public Type getType() { - return Type.COSMETIC; - } - - @Override - public int getButtonHighlightColor() { - return COLOR.getRGB(); - } - - @Override - public void showError(final GuiGraphics graphics, - final int mouseX, - final int mouseY, - final IRecipeSlotsView recipeSlotsView, - final int recipeX, - final int recipeY) { - final PoseStack poseStack = graphics.pose(); - poseStack.pushPose(); - poseStack.translate(recipeX, recipeY, 0); - slotsWithMissingItems.forEach(slot -> slot.drawHighlight(graphics, COLOR.getRGB())); - poseStack.popPose(); - final Screen screen = Minecraft.getInstance().screen; - if (screen != null) { - graphics.renderTooltip(Minecraft.getInstance().font, MISSING_MESSAGE, mouseX, mouseY); - } - } -} diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridCraftingRecipeTransferHandler.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridCraftingRecipeTransferHandler.java index 1bd766e..b77ee66 100644 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridCraftingRecipeTransferHandler.java +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridCraftingRecipeTransferHandler.java @@ -13,14 +13,13 @@ import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferError; -import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; -class PatternGridCraftingRecipeTransferHandler implements - IRecipeTransferHandler> { +class PatternGridCraftingRecipeTransferHandler + extends AbstractPatternGridRecipeTransferHandler> { @Override public Class getContainerClass() { return PatternGridContainerMenu.class; @@ -47,7 +46,8 @@ public IRecipeTransferError transferRecipe(final PatternGridContainerMenu contai if (doTransfer) { final List> inputs = SlotUtil.getItems(recipeSlots, RecipeIngredientRole.INPUT); containerMenu.transferCraftingRecipe(inputs); + return null; } - return null; + return autocraftableHint(containerMenu.getView(), recipeSlots); } } diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridProcessingRecipeTransferHandler.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridProcessingRecipeTransferHandler.java index f1f3645..35de7ec 100644 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridProcessingRecipeTransferHandler.java +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridProcessingRecipeTransferHandler.java @@ -41,6 +41,6 @@ public IRecipeTransferError transferRecipe( final List> outputs = SlotUtil.getResources(recipeSlots, RecipeIngredientRole.OUTPUT); container.transferProcessingRecipe(inputs, outputs); } - return null; + return AbstractPatternGridRecipeTransferHandler.autocraftableHint(container.getView(), recipeSlots); } } diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridRecipeTransferError.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridRecipeTransferError.java new file mode 100644 index 0000000..63269f3 --- /dev/null +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridRecipeTransferError.java @@ -0,0 +1,64 @@ +package com.refinedmods.refinedstorage.jei.common; + +import com.refinedmods.refinedstorage.common.Platform; + +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import mezz.jei.api.gui.ingredient.IRecipeSlotView; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.network.chat.Component; + +import static com.refinedmods.refinedstorage.jei.common.Common.MOD_ID; + +class PatternGridRecipeTransferError extends AbstractRecipeTransferError { + private static final List ALL_AUTOCRAFTABLE_TOOLTIP = List.of( + MOVE_ITEMS, + createAutocraftableHint(Component.translatable("gui.%s.transfer.all_autocraftable".formatted(MOD_ID))) + ); + private static final List SOME_AUTOCRAFTABLE_TOOLTIP = List.of( + MOVE_ITEMS, + createAutocraftableHint(Component.translatable("gui.%s.transfer.some_autocraftable".formatted(MOD_ID))) + ); + + private final List autocraftableSlots; + private final boolean allAreAutocraftable; + + PatternGridRecipeTransferError(final List autocraftableSlots, + final boolean allAreAutocraftable) { + this.autocraftableSlots = autocraftableSlots; + this.allAreAutocraftable = allAreAutocraftable; + } + + @Override + public int getButtonHighlightColor() { + return AUTOCRAFTABLE_COLOR; + } + + @Override + public Type getType() { + return Type.COSMETIC; + } + + @Override + public void showError(final GuiGraphics graphics, + final int mouseX, + final int mouseY, + final IRecipeSlotsView recipeSlotsView, + final int recipeX, + final int recipeY) { + final PoseStack poseStack = graphics.pose(); + poseStack.pushPose(); + poseStack.translate(recipeX, recipeY, 0); + autocraftableSlots.forEach(input -> input.drawHighlight(graphics, AUTOCRAFTABLE_COLOR)); + poseStack.popPose(); + Platform.INSTANCE.renderTooltip( + graphics, + allAreAutocraftable ? ALL_AUTOCRAFTABLE_TOOLTIP : SOME_AUTOCRAFTABLE_TOOLTIP, + mouseX, + mouseY + ); + } +} diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridSmithingTableRecipeTransferHandler.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridSmithingTableRecipeTransferHandler.java index 4ae65eb..f7703fc 100644 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridSmithingTableRecipeTransferHandler.java +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridSmithingTableRecipeTransferHandler.java @@ -13,14 +13,13 @@ import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferError; -import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.SmithingRecipe; -class PatternGridSmithingTableRecipeTransferHandler implements - IRecipeTransferHandler> { +class PatternGridSmithingTableRecipeTransferHandler + extends AbstractPatternGridRecipeTransferHandler> { @Override public Class getContainerClass() { return PatternGridContainerMenu.class; @@ -55,6 +54,6 @@ public IRecipeTransferError transferRecipe(final PatternGridContainerMenu contai inputSlots.get(2) ); } - return null; + return autocraftableHint(containerMenu.getView(), recipeSlots); } } diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridStonecutterRecipeTransferHandler.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridStonecutterRecipeTransferHandler.java index 54aea02..b915f32 100644 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridStonecutterRecipeTransferHandler.java +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/PatternGridStonecutterRecipeTransferHandler.java @@ -11,14 +11,13 @@ import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferError; -import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.StonecutterRecipe; -class PatternGridStonecutterRecipeTransferHandler implements - IRecipeTransferHandler> { +class PatternGridStonecutterRecipeTransferHandler + extends AbstractPatternGridRecipeTransferHandler> { @Override public Class getContainerClass() { return PatternGridContainerMenu.class; @@ -56,6 +55,6 @@ public IRecipeTransferError transferRecipe(final PatternGridContainerMenu contai outputStacks.getFirst().getFirst() ); } - return null; + return autocraftableHint(containerMenu.getView(), recipeSlots); } } diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/RefinedStorageModPlugin.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/RefinedStorageModPlugin.java index 878ef36..16c719a 100644 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/RefinedStorageModPlugin.java +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/RefinedStorageModPlugin.java @@ -1,21 +1,28 @@ package com.refinedmods.refinedstorage.jei.common; +import com.refinedmods.refinedstorage.common.content.Items; import com.refinedmods.refinedstorage.common.grid.screen.AbstractGridScreen; import com.refinedmods.refinedstorage.common.support.AbstractBaseScreen; +import java.util.function.Supplier; import javax.annotation.Nullable; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.constants.RecipeTypes; +import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.registration.IGuiHandlerRegistration; +import mezz.jei.api.registration.IIngredientAliasRegistration; import mezz.jei.api.registration.IRecipeTransferRegistration; import mezz.jei.api.runtime.IJeiRuntime; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; + +import static com.refinedmods.refinedstorage.jei.common.Common.MOD_ID; @JeiPlugin public class RefinedStorageModPlugin implements IModPlugin { - private static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(Common.MOD_ID, "plugin"); + private static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(MOD_ID, "plugin"); @Nullable private static IJeiRuntime runtime; @@ -24,6 +31,15 @@ public ResourceLocation getPluginUid() { return ID; } + @Override + public void registerIngredientAliases(final IIngredientAliasRegistration registration) { + registration.addAliases(VanillaTypes.ITEM_STACK, Items.INSTANCE.getDiskInterfaces() + .stream() + .map(Supplier::get) + .map(Item::getDefaultInstance) + .toList(), "alias.%s.refinedstorage1_disk_manipulator".formatted(MOD_ID)); + } + @Override public void registerRecipeTransferHandlers(final IRecipeTransferRegistration registration) { registration.addRecipeTransferHandler(new CraftingGridRecipeTransferHandler(), RecipeTypes.CRAFTING); diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/SlotUtil.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/SlotUtil.java index bf5ca76..ef849ac 100644 --- a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/SlotUtil.java +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/SlotUtil.java @@ -43,7 +43,7 @@ static List> getResources(final IRecipeSlotsView recipeSlot return recipeSlots.getSlotViews(role).stream().map(SlotUtil::getResources).toList(); } - private static List getResources(final IRecipeSlotView slotView) { + public static List getResources(final IRecipeSlotView slotView) { final List resources = slotView.getAllIngredients() .flatMap(ingredient -> RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResourceAmount( ingredient.getIngredient()).stream()) diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferInput.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferInput.java new file mode 100644 index 0000000..c89ce4b --- /dev/null +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferInput.java @@ -0,0 +1,10 @@ +package com.refinedmods.refinedstorage.jei.common; + +import com.refinedmods.refinedstorage.common.support.resource.ItemResource; + +import javax.annotation.Nullable; + +import mezz.jei.api.gui.ingredient.IRecipeSlotView; + +record TransferInput(IRecipeSlotView view, TransferInputType type, @Nullable ItemResource autocraftableResource) { +} diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferInputType.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferInputType.java new file mode 100644 index 0000000..dbe7c6e --- /dev/null +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferInputType.java @@ -0,0 +1,7 @@ +package com.refinedmods.refinedstorage.jei.common; + +enum TransferInputType { + AVAILABLE, + MISSING, + AUTOCRAFTABLE +} diff --git a/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferType.java b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferType.java new file mode 100644 index 0000000..23d532d --- /dev/null +++ b/refinedstorage-jei-integration-common/src/main/java/com/refinedmods/refinedstorage/jei/common/TransferType.java @@ -0,0 +1,13 @@ +package com.refinedmods.refinedstorage.jei.common; + +enum TransferType { + AVAILABLE, + MISSING, + MISSING_BUT_ALL_AUTOCRAFTABLE, + MISSING_BUT_SOME_AUTOCRAFTABLE; + + boolean canOpenAutocraftingPreview() { + return this == TransferType.MISSING_BUT_ALL_AUTOCRAFTABLE + || this == TransferType.MISSING_BUT_SOME_AUTOCRAFTABLE; + } +} diff --git a/refinedstorage-jei-integration-common/src/main/resources/assets/refinedstorage_jei_integration/lang/en_us.json b/refinedstorage-jei-integration-common/src/main/resources/assets/refinedstorage_jei_integration/lang/en_us.json index 9cff150..a11a29b 100644 --- a/refinedstorage-jei-integration-common/src/main/resources/assets/refinedstorage_jei_integration/lang/en_us.json +++ b/refinedstorage-jei-integration-common/src/main/resources/assets/refinedstorage_jei_integration/lang/en_us.json @@ -2,5 +2,11 @@ "gui.refinedstorage_jei_integration.grid.synchronizer": "JEI", "gui.refinedstorage_jei_integration.grid.synchronizer.help": "Sync the search box text to the JEI filter.", "gui.refinedstorage_jei_integration.grid.synchronizer.two_way": "JEI two-way", - "gui.refinedstorage_jei_integration.grid.synchronizer.two_way.help": "Sync the search box text to the JEI filter, and the JEI filter to the search box text." + "gui.refinedstorage_jei_integration.grid.synchronizer.two_way.help": "Sync the search box text to the JEI filter, and the JEI filter to the search box text.", + "gui.refinedstorage_jei_integration.transfer.missing_but_all_autocraftable": "Missing items, all are autocraftable", + "gui.refinedstorage_jei_integration.transfer.missing_but_some_autocraftable": "Missing items, some are autocraftable", + "gui.refinedstorage_jei_integration.transfer.ctrl_click_to_autocraft": "CTRL + click to autocraft", + "gui.refinedstorage_jei_integration.transfer.all_autocraftable": "All are autocraftable", + "gui.refinedstorage_jei_integration.transfer.some_autocraftable": "Some are autocraftable", + "alias.refinedstorage_jei_integration.refinedstorage1_disk_manipulator": "Disk Manipulator" } \ No newline at end of file diff --git a/refinedstorage-jei-integration-fabric/build.gradle.kts b/refinedstorage-jei-integration-fabric/build.gradle.kts index b8738b3..4ad56c4 100644 --- a/refinedstorage-jei-integration-fabric/build.gradle.kts +++ b/refinedstorage-jei-integration-fabric/build.gradle.kts @@ -27,7 +27,6 @@ repositories { refinedarchitect { modId = "refinedstorage_jei_integration" fabric() - compileWithProject(project(":refinedstorage-jei-integration-common")) publishing { maven = true } @@ -41,7 +40,13 @@ val refinedstorageVersion: String by project val jeiVersion: String by project val minecraftVersion: String by project +val commonJava by configurations.existing +val commonResources by configurations.existing + dependencies { + compileOnly(project(":refinedstorage-jei-integration-common")) + commonJava(project(path = ":refinedstorage-jei-integration-common", configuration = "commonJava")) + commonResources(project(path = ":refinedstorage-jei-integration-common", configuration = "commonResources")) modApi("com.refinedmods.refinedstorage:refinedstorage-fabric:${refinedstorageVersion}") modRuntimeOnly("mezz.jei:jei-${minecraftVersion}-fabric:${jeiVersion}") modCompileOnlyApi("mezz.jei:jei-${minecraftVersion}-common-api:${jeiVersion}") diff --git a/refinedstorage-jei-integration-fabric/src/main/resources/fabric.mod.json b/refinedstorage-jei-integration-fabric/src/main/resources/fabric.mod.json index abc49b6..12fd7d4 100644 --- a/refinedstorage-jei-integration-fabric/src/main/resources/fabric.mod.json +++ b/refinedstorage-jei-integration-fabric/src/main/resources/fabric.mod.json @@ -36,8 +36,8 @@ "fabricloader": ">=0.14.6", "fabric-api": "*", "minecraft": "~1.21", - "refinedstorage": ">=2.0.0-milestone.4.7", - "jei": ">=19.8.2", + "refinedstorage": ">=2.0.0-milestone.4.8", + "jei": ">=19.20.0", "java": ">=17" } } diff --git a/refinedstorage-jei-integration-neoforge/build.gradle.kts b/refinedstorage-jei-integration-neoforge/build.gradle.kts index 2a99098..b768c89 100644 --- a/refinedstorage-jei-integration-neoforge/build.gradle.kts +++ b/refinedstorage-jei-integration-neoforge/build.gradle.kts @@ -19,7 +19,6 @@ repositories { refinedarchitect { modId = "refinedstorage_jei_integration" neoForge() - compileWithProject(project(":refinedstorage-jei-integration-common")) publishing { maven = true } @@ -33,9 +32,16 @@ val refinedstorageVersion: String by project val jeiVersion: String by project val minecraftVersion: String by project +val commonJava by configurations.existing +val commonResources by configurations.existing + dependencies { + compileOnly(project(":refinedstorage-jei-integration-common")) + commonJava(project(path = ":refinedstorage-jei-integration-common", configuration = "commonJava")) + commonResources(project(path = ":refinedstorage-jei-integration-common", configuration = "commonResources")) api("com.refinedmods.refinedstorage:refinedstorage-neoforge:${refinedstorageVersion}") runtimeOnly("mezz.jei:jei-${minecraftVersion}-neoforge:${jeiVersion}") compileOnlyApi("mezz.jei:jei-${minecraftVersion}-common-api:${jeiVersion}") + testCompileOnly("mezz.jei:jei-${minecraftVersion}-common:${jeiVersion}") compileOnlyApi("mezz.jei:jei-${minecraftVersion}-neoforge-api:${jeiVersion}") } diff --git a/refinedstorage-jei-integration-neoforge/src/main/resources/META-INF/neoforge.mods.toml b/refinedstorage-jei-integration-neoforge/src/main/templates/META-INF/neoforge.mods.toml similarity index 90% rename from refinedstorage-jei-integration-neoforge/src/main/resources/META-INF/neoforge.mods.toml rename to refinedstorage-jei-integration-neoforge/src/main/templates/META-INF/neoforge.mods.toml index 700533b..f43c21f 100644 --- a/refinedstorage-jei-integration-neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/refinedstorage-jei-integration-neoforge/src/main/templates/META-INF/neoforge.mods.toml @@ -14,10 +14,10 @@ JEI integration for Refined Storage. [[dependencies.refinedstorage_jei_integration]] modId = "refinedstorage" type = "required" -versionRange = "2.0.0-milestone.4.7" +versionRange = "2.0.0-milestone.4.8" side = "BOTH" [[dependencies.refinedstorage_jei_integration]] modId = "jei" type = "required" -versionRange = "[19.8.2,)" +versionRange = "[19.20.0,)" side = "BOTH"