From 5057d394afaee71d6700ce38aa960cad63eafe0f Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Thu, 8 Aug 2024 19:32:34 +0200 Subject: [PATCH] feat: pattern grid recipe transfer Also adds support for ghost dragging the new filter slots. --- CHANGELOG.md | 4 + README.md | 2 +- gradle.properties | 2 +- ...java => CraftingGridEmiRecipeHandler.java} | 20 +-- .../EmiRecipeModIngredientConverter.java | 18 +++ .../emi/common/FilterEmiDragDropHandler.java | 92 +++++++++++++ .../emi/common/GridEmiStackProvider.java | 2 +- .../common/PatternGridEmiRecipeHandler.java | 122 ++++++++++++++++++ .../emi/common/RefinedStorageEmiPlugin.java | 6 +- ...l.java => ResourceEmiDragDropHandler.java} | 10 +- .../emi/recipe/defaults/refinedstorage.json | 1 + 11 files changed, 261 insertions(+), 18 deletions(-) rename refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/{EmiRecipeHandlerImpl.java => CraftingGridEmiRecipeHandler.java} (85%) create mode 100644 refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/FilterEmiDragDropHandler.java create mode 100644 refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/PatternGridEmiRecipeHandler.java rename refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/{EmiDragDropHandlerImpl.java => ResourceEmiDragDropHandler.java} (90%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a84262..16a0467 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Recipe transfer support for the Pattern Grid. + ## [0.3.2] - 2024-07-26 ### Fixed diff --git a/README.md b/README.md index 61ef4c0..5e66d33 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Adds support for: - Exclusion zones - Ghost ingredient dragging - Using the R/U keys on Grid slots and filtering slots -- Recipe transfer integration for the Crafting Grid +- Recipe transfer integration for the Crafting Grid and Pattern Grid - Grid / EMI search box synchronization ## Links diff --git a/gradle.properties b/gradle.properties index 55ebeff..8f7a637 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ refinedarchitectVersion=0.16.9 -refinedstorageVersion=2.0.0-milestone.4.5 +refinedstorageVersion=2.0.0-milestone.4.6 emiVersion=1.1.10+1.21 # Gradle org.gradle.jvmargs=-Xmx1G diff --git a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiRecipeHandlerImpl.java b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/CraftingGridEmiRecipeHandler.java similarity index 85% rename from refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiRecipeHandlerImpl.java rename to refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/CraftingGridEmiRecipeHandler.java index 88105fb..db16152 100644 --- a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiRecipeHandlerImpl.java +++ b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/CraftingGridEmiRecipeHandler.java @@ -22,16 +22,16 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -class EmiRecipeHandlerImpl implements EmiRecipeHandler { +class CraftingGridEmiRecipeHandler implements EmiRecipeHandler { @Override public EmiPlayerInventory getInventory(final AbstractContainerScreen screen) { final ResourceList available = screen.getMenu().getAvailableListForRecipeTransfer(); - return new EmiPlayerInventory(available.getAll().stream() - .filter(resourceAmount -> resourceAmount.getResource() instanceof ItemResource) + return new EmiPlayerInventory(available.copyState().stream() + .filter(resourceAmount -> resourceAmount.resource() instanceof ItemResource) .map(resourceAmount -> EmiStack.of( - ((ItemResource) resourceAmount.getResource()).item(), - ((ItemResource) resourceAmount.getResource()).components(), - resourceAmount.getAmount() + ((ItemResource) resourceAmount.resource()).item(), + ((ItemResource) resourceAmount.resource()).components(), + resourceAmount.amount() )).toList()); } @@ -59,7 +59,7 @@ private boolean hasMissingItems(final List inputs, final Resource } private boolean isAvailable(final ResourceList available, final EmiIngredient input) { - final List possibilities = getStacks(input); + final List possibilities = getItems(input); for (final ItemResource possibility : possibilities) { if (available.remove(possibility, 1).isPresent()) { return true; @@ -68,8 +68,8 @@ private boolean isAvailable(final ResourceList available, final EmiIngredient in return false; } - private List getStacks(final EmiIngredient input) { - return input.getEmiStacks() + private List getItems(final EmiIngredient ingredient) { + return ingredient.getEmiStacks() .stream() .map(EmiStack::getItemStack) .filter(stack -> !stack.isEmpty()) @@ -81,7 +81,7 @@ private List getStacks(final EmiIngredient input) { public boolean craft(final EmiRecipe recipe, final EmiCraftContext context) { final List> inputs = recipe.getInputs() .stream() - .map(this::getStacks) + .map(this::getItems) .toList(); context.getScreenHandler().transferRecipe(inputs); return true; diff --git a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiRecipeModIngredientConverter.java b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiRecipeModIngredientConverter.java index 239a205..8b912da 100644 --- a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiRecipeModIngredientConverter.java +++ b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiRecipeModIngredientConverter.java @@ -1,5 +1,6 @@ package com.refinedmods.refinedstorage.emi.common; +import com.refinedmods.refinedstorage.api.resource.ResourceAmount; import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey; import com.refinedmods.refinedstorage.common.api.support.resource.RecipeModIngredientConverter; import com.refinedmods.refinedstorage.common.support.resource.FluidResource; @@ -26,6 +27,23 @@ public Optional convertToResource(final Object ingredient) return Optional.empty(); } + @Override + public Optional convertToResourceAmount(final Object ingredient) { + if (ingredient instanceof FluidEmiStack fluid) { + return Optional.of(new ResourceAmount( + new FluidResource((Fluid) fluid.getKey(), fluid.getComponentChanges()), + fluid.getAmount() + )); + } + if (ingredient instanceof ItemEmiStack item) { + return Optional.of(new ResourceAmount( + new ItemResource((Item) item.getKey(), item.getComponentChanges()), + item.getAmount() + )); + } + return Optional.empty(); + } + @Override public Optional convertToIngredient(final PlatformResourceKey resource) { if (resource instanceof ItemResource itemResource) { diff --git a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/FilterEmiDragDropHandler.java b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/FilterEmiDragDropHandler.java new file mode 100644 index 0000000..d8b2cc7 --- /dev/null +++ b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/FilterEmiDragDropHandler.java @@ -0,0 +1,92 @@ +package com.refinedmods.refinedstorage.emi.common; + +import com.refinedmods.refinedstorage.common.support.AbstractBaseContainerMenu; +import com.refinedmods.refinedstorage.common.support.AbstractBaseScreen; +import com.refinedmods.refinedstorage.common.support.containermenu.FilterSlot; +import com.refinedmods.refinedstorage.common.support.packet.c2s.C2SPackets; + +import dev.emi.emi.api.EmiDragDropHandler; +import dev.emi.emi.api.stack.EmiIngredient; +import dev.emi.emi.api.stack.ItemEmiStack; +import dev.emi.emi.runtime.EmiDrawContext; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +class FilterEmiDragDropHandler implements EmiDragDropHandler { + @Override + public boolean dropStack(final Screen screen, final EmiIngredient stack, final int x, final int y) { + if (!(screen instanceof AbstractBaseScreen baseScreen)) { + return false; + } + if (!(baseScreen.getMenu() instanceof AbstractBaseContainerMenu menu)) { + return false; + } + if (!(stack instanceof ItemEmiStack emiStack)) { + return false; + } + return dropStack(menu, baseScreen, emiStack.getItemStack(), x, y); + } + + private boolean dropStack(final AbstractBaseContainerMenu menu, + final AbstractBaseScreen baseScreen, + final ItemStack stack, + final int x, + final int y) { + for (final Slot slot : menu.slots) { + if (slot instanceof FilterSlot filterSlot && dropStack(stack, filterSlot, x, y, baseScreen)) { + return true; + } + } + return false; + } + + private boolean dropStack(final ItemStack stack, + final FilterSlot slot, + final int x, + final int y, + final AbstractBaseScreen baseScreen) { + if (!isSlotValid(stack, slot)) { + return false; + } + final int slotX = baseScreen.getLeftPos() + slot.x; + final int slotY = baseScreen.getTopPos() + slot.y; + if (x < slotX || y < slotY || x > slotX + 16 || y > slotY + 16) { + return false; + } + C2SPackets.sendFilterSlotChange(stack, slot.index); + return true; + } + + @Override + public void render(final Screen screen, + final EmiIngredient dragged, + final GuiGraphics draw, + final int mouseX, + final int mouseY, + final float delta) { + if (!(screen instanceof AbstractBaseScreen baseScreen)) { + return; + } + if (!(baseScreen.getMenu() instanceof AbstractBaseContainerMenu menu)) { + return; + } + if (dragged.isEmpty() || !(dragged.getEmiStacks().getFirst() instanceof ItemEmiStack emiStack)) { + return; + } + final ItemStack stack = emiStack.getItemStack(); + final EmiDrawContext context = EmiDrawContext.wrap(draw); + for (final Slot slot : menu.slots) { + if (!(slot instanceof FilterSlot filterSlot) || !isSlotValid(stack, filterSlot)) { + continue; + } + context.fill(baseScreen.getLeftPos() + slot.x, baseScreen.getTopPos() + slot.y, 17, 17, 0x8822BB33); + } + } + + private static boolean isSlotValid(final ItemStack stack, final FilterSlot slot) { + return slot.isActive() && slot.mayPlace(stack); + } +} + diff --git a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/GridEmiStackProvider.java b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/GridEmiStackProvider.java index 35c04e9..e6703f6 100644 --- a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/GridEmiStackProvider.java +++ b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/GridEmiStackProvider.java @@ -20,7 +20,7 @@ public EmiStackInteraction getStackAt(final Screen screen, final int x, final in if (resource == null) { return EmiStackInteraction.EMPTY; } - final PlatformResourceKey underlyingResource = resource.getUnderlyingResource(); + final PlatformResourceKey underlyingResource = resource.getResourceForRecipeMods(); if (underlyingResource == null) { return EmiStackInteraction.EMPTY; } diff --git a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/PatternGridEmiRecipeHandler.java b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/PatternGridEmiRecipeHandler.java new file mode 100644 index 0000000..12eb365 --- /dev/null +++ b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/PatternGridEmiRecipeHandler.java @@ -0,0 +1,122 @@ +package com.refinedmods.refinedstorage.emi.common; + +import com.refinedmods.refinedstorage.api.resource.ResourceAmount; +import com.refinedmods.refinedstorage.common.api.RefinedStorageApi; +import com.refinedmods.refinedstorage.common.autocrafting.PatternGridContainerMenu; +import com.refinedmods.refinedstorage.common.support.resource.ItemResource; + +import java.util.List; +import java.util.stream.Collectors; + +import dev.emi.emi.api.recipe.EmiPlayerInventory; +import dev.emi.emi.api.recipe.EmiRecipe; +import dev.emi.emi.api.recipe.VanillaEmiRecipeCategories; +import dev.emi.emi.api.recipe.handler.EmiCraftContext; +import dev.emi.emi.api.recipe.handler.EmiRecipeHandler; +import dev.emi.emi.api.stack.EmiIngredient; +import dev.emi.emi.api.stack.EmiStack; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; + +class PatternGridEmiRecipeHandler implements EmiRecipeHandler { + @Override + public EmiPlayerInventory getInventory(final AbstractContainerScreen screen) { + return new EmiPlayerInventory(List.of()); + } + + @Override + public boolean supportsRecipe(final EmiRecipe recipe) { + return true; + } + + @Override + public boolean canCraft(final EmiRecipe recipe, final EmiCraftContext context) { + return true; + } + + @Override + public boolean craft(final EmiRecipe recipe, final EmiCraftContext context) { + if (recipe.getCategory() == VanillaEmiRecipeCategories.CRAFTING) { + transferCraftingRecipe(recipe, context); + } else if (recipe.getCategory() == VanillaEmiRecipeCategories.STONECUTTING) { + transferStonecutterRecipe(recipe, context); + } else if (recipe.getCategory() == VanillaEmiRecipeCategories.SMITHING) { + transferSmithingTableRecipe(recipe, context); + } else { + transferProcessingRecipe(recipe, context); + } + return true; + } + + private void transferCraftingRecipe(final EmiRecipe recipe, + final EmiCraftContext context) { + final List> inputs = recipe.getInputs() + .stream() + .map(this::getItems) + .toList(); + context.getScreenHandler().transferCraftingRecipe(inputs); + } + + private void transferStonecutterRecipe(final EmiRecipe recipe, + final EmiCraftContext context) { + final List> inputs = recipe.getInputs() + .stream() + .map(this::getItems) + .toList(); + final List> outputs = recipe.getOutputs() + .stream() + .map(this::getItems) + .toList(); + if (!inputs.isEmpty() && !outputs.isEmpty() && !inputs.getFirst().isEmpty() && !outputs.getFirst().isEmpty()) { + context.getScreenHandler().transferStonecutterRecipe( + inputs.getFirst().getFirst(), + outputs.getFirst().getFirst() + ); + } + } + + private void transferSmithingTableRecipe(final EmiRecipe recipe, + final EmiCraftContext context) { + final List> inputs = recipe.getInputs() + .stream() + .map(this::getItems) + .toList(); + if (inputs.size() == 3) { + context.getScreenHandler().transferSmithingTableRecipe( + inputs.getFirst(), + inputs.get(1), + inputs.get(2) + ); + } + } + + private List getItems(final EmiIngredient ingredient) { + return ingredient.getEmiStacks() + .stream() + .map(EmiStack::getItemStack) + .filter(stack -> !stack.isEmpty()) + .map(ItemResource::ofItemStack) + .collect(Collectors.toList()); + } + + private void transferProcessingRecipe(final EmiRecipe recipe, + final EmiCraftContext context) { + final List> inputs = recipe.getInputs() + .stream() + .map(this::getResources) + .toList(); + final List> outputs = recipe.getOutputs() + .stream() + .map(this::getResources) + .toList(); + context.getScreenHandler().transferProcessingRecipe(inputs, outputs); + } + + + private List getResources(final EmiIngredient ingredient) { + return ingredient.getEmiStacks() + .stream() + .flatMap(emiStack -> RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResourceAmount(emiStack) + .stream()) + .collect(Collectors.toList()); + } +} diff --git a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/RefinedStorageEmiPlugin.java b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/RefinedStorageEmiPlugin.java index 3f9ef23..f8428fe 100644 --- a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/RefinedStorageEmiPlugin.java +++ b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/RefinedStorageEmiPlugin.java @@ -13,7 +13,9 @@ public void register(final EmiRegistry registry) { registry.addGenericExclusionArea(new EmiExclusionAreaImpl()); registry.addGenericStackProvider(new GridEmiStackProvider()); registry.addGenericStackProvider(new ResourceEmiStackProvider()); - registry.addGenericDragDropHandler(new EmiDragDropHandlerImpl()); - registry.addRecipeHandler(Menus.INSTANCE.getCraftingGrid(), new EmiRecipeHandlerImpl()); + registry.addGenericDragDropHandler(new ResourceEmiDragDropHandler()); + registry.addGenericDragDropHandler(new FilterEmiDragDropHandler()); + registry.addRecipeHandler(Menus.INSTANCE.getCraftingGrid(), new CraftingGridEmiRecipeHandler()); + registry.addRecipeHandler(Menus.INSTANCE.getPatternGrid(), new PatternGridEmiRecipeHandler()); } } diff --git a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiDragDropHandlerImpl.java b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/ResourceEmiDragDropHandler.java similarity index 90% rename from refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiDragDropHandlerImpl.java rename to refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/ResourceEmiDragDropHandler.java index d80dd28..2ff4da2 100644 --- a/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/EmiDragDropHandlerImpl.java +++ b/refinedstorage-emi-integration-common/src/main/java/com/refinedmods/refinedstorage/emi/common/ResourceEmiDragDropHandler.java @@ -13,7 +13,7 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; -class EmiDragDropHandlerImpl implements EmiDragDropHandler { +class ResourceEmiDragDropHandler implements EmiDragDropHandler { @Override public boolean dropStack(final Screen screen, final EmiIngredient stack, final int x, final int y) { if (!(screen instanceof AbstractBaseScreen baseScreen)) { @@ -45,7 +45,7 @@ private boolean dropStack(final PlatformResourceKey resource, final int x, final int y, final AbstractBaseScreen baseScreen) { - if (!slot.isFilter() || !slot.isValid(resource)) { + if (!isSlotValid(resource, slot)) { return false; } final int slotX = baseScreen.getLeftPos() + slot.x; @@ -73,12 +73,16 @@ public void render(final Screen screen, RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResource(dragged).ifPresent(resource -> { final EmiDrawContext context = EmiDrawContext.wrap(draw); for (final ResourceSlot slot : menu.getResourceSlots()) { - if (!slot.isFilter() || !slot.isValid(resource)) { + if (!isSlotValid(resource, slot)) { continue; } context.fill(baseScreen.getLeftPos() + slot.x, baseScreen.getTopPos() + slot.y, 17, 17, 0x8822BB33); } }); } + + private static boolean isSlotValid(final PlatformResourceKey resource, final ResourceSlot slot) { + return slot.isFilter() && slot.isActive() && slot.isValid(resource); + } } diff --git a/refinedstorage-emi-integration-common/src/main/resources/assets/emi/recipe/defaults/refinedstorage.json b/refinedstorage-emi-integration-common/src/main/resources/assets/emi/recipe/defaults/refinedstorage.json index a91eba4..17e6f64 100644 --- a/refinedstorage-emi-integration-common/src/main/resources/assets/emi/recipe/defaults/refinedstorage.json +++ b/refinedstorage-emi-integration-common/src/main/resources/assets/emi/recipe/defaults/refinedstorage.json @@ -6,6 +6,7 @@ "refinedstorage:upgrade", "refinedstorage:fortune_3_upgrade", "refinedstorage:crafting_grid", + "refinedstorage:pattern_grid", "refinedstorage:64b_fluid_storage_disk", "refinedstorage:security_card", "refinedstorage:256b_fluid_storage_disk",