Skip to content

Commit

Permalink
feat: pattern grid recipe transfer
Browse files Browse the repository at this point in the history
Also adds support for ghost dragging
the new filter slots.
  • Loading branch information
raoulvdberge committed Aug 8, 2024
1 parent eb9465f commit 5057d39
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;

class EmiRecipeHandlerImpl implements EmiRecipeHandler<CraftingGridContainerMenu> {
class CraftingGridEmiRecipeHandler implements EmiRecipeHandler<CraftingGridContainerMenu> {
@Override
public EmiPlayerInventory getInventory(final AbstractContainerScreen<CraftingGridContainerMenu> 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());
}

Expand Down Expand Up @@ -59,7 +59,7 @@ private boolean hasMissingItems(final List<EmiIngredient> inputs, final Resource
}

private boolean isAvailable(final ResourceList available, final EmiIngredient input) {
final List<ItemResource> possibilities = getStacks(input);
final List<ItemResource> possibilities = getItems(input);
for (final ItemResource possibility : possibilities) {
if (available.remove(possibility, 1).isPresent()) {
return true;
Expand All @@ -68,8 +68,8 @@ private boolean isAvailable(final ResourceList available, final EmiIngredient in
return false;
}

private List<ItemResource> getStacks(final EmiIngredient input) {
return input.getEmiStacks()
private List<ItemResource> getItems(final EmiIngredient ingredient) {
return ingredient.getEmiStacks()
.stream()
.map(EmiStack::getItemStack)
.filter(stack -> !stack.isEmpty())
Expand All @@ -81,7 +81,7 @@ private List<ItemResource> getStacks(final EmiIngredient input) {
public boolean craft(final EmiRecipe recipe, final EmiCraftContext<CraftingGridContainerMenu> context) {
final List<List<ItemResource>> inputs = recipe.getInputs()
.stream()
.map(this::getStacks)
.map(this::getItems)
.toList();
context.getScreenHandler().transferRecipe(inputs);
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -26,6 +27,23 @@ public Optional<PlatformResourceKey> convertToResource(final Object ingredient)
return Optional.empty();
}

@Override
public Optional<ResourceAmount> 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<Object> convertToIngredient(final PlatformResourceKey resource) {
if (resource instanceof ItemResource itemResource) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Screen> {
@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);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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<PatternGridContainerMenu> {
@Override
public EmiPlayerInventory getInventory(final AbstractContainerScreen<PatternGridContainerMenu> screen) {
return new EmiPlayerInventory(List.of());
}

@Override
public boolean supportsRecipe(final EmiRecipe recipe) {
return true;
}

@Override
public boolean canCraft(final EmiRecipe recipe, final EmiCraftContext<PatternGridContainerMenu> context) {
return true;
}

@Override
public boolean craft(final EmiRecipe recipe, final EmiCraftContext<PatternGridContainerMenu> 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<PatternGridContainerMenu> context) {
final List<List<ItemResource>> inputs = recipe.getInputs()
.stream()
.map(this::getItems)
.toList();
context.getScreenHandler().transferCraftingRecipe(inputs);
}

private void transferStonecutterRecipe(final EmiRecipe recipe,
final EmiCraftContext<PatternGridContainerMenu> context) {
final List<List<ItemResource>> inputs = recipe.getInputs()
.stream()
.map(this::getItems)
.toList();
final List<List<ItemResource>> 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<PatternGridContainerMenu> context) {
final List<List<ItemResource>> 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<ItemResource> 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<PatternGridContainerMenu> context) {
final List<List<ResourceAmount>> inputs = recipe.getInputs()
.stream()
.map(this::getResources)
.toList();
final List<List<ResourceAmount>> outputs = recipe.getOutputs()
.stream()
.map(this::getResources)
.toList();
context.getScreenHandler().transferProcessingRecipe(inputs, outputs);
}


private List<ResourceAmount> getResources(final EmiIngredient ingredient) {
return ingredient.getEmiStacks()
.stream()
.flatMap(emiStack -> RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResourceAmount(emiStack)
.stream())
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;

class EmiDragDropHandlerImpl implements EmiDragDropHandler<Screen> {
class ResourceEmiDragDropHandler implements EmiDragDropHandler<Screen> {
@Override
public boolean dropStack(final Screen screen, final EmiIngredient stack, final int x, final int y) {
if (!(screen instanceof AbstractBaseScreen<?> baseScreen)) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit 5057d39

Please sign in to comment.